### Eclipse Workspace Patch 1.0
#P org.jboss.tools.vpe
Index: src/org/jboss/tools/vpe/editor/VpeController.java
===================================================================
--- src/org/jboss/tools/vpe/editor/VpeController.java	(revision 40740)
+++ src/org/jboss/tools/vpe/editor/VpeController.java	(working copy)
@@ -175,6 +175,11 @@
 	private ScrollBar sourceEditorVerticalScrollBar;
 	private boolean sourceScrollEventFlag = false;
 	private boolean visualScrollEventFlag = false;
+	/*
+	 * https://issues.jboss.org/browse/JBIDE-11137
+	 * flag to indicate that visual selection is being updated.
+	 */
+	boolean visualSelectionIsAlreadyInProgress = false;
 	
 	public static final int DEFAULT_UPDATE_DELAY_TIME = 400;
 	private boolean visualEditorVisible = true;
@@ -426,9 +431,9 @@
 
 		// pageContext.fireTaglibsChanged();
 
-		// yradtsevich: we have to refresh VPE selection on init (fix of
-		// JBIDE-4037)
-		sourceSelectionChanged(true);
+		// yradtsevich: we have to refresh VPE selection on init 
+		// (fix of JBIDE-4037)
+		sourceSelectionChanged();
 		refreshCommands();
 		/*
 		 * Enable/disable "Externalize strings" toolbar icon 
@@ -816,23 +821,19 @@
 	}
 
 	public void sourceSelectionChanged() {
-		sourceSelectionChanged(false);
-	}
-
-	public void sourceSelectionChanged(boolean showCaret) {
 		// we should processed if we have correct view in visual editor,
 		// otherwise we shouldn't process this event
 		if (getChangeEvents().size() > 0) {
 			return;
 		}
-
-		if (selectionManager != null)
+		if (selectionManager != null && !visualSelectionIsAlreadyInProgress) {
 			selectionManager.refreshVisualSelection();
+		}
 	}
 
-	public void sourceSelectionToVisualSelection(boolean showCaret) {
+	public void sourceSelectionToVisualSelection() {
 		if (editPart.getVisualMode() != VpeEditorPart.SOURCE_MODE) {
-			sourceSelectionChanged(showCaret);
+			sourceSelectionChanged();
 		}
 	}
 
@@ -886,34 +887,40 @@
 
 	public void notifySelectionChanged(nsIDOMDocument doc,
 		nsISelection selection, short reason) {
-		mouseUpSelectionReasonFlag = (reason & nsISelectionListener.MOUSEUP_REASON) != 0;
-		if (
-				// commited by Dzmitrovich - experimental
-				// TODO check selection and if are appear errors then
-				// uncommented next code
-			    // reason != nsISelectionListener.NO_REASON
-				(reason & (nsISelectionListener.KEYPRESS_REASON
-						| nsISelectionListener.SELECTALL_REASON
-						| nsISelectionListener.MOUSEDOWN_REASON)) != 0) {
-			if (VpeDebug.PRINT_VISUAL_SELECTION_EVENT) {
-				System.out
-						.println("<<< notifySelectionChanged: " + reason); //$NON-NLS-1$
+		if (!visualSelectionIsAlreadyInProgress) {
+			visualSelectionIsAlreadyInProgress = true;
+			
+			mouseUpSelectionReasonFlag = (reason & nsISelectionListener.MOUSEUP_REASON) != 0;
+			if (
+					// commited by Dzmitrovich - experimental
+					// TODO check selection and if are appear errors then
+					// uncommented next code
+//					 reason != nsISelectionListener.NO_REASON)
+					(reason & (nsISelectionListener.KEYPRESS_REASON
+							| nsISelectionListener.SELECTALL_REASON
+							| nsISelectionListener.MOUSEDOWN_REASON)) != 0) 
+			{
+				if (VpeDebug.PRINT_VISUAL_SELECTION_EVENT) {
+					System.out
+					.println("<<< notifySelectionChanged: " + reason); //$NON-NLS-1$
+				}
+				nsIDOMNode node = SelectionUtil.getSelectedNode(selection);
+				/*
+				 * Fixes https://jira.jboss.org/jira/browse/JBIDE-2571
+				 * Checking if the node is of text type was removed to allow
+				 * <select> node to be selected on the first click.
+				 */
+				if (node != null) {
+					selectionManager.setSelection(SelectionUtil.getSelectedNode(selection),
+							selection.getFocusOffset(), selection.getAnchorOffset());
+				}
 			}
