Merge remote branch 'origin/master'
diff --git a/bundles/org.eclipse.orion.client.core/web/css/ide.css b/bundles/org.eclipse.orion.client.core/web/css/ide.css
index 669283d..942d0a6 100644
--- a/bundles/org.eclipse.orion.client.core/web/css/ide.css
+++ b/bundles/org.eclipse.orion.client.core/web/css/ide.css
@@ -195,6 +195,10 @@
     overflow-x: auto;
 }
 
+.auxpaneNoPadding {
+    background: #ededed;
+}
+
 .nihilo .dijitSplitterV .dijitSplitterThumb {	
 	background: #dddddd;
 }
diff --git a/bundles/org.eclipse.orion.client.core/web/edit/setup.js b/bundles/org.eclipse.orion.client.core/web/edit/setup.js
index 1019876..5dbb832 100644
--- a/bundles/org.eclipse.orion.client.core/web/edit/setup.js
+++ b/bundles/org.eclipse.orion.client.core/web/edit/setup.js
@@ -336,9 +336,13 @@
 			var genericBindings = new mEditorFeatures.TextActions(editor, undoStack);
 			keyModeStack.push(genericBindings);
 			
+			// Linked Mode
+			var linkedMode = new orion.editor.LinkedMode(editor);
+			keyModeStack.push(linkedMode);
+			
 			// create keybindings for source editing
 			// TODO this should probably be something that happens more dynamically, when the editor changes input
-			var codeBindings = new mEditorFeatures.SourceCodeActions(editor, undoStack, contentAssist);
+			var codeBindings = new mEditorFeatures.SourceCodeActions(editor, undoStack, contentAssist, linkedMode);
 			keyModeStack.push(codeBindings);
 			
 			// give our external escape handler a shot at handling escape
diff --git a/bundles/org.eclipse.orion.client.core/web/orion/compare/compare-container.js b/bundles/org.eclipse.orion.client.core/web/orion/compare/compare-container.js
index b8dcf6f..1db18dd 100644
--- a/bundles/org.eclipse.orion.client.core/web/orion/compare/compare-container.js
+++ b/bundles/org.eclipse.orion.client.core/web/orion/compare/compare-container.js
@@ -129,100 +129,6 @@
 	return CompareContainer;
 }());
 
-exports.SBSCompareContainer = (function() {
-	/** @private */
-	function SBSCompareContainer(resgistry ,leftEditorDivId , rightEditorDivId) {
-		this._textViewLeft = null;
-		this._textViewRight = null;
-		this._registry = resgistry;
-		this._leftEditorDivId = leftEditorDivId;
-		this._rightEditorDivId = rightEditorDivId;
-	}
-	SBSCompareContainer.prototype = new exports.CompareContainer();
-	SBSCompareContainer.prototype.setEditor = function(input , diff){	
-		var result = this.parseMapper(input , diff);
-		if(this._textViewLeft && this._textViewRight){
-			if(result.delim === this._textViewLeft.getModel().getLineDelimiter() ){
-				this._textViewLeft.getModel().init(result.mapper);
-				this._textViewLeft.setText(result.output);
-				this._textViewRight.getModel().init(result.mapper);
-				this._textViewRight.setText(input);
-				this._initDiffPosition(this._textViewLeft);
-				return;
-			}
-		}
-				
-		var modelLeft = new mTextModel.TextModel(result.output, result.delim);
-		var compareModelLeft = new mCompareModel.CompareTextModel(modelLeft, {mapper:result.mapper , columnIndex:0} , new mGapModel.GapLineFeeder( result.delim));
-		var modelRight = new mTextModel.TextModel(input, result.delim);
-		var compareModelRight = new mCompareModel.CompareTextModel(modelRight, {mapper:result.mapper , columnIndex:1} , new mGapModel.GapLineFeeder( result.delim));
-		
-		var optionsRight = {
-			parent: this._rightEditorDivId,
-			model: compareModelRight,
-			readonly: true,
-			stylesheet: "/orion/compare/editor.css" 
-		};
-		this._textViewRight = new mTextView.TextView(optionsRight);
-		this._textViewRight.addRuler(new mRulers.LineNumberCompareRuler(0,"left", {styleClass: "ruler_lines"}, {styleClass: "ruler_lines_odd"}, {styleClass: "ruler_lines_even"}));
-				
-		var optionsLeft = {
-			parent: this._leftEditorDivId,
-			model: compareModelLeft,
-			readonly: true,
-			stylesheet: "/orion/compare/editor.css" 
-		};
-		this._textViewLeft = new mTextView.TextView(optionsLeft);
-		this._textViewLeft.addRuler(new mRulers.LineNumberCompareRuler(0,"left", {styleClass: "ruler_lines"}, {styleClass: "ruler_lines_odd"}, {styleClass: "ruler_lines_even"}));
-		
-		var self = this;
-		this._textViewLeft.addEventListener("LineStyle", window, function(lineStyleEvent) {
-			var lineIndex = lineStyleEvent.lineIndex;
-			var lineStart = lineStyleEvent.lineStart;
-			var lineType =  self._editorLeft.getModel().getLineType(lineIndex);
-			//lineStyleEvent.ranges = [];
-			//lineStyleEvent.ranges.push ({start: lineStart, end: lineStart + 3, style: {style: {backgroundColor: "blue"} }});
-			if(lineType === "added") {
-				lineStyleEvent.style = {style: {backgroundColor: "#99EE99"}};
-			} else if (lineType === "changed"){
-				lineStyleEvent.style = {style: {backgroundColor: "#FFDD88"}};
-			} else if (lineType === "removed" || lineType === "changed_gap"){
-				lineStyleEvent.style = {style: {backgroundColor: "#DDDDDD"}};
-			} 
-		}); 
-
-		this._textViewLeft.addEventListener("Scroll", window, function(scrollEvent) {
-			self._editorRight.setTopPixel(self._editorLeft.getTopPixel());
-		}); 
-				
-		this._textViewLeft.redrawRange();
-		
-		this._textViewRight.addEventListener("LineStyle", window, function(lineStyleEvent) {
-			var lineIndex = lineStyleEvent.lineIndex;
-			var lineStart = lineStyleEvent.lineStart;
-			var lineType =  self._editorRight.getModel().getLineType(lineIndex);
-			if(lineType === "removed") {
-				lineStyleEvent.style = {style: {backgroundColor: "#EE9999"}};
-			} else if (lineType === "changed"){
-				lineStyleEvent.style = {style: {backgroundColor: "#FFDD88"}};
-			} else if (lineType === "added" || lineType === "changed_gap"){
-				lineStyleEvent.style = {style: {backgroundColor: "#DDDDDD"}};
-			} 
-		}); 
-
-		this._textViewRight.addEventListener("Scroll", window, function(scrollEvent) {
-			self._editorLeft.setTopPixel(self._editorRight.getTopPixel());
-		}); 
-				
-		var overview  = new exports.CompareOverviewRuler("right", {styleClass: "ruler_overview"});
-		this._textViewRight.addRuler(overview);
-				
-		this._initDiffPosition(this._textViewLeft);
-		this._textViewRight.redrawRange();
-	};
-	return SBSCompareContainer;
-}());
-
 //temporary text ssyntax styler , we will need to change it later to some thing else
 exports.CompareSyntaxHighlighter = (function() {
 	function CompareSyntaxHighlighter(){
@@ -284,8 +190,8 @@
 			var lineIndex = lineStyleEvent.lineIndex;
 			var lineTypeWrapper =  textView.getModel().getLineType(lineIndex);
 			var lineType = lineTypeWrapper.type;
-			var annotationIndex = textView.getModel().getAnnotationIndexByMapper(lineTypeWrapper.mapperIndex).current;
-			var conflict = textView.getModel().isMapperConflict(lineTypeWrapper.mapperIndex);
+			var annotationIndex = mCompareUtils.getAnnotationIndexByMapper(textView.getModel().getAnnotations(), lineTypeWrapper.mapperIndex).current;
+			var conflict = mCompareUtils.isMapperConflict(textView.getModel().getMapper(), lineTypeWrapper.mapperIndex);
 			//https://bugs.eclipse.org/bugs/show_bug.cgi?id=349227 : we were using border style as the line below.Changing to back ground color and image.
 			//lineStyleEvent.style = {style: {backgroundColor: "#EEEEEE" , borderTop: "1px #AAAAAA solid" , borderLeft: borderStyle , borderRight: borderStyle}};
 			var backgroundColor = conflict ? "#EEB4B4" : "#DDDDDD";
@@ -405,7 +311,9 @@
 		this._textViewLeft = this._editorLeft.getTextView();
 		this._editorRight = this.createEditorContainer(rightContent , delim , mapper ,1 , this._rightEditorDivId , this._uiFactory.getStatusDivId(false) ,true, createLineStyler , fileURIRight);
 		this._textViewRight = this._editorRight.getTextView();
-		var overview  = new mRulers.CompareMergeOverviewRuler(this._compareMatchRenderer ,"right", {styleClass: "ruler_overview"});
+		var that = this;
+		var overview  = new mRulers.CompareMergeOverviewRuler("right", {styleClass: "ruler_overview"} , that._compareMatchRenderer.getAnnotation(),
+				                    function(lineIndex, ruler){that._compareMatchRenderer.matchPositionFromAnnotation(lineIndex);});
 		this._textViewRight.addRuler(overview);
 		this._compareMatchRenderer.setOverviewRuler(overview);
 		var self = this;
@@ -546,7 +454,7 @@
 		textView.addEventListener("Selection", this, function() {
 			var lineIndex = textView.getModel().getLineAtOffset(textView.getCaretOffset());
 			var mapperIndex = mCompareUtils.lookUpMapper(textView.getModel().getMapper() , columnIndex , lineIndex).mapperIndex;
-			var annotationIndex = textView.getModel().getAnnotationIndexByMapper(mapperIndex);
+			var annotationIndex = mCompareUtils.getAnnotationIndexByMapper(textView.getModel().getAnnotations(), mapperIndex);
 			if(annotationIndex.current !== -1)
 				self._compareMatchRenderer.gotoDiff(annotationIndex.current);
 		}); 
@@ -603,10 +511,12 @@
 exports.InlineCompareContainer = (function() {
 	/** @private */
 	function InlineCompareContainer(diffProvider ,resgistry , editorDivId ) {
+		this._annotation = new mRulers.CompareAnnotation();
 		this.setDiffProvider(diffProvider);
 		this._registry = resgistry;
 		this._editorDivId = editorDivId;
 		this.initEditorContainers("" , "\n" , [],[]);
+		this.hasContent = false;
 	}
 	InlineCompareContainer.prototype = new exports.CompareContainer();
 	
@@ -634,6 +544,7 @@
 			this._textView.setText("");
 			this.removeRulers();
 		}
+		this.hasContent = false;
 	};
 
 	InlineCompareContainer.prototype.createEditorContainer = function(content , delim , mapper , diffArray ,createLineStyler , fileURI){
@@ -680,8 +591,26 @@
 			
 		this._rulerOrigin = new mRulers.LineNumberCompareRuler(1,"left", {styleClass: "ruler_lines"}, {styleClass: "ruler_lines_odd"}, {styleClass: "ruler_lines_even"});
 		this._rulerNew = new mRulers.LineNumberCompareRuler(0,"left", {styleClass: "ruler_lines"}, {styleClass: "ruler_lines_odd"}, {styleClass: "ruler_lines_even"});
-		this._overview  = new mRulers.CompareOverviewRuler("right", {styleClass: "ruler_overview"});
+		var that = this;
+		this._overview  = new mRulers.CompareMergeOverviewRuler("right", {styleClass: "ruler_overview"} , that._annotation,
+				function(lineIndex, ruler){
+					that._annotation.matchPositionFromAnnotation(lineIndex);
+					that.positionAnnotation(lineIndex);
+				});
 		textView.addEventListener("LineStyle", this, this._onLineStyle);
+		
+		textView.addEventListener("Selection", this, function() {
+			var lineIndex = textView.getModel().getLineAtOffset(textView.getCaretOffset());
+			var mapperIndex = textView.getModel().getLineType(lineIndex).mapperIndex;
+			var annotationIndex = mCompareUtils.getAnnotationIndexByMapper(textView.getModel().getAnnotations(), mapperIndex);
+			if(annotationIndex.current !== -1){
+				that._annotation.gotoDiff(annotationIndex.current);
+				var drawLine = textView.getTopIndex() ;
+				textView.redrawRange();
+				textView.redrawLines(drawLine , drawLine+  1 , that._overview);
+			}
+		}); 
+		
 		return editor;
 	};
 
@@ -693,15 +622,25 @@
 	InlineCompareContainer.prototype._onLineStyle = function(lineStyleEvent){
 		var lineIndex = lineStyleEvent.lineIndex;
 		var lineStart = lineStyleEvent.lineStart;
-		var lineType = this._textView.getModel().getLineType(lineIndex);
+		var lineTypeWrapper = this._textView.getModel().getLineType(lineIndex);
+		var lineType = lineTypeWrapper.type;
+		
+		var annotationIndex = mCompareUtils.getAnnotationIndexByMapper(this._textView.getModel().getAnnotations(), lineTypeWrapper.mapperIndex).current;
 		if(lineType === "added") {
-			lineStyleEvent.style = {style: {backgroundColor: "#99EE99"}};
+			if(annotationIndex === this._annotation.getCurrentAnnotationIndex())
+				lineStyleEvent.style = {style: {backgroundColor: "#00B400"}};
+			else
+				lineStyleEvent.style = {style: {backgroundColor: "#99EE99"}};
 		} else if (lineType === "removed"){
-			lineStyleEvent.style = {style: {backgroundColor: "#EE9999"}};
+			if(annotationIndex === this._annotation.getCurrentAnnotationIndex())
+				lineStyleEvent.style = {style: {backgroundColor: "#B44040"}};
+			else
+				lineStyleEvent.style = {style: {backgroundColor: "#EE9999"}};
 		} 
 	};
 	
 	InlineCompareContainer.prototype.setEditor = function(input , diff){
+		this.hasContent = true;
 		var result = this.parseMapper(input , diff , false , true);
 		var self = this;
 		if(!this._textView){
@@ -713,9 +652,33 @@
 			
 			this._textView.getModel().init(result.mapper , result.diffArray);
 			this._textView.setText(input);
+			this._annotation.init(result.mapper ,this._textView);
 		}
 		this._initDiffPosition(this._textView);
 	};
+	
+	InlineCompareContainer.prototype.nextDiff = function(){	
+		this._annotation.nextDiff();
+		this.positionAnnotation(this._textView.getModel().getAnnotations()[this._annotation.getCurrentAnnotationIndex()][0]);
+	};
+	
+	InlineCompareContainer.prototype.prevDiff = function(){	
+		this._annotation.prevDiff();
+		this.positionAnnotation(this._textView.getModel().getAnnotations()[this._annotation.getCurrentAnnotationIndex()][0]);
+	};
+	
+	InlineCompareContainer.prototype.positionAnnotation = function(lineIndex){	
+		if(this._textView){
+			var lineHeight = this._textView.getLineHeight();
+			var clientArea = this._textView.getClientArea();
+			var lines = Math.floor(clientArea.height / lineHeight/3);
+			this._textView.setTopIndex((lineIndex - lines) > 0 ? lineIndex - lines : 0);
+			this._textView.redrawRange();
+			var drawLine = this._textView.getTopIndex() ;
+			this._textView.redrawLines(drawLine , drawLine+  1 , this._overview);
+		}
+	};
+
 	return InlineCompareContainer;
 }());
 
diff --git a/bundles/org.eclipse.orion.client.core/web/orion/compare/compare-m-model.js b/bundles/org.eclipse.orion.client.core/web/orion/compare/compare-m-model.js
index 29dcb5c..29b5b8c 100644
--- a/bundles/org.eclipse.orion.client.core/web/orion/compare/compare-m-model.js
+++ b/bundles/org.eclipse.orion.client.core/web/orion/compare/compare-m-model.js
@@ -63,14 +63,6 @@
 			return this._mapper.length === 0;
 		},
 		
-		isMapperConflict: function(mapperIndex){
-			if(mapperIndex < 0)
-				return false;
-			if(!this._mapper[mapperIndex][3])
-				return false;
-			return this._mapper[mapperIndex][3] === 1;
-		},
-		
 		getAnnotations: function(){
 			if(this._annotations === undefined){
 				this._annotations = [];
@@ -85,6 +77,7 @@
 		},
 		
 		getAnnotationH: function(annotationIndex){
+			this.getAnnotations();
 			var mapperIndex = this._annotations[annotationIndex][1];
 			return 	(mapperIndex === -1) ? 0 :this._mapper[mapperIndex][this._mapperColumnIndex];
 			//return 	(annotationIndex === -1) ? 0 : Math.max(this._mapper[annotationIndex][0], this._mapper[annotationIndex][1]);
@@ -95,34 +88,6 @@
 			return 	this.getLineCount();
 		},
 		
-		getAnnotationIndex: function(lineIndex){
-			if(this._annotations === undefined)
-				this.getAnnotations();
-			for (var i = 0 ; i < this._annotations.length ; i++){
-				if(this._annotations[i][0] === lineIndex){
-					return i;//this._annotations[i][1];
-				}
-			}
-			return -1;
-		},
-		
-		getAnnotationMapperIndex: function(annotationIndex){
-			if(this._annotations === undefined)
-				this.getAnnotations();
-			return this._annotations[annotationIndex][1];
-		},
-		
-		getAnnotationIndexByMapper: function(mapperIndex){
-			if(this._annotations === undefined)
-				this.getAnnotations();
-			for (var i = 0 ; i < this._annotations.length ; i++){
-				if(this._annotations[i][1] === mapperIndex){
-					return {current:i,prev:i-1,next:i+1};
-				}
-			}
-			return {current:-1,prev:-1,next:-1};
-		},
-		
 		getLineNumber: function(lineIndex , mapperColumnIndex){
 			return lineIndex;
 		},
diff --git a/bundles/org.eclipse.orion.client.core/web/orion/compare/compare-model.js b/bundles/org.eclipse.orion.client.core/web/orion/compare/compare-model.js
index 443049d..4d05331 100644
--- a/bundles/org.eclipse.orion.client.core/web/orion/compare/compare-model.js
+++ b/bundles/org.eclipse.orion.client.core/web/orion/compare/compare-model.js
@@ -76,6 +76,10 @@
 			return this._lineFeeder.getLineType(lineIndex , this._mapperColumnIndex);
 		},
 			
+		getMapper: function(){
+			return this._mapper;
+		},
+		
 		getAnnotations: function(){
 			return this._lineFeeder.getAnnotations();
 		},
@@ -84,6 +88,10 @@
 			return this._lineFeeder.getAnnotationH(lineIndex);
 		},
 		
+		getAnnotationLineCount: function(){
+			return 	this.getLineCount();
+		},
+		
 		getLineNumber: function(lineIndex , mapperColumnIndex){
 			if(this._lineFeeder.getLineNumber)
 				return this._lineFeeder.getLineNumber(lineIndex , mapperColumnIndex);
@@ -282,7 +290,7 @@
 					gapBlocks.push([curLineindex + this._mapper[i][mapperColumnIndexCompare] , gap , this._mapper[i][2]]);
 				}
 				if((this._mapper[i][2] !== 0))
-					this._annotations.push([curLineindex , delta]);
+					this._annotations.push([curLineindex , i, delta]);
 				curLineindex += delta;
 			}
 			return {gapBlocks:gapBlocks , gapNumber:gapNumber};
@@ -315,19 +323,19 @@
 					delta = this._mapper[i][mapperColumnIndex] + this._mapper[i][mapperColumnIndexCompare];
 				if(lineIndex >= curLineindex && lineIndex < (curLineindex +delta)){
 					if(this._mapper[i][2] === 0){
-						return "unchnaged";
+						return {type:"unchnaged" , mapperIndex:i};
 					} else if(this._mapper[i][2] < 0){
-						return "removed";
+						return {type:"removed" , mapperIndex:i};
 					} else if(this._mapper[i][1] === 0){
-						return "added";
+						return {type:"added", mapperIndex:i};
 					} else if (lineIndex < this._mapper[i][mapperColumnIndexCompare] + curLineindex){
-						return "removed";
+						return {type:"removed" , mapperIndex:i};
 					}	
-					return "added";
+					return {type:"added" , mapperIndex:i};
 				}
 				curLineindex += delta;
 			}
-			return "unchnaged";
+			return {type:"unchnaged" , mapperIndex:-1};
 		},
 		
 		getLineNumber: function(lineIndex , mapperColumnIndex){
@@ -367,12 +375,8 @@
 			return this._annotations;
 		},
 		
-		getAnnotationH: function(lineIndex){
-			for (var i = 0 ; i < this._annotations.length ; i++){
-				if(this._annotations[i][0] === lineIndex)
-					return this._annotations[i][1];
-			}
-			return 0;
+		getAnnotationH: function(annotationIndex){
+			return  this._annotations[annotationIndex][2];
 		}
 		
 	};
@@ -380,6 +384,7 @@
 	return DiffLineFeeder;
 }()); 
 
+// Gap line feeder is no longer used. But we refer to it as an example how the different line feeders serve the compare model.
 orion.GapLineFeeder = (function() {
 	var isWindows = navigator.platform.indexOf("Win") !== -1;
 
@@ -404,7 +409,7 @@
 				}
 				var delta = Math.max(this._mapper[i][mapperColumnIndexCompare], this._mapper[i][mapperColumnIndex]);
 				if((this._mapper[i][2] !== 0))
-					this._annotations.push([curLineindex , delta]);
+					this._annotations.push([curLineindex , i, delta]);
 				curLineindex += delta;
 			}
 			return {gapBlocks:gapBlocks , gapNumber:gapNumber};
@@ -444,12 +449,8 @@
 			return this._annotations;
 		},
 		
-		getAnnotationH: function(lineIndex){
-			for (var i = 0 ; i < this._annotations.length ; i++){
-				if(this._annotations[i][0] === lineIndex)
-					return this._annotations[i][1];
-			}
-			return 0;
+		getAnnotationH: function(annotationIndex){
+			return  this._annotations[annotationIndex][2];
 		}
 		
 	};
diff --git a/bundles/org.eclipse.orion.client.core/web/orion/compare/compareUtils.js b/bundles/org.eclipse.orion.client.core/web/orion/compare/compareUtils.js
index 6520dbf..feaafc9 100644
--- a/bundles/org.eclipse.orion.client.core/web/orion/compare/compareUtils.js
+++ b/bundles/org.eclipse.orion.client.core/web/orion/compare/compareUtils.js
@@ -159,6 +159,39 @@
 	}
 	return fromIndex;
 };
+
+
+orion.compareUtils.getAnnotationIndex = function(annotations, lineIndex){
+	for (var i = 0 ; i < annotations.length ; i++){
+		if(annotations[i][0] === lineIndex){
+			return i;
+		}
+	}
+	return -1;
+};
+
+orion.compareUtils.getAnnotationMapperIndex = function(annotations, annotationIndex){
+	return annotations[annotationIndex][1];
+};
+
+orion.compareUtils.getAnnotationIndexByMapper = function(annotations, mapperIndex){
+	for (var i = 0 ; i < annotations.length ; i++){
+		if(annotations[i][1] === mapperIndex){
+			return {current:i,prev:i-1,next:i+1};
+		}
+	}
+	return {current:-1,prev:-1,next:-1};
+};
+
+orion.compareUtils.isMapperConflict = function(mapper, mapperIndex){
+	if(mapperIndex < 0)
+		return false;
+	if(!mapper[mapperIndex][3])
+		return false;
+	return mapper[mapperIndex][3] === 1;
+};
+
+
 return orion.compareUtils;
 });
 
diff --git a/bundles/org.eclipse.orion.client.core/web/orion/compare/rulers.js b/bundles/org.eclipse.orion.client.core/web/orion/compare/rulers.js
index dd20414..0bcdf5b 100644
--- a/bundles/org.eclipse.orion.client.core/web/orion/compare/rulers.js
+++ b/bundles/org.eclipse.orion.client.core/web/orion/compare/rulers.js
@@ -95,6 +95,67 @@
 	return LineNumberCompareRuler;
 }());
 
+orion.CompareAnnotation =  (function() {
+
+	function CompareAnnotation() {
+		this._currentAnnotationIndex = 0;
+	}
+
+	CompareAnnotation.prototype =  {
+		
+		init: function(mapper , editor ){
+			this._mapper = mapper;
+			this._editor = editor;
+			this._currentAnnotationIndex = 0;
+		},
+		
+		getCurrentAnnotationIndex: function(){
+			return this._currentAnnotationIndex;
+		},
+		
+		getCurrentMapperIndex: function(){
+			var annotations = this._editor.getModel().getAnnotations();
+			return annotations.length === 0 ? -1 : annotations[this._currentAnnotationIndex][1];
+		},
+		
+		matchPositionFromAnnotation: function(index){
+			var annotaionIndex = index;
+			if(index === -1){
+				annotaionIndex = 0;
+			} else {
+				var model =  this._editor.getModel();
+				annotaionIndex = mCompareUtils.getAnnotationIndex(model.getAnnotations(), index);
+			}
+			this._currentAnnotationIndex = annotaionIndex;
+		},
+		
+		gotoDiff: function(annotationIndex){
+			this._currentAnnotationIndex = annotationIndex;
+		},
+		
+		nextDiff: function(){
+			var annotations = this._editor.getModel().getAnnotations();
+			if(annotations.length !== 0 ){
+				if((annotations.length -1) === this._currentAnnotationIndex)
+					this._currentAnnotationIndex = 0;
+				else
+					this._currentAnnotationIndex += 1;
+			}
+		},
+		
+		prevDiff: function(){
+			var annotations = this._editor.getModel().getAnnotations();
+			if(annotations.length !== 0 ){
+				if(0 === this._currentAnnotationIndex)
+					this._currentAnnotationIndex = annotations.length -1;
+				else
+					this._currentAnnotationIndex -= 1;
+			}
+		}
+	};
+	return CompareAnnotation;
+}()); 
+
 /**
  * Creates a new compare overview ruler for the compare editor.
  * @class The compare overview ruler is used by the compare editor to 
@@ -175,8 +236,9 @@
 
 
 orion.CompareMergeOverviewRuler = (function() {
-	function CompareMergeOverviewRuler (compareMatchRenderer , rulerLocation, rulerStyle) {
-		this._compareMatchRenderer = compareMatchRenderer;
+	function CompareMergeOverviewRuler ( rulerLocation, rulerStyle , compareAnnotaion , onClick) {
+		this._compareAnnotaion = compareAnnotaion;
+		this._onClick = onClick;
 		orion.CompareRuler.call(this, rulerLocation, "document", rulerStyle);
 	}
 	CompareMergeOverviewRuler.prototype = new orion.CompareRuler();
@@ -215,12 +277,12 @@
 			
 			var model = this._editor.getModel();
 			if(lineIndex >= 0 && model.getAnnotationH){
-				var annotationIndex = model.getAnnotationIndex(lineIndex);
-				var mapperIndex = model.getAnnotationMapperIndex(annotationIndex);
-				var conflict = model.isMapperConflict(mapperIndex);
+				var annotationIndex = mCompareUtils.getAnnotationIndex(model.getAnnotations(), lineIndex);
+				var mapperIndex = mCompareUtils.getAnnotationMapperIndex(model.getAnnotations(), annotationIndex);
+				var conflict = mCompareUtils.isMapperConflict(model.getMapper(), mapperIndex);
 				if(conflict)
 					style.border = "1px #FF0000 solid";
-				if(annotationIndex === this._compareMatchRenderer.getCurrentAnnotationIndex())
+				if(annotationIndex === this._compareAnnotaion.getCurrentAnnotationIndex())
 					style.backgroundColor = conflict ? "red" :"blue";
 				var anH = model.getAnnotationH(annotationIndex);
 				var lC = model.getAnnotationLineCount();
@@ -240,7 +302,7 @@
 	};
 	CompareMergeOverviewRuler.prototype.onClick = function(lineIndex, e) {
 		if (lineIndex === undefined) { return; }
-		this._compareMatchRenderer.matchPositionFromAnnotation(lineIndex);
+		this._onClick(lineIndex , this);
 	};
 	CompareMergeOverviewRuler.prototype._onModelChanged = function(e) {
 		var model = this._editor.getModel();
@@ -257,6 +319,7 @@
 	function CompareMatchRenderer(canvasDiv) {
 		this._canvasDiv = canvasDiv;
 		this._mapper = undefined;
+		this._annotation = new orion.CompareAnnotation();
 	}
 
 	CompareMatchRenderer.prototype =  {
@@ -265,17 +328,20 @@
 			this._mapper = mapper;
 			this._leftEditor = leftEditor;
 			this._rightEditor = rightEditor;
-			this._currentAnnotationIndex = 0;
+			this._annotation.init(mapper , rightEditor);
 			this.render();
 		},
 		
+		getAnnotation: function(){
+			return this._annotation;
+		},
+		
 		getCurrentAnnotationIndex: function(){
-			return this._currentAnnotationIndex;
+			return this._annotation.getCurrentAnnotationIndex();
 		},
 		
 		getCurrentMapperIndex: function(){
-			var annotations = this._rightEditor.getModel().getAnnotations();
-			return annotations.length === 0 ? -1 : annotations[this._currentAnnotationIndex][1];
+			return this._annotation.getCurrentMapperIndex();
 		},
 		
 		setOverviewRuler: function(overview){
@@ -306,16 +372,10 @@
 		},
 
 		matchPositionFromAnnotation: function(index){
-			var annotaionIndex = index;
-			if(index === -1){
-				annotaionIndex = 0;
-			} else {
-				var model =  this._rightEditor.getModel();
-				annotaionIndex = model.getAnnotationIndex(index);
-			}
-			this._currentAnnotationIndex = annotaionIndex;
-			this.positionAnnotation(annotaionIndex);
+			this._annotation.matchPositionFromAnnotation(index);
+			this.positionAnnotation(this._annotation.getCurrentAnnotationIndex());
 		},
+		
 		positionAnnotation: function(annotationIndex){
 			var annotations = this._rightEditor.getModel().getAnnotations();
 			if(annotations.length === 0)
@@ -330,7 +390,7 @@
 		},
 		
 		gotoDiff: function(annotationIndex){
-			this._currentAnnotationIndex = annotationIndex;
+			this._annotation.gotoDiff(annotationIndex);
 			var drawLine = this._rightEditor.getTopIndex() ;
 			this._leftEditor.redrawRange();
 			this._rightEditor.redrawRange();
@@ -338,26 +398,14 @@
 		},
 		
 		nextDiff: function(){
-			var annotations = this._rightEditor.getModel().getAnnotations();
-			if(annotations.length !== 0 ){
-				if((annotations.length -1) === this._currentAnnotationIndex)
-					this._currentAnnotationIndex = 0;
-				else
-					this._currentAnnotationIndex += 1;
-			}
-			this.positionAnnotation(this._currentAnnotationIndex);
+			this._annotation.nextDiff();
+			this.positionAnnotation(this._annotation.getCurrentAnnotationIndex());
 			this.render();
 		},
 		
 		prevDiff: function(){
-			var annotations = this._rightEditor.getModel().getAnnotations();
-			if(annotations.length !== 0 ){
-				if(0 === this._currentAnnotationIndex)
-					this._currentAnnotationIndex = annotations.length -1;
-				else
-					this._currentAnnotationIndex -= 1;
-			}
-			this.positionAnnotation(this._currentAnnotationIndex);
+			this._annotation.prevDiff();
+			this.positionAnnotation(this._annotation.getCurrentAnnotationIndex());
 			this.render();
 		},
 		
@@ -457,5 +505,6 @@
 	
 	return CompareMatchRenderer;
 }()); 
+
 return orion;
 });
diff --git a/bundles/org.eclipse.orion.client.core/web/orion/fileCommands.js b/bundles/org.eclipse.orion.client.core/web/orion/fileCommands.js
index ea3415d..241a6fb 100644
--- a/bundles/org.eclipse.orion.client.core/web/orion/fileCommands.js
+++ b/bundles/org.eclipse.orion.client.core/web/orion/fileCommands.js
@@ -366,7 +366,7 @@
 		commandService.addCommand(deleteCommand, "dom");
 	
 		var downloadCommand = new mCommands.Command({
-			name: "Export as zip...",
+			name: "Export as zip",
 			image: "/images/exportzip.gif",
 			id: "eclipse.downloadFile",
 			visibleWhen: function(item) {
diff --git a/bundles/org.eclipse.orion.client.core/web/search/search.html b/bundles/org.eclipse.orion.client.core/web/search/search.html
index 3c12733..fcd3769 100644
--- a/bundles/org.eclipse.orion.client.core/web/search/search.html
+++ b/bundles/org.eclipse.orion.client.core/web/search/search.html
@@ -4,7 +4,7 @@
 		<meta name="copyright" content="Copyright (c) IBM Corporation and others 2010." >
 		<meta http-equiv="Content-Language" content="en-us">
 		<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
-    	<title>Orion Search Results</title>
+    	<title>Search Results</title>
     	<link rel="stylesheet" type="text/css" href="search.css" /> 
     	<script type="text/javascript" src="/requirejs/require.js"></script>
 		<script type="text/javascript">
diff --git a/bundles/org.eclipse.orion.client.editor/web/orion/editor/contentAssist.js b/bundles/org.eclipse.orion.client.editor/web/orion/editor/contentAssist.js
index 80e60c0..6d668e3 100644
--- a/bundles/org.eclipse.orion.client.editor/web/orion/editor/contentAssist.js
+++ b/bundles/org.eclipse.orion.client.editor/web/orion/editor/contentAssist.js
@@ -18,13 +18,15 @@
 orion.editor = orion.editor || {};
 
 /**
- * A <tt>ContentAssist</tt> will look for content assist providers in the service registry (if provided).
- * Alternatively, providers can be registered directly by calling {@link #addProvider}.
  * @name orion.editor.ContentAssist
- * @class Can be attached to an Editor to display content assist suggestions.
+ * @class A key mode for {@link orion.editor.Editor} that can display content assist suggestions.
+ * @description A <code>ContentAssist</code> will look for content assist providers in the service registry (if provided).
+ * Alternatively, providers can be registered directly by calling {@link #addProvider}.
+ * <p>To be notified when a proposal has been accepted by the user, clients can register a listener for the <code>"accept"</code> event
+ * using {@link #addEventListener}.</p>
  * @param {orion.editor.Editor} editor The Editor to provide content assist for.
  * @param {String|DomNode} contentAssistId The ID or DOMNode to use as the parent for content assist.
- * @param {orion.ServiceRegistry} [serviceRegistry] Service registry to use for looking up content assist providers.
+ * @param {orion.serviceregistry.ServiceRegistry} [serviceRegistry] Service registry to use for looking up content assist providers.
  * If this parameter is omitted, providers must instead be registered by calling {@link #addProvider}.
  */
 orion.editor.ContentAssist = (function() {
@@ -39,6 +41,8 @@
 		this.contentAssistProviders = [];
 		this.activeServiceReferences = [];
 		this.activeContentAssistProviders = [];
+		this.listeners = {};
+		this.proposals = [];
 		this.contentAssistListener = {
 			onModelChanged: function(event) {
 				if (!this.finishing) {
@@ -49,6 +53,7 @@
 				this.showContentAssist(false);
 			}
 		};
+
 		this.init();
 	}
 	ContentAssist.prototype = /** @lends orion.editor.ContentAssist.prototype */ {
@@ -61,6 +66,23 @@
 			}));
 			dojo.connect(this.editor, "onInputChange", this, this.inputChanged);
 		},
+		/** Registers a listener with this <code>ContentAssist</code>. */
+		addEventListener: function(/** String */ type, /** Function */ listener) {
+			if (!this.listeners[type]) {
+				this.listeners[type] = [];
+			}
+			this.listeners[type].push(listener);
+		},
+		/** @private */
+		dispatchEvent: function(/** String */ type, /** Object */ data) {
+			var event = { type: type, data: data };
+			var listeners = this.listeners[type];
+			if (listeners) {
+				for (var i=0; i < listeners.length; i++) {
+					listeners[i](event);
+				}
+			}
+		},
 		/** @private */
 		inputChanged: function(/**String*/ fileName) {
 			if (this.serviceRegistry) {
@@ -95,7 +117,7 @@
 		},
 		lineUp: function() {
 			if (this.contentAssistPanel) {
-				var selected = this.getSelected();
+				var selected = this.getSelectedNode();
 				if (selected === this.contentAssistPanel.firstChild) {
 					this.setSelected(this.contentAssistPanel.lastChild);
 				} else {
@@ -106,7 +128,7 @@
 		},
 		lineDown: function() {
 			if (this.contentAssistPanel) {
-				var selected = this.getSelected();
+				var selected = this.getSelectedNode();
 				if (selected === this.contentAssistPanel.lastChild) {
 					this.setSelected(this.contentAssistPanel.firstChild);
 				} else {
@@ -115,7 +137,33 @@
 				return true;
 			}
 		},
-		setSelected: function(node) {
+		enter: function() {
+			if (this.contentAssistPanel) {
+				return this.accept();
+			} else {
+				return false;
+			}
+		},
+		/**
+		 * Accepts the currently selected proposal, if any.
+		 * @returns {Boolean}
+		 */
+		accept: function() {
+			var proposal = this.getSelectedProposal();
+			if (proposal === null) {
+				return false;
+			}
+			this.finishing = true;
+			this.showContentAssist(false);
+			var data = {
+				proposal: proposal,
+				start: this.textView.getCaretOffset() - this.prefix.length,
+				end: this.textView.getCaretOffset()
+			};
+			this.dispatchEvent("accept", data);
+			return true;
+		},
+		setSelected: function(/** DOMNode */ node) {
 			var nodes = this.contentAssistPanel.childNodes;
 			for (var i=0; i < nodes.length; i++) {
 				var child = nodes[i];
@@ -127,27 +175,29 @@
 				}
 			}
 		},
-		getSelected: function() {
+		/** @returns {DOMNode} The DOM node of the currently selected proposal. */
+		getSelectedNode: function() {
+			var index = this.getSelectedIndex();
+			return index === -1 ? null : this.contentAssistPanel.childNodes[index];
+		},
+		/** @returns {Number} The index of the currently selected proposal. */
+		getSelectedIndex: function() {
 			var nodes = this.contentAssistPanel.childNodes;
 			for (var i=0; i < nodes.length; i++) {
 				if (nodes[i].className === "selected") {
-					return nodes[i];
+					return i;
 				}
 			}
-			return null;
+			return -1;
 		},
-		enter: function() {
-			if (this.contentAssistPanel) {
-				var proposal = this.getSelected();
-				this.finishing = true;
-				this.textView.setText(proposal.innerHTML.substring(this.prefix.length), this.textView.getCaretOffset(), this.textView.getCaretOffset());
-				this.showContentAssist(false);
-				return true;
-			}
+		/** @returns {Object} The currently selected proposal. */
+		getSelectedProposal: function() {
+			var index = this.getSelectedIndex();
+			return index === -1 ? null : this.proposals[index];
 		},
 		click: function(e) {
 			this.setSelected(e.target);
-			this.enter();
+			this.accept();
 			this.editor.getTextView().focus();
 		},
 		/**
@@ -188,18 +238,39 @@
 //				}
 				this.prefix = this.textView.getText(index, offset);
 				
-				var proposals = [],
-				    buffer = this.textView.getText(),
+				var buffer = this.textView.getText(),
 				    selection = this.textView.getSelection();
+
+				/**
+				 * Bug/feature: The selection returned by the textView doesn't seem to be updated before notifying the listeners
+				 * of onModelChanged. If content assist is triggered by Ctrl+Space, the start/end position of the selection
+				 * (i.e. the caret position) is correct. But if the user then starts to type some text (in order to filter the
+				 * the completion proposals list by a prefix) - i.e. onModelChanged listeners are notified and, in turn,
+				 * this method - the selection is not up-to-date. Because of that, I just did a simple hack of adding the offset
+				 * field for selection, which is computed above and is always correct. The selection is passed to the content
+				 * assist providers.
+				 */
+				selection.offset = offset;
+
+				/**
+				 * Each element of the keywords array returned by content assist providers may be either:
+				 * - String: a simple string proposal
+				 * - Object: must have a property "proposal" giving the proposal string. May also have other fields, which 
+				 * can trigger linked mode behavior in the editor.
+				 */
 				this.getKeywords(this.prefix, buffer, selection).then(
 					dojo.hitch(this, function(keywords) {
+						this.proposals = [];
 						for (var i = 0; i < keywords.length; i++) {
 							var proposal = keywords[i];
-							if (proposal.substr(0, this.prefix.length) === this.prefix) {
-								proposals.push(proposal);
+							if (proposal === null || proposal === undefined) {
+								continue;
+							}
+							if (this.matchesPrefix(proposal) || this.matchesPrefix(proposal.proposal)) {
+								this.proposals.push(proposal);
 							}
 						}
-						if (proposals.length === 0) {
+						if (this.proposals.length === 0) {
 							this.showContentAssist(false);
 							return;
 						}
@@ -207,8 +278,8 @@
 						var caretLocation = this.textView.getLocationAtOffset(offset);
 						caretLocation.y += this.textView.getLineHeight();
 						this.contentAssistPanel.innerHTML = "";
-						for (i = 0; i<proposals.length; i++) {
-							createDiv(proposals[i], i===0, this.contentAssistPanel);
+						for (i = 0; i < this.proposals.length; i++) {
+							createDiv(this.getDisplayString(this.proposals[i]), i===0, this.contentAssistPanel);
 						}
 						this.textView.convert(caretLocation, "document", "page");
 						this.contentAssistPanel.style.position = "absolute";
@@ -226,6 +297,12 @@
 					}));
 			}
 		},
+		getDisplayString: function(proposal) {
+			return typeof proposal === "string" ? proposal : proposal.proposal;
+		},
+		matchesPrefix: function(str) {
+			return typeof str === "string" && str.substr(0, this.prefix.length) === this.prefix;
+		},
 		/**
 		 * @param {String} prefix A prefix against which content assist proposals should be evaluated.
 		 * @param {String} buffer The entire buffer being edited.
diff --git a/bundles/org.eclipse.orion.client.editor/web/orion/editor/editor.js b/bundles/org.eclipse.orion.client.editor/web/orion/editor/editor.js
index 106ecf8..8001b41 100644
--- a/bundles/org.eclipse.orion.client.editor/web/orion/editor/editor.js
+++ b/bundles/org.eclipse.orion.client.editor/web/orion/editor/editor.js
@@ -281,6 +281,15 @@
 				}
 				return false;
 			}));
+
+			textView.setAction("enter", dojo.hitch(this, function() {
+				for (var i=0; i<this._keyModes.length; i++) {
+					if (this._keyModes[i].isActive()) {
+						return this._keyModes[i].enter();
+					}
+				}
+				return false;
+			}));
 						
 			/** @this {orion.editor.Editor} */
 			function updateCursorStatus() {
diff --git a/bundles/org.eclipse.orion.client.editor/web/orion/editor/editorFeatures.js b/bundles/org.eclipse.orion.client.editor/web/orion/editor/editorFeatures.js
index 88da79a..c41331a 100644
--- a/bundles/org.eclipse.orion.client.editor/web/orion/editor/editorFeatures.js
+++ b/bundles/org.eclipse.orion.client.editor/web/orion/editor/editorFeatures.js
@@ -8,7 +8,7 @@
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
-/*global window widgets eclipse:true orion:true serviceRegistry dojo dijit */
+/*global define window widgets eclipse:true orion:true serviceRegistry dojo dijit */
 /*jslint maxerr:150 browser:true devel:true regexp:false*/
 
 
@@ -571,11 +571,20 @@
 }());
 
 orion.editor.SourceCodeActions = (function() {
-	function SourceCodeActions(editor, undoStack, contentAssist) {
+	/**
+	 * @param {orion.editor.ContentAssist} [contentAssist]
+	 * @param {orion.editor.LinkedMode} [linkedMode]
+	 */
+	function SourceCodeActions(editor, undoStack, contentAssist, linkedMode) {
 		this.editor = editor;
 		this.textView = editor.getTextView();
 		this.undoStack = undoStack;
 		this.contentAssist = contentAssist;
+		this.linkedMode = linkedMode;
+		if (this.contentAssist) {
+			this.contentAssist.addEventListener("accept", dojo.hitch(this, this.contentAssistProposalAccepted));
+		}
+		
 		this.init();
 	}
 	SourceCodeActions.prototype = {
@@ -746,37 +755,56 @@
 				this.endUndo();
 				return true;
 			}));
-			
-			//Auto indent
-			this.textView.setAction("enter", dojo.hitch(this, function() {
-				if (this.contentAssist && this.contentAssist.isActive()) {
-					return this.contentAssist.enter();
-				}
-				var selection = this.textView.getSelection();
-				if (selection.start === selection.end) {
-					var model = this.textView.getModel();
-					var lineIndex = model.getLineAtOffset(selection.start);
-					var lineText = model.getLine(lineIndex);
-					var lineStart = model.getLineStart(lineIndex);
-					var index = 0, end = selection.start - lineStart, c;
-					while (index < end && ((c = lineText.charCodeAt(index)) === 32 || c === 9)) { index++; }
-					if (index > 0) {
-						var prefix = lineText.substring(0, index);
-						index = end;
-						while (index < lineText.length && ((c = lineText.charCodeAt(index++)) === 32 || c === 9)) { selection.end++; }
-						this.textView.setText(model.getLineDelimiter() + prefix, selection.start, selection.end);
-						return true;
-					}
-				}
-				return false;
-			}));
 		},
-	
+		/**
+		 * Called when a content assist proposal has been accepted. Inserts the proposal into the
+		 * document. Activates Linked Mode if applicable for the selected proposal.
+		 */
+		contentAssistProposalAccepted: function(event) {
+			/**
+			 * The event.proposal may be either a simple string or an object with this shape:
+			 * {   proposal: "[proposal string]", // Actual text of the proposal
+			 *     positions: [{
+			 *         offset: 10, // Offset of start position of parameter i
+			 *         length: 3  // Length of parameter string for parameter i
+			 *     }], // One object for each parameter; can be null
+			 *     escapePosition: 19 // Offset that caret will be placed at after exiting Linked Mode; can be null
+			 * }
+			 * Offsets are relative to the text buffer.
+			 */
+			var proposalInfo = event.data.proposal;
+			var proposal;
+			if (typeof proposalInfo === "string") {
+				proposal = proposalInfo;
+			} else if (typeof proposalInfo.proposal === "string") {
+				proposal = proposalInfo.proposal;
+			}
+			this.textView.setText(proposal, event.data.start, event.data.end);
+			
+			if (proposalInfo.positions && this.linkedMode) {
+				var positionGroups = [];
+				for (var i = 0; i < proposalInfo.positions.length; ++i) {
+					positionGroups[i] = {
+						positions: [{
+							offset: proposalInfo.positions[i].offset,
+							length: proposalInfo.positions[i].length
+						}]
+					};
+				}
+
+				var linkedModeModel = {
+					groups: positionGroups,
+					escapePosition: proposalInfo.escapePosition
+				};
+				this.linkedMode.enterLinkedMode(linkedModeModel);
+			}
+			return true;
+		},
 		cancel: function() {
 			return false;
 		},
 		isActive: function() {
-			return false;  // we have no modal interactions
+			return true;
 		},
 		lineUp: function() {
 			return false;
@@ -785,12 +813,167 @@
 			return false;
 		},
 		enter: function() {
+			// Auto indent
+			var selection = this.textView.getSelection();
+			if (selection.start === selection.end) {
+				var model = this.textView.getModel();
+				var lineIndex = model.getLineAtOffset(selection.start);
+				var lineText = model.getLine(lineIndex);
+				var lineStart = model.getLineStart(lineIndex);
+				var index = 0, end = selection.start - lineStart, c;
+				while (index < end && ((c = lineText.charCodeAt(index)) === 32 || c === 9)) { index++; }
+				if (index > 0) {
+					var prefix = lineText.substring(0, index);
+					index = end;
+					while (index < lineText.length && ((c = lineText.charCodeAt(index++)) === 32 || c === 9)) { selection.end++; }
+					this.textView.setText(model.getLineDelimiter() + prefix, selection.start, selection.end);
+					return true;
+				}
+			}
 			return false;
 		}
 	};
 	return SourceCodeActions;
 }());
 
+orion.editor.LinkedMode = (function() {
+	function LinkedMode(editor) {
+		this.editor = editor;
+		this.textView = editor.getTextView();
+		
+		/**
+		 * The variables used by the Linked Mode. The elements of linkedModePositions have following structure:
+		 * {
+		 *     offset: 10, // The offset of the position counted from the beginning of the text buffer
+		 *     length: 3 // The length of the position (selection)
+		 * }
+		 *
+		 * The linkedModeEscapePosition contains an offset (counted from the beginning of the text buffer) of a
+		 * position where the caret will be placed after exiting from the Linked Mode.
+		 */
+		this.linkedModeActive = false;
+		this.linkedModePositions = [];
+		this.linkedModeCurrentPositionIndex = 0;
+		this.linkedModeEscapePosition = 0;
+		
+		/**
+		 * Listener called when Linked Mode is active. Updates position's offsets and length
+		 * on user change. Also escapes the Linked Mode if the text buffer was modified outside of the Linked Mode positions.
+		 */
+		this.linkedModeListener = {
+			onVerify: dojo.hitch(this, function(event) {
+				var changeInsideGroup = false;
+				var offsetDifference = 0;
+				for (var i = 0; i < this.linkedModePositions.length; ++i) {
+					var position = this.linkedModePositions[i];
+					if (changeInsideGroup) {
+						// The change has already been noticed, update the offsets of all positions next to the changed one
+						position.offset += offsetDifference;
+					} else if (event.start >= position.offset && event.end <= position.offset + position.length) {
+						// The change was done in the current position, update its length
+						var oldLength = position.length;
+						position.length = (event.start - position.offset) + event.text.length + (position.offset + position.length - event.end);
+						offsetDifference = position.length - oldLength;
+						changeInsideGroup = true;
+					}
+				}
+
+				if (changeInsideGroup) {
+					// Update escape position too
+					this.linkedModeEscapePosition += offsetDifference;
+				} else {
+					// The change has been done outside of the positions, exit the Linked Mode
+					this.cancel();
+				}
+			})
+		};
+	}
+	LinkedMode.prototype = {
+		/**
+		 * Starts Linked Mode, selects the first position and registers the listeners.
+		 * @parma {Object} linkedModeModel An object describing the model to be used by linked mode.
+		 * Contains one or more position groups. If one positions in a group is edited, the other positions in the
+		 * group are edited the same way. The structure is as follows:<pre>
+		 * {
+		 *     groups: [{
+		 *         positions: [{
+		 *             offset: 10, // Relative to the text buffer
+		 *             length: 3
+		 *         }]
+		 *     }],
+		 *     escapePosition: 19, // Relative to the text buffer
+		 * }</pre>
+		 */
+		enterLinkedMode: function(linkedModeModel) {
+			if (this.linkedModeActive) {
+				return;
+			}
+			this.linkedModeActive = true;
+
+			// NOTE: only the first position from each group is supported for now
+			this.linkedModePositions = [];
+			for (var i = 0; i < linkedModeModel.groups.length; ++i) {
+				var group = linkedModeModel.groups[i];
+				this.linkedModePositions[i] = {
+					offset: group.positions[0].offset,
+					length: group.positions[0].length
+				};
+			}
+
+			this.linkedModeEscapePosition = linkedModeModel.escapePosition;
+			this.linkedModeCurrentPositionIndex = 0;
+			this.selectTextForLinkedModePosition(this.linkedModePositions[this.linkedModeCurrentPositionIndex]);
+
+			this.textView.addEventListener("Verify", this, this.linkedModeListener.onVerify);
+
+			this.textView.setKeyBinding(new orion.textview.KeyBinding(9), "nextLinkedModePosition");
+			this.textView.setAction("nextLinkedModePosition", dojo.hitch(this, function() {
+				// Switch to the next group on TAB key
+				this.linkedModeCurrentPositionIndex = ++this.linkedModeCurrentPositionIndex % this.linkedModePositions.length;
+				this.selectTextForLinkedModePosition(this.linkedModePositions[this.linkedModeCurrentPositionIndex]);
+				return true;
+			}));
+			
+			this.textView.setKeyBinding(new orion.textview.KeyBinding(9, false, true), "previousLinkedModePosition");
+			this.textView.setAction("previousLinkedModePosition", dojo.hitch(this, function() {
+				this.linkedModeCurrentPositionIndex = this.linkedModeCurrentPositionIndex > 0 ? this.linkedModeCurrentPositionIndex-1 : this.linkedModePositions.length-1;
+				this.selectTextForLinkedModePosition(this.linkedModePositions[this.linkedModeCurrentPositionIndex]);
+				return true;
+			}));
+
+			this.editor.reportStatus("Linked Mode entered");
+		},
+		isActive: function() {
+			return this.linkedModeActive;
+		},
+		enter: function() {
+			this.cancel();
+			return true;
+		},
+		/** Exits Linked Mode. Places the caret at linkedModeEscapePosition. */
+		cancel: function() {
+			if (!this.linkedModeActive) {
+				return;
+			}
+			this.linkedModeActive = false;
+			this.textView.removeEventListener("Verify", this, this.linkedModeListener.onVerify);
+			this.textView.setKeyBinding(new orion.textview.KeyBinding(9), "tab");
+			this.textView.setKeyBinding(new orion.textview.KeyBinding(9, false, true), null);
+			
+			this.textView.setCaretOffset(this.linkedModeEscapePosition, false);
+
+			this.editor.reportStatus("Linked Mode exited");
+		},
+		/**
+		 * Updates the selection in the textView for given Linked Mode position.
+		 */
+		selectTextForLinkedModePosition: function(position) {
+			this.textView.setSelection(position.offset, position.offset + position.length);
+		}
+	};
+	return LinkedMode;
+}());
+
 if (typeof window !== "undefined" && typeof window.define !== "undefined") {
 	define(['dojo', 'orion/textview/undoStack', 'orion/textview/keyBinding', 'orion/textview/rulers'], function() {
 		return orion.editor;
diff --git a/bundles/org.eclipse.orion.client.git/web/git/git-log.js b/bundles/org.eclipse.orion.client.git/web/git/git-log.js
index 681435d..e644d99 100644
--- a/bundles/org.eclipse.orion.client.git/web/git/git-log.js
+++ b/bundles/org.eclipse.orion.client.git/web/git/git-log.js
@@ -82,9 +82,11 @@
 	
 	// git contributions
 	commandService.registerCommandContribution("eclipse.orion.git.fetch", 100, "pageActions", "eclipse.gitGroup.page");
+	commandService.registerCommandContribution("eclipse.orion.git.fetchForce", 100, "pageActions", "eclipse.gitGroup.page");
 	commandService.registerCommandContribution("eclipse.orion.git.merge", 100, "pageActions", "eclipse.gitGroup.page");
 	commandService.registerCommandContribution("eclipse.orion.git.switchToCurrentLocal", 100, "pageActions", "eclipse.gitGroup.page");	
 	commandService.registerCommandContribution("eclipse.orion.git.push", 100, "pageActions", "eclipse.gitGroup.page");
+	commandService.registerCommandContribution("eclipse.orion.git.pushForce", 100, "pageActions", "eclipse.gitGroup.page");
 	commandService.registerCommandContribution("eclipse.orion.git.switchToRemote", 100, "pageActions", "eclipse.gitGroup.page");
 	commandService.registerCommandContribution("eclipse.orion.git.addTag", 3);
 	
diff --git a/bundles/org.eclipse.orion.client.git/web/git/git-status.html b/bundles/org.eclipse.orion.client.git/web/git/git-status.html
index 3177729..cbeba57 100644
--- a/bundles/org.eclipse.orion.client.git/web/git/git-status.html
+++ b/bundles/org.eclipse.orion.client.git/web/git/git-status.html
@@ -61,7 +61,7 @@
 		</div>
 		
 		<!-- inline compare viewer : start vvv-->
-		<div id = "viewerZone" dojoType="dijit.layout.BorderContainer" design="headline" liveSplitters="false" persist="false" gutters="false" region="center"  splitter="false">
+		<div id = "viewerZone" class="auxpaneNoPadding" dojoType="dijit.layout.BorderContainer" design="headline" liveSplitters="false" persist="false" gutters="false" region="center"  splitter="false">
 		</div>
 		
 		<div class="footer" id="footer" dojoType="dijit.layout.ContentPane" region="bottom" splitter="false">
diff --git a/bundles/org.eclipse.orion.client.git/web/git/git-status.js b/bundles/org.eclipse.orion.client.git/web/git/git-status.js
index 83d4427..ed3e608 100644
--- a/bundles/org.eclipse.orion.client.git/web/git/git-status.js
+++ b/bundles/org.eclipse.orion.client.git/web/git/git-status.js
@@ -49,7 +49,7 @@
 
 		mGlobalCommands.generateBanner("toolbar", serviceRegistry, commandService, preferenceService, searcher);
 	
-		var controller = new mGitStatusTable.GitStatusController({renderLog :true},serviceRegistry , statusService,"unstagedZone" , "stagedZone");
+		var controller = new mGitStatusTable.GitStatusController({renderLog :true},serviceRegistry , commandService , statusService,"unstagedZone" , "stagedZone");
 		controller.getGitStatus(dojo.hash(),true);
 	
 		//every time the user manually changes the hash, we need to load the git status
diff --git a/bundles/org.eclipse.orion.client.git/web/orion/git/git-status-table.js b/bundles/org.eclipse.orion.client.git/web/orion/git/git-status-table.js
index 93679e1..47160ff 100644
--- a/bundles/org.eclipse.orion.client.git/web/orion/git/git-status-table.js
+++ b/bundles/org.eclipse.orion.client.git/web/orion/git/git-status-table.js
@@ -370,13 +370,12 @@
 		this._parentId = parentId;
 	}
 	InlineCompareRenderer.prototype = {
-		render: function () {
+		render: function (createCommandSpan) {
 			var titleTable = dojo.create("table" , {width:"100%"});
 			var row = dojo.create("tr", null, titleTable);
 			var titleCol = dojo.create("td", {nowrap :true}, row, "last");
 			var title = dojo.create("h2", {id :"fileNameInViewer" ,innerHTML: "Select a file on the left to compare..."}, titleCol, "last");
 			var titleDiv = new dijit.layout.ContentPane({region: "top", style:"width:100%;height:30px;overflow: hidden;"});
-			//dojo.addClass(titleDiv, 'auxpane');
 			titleDiv.attr('content', titleTable);
 			
 			var viewerDiv = new dijit.layout.ContentPane({"class":"mainpane" ,id : "inline-compare-viewer" ,splitter:false ,region: "center", style:"width:100%;height:100%;overflow: hidden;"});
@@ -385,6 +384,14 @@
 			var parent = dijit.byId(this._parentId);
 			parent.addChild(titleDiv);
 			parent.addChild(viewerDiv);
+			if (createCommandSpan) {
+				td = document.createElement('td');
+				td.id = "rightContainerCommands"; // this id should not be known here.  It is decided in compare-container.js
+				row.appendChild(td);
+				td.noWrap = true;
+				row.align = "right";
+				titleTable.align = "right";
+			}
 		}
 		
 	};
@@ -392,8 +399,9 @@
 }());
 
 orion.GitStatusController = (function() {
-	function GitStatusController(options ,serviceRegistry , statusService, unstagedDivId , stagedDivId) {
+	function GitStatusController(options ,serviceRegistry , commandService , statusService, unstagedDivId , stagedDivId) {
 		this._registry = serviceRegistry;
+		this._commandService = commandService;
 		this._statusService = statusService;
 		this._model = new orion.GitStatusModel();
 		this._timerOn = false;
@@ -417,7 +425,8 @@
 	        //this._gitCommitNavigatorRem = new mGitCommitNavigator.GitCommitNavigator(serviceRegistry, null, null,this._remoteTableRenderer.getLogContentId());
 		}
 		
-		(new orion.InlineCompareRenderer(serviceRegistry ,"viewerZone")).render();
+		(new orion.InlineCompareRenderer(serviceRegistry ,"viewerZone")).render(true);
+		this._generateInlineCompareCmds();
 		
 		this._unstagedContentRenderer = new orion.GitStatusContentRenderer(serviceRegistry ,this._unstagedTableRenderer.getStatusContentId(), this);
 		this._stagedContentRenderer = new orion.GitStatusContentRenderer(serviceRegistry ,this._stagedTableRenderer.getStatusContentId() , this);
@@ -820,6 +829,41 @@
 			});
 		},
 
+		_generateInlineCompareCmds: function(){	
+			var that = this;
+			var nextDiffCommand = new mCommands.Command({
+				name : "Next Diff",
+				image : "/images/move_down.gif",
+				id: "orion.compare.nextDiff",
+				groupId: "orion.compareGroup",
+				/*
+				visibleWhen: function(item) {
+					return that._inlineCompareContainer && that._inlineCompareContainer.hasContent;
+				},*/
+				
+				callback : function() {
+					that._inlineCompareContainer.nextDiff();
+			}});
+			var prevDiffCommand = new mCommands.Command({
+				name : "Previous Diff",
+				image : "/images/move_up.gif",
+				id: "orion.compare.prevDiff",
+				groupId: "orion.compareGroup",
+				
+				
+				callback : function() {
+					that._inlineCompareContainer.prevDiff();
+			}});
+			
+			this._commandService.addCommand(prevDiffCommand, "dom");
+			this._commandService.addCommand(nextDiffCommand, "dom");
+				
+			// Register command contributions
+			this._commandService.registerCommandContribution("orion.compare.prevDiff", 2, "rightContainerCommands");
+			this._commandService.registerCommandContribution("orion.compare.nextDiff", 1, "rightContainerCommands");
+			this._commandService.renderCommands("rightContainerCommands", "dom", self, self, "image");
+		},
+		
 		startTimer: function(){
 			if(!this.timerOn){
 				this.timerOn = true;
@@ -850,6 +894,7 @@
 			this.hasUnstaged = false;
 			dojo.place(document.createTextNode("Select a file on the left to compare..."), "fileNameInViewer", "only");
 			dojo.style("fileNameInViewer", "color", "#6d6d6d");
+			dojo.empty("rightContainerCommands");
 		},
 
 		_createImgButton: function(enableWaitCursor ,imgParentDiv , imgSrc, imgTitle,onClick){
@@ -957,9 +1002,12 @@
 														dojo.place(document.createTextNode(message), "fileNameInViewer", "only");
 														dojo.style("fileNameInViewer", "color", "#6d6d6d");
 														self._statusService.setProgressMessage("");
+														dojo.empty("rightContainerCommands");
+														self._commandService.renderCommands("rightContainerCommands", "dom", self, self, "image");
 													},
 													function(response, ioArgs){
 														self.handleServerErrors(response , ioArgs);
+														dojo.empty("rightContainerCommands");
 													}
 			);
 		},
diff --git a/bundles/org.eclipse.orion.client.git/web/orion/git/gitClient.js b/bundles/org.eclipse.orion.client.git/web/orion/git/gitClient.js
index 00ae8fc..673510c 100644
--- a/bundles/org.eclipse.orion.client.git/web/orion/git/gitClient.js
+++ b/bundles/org.eclipse.orion.client.git/web/orion/git/gitClient.js
@@ -587,7 +587,7 @@
 				}
 			});
 		},
-		doFetch : function(gitRemoteBranchURI, onLoad, gitSshUsername, gitSshPassword, gitSshKnownHost, gitPrivateKey, gitPassphrase) {
+		doFetch : function(gitRemoteBranchURI, force, onLoad, gitSshUsername, gitSshPassword, gitSshKnownHost, gitPrivateKey, gitPassphrase) {
 			var service = this;
 			
 			return dojo.xhrPost({
@@ -597,6 +597,7 @@
 				},
 				postData : dojo.toJson({
 					"Fetch" : "true",
+					"Force" : force,
 					"GitSshUsername" : gitSshUsername,
 					"GitSshPassword" : gitSshPassword,
 					"GitSshKnownHost" : gitSshKnownHost,
@@ -643,7 +644,7 @@
 				}
 			});
 		},
-		doPush : function(gitBranchURI, srcRef, onLoad, gitSshUsername, gitSshPassword, gitSshKnownHost, gitPrivateKey, gitPassphrase) {
+		doPush : function(gitBranchURI, srcRef, force, onLoad, gitSshUsername, gitSshPassword, gitSshKnownHost, gitPrivateKey, gitPassphrase) {
 			var service = this;
 			
 			return dojo.xhrPost({
@@ -654,6 +655,7 @@
 				postData : dojo.toJson({
 					"PushSrcRef" : srcRef,
 					"PushTags" : true,
+					"Force" : force,
 					"GitSshUsername" : gitSshUsername,
 					"GitSshPassword" : gitSshPassword,
 					"GitSshKnownHost" : gitSshKnownHost,
diff --git a/bundles/org.eclipse.orion.client.git/web/orion/git/gitCommands.js b/bundles/org.eclipse.orion.client.git/web/orion/git/gitCommands.js
index 89fcf0c..2621fe6 100644
--- a/bundles/org.eclipse.orion.client.git/web/orion/git/gitCommands.js
+++ b/bundles/org.eclipse.orion.client.git/web/orion/git/gitCommands.js
@@ -439,7 +439,7 @@
 						var func = arguments.callee;
 						serviceRegistry.getService("orion.git.provider").then(function(gitService) {
 							serviceRegistry.getService("orion.page.message").then(function(progressService) {
-								var deferred = gitService.doFetch(path, null, options.gitSshUsername, options.gitSshPassword, options.knownHosts, options.gitPrivateKey, options.gitPassphrase);
+								var deferred = gitService.doFetch(path, false, null, options.gitSshUsername, options.gitSshPassword, options.knownHosts, options.gitPrivateKey, options.gitPassphrase);
 								progressService.showWhile(deferred, "Fetching remote: " + path).then(
 									function(jsonData, secondArg) {
 										exports.handleProgressServiceResponse(jsonData, options, serviceRegistry,
@@ -488,6 +488,64 @@
 		commandService.addCommand(fetchCommand, "dom");
 		commandService.addCommand(fetchCommand, "object");
 		
+		var fetchForceCommand = new mCommands.Command({
+			name : "Force Fetch",
+			id : "eclipse.orion.git.fetchForce",
+			callback: function(item) {
+				var path = item.Location;
+				exports.getDefaultSshOptions(serviceRegistry).then(function(options){
+						var func = arguments.callee;
+						serviceRegistry.getService("orion.git.provider").then(function(gitService) {
+							serviceRegistry.getService("orion.page.message").then(function(progressService) {
+								var deferred = gitService.doFetch(path, true, null, options.gitSshUsername, options.gitSshPassword, options.knownHosts, options.gitPrivateKey, options.gitPassphrase);
+								progressService.showWhile(deferred, "Fetching remote: " + path).then(
+									function(jsonData, secondArg) {
+										exports.handleProgressServiceResponse(jsonData, options, serviceRegistry,
+												function(jsonData){
+													dojo.xhrGet({
+														url : path,
+														headers : {
+															"Orion-Version" : "1"
+														},
+														postData : dojo.toJson({
+															"GitSshUsername" : options.gitSshUsername,
+															"GitSshPassword" : options.gitSshPassword,
+															"GitSshPrivateKey": options.gitPrivateKey,
+															"GitSshPassphrase": options.gitPassphrase,
+															"GitSshKnownHost" : options.knownHosts
+														}),
+														handleAs : "json",
+														timeout : 5000,
+														load : function(jsonData, secondArg) {
+															return jsonData;
+														},
+														error : function(error, ioArgs) {
+															//handleGetAuthenticationError(this, ioArgs);
+															console.error("HTTP status code: ", ioArgs.xhr.status);
+															return error;
+														}
+													}).then(function(remoteJsonData){
+														if (explorer.parentId === "explorer-tree")
+															gitService.getLog(remoteJsonData.HeadLocation, remoteJsonData.Id, function(scopedCommitsJsonData, secondArd) {
+																explorer.renderer.setIncomingCommits(scopedCommitsJsonData);
+																explorer.loadCommitsList(remoteJsonData.CommitLocation + "?page=1", remoteJsonData, true);			
+															});
+													}, displayErrorOnStatus
+													);
+												}, func, "Fetch Git Repository");
+									});
+							});
+						});
+					});	
+			},
+			visibleWhen : function(item) {
+				return item.Type === "RemoteTrackingBranch" || item.Type === "Remote";
+			}
+		});
+	
+		commandService.addCommand(fetchForceCommand, "dom");
+		commandService.addCommand(fetchForceCommand, "object");
+		
 		var mergeCommand = new mCommands.Command({
 			name : "Merge",
 			image : "/git/images/merge.gif",
@@ -564,7 +622,7 @@
 						var func = arguments.callee;
 						serviceRegistry.getService("orion.git.provider").then(function(gitService) {
 							serviceRegistry.getService("orion.page.message").then(function(progressService) {
-								var deferred = gitService.doPush(item.RemoteLocation, "HEAD", null, options.gitSshUsername, options.gitSshPassword, options.knownHosts, options.gitPrivateKey, options.gitPassphrase);
+								var deferred = gitService.doPush(item.RemoteLocation, "HEAD", false, null, options.gitSshUsername, options.gitSshPassword, options.knownHosts, options.gitPrivateKey, options.gitPassphrase);
 								progressService.showWhile(deferred, "Pushing remote: " + path).then(function(remoteJsonData){
 									exports.handleProgressServiceResponse(remoteJsonData, options, serviceRegistry,
 											function(jsonData){
@@ -591,6 +649,40 @@
 		commandService.addCommand(pushCommand, "dom");
 		commandService.addCommand(pushCommand, "object");
 		
+		var pushForceCommand = new mCommands.Command({
+			name : "Force Push All",
+			image : "/git/images/push.gif",
+			id : "eclipse.orion.git.pushForce",
+			callback: function(item) {
+				var path = dojo.hash();
+				exports.getDefaultSshOptions(serviceRegistry).then(function(options){
+						var func = arguments.callee;
+						serviceRegistry.getService("orion.git.provider").then(function(gitService) {
+							serviceRegistry.getService("orion.page.message").then(function(progressService) {
+								var deferred = gitService.doPush(item.RemoteLocation, "HEAD", true, null, options.gitSshUsername, options.gitSshPassword, options.knownHosts, options.gitPrivateKey, options.gitPassphrase);
+								progressService.showWhile(deferred, "Pushing remote: " + path).then(function(remoteJsonData){
+									exports.handleProgressServiceResponse(remoteJsonData, options, serviceRegistry,
+											function(jsonData){
+												if (jsonData.Result.Severity == "Ok")
+													dojo.query(".treeTableRow").forEach(function(node, i) {
+														dojo.toggleClass(node, "outgoingCommitsdRow", false);
+													});
+											}, func, "Push Git Repository");
+									});
+								});
+							});
+				});
+			},
+			visibleWhen : function(item) {
+				if (item.toRef)
+					// for action in the git log
+					return item.RepositoryPath === "" && item.toRef.Type === "Branch" && item.toRef.Current && item.toRef.RemoteLocation;
+			}
+		});
+	
+		commandService.addCommand(pushForceCommand, "dom");
+		commandService.addCommand(pushForceCommand, "object");
+		
 		var switchToRemote = new mCommands.Command({
 			name : "Switch to Remote",
 			id : "eclipse.orion.git.switchToRemote",
@@ -782,7 +874,7 @@
 						var func = arguments.callee;
 						serviceRegistry.getService("orion.git.provider").then(function(gitService) {
 							serviceRegistry.getService("orion.page.message").then(function(progressService) {
-								var deferred = gitService.doFetch(path, null, options.gitSshUsername, options.gitSshPassword, options.knownHosts, options.gitPrivateKey, options.gitPassphrase);
+								var deferred = gitService.doFetch(path, false, null, options.gitSshUsername, options.gitSshPassword, options.knownHosts, options.gitPrivateKey, options.gitPassphrase);
 								progressService.showWhile(deferred, "Fetching remote: " + path).then(
 									function(jsonData, secondArg) {
 										exports.handleProgressServiceResponse(jsonData, options, serviceRegistry,
@@ -906,7 +998,7 @@
 						var func = arguments.callee;
 						serviceRegistry.getService("orion.git.provider").then(function(gitService) {
 							serviceRegistry.getService("orion.page.message").then(function(progressService) {
-								var deferred = gitService.doPush(item.RemoteLocation, "HEAD", null, options.gitSshUsername, options.gitSshPassword, options.knownHosts, options.gitPrivateKey, options.gitPassphrase);
+								var deferred = gitService.doPush(item.RemoteLocation, "HEAD", false, null, options.gitSshUsername, options.gitSshPassword, options.knownHosts, options.gitPrivateKey, options.gitPassphrase);
 								progressService.showWhile(deferred, "Pushing remote: " + path).then(function(remoteJsonData){
 									exports.handleProgressServiceResponse(remoteJsonData, options, serviceRegistry,
 											function(jsonData){
diff --git a/bundles/org.eclipse.orion.client.users.ui/web/orion/profile/profile.js b/bundles/org.eclipse.orion.client.users.ui/web/orion/profile/profile.js
index fd701a1..cdbc5a1 100644
--- a/bundles/org.eclipse.orion.client.users.ui/web/orion/profile/profile.js
+++ b/bundles/org.eclipse.orion.client.users.ui/web/orion/profile/profile.js
@@ -59,6 +59,7 @@
 			this.commandService = options.commandService;
 			this.pageActionsPlaceholder = options.pageActionsPlaceholder;
 			this.usersClient = options.usersClient;
+			this.iframes = new Array();
 			
 			var userProfile = this;
 			
@@ -120,6 +121,7 @@
 				}
 				
 				this.profileForm.destroy();
+				this.iframes = new Array();
 			}
 			this.pageActionsPlaceholder =  dojo.byId('pageActions');
 			dojo.empty(this.pageActionsPlaceholder);
@@ -146,9 +148,10 @@
 							function(ref){
 								var plugin = registry.getService(ref.getServiceReferences()[0]);
 								plugin.then(function(pluginService){
-									pluginService.getDivContent().then(function(content) {
-										dojo.hitch(userProfile, userProfile.draw(content, div));
-									});
+									if(pluginService.getDivContent)
+										pluginService.getDivContent().then(function(content) {
+											dojo.hitch(userProfile, userProfile.draw(content, div));
+										});
 								});
 							});
 					})(pluginDiv);
@@ -188,11 +191,20 @@
 					if(dojo.byId("profileBanner"))
 						dojo.byId("profileBanner").innerHTML = "Profile Information for <b style='color: #000'>" + jsonData.login + "</b>";
 				}
+				for(var i in this.iframes){
+					this.setHash(this.iframes[i], jsonData.Location);
+				}
 			}else{
 				throw new Error("User is not defined");
 			}
 		},
-		
+		setHash: function(iframe, hash){
+			if(iframe.src.indexOf("#")>0){
+				iframe.src = iframe.src.substr(0, iframe.src.indexOf("#")) + "#" + hash;
+			}else{
+				iframe.src = iframe.src + "#" + hash;
+			}
+		},
 		createFormElem: function(json, node){
 			  if(!json.type){
 			    throw new Error("type is missing!");
@@ -220,7 +232,13 @@
 			  }
 			  
 			},
-		
+		drawIframe: function(desc, placeholder){
+			var iframe = dojo.create("iframe", desc, placeholder);
+			this.iframes.push(iframe);
+			if(this.lastJSON)
+				this.setHash(iframe, this.lastJSON.Location);
+			dojo.place(iframe, placeholder);
+		},
 		draw: function(content, placeholder){
 			var profile = this;
 			placeholder.innerHTML = "";
@@ -244,6 +262,11 @@
 				
 				var sectionContents = dojo.create("div", null, placeholder);
 				
+				if(content.sections[i].type==="iframe"){
+					dojo.hitch(this, this.drawIframe(content.sections[i].data, sectionContents));
+					return;
+				}
+				
 				for(var j=0; j<content.sections[i].data.length; j++){
 					var data = content.sections[i].data[j];
 					var dataDiv = dojo.create("div", null, sectionContents);