View | Details | Raw Unified | Return to bug 140489 | Differences between
and this patch

Collapse All | Expand All

(-)META-INF/MANIFEST.MF (-1 / +2 lines)
Lines 69-74 Link Here
69
 org.eclipse.help,
69
 org.eclipse.help,
70
 org.eclipse.ui.navigator,
70
 org.eclipse.ui.navigator,
71
 org.eclipse.core.expressions,
71
 org.eclipse.core.expressions,
72
 org.eclipse.ui.navigator.resources
72
 org.eclipse.ui.navigator.resources,
73
 com.ibm.icu
73
Eclipse-LazyStart: true
74
Eclipse-LazyStart: true
74
Bundle-RequiredExecutionEnvironment: J2SE-1.4
75
Bundle-RequiredExecutionEnvironment: J2SE-1.4
(-)src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties (+1 lines)
Lines 108-113 Link Here
108
CEditorPreferencePage.colorPage.preview=Preview:
108
CEditorPreferencePage.colorPage.preview=Preview:
109
CEditorPreferencePage.behaviorPage.tabSpace=&Insert space for tabs
109
CEditorPreferencePage.behaviorPage.tabSpace=&Insert space for tabs
110
CEditorPreferencePage.behaviorPage.matchingBrackets=Highlight &matching brackets
110
CEditorPreferencePage.behaviorPage.matchingBrackets=Highlight &matching brackets
111
CEditorPreferencePage.behaviorPage.subWordNavigation=Smart &caret positioning in identifiers
111
CEditorPreferencePage.behaviorPage.inactiveCode=Highlight &inactive code
112
CEditorPreferencePage.behaviorPage.inactiveCode=Highlight &inactive code
112
CEditorPreferencePage.behaviorPage.appearanceColorOptions=Appearance color options:
113
CEditorPreferencePage.behaviorPage.appearanceColorOptions=Appearance color options:
113
CEditorPreferencePage.behaviorPage.matchingBracketColor=Matching brackets highlight
114
CEditorPreferencePage.behaviorPage.matchingBracketColor=Matching brackets highlight
(-)src/org/eclipse/cdt/internal/ui/preferences/CEditorPreferencePage.java (-1 / +7 lines)
Lines 118-123 Link Here
118
        overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ICColorConstants.C_NUMBER + "_bold")); //$NON-NLS-1$
118
        overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ICColorConstants.C_NUMBER + "_bold")); //$NON-NLS-1$
119
        overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ICColorConstants.C_OPERATOR));
119
        overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ICColorConstants.C_OPERATOR));
120
        overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ICColorConstants.C_OPERATOR + "_bold")); //$NON-NLS-1$
120
        overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ICColorConstants.C_OPERATOR + "_bold")); //$NON-NLS-1$
121
		overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, CEditor.SUB_WORD_NAVIGATION));
121
		overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, CEditor.MATCHING_BRACKETS_COLOR));
122
		overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, CEditor.MATCHING_BRACKETS_COLOR));
122
		overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, CEditor.MATCHING_BRACKETS));
123
		overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, CEditor.MATCHING_BRACKETS));
123
		overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, CEditor.INACTIVE_CODE_COLOR));
124
		overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, CEditor.INACTIVE_CODE_COLOR));
Lines 147-152 Link Here
147
		// JDT also enables this feature.
148
		// JDT also enables this feature.
148
		store.setDefault(AbstractTextEditor.PREFERENCE_NAVIGATION_SMART_HOME_END, true);    
149
		store.setDefault(AbstractTextEditor.PREFERENCE_NAVIGATION_SMART_HOME_END, true);    
149
150
151
		store.setDefault(CEditor.SUB_WORD_NAVIGATION, true);
152
		
150
		store.setDefault(CEditor.MATCHING_BRACKETS, true);
153
		store.setDefault(CEditor.MATCHING_BRACKETS, true);
151
		PreferenceConverter.setDefault(store, CEditor.MATCHING_BRACKETS_COLOR, new RGB(170,170,170));
154
		PreferenceConverter.setDefault(store, CEditor.MATCHING_BRACKETS_COLOR, new RGB(170,170,170));
152
155
Lines 336-342 Link Here
336
		layout.numColumns = 2;
339
		layout.numColumns = 2;
337
		behaviorComposite.setLayout(layout);
340
		behaviorComposite.setLayout(layout);
338
341
339
		String label = PreferencesMessages.getString("CEditorPreferencePage.behaviorPage.matchingBrackets"); //$NON-NLS-1$
342
		String label= PreferencesMessages.getString("CEditorPreferencePage.behaviorPage.subWordNavigation"); //$NON-NLS-1$; 
343
		addCheckBox(behaviorComposite, label, CEditor.SUB_WORD_NAVIGATION, 0);
344
345
		label = PreferencesMessages.getString("CEditorPreferencePage.behaviorPage.matchingBrackets"); //$NON-NLS-1$
340
		addCheckBox(behaviorComposite, label, CEditor.MATCHING_BRACKETS, 0);
346
		addCheckBox(behaviorComposite, label, CEditor.MATCHING_BRACKETS, 0);
341
347
342
		label = PreferencesMessages.getString("CEditorPreferencePage.behaviorPage.inactiveCode"); //$NON-NLS-1$
348
		label = PreferencesMessages.getString("CEditorPreferencePage.behaviorPage.inactiveCode"); //$NON-NLS-1$
(-)src/org/eclipse/cdt/internal/ui/editor/CEditor.java (+414 lines)
Lines 10-19 Link Here
10
 *     QNX Software System
10
 *     QNX Software System
11
 *     Anton Leherbauer (Wind River Systems)
11
 *     Anton Leherbauer (Wind River Systems)
12
 *     Markus Schorn (Wind River Systems)
12
 *     Markus Schorn (Wind River Systems)
13
 *     Sergey Prigogin, Google
13
 *******************************************************************************/
14
 *******************************************************************************/
14
package org.eclipse.cdt.internal.ui.editor;
15
package org.eclipse.cdt.internal.ui.editor;
15
16
16
17
18
import java.text.CharacterIterator;
17
import java.util.Iterator;
19
import java.util.Iterator;
18
import java.util.ResourceBundle;
20
import java.util.ResourceBundle;
19
21
Lines 21-26 Link Here
21
import org.eclipse.core.runtime.CoreException;
23
import org.eclipse.core.runtime.CoreException;
22
import org.eclipse.core.runtime.content.IContentType;
24
import org.eclipse.core.runtime.content.IContentType;
23
import org.eclipse.jface.action.Action;
25
import org.eclipse.jface.action.Action;
26
import org.eclipse.jface.action.IAction;
24
import org.eclipse.jface.action.IMenuManager;
27
import org.eclipse.jface.action.IMenuManager;
25
import org.eclipse.jface.action.IStatusLineManager;
28
import org.eclipse.jface.action.IStatusLineManager;
26
import org.eclipse.jface.preference.IPreferenceStore;
29
import org.eclipse.jface.preference.IPreferenceStore;
Lines 72-77 Link Here
72
import org.eclipse.jface.viewers.SelectionChangedEvent;
75
import org.eclipse.jface.viewers.SelectionChangedEvent;
73
import org.eclipse.search.ui.actions.TextSearchGroup;
76
import org.eclipse.search.ui.actions.TextSearchGroup;
74
import org.eclipse.swt.SWT;
77
import org.eclipse.swt.SWT;
78
import org.eclipse.swt.custom.ST;
75
import org.eclipse.swt.custom.StyledText;
79
import org.eclipse.swt.custom.StyledText;
76
import org.eclipse.swt.dnd.DND;
80
import org.eclipse.swt.dnd.DND;
77
import org.eclipse.swt.dnd.DragSource;
81
import org.eclipse.swt.dnd.DragSource;
Lines 104-115 Link Here
104
import org.eclipse.ui.texteditor.ITextEditorActionConstants;
108
import org.eclipse.ui.texteditor.ITextEditorActionConstants;
105
import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
109
import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
106
import org.eclipse.ui.texteditor.ITextEditorDropTargetListener;
110
import org.eclipse.ui.texteditor.ITextEditorDropTargetListener;
111
import org.eclipse.ui.texteditor.IUpdate;
107
import org.eclipse.ui.texteditor.ResourceAction;
112
import org.eclipse.ui.texteditor.ResourceAction;
108
import org.eclipse.ui.texteditor.SourceViewerDecorationSupport;
113
import org.eclipse.ui.texteditor.SourceViewerDecorationSupport;
109
import org.eclipse.ui.texteditor.TextEditorAction;
114
import org.eclipse.ui.texteditor.TextEditorAction;
115
import org.eclipse.ui.texteditor.TextNavigationAction;
110
import org.eclipse.ui.texteditor.TextOperationAction;
116
import org.eclipse.ui.texteditor.TextOperationAction;
111
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
117
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
112
118
119
import com.ibm.icu.text.BreakIterator;
120
113
import org.eclipse.cdt.core.CCorePlugin;
121
import org.eclipse.cdt.core.CCorePlugin;
114
import org.eclipse.cdt.core.CCorePreferenceConstants;
122
import org.eclipse.cdt.core.CCorePreferenceConstants;
115
import org.eclipse.cdt.core.model.CModelException;
123
import org.eclipse.cdt.core.model.CModelException;
Lines 138-143 Link Here
138
import org.eclipse.cdt.internal.ui.text.CPairMatcher;
146
import org.eclipse.cdt.internal.ui.text.CPairMatcher;
139
import org.eclipse.cdt.internal.ui.text.CSourceViewerConfiguration;
147
import org.eclipse.cdt.internal.ui.text.CSourceViewerConfiguration;
140
import org.eclipse.cdt.internal.ui.text.CTextTools;
148
import org.eclipse.cdt.internal.ui.text.CTextTools;
149
import org.eclipse.cdt.internal.ui.text.CWordIterator;
150
import org.eclipse.cdt.internal.ui.text.DocumentCharacterIterator;
141
import org.eclipse.cdt.internal.ui.text.HTMLTextPresenter;
151
import org.eclipse.cdt.internal.ui.text.HTMLTextPresenter;
142
import org.eclipse.cdt.internal.ui.text.ICPartitions;
152
import org.eclipse.cdt.internal.ui.text.ICPartitions;
143
import org.eclipse.cdt.internal.ui.text.c.hover.SourceViewerInformationControl;
153
import org.eclipse.cdt.internal.ui.text.c.hover.SourceViewerInformationControl;
Lines 512-517 Link Here
512
	/** Listener to annotation model changes that updates the error tick in the tab image */