-			nsIDOMNode node = SelectionUtil.getSelectedNode(selection);
-			/*
-			 * Fixes https://jira.jboss.org/jira/browse/JBIDE-2571
-			 * Checking if the node is of text type was removed to allow
-			 * <select> node to be selected on the first click.
-			 */
-			if (node != null) {
-				selectionManager.setSelection(SelectionUtil.getSelectedNode(selection),
-						selection.getFocusOffset(), selection.getAnchorOffset());
-			}
+			// enables cursor on selection event
+			visualSelectionController.setCaretEnabled(true);
+			// enables cursor on selection event
+			visualSelectionController.setCaretEnabled(true);
+			visualSelectionIsAlreadyInProgress = false;
 		}
-		// enables cursor on selection event
-		visualSelectionController.setCaretEnabled(true);
-		// enables cursor on selection event
-		visualSelectionController.setCaretEnabled(true);
 	}
 
 	public void mouseDown(nsIDOMMouseEvent mouseEvent) {
Index: src/org/jboss/tools/vpe/editor/template/SelectionManager.java
===================================================================
--- src/org/jboss/tools/vpe/editor/template/SelectionManager.java	(revision 40740)
+++ src/org/jboss/tools/vpe/editor/template/SelectionManager.java	(working copy)
@@ -13,10 +13,14 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import org.eclipse.swt.graphics.Point;
 import org.eclipse.wst.sse.ui.StructuredTextEditor;
 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;
 import org.jboss.tools.jst.jsp.util.NodesManagingUtil;
 import org.jboss.tools.vpe.editor.context.VpePageContext;
 import org.jboss.tools.vpe.editor.mapping.NodeData;
@@ -58,6 +62,9 @@
 	 * selection
 	 */
 	private VpeSelectionController selectionController;
+	
+	private static Pattern START_WHITESPACE = Pattern.compile("(?<=^)(\\s+)"); //$NON-NLS-1$
+	private static Pattern END_WHITESPACE = Pattern.compile("(\\s+)(?=$)"); //$NON-NLS-1$
 
 	public SelectionManager(VpePageContext pageContext,
 			StructuredTextEditor sourceEditor,
@@ -96,19 +103,25 @@
 		/*************** Calculate selection range ****************************/
 		int selectionOffset;
 		int selectionLength;
+		boolean leftToRightSelection = anchorOffset <= focusOffset; 
 		if (selectionData.isNodeEditable()) {
-			Point sourceSelectionRange = SelectionUtil.getSourceSelectionRange(
-					visualNode, focusOffset, anchorOffset, selectionData.getSourceNode());
+			Point sourceSelectionRange;
+			if (leftToRightSelection) {
+				 sourceSelectionRange = SelectionUtil.getSourceSelectionRange(
+						 visualNode, anchorOffset, focusOffset, selectionData.getSourceNode());
+			} else {
+				sourceSelectionRange = SelectionUtil.getSourceSelectionRange(
+						visualNode, focusOffset, anchorOffset, selectionData.getSourceNode());
+			}
 			selectionOffset = sourceSelectionRange.x;
-			selectionLength = sourceSelectionRange.y;
+			selectionLength = sourceSelectionRange.y - sourceSelectionRange.x;
 		} else {
 			selectionOffset = 0;
 			selectionLength = NodesManagingUtil.getNodeLength(selectionData.getSourceNode());
 		}
 		/*************** Apply selection to views *****************************/
-		SelectionUtil.setSourceSelection(getPageContext(),
-				selectionData.getSourceNode(),
-				selectionOffset, selectionLength);
+		SelectionUtil.setSourceSelection(getPageContext(), 
+				selectionData.getSourceNode(), selectionOffset, selectionLength);
 		refreshVisualNodeSelection();
 		setUpdateSelectionEventFlag(false);
 	}
@@ -253,49 +266,129 @@
 	 */
 	private void restoreVisualCursorPosition(VpeTemplate template,
 			NodeData nodeData, Point selectionRange) {
-
 		nsIDOMNode visualNode = nodeData.getVisualNode();
+		if ((visualNode != null) && (nodeData.getSourceNode() != null)
+				&& (visualNode.getNodeType() == nsIDOMNode.TEXT_NODE)) {
 
-		if (visualNode != null
-				&& visualNode.getNodeType() == nsIDOMNode.TEXT_NODE
-				&& nodeData.getSourceNode() != null) {
-
 			Node targetSourceNode = nodeData.getSourceNode();
-
 			int focusOffcetReferenceToSourceNode = selectionRange.x
 					- NodesManagingUtil.getStartOffsetNode(targetSourceNode);
-
 			int anchorOffcetReferenceToSourceNode = selectionRange.x + selectionRange.y
 					- NodesManagingUtil.getStartOffsetNode(targetSourceNode);
-
-			int length = visualNode.getNodeValue().length();
-//			if (focusOffcetReferenceToSourceNode > length
-//					|| anchorOffcetReferenceToSourceNode > length)
-//				return;
 			NodeImpl sourceTextImpl = (NodeImpl) targetSourceNode;
 			int visualNodeFocusOffcet = TextUtil.visualPosition(
 					sourceTextImpl.getValueSource(),
 					focusOffcetReferenceToSourceNode);
-
 			int visualNodeAnchorOffcet = TextUtil.visualPosition(
 					sourceTextImpl.getValueSource(),
 					anchorOffcetReferenceToSourceNode);
-			if (visualNodeFocusOffcet > length
-					|| visualNodeAnchorOffcet > length)
-					return;
+			int length = visualNode.getNodeValue().length();
+			
+			if (visualNodeFocusOffcet > length || visualNodeAnchorOffcet > length) {
+				return;
+			}
 			nsISelection selection = selectionController.getSelection(
 					nsISelectionController.SELECTION_NORMAL);
-
-			selection.collapse(
-					visualNode, visualNodeFocusOffcet);
-
-			if (visualNodeAnchorOffcet != visualNodeFocusOffcet) {
-				selection.extend(
-						visualNode, visualNodeAnchorOffcet);
+			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;
+				}
+				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) {
+					/*
+					 * Nothing is selected.
+					 */
+					selection.collapse(visualNode, selectionStartOffset);
+				} else {
+					int newX = selectionRange.x;
+					int newY = selectionRange.y;
+					if (newX < goodX) {
+						newY = newY - (goodX - newX);
+						newX = goodX;
+					}
+					if ((newX + newY) > goodY){
+						newY = goodY - newX;
+					}
+					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
+					 */
+					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/template/KeyEventManager.java
===================================================================
--- src/org/jboss/tools/vpe/editor/template/KeyEventManager.java	(revision 40740)
+++ src/org/jboss/tools/vpe/editor/template/KeyEventManager.java	(working copy)
@@ -309,8 +309,8 @@
 			if (range.y == 0) {
 				int offset = getEscOffset(visibleSourceNode, range, delete);
 				if (offset != 0)
-					SelectionUtil.setSourceSelection(pageContext, range.x,
-							offset);
+					SelectionUtil.setSourceSelection(
+							pageContext, range.x,offset);
 
 			}
 			sourceEditor.getTextViewer().getTextWidget().invokeAction(delete);
Index: src/org/jboss/tools/vpe/editor/util/SelectionUtil.java
===================================================================
--- src/org/jboss/tools/vpe/editor/util/SelectionUtil.java	(revision 40740)
+++ src/org/jboss/tools/vpe/editor/util/SelectionUtil.java	(working copy)
@@ -94,7 +94,7 @@
 	 * @param offset
 	 * @param length
 	 */
-	public static void setSourceSelection(VpePageContext pageContext,
+	public static void setSourceSelection(VpePageContext pageContext, 
 			Node node, int offset, int length) {
 		int start = NodesManagingUtil.getStartOffsetNode(node);
 		setSourceSelection(pageContext, start + offset, length);
@@ -106,8 +106,7 @@
 	 * @param node
 	 * @param offset
 	 */
-	public static void setSourceSelection(VpePageContext pageContext,
-			Node node, int offset) {
+	public static void setSourceSelection(VpePageContext pageContext, Node node, int offset) {
 		int start = NodesManagingUtil.getStartOffsetNode(node);
 		pageContext.getSourceBuilder().getStructuredTextViewer()
 				.getTextWidget().setSelection(start + offset);
@@ -121,10 +120,10 @@
 	 */
 	public static void setSourceSelection(VpePageContext pageContext,
 			int offset, int length) {
-		pageContext.getSourceBuilder().getStructuredTextViewer()
-				.setSelectedRange(offset, length);
-		pageContext.getSourceBuilder().getStructuredTextViewer().revealRange(
-				offset, length);
+		pageContext.getSourceBuilder().getStructuredTextViewer().
+				setSelectedRange(offset, length);
+		pageContext.getSourceBuilder().getStructuredTextViewer().
+				revealRange(offset, length);
 	}
 
 	/**
@@ -211,12 +210,15 @@
 	 * Return source editor part selection range, range returns relatively to
 	 * start of text in source, not for start of document
 	 * 
-	 * @param selection
-	 *            the selection in visual part of editor
-	 * @return source editor selection range
+	 * @param focusedNode visual node
+	 * @param startOffset visual node start offset
+	 * @param endOffset visual node end offset
+	 * @param sourceNode corresponding source node
+	 *            
+	 * @return source editor text selection range [startOffset, endOffset]
 	 */
 	public static Point getSourceSelectionRange(nsIDOMNode focusedNode,
-			int focusOffset, int anchorOffset, Node sourceNode) {
+			int startOffset, int endOffset, Node sourceNode) {
 		// gets visual selection range
 		Point sourceRange = new Point(0, 0);
 		// converts to source selection
@@ -224,10 +226,9 @@
 			//fix for JBIDE-3650
 			NodeImpl nodeImpl = (NodeImpl) sourceNode;
 			sourceRange.x = TextUtil.sourcePosition(nodeImpl.getValueSource(),
-					focusedNode.getNodeValue(), focusOffset);
+					focusedNode.getNodeValue(), startOffset);
 			sourceRange.y = TextUtil.sourcePosition(nodeImpl.getValueSource(),
-					focusedNode.getNodeValue(), anchorOffset)
-					- sourceRange.x;
+					focusedNode.getNodeValue(), endOffset);
 		}
 		return sourceRange;
 	}
@@ -235,8 +236,8 @@
 	
 	public static VpeNodeMapping getNodeMappingBySourceSelection(
 			StructuredTextEditor sourceEditor, VpeDomMapping domMapping) {
-		List<VpeNodeMapping> mappings
-				= getNodeMappingsBySourceSelection(sourceEditor, domMapping);
+		List<VpeNodeMapping> mappings = 
+				getNodeMappingsBySourceSelection(sourceEditor, domMapping);
 		if (!mappings.isEmpty()) {
 			return mappings.get(0);
 		} else {
@@ -360,8 +361,7 @@
 	 *            StructuredTextEditor object
 	 * @return sourceSelectionRange
 	 */
-	public static Point getSourceSelectionRange(
-			StructuredTextEditor sourceEditor) {
+	public static Point getSourceSelectionRange(StructuredTextEditor sourceEditor) {
 		ITextViewer textViewer = sourceEditor.getTextViewer();
 		if (textViewer != null) {
 			return textViewer.getSelectedRange();
Index: src/org/jboss/tools/vpe/editor/toolbar/format/FormatController.java
===================================================================
--- src/org/jboss/tools/vpe/editor/toolbar/format/FormatController.java	(revision 40740)
+++ src/org/jboss/tools/vpe/editor/toolbar/format/FormatController.java	(working copy)
@@ -40,7 +40,7 @@
 		manager.setControllerNotifedSelectionChange(true);
 		run();
 //		manager.getVpeController().sourceSelectionChanged(true);
-		manager.getVpeController().sourceSelectionToVisualSelection(true);
+		manager.getVpeController().sourceSelectionToVisualSelection();
 		manager.setControllerNotifedSelectionChange(false);
 	}
 
