Bug 549604 - Text editor status line should show caret offset and
selection

The status line of the test editors before this change shows line:column
information only. This change introduces additionally current cursor
offset, or, if the editor has selection, count of selected characters.

If the editor has no selection, line:column:caret offset is shown.
If the editor has some selection, line:column[selected characters count]
is shown.

Both additions to the status line are enabled by default but can be
turned off on the General -> Editors -> Test Editors preference page.

Change-Id: I9e06f48f29987ac4eb21bfe0e818166bcbc61dbe
Signed-off-by: Andrey Loskutov <loskutov@gmx.de>
diff --git a/org.eclipse.ui.editors/META-INF/MANIFEST.MF b/org.eclipse.ui.editors/META-INF/MANIFEST.MF
index efeb598..c3821be 100644
--- a/org.eclipse.ui.editors/META-INF/MANIFEST.MF
+++ b/org.eclipse.ui.editors/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.ui.editors; singleton:=true
-Bundle-Version: 3.11.600.qualifier
+Bundle-Version: 3.12.0.qualifier
 Bundle-Activator: org.eclipse.ui.internal.editors.text.EditorsPlugin
 Bundle-ActivationPolicy: lazy
 Bundle-Vendor: %providerName
@@ -21,7 +21,7 @@
  org.eclipse.ui.ide;bundle-version="[3.5.0,4.0.0)",
  org.eclipse.ui;bundle-version="[3.5.0,4.0.0)",
  org.eclipse.jface.text;bundle-version="[3.8.0,4.0.0)",
- org.eclipse.ui.workbench.texteditor;bundle-version="[3.10.0,4.0.0)",
+ org.eclipse.ui.workbench.texteditor;bundle-version="[3.13.0,4.0.0)",
  org.eclipse.core.filebuffers;visibility:=reexport;bundle-version="[3.5.0,4.0.0)",
  org.eclipse.core.resources;bundle-version="[3.5.0,4.0.0)",
  org.eclipse.core.filesystem;bundle-version="[1.2.0,2.0.0)"
diff --git a/org.eclipse.ui.editors/pom.xml b/org.eclipse.ui.editors/pom.xml
index fb389ea..0402e5b 100644
--- a/org.eclipse.ui.editors/pom.xml
+++ b/org.eclipse.ui.editors/pom.xml
@@ -18,6 +18,6 @@
   </parent>
   <groupId>org.eclipse.ui</groupId>
   <artifactId>org.eclipse.ui.editors</artifactId>
-  <version>3.11.600-SNAPSHOT</version>
+  <version>3.12.0-SNAPSHOT</version>
   <packaging>eclipse-plugin</packaging>
 </project>
diff --git a/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/text/TextEditorDefaultsPreferencePage.java b/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/text/TextEditorDefaultsPreferencePage.java
index 751675a..fc766cc 100644
--- a/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/text/TextEditorDefaultsPreferencePage.java
+++ b/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/text/TextEditorDefaultsPreferencePage.java
@@ -743,6 +743,9 @@
 		overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_LINE_NUMBER_RULER_COLOR));
 		overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_LINE_NUMBER_RULER));
 
+		overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_CARET_OFFSET));
+		overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_SELECTION_SIZE));
+
 		overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SELECTION_FOREGROUND_COLOR));
 		overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SELECTION_FOREGROUND_DEFAULT_COLOR));
 		overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SELECTION_BACKGROUND_COLOR));
@@ -885,6 +888,14 @@
 		Preference showLineNumbers= new Preference(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_LINE_NUMBER_RULER, label, null);
 		addCheckBox(appearanceComposite, showLineNumbers, new BooleanDomain(), 0);
 
+		label= TextEditorMessages.TextEditorPreferencePage_showCaretOffsetInStatus;
+		Preference showCaretOffset= new Preference(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_CARET_OFFSET, label, null);
+		addCheckBox(appearanceComposite, showCaretOffset, new BooleanDomain(), 0);
+
+		label= TextEditorMessages.TextEditorPreferencePage_showSelectionInStatus;
+		Preference showSelectionNumbers= new Preference(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_SELECTION_SIZE, label, null);
+		addCheckBox(appearanceComposite, showSelectionNumbers, new BooleanDomain(), 0);
+
 		label= TextEditorMessages.TextEditorDefaultsPreferencePage_range_indicator;
 		Preference showMagnet= new Preference(AbstractDecoratedTextEditorPreferenceConstants.SHOW_RANGE_INDICATOR, label, null);
 		addCheckBox(appearanceComposite, showMagnet, new BooleanDomain(), 0);