522
	/** Listener to annotation model changes that updates the error tick in the tab image */
513
	private CEditorErrorTickUpdater fCEditorErrorTickUpdater;
523
	private CEditorErrorTickUpdater fCEditorErrorTickUpdater;
514
524
525
	/** Preference key for sub-word navigation, aka smart caret positioning */
526
	public final static String SUB_WORD_NAVIGATION= "subWordNavigation"; //$NON-NLS-1$
515
	/** Preference key for matching brackets */
527
	/** Preference key for matching brackets */
516
	public final static String MATCHING_BRACKETS = "matchingBrackets"; //$NON-NLS-1$
528
	public final static String MATCHING_BRACKETS = "matchingBrackets"; //$NON-NLS-1$
517
	/** Preference key for matching brackets color */
529
	/** Preference key for matching brackets color */
Lines 1396-1401 Link Here
1396
		return store.getBoolean(SPACES_FOR_TABS);
1408
		return store.getBoolean(SPACES_FOR_TABS);
1397
	}
1409
	}
1398
1410
1411
	/*
1412
	 * @see org.eclipse.ui.texteditor.AbstractTextEditor#createNavigationActions()
1413
	 */
1414
	protected void createNavigationActions() {
1415
		super.createNavigationActions();
1416
1417
		final StyledText textWidget = getSourceViewer().getTextWidget();
1418
1419
		IAction action = new NavigatePreviousSubWordAction();
1420
		action.setActionDefinitionId(ITextEditorActionDefinitionIds.WORD_PREVIOUS);
1421
		setAction(ITextEditorActionDefinitionIds.WORD_PREVIOUS, action);
1422
		textWidget.setKeyBinding(SWT.CTRL | SWT.ARROW_LEFT, SWT.NULL);
1423
1424
		action = new NavigateNextSubWordAction();
1425
		action.setActionDefinitionId(ITextEditorActionDefinitionIds.WORD_NEXT);
1426
		setAction(ITextEditorActionDefinitionIds.WORD_NEXT, action);
1427
		textWidget.setKeyBinding(SWT.CTRL | SWT.ARROW_RIGHT, SWT.NULL);
1428
1429
		action = new SelectPreviousSubWordAction();
1430
		action.setActionDefinitionId(ITextEditorActionDefinitionIds.SELECT_WORD_PREVIOUS);
1431
		setAction(ITextEditorActionDefinitionIds.SELECT_WORD_PREVIOUS, action);
1432
		textWidget.setKeyBinding(SWT.CTRL | SWT.SHIFT | SWT.ARROW_LEFT, SWT.NULL);
1433
1434
		action = new SelectNextSubWordAction();
1435
		action.setActionDefinitionId(ITextEditorActionDefinitionIds.SELECT_WORD_NEXT);
1436
		setAction(ITextEditorActionDefinitionIds.SELECT_WORD_NEXT, action);
1437
		textWidget.setKeyBinding(SWT.CTRL | SWT.SHIFT | SWT.ARROW_RIGHT, SWT.NULL);
1438
		
1439
		action= new DeletePreviousSubWordAction();
1440
		action.setActionDefinitionId(ITextEditorActionDefinitionIds.DELETE_PREVIOUS_WORD);
1441
		setAction(ITextEditorActionDefinitionIds.DELETE_PREVIOUS_WORD, action);
1442
		textWidget.setKeyBinding(SWT.CTRL | SWT.BS, SWT.NULL);
1443
		markAsStateDependentAction(ITextEditorActionDefinitionIds.DELETE_PREVIOUS_WORD, true);
1444
1445
		action= new DeleteNextSubWordAction();
1446
		action.setActionDefinitionId(ITextEditorActionDefinitionIds.DELETE_NEXT_WORD);
1447
		setAction(ITextEditorActionDefinitionIds.DELETE_NEXT_WORD, action);
1448
		textWidget.setKeyBinding(SWT.CTRL | SWT.DEL, SWT.NULL);
1449
		markAsStateDependentAction(ITextEditorActionDefinitionIds.DELETE_NEXT_WORD, true);
1450
	}
1451
1399
	interface ITextConverter {
1452
	interface ITextConverter {
1400
		void customizeDocumentCommand(IDocument document, DocumentCommand command);
1453
		void customizeDocumentCommand(IDocument document, DocumentCommand command);
1401
	}
1454
	}
Lines 1669-1672 Link Here
1669
		System.arraycopy(parentPrefPageIds, 0, prefPageIds, nIds, parentPrefPageIds.length);
1722
		System.arraycopy(parentPrefPageIds, 0, prefPageIds, nIds, parentPrefPageIds.length);
1670
		return prefPageIds;
1723
		return prefPageIds;
1671
	}
1724
	}
1725
1726
	/**
1727
	 * Text navigation action to navigate to the next sub-word.
1728
	 *
1729
	 * @since 3.0
1730
	 */
1731
	protected abstract class NextSubWordAction extends TextNavigationAction {
1732
1733
		protected CWordIterator fIterator = new CWordIterator();
1734
1735
		/**
1736
		 * Creates a new next sub-word action.
1737
		 *
1738
		 * @param code Action code for the default operation. Must be an action code from @see org.eclipse.swt.custom.ST.
1739
		 */
1740
		protected NextSubWordAction(int code) {
1741
			super(getSourceViewer().getTextWidget(), code);
1742
		}
1743
1744
		/*
1745
		 * @see org.eclipse.jface.action.IAction#run()
1746
		 */
1747
		public void run() {
1748
			// Check whether sub word navigation is enabled.
1749
			final IPreferenceStore store = getPreferenceStore();
1750
			if (!store.getBoolean(SUB_WORD_NAVIGATION)) {
1751
				super.run();
1752
				return;
1753
			}
1754
1755
			final ISourceViewer viewer = getSourceViewer();
1756
			final IDocument document = viewer.getDocument();
1757
			fIterator.setText((CharacterIterator) new DocumentCharacterIterator(document));
1758
			int position = widgetOffset2ModelOffset(viewer, viewer.getTextWidget().getCaretOffset());
1759
			if (position == -1)
1760
				return;
1761
1762
			int next = findNextPosition(position);
1763
			if (next != BreakIterator.DONE) {
1764
				setCaretPosition(next);
1765
				getTextWidget().showSelection();
1766
				fireSelectionChanged();
1767
			}
1768
1769
		}
1770
1771
		/**
1772
		 * Finds the next position after the given position.
1773
		 *
1774
		 * @param position the current position
1775
		 * @return the next position
1776
		 */
1777
		protected int findNextPosition(int position) {
1778
			ISourceViewer viewer = getSourceViewer();
1779
			int widget = -1;
1780
			while (position != BreakIterator.DONE && widget == -1) { // TODO: optimize
1781
				position = fIterator.following(position);
1782
				if (position != BreakIterator.DONE)
1783
					widget = modelOffset2WidgetOffset(viewer, position);
1784
			}
1785
			return position;
1786
		}
1787
1788
		/**
1789
		 * Sets the caret position to the sub-word boundary given with <code>position</code>.
1790
		 *
1791
		 * @param position Position where the action should move the caret
1792
		 */
1793
		protected abstract void setCaretPosition(int position);
1794
	}
1795
1796
	/**
1797
	 * Text navigation action to navigate to the next sub-word.
1798
	 *
1799
	 * @since 3.0
1800
	 */
1801
	protected class NavigateNextSubWordAction extends NextSubWordAction {
1802
1803
		/**
1804
		 * Creates a new navigate next sub-word action.
1805
		 */
1806
		public NavigateNextSubWordAction() {
1807
			super(ST.WORD_NEXT);
1808
		}
1809
1810
		/*
1811
		 * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor.NextSubWordAction#setCaretPosition(int)
1812
		 */
1813
		protected void setCaretPosition(final int position) {
1814
			getTextWidget().setCaretOffset(modelOffset2WidgetOffset(getSourceViewer(), position));
1815
		}
1816
	}
1817
1818
	/**
1819
	 * Text operation action to delete the next sub-word.
1820
	 *
1821
	 * @since 3.0
1822
	 */
1823
	protected class DeleteNextSubWordAction extends NextSubWordAction implements IUpdate {
1824
1825
		/**
1826
		 * Creates a new delete next sub-word action.
1827
		 */
1828
		public DeleteNextSubWordAction() {
1829
			super(ST.DELETE_WORD_NEXT);
1830
		}
1831
1832
		/*
1833
		 * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor.NextSubWordAction#setCaretPosition(int)
1834
		 */
1835
		protected void setCaretPosition(final int position) {
1836
			if (!validateEditorInputState())
1837
				return;
1838
1839
			final ISourceViewer viewer = getSourceViewer();
1840
			final int caret, length;
1841
			Point selection = viewer.getSelectedRange();
1842
			if (selection.y != 0) {
1843
				caret = selection.x;
1844
				length = selection.y;
1845
			} else {
1846
				caret = widgetOffset2ModelOffset(viewer, viewer.getTextWidget().getCaretOffset());
1847
				length = position - caret;
1848
			}
1849
1850
			try {
1851
				viewer.getDocument().replace(caret, length, ""); //$NON-NLS-1$
1852
			} catch (BadLocationException exception) {
1853
				// Should not happen
1854
			}
1855
		}
1856
1857
		/*
1858
		 * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor.NextSubWordAction#findNextPosition(int)
1859
		 */
1860
		protected int findNextPosition(int position) {
1861
			return fIterator.following(position);
1862
		}
1863
1864
		/*
1865
		 * @see org.eclipse.ui.texteditor.IUpdate#update()
1866
		 */
1867
		public void update() {
1868
			setEnabled(isEditorInputModifiable());
1869
		}
1870
	}
1871
1872
	/**
1873
	 * Text operation action to select the next sub-word.
1874
	 *
1875
	 * @since 3.0
1876
	 */
1877
	protected class SelectNextSubWordAction extends NextSubWordAction {
1878
1879
		/**
1880
		 * Creates a new select next sub-word action.
1881
		 */
1882
		public SelectNextSubWordAction() {
1883
			super(ST.SELECT_WORD_NEXT);
1884
		}
1885
1886
		/*
1887
		 * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor.NextSubWordAction#setCaretPosition(int)
1888
		 */
1889
		protected void setCaretPosition(final int position) {
1890
			final ISourceViewer viewer = getSourceViewer();
1891
1892
			final StyledText text = viewer.getTextWidget();
1893
			if (text != null && !text.isDisposed()) {
1894
1895
				final Point selection = text.getSelection();
1896
				final int caret = text.getCaretOffset();
1897
				final int offset = modelOffset2WidgetOffset(viewer, position);
1898
1899
				if (caret == selection.x)
1900
					text.setSelectionRange(selection.y, offset - selection.y);
1901
				else
1902
					text.setSelectionRange(selection.x, offset - selection.x);
1903
			}
1904
		}
1905
	}
1906
1907
	/**
1908
	 * Text navigation action to navigate to the previous sub-word.
1909
	 *
1910
	 * @since 3.0
1911
	 */
1912
	protected abstract class PreviousSubWordAction extends TextNavigationAction {
1913
1914
		protected CWordIterator fIterator = new CWordIterator();
1915
1916
		/**
1917
		 * Creates a new previous sub-word action.
1918
		 *
1919
		 * @param code Action code for the default operation. Must be an action code from @see org.eclipse.swt.custom.ST.
1920
		 */
1921
		protected PreviousSubWordAction(final int code) {
1922
			super(getSourceViewer().getTextWidget(), code);
1923
		}
1924
1925
		/*
1926
		 * @see org.eclipse.jface.action.IAction#run()
1927
		 */
1928
		public void run() {
1929
			// Check whether sub word navigation is enabled.
1930
			final IPreferenceStore store = getPreferenceStore();
1931
			if (!store.getBoolean(SUB_WORD_NAVIGATION)) {
1932
				super.run();
1933
				return;
1934
			}
1935
1936
			final ISourceViewer viewer = getSourceViewer();
1937
			final IDocument document = viewer.getDocument();
1938
			fIterator.setText((CharacterIterator) new DocumentCharacterIterator(document));
1939
			int position = widgetOffset2ModelOffset(viewer, viewer.getTextWidget().getCaretOffset());
1940
			if (position == -1)
1941
				return;
1942
1943
			int previous = findPreviousPosition(position);
1944
			if (previous != BreakIterator.DONE) {
1945
				setCaretPosition(previous);
1946
				getTextWidget().showSelection();
1947
				fireSelectionChanged();
1948
			}
1949
1950
		}
1951
1952
		/**
1953
		 * Finds the previous position before the given position.
1954
		 *
1955
		 * @param position the current position
1956
		 * @return the previous position
1957
		 */
1958
		protected int findPreviousPosition(int position) {
1959
			ISourceViewer viewer = getSourceViewer();
1960
			int widget = -1;
1961
			while (position != BreakIterator.DONE && widget == -1) { // TODO: optimize
1962
				position = fIterator.preceding(position);
1963
				if (position != BreakIterator.DONE)
1964
					widget = modelOffset2WidgetOffset(viewer, position);
1965
			}
1966
			return position;
1967
		}
1968
1969
		/**
1970
		 * Sets the caret position to the sub-word boundary given with <code>position</code>.
1971
		 *
1972
		 * @param position Position where the action should move the caret
1973
		 */
1974
		protected abstract void setCaretPosition(int position);
1975
	}
1976
1977
	/**
1978
	 * Text navigation action to navigate to the previous sub-word.
1979
	 *
1980
	 * @since 3.0
1981
	 */
1982
	protected class NavigatePreviousSubWordAction extends PreviousSubWordAction {
1983
1984
		/**
1985
		 * Creates a new navigate previous sub-word action.
1986
		 */
1987
		public NavigatePreviousSubWordAction() {
1988
			super(ST.WORD_PREVIOUS);
1989
		}
1990
1991
		/*
1992
		 * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor.PreviousSubWordAction#setCaretPosition(int)
1993
		 */
1994
		protected void setCaretPosition(final int position) {
1995
			getTextWidget().setCaretOffset(modelOffset2WidgetOffset(getSourceViewer(), position));
1996
		}
1997
	}
1998
1999
	/**
2000
	 * Text operation action to delete the previous sub-word.
2001
	 *
2002
	 * @since 3.0
2003
	 */
2004
	protected class DeletePreviousSubWordAction extends PreviousSubWordAction implements IUpdate {
2005
2006
		/**
2007
		 * Creates a new delete previous sub-word action.
2008
		 */
2009
		public DeletePreviousSubWordAction() {
2010
			super(ST.DELETE_WORD_PREVIOUS);
2011
		}
2012
2013
		/*
2014
		 * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor.PreviousSubWordAction#setCaretPosition(int)
2015
		 */
2016
		protected void setCaretPosition(int position) {
2017
			if (!validateEditorInputState())
2018
				return;
2019
2020
			final int length;
2021
			final ISourceViewer viewer = getSourceViewer();
2022
			Point selection = viewer.getSelectedRange();
2023
			if (selection.y != 0) {
2024
				position = selection.x;
2025
				length = selection.y;
2026
			} else {
2027
				length = widgetOffset2ModelOffset(viewer, viewer.getTextWidget().getCaretOffset()) - position;
2028
			}
2029
2030
			try {
2031
				viewer.getDocument().replace(position, length, ""); //$NON-NLS-1$
2032
			} catch (BadLocationException exception) {
2033
				// Should not happen
2034
			}
2035
		}
2036
2037
		/*
2038
		 * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor.PreviousSubWordAction#findPreviousPosition(int)
2039
		 */
2040
		protected int findPreviousPosition(int position) {
2041
			return fIterator.preceding(position);
2042
		}
2043
2044
		/*
2045
		 * @see org.eclipse.ui.texteditor.IUpdate#update()
2046
		 */
2047
		public void update() {
2048
			setEnabled(isEditorInputModifiable());
2049
		}
2050
	}
2051
2052
	/**
2053
	 * Text operation action to select the previous sub-word.
2054
	 *
2055
	 * @since 3.0
2056
	 */
2057
	protected class SelectPreviousSubWordAction extends PreviousSubWordAction {
2058
2059
		/**
2060
		 * Creates a new select previous sub-word action.
2061
		 */
2062
		public SelectPreviousSubWordAction() {
2063
			super(ST.SELECT_WORD_PREVIOUS);
2064
		}
2065
2066
		/*
2067
		 * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor.PreviousSubWordAction#setCaretPosition(int)
2068
		 */
2069
		protected void setCaretPosition(final int position) {
2070
			final ISourceViewer viewer = getSourceViewer();
2071
2072
			final StyledText text = viewer.getTextWidget();
2073
			if (text != null && !text.isDisposed()) {
2074
2075
				final Point selection = text.getSelection();
2076
				final int caret = text.getCaretOffset();
2077
				final int offset = modelOffset2WidgetOffset(viewer, position);
2078
2079
				if (caret == selection.x)
2080
					text.setSelectionRange(selection.y, offset - selection.y);
2081
				else
2082
					text.setSelectionRange(selection.x, offset - selection.x);
2083
			}
2084
		}
2085
	}
1672
}
2086
}
(-)src/org/eclipse/cdt/internal/ui/text/CBreakIterator.java (+449 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *     Sergey Prigogin, Google
11
 *******************************************************************************/
12
package org.eclipse.cdt.internal.ui.text;
13
14
import com.ibm.icu.text.BreakIterator;
15
import java.text.CharacterIterator;
16
17
import org.eclipse.jface.text.Assert;
18
19
20
/**
21
 * A C break iterator. It returns all breaks, including before and after
22
 * whitespace, and it returns all camel case breaks.
23
 * <p>
24
 * A line break may be any of "\n", "\r", "\r\n", "\n\r".
25
 * </p>
26
 *
27
 * @since 3.0
28
 */
29
public class CBreakIterator extends BreakIterator {
30
31
	/**
32
	 * A run of common characters.
33
	 */
34
	protected static abstract class Run {
35
		/** The length of this run. */
36
		protected int length;
37
38
		public Run() {
39
			init();
40
		}
41
42
		/**
43
		 * Returns <code>true</code> if this run consumes <code>ch</code>,
44
		 * <code>false</code> otherwise. If <code>true</code> is returned,
45
		 * the length of the receiver is adjusted accordingly.
46
		 *
47
		 * @param ch the character to test
48
		 * @return <code>true</code> if <code>ch</code> was consumed
49
		 */
50
		protected boolean consume(char ch) {
51
			if (isValid(ch)) {
52
				length++;
53
				return true;
54
			}
55
			return false;
56
		}
57
58
		/**
59
		 * Whether this run accepts that character; does not update state. Called
60
		 * from the default implementation of <code>consume</code>.
61
		 *
62
		 * @param ch the character to test
63
		 * @return <code>true</code> if <code>ch</code> is accepted
64
		 */
65
		protected abstract boolean isValid(char ch);
66
67
		/**
68
		 * Resets this run to the initial state.
69
		 */
70
		protected void init() {
71
			length= 0;
72
		}
73
	}
74
75
	static final class Whitespace extends Run {
76
		protected boolean isValid(char ch) {
77
			return Character.isWhitespace(ch) && ch != '\n' && ch != '\r';
78
		}
79
	}
80
81
	static final class LineDelimiter extends Run {
82
		/** State: INIT -> delimiter -> EXIT. */
83
		private char fState;
84
		private static final char INIT= '\0';
85
		private static final char EXIT= '\1';
86
87
		/*
88
		 * @see org.eclipse.jdt.internal.ui.text.CBreakIterator.Run#init()
89
		 */
90
		protected void init() {
91
			super.init();
92
			fState= INIT;
93
		}
94
95
		/*
96
		 * @see org.eclipse.jdt.internal.ui.text.CBreakIterator.Run#consume(char)
97
		 */
98
		protected boolean consume(char ch) {
99
			if (!isValid(ch) || fState == EXIT)
100
				return false;
101
102
			if (fState == INIT) {
103
				fState= ch;
104
				length++;
105
				return true;
106
			} else if (fState != ch) {
107
				fState= EXIT;
108
				length++;
109
				return true;
110
			} else {
111
				return false;
112
			}
113
		}
114
115
		protected boolean isValid(char ch) {
116
			return ch == '\n' || ch == '\r';
117
		}
118
	}
119
120
	static final class Identifier extends Run {
121
		/*
122
		 * @see org.eclipse.jdt.internal.ui.text.CBreakIterator.Run#isValid(char)
123
		 */
124
		protected boolean isValid(char ch) {
125
			return Character.isJavaIdentifierPart(ch);
126
		}
127
	}
128
129
	static final class CamelCaseIdentifier extends Run {
130
		/* states */
131
		private static final int S_INIT= 0;
132
		private static final int S_LOWER= 1;
133
		private static final int S_ONE_CAP= 2;
134
		private static final int S_ALL_CAPS= 3;
135
		private static final int S_UNDERSCORE= 4;
136
		private static final int S_EXIT= 5;
137
		private static final int S_EXIT_MINUS_ONE= 6;
138
139
		/* character types */
140
		private static final int K_INVALID= 0;
141
		private static final int K_LOWER= 1;
142
		private static final int K_UPPER= 2;
143
		private static final int K_UNDERSCORE= 3;
144
		private static final int K_OTHER= 4;
145
146
		private int fState;
147
148
		private final static int[][] MATRIX= new int[][] {
149
				// K_INVALID, K_LOWER,           K_UPPER,    K_UNDERSCORE, K_OTHER
150
				{  S_EXIT,    S_LOWER,           S_ONE_CAP,  S_UNDERSCORE, S_LOWER }, // S_INIT
151
				{  S_EXIT,    S_LOWER,           S_EXIT,     S_UNDERSCORE, S_LOWER }, // S_LOWER
152
				{  S_EXIT,    S_LOWER,           S_ALL_CAPS, S_UNDERSCORE, S_LOWER }, // S_ONE_CAP
153
				{  S_EXIT,    S_EXIT_MINUS_ONE,  S_ALL_CAPS, S_UNDERSCORE, S_LOWER }, // S_ALL_CAPS
154
				{  S_EXIT,    S_EXIT,            S_EXIT,     S_UNDERSCORE, S_EXIT  }, // S_UNDERSCORE
155
		};
156
157
		/*
158
		 * @see org.eclipse.jdt.internal.ui.text.CBreakIterator.Run#init()
159
		 */
160
		protected void init() {
161
			super.init();
162
			fState= S_INIT;
163
		}
164
165
		/*
166
		 * @see org.eclipse.jdt.internal.ui.text.CBreakIterator.Run#consumes(char)
167
		 */
168
		protected boolean consume(char ch) {
169
			int kind= getKind(ch);
170
			fState= MATRIX[fState][kind];
171
			switch (fState) {
172
				case S_LOWER:
173
				case S_ONE_CAP:
174
				case S_ALL_CAPS:
175
				case S_UNDERSCORE:
176
					length++;
177
					return true;
178
				case S_EXIT:
179
					return false;
180
				case S_EXIT_MINUS_ONE:
181
					length--;
182
					return false;
183
				default:
184
					Assert.isTrue(false);
185
					return false;
186
			}
187
		}
188
189
		/**
190
		 * Determines the kind of a character.
191
		 *
192
		 * @param ch the character to test
193
		 */
194
		private int getKind(char ch) {
195
			if (Character.isUpperCase(ch))
196
				return K_UPPER;
197
			if (Character.isLowerCase(ch))
198
				return K_LOWER;
199
			if (ch == '_')
200
				return K_UNDERSCORE;
201
			if (Character.isJavaIdentifierPart(ch)) // digits...
202
				return K_OTHER;
203
			return K_INVALID;
204
		}
205
206
		/*
207
		 * @see org.eclipse.jdt.internal.ui.text.CBreakIterator.Run#isValid(char)
208
		 */
209
		protected boolean isValid(char ch) {
210
			return Character.isJavaIdentifierPart(ch);
211
		}
212
	}
213
214
	static final class Other extends Run {
215
		/*
216
		 * @see org.eclipse.jdt.internal.ui.text.CBreakIterator.Run#isValid(char)
217
		 */
218
		protected boolean isValid(char ch) {
219
			return !Character.isWhitespace(ch) && !Character.isJavaIdentifierPart(ch);
220
		}
221
	}
222
223
	private static final Run WHITESPACE= new Whitespace();
224
	private static final Run DELIMITER= new LineDelimiter();
225
	private static final Run IDENTIFIER= new Identifier();
226
	private static final Run CAMELCASE= new CamelCaseIdentifier();
227
	private static final Run OTHER= new Other();
228
229
	/** The platform break iterator (word instance) used as a base. */
230
	protected final BreakIterator fIterator;
231
	/** The text we operate on. */
232
	protected CharSequence fText;
233
	/** our current position for the stateful methods. */
234
	private int fIndex;
235
	/** Break on camel case word boundaries */
236
	private boolean fCamelCaseBreakEnabled = true;
237
238
239
	/**
240
	 * Creates a new break iterator.
241
	 */
242
	public CBreakIterator() {
243
		fIterator= BreakIterator.getWordInstance();
244
		fIndex= fIterator.current();
245
	}
246
247
	/*
248
	 * @see java.text.BreakIterator#current()
249
	 */
250
	public int current() {
251
		return fIndex;
252
	}
253
254
	/*
255
	 * @see java.text.BreakIterator#first()
256
	 */
257
	public int first() {
258
		fIndex= fIterator.first();
259
		return fIndex;
260
	}
261
262
	/*
263
	 * @see java.text.BreakIterator#following(int)
264
	 */
265
	public int following(int offset) {
266
		// work around too eager IAEs in standard implementation
267
		if (offset == getText().getEndIndex())
268
			return DONE;
269
270
		int next= fIterator.following(offset);
271
		if (next == DONE)
272
			return DONE;
273
274
		// TODO deal with complex script word boundaries
275
		// Math.min(offset + run.length, next) does not work
276
		// since BreakIterator.getWordInstance considers _ as boundaries
277
		// seems to work fine, however
278
		Run run= consumeRun(offset);
279
		return offset + run.length;
280
281
	}
282
283
	/**
284
	 * Consumes a run of characters at the limits of which we introduce a break.
285
	 * @param offset the offset to start at
286
	 * @return the run that was consumed
287
	 */
288
	private Run consumeRun(int offset) {
289
		// assert offset < length
290
291
		char ch= fText.charAt(offset);
292
		int length= fText.length();
293
		Run run= getRun(ch);
294
		while (run.consume(ch) && offset < length - 1) {
295
			offset++;
296
			ch= fText.charAt(offset);
297
		}
298
299
		return run;
300
	}
301
302
	/**
303
	 * Returns a run based on a character.
304
	 *
305
	 * @param ch the character to test
306
	 * @return the correct character given <code>ch</code>
307
	 */
308
	private Run getRun(char ch) {
309
		Run run;
310
		if (WHITESPACE.isValid(ch))
311
			run= WHITESPACE;
312
		else if (DELIMITER.isValid(ch))
313
			run= DELIMITER;
314
		else if (IDENTIFIER.isValid(ch)) {
315
			if (fCamelCaseBreakEnabled)
316
				run= CAMELCASE;
317
			else
318
				run= IDENTIFIER;
319
		}
320
		else if (OTHER.isValid(ch))
321
			run= OTHER;
322
		else {
323
			Assert.isTrue(false);
324
			return null;
325
		}
326
327
		run.init();
328
		return run;
329
	}
330
331
	/*
332
	 * @see java.text.BreakIterator#getText()
333
	 */
334
	public CharacterIterator getText() {
335
		return fIterator.getText();
336
	}
337
338
	/*
339
	 * @see java.text.BreakIterator#isBoundary(int)
340
	 */
341
	public boolean isBoundary(int offset) {
342
        if (offset == getText().getBeginIndex())
343
            return true;
344
        else
345
            return following(offset - 1) == offset;
346
	}
347
348
	/*
349
	 * @see java.text.BreakIterator#last()
350
	 */
351
	public int last() {
352
		fIndex= fIterator.last();
353
		return fIndex;
354
	}
355
356
	/*
357
	 * @see java.text.BreakIterator#next()
358
	 */
359
	public int next() {
360
		fIndex= following(fIndex);
361
		return fIndex;
362
	}
363
364
	/*
365
	 * @see java.text.BreakIterator#next(int)
366
	 */
367
	public int next(int n) {
368
		return fIterator.next(n);
369
	}
370
371
	/*
372
	 * @see java.text.BreakIterator#preceding(int)
373
	 */
374
	public int preceding(int offset) {
375
		if (offset == getText().getBeginIndex())
376
			return DONE;
377
378
		if (isBoundary(offset - 1))
379
			return offset - 1;
380
381
		int previous= offset - 1;
382
		do {
383
			previous= fIterator.preceding(previous);
384
		} while (!isBoundary(previous));
385
386
		int last= DONE;
387
		while (previous < offset) {
388
			last= previous;
389
			previous= following(previous);
390
		}
391
392
		return last;
393
	}
394
395
	/*
396
	 * @see java.text.BreakIterator#previous()
397
	 */
398
	public int previous() {
399
		fIndex= preceding(fIndex);
400
		return fIndex;
401
	}
402
403
	/*
404
	 * @see java.text.BreakIterator#setText(java.lang.String)
405
	 */
406
	public void setText(String newText) {
407
		setText((CharSequence) newText);
408
	}
409
410
	/**
411
	 * Creates a break iterator given a char sequence.
412
	 * @param newText the new text
413
	 */
414
	public void setText(CharSequence newText) {
415
		fText= newText;
416
		fIterator.setText(new SequenceCharacterIterator(newText));
417
		first();
418
	}
419
420
	/*
421
	 * @see java.text.BreakIterator#setText(java.text.CharacterIterator)
422
	 */
423
	public void setText(CharacterIterator newText) {
424
		if (newText instanceof CharSequence) {
425
			fText= (CharSequence) newText;
426
			fIterator.setText(newText);
427
			first();
428
		} else {
429
			throw new UnsupportedOperationException("CharacterIterator not supported"); //$NON-NLS-1$
430
		}
431
	}
432
433
	/**
434
	 * Enables breaks at word boundaries inside a camel case identifier.
435
	 *  
436
	 * @param enable <code>true</code> to enable, <code>false</code> to disable.
437
	 */
438
	public void setCamelCaseBreakEnabled(boolean camelCaseBreakEnabled) {
439
		fCamelCaseBreakEnabled = camelCaseBreakEnabled;
440
	}
441
442
	/**
443
	 * @return <code>true</code> if breaks at word boundaries inside
444
	 * a camel case identifier are enabled.
445
	 */
446
	public boolean isCamelCaseBreakEnabled() {
447
		return fCamelCaseBreakEnabled;
448
	}
449
}
(-)src/org/eclipse/cdt/internal/ui/text/DocumentCharacterIterator.java (+222 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2005 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.cdt.internal.ui.text;
12
13
import java.text.CharacterIterator;
14
15
import org.eclipse.jface.text.Assert;
16
import org.eclipse.jface.text.BadLocationException;
17
import org.eclipse.jface.text.IDocument;
18
19
20
/**
21
 * An <code>IDocument</code> based implementation of
22
 * <code>CharacterIterator</code> and <code>CharSequence</code>. Note that
23
 * the supplied document is not copied; if the document is modified during the
24
 * lifetime of a <code>DocumentCharacterIterator</code>, the methods
25
 * returning document content may not always return the same values. Also, if
26
 * accessing the document fails with a {@link BadLocationException}, any of
27
 * <code>CharacterIterator</code> methods as well as <code>charAt</code>may
28
 * return {@link CharacterIterator#DONE}.
29
 *
30
 * @since 3.0
31
 */
32
public class DocumentCharacterIterator implements CharacterIterator, CharSequence {
33
34
	private int fIndex= -1;
35
	private final IDocument fDocument;
36
	private final int fFirst;
37
	private final int fLast;
38
39
	private void invariant() {
40
		Assert.isTrue(fIndex >= fFirst);
41
		Assert.isTrue(fIndex <= fLast);
42
	}
43
44
	/**
45
	 * Creates an iterator for the entire document.
46
	 *
47
	 * @param document the document backing this iterator
48
	 */
49
	public DocumentCharacterIterator(IDocument document) {
50
		this(document, 0);
51
	}
52
53
	/**
54
	 * Creates an iterator, starting at offset <code>first</code>.
55
	 *
56
	 * @param document the document backing this iterator
57
	 * @param first the first character to consider
58
	 * @throws IllegalArgumentException if the indices are out of bounds
59
	 */
60
	public DocumentCharacterIterator(IDocument document, int first) throws IllegalArgumentException {
61
		this(document, first, document.getLength());
62
	}
63
64
	/**
65
	 * Creates an iterator for the document contents from <code>first</code>
66
	 * (inclusive) to <code>last</code> (exclusive).
67
	 *
68
	 * @param document the document backing this iterator
69
	 * @param first the first character to consider
70
	 * @param last the last character index to consider
71
	 * @throws IllegalArgumentException if the indices are out of bounds
72
	 */
73
	public DocumentCharacterIterator(IDocument document, int first, int last) throws IllegalArgumentException {
74
		if (document == null)
75
			throw new NullPointerException();
76
		if (first < 0 || first > last)
77
			throw new IllegalArgumentException();
78
		if (last > document.getLength())
79
			throw new IllegalArgumentException();
80
		fDocument= document;
81
		fFirst= first;
82
		fLast= last;
83
		fIndex= first;
84
		invariant();
85
	}
86
87
	/*
88
	 * @see java.text.CharacterIterator#first()
89
	 */
90
	public char first() {
91
		return setIndex(getBeginIndex());
92
	}
93
94
	/*
95
	 * @see java.text.CharacterIterator#last()
96
	 */
97
	public char last() {
98
		if (fFirst == fLast)
99
			return setIndex(getEndIndex());
100
		else
101
			return setIndex(getEndIndex() - 1);
102
	}
103
104
	/*
105
	 * @see java.text.CharacterIterator#current()
106
	 */
107
	public char current() {
108
		if (fIndex >= fFirst && fIndex < fLast)
109
			try {
110
				return fDocument.getChar(fIndex);
111
			} catch (BadLocationException e) {
112
				// ignore
113
			}
114
		return DONE;
115
	}
116
117
	/*
118
	 * @see java.text.CharacterIterator#next()
119
	 */
120
	public char next() {
121
		return setIndex(Math.min(fIndex + 1, getEndIndex()));
122
	}
123
124
	/*
125
	 * @see java.text.CharacterIterator#previous()
126
	 */
127
	public char previous() {
128
		if (fIndex > getBeginIndex()) {
129
			return setIndex(fIndex - 1);
130
		} else {
131
			return DONE;
132
		}
133
	}
134
135
	/*
136
	 * @see java.text.CharacterIterator#setIndex(int)
137
	 */
138
	public char setIndex(int position) {
139
		if (position >= getBeginIndex() && position <= getEndIndex())
140
			fIndex= position;
141
		else
142
			throw new IllegalArgumentException();
143
144
		invariant();
145
		return current();
146
	}
147
148
	/*
149
	 * @see java.text.CharacterIterator#getBeginIndex()
150
	 */
151
	public int getBeginIndex() {
152
		return fFirst;
153
	}
154
155
	/*
156
	 * @see java.text.CharacterIterator#getEndIndex()
157
	 */
158
	public int getEndIndex() {
159
		return fLast;
160
	}
161
162
	/*
163
	 * @see java.text.CharacterIterator#getIndex()
164
	 */
165
	public int getIndex() {
166
		return fIndex;
167
	}
168
169
	/*
170
	 * @see java.text.CharacterIterator#clone()
171
	 */
172
	public Object clone() {
173
		try {
174
			return super.clone();
175
		} catch (CloneNotSupportedException e) {
176
			throw new InternalError();
177
		}
178
	}
179
180
	/*
181
	 * @see java.lang.CharSequence#length()
182
	 */
183
	public int length() {
184
		return getEndIndex() - getBeginIndex();
185
	}
186
187
	/**
188
	 * {@inheritDoc}
189
	 * <p>
190
	 * Note that, if the document is modified concurrently, this method may
191
	 * return {@link CharacterIterator#DONE} if a {@link BadLocationException}
192
	 * was thrown when accessing the backing document.
193
	 * </p>
194
	 *
195
	 * @param index {@inheritDoc}
196
	 * @return {@inheritDoc}
197
	 */
198
	public char charAt(int index) {
199
		if (index >= 0 && index < length())
200
			try {
201
				return fDocument.getChar(getBeginIndex() + index);
202
			} catch (BadLocationException e) {
203
				// ignore and return DONE
204
				return DONE;
205
			}
206
		else
207
			throw new IndexOutOfBoundsException();
208
	}
209
210
	/*
211
	 * @see java.lang.CharSequence#subSequence(int, int)
212
	 */
213
	public CharSequence subSequence(int start, int end) {
214
		if (start < 0)
215
			throw new IndexOutOfBoundsException();
216
		if (end < start)
217
			throw new IndexOutOfBoundsException();
218
		if (end > length())
219
			throw new IndexOutOfBoundsException();
220
		return new DocumentCharacterIterator(fDocument, getBeginIndex() + start, getBeginIndex() + end);
221
	}
222
}
(-)src/org/eclipse/cdt/internal/ui/text/CWordIterator.java (+239 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *     Sergey Prigogin, Google
11
 *******************************************************************************/
12
package org.eclipse.cdt.internal.ui.text;
13
14
import com.ibm.icu.text.BreakIterator;
15
import java.text.CharacterIterator;
16
17
import org.eclipse.jface.text.Assert;
18
19
20
/**
21
 * Breaks C text into word starts, also stops at line start and end. No
22
 * direction dependency.
23
 *
24
 * @since 3.0
25
 */
26
public class CWordIterator extends BreakIterator {
27
28
	/**
29
	 * The underlying java break iterator. It returns all breaks, including
30
	 * before and after every whitespace.
31
	 */
32
	private CBreakIterator fIterator;
33
	/** The current index for the stateful operations. */
34
	private int fIndex;
35
36
	/**
37
	 * Creates a new word iterator.
38
	 */
39
	public CWordIterator() {
40
		fIterator= new CBreakIterator();
41
		first();
42
	}
43
44
	/*
45
	 * @see java.text.BreakIterator#first()
46
	 */
47
	public int first() {
48
		fIndex= fIterator.first();
49
		return fIndex;
50
	}
51
52
	/*
53
	 * @see java.text.BreakIterator#last()
54
	 */
55
	public int last() {
56
		fIndex= fIterator.last();
57
		return fIndex;
58
	}
59
60
	/*
61
	 * @see java.text.BreakIterator#next(int)
62
	 */
63
	public int next(int n) {
64
		int next= 0;
65
		while (--n > 0 && next != DONE) {
66
			next= next();
67
		}
68
		return next;
69
	}
70
71
	/*
72
	 * @see java.text.BreakIterator#next()
73
	 */
74
	public int next() {
75
		fIndex= following(fIndex);
76
		return fIndex;
77
	}
78
79
	/*
80
	 * @see java.text.BreakIterator#previous()
81
	 */
82
	public int previous() {
83
		fIndex= preceding(fIndex);
84
		return fIndex;
85
	}
86
87
88
	/*
89
	 * @see java.text.BreakIterator#preceding(int)
90
	 */
91
	public int preceding(int offset) {
92
		int first= fIterator.preceding(offset);
93
		if (isWhitespace(first, offset)) {
94
			int second= fIterator.preceding(first);
95
			if (second != DONE && !isDelimiter(second, first))
96
				return second;
97
		}
98
		return first;
99
	}
100
101
	/*
102
	 * @see java.text.BreakIterator#following(int)
103
	 */
104
	public int following(int offset) {
105
		int first= fIterator.following(offset);
106
		if (eatFollowingWhitespace(offset, first)) {
107
			int second= fIterator.following(first);
108
			if (isWhitespace(first, second))
109
				return second;
110
		}
111
		return first;
112
	}
113
114
	private boolean eatFollowingWhitespace(int offset, int exclusiveEnd) {
115
		if (exclusiveEnd == DONE || offset == DONE)
116
			return false;
117
118
		if (isWhitespace(offset, exclusiveEnd))
119
			return false;
120
		if (isDelimiter(offset, exclusiveEnd))
121
			return false;
122
123
		return true;
124
	}
125
126
	/**
127
	 * Returns <code>true</code> if the given sequence into the underlying text
128
	 * represents a delimiter, <code>false</code> otherwise.
129
	 *
130
	 * @param offset the offset
131
	 * @param exclusiveEnd the end offset
132
	 * @return <code>true</code> if the given range is a delimiter
133
	 */
134
	private boolean isDelimiter(int offset, int exclusiveEnd) {
135
		if (exclusiveEnd == DONE || offset == DONE)
136
			return false;
137
138
		Assert.isTrue(offset >= 0);
139
		Assert.isTrue(exclusiveEnd <= getText().getEndIndex());
140
		Assert.isTrue(exclusiveEnd > offset);
141
142
		CharSequence seq= fIterator.fText;
143
144
		while (offset < exclusiveEnd) {
145
			char ch= seq.charAt(offset);
146
			if (ch != '\n' && ch != '\r')
147
				return false;
148
			offset++;
149
		}
150
151
		return true;
152
	}
153
154
	/**
155
	 * Returns <code>true</code> if the given sequence into the underlying text
156
	 * represents whitespace, but not a delimiter, <code>false</code> otherwise.
157
	 *
158
	 * @param offset the offset
159
	 * @param exclusiveEnd the end offset
160
	 * @return <code>true</code> if the given range is whitespace
161
	 */
162
	private boolean isWhitespace(int offset, int exclusiveEnd) {
163
		if (exclusiveEnd == DONE || offset == DONE)
164
			return false;
165
166
		Assert.isTrue(offset >= 0);
167
		Assert.isTrue(exclusiveEnd <= getText().getEndIndex());
168
		Assert.isTrue(exclusiveEnd > offset);
169
170
		CharSequence seq= fIterator.fText;
171
172
		while (offset < exclusiveEnd) {
173
			char ch= seq.charAt(offset);
174
			if (!Character.isWhitespace(ch))
175
				return false;
176
			if (ch == '\n' || ch == '\r')
177
				return false;
178
			offset++;
179
		}
180
181
		return true;
182
	}
183
184
	/*
185
	 * @see java.text.BreakIterator#current()
186
	 */
187
	public int current() {
188
		return fIndex;
189
	}
190
191
	/*
192
	 * @see java.text.BreakIterator#getText()
193
	 */
194
	public CharacterIterator getText() {
195
		return fIterator.getText();
196
	}
197
198
	/**
199
	 * Sets the text as <code>CharSequence</code>.
200
	 * @param newText the new text
201
	 */
202
	public void setText(CharSequence newText) {
203
		fIterator.setText(newText);
204
		first();
205
	}
206
207
	/*
208
	 * @see java.text.BreakIterator#setText(java.text.CharacterIterator)
209
	 */
210
	public void setText(CharacterIterator newText) {
211
		fIterator.setText(newText);
212
		first();
213
	}
214
215
	/*
216
	 * @see java.text.BreakIterator#setText(java.lang.String)
217
	 */
218
	public void setText(String newText) {
219
		setText((CharSequence) newText);
220
	}
221
222
	/**
223
	 * Enables breaks at word boundaries inside a camel case identifier.
224
	 *  
225
	 * @param camelCaseBreakEnabled <code>true</code> to enable,
226
	 * <code>false</code> to disable.
227
	 */
228
	public void setCamelCaseBreakEnabled(boolean camelCaseBreakEnabled) {
229
		fIterator.setCamelCaseBreakEnabled(camelCaseBreakEnabled);
230
	}
231
232
	/**
233
	 * @return <code>true</code> if breaks at word boundaries inside
234
	 * a camel case identifier are enabled.
235
	 */
236
	public boolean isCamelCaseBreakEnabled() {
237
		return fIterator.isCamelCaseBreakEnabled();
238
	}
239
}
(-)src/org/eclipse/cdt/internal/ui/text/SequenceCharacterIterator.java (+166 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2005 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.cdt.internal.ui.text;
12
13
import java.text.CharacterIterator;
14
15
import org.eclipse.jface.text.Assert;
16
17
18
/**
19
 * A <code>CharSequence</code> based implementation of <code>CharacterIterator</code>.
20
 *
21
 * @since 3.0
22
 */
23
public class SequenceCharacterIterator implements CharacterIterator {
24
25
	private int fIndex= -1;
26
	private final CharSequence fSequence;
27
	private final int fFirst;
28
	private final int fLast;
29
30
	private void invariant() {
31
		Assert.isTrue(fIndex >= fFirst);
32
		Assert.isTrue(fIndex <= fLast);
33
	}
34
35
	/**
36
	 * Creates an iterator for the entire sequence.
37
	 *
38
	 * @param sequence the sequence backing this iterator
39
	 */
40
	public SequenceCharacterIterator(CharSequence sequence) {
41
		this(sequence, 0);
42
	}
43
44
	/**
45
	 * Creates an iterator.
46
	 *
47
	 * @param sequence the sequence backing this iterator
48
	 * @param first the first character to consider
49
	 * @throws IllegalArgumentException if the indices are out of bounds
50
	 */
51
	public SequenceCharacterIterator(CharSequence sequence, int first) throws IllegalArgumentException {
52
		this(sequence, first, sequence.length());
53
	}
54
55
	/**
56
	 * Creates an iterator.
57
	 *
58
	 * @param sequence the sequence backing this iterator
59
	 * @param first the first character to consider
60
	 * @param last the last character index to consider
61
	 * @throws IllegalArgumentException if the indices are out of bounds
62
	 */
63
	public SequenceCharacterIterator(CharSequence sequence, int first, int last) throws IllegalArgumentException {
64
		if (sequence == null)
65
			throw new NullPointerException();
66
		if (first < 0 || first > last)
67
			throw new IllegalArgumentException();
68
		if (last > sequence.length())
69
			throw new IllegalArgumentException();
70
		fSequence= sequence;
71
		fFirst= first;
72
		fLast= last;
73
		fIndex= first;
74
		invariant();
75
	}
76
77
	/*
78
	 * @see java.text.CharacterIterator#first()
79
	 */
80
	public char first() {
81
		return setIndex(getBeginIndex());
82
	}
83
84
	/*
85
	 * @see java.text.CharacterIterator#last()
86
	 */
87
	public char last() {
88
		if (fFirst == fLast)
89
			return setIndex(getEndIndex());
90
		else
91
			return setIndex(getEndIndex() - 1);
92
	}
93
94
	/*
95
	 * @see java.text.CharacterIterator#current()
96
	 */
97
	public char current() {
98
		if (fIndex >= fFirst && fIndex < fLast)
99
			return fSequence.charAt(fIndex);
100
		else
101
			return DONE;
102
	}
103
104
	/*
105
	 * @see java.text.CharacterIterator#next()
106
	 */
107
	public char next() {
108
		return setIndex(Math.min(fIndex + 1, getEndIndex()));
109
	}
110
111
	/*
112
	 * @see java.text.CharacterIterator#previous()
113
	 */
114
	public char previous() {
115
		if (fIndex > getBeginIndex()) {
116
			return setIndex(fIndex - 1);
117
		} else {
118
			return DONE;
119
		}
120
	}
121
122
	/*
123
	 * @see java.text.CharacterIterator#setIndex(int)
124
	 */
125
	public char setIndex(int position) {
126
		if (position >= getBeginIndex() && position <= getEndIndex())
127
			fIndex= position;
128
		else
129
			throw new IllegalArgumentException();
130
131
		invariant();
132
		return current();
133
	}
134
135
	/*
136
	 * @see java.text.CharacterIterator#getBeginIndex()
137
	 */
138
	public int getBeginIndex() {
139
		return fFirst;
140
	}
141
142
	/*
143
	 * @see java.text.CharacterIterator#getEndIndex()
144
	 */
145
	public int getEndIndex() {
146
		return fLast;
147
	}
148
149
	/*
150
	 * @see java.text.CharacterIterator#getIndex()
151
	 */
152
	public int getIndex() {
153
		return fIndex;
154
	}
155
156
	/*
157
	 * @see java.text.CharacterIterator#clone()
158
	 */
159
	public Object clone() {
160
		try {
161
			return super.clone();
162
		} catch (CloneNotSupportedException e) {
163
			throw new InternalError();
164
		}
165
	}
166
}
(-)ui/org/eclipse/cdt/ui/tests/AutomatedSuite.java (+6 lines)
Lines 15-20 Link Here
15
import junit.framework.TestSuite;
15
import junit.framework.TestSuite;
16
16
17
import org.eclipse.cdt.ui.tests.text.CAutoIndentTest;
17
import org.eclipse.cdt.ui.tests.text.CAutoIndentTest;
18
import org.eclipse.cdt.ui.tests.text.CBreakIteratorTest;
19
import org.eclipse.cdt.ui.tests.text.CWordIteratorTest;
18
import org.eclipse.cdt.ui.tests.text.NumberRuleTest;
20
import org.eclipse.cdt.ui.tests.text.NumberRuleTest;
19
import org.eclipse.cdt.ui.tests.text.contentassist.CompletionFailedTest_MemberReference_Arrow_Prefix2;
21
import org.eclipse.cdt.ui.tests.text.contentassist.CompletionFailedTest_MemberReference_Arrow_Prefix2;
20
import org.eclipse.cdt.ui.tests.text.contentassist.CompletionTest_ArgumentType_NoPrefix;
22
import org.eclipse.cdt.ui.tests.text.contentassist.CompletionTest_ArgumentType_NoPrefix;
Lines 136-141 Link Here
136
		addTest( CSelectionTestsDOMIndexer.suite() );
138
		addTest( CSelectionTestsDOMIndexer.suite() );
137
		addTest( CPPSelectionTestsCTagsIndexer.suite() );
139
		addTest( CPPSelectionTestsCTagsIndexer.suite() );
138
		addTest( CSelectionTestsCTagsIndexer.suite() );
140
		addTest( CSelectionTestsCTagsIndexer.suite() );
141
142
		// Break iterator tests.
143
		addTest(CBreakIteratorTest.suite());
144
		addTest(CWordIteratorTest.suite());
139
	}
145
	}
140
	
146
	
141
}
147
}
(-)META-INF/MANIFEST.MF (-1 / +2 lines)
Lines 32-37 Link Here
32
 org.eclipse.compare,
32
 org.eclipse.compare,
33
 org.eclipse.ui.console,
33
 org.eclipse.ui.console,
34
 org.eclipse.core.expressions,
34
 org.eclipse.core.expressions,
35
 org.eclipse.cdt.make.core
35
 org.eclipse.cdt.make.core,
36
 com.ibm.icu
36
Eclipse-LazyStart: true
37
Eclipse-LazyStart: true
37
Bundle-Vendor: Eclipse.org
38
Bundle-Vendor: Eclipse.org
(-)ui/org/eclipse/cdt/ui/tests/text/CBreakIteratorTest.java (+122 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2005 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *     Sergey Prigogin, Google
11
 *******************************************************************************/
12
package org.eclipse.cdt.ui.tests.text;
13
14
import junit.framework.Test;
15
import junit.framework.TestSuite;
16
17
import org.eclipse.cdt.internal.ui.text.CBreakIterator;
18
19
20
public class CBreakIteratorTest extends BreakIteratorTest {
21
22
	public static Test suite() {
23
		return new TestSuite(CBreakIteratorTest.class);
24
	}
25
26
	/*
27
	 * @see junit.framework.TestCase#setUp()
28
	 */
29
	protected void setUp() throws Exception {
30
		fBreakIterator= new CBreakIterator();
31
	}
32
	
33
	public void testNext1() {
34
		assertNextPositions("word word", new int[] { 4, 5, 9 });
35
	}
36
	
37
	public void testNext2() {
38
		assertNextPositions("wordWord word", new int[] { 4, 8, 9, 13 });
39
	}
40
	
41
	public void testNextSpace() {
42
		assertNextPositions(" word ", new int[] { 1, 5, 6 });
43
	}
44
	
45
	public void testNextParen() {
46
		assertNextPositions("word(params)", new int[] { 4, 5, 11, 12 });
47
	}
48
	
49
	public void testNextLn() {
50
		String s= new String("word \n" +
51
				"  word2");
52
		assertNextPositions(s, new int[] { 4, 5, 6, 8, 13 });
53
	}
54
55
	public void testMultiNextLn() {
56
		String s= new String("word \n" +
57
				"\n" +
58
				"\n" +
59
				"  word2");
60
		assertNextPositions(s, new int[] { 4, 5, 6, 7, 8, 10, 15 });
61
	}
62
63
	public void testMultiNextLn2() {
64
		String s= new String("word \r\n" +
65
				"\r\n" +
66
				"\r\n" +
67
				"  word2");
68
		assertNextPositions(s, new int[] { 4, 5, 7, 9, 11, 13, 18 });
69
	}
70
71
	public void testNextCamelCaseWord() {
72
		String s= new String("   _isURLConnection_pool   ");
73
		assertNextPositions(s, new int[] { 3, 4, 6, 9, 20, 24, 27 });
74
	}
75
	
76
	public void testPrevious1() {
77
		String s= new String("word word");
78
		assertPreviousPositions(s, new int[] { 0, 4, 5 });
79
	}
80
	
81
	public void testPrevious2() {
82
		String s= new String("wordWord word");
83
		assertPreviousPositions(s, new int[] { 0, 4, 8, 9 });
84
	}
85
	
86
	public void testPreviousSpace() {
87
		String s= new String(" word ");
88
		assertPreviousPositions(s, new int[] { 1, 5 });
89
	}
90
	
91
	public void testPreviousParen() {
92
		String s= new String("word(params)");
93
		assertPreviousPositions(s, new int[] { 0, 4, 5, 11 });
94
	}
95
	
96
	public void testPreviousLn() {
97
		String s= new String("word \n" +
98
				"  word2");
99
		assertPreviousPositions(s, new int[] { 0, 4, 5, 6, 8 });
100
	}
101
	
102
	public void testMultiPreviousLn() {
103
		String s= new String("word \n" +
104
				"\n" +
105
				"\n" +
106
				"  word2");
107
		assertPreviousPositions(s, new int[] { 0, 4, 5, 6, 7, 8, 10 });
108
	}
109
110
	public void testMultiPreviousLn2() {
111
		String s= new String("word \r\n" +
112
				"\r\n" +
113
				"\r\n" +
114
				"  word2");
115
		assertPreviousPositions(s, new int[] { 0, 4, 5, 7, 9, 11, 13 });
116
	}
117
118
	public void testPreviousCamelCaseWord() {
119
		String s= new String("   _isURLConnection_pool   ");
120
		assertPreviousPositions(s, new int[] { 0, 3, 4, 6, 9, 20, 24 });
121
	}
122
}
(-)ui/org/eclipse/cdt/ui/tests/text/BreakIteratorTest.java (+88 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *     Sergey Prigogin, Google
11
 *******************************************************************************/
12
package org.eclipse.cdt.ui.tests.text;
13
14
import com.ibm.icu.text.BreakIterator;
15
16
import junit.framework.TestCase;
17
18
19
public class BreakIteratorTest extends TestCase {
20
21
	protected BreakIterator fBreakIterator;
22
23
	public void assertNextPositions(CharSequence ci, int position) {
24
		assertNextPositions(ci, new int[] {position});
25
	}
26
27
	public void assertNextPositions(CharSequence ci, int[] positions) {
28
		fBreakIterator.setText(ci.toString());
29
		
30
		// test next()
31
		for (int i = 0; i < positions.length; i++) {
32
			int pos= fBreakIterator.next(); 
33
			assertEquals(positions[i], pos);
34
		}
35
		
36
		// test following()
37
		int idx= 0;
38
		for (int i = 0; i < positions.length; i++) {
39
			int position= positions[i];
40
			while (idx < position) {
41
				if (!illegalPos(ci, idx))
42
					assertEquals(position, fBreakIterator.following(idx));
43
				idx++;
44
			}
45
		}
46
		
47
	}
48
49
	/**
50
	 * Check if we are in a multibyte delimiter
51
	 * @param idx
52
	 * @return
53
	 */
54
	private boolean illegalPos(CharSequence seq, int idx) {
55
		String DELIMS= "\n\r";
56
		if (idx == 0 || idx == seq.length())
57
			return false;
58
		char one= seq.charAt(idx - 1);
59
		char two= seq.charAt(idx);
60
		return one != two && DELIMS.indexOf(one) != -1 && DELIMS.indexOf(two) != -1;
61
	}
62
63
	public void assertPreviousPositions(CharSequence ci, int position) {
64
		assertPreviousPositions(ci, new int[] {position});
65
	}
66
67
	public void assertPreviousPositions(CharSequence ci, int[] positions) {
68
		fBreakIterator.setText(ci.toString());
69
		fBreakIterator.last();
70
		
71
		for (int i = positions.length - 1; i >= 0; i--) {
72
			int pos= fBreakIterator.previous(); 
73
			assertEquals(positions[i], pos);
74
		}
75
	
76
		// test preceding()
77
		int idx= ci.length();
78
		for (int i = positions.length - 1; i >= 0; i--) {
79
			int position= positions[i];
80
			while (idx > position) {
81
				if (!illegalPos(ci, idx))
82
					assertEquals(position, fBreakIterator.preceding(idx));
83
				idx--;
84
			}
85
		}
86
	}
87
88
}
(-)ui/org/eclipse/cdt/ui/tests/text/CWordIteratorTest.java (+123 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2005 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *     Sergey Prigogin, Google
11
******************************************************************************/
12
package org.eclipse.cdt.ui.tests.text;
13
14
import junit.framework.Test;
15
import junit.framework.TestSuite;
16
17
import org.eclipse.cdt.internal.ui.text.CWordIterator;
18
19
20
public class CWordIteratorTest extends BreakIteratorTest {
21
22
	public static Test suite() {
23
		return new TestSuite(CBreakIteratorTest.class);
24
	}
25
26
	/*
27
	 * @see junit.framework.TestCase#setUp()
28
	 */
29
	protected void setUp() throws Exception {
30
		fBreakIterator= new CWordIterator();
31
	}
32
	
33
	public void testNext1() {
34
		assertNextPositions("word word", new int[] { 5, 9 });
35
	}
36
	
37
	public void testNext2() {
38
		assertNextPositions("wordWord word", new int[] { 4, 9, 13 });
39
	}
40
	
41
	public void testNextSpace() {
42
		assertNextPositions(" word ", new int[] { 1, 6 });
43
	}
44
	
45
	public void testNextParen() {
46
		assertNextPositions("word(params)", new int[] { 4, 5, 11, 12 });
47
	}
48
	
49
	public void testNextLn() {
50
		String s= new String("word \n" +
51
				"  word2");
52
		assertNextPositions(s, new int[] { 5, 6, 8, 13 });
53
	}
54
	
55
	public void testMultiNextLn() {
56
		String s= new String("word \n" +
57
				"\n" +
58
				"\n" +
59
				"  word2");
60
		assertNextPositions(s, new int[] { 5, 6, 7, 8, 10, 15 });
61
	}
62
	
63
	public void testMultiNextLn2() {
64
		String s= new String("word \r\n" +
65
				"\r\n" +
66
				"\r\n" +
67
				"  word2");
68
		assertNextPositions(s, new int[] { 5, 7, 9, 11, 13, 18 });
69
	}
70
71
	public void testNextCamelCaseWord() {
72
		String s= new String("   _isURLConnection_pool   ");
73
		assertNextPositions(s, new int[] { 3, 4, 6, 9, 20, 27 });
74
	}
75
	
76
	public void testPrevious1() {
77
		String s= new String("word word");
78
		assertPreviousPositions(s, new int[] { 0, 5 });
79
	}
80
	
81
	public void testPrevious2() {
82
		String s= new String("wordWord word");
83
		assertPreviousPositions(s, new int[] { 0, 4, 9 });
84
	}
85
	
86
	public void testPreviousSpace() {
87
		String s= new String(" word ");
88
		assertPreviousPositions(s, new int[] { 1 });
89
	}
90
	
91
	public void testPreviousParen() {
92
		String s= new String("word(params)");
93
		assertPreviousPositions(s, new int[] { 0, 4, 5, 11 });
94
	}
95
	
96
	public void testPreviousLn() {
97
		String s= new String("word \n" +
98
				"  word2");
99
		assertPreviousPositions(s, new int[] { 0, 5, 6, 8 });
100
	}
101
	
102
	public void testMultiPreviousLn() {
103
		String s= new String("word \n" +
104
				"\n" +
105
				"\n" +
106
				"  word2");
107
		assertPreviousPositions(s, new int[] { 0, 5, 6, 7, 8, 10 });
108
	}
109
	
110
	public void testMultiPreviousLn2() {
111
		String s= new String("word \r\n" +
112
				"\r\n" +
113
				"\r\n" +
114
				"  word2");
115
		assertPreviousPositions(s, new int[] { 0, 5, 7, 9, 11, 13 });
116
	}
117
118
	public void testPreviousCamelCaseWord() {
119
		String s= new String("   _isURLConnection_pool   ");
120
		assertPreviousPositions(s, new int[] { 0, 3, 4, 6, 9, 20 });
121
	}
122
123
}

Return to bug 140489