### Eclipse Workspace Patch 1.0
#P org.jboss.tools.vpe
Index: src/org/jboss/tools/vpe/editor/util/TextUtil.java
===================================================================
--- src/org/jboss/tools/vpe/editor/util/TextUtil.java	(revision 41574)
+++ src/org/jboss/tools/vpe/editor/util/TextUtil.java	(working copy)
@@ -319,7 +319,11 @@
 
 	public static int visualPosition(String sourceText, int sourcePosition) {
 		int calcPosition = sourcePosition;
-		if (sourceText == null) {
+		/*
+		 * https://issues.jboss.org/browse/JBIDE-12052
+		 * Fix StringIndexOutOfBoundsException
+		 */
+		if ((sourceText == null) || (sourcePosition < 0)){
 			return 0;
 		}
 		int start = sourceText.indexOf(CHR_ESC_START);
Index: src/org/jboss/tools/vpe/editor/template/SelectionManager.java
===================================================================
--- src/org/jboss/tools/vpe/editor/template/SelectionManager.java	(revision 41574)
+++ src/org/jboss/tools/vpe/editor/template/SelectionManager.java	(working copy)
@@ -18,6 +18,7 @@
 
 import org.eclipse.swt.graphics.Point;
 import org.eclipse.wst.sse.ui.StructuredTextEditor;
+import org.eclipse.wst.xml.core.internal.document.AttrImpl;
 import org.eclipse.wst.xml.core.internal.document.NodeImpl;
 import org.eclipse.wst.xml.core.internal.document.TextImpl;
 import org.jboss.tools.jst.jsp.selection.SelectionHelper;
@@ -239,16 +240,16 @@
 		
 		if (nodeMapping instanceof VpeElementMapping) {
 			VpeElementMapping elementMapping = (VpeElementMapping) nodeMapping;
-			nsIDOMNode targetVisualNode = elementMapping.getTemplate()
-					.getVisualNodeBySourcePosition(
-							elementMapping, range, getDomMapping());
-			NodeData nodeData = elementMapping.getTemplate().getNodeData(targetVisualNode,
+			VpeTemplate template = elementMapping.getTemplate();
+			nsIDOMNode targetVisualNode = template.getVisualNodeBySourcePosition(
+					elementMapping, range, getDomMapping());
+			NodeData nodeData = template.getNodeData(targetVisualNode,
 					elementMapping.getElementData(), getDomMapping());
 			// we can restore cursor position only if we have nodeData and
 			// range.y==0
 			if (nodeData != null) {
 				// restore cursor position in source document
-				restoreVisualCursorPosition(elementMapping.getTemplate(), nodeData, range);
+				restoreVisualCursorPosition(template, nodeData, range);
 			}
 		}
 	}
@@ -256,134 +257,155 @@
 	/**
 	 * Restores visual cursor position in visual part of editor
 	 * 
-	 * @param template
-	 *            - current template in scope of which we are editing data
-	 *            !IMPORTANT for current implementation in should be a text node
-	 * @param nodeData
-	 *            -contains mapping before sourceNode(it's can be an attribute)
-	 *            and visual node, attribute
+	 * @param template - current template in scope of which we are editing data
+	 *            	!IMPORTANT for current implementation in should be a text node
+	 * @param nodeData - contains mapping before sourceNode(it's can be an attribute)
+	 *            	and visual node, attribute
+	 * @param selectionRange - a <code>Point</code> with x as the offset 
+	 * 				and y as the length of the current selection or <code>null</code> 
 	 */
 	private void restoreVisualCursorPosition(VpeTemplate template,
 			NodeData nodeData, Point selectionRange) {
-		nsIDOMNode visualNode = nodeData.getVisualNode();
-		if ((visualNode != null) && (nodeData.getSourceNode() != null)
-				&& (visualNode.getNodeType() == nsIDOMNode.TEXT_NODE)) {
-
-			Node targetSourceNode = nodeData.getSourceNode();
-			int focusOffcetReferenceToSourceNode = selectionRange.x
-					- NodesManagingUtil.getStartOffsetNode(targetSourceNode);
-			int anchorOffcetReferenceToSourceNode = selectionRange.x + selectionRange.y
-					- NodesManagingUtil.getStartOffsetNode(targetSourceNode);
-			NodeImpl sourceTextImpl = (NodeImpl) targetSourceNode;
-			int visualNodeFocusOffcet = TextUtil.visualPosition(
-					sourceTextImpl.getValueSource(),
-					focusOffcetReferenceToSourceNode);
-			int visualNodeAnchorOffcet = TextUtil.visualPosition(
-					sourceTextImpl.getValueSource(),
-					anchorOffcetReferenceToSourceNode);
-			int length = visualNode.getNodeValue().length();
+		if (nodeData != null) {
+			nsIDOMNode visualNode = nodeData.getVisualNode();
+			Node sourceNode = nodeData.getSourceNode();
 			
-			if (visualNodeFocusOffcet > length || visualNodeAnchorOffcet > length) {
-				return;
-			}
-			nsISelection selection = selectionController.getSelection(
-					nsISelectionController.SELECTION_NORMAL);
-			if ((visualNodeFocusOffcet == visualNodeAnchorOffcet)) {
-				/*
-				 * Nothing is selected.
-				 */
-				selection.collapse(visualNode, visualNodeFocusOffcet);
-			} else {
-				/*
-				 * https://issues.jboss.org/browse/JBIDE-11137
-				 * Detect selection direction
-				 */
-				int selectionStartOffset;
-				int selectionEndOffset;
-				if (visualNodeFocusOffcet <= visualNodeAnchorOffcet) {
-					selectionStartOffset = visualNodeFocusOffcet;
-					selectionEndOffset = visualNodeAnchorOffcet;
-				} else {
-					selectionStartOffset = visualNodeAnchorOffcet;
-					selectionEndOffset = visualNodeFocusOffcet;
+			if ((selectionRange != null) && (sourceNode != null) && (visualNode != null) 
+					&& (visualNode.getNodeType() == nsIDOMNode.TEXT_NODE)) {
+				
+				int focusOffcetReferenceToSourceNode = selectionRange.x
+						- NodesManagingUtil.getStartOffsetNode(sourceNode);
+				int anchorOffcetReferenceToSourceNode = selectionRange.x + selectionRange.y
+						- NodesManagingUtil.getStartOffsetNode(sourceNode);
+				NodeImpl sourceTextImpl = (NodeImpl) sourceNode;
+				int visualNodeFocusOffcet = TextUtil.visualPosition(
+						sourceTextImpl.getValueSource(),
+						focusOffcetReferenceToSourceNode);
+				int visualNodeAnchorOffcet = TextUtil.visualPosition(
+						sourceTextImpl.getValueSource(),
+						anchorOffcetReferenceToSourceNode);
+				int length = visualNode.getNodeValue().length();
+				
+				if (visualNodeFocusOffcet > length || visualNodeAnchorOffcet > length) {
+					return;
 				}
-				int sourceStartSel = selectionRange.x;
-				int sourceSelLength =  selectionRange.y;
-				int caretOffset = SelectionHelper.getCaretOffset(sourceEditor);
-				TextImpl txt = null;
-				String wholeText = null;
-				int txtStartOffset= -1;
-				int txtEndOffset = -1;
-				int wsStartLength = 0;
-				int wsEndLength = 0;
-				int goodX = 0;
-				int goodY = 0;
-				if (targetSourceNode instanceof TextImpl) {
-					txt = (TextImpl) targetSourceNode;
-					wholeText = txt.getSource();//WholeText();
-					txtStartOffset = txt.getStartOffset();
-					txtEndOffset = txt.getEndOffset();
-					Matcher matcher = START_WHITESPACE.matcher(wholeText);
-					if (matcher.find()) {
-						wsStartLength = matcher.group(1).length();
-					} 
-					matcher = END_WHITESPACE.matcher(wholeText);
-					if (matcher.find()) {
-						wsEndLength = matcher.group(1).length();
-					}
-					goodX = txtStartOffset + wsStartLength;
-					goodY = txtEndOffset - wsEndLength;
-				}
-				boolean skip = false;
-				int allowedLength = 0;  
-				if ((caretOffset >= txtStartOffset) && (caretOffset <= (txtStartOffset + wsStartLength))) {
-					allowedLength = wsStartLength - (caretOffset - txtStartOffset); 
-					if (sourceSelLength <= allowedLength) {
-						skip = true;
-					}
-				} else if ((caretOffset <= txtEndOffset) && (caretOffset >= (txtEndOffset - wsEndLength))
-						&& (sourceSelLength <= wsEndLength)) {
-					allowedLength = wsStartLength - (txtEndOffset - caretOffset); 
-					if (sourceSelLength <= allowedLength) {
-						skip = true;
-					}
-				}
-				if (skip) {
+				
+				nsISelection selection = selectionController.getSelection(
+						nsISelectionController.SELECTION_NORMAL);
+				if ((visualNodeFocusOffcet == visualNodeAnchorOffcet)) {
 					/*
 					 * Nothing is selected.
 					 */
-					selection.collapse(visualNode, selectionStartOffset);
+					selection.collapse(visualNode, visualNodeFocusOffcet);
 				} else {
-					int newX = selectionRange.x;
-					int newY = selectionRange.y;
-					if (newX < goodX) {
-						newY = newY - (goodX - newX);
-						newX = goodX;
+					/*
+					 * https://issues.jboss.org/browse/JBIDE-11137
+					 * Detect selection direction
+					 */
+					int selectionStartOffset;
+					int selectionEndOffset;
+					if (visualNodeFocusOffcet <= visualNodeAnchorOffcet) {
+						selectionStartOffset = visualNodeFocusOffcet;
+						selectionEndOffset = visualNodeAnchorOffcet;
+					} else {
+						selectionStartOffset = visualNodeAnchorOffcet;
+						selectionEndOffset = visualNodeFocusOffcet;
 					}
-					if ((newX + newY) > goodY){
-						newY = goodY - newX;
+					int sourceStartSel = selectionRange.x;
+					int sourceSelLength =  selectionRange.y;
+					int caretOffset = SelectionHelper.getCaretOffset(sourceEditor);
+					TextImpl txt = null;
+					AttrImpl attr = null;
+					String wholeText = null;
+					boolean sourceIsCorrect = false;
+					int txtStartOffset= -1;
+					int txtEndOffset = -1;
+					int wsStartLength = 0;
+					int wsEndLength = 0;
+					int goodX = 0;
+					int goodY = 0;
+					if (sourceNode instanceof TextImpl) {
+						txt = (TextImpl) sourceNode;
+						wholeText = txt.getSource();
+						txtStartOffset = txt.getStartOffset();
+						txtEndOffset = txt.getEndOffset();
+						sourceIsCorrect = true;
+					} else if (sourceNode instanceof AttrImpl) {
+						attr = (AttrImpl) sourceNode;
+						wholeText = attr.getValueSource();
+						txtStartOffset = attr.getValueRegionStartOffset();
+						txtEndOffset = txtStartOffset + attr.getValueRegionText().length();
+						sourceIsCorrect = true;
 					}
-					Point newSrcRange = new Point(newX, newY);
-					int srcStartOffset = newSrcRange.x - NodesManagingUtil.getStartOffsetNode(targetSourceNode);
-					int srcEndOffset = newSrcRange.x + newSrcRange.y - NodesManagingUtil.getStartOffsetNode(targetSourceNode);
-					int visualStartOffset = TextUtil.visualPosition(sourceTextImpl.getValueSource(), srcStartOffset);
-					int visualEndOffset = TextUtil.visualPosition(sourceTextImpl.getValueSource(), srcEndOffset);
-					if (visualStartOffset > length || visualEndOffset > length) {
-						return;
-					}
 					/*
-					 * Detect selection direction
+					 * Currently only text and attribute nodes are supported.
 					 */
-					boolean toLeft = caretOffset <= newSrcRange.x;
-					boolean toRight = caretOffset >= newSrcRange.x + newSrcRange.y;
-					int min = Math.min(visualStartOffset, visualEndOffset);
-					int max = Math.max(visualStartOffset, visualEndOffset);
-					if (toRight) {
-						selection.collapse(visualNode, min);
-						selection.extend(visualNode, max);
-					} else if (toLeft) {
-						selection.collapse(visualNode, max);
-						selection.extend(visualNode, min);
+					if (sourceIsCorrect) {
+						Matcher matcher = START_WHITESPACE.matcher(wholeText);
+						if (matcher.find()) {
+							wsStartLength = matcher.group(1).length();
+						} 
+						matcher = END_WHITESPACE.matcher(wholeText);
+						if (matcher.find()) {
+							wsEndLength = matcher.group(1).length();
+						}
+						goodX = txtStartOffset + wsStartLength;
+						goodY = txtEndOffset - wsEndLength;
+						boolean skip = false;
+						int allowedLength = 0;  
+						if ((caretOffset >= txtStartOffset) && (caretOffset <= (txtStartOffset + wsStartLength))) {
+							allowedLength = wsStartLength - (caretOffset - txtStartOffset); 
+							if (sourceSelLength <= allowedLength) {
+								skip = true;
+							}
+						} else if ((caretOffset <= txtEndOffset) && (caretOffset >= (txtEndOffset - wsEndLength))
+								&& (sourceSelLength <= wsEndLength)) {
+							allowedLength = wsStartLength - (txtEndOffset - caretOffset); 
+							if (sourceSelLength <= allowedLength) {
+								skip = true;
+							}
+						}
+						if (skip) {
+							/*
+							 * Nothing is selected.
+							 */
+							selection.collapse(visualNode, selectionStartOffset);
+						} else {
+							int newX = selectionRange.x;
+							int newY = selectionRange.y;
+							if (newX < goodX) {
+								newY = newY - (goodX - newX);
+								if (newY < 0) {
+									newY = 0;
+								}
+								newX = goodX;
+							}
+							if ((newX + newY) > goodY) {
+								newY = Math.abs(goodY - newX);
+							}
+							Point newSrcRange = new Point(newX, newY);
+							int srcStartOffset = newSrcRange.x - NodesManagingUtil.getStartOffsetNode(sourceNode);
+							int srcEndOffset = srcStartOffset + newSrcRange.y;
+							int visualStartOffset = TextUtil.visualPosition(sourceTextImpl.getValueSource(), srcStartOffset);
+							int visualEndOffset = TextUtil.visualPosition(sourceTextImpl.getValueSource(), srcEndOffset);
+							if (visualStartOffset > length || visualEndOffset > length) {
+								return;
+							}
+							/*
+							 * Detect selection direction
+							 */
+							boolean toLeft = caretOffset <= newSrcRange.x;
+							boolean toRight = caretOffset >= newSrcRange.x + newSrcRange.y;
+							int min = Math.min(visualStartOffset, visualEndOffset);
+							int max = Math.max(visualStartOffset, visualEndOffset);
+							if (toRight) {
+								selection.collapse(visualNode, min);
+								selection.extend(visualNode, max);
+							} else if (toLeft) {
+								selection.collapse(visualNode, max);
+								selection.extend(visualNode, min);
+							}
+						}
 					}
 				}
 			}
Index: src/org/jboss/tools/vpe/editor/util/SelectionUtil.java
===================================================================
--- src/org/jboss/tools/vpe/editor/util/SelectionUtil.java	(revision 41574)
+++ src/org/jboss/tools/vpe/editor/util/SelectionUtil.java	(working copy)
@@ -359,7 +359,8 @@
 	 * 
 	 * @param sourceEditor
 	 *            StructuredTextEditor object
-	 * @return sourceSelectionRange
+	 * @return a <code>Point</code> with x as the offset 
+	 * and y as the length of the current selection or <code>null</code>
 	 */
 	public static Point getSourceSelectionRange(StructuredTextEditor sourceEditor) {
 		ITextViewer textViewer = sourceEditor.getTextViewer();