diff --git a/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/text/TextEditorMessages.java b/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/text/TextEditorMessages.java
index 67f0ae9..12568d9 100644
--- a/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/text/TextEditorMessages.java
+++ b/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/text/TextEditorMessages.java
@@ -40,6 +40,8 @@
 	public static String TextEditorPreferencePage_printMarginColumn;
 	public static String TextEditorPreferencePage_printMarginAllowOverride;
 	public static String TextEditorPreferencePage_showLineNumbers;
+	public static String TextEditorPreferencePage_showCaretOffsetInStatus;
+	public static String TextEditorPreferencePage_showSelectionInStatus;
 	public static String TextEditorPreferencePage_highlightCurrentLine;
 	public static String TextEditorPreferencePage_showPrintMargin;
 	public static String TextEditorPreferencePage_color;
diff --git a/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/text/TextEditorMessages.properties b/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/text/TextEditorMessages.properties
index d3216b4..a770961 100644
--- a/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/text/TextEditorMessages.properties
+++ b/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/text/TextEditorMessages.properties
@@ -22,6 +22,8 @@
 TextEditorPreferencePage_printMarginColumn=Print margin colu&mn:
 TextEditorPreferencePage_printMarginAllowOverride=Allow &editors to override the margin column
 TextEditorPreferencePage_showLineNumbers=Show line num&bers
+TextEditorPreferencePage_showCaretOffsetInStatus=Show c&ursor position in the status line
+TextEditorPreferencePage_showSelectionInStatus=Show selection si&ze in the status line
 TextEditorPreferencePage_highlightCurrentLine=Hi&ghlight current line
 TextEditorPreferencePage_showPrintMargin=Sho&w print margin
 TextEditorPreferencePage_color=&Color:
diff --git a/org.eclipse.ui.editors/src/org/eclipse/ui/texteditor/AbstractDecoratedTextEditorPreferenceConstants.java b/org.eclipse.ui.editors/src/org/eclipse/ui/texteditor/AbstractDecoratedTextEditorPreferenceConstants.java
index 25f7c48..7f71c18 100644
--- a/org.eclipse.ui.editors/src/org/eclipse/ui/texteditor/AbstractDecoratedTextEditorPreferenceConstants.java
+++ b/org.eclipse.ui.editors/src/org/eclipse/ui/texteditor/AbstractDecoratedTextEditorPreferenceConstants.java
@@ -198,12 +198,34 @@
 	public final static String EDITOR_LINE_NUMBER_RULER= "lineNumberRuler"; //$NON-NLS-1$
 
 	/**
-	 * A named preference that holds the color used to render line numbers inside the line number ruler
-	 * (value <code>"lineNumberColor"</code>).
+	 * A named preference that controls if the caret offset is shown in the status line.
+	 * <p>
+	 * The preference value is of type <code>Boolean</code>.
+	 * </p>
+	 * 
+	 * @since 3.12
+	 */
+	public final static String EDITOR_SHOW_CARET_OFFSET= AbstractTextEditor.PREFERENCE_SHOW_CARET_OFFSET;
+
+	/**
+	 * A named preference that controls if the selection size (number of selected characters) is
+	 * shown in the status line.
+	 * <p>
+	 * The preference value is of type <code>Boolean</code>.
+	 * </p>
+	 * 
+	 * @since 3.12
+	 */
+	public final static String EDITOR_SHOW_SELECTION_SIZE= AbstractTextEditor.PREFERENCE_SHOW_SELECTION_SIZE;
+
+	/**
+	 * A named preference that holds the color used to render line numbers inside the line number
+	 * ruler (value <code>"lineNumberColor"</code>).
 	 * <p>
 	 * The preference value is of type <code>String</code>. A RGB color value encoded as a string
 	 * using class <code>PreferenceConverter</code>.
 	 * </p>
+	 * 
 	 * @see org.eclipse.jface.resource.StringConverter
 	 * @see PreferenceConverter
 	 * @see #EDITOR_LINE_NUMBER_RULER
@@ -693,6 +715,9 @@
 
 		store.setDefault(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_LINE_NUMBER_RULER, false);
 
+		store.setDefault(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_CARET_OFFSET, true);
+		store.setDefault(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SHOW_SELECTION_SIZE, true);
+
 		if (!store.getBoolean(USE_QUICK_DIFF_PREFERENCE_PAGE)) {
 			store.setDefault(AbstractDecoratedTextEditorPreferenceConstants.QUICK_DIFF_ALWAYS_ON, true);
 			store.setDefault(AbstractDecoratedTextEditorPreferenceConstants.QUICK_DIFF_CHARACTER_MODE, false);
diff --git a/org.eclipse.ui.workbench.texteditor/.settings/.api_filters b/org.eclipse.ui.workbench.texteditor/.settings/.api_filters
index 8593692..568f0e5 100644
--- a/org.eclipse.ui.workbench.texteditor/.settings/.api_filters
+++ b/org.eclipse.ui.workbench.texteditor/.settings/.api_filters
@@ -1,10 +1,24 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <component id="org.eclipse.ui.workbench.texteditor" version="2">
     <resource path="META-INF/MANIFEST.MF">
-        <filter comment="Filter for bug 515570 - [api] org.eclipse.ui.editorActions should allow modifiers" id="926941240">
+        <filter comment="Bug 549604" id="926941240">
             <message_arguments>
+                <message_argument value="3.13.0"/>
                 <message_argument value="3.12.0"/>
-                <message_argument value="3.11.300"/>
+            </message_arguments>
+        </filter>
+    </resource>
+    <resource path="src/org/eclipse/ui/texteditor/AbstractTextEditor.java" type="org.eclipse.ui.texteditor.AbstractTextEditor">
+        <filter comment="Bug 549604" id="336658481">
+            <message_arguments>
+                <message_argument value="org.eclipse.ui.texteditor.AbstractTextEditor"/>
+                <message_argument value="PREFERENCE_SHOW_CARET_OFFSET"/>
+            </message_arguments>
+        </filter>
+        <filter comment="Bug 549604" id="336658481">
+            <message_arguments>
+                <message_argument value="org.eclipse.ui.texteditor.AbstractTextEditor"/>
+                <message_argument value="PREFERENCE_SHOW_SELECTION_SIZE"/>
             </message_arguments>
         </filter>
     </resource>
diff --git a/org.eclipse.ui.workbench.texteditor/META-INF/MANIFEST.MF b/org.eclipse.ui.workbench.texteditor/META-INF/MANIFEST.MF
index e9a990e..5b8753e 100644
--- a/org.eclipse.ui.workbench.texteditor/META-INF/MANIFEST.MF
+++ b/org.eclipse.ui.workbench.texteditor/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.ui.workbench.texteditor; singleton:=true
-Bundle-Version: 3.12.200.qualifier
+Bundle-Version: 3.13.0.qualifier
 Bundle-Activator: org.eclipse.ui.internal.texteditor.TextEditorPlugin
 Bundle-ActivationPolicy: lazy
 Bundle-Vendor: %providerName
diff --git a/org.eclipse.ui.workbench.texteditor/pom.xml b/org.eclipse.ui.workbench.texteditor/pom.xml
index bcad58d..e0b0fc7 100644
--- a/org.eclipse.ui.workbench.texteditor/pom.xml
+++ b/org.eclipse.ui.workbench.texteditor/pom.xml
@@ -18,6 +18,6 @@
   </parent>
   <groupId>org.eclipse.ui</groupId>
   <artifactId>org.eclipse.ui.workbench.texteditor</artifactId>
-  <version>3.12.200-SNAPSHOT</version>
+  <version>3.13.0-SNAPSHOT</version>
   <packaging>eclipse-plugin</packaging>
 </project>
diff --git a/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/AbstractTextEditor.java b/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/AbstractTextEditor.java
index beb70b4..7b488a3 100644
--- a/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/AbstractTextEditor.java
+++ b/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/AbstractTextEditor.java
@@ -26,11 +26,13 @@
 
 import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.ResourceBundle;
+import java.util.concurrent.atomic.AtomicInteger;
 
 import org.osgi.framework.Bundle;
 
@@ -119,6 +121,7 @@
 
 import org.eclipse.jface.text.AbstractInformationControlManager;
 import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.BlockTextSelection;
 import org.eclipse.jface.text.DefaultLineTracker;
 import org.eclipse.jface.text.DocumentEvent;
 import org.eclipse.jface.text.IDocument;
@@ -2227,6 +2230,26 @@
 	 */
 	public static final String PREFERENCE_WORD_WRAP_ENABLED= "wordwrap.enabled"; //$NON-NLS-1$
 
+	/**
+	 * A named preference to control the initial caret offset visibility on the status line.
+	 * <p>
+	 * Value is of type <code>Boolean</code>.
+	 * </p>
+	 *
+	 * @since 3.13
+	 */
+	public static final String PREFERENCE_SHOW_CARET_OFFSET = "showCaretOffset"; //$NON-NLS-1$
+
+	/**
+	 * A named preference to control the selection visibility on the status line.
+	 * <p>
+	 * Value is of type <code>Boolean</code>.
+	 * </p>
+	 *
+	 * @since 3.13
+	 */
+	public static final String PREFERENCE_SHOW_SELECTION_SIZE = "showSelectionSize"; //$NON-NLS-1$
+
 	/** Menu id for the editor context menu. */
 	public static final String DEFAULT_EDITOR_CONTEXT_MENU_ID= "#EditorContext"; //$NON-NLS-1$
 	/** Menu id for the ruler context menu. */
@@ -2324,8 +2347,10 @@
 	private final PositionLabelValue fLineLabel= new PositionLabelValue();
 	/** The position label value of the current column. */
 	private final PositionLabelValue fColumnLabel= new PositionLabelValue();
+	/** The position label value of the current offset. */
+	private final PositionLabelValue fOffsetLabel = new PositionLabelValue();
 	/** The arguments for the position label pattern. */
-	private final Object[] fPositionLabelPatternArguments= new Object[] { fLineLabel, fColumnLabel };
+	private final Object[] fPositionLabelPatternArguments = new Object[] { fLineLabel, fColumnLabel, fOffsetLabel };
 	/**
 	 * The column support of this editor.
 	 * @since 3.3
@@ -6706,7 +6731,6 @@
 		StyledText styledText= fSourceViewer.getTextWidget();
 		int caret= widgetOffset2ModelOffset(fSourceViewer, styledText.getCaretOffset());
 		IDocument document= fSourceViewer.getDocument();
-
 		if (document == null)
 			return fErrorLabel;
 
@@ -6725,8 +6749,32 @@
 
 			fLineLabel.fValue= line + 1;
 			fColumnLabel.fValue= column + 1;
-			return NLSUtility.format(fPositionLabelPattern, fPositionLabelPatternArguments);
-
+			boolean showSelection = getPreferenceStore().getBoolean(PREFERENCE_SHOW_SELECTION_SIZE);
+			boolean showOffset = getPreferenceStore().getBoolean(PREFERENCE_SHOW_CARET_OFFSET);
+			Point selectedRange = fSourceViewer.getSelectedRange();
+			int selectionLength = selectedRange != null ? selectedRange.y : 0;
+			fOffsetLabel.fValue = selectionLength == 0 ? caret : selectionLength;
+			showSelection = showSelection && selectionLength > 0;
+			if (!showSelection) {
+				if (!showOffset) {
+					// shows line : column
+					return NLSUtility.format(fPositionLabelPattern, fPositionLabelPatternArguments);
+				}
+				// shows line : column : offset
+				return NLSUtility.format(EditorMessages.Editor_statusline_position_pattern_offset,
+						fPositionLabelPatternArguments);
+			}
+			// To show *right* selection, we first need to know if we are in the
+			// block selection mode or not
+			if (isBlockSelectionModeSupported() && isBlockSelectionModeEnabled()) {
+				BlockTextSelection block = (BlockTextSelection) fSourceViewer.getSelectionProvider().getSelection();
+				AtomicInteger sum = new AtomicInteger();
+				Arrays.asList(block.getRegions()).forEach(r -> sum.addAndGet(r.getLength()));
+				fOffsetLabel.fValue = sum.intValue();
+			}
+			// shows line : column [selection size]
+			return NLSUtility.format(EditorMessages.Editor_statusline_position_pattern_selection,
+					fPositionLabelPatternArguments);
 		} catch (BadLocationException x) {
 			return fErrorLabel;
 		}
diff --git a/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/EditorMessages.java b/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/EditorMessages.java
index 5bc5d95..7fae625 100644
--- a/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/EditorMessages.java
+++ b/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/EditorMessages.java
@@ -94,6 +94,8 @@
 	public static String Editor_statusline_mode_overwrite_label;
 	public static String Editor_statusline_mode_smartinsert_label;
 	public static String Editor_statusline_position_pattern;
+	public static String Editor_statusline_position_pattern_offset;
+	public static String Editor_statusline_position_pattern_selection;
 	public static String Editor_statusline_error_label;
 	public static String WorkbenchChainedTextFontFieldEditor_defaultWorkbenchTextFont;
 	public static String FindReplace_title;
diff --git a/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/EditorMessages.properties b/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/EditorMessages.properties
index 552911f..2aa6b14 100644
--- a/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/EditorMessages.properties
+++ b/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/EditorMessages.properties
@@ -87,6 +87,8 @@
 Editor_statusline_mode_overwrite_label=Overwrite
 Editor_statusline_mode_smartinsert_label=Smart Insert
 Editor_statusline_position_pattern={0} : {1}
+Editor_statusline_position_pattern_offset={0} : {1} : {2}
+Editor_statusline_position_pattern_selection={0} : {1} [{2}]
 Editor_statusline_error_label=?
 
 ## Others ##