diff --git a/org.fortiss.tooling.base.ui/META-INF/MANIFEST.MF b/org.fortiss.tooling.base.ui/META-INF/MANIFEST.MF
index 9bb1ff85da9bb0ceadff74e98f30f861d556d799..e7108c82a4fdc073a777578f0329f3db93bb9a77 100644
--- a/org.fortiss.tooling.base.ui/META-INF/MANIFEST.MF
+++ b/org.fortiss.tooling.base.ui/META-INF/MANIFEST.MF
@@ -23,6 +23,7 @@ Export-Package: org.fortiss.tooling.base.ui,
  org.fortiss.tooling.base.ui.dnd.gef,
  org.fortiss.tooling.base.ui.dnd.jface,
  org.fortiss.tooling.base.ui.editor,
+ org.fortiss.tooling.base.ui.editor.annotations,
  org.fortiss.tooling.base.ui.editpart,
  org.fortiss.tooling.base.ui.editpart.allocation,
  org.fortiss.tooling.base.ui.editpart.command,
diff --git a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/.ratings b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/.ratings
index 16c1534386d115e94e2a6106fc20f35f4acd5893..2d1b98a8f4ee06c2a92ac72d47ec75a6dbf1b2d2 100644
--- a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/.ratings
+++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/.ratings
@@ -7,4 +7,7 @@ DiagramEditorBase.java 09663ce095074d1a8eef086284eea0a7776e0431 GREEN
 DiagramKeyHandler.java cfd15ac8f9fc933739cef5e7039960e19826d1ce GREEN
 FormsEditorBase.java 4046d340913d951340084ae7240d79f8e75cb8d4 GREEN
 GEFEditorBase.java e668f596f45f07215994cbbd3929a9438331718f GREEN
+SourceEditorBase.java 347d6b45d577abd7e23a7234904be118e82469f1 YELLOW
+SourceEditorConfigurationBase.java db3898fe1cace33aab0dd83d9711205c235c9861 YELLOW
+SourceEditorUndoRedo.java 5f5d1b05c8b1287a9e37d866eda3474b6dcbd014 YELLOW
 TreeViewerEditorBase.java 1c59689ff57c4f3cc180d85f13021fc03461ecb0 GREEN
diff --git a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/SourceEditorBase.java b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/SourceEditorBase.java
new file mode 100644
index 0000000000000000000000000000000000000000..347d6b45d577abd7e23a7234904be118e82469f1
--- /dev/null
+++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/SourceEditorBase.java
@@ -0,0 +1,373 @@
+/*-------------------------------------------------------------------------+
+| Copyright 2012 fortiss GmbH                                              |
+|                                                                          |
+| Licensed under the Apache License, Version 2.0 (the "License");          |
+| you may not use this file except in compliance with the License.         |
+| You may obtain a copy of the License at                                  |
+|                                                                          |
+|    http://www.apache.org/licenses/LICENSE-2.0                            |
+|                                                                          |
+| Unless required by applicable law or agreed to in writing, software      |
+| distributed under the License is distributed on an "AS IS" BASIS,        |
+| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+| See the License for the specific language governing permissions and      |
+| limitations under the License.                                           |
++--------------------------------------------------------------------------*/
+package org.fortiss.tooling.base.ui.editor;
+
+import static java.util.regex.Pattern.compile;
+import static org.eclipse.wb.swt.SWTResourceManager.getColor;
+import static org.fortiss.tooling.base.ui.editor.annotations.ErrorAnnotation.ERROR_RGB;
+import static org.fortiss.tooling.base.ui.editor.annotations.ErrorAnnotation.ERROR_TYPE;
+import static org.fortiss.tooling.base.ui.utils.FontUtils.CODEFONT_11PT;
+import static org.fortiss.tooling.base.ui.utils.FontUtils.createFont;
+
+import java.util.regex.Pattern;
+
+import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.emf.ecore.EAttribute;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.util.EContentAdapter;
+import org.eclipse.jface.text.DefaultInformationControl;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IInformationControl;
+import org.eclipse.jface.text.IInformationControlCreator;
+import org.eclipse.jface.text.ITextListener;
+import org.eclipse.jface.text.TextEvent;
+import org.eclipse.jface.text.source.AnnotationBarHoverManager;
+import org.eclipse.jface.text.source.AnnotationModel;
+import org.eclipse.jface.text.source.AnnotationPainter;
+import org.eclipse.jface.text.source.AnnotationRulerColumn;
+import org.eclipse.jface.text.source.CompositeRuler;
+import org.eclipse.jface.text.source.IAnnotationAccess;
+import org.eclipse.jface.text.source.ISharedTextColors;
+import org.eclipse.jface.text.source.OverviewRuler;
+import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.jface.text.source.SourceViewerConfiguration;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.ST;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.actions.TextStyledTextActionHandler;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+import org.eclipse.ui.forms.widgets.ScrolledForm;
+import org.eclipse.wb.swt.SWTResourceManager;
+import org.fortiss.tooling.base.ui.editor.annotations.AnnotationHover;
+import org.fortiss.tooling.base.ui.editor.annotations.AnnotationMarkerAccess;
+import org.fortiss.tooling.kernel.extension.data.ITopLevelElement;
+import org.fortiss.tooling.kernel.service.ILibraryService;
+import org.fortiss.tooling.kernel.service.IPersistencyService;
+import org.fortiss.tooling.kernel.ui.extension.base.EditorBase;
+import org.fortiss.tooling.kernel.ui.service.IActionService;
+
+/**
+ * Editor for code specifications.
+ * 
+ * @author kanav
+ * @param <T>
+ */
+
+public abstract class SourceEditorBase<T extends EObject> extends EditorBase<T> {
+
+	/** Stores the forms toolkit. */
+	private final FormToolkit formToolkit = new FormToolkit(Display.getDefault());
+
+	/** Stores the scrolled form. */
+	private ScrolledForm scrldfrm;
+
+	/** Stores the source viewer. */
+	protected SourceViewer sourceViewer;
+
+	/** Stores the annotation model. */
+	protected AnnotationModel annotationModel = new AnnotationModel();
+
+	/** Tracks whether changes to the source programmatically or by the user. */
+	private EditSource editSource = new EditSource();
+
+	/** Returns annotationModel. */
+	public AnnotationModel getAnnotationModel() {
+		return annotationModel;
+	}
+
+	/** Stores the pattern applied to the error messages. */
+	protected final Pattern pattern = compile("line (\\d*):(\\d*) (.*)");
+
+	/** {@inheritDoc} */
+	@Override
+	public void createPartControl(Composite parent) {
+		installModelChangeListener();
+
+		parent.setLayout(new FillLayout());
+
+		scrldfrm = formToolkit.createScrolledForm(parent);
+		formToolkit.paintBordersFor(scrldfrm);
+		scrldfrm.setText(getTitleText());
+		scrldfrm.getBody().setLayout(new FillLayout(SWT.HORIZONTAL));
+		formToolkit.decorateFormHeading(scrldfrm.getForm());
+
+		createCodeEditor(scrldfrm.getBody());
+		updateModel();
+
+		if(ILibraryService.getInstance().isLibraryElementShadow(editedObject)) {
+			sourceViewer.getControl().setEnabled(false);
+		}
+	}
+
+	/** Returns the title of the source viewer. */
+	protected abstract String getTitleText();
+
+	/**
+	 * Installs an adapter that updates the editor whenever the underlying
+	 * model is modified. Currently, only renaming is supported.
+	 */
+	protected void installModelChangeListener() {
+		getEditedObject().eAdapters().add(new EContentAdapter() {
+
+			/** {@inheritDoc} */
+			@Override
+			public void notifyChanged(Notification notification) {
+				if((notification.getEventType() == Notification.SET)) {
+					// Only trigger for model changes of the string representation. Otherwise, we
+					// would also react on the indirect change of the container.
+					if(!isTargetFeature(notification) || !isUpdateableAndRequired()) {
+						return;
+					}
+					// Do not act on user edits.
+					if(editSource.editor) {
+						return;
+					}
+
+					// Update the displayed sources and track the state.
+					editSource.model = true;
+					String formattedCode = getStringRepresentation();
+					sourceViewer.getTextWidget().setText(formattedCode);
+					sourceViewer.unconfigure();
+					sourceViewer.configure(getSourceViewerConfig());
+					editSource.model = false;
+					showErrors();
+				}
+			}
+
+			/**
+			 * Check whether the modification updated the string representation of the code spec.
+			 */
+			private boolean isTargetFeature(Notification notification) {
+				if(notification.getFeature() instanceof EAttribute) {
+					EAttribute feature = (EAttribute)notification.getFeature();
+					if(feature == getTargetFeature()) {
+						return true;
+					}
+				}
+				return false;
+			}
+
+			/** Check parsability and the presence of a change. */
+			private boolean isUpdateableAndRequired() {
+				// Only update parsable models.
+				if(toBeParsed()) {
+					return false;
+				}
+				// No change --> Exit.
+				if((sourceViewer.getTextWidget() == null) || (sourceViewer.getTextWidget().getText()
+						.equals(getStringRepresentation()))) {
+					return false;
+				}
+				return true;
+			}
+		});
+	}
+
+	/** Returns the feature in ecore model for this source editor. */
+	protected abstract EAttribute getTargetFeature();
+
+	/** Creates the actual editor. */
+	private void createCodeEditor(Composite parent) {
+		IAnnotationAccess fAnnotationAccess = new AnnotationMarkerAccess();
+
+		// rulers
+		CompositeRuler fCompositeRuler = new CompositeRuler();
+		OverviewRuler fOverviewRuler =
+				new OverviewRuler(fAnnotationAccess, 12, new ISharedTextColors() {
+					/** {@inheritDoc} */
+					@Override
+					public Color getColor(RGB rgb) {
+						// Cannot use static import to disambiguate from local method name
+						return SWTResourceManager.getColor(rgb);
+					}
+
+					/** {@inheritDoc} */
+					@Override
+					public void dispose() {
+						// Nothing to do
+					}
+				});
+		AnnotationRulerColumn annotationRuler =
+				new AnnotationRulerColumn(annotationModel, 16, fAnnotationAccess);
+		fCompositeRuler.setModel(annotationModel);
+		fOverviewRuler.setModel(annotationModel);
+
+		// annotation ruler is decorating our composite ruler
+		fCompositeRuler.addDecorator(0, annotationRuler);
+		// add what types are show on the different rulers
+		annotationRuler.addAnnotationType(ERROR_TYPE);
+		fOverviewRuler.addAnnotationType(ERROR_TYPE);
+		fOverviewRuler.addHeaderAnnotationType(ERROR_TYPE);
+		// set what layer this type is on
+		fOverviewRuler.setAnnotationTypeLayer(ERROR_TYPE, 3);
+		// set what color is used on the overview ruler for the type
+		fOverviewRuler.setAnnotationTypeColor(ERROR_TYPE, getColor(ERROR_RGB));
+
+		// create the actual source viewer
+		sourceViewer = new SourceViewer(parent, fCompositeRuler, fOverviewRuler, true,
+				SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL);
+		sourceViewer.setDocument(new Document(), annotationModel);
+
+		// Context menu
+		Menu menu = new Menu(parent.getShell(), SWT.POP_UP);
+		final StyledText editor = sourceViewer.getTextWidget();
+		createMenuItem(menu, "Cut", () -> editor.invokeAction(ST.CUT));
+		createMenuItem(menu, "Copy", () -> editor.invokeAction(ST.COPY));
+		createMenuItem(menu, "Paste", () -> editor.invokeAction(ST.PASTE));
+		editor.setMenu(menu);
+
+		// hover manager that shows text when hovering
+		AnnotationBarHoverManager fAnnotationHoverManager =
+				new AnnotationBarHoverManager(fCompositeRuler, sourceViewer,
+						new AnnotationHover(annotationModel), new AnnotationConfiguration());
+		fAnnotationHoverManager.install(annotationRuler.getControl());
+
+		// to paint the annotations
+		AnnotationPainter ap = new AnnotationPainter(sourceViewer, fAnnotationAccess);
+		ap.addAnnotationType(null, ERROR_TYPE);
+		ap.setAnnotationTypeColor(ERROR_TYPE, getColor(ERROR_RGB));
+		sourceViewer.addPainter(ap);
+
+		// Setup the editor concerning syntax highlighting and content assist
+		sourceViewer.configure(getSourceViewerConfig());
+		Font font = createFont(CODEFONT_11PT);
+		sourceViewer.getTextWidget().setFont(font);
+		new SourceEditorUndoRedo(sourceViewer.getTextWidget());
+		sourceViewer.addTextListener(new ITextListener() {
+			@Override
+			public void textChanged(TextEvent event) {
+				if(editSource.model) {
+					return;
+				}
+				if(event.getDocumentEvent() != null) {
+					if(!isInitialLoading(event)) {
+						// Persist the current state of the editor on every input. Guarded to
+						// support the model change listener (responsible for renaming).
+						editSource.editor = true;
+						ITopLevelElement modelContext = IPersistencyService.getInstance()
+								.getTopLevelElementFor(getEditedObject());
+						modelContext.runAsCommand(() -> setStringRepresentation(
+								sourceViewer.getTextWidget().getText()));
+						editSource.editor = false;
+					}
+					showErrors();
+				}
+			}
+
+			private boolean isInitialLoading(TextEvent event) {
+				if(event.getDocumentEvent().getModificationStamp() == 1) {
+					return true;
+				}
+				return false;
+			}
+		});
+		sourceViewer.getControl().addDisposeListener(new DisposeListener() {
+			/** {@inheritDoc} */
+			@Override
+			public void widgetDisposed(DisposeEvent e) {
+				font.dispose();
+			}
+		});
+	}
+
+	/**
+	 * Creates the SourceViewerConfiguration containing the setup for both syntax highlighting and
+	 * content assist.
+	 */
+	abstract protected SourceViewerConfiguration getSourceViewerConfig();
+
+	/** Returns the string representation of the object. */
+	abstract protected String getStringRepresentation();
+
+	/** Update the string representation in the model element. */
+	abstract protected void setStringRepresentation(String s);
+
+	/** Displays the actual error in the editor. */
+	public abstract void showErrors();
+
+	/** {@inheritDoc} */
+	@Override
+	public void registerGlobalActions(IActionBars bars) {
+		IActionService.getInstance().registerGlobalUndoRedoActions(bars);
+		super.registerGlobalActions(bars);
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	protected void addTextStyledText(TextStyledTextActionHandler textStyledTextActionHandler) {
+		textStyledTextActionHandler.addText(sourceViewer.getTextWidget());
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public void dispose() {
+		super.dispose();
+	}
+
+	/** Performs the text to model binding. */
+	abstract protected void updateModel();
+
+	/** Checks if the model element is to be parsed or not. */
+	abstract protected boolean toBeParsed();
+
+	/**
+	 * Adds a menu item to <code>menu</code> with description <code>description</code>, triggering
+	 * <code>r</code> when selected.
+	 */
+	protected static void createMenuItem(Menu menu, String description, Runnable r) {
+
+		MenuItem pasteItem = new MenuItem(menu, SWT.PUSH);
+		pasteItem.setText(description);
+		pasteItem.addSelectionListener(new SelectionAdapter() {
+			/** {@inheritDoc} */
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				r.run();
+			}
+		});
+	}
+
+	/** Encapsulates the source of a textual change in the spec. */
+	private class EditSource {
+		/** Change performed by a user. */
+		public boolean editor = false;
+		/** Change coming from the model. */
+		public boolean model = false;
+	}
+
+	/** Class acting as annotation configuration. */
+	public static class AnnotationConfiguration implements IInformationControlCreator {
+		/** {@inheritDoc} */
+		@Override
+		public IInformationControl createInformationControl(Shell shell) {
+			return new DefaultInformationControl(shell);
+		}
+	}
+}
diff --git a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/SourceEditorConfigurationBase.java b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/SourceEditorConfigurationBase.java
new file mode 100644
index 0000000000000000000000000000000000000000..db3898fe1cace33aab0dd83d9711205c235c9861
--- /dev/null
+++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/SourceEditorConfigurationBase.java
@@ -0,0 +1,121 @@
+/*-------------------------------------------------------------------------+
+| Copyright 2012 fortiss GmbH                                              |
+|                                                                          |
+| Licensed under the Apache License, Version 2.0 (the "License");          |
+| you may not use this file except in compliance with the License.         |
+| You may obtain a copy of the License at                                  |
+|                                                                          |
+|    http://www.apache.org/licenses/LICENSE-2.0                            |
+|                                                                          |
+| Unless required by applicable law or agreed to in writing, software      |
+| distributed under the License is distributed on an "AS IS" BASIS,        |
+| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+| See the License for the specific language governing permissions and      |
+| limitations under the License.                                           |
++--------------------------------------------------------------------------*/
+package org.fortiss.tooling.base.ui.editor;
+
+import static org.eclipse.jface.text.IDocument.DEFAULT_CONTENT_TYPE;
+import static org.eclipse.wb.swt.SWTResourceManager.getColor;
+
+import java.util.List;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.jface.text.presentation.IPresentationReconciler;
+import org.eclipse.jface.text.presentation.PresentationReconciler;
+import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
+import org.eclipse.jface.text.rules.IRule;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.ITokenScanner;
+import org.eclipse.jface.text.rules.IWordDetector;
+import org.eclipse.jface.text.rules.RuleBasedScanner;
+import org.eclipse.jface.text.rules.WordRule;
+import org.eclipse.jface.text.source.IAnnotationHover;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.SourceViewerConfiguration;
+import org.eclipse.swt.graphics.Color;
+import org.fortiss.tooling.base.ui.editor.SourceEditorBase;
+import org.fortiss.tooling.base.ui.editor.annotations.AnnotationHover;
+
+/**
+ * Class responsible for proper configuration of the {@link SourceEditorBase}.
+ * 
+ * @author doebber
+ */
+public abstract class SourceEditorConfigurationBase<T extends EObject>
+		extends SourceViewerConfiguration {
+
+	/** Stores the actual editor object. */
+	protected SourceEditorBase<T> editor;
+
+	/** Constructor. */
+	public SourceEditorConfigurationBase(SourceEditorBase<T> editor) {
+		this.editor = editor;
+	}
+
+	/** Color constant used to display code dark red. */
+	protected Color DARK_RED = getColor(128, 0, 0);
+
+	/** Color constant used to display code dark blue. */
+	protected Color DARK_BLUE = getColor(0, 0, 128);
+
+	/** Detector used to create the scanners. */
+	protected IWordDetector detector = new IWordDetector() {
+		/** {@inheritDoc} */
+		@Override
+		public boolean isWordStart(char c) {
+			return Character.isLetterOrDigit(c);
+		}
+
+		/** {@inheritDoc} */
+		@Override
+		public boolean isWordPart(char c) {
+			return Character.isLetterOrDigit(c) || c == '_';
+		}
+	};
+
+	/** {@inheritDoc} */
+	@Override
+	public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) {
+		PresentationReconciler reconciler = new PresentationReconciler();
+
+		DefaultDamagerRepairer dr = new DefaultDamagerRepairer(getScanner());
+		reconciler.setDamager(dr, DEFAULT_CONTENT_TYPE);
+		reconciler.setRepairer(dr, DEFAULT_CONTENT_TYPE);
+
+		return reconciler;
+	}
+
+	/** Returns the scanner. */
+	private ITokenScanner getScanner() {
+		return getScannerForSyntaxHighlighting();
+	}
+
+	/** Returns the annotation hover. */
+	@Override
+	public IAnnotationHover getAnnotationHover(ISourceViewer sourceViewer) {
+		return new AnnotationHover(editor.getAnnotationModel());
+	}
+
+	/** Returns the rule based scanner. */
+	private RuleBasedScanner getScannerForSyntaxHighlighting() {
+		List<WordRule> rules = getCommonRules();
+		rules.add(getRuleSpecificToEditor());
+		RuleBasedScanner scanner = new RuleBasedScanner();
+		scanner.setRules(rules.toArray(new IRule[0]));
+		return scanner;
+	}
+
+	/** Returns a list of rules common for the syntax highlighting. */
+	abstract protected List<WordRule> getCommonRules();
+
+	/** Returns a rule specific to the editor. */
+	abstract protected WordRule getRuleSpecificToEditor();
+
+	/** Adds the words to the rule with the given token. */
+	protected void addWordsToRule(List<String> words, WordRule rule, IToken token) {
+		for(String word : words) {
+			rule.addWord(word, token);
+		}
+	}
+}
diff --git a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/SourceEditorUndoRedo.java b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/SourceEditorUndoRedo.java
new file mode 100644
index 0000000000000000000000000000000000000000..5f5d1b05c8b1287a9e37d866eda3474b6dcbd014
--- /dev/null
+++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/SourceEditorUndoRedo.java
@@ -0,0 +1,200 @@
+/*-------------------------------------------------------------------------+
+| Copyright 2014 fortiss GmbH                                              |
+|                                                                          |
+| Licensed under the Apache License, Version 2.0 (the "License");          |
+| you may not use this file except in compliance with the License.         |
+| You may obtain a copy of the License at                                  |
+|                                                                          |
+|    http://www.apache.org/licenses/LICENSE-2.0                            |
+|                                                                          |
+| Unless required by applicable law or agreed to in writing, software      |
+| distributed under the License is distributed on an "AS IS" BASIS,        |
+| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+| See the License for the specific language governing permissions and      |
+| limitations under the License.                                           |
++--------------------------------------------------------------------------*/
+package org.fortiss.tooling.base.ui.editor;
+
+import java.util.Stack;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.ExtendedModifyEvent;
+import org.eclipse.swt.custom.ExtendedModifyListener;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+
+/**
+ * Hack to fix the seemingly broken undo-redo functionality of SourceViewer.
+ * 
+ * @author aravantinos
+ */
+public class SourceEditorUndoRedo implements KeyListener, ExtendedModifyListener {
+	/**
+	 * Encapsulation of the Undo and Redo stack(s).
+	 */
+	private static class UndoRedoStack<T> {
+
+		/** Command stack in the "undo direction". */
+		private Stack<T> undo;
+
+		/** Command stack in the "redo direction". */
+		private Stack<T> redo;
+
+		/** Constructor. */
+		public UndoRedoStack() {
+			undo = new Stack<T>();
+			redo = new Stack<T>();
+		}
+
+		/** Adds a command to the undo stack. */
+		public void pushUndo(T delta) {
+			undo.add(delta);
+		}
+
+		/** Adds a command to the redo stack. */
+		public void pushRedo(T delta) {
+			redo.add(delta);
+		}
+
+		/** Pops a command from the undo stack. */
+		public T popUndo() {
+			T res = undo.pop();
+			return res;
+		}
+
+		/** Pops a command from the redo stack. */
+		public T popRedo() {
+			T res = redo.pop();
+			return res;
+		}
+
+		/** Empties the redo stack. */
+		public void clearRedo() {
+			redo.clear();
+		}
+
+		/** Returns true if the undo stack is not empty. */
+		public boolean hasUndo() {
+			return !undo.isEmpty();
+		}
+
+		/** Returns true if the redo stack is not empty. */
+		public boolean hasRedo() {
+			return !redo.isEmpty();
+		}
+	}
+
+	/** The editor GUI itself. */
+	private StyledText editor;
+
+	/** The local undo/redo command stack. */
+	private UndoRedoStack<ExtendedModifyEvent> stack;
+
+	/** Flag to know whether we are in the course of an undo event. */
+	private boolean isUndo;
+
+	/** Flag to know whether we are in the course of an redo event. */
+	private boolean isRedo;
+
+	/**
+	 * Creates a new instance of this class. Automatically starts listening to
+	 * corresponding key and modify events coming from the given
+	 * <var>editor</var>.
+	 * 
+	 * @param editor
+	 *            the text field to which the Undo-Redo functionality should be
+	 *            added
+	 */
+	public SourceEditorUndoRedo(StyledText editor) {
+		editor.addExtendedModifyListener(this);
+		editor.addKeyListener(this);
+
+		this.editor = editor;
+		stack = new UndoRedoStack<ExtendedModifyEvent>();
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public void keyPressed(KeyEvent e) {
+		// Listen to CTRL+Z for Undo, to CTRL+Y or CTRL+SHIFT+Z for Redo
+		if((e.stateMask & SWT.MOD1) > 0 && !((e.stateMask & SWT.ALT) > 0)) {
+			boolean isShift = (e.stateMask & SWT.SHIFT) > 0;
+			if(!isShift && e.keyCode == 'z') {
+				undo();
+			}
+		}
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public void keyReleased(KeyEvent e) {
+		// Listen to CTRL+Z for Undo, to CTRL+Y or CTRL+SHIFT+Z for Redo
+		if((e.stateMask & SWT.MOD1) > 0 && !((e.stateMask & SWT.ALT) > 0)) {
+			boolean isShift = (e.stateMask & SWT.SHIFT) > 0;
+			if(!isShift && e.keyCode == 'z') {
+				undo();
+			} else if(!isShift && e.keyCode == 'y' || isShift && e.keyCode == 'z') {
+				redo();
+			}
+		}
+	}
+
+	/**
+	 * Creates a corresponding Undo or Redo step from the given event and pushes
+	 * it to the stack. The Redo stack is, logically, emptied if the event comes
+	 * from a normal user action.
+	 * 
+	 * @param event
+	 * @see org.eclipse.swt.custom.ExtendedModifyListener#modifyText(org.eclipse.
+	 *      swt.custom.ExtendedModifyEvent)
+	 */
+	@Override
+	public void modifyText(ExtendedModifyEvent event) {
+		if(isUndo) {
+			stack.pushRedo(event);
+		} else { // is Redo or a normal user action
+			stack.pushUndo(event);
+			if(!isRedo) {
+				stack.clearRedo();
+			}
+		}
+	}
+
+	/**
+	 * Performs the Undo action. A new corresponding Redo step is automatically
+	 * pushed to the stack.
+	 */
+	private void undo() {
+		if(stack.hasUndo()) {
+			isUndo = true;
+			revertEvent(stack.popUndo());
+			isUndo = false;
+		}
+	}
+
+	/**
+	 * Performs the Redo action. A new corresponding Undo step is automatically
+	 * pushed to the stack.
+	 */
+	private void redo() {
+		if(stack.hasRedo()) {
+			isRedo = true;
+			revertEvent(stack.popRedo());
+			isRedo = false;
+		}
+	}
+
+	/**
+	 * Reverts the given modify event, in the way as the Eclipse text editor
+	 * does it.
+	 * 
+	 * @param event
+	 */
+	private void revertEvent(ExtendedModifyEvent event) {
+		editor.replaceTextRange(event.start, event.length, event.replacedText);
+		// (causes the modifyText() listener method to be called)
+
+		editor.setSelectionRange(event.start, event.replacedText.length());
+	}
+}
diff --git a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/annotations/.ratings b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/annotations/.ratings
new file mode 100644
index 0000000000000000000000000000000000000000..3c068c53b36a251eb4d369355471e4206b1b35e1
--- /dev/null
+++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/annotations/.ratings
@@ -0,0 +1,3 @@
+AnnotationHover.java 02988c3a040a394afb427af10c965d9f82b9a01d GREEN
+AnnotationMarkerAccess.java 1977a4093f76d42638a560ed305f1d2cc3dedc4e GREEN
+ErrorAnnotation.java 3e05aaeb93ca19bb99aed312427752c2c3f1959f GREEN
diff --git a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/annotations/AnnotationHover.java b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/annotations/AnnotationHover.java
new file mode 100644
index 0000000000000000000000000000000000000000..02988c3a040a394afb427af10c965d9f82b9a01d
--- /dev/null
+++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/annotations/AnnotationHover.java
@@ -0,0 +1,78 @@
+/*-------------------------------------------------------------------------+
+| Copyright 2012 fortiss GmbH                                              |
+|                                                                          |
+| Licensed under the Apache License, Version 2.0 (the "License");          |
+| you may not use this file except in compliance with the License.         |
+| You may obtain a copy of the License at                                  |
+|                                                                          |
+|    http://www.apache.org/licenses/LICENSE-2.0                            |
+|                                                                          |
+| Unless required by applicable law or agreed to in writing, software      |
+| distributed under the License is distributed on an "AS IS" BASIS,        |
+| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+| See the License for the specific language governing permissions and      |
+| limitations under the License.                                           |
++--------------------------------------------------------------------------*/
+package org.fortiss.tooling.base.ui.editor.annotations;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextHover;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.AnnotationModel;
+import org.eclipse.jface.text.source.IAnnotationHover;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.fortiss.tooling.base.ui.editor.annotations.ErrorAnnotation;
+
+/**
+ * Class acting as annotation hover manager.
+ * 
+ * @author doebber
+ */
+public class AnnotationHover implements IAnnotationHover, ITextHover {
+
+	/** Stores the {@link AnnotationModel}. */
+	private final AnnotationModel model;
+
+	/** Constructor. */
+	public AnnotationHover(AnnotationModel model) {
+		this.model = model;
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public String getHoverInfo(ISourceViewer sourceViewer, int lineNumber) {
+		Iterator<?> ite = model.getAnnotationIterator();
+
+		ArrayList<String> all = new ArrayList<String>();
+
+		while(ite.hasNext()) {
+			Annotation a = (Annotation)ite.next();
+			if(a instanceof ErrorAnnotation) {
+				all.add(((ErrorAnnotation)a).getText());
+			}
+		}
+
+		StringBuffer total = new StringBuffer();
+		for(String str : all) {
+			total.append(" " + str);// + "\n");
+		}
+
+		return total.toString();
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
+		return null;
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public IRegion getHoverRegion(ITextViewer textViewer, int offset) {
+		return null;
+	}
+}
diff --git a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/annotations/AnnotationMarkerAccess.java b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/annotations/AnnotationMarkerAccess.java
new file mode 100644
index 0000000000000000000000000000000000000000..1977a4093f76d42638a560ed305f1d2cc3dedc4e
--- /dev/null
+++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/annotations/AnnotationMarkerAccess.java
@@ -0,0 +1,104 @@
+/*-------------------------------------------------------------------------+
+| Copyright 2012 fortiss GmbH                                              |
+|                                                                          |
+| Licensed under the Apache License, Version 2.0 (the "License");          |
+| you may not use this file except in compliance with the License.         |
+| You may obtain a copy of the License at                                  |
+|                                                                          |
+|    http://www.apache.org/licenses/LICENSE-2.0                            |
+|                                                                          |
+| Unless required by applicable law or agreed to in writing, software      |
+| distributed under the License is distributed on an "AS IS" BASIS,        |
+| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+| See the License for the specific language governing permissions and      |
+| limitations under the License.                                           |
++--------------------------------------------------------------------------*/
+package org.fortiss.tooling.base.ui.editor.annotations;
+
+import static org.eclipse.jface.text.source.ImageUtilities.drawImage;
+
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.IAnnotationAccess;
+import org.eclipse.jface.text.source.IAnnotationAccessExtension;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Canvas;
+
+/**
+ * Class providing annotation marker access.
+ * 
+ * @author doebber
+ */
+public class AnnotationMarkerAccess implements IAnnotationAccess, IAnnotationAccessExtension {
+	/** {@inheritDoc} */
+	@Override
+	public Object getType(Annotation annotation) {
+		return annotation.getType();
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public boolean isMultiLine(Annotation annotation) {
+		return true;
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public boolean isTemporary(Annotation annotation) {
+		return !annotation.isPersistent();
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public String getTypeLabel(Annotation annotation) {
+		if(annotation instanceof ErrorAnnotation) {
+			return "Errors";
+		}
+
+		return null;
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public int getLayer(Annotation annotation) {
+		if(annotation instanceof ErrorAnnotation) {
+			return ((ErrorAnnotation)annotation).getLayer();
+		}
+
+		return 0;
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public void paint(Annotation annotation, GC gc, Canvas canvas, Rectangle bounds) {
+		drawImage(((ErrorAnnotation)annotation).getImage(), gc, canvas, bounds, SWT.CENTER,
+				SWT.TOP);
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public boolean isPaintable(Annotation annotation) {
+		if(annotation instanceof ErrorAnnotation) {
+			return ((ErrorAnnotation)annotation).getImage() != null;
+		}
+
+		return false;
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public boolean isSubtype(Object annotationType, Object potentialSupertype) {
+		if(annotationType.equals(potentialSupertype)) {
+			return true;
+		}
+
+		return false;
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public Object[] getSupertypes(Object annotationType) {
+		return new Object[0];
+	}
+}
diff --git a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/annotations/ErrorAnnotation.java b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/annotations/ErrorAnnotation.java
new file mode 100644
index 0000000000000000000000000000000000000000..3e05aaeb93ca19bb99aed312427752c2c3f1959f
--- /dev/null
+++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/annotations/ErrorAnnotation.java
@@ -0,0 +1,100 @@
+/*-------------------------------------------------------------------------+
+| Copyright 2012 fortiss GmbH                                              |
+|                                                                          |
+| Licensed under the Apache License, Version 2.0 (the "License");          |
+| you may not use this file except in compliance with the License.         |
+| You may obtain a copy of the License at                                  |
+|                                                                          |
+|    http://www.apache.org/licenses/LICENSE-2.0                            |
+|                                                                          |
+| Unless required by applicable law or agreed to in writing, software      |
+| distributed under the License is distributed on an "AS IS" BASIS,        |
+| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+| See the License for the specific language governing permissions and      |
+| limitations under the License.                                           |
++--------------------------------------------------------------------------*/
+package org.fortiss.tooling.base.ui.editor.annotations;
+
+import static org.eclipse.wb.swt.ResourceManager.getPluginImage;
+import static org.fortiss.tooling.base.ui.ToolingBaseUIActivator.PLUGIN_ID;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.RGB;
+
+/**
+ * Objects of this class represent one error annotation.
+ * 
+ * @author doebber
+ */
+public class ErrorAnnotation extends Annotation {
+	/** Stores the marker. */
+	private IMarker marker;
+	/** Stores the error text. */
+	private String text;
+	/** Stores the line number. */
+	private int line;
+	/** Stores the error's text position. */
+	private Position position;
+	/** Stores the error type. */
+	public static String ERROR_TYPE = "error.type";
+	/** Stores the error color. */
+	public static final RGB ERROR_RGB = new RGB(255, 0, 0);
+
+	/** Constructor. */
+	public ErrorAnnotation(IMarker marker) {
+		this.marker = marker;
+	}
+
+	/** Constructor. */
+	public ErrorAnnotation(int line, String text) {
+		super(ERROR_TYPE, true, null);
+		this.marker = null;
+		this.line = line;
+		this.text = text;
+	}
+
+	/** Returns the marker. */
+	public IMarker getMarker() {
+		return marker;
+	}
+
+	/** Returns the line. */
+	public int getLine() {
+		return line;
+	}
+
+	/** Returns the error text. */
+	@Override
+	public String getText() {
+		return text;
+	}
+
+	/** Returns the image. */
+	public Image getImage() {
+		return getPluginImage(PLUGIN_ID, "/icons/error.gif");
+	}
+
+	/** Returns the layer. */
+	public int getLayer() {
+		return 3;
+	}
+
+	/** Returns the type. */
+	@Override
+	public String getType() {
+		return ERROR_TYPE;
+	}
+
+	/** Returns the position. */
+	public Position getPosition() {
+		return position;
+	}
+
+	/** Sets the position. */
+	public void setPosition(Position position) {
+		this.position = position;
+	}
+}