Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 46330 Details for
Bug 140489
Support "smart caret positioning" similar to Java
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
[patch]
Implementation of "smart caret positioning" for C files. Added junit tests and merged with HEAD.
patch_smart_caret_positioning.txt (text/plain), 60.10 KB, created by
Sergey Prigogin
on 2006-07-15 01:31:39 EDT
(
hide
)
Description:
Implementation of "smart caret positioning" for C files. Added junit tests and merged with HEAD.
Filename:
MIME Type:
Creator:
Sergey Prigogin
Created:
2006-07-15 01:31:39 EDT
Size:
60.10 KB
patch
obsolete
>### Eclipse Workspace Patch 1.0 >#P org.eclipse.cdt.ui >Index: META-INF/MANIFEST.MF >=================================================================== >RCS file: /home/tools/org.eclipse.cdt-core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF,v >retrieving revision 1.10 >diff -u -r1.10 MANIFEST.MF >--- META-INF/MANIFEST.MF 5 Jul 2006 14:23:52 -0000 1.10 >+++ META-INF/MANIFEST.MF 15 Jul 2006 05:33:46 -0000 >@@ -69,6 +69,7 @@ > org.eclipse.help, > org.eclipse.ui.navigator, > org.eclipse.core.expressions, >- org.eclipse.ui.navigator.resources >+ org.eclipse.ui.navigator.resources, >+ com.ibm.icu > Eclipse-LazyStart: true > Bundle-RequiredExecutionEnvironment: J2SE-1.4 >Index: src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties >=================================================================== >RCS file: /home/tools/org.eclipse.cdt-core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties,v >retrieving revision 1.44 >diff -u -r1.44 PreferencesMessages.properties >--- src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties 14 Jul 2006 13:21:46 -0000 1.44 >+++ src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties 15 Jul 2006 05:33:46 -0000 >@@ -108,6 +108,7 @@ > CEditorPreferencePage.colorPage.preview=Preview: > CEditorPreferencePage.behaviorPage.tabSpace=&Insert space for tabs > CEditorPreferencePage.behaviorPage.matchingBrackets=Highlight &matching brackets >+CEditorPreferencePage.behaviorPage.subWordNavigation=Smart &caret positioning in identifiers > CEditorPreferencePage.behaviorPage.inactiveCode=Highlight &inactive code > CEditorPreferencePage.behaviorPage.appearanceColorOptions=Appearance color options: > CEditorPreferencePage.behaviorPage.matchingBracketColor=Matching brackets highlight >Index: src/org/eclipse/cdt/internal/ui/preferences/CEditorPreferencePage.java >=================================================================== >RCS file: /home/tools/org.eclipse.cdt-core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CEditorPreferencePage.java,v >retrieving revision 1.56 >diff -u -r1.56 CEditorPreferencePage.java >--- src/org/eclipse/cdt/internal/ui/preferences/CEditorPreferencePage.java 14 Jul 2006 13:21:46 -0000 1.56 >+++ src/org/eclipse/cdt/internal/ui/preferences/CEditorPreferencePage.java 15 Jul 2006 05:33:46 -0000 >@@ -118,6 +118,7 @@ > overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ICColorConstants.C_NUMBER + "_bold")); //$NON-NLS-1$ > overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ICColorConstants.C_OPERATOR)); > overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, ICColorConstants.C_OPERATOR + "_bold")); //$NON-NLS-1$ >+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, CEditor.SUB_WORD_NAVIGATION)); > overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, CEditor.MATCHING_BRACKETS_COLOR)); > overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, CEditor.MATCHING_BRACKETS)); > overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, CEditor.INACTIVE_CODE_COLOR)); >@@ -147,6 +148,8 @@ > // JDT also enables this feature. > store.setDefault(AbstractTextEditor.PREFERENCE_NAVIGATION_SMART_HOME_END, true); > >+ store.setDefault(CEditor.SUB_WORD_NAVIGATION, true); >+ > store.setDefault(CEditor.MATCHING_BRACKETS, true); > PreferenceConverter.setDefault(store, CEditor.MATCHING_BRACKETS_COLOR, new RGB(170,170,170)); > >@@ -336,7 +339,10 @@ > layout.numColumns = 2; > behaviorComposite.setLayout(layout); > >- String label = PreferencesMessages.getString("CEditorPreferencePage.behaviorPage.matchingBrackets"); //$NON-NLS-1$ >+ String label= PreferencesMessages.getString("CEditorPreferencePage.behaviorPage.subWordNavigation"); //$NON-NLS-1$; >+ addCheckBox(behaviorComposite, label, CEditor.SUB_WORD_NAVIGATION, 0); >+ >+ label = PreferencesMessages.getString("CEditorPreferencePage.behaviorPage.matchingBrackets"); //$NON-NLS-1$ > addCheckBox(behaviorComposite, label, CEditor.MATCHING_BRACKETS, 0); > > label = PreferencesMessages.getString("CEditorPreferencePage.behaviorPage.inactiveCode"); //$NON-NLS-1$ >Index: src/org/eclipse/cdt/internal/ui/editor/CEditor.java >=================================================================== >RCS file: /home/tools/org.eclipse.cdt-core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java,v >retrieving revision 1.105 >diff -u -r1.105 CEditor.java >--- src/org/eclipse/cdt/internal/ui/editor/CEditor.java 14 Jul 2006 13:21:46 -0000 1.105 >+++ src/org/eclipse/cdt/internal/ui/editor/CEditor.java 15 Jul 2006 05:33:46 -0000 >@@ -10,10 +10,12 @@ > * QNX Software System > * Anton Leherbauer (Wind River Systems) > * Markus Schorn (Wind River Systems) >+ * Sergey Prigogin, Google > *******************************************************************************/ > package org.eclipse.cdt.internal.ui.editor; > > >+import java.text.CharacterIterator; > import java.util.Iterator; > import java.util.ResourceBundle; > >@@ -21,6 +23,7 @@ > import org.eclipse.core.runtime.CoreException; > import org.eclipse.core.runtime.content.IContentType; > import org.eclipse.jface.action.Action; >+import org.eclipse.jface.action.IAction; > import org.eclipse.jface.action.IMenuManager; > import org.eclipse.jface.action.IStatusLineManager; > import org.eclipse.jface.preference.IPreferenceStore; >@@ -72,6 +75,7 @@ > import org.eclipse.jface.viewers.SelectionChangedEvent; > import org.eclipse.search.ui.actions.TextSearchGroup; > import org.eclipse.swt.SWT; >+import org.eclipse.swt.custom.ST; > import org.eclipse.swt.custom.StyledText; > import org.eclipse.swt.dnd.DND; > import org.eclipse.swt.dnd.DragSource; >@@ -104,12 +108,16 @@ > import org.eclipse.ui.texteditor.ITextEditorActionConstants; > import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; > import org.eclipse.ui.texteditor.ITextEditorDropTargetListener; >+import org.eclipse.ui.texteditor.IUpdate; > import org.eclipse.ui.texteditor.ResourceAction; > import org.eclipse.ui.texteditor.SourceViewerDecorationSupport; > import org.eclipse.ui.texteditor.TextEditorAction; >+import org.eclipse.ui.texteditor.TextNavigationAction; > import org.eclipse.ui.texteditor.TextOperationAction; > import org.eclipse.ui.views.contentoutline.IContentOutlinePage; > >+import com.ibm.icu.text.BreakIterator; >+ > import org.eclipse.cdt.core.CCorePlugin; > import org.eclipse.cdt.core.CCorePreferenceConstants; > import org.eclipse.cdt.core.model.CModelException; >@@ -138,6 +146,8 @@ > import org.eclipse.cdt.internal.ui.text.CPairMatcher; > import org.eclipse.cdt.internal.ui.text.CSourceViewerConfiguration; > import org.eclipse.cdt.internal.ui.text.CTextTools; >+import org.eclipse.cdt.internal.ui.text.CWordIterator; >+import org.eclipse.cdt.internal.ui.text.DocumentCharacterIterator; > import org.eclipse.cdt.internal.ui.text.HTMLTextPresenter; > import org.eclipse.cdt.internal.ui.text.ICPartitions; > import org.eclipse.cdt.internal.ui.text.c.hover.SourceViewerInformationControl; >@@ -512,6 +522,8 @@ > /** Listener to annotation model changes that updates the error tick in the tab image */ > private CEditorErrorTickUpdater fCEditorErrorTickUpdater; > >+ /** Preference key for sub-word navigation, aka smart caret positioning */ >+ public final static String SUB_WORD_NAVIGATION= "subWordNavigation"; //$NON-NLS-1$ > /** Preference key for matching brackets */ > public final static String MATCHING_BRACKETS = "matchingBrackets"; //$NON-NLS-1$ > /** Preference key for matching brackets color */ >@@ -1396,6 +1408,47 @@ > return store.getBoolean(SPACES_FOR_TABS); > } > >+ /* >+ * @see org.eclipse.ui.texteditor.AbstractTextEditor#createNavigationActions() >+ */ >+ protected void createNavigationActions() { >+ super.createNavigationActions(); >+ >+ final StyledText textWidget = getSourceViewer().getTextWidget(); >+ >+ IAction action = new NavigatePreviousSubWordAction(); >+ action.setActionDefinitionId(ITextEditorActionDefinitionIds.WORD_PREVIOUS); >+ setAction(ITextEditorActionDefinitionIds.WORD_PREVIOUS, action); >+ textWidget.setKeyBinding(SWT.CTRL | SWT.ARROW_LEFT, SWT.NULL); >+ >+ action = new NavigateNextSubWordAction(); >+ action.setActionDefinitionId(ITextEditorActionDefinitionIds.WORD_NEXT); >+ setAction(ITextEditorActionDefinitionIds.WORD_NEXT, action); >+ textWidget.setKeyBinding(SWT.CTRL | SWT.ARROW_RIGHT, SWT.NULL); >+ >+ action = new SelectPreviousSubWordAction(); >+ action.setActionDefinitionId(ITextEditorActionDefinitionIds.SELECT_WORD_PREVIOUS); >+ setAction(ITextEditorActionDefinitionIds.SELECT_WORD_PREVIOUS, action); >+ textWidget.setKeyBinding(SWT.CTRL | SWT.SHIFT | SWT.ARROW_LEFT, SWT.NULL); >+ >+ action = new SelectNextSubWordAction(); >+ action.setActionDefinitionId(ITextEditorActionDefinitionIds.SELECT_WORD_NEXT); >+ setAction(ITextEditorActionDefinitionIds.SELECT_WORD_NEXT, action); >+ textWidget.setKeyBinding(SWT.CTRL | SWT.SHIFT | SWT.ARROW_RIGHT, SWT.NULL); >+ >+ action= new DeletePreviousSubWordAction(); >+ action.setActionDefinitionId(ITextEditorActionDefinitionIds.DELETE_PREVIOUS_WORD); >+ setAction(ITextEditorActionDefinitionIds.DELETE_PREVIOUS_WORD, action); >+ textWidget.setKeyBinding(SWT.CTRL | SWT.BS, SWT.NULL); >+ markAsStateDependentAction(ITextEditorActionDefinitionIds.DELETE_PREVIOUS_WORD, true); >+ >+ action= new DeleteNextSubWordAction(); >+ action.setActionDefinitionId(ITextEditorActionDefinitionIds.DELETE_NEXT_WORD); >+ setAction(ITextEditorActionDefinitionIds.DELETE_NEXT_WORD, action); >+ textWidget.setKeyBinding(SWT.CTRL | SWT.DEL, SWT.NULL); >+ markAsStateDependentAction(ITextEditorActionDefinitionIds.DELETE_NEXT_WORD, true); >+ } >+ > interface ITextConverter { > void customizeDocumentCommand(IDocument document, DocumentCommand command); > } >@@ -1669,4 +1722,365 @@ > System.arraycopy(parentPrefPageIds, 0, prefPageIds, nIds, parentPrefPageIds.length); > return prefPageIds; > } >+ >+ /** >+ * Text navigation action to navigate to the next sub-word. >+ * >+ * @since 3.0 >+ */ >+ protected abstract class NextSubWordAction extends TextNavigationAction { >+ >+ protected CWordIterator fIterator = new CWordIterator(); >+ >+ /** >+ * Creates a new next sub-word action. >+ * >+ * @param code Action code for the default operation. Must be an action code from @see org.eclipse.swt.custom.ST. >+ */ >+ protected NextSubWordAction(int code) { >+ super(getSourceViewer().getTextWidget(), code); >+ } >+ >+ /* >+ * @see org.eclipse.jface.action.IAction#run() >+ */ >+ public void run() { >+ // Check whether sub word navigation is enabled. >+ final IPreferenceStore store = getPreferenceStore(); >+ if (!store.getBoolean(SUB_WORD_NAVIGATION)) { >+ super.run(); >+ return; >+ } >+ >+ final ISourceViewer viewer = getSourceViewer(); >+ final IDocument document = viewer.getDocument(); >+ fIterator.setText((CharacterIterator) new DocumentCharacterIterator(document)); >+ int position = widgetOffset2ModelOffset(viewer, viewer.getTextWidget().getCaretOffset()); >+ if (position == -1) >+ return; >+ >+ int next = findNextPosition(position); >+ if (next != BreakIterator.DONE) { >+ setCaretPosition(next); >+ getTextWidget().showSelection(); >+ fireSelectionChanged(); >+ } >+ >+ } >+ >+ /** >+ * Finds the next position after the given position. >+ * >+ * @param position the current position >+ * @return the next position >+ */ >+ protected int findNextPosition(int position) { >+ ISourceViewer viewer = getSourceViewer(); >+ int widget = -1; >+ while (position != BreakIterator.DONE && widget == -1) { // TODO: optimize >+ position = fIterator.following(position); >+ if (position != BreakIterator.DONE) >+ widget = modelOffset2WidgetOffset(viewer, position); >+ } >+ return position; >+ } >+ >+ /** >+ * Sets the caret position to the sub-word boundary given with <code>position</code>. >+ * >+ * @param position Position where the action should move the caret >+ */ >+ protected abstract void setCaretPosition(int position); >+ } >+ >+ /** >+ * Text navigation action to navigate to the next sub-word. >+ * >+ * @since 3.0 >+ */ >+ protected class NavigateNextSubWordAction extends NextSubWordAction { >+ >+ /** >+ * Creates a new navigate next sub-word action. >+ */ >+ public NavigateNextSubWordAction() { >+ super(ST.WORD_NEXT); >+ } >+ >+ /* >+ * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor.NextSubWordAction#setCaretPosition(int) >+ */ >+ protected void setCaretPosition(final int position) { >+ getTextWidget().setCaretOffset(modelOffset2WidgetOffset(getSourceViewer(), position)); >+ } >+ } >+ >+ /** >+ * Text operation action to delete the next sub-word. >+ * >+ * @since 3.0 >+ */ >+ protected class DeleteNextSubWordAction extends NextSubWordAction implements IUpdate { >+ >+ /** >+ * Creates a new delete next sub-word action. >+ */ >+ public DeleteNextSubWordAction() { >+ super(ST.DELETE_WORD_NEXT); >+ } >+ >+ /* >+ * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor.NextSubWordAction#setCaretPosition(int) >+ */ >+ protected void setCaretPosition(final int position) { >+ if (!validateEditorInputState()) >+ return; >+ >+ final ISourceViewer viewer = getSourceViewer(); >+ final int caret, length; >+ Point selection = viewer.getSelectedRange(); >+ if (selection.y != 0) { >+ caret = selection.x; >+ length = selection.y; >+ } else { >+ caret = widgetOffset2ModelOffset(viewer, viewer.getTextWidget().getCaretOffset()); >+ length = position - caret; >+ } >+ >+ try { >+ viewer.getDocument().replace(caret, length, ""); //$NON-NLS-1$ >+ } catch (BadLocationException exception) { >+ // Should not happen >+ } >+ } >+ >+ /* >+ * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor.NextSubWordAction#findNextPosition(int) >+ */ >+ protected int findNextPosition(int position) { >+ return fIterator.following(position); >+ } >+ >+ /* >+ * @see org.eclipse.ui.texteditor.IUpdate#update() >+ */ >+ public void update() { >+ setEnabled(isEditorInputModifiable()); >+ } >+ } >+ >+ /** >+ * Text operation action to select the next sub-word. >+ * >+ * @since 3.0 >+ */ >+ protected class SelectNextSubWordAction extends NextSubWordAction { >+ >+ /** >+ * Creates a new select next sub-word action. >+ */ >+ public SelectNextSubWordAction() { >+ super(ST.SELECT_WORD_NEXT); >+ } >+ >+ /* >+ * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor.NextSubWordAction#setCaretPosition(int) >+ */ >+ protected void setCaretPosition(final int position) { >+ final ISourceViewer viewer = getSourceViewer(); >+ >+ final StyledText text = viewer.getTextWidget(); >+ if (text != null && !text.isDisposed()) { >+ >+ final Point selection = text.getSelection(); >+ final int caret = text.getCaretOffset(); >+ final int offset = modelOffset2WidgetOffset(viewer, position); >+ >+ if (caret == selection.x) >+ text.setSelectionRange(selection.y, offset - selection.y); >+ else >+ text.setSelectionRange(selection.x, offset - selection.x); >+ } >+ } >+ } >+ >+ /** >+ * Text navigation action to navigate to the previous sub-word. >+ * >+ * @since 3.0 >+ */ >+ protected abstract class PreviousSubWordAction extends TextNavigationAction { >+ >+ protected CWordIterator fIterator = new CWordIterator(); >+ >+ /** >+ * Creates a new previous sub-word action. >+ * >+ * @param code Action code for the default operation. Must be an action code from @see org.eclipse.swt.custom.ST. >+ */ >+ protected PreviousSubWordAction(final int code) { >+ super(getSourceViewer().getTextWidget(), code); >+ } >+ >+ /* >+ * @see org.eclipse.jface.action.IAction#run() >+ */ >+ public void run() { >+ // Check whether sub word navigation is enabled. >+ final IPreferenceStore store = getPreferenceStore(); >+ if (!store.getBoolean(SUB_WORD_NAVIGATION)) { >+ super.run(); >+ return; >+ } >+ >+ final ISourceViewer viewer = getSourceViewer(); >+ final IDocument document = viewer.getDocument(); >+ fIterator.setText((CharacterIterator) new DocumentCharacterIterator(document)); >+ int position = widgetOffset2ModelOffset(viewer, viewer.getTextWidget().getCaretOffset()); >+ if (position == -1) >+ return; >+ >+ int previous = findPreviousPosition(position); >+ if (previous != BreakIterator.DONE) { >+ setCaretPosition(previous); >+ getTextWidget().showSelection(); >+ fireSelectionChanged(); >+ } >+ >+ } >+ >+ /** >+ * Finds the previous position before the given position. >+ * >+ * @param position the current position >+ * @return the previous position >+ */ >+ protected int findPreviousPosition(int position) { >+ ISourceViewer viewer = getSourceViewer(); >+ int widget = -1; >+ while (position != BreakIterator.DONE && widget == -1) { // TODO: optimize >+ position = fIterator.preceding(position); >+ if (position != BreakIterator.DONE) >+ widget = modelOffset2WidgetOffset(viewer, position); >+ } >+ return position; >+ } >+ >+ /** >+ * Sets the caret position to the sub-word boundary given with <code>position</code>. >+ * >+ * @param position Position where the action should move the caret >+ */ >+ protected abstract void setCaretPosition(int position); >+ } >+ >+ /** >+ * Text navigation action to navigate to the previous sub-word. >+ * >+ * @since 3.0 >+ */ >+ protected class NavigatePreviousSubWordAction extends PreviousSubWordAction { >+ >+ /** >+ * Creates a new navigate previous sub-word action. >+ */ >+ public NavigatePreviousSubWordAction() { >+ super(ST.WORD_PREVIOUS); >+ } >+ >+ /* >+ * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor.PreviousSubWordAction#setCaretPosition(int) >+ */ >+ protected void setCaretPosition(final int position) { >+ getTextWidget().setCaretOffset(modelOffset2WidgetOffset(getSourceViewer(), position)); >+ } >+ } >+ >+ /** >+ * Text operation action to delete the previous sub-word. >+ * >+ * @since 3.0 >+ */ >+ protected class DeletePreviousSubWordAction extends PreviousSubWordAction implements IUpdate { >+ >+ /** >+ * Creates a new delete previous sub-word action. >+ */ >+ public DeletePreviousSubWordAction() { >+ super(ST.DELETE_WORD_PREVIOUS); >+ } >+ >+ /* >+ * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor.PreviousSubWordAction#setCaretPosition(int) >+ */ >+ protected void setCaretPosition(int position) { >+ if (!validateEditorInputState()) >+ return; >+ >+ final int length; >+ final ISourceViewer viewer = getSourceViewer(); >+ Point selection = viewer.getSelectedRange(); >+ if (selection.y != 0) { >+ position = selection.x; >+ length = selection.y; >+ } else { >+ length = widgetOffset2ModelOffset(viewer, viewer.getTextWidget().getCaretOffset()) - position; >+ } >+ >+ try { >+ viewer.getDocument().replace(position, length, ""); //$NON-NLS-1$ >+ } catch (BadLocationException exception) { >+ // Should not happen >+ } >+ } >+ >+ /* >+ * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor.PreviousSubWordAction#findPreviousPosition(int) >+ */ >+ protected int findPreviousPosition(int position) { >+ return fIterator.preceding(position); >+ } >+ >+ /* >+ * @see org.eclipse.ui.texteditor.IUpdate#update() >+ */ >+ public void update() { >+ setEnabled(isEditorInputModifiable()); >+ } >+ } >+ >+ /** >+ * Text operation action to select the previous sub-word. >+ * >+ * @since 3.0 >+ */ >+ protected class SelectPreviousSubWordAction extends PreviousSubWordAction { >+ >+ /** >+ * Creates a new select previous sub-word action. >+ */ >+ public SelectPreviousSubWordAction() { >+ super(ST.SELECT_WORD_PREVIOUS); >+ } >+ >+ /* >+ * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor.PreviousSubWordAction#setCaretPosition(int) >+ */ >+ protected void setCaretPosition(final int position) { >+ final ISourceViewer viewer = getSourceViewer(); >+ >+ final StyledText text = viewer.getTextWidget(); >+ if (text != null && !text.isDisposed()) { >+ >+ final Point selection = text.getSelection(); >+ final int caret = text.getCaretOffset(); >+ final int offset = modelOffset2WidgetOffset(viewer, position); >+ >+ if (caret == selection.x) >+ text.setSelectionRange(selection.y, offset - selection.y); >+ else >+ text.setSelectionRange(selection.x, offset - selection.x); >+ } >+ } >+ } > } >Index: src/org/eclipse/cdt/internal/ui/text/CBreakIterator.java >=================================================================== >RCS file: src/org/eclipse/cdt/internal/ui/text/CBreakIterator.java >diff -N src/org/eclipse/cdt/internal/ui/text/CBreakIterator.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/cdt/internal/ui/text/CBreakIterator.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,449 @@ >+/******************************************************************************* >+ * Copyright (c) 2000, 2006 IBM Corporation and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * IBM Corporation - initial API and implementation >+ * Sergey Prigogin, Google >+ *******************************************************************************/ >+package org.eclipse.cdt.internal.ui.text; >+ >+import com.ibm.icu.text.BreakIterator; >+import java.text.CharacterIterator; >+ >+import org.eclipse.jface.text.Assert; >+ >+ >+/** >+ * A C break iterator. It returns all breaks, including before and after >+ * whitespace, and it returns all camel case breaks. >+ * <p> >+ * A line break may be any of "\n", "\r", "\r\n", "\n\r". >+ * </p> >+ * >+ * @since 3.0 >+ */ >+public class CBreakIterator extends BreakIterator { >+ >+ /** >+ * A run of common characters. >+ */ >+ protected static abstract class Run { >+ /** The length of this run. */ >+ protected int length; >+ >+ public Run() { >+ init(); >+ } >+ >+ /** >+ * Returns <code>true</code> if this run consumes <code>ch</code>, >+ * <code>false</code> otherwise. If <code>true</code> is returned, >+ * the length of the receiver is adjusted accordingly. >+ * >+ * @param ch the character to test >+ * @return <code>true</code> if <code>ch</code> was consumed >+ */ >+ protected boolean consume(char ch) { >+ if (isValid(ch)) { >+ length++; >+ return true; >+ } >+ return false; >+ } >+ >+ /** >+ * Whether this run accepts that character; does not update state. Called >+ * from the default implementation of <code>consume</code>. >+ * >+ * @param ch the character to test >+ * @return <code>true</code> if <code>ch</code> is accepted >+ */ >+ protected abstract boolean isValid(char ch); >+ >+ /** >+ * Resets this run to the initial state. >+ */ >+ protected void init() { >+ length= 0; >+ } >+ } >+ >+ static final class Whitespace extends Run { >+ protected boolean isValid(char ch) { >+ return Character.isWhitespace(ch) && ch != '\n' && ch != '\r'; >+ } >+ } >+ >+ static final class LineDelimiter extends Run { >+ /** State: INIT -> delimiter -> EXIT. */ >+ private char fState; >+ private static final char INIT= '\0'; >+ private static final char EXIT= '\1'; >+ >+ /* >+ * @see org.eclipse.jdt.internal.ui.text.CBreakIterator.Run#init() >+ */ >+ protected void init() { >+ super.init(); >+ fState= INIT; >+ } >+ >+ /* >+ * @see org.eclipse.jdt.internal.ui.text.CBreakIterator.Run#consume(char) >+ */ >+ protected boolean consume(char ch) { >+ if (!isValid(ch) || fState == EXIT) >+ return false; >+ >+ if (fState == INIT) { >+ fState= ch; >+ length++; >+ return true; >+ } else if (fState != ch) { >+ fState= EXIT; >+ length++; >+ return true; >+ } else { >+ return false; >+ } >+ } >+ >+ protected boolean isValid(char ch) { >+ return ch == '\n' || ch == '\r'; >+ } >+ } >+ >+ static final class Identifier extends Run { >+ /* >+ * @see org.eclipse.jdt.internal.ui.text.CBreakIterator.Run#isValid(char) >+ */ >+ protected boolean isValid(char ch) { >+ return Character.isJavaIdentifierPart(ch); >+ } >+ } >+ >+ static final class CamelCaseIdentifier extends Run { >+ /* states */ >+ private static final int S_INIT= 0; >+ private static final int S_LOWER= 1; >+ private static final int S_ONE_CAP= 2; >+ private static final int S_ALL_CAPS= 3; >+ private static final int S_UNDERSCORE= 4; >+ private static final int S_EXIT= 5; >+ private static final int S_EXIT_MINUS_ONE= 6; >+ >+ /* character types */ >+ private static final int K_INVALID= 0; >+ private static final int K_LOWER= 1; >+ private static final int K_UPPER= 2; >+ private static final int K_UNDERSCORE= 3; >+ private static final int K_OTHER= 4; >+ >+ private int fState; >+ >+ private final static int[][] MATRIX= new int[][] { >+ // K_INVALID, K_LOWER, K_UPPER, K_UNDERSCORE, K_OTHER >+ { S_EXIT, S_LOWER, S_ONE_CAP, S_UNDERSCORE, S_LOWER }, // S_INIT >+ { S_EXIT, S_LOWER, S_EXIT, S_UNDERSCORE, S_LOWER }, // S_LOWER >+ { S_EXIT, S_LOWER, S_ALL_CAPS, S_UNDERSCORE, S_LOWER }, // S_ONE_CAP >+ { S_EXIT, S_EXIT_MINUS_ONE, S_ALL_CAPS, S_UNDERSCORE, S_LOWER }, // S_ALL_CAPS >+ { S_EXIT, S_EXIT, S_EXIT, S_UNDERSCORE, S_EXIT }, // S_UNDERSCORE >+ }; >+ >+ /* >+ * @see org.eclipse.jdt.internal.ui.text.CBreakIterator.Run#init() >+ */ >+ protected void init() { >+ super.init(); >+ fState= S_INIT; >+ } >+ >+ /* >+ * @see org.eclipse.jdt.internal.ui.text.CBreakIterator.Run#consumes(char) >+ */ >+ protected boolean consume(char ch) { >+ int kind= getKind(ch); >+ fState= MATRIX[fState][kind]; >+ switch (fState) { >+ case S_LOWER: >+ case S_ONE_CAP: >+ case S_ALL_CAPS: >+ case S_UNDERSCORE: >+ length++; >+ return true; >+ case S_EXIT: >+ return false; >+ case S_EXIT_MINUS_ONE: >+ length--; >+ return false; >+ default: >+ Assert.isTrue(false); >+ return false; >+ } >+ } >+ >+ /** >+ * Determines the kind of a character. >+ * >+ * @param ch the character to test >+ */ >+ private int getKind(char ch) { >+ if (Character.isUpperCase(ch)) >+ return K_UPPER; >+ if (Character.isLowerCase(ch)) >+ return K_LOWER; >+ if (ch == '_') >+ return K_UNDERSCORE; >+ if (Character.isJavaIdentifierPart(ch)) // digits... >+ return K_OTHER; >+ return K_INVALID; >+ } >+ >+ /* >+ * @see org.eclipse.jdt.internal.ui.text.CBreakIterator.Run#isValid(char) >+ */ >+ protected boolean isValid(char ch) { >+ return Character.isJavaIdentifierPart(ch); >+ } >+ } >+ >+ static final class Other extends Run { >+ /* >+ * @see org.eclipse.jdt.internal.ui.text.CBreakIterator.Run#isValid(char) >+ */ >+ protected boolean isValid(char ch) { >+ return !Character.isWhitespace(ch) && !Character.isJavaIdentifierPart(ch); >+ } >+ } >+ >+ private static final Run WHITESPACE= new Whitespace(); >+ private static final Run DELIMITER= new LineDelimiter(); >+ private static final Run IDENTIFIER= new Identifier(); >+ private static final Run CAMELCASE= new CamelCaseIdentifier(); >+ private static final Run OTHER= new Other(); >+ >+ /** The platform break iterator (word instance) used as a base. */ >+ protected final BreakIterator fIterator; >+ /** The text we operate on. */ >+ protected CharSequence fText; >+ /** our current position for the stateful methods. */ >+ private int fIndex; >+ /** Break on camel case word boundaries */ >+ private boolean fCamelCaseBreakEnabled = true; >+ >+ >+ /** >+ * Creates a new break iterator. >+ */ >+ public CBreakIterator() { >+ fIterator= BreakIterator.getWordInstance(); >+ fIndex= fIterator.current(); >+ } >+ >+ /* >+ * @see java.text.BreakIterator#current() >+ */ >+ public int current() { >+ return fIndex; >+ } >+ >+ /* >+ * @see java.text.BreakIterator#first() >+ */ >+ public int first() { >+ fIndex= fIterator.first(); >+ return fIndex; >+ } >+ >+ /* >+ * @see java.text.BreakIterator#following(int) >+ */ >+ public int following(int offset) { >+ // work around too eager IAEs in standard implementation >+ if (offset == getText().getEndIndex()) >+ return DONE; >+ >+ int next= fIterator.following(offset); >+ if (next == DONE) >+ return DONE; >+ >+ // TODO deal with complex script word boundaries >+ // Math.min(offset + run.length, next) does not work >+ // since BreakIterator.getWordInstance considers _ as boundaries >+ // seems to work fine, however >+ Run run= consumeRun(offset); >+ return offset + run.length; >+ >+ } >+ >+ /** >+ * Consumes a run of characters at the limits of which we introduce a break. >+ * @param offset the offset to start at >+ * @return the run that was consumed >+ */ >+ private Run consumeRun(int offset) { >+ // assert offset < length >+ >+ char ch= fText.charAt(offset); >+ int length= fText.length(); >+ Run run= getRun(ch); >+ while (run.consume(ch) && offset < length - 1) { >+ offset++; >+ ch= fText.charAt(offset); >+ } >+ >+ return run; >+ } >+ >+ /** >+ * Returns a run based on a character. >+ * >+ * @param ch the character to test >+ * @return the correct character given <code>ch</code> >+ */ >+ private Run getRun(char ch) { >+ Run run; >+ if (WHITESPACE.isValid(ch)) >+ run= WHITESPACE; >+ else if (DELIMITER.isValid(ch)) >+ run= DELIMITER; >+ else if (IDENTIFIER.isValid(ch)) { >+ if (fCamelCaseBreakEnabled) >+ run= CAMELCASE; >+ else >+ run= IDENTIFIER; >+ } >+ else if (OTHER.isValid(ch)) >+ run= OTHER; >+ else { >+ Assert.isTrue(false); >+ return null; >+ } >+ >+ run.init(); >+ return run; >+ } >+ >+ /* >+ * @see java.text.BreakIterator#getText() >+ */ >+ public CharacterIterator getText() { >+ return fIterator.getText(); >+ } >+ >+ /* >+ * @see java.text.BreakIterator#isBoundary(int) >+ */ >+ public boolean isBoundary(int offset) { >+ if (offset == getText().getBeginIndex()) >+ return true; >+ else >+ return following(offset - 1) == offset; >+ } >+ >+ /* >+ * @see java.text.BreakIterator#last() >+ */ >+ public int last() { >+ fIndex= fIterator.last(); >+ return fIndex; >+ } >+ >+ /* >+ * @see java.text.BreakIterator#next() >+ */ >+ public int next() { >+ fIndex= following(fIndex); >+ return fIndex; >+ } >+ >+ /* >+ * @see java.text.BreakIterator#next(int) >+ */ >+ public int next(int n) { >+ return fIterator.next(n); >+ } >+ >+ /* >+ * @see java.text.BreakIterator#preceding(int) >+ */ >+ public int preceding(int offset) { >+ if (offset == getText().getBeginIndex()) >+ return DONE; >+ >+ if (isBoundary(offset - 1)) >+ return offset - 1; >+ >+ int previous= offset - 1; >+ do { >+ previous= fIterator.preceding(previous); >+ } while (!isBoundary(previous)); >+ >+ int last= DONE; >+ while (previous < offset) { >+ last= previous; >+ previous= following(previous); >+ } >+ >+ return last; >+ } >+ >+ /* >+ * @see java.text.BreakIterator#previous() >+ */ >+ public int previous() { >+ fIndex= preceding(fIndex); >+ return fIndex; >+ } >+ >+ /* >+ * @see java.text.BreakIterator#setText(java.lang.String) >+ */ >+ public void setText(String newText) { >+ setText((CharSequence) newText); >+ } >+ >+ /** >+ * Creates a break iterator given a char sequence. >+ * @param newText the new text >+ */ >+ public void setText(CharSequence newText) { >+ fText= newText; >+ fIterator.setText(new SequenceCharacterIterator(newText)); >+ first(); >+ } >+ >+ /* >+ * @see java.text.BreakIterator#setText(java.text.CharacterIterator) >+ */ >+ public void setText(CharacterIterator newText) { >+ if (newText instanceof CharSequence) { >+ fText= (CharSequence) newText; >+ fIterator.setText(newText); >+ first(); >+ } else { >+ throw new UnsupportedOperationException("CharacterIterator not supported"); //$NON-NLS-1$ >+ } >+ } >+ >+ /** >+ * Enables breaks at word boundaries inside a camel case identifier. >+ * >+ * @param enable <code>true</code> to enable, <code>false</code> to disable. >+ */ >+ public void setCamelCaseBreakEnabled(boolean camelCaseBreakEnabled) { >+ fCamelCaseBreakEnabled = camelCaseBreakEnabled; >+ } >+ >+ /** >+ * @return <code>true</code> if breaks at word boundaries inside >+ * a camel case identifier are enabled. >+ */ >+ public boolean isCamelCaseBreakEnabled() { >+ return fCamelCaseBreakEnabled; >+ } >+} >Index: src/org/eclipse/cdt/internal/ui/text/DocumentCharacterIterator.java >=================================================================== >RCS file: src/org/eclipse/cdt/internal/ui/text/DocumentCharacterIterator.java >diff -N src/org/eclipse/cdt/internal/ui/text/DocumentCharacterIterator.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/cdt/internal/ui/text/DocumentCharacterIterator.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,222 @@ >+/******************************************************************************* >+ * Copyright (c) 2000, 2005 IBM Corporation and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * IBM Corporation - initial API and implementation >+ *******************************************************************************/ >+package org.eclipse.cdt.internal.ui.text; >+ >+import java.text.CharacterIterator; >+ >+import org.eclipse.jface.text.Assert; >+import org.eclipse.jface.text.BadLocationException; >+import org.eclipse.jface.text.IDocument; >+ >+ >+/** >+ * An <code>IDocument</code> based implementation of >+ * <code>CharacterIterator</code> and <code>CharSequence</code>. Note that >+ * the supplied document is not copied; if the document is modified during the >+ * lifetime of a <code>DocumentCharacterIterator</code>, the methods >+ * returning document content may not always return the same values. Also, if >+ * accessing the document fails with a {@link BadLocationException}, any of >+ * <code>CharacterIterator</code> methods as well as <code>charAt</code>may >+ * return {@link CharacterIterator#DONE}. >+ * >+ * @since 3.0 >+ */ >+public class DocumentCharacterIterator implements CharacterIterator, CharSequence { >+ >+ private int fIndex= -1; >+ private final IDocument fDocument; >+ private final int fFirst; >+ private final int fLast; >+ >+ private void invariant() { >+ Assert.isTrue(fIndex >= fFirst); >+ Assert.isTrue(fIndex <= fLast); >+ } >+ >+ /** >+ * Creates an iterator for the entire document. >+ * >+ * @param document the document backing this iterator >+ */ >+ public DocumentCharacterIterator(IDocument document) { >+ this(document, 0); >+ } >+ >+ /** >+ * Creates an iterator, starting at offset <code>first</code>. >+ * >+ * @param document the document backing this iterator >+ * @param first the first character to consider >+ * @throws IllegalArgumentException if the indices are out of bounds >+ */ >+ public DocumentCharacterIterator(IDocument document, int first) throws IllegalArgumentException { >+ this(document, first, document.getLength()); >+ } >+ >+ /** >+ * Creates an iterator for the document contents from <code>first</code> >+ * (inclusive) to <code>last</code> (exclusive). >+ * >+ * @param document the document backing this iterator >+ * @param first the first character to consider >+ * @param last the last character index to consider >+ * @throws IllegalArgumentException if the indices are out of bounds >+ */ >+ public DocumentCharacterIterator(IDocument document, int first, int last) throws IllegalArgumentException { >+ if (document == null) >+ throw new NullPointerException(); >+ if (first < 0 || first > last) >+ throw new IllegalArgumentException(); >+ if (last > document.getLength()) >+ throw new IllegalArgumentException(); >+ fDocument= document; >+ fFirst= first; >+ fLast= last; >+ fIndex= first; >+ invariant(); >+ } >+ >+ /* >+ * @see java.text.CharacterIterator#first() >+ */ >+ public char first() { >+ return setIndex(getBeginIndex()); >+ } >+ >+ /* >+ * @see java.text.CharacterIterator#last() >+ */ >+ public char last() { >+ if (fFirst == fLast) >+ return setIndex(getEndIndex()); >+ else >+ return setIndex(getEndIndex() - 1); >+ } >+ >+ /* >+ * @see java.text.CharacterIterator#current() >+ */ >+ public char current() { >+ if (fIndex >= fFirst && fIndex < fLast) >+ try { >+ return fDocument.getChar(fIndex); >+ } catch (BadLocationException e) { >+ // ignore >+ } >+ return DONE; >+ } >+ >+ /* >+ * @see java.text.CharacterIterator#next() >+ */ >+ public char next() { >+ return setIndex(Math.min(fIndex + 1, getEndIndex())); >+ } >+ >+ /* >+ * @see java.text.CharacterIterator#previous() >+ */ >+ public char previous() { >+ if (fIndex > getBeginIndex()) { >+ return setIndex(fIndex - 1); >+ } else { >+ return DONE; >+ } >+ } >+ >+ /* >+ * @see java.text.CharacterIterator#setIndex(int) >+ */ >+ public char setIndex(int position) { >+ if (position >= getBeginIndex() && position <= getEndIndex()) >+ fIndex= position; >+ else >+ throw new IllegalArgumentException(); >+ >+ invariant(); >+ return current(); >+ } >+ >+ /* >+ * @see java.text.CharacterIterator#getBeginIndex() >+ */ >+ public int getBeginIndex() { >+ return fFirst; >+ } >+ >+ /* >+ * @see java.text.CharacterIterator#getEndIndex() >+ */ >+ public int getEndIndex() { >+ return fLast; >+ } >+ >+ /* >+ * @see java.text.CharacterIterator#getIndex() >+ */ >+ public int getIndex() { >+ return fIndex; >+ } >+ >+ /* >+ * @see java.text.CharacterIterator#clone() >+ */ >+ public Object clone() { >+ try { >+ return super.clone(); >+ } catch (CloneNotSupportedException e) { >+ throw new InternalError(); >+ } >+ } >+ >+ /* >+ * @see java.lang.CharSequence#length() >+ */ >+ public int length() { >+ return getEndIndex() - getBeginIndex(); >+ } >+ >+ /** >+ * {@inheritDoc} >+ * <p> >+ * Note that, if the document is modified concurrently, this method may >+ * return {@link CharacterIterator#DONE} if a {@link BadLocationException} >+ * was thrown when accessing the backing document. >+ * </p> >+ * >+ * @param index {@inheritDoc} >+ * @return {@inheritDoc} >+ */ >+ public char charAt(int index) { >+ if (index >= 0 && index < length()) >+ try { >+ return fDocument.getChar(getBeginIndex() + index); >+ } catch (BadLocationException e) { >+ // ignore and return DONE >+ return DONE; >+ } >+ else >+ throw new IndexOutOfBoundsException(); >+ } >+ >+ /* >+ * @see java.lang.CharSequence#subSequence(int, int) >+ */ >+ public CharSequence subSequence(int start, int end) { >+ if (start < 0) >+ throw new IndexOutOfBoundsException(); >+ if (end < start) >+ throw new IndexOutOfBoundsException(); >+ if (end > length()) >+ throw new IndexOutOfBoundsException(); >+ return new DocumentCharacterIterator(fDocument, getBeginIndex() + start, getBeginIndex() + end); >+ } >+} >Index: src/org/eclipse/cdt/internal/ui/text/CWordIterator.java >=================================================================== >RCS file: src/org/eclipse/cdt/internal/ui/text/CWordIterator.java >diff -N src/org/eclipse/cdt/internal/ui/text/CWordIterator.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/cdt/internal/ui/text/CWordIterator.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,239 @@ >+/******************************************************************************* >+ * Copyright (c) 2000, 2006 IBM Corporation and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * IBM Corporation - initial API and implementation >+ * Sergey Prigogin, Google >+ *******************************************************************************/ >+package org.eclipse.cdt.internal.ui.text; >+ >+import com.ibm.icu.text.BreakIterator; >+import java.text.CharacterIterator; >+ >+import org.eclipse.jface.text.Assert; >+ >+ >+/** >+ * Breaks C text into word starts, also stops at line start and end. No >+ * direction dependency. >+ * >+ * @since 3.0 >+ */ >+public class CWordIterator extends BreakIterator { >+ >+ /** >+ * The underlying java break iterator. It returns all breaks, including >+ * before and after every whitespace. >+ */ >+ private CBreakIterator fIterator; >+ /** The current index for the stateful operations. */ >+ private int fIndex; >+ >+ /** >+ * Creates a new word iterator. >+ */ >+ public CWordIterator() { >+ fIterator= new CBreakIterator(); >+ first(); >+ } >+ >+ /* >+ * @see java.text.BreakIterator#first() >+ */ >+ public int first() { >+ fIndex= fIterator.first(); >+ return fIndex; >+ } >+ >+ /* >+ * @see java.text.BreakIterator#last() >+ */ >+ public int last() { >+ fIndex= fIterator.last(); >+ return fIndex; >+ } >+ >+ /* >+ * @see java.text.BreakIterator#next(int) >+ */ >+ public int next(int n) { >+ int next= 0; >+ while (--n > 0 && next != DONE) { >+ next= next(); >+ } >+ return next; >+ } >+ >+ /* >+ * @see java.text.BreakIterator#next() >+ */ >+ public int next() { >+ fIndex= following(fIndex); >+ return fIndex; >+ } >+ >+ /* >+ * @see java.text.BreakIterator#previous() >+ */ >+ public int previous() { >+ fIndex= preceding(fIndex); >+ return fIndex; >+ } >+ >+ >+ /* >+ * @see java.text.BreakIterator#preceding(int) >+ */ >+ public int preceding(int offset) { >+ int first= fIterator.preceding(offset); >+ if (isWhitespace(first, offset)) { >+ int second= fIterator.preceding(first); >+ if (second != DONE && !isDelimiter(second, first)) >+ return second; >+ } >+ return first; >+ } >+ >+ /* >+ * @see java.text.BreakIterator#following(int) >+ */ >+ public int following(int offset) { >+ int first= fIterator.following(offset); >+ if (eatFollowingWhitespace(offset, first)) { >+ int second= fIterator.following(first); >+ if (isWhitespace(first, second)) >+ return second; >+ } >+ return first; >+ } >+ >+ private boolean eatFollowingWhitespace(int offset, int exclusiveEnd) { >+ if (exclusiveEnd == DONE || offset == DONE) >+ return false; >+ >+ if (isWhitespace(offset, exclusiveEnd)) >+ return false; >+ if (isDelimiter(offset, exclusiveEnd)) >+ return false; >+ >+ return true; >+ } >+ >+ /** >+ * Returns <code>true</code> if the given sequence into the underlying text >+ * represents a delimiter, <code>false</code> otherwise. >+ * >+ * @param offset the offset >+ * @param exclusiveEnd the end offset >+ * @return <code>true</code> if the given range is a delimiter >+ */ >+ private boolean isDelimiter(int offset, int exclusiveEnd) { >+ if (exclusiveEnd == DONE || offset == DONE) >+ return false; >+ >+ Assert.isTrue(offset >= 0); >+ Assert.isTrue(exclusiveEnd <= getText().getEndIndex()); >+ Assert.isTrue(exclusiveEnd > offset); >+ >+ CharSequence seq= fIterator.fText; >+ >+ while (offset < exclusiveEnd) { >+ char ch= seq.charAt(offset); >+ if (ch != '\n' && ch != '\r') >+ return false; >+ offset++; >+ } >+ >+ return true; >+ } >+ >+ /** >+ * Returns <code>true</code> if the given sequence into the underlying text >+ * represents whitespace, but not a delimiter, <code>false</code> otherwise. >+ * >+ * @param offset the offset >+ * @param exclusiveEnd the end offset >+ * @return <code>true</code> if the given range is whitespace >+ */ >+ private boolean isWhitespace(int offset, int exclusiveEnd) { >+ if (exclusiveEnd == DONE || offset == DONE) >+ return false; >+ >+ Assert.isTrue(offset >= 0); >+ Assert.isTrue(exclusiveEnd <= getText().getEndIndex()); >+ Assert.isTrue(exclusiveEnd > offset); >+ >+ CharSequence seq= fIterator.fText; >+ >+ while (offset < exclusiveEnd) { >+ char ch= seq.charAt(offset); >+ if (!Character.isWhitespace(ch)) >+ return false; >+ if (ch == '\n' || ch == '\r') >+ return false; >+ offset++; >+ } >+ >+ return true; >+ } >+ >+ /* >+ * @see java.text.BreakIterator#current() >+ */ >+ public int current() { >+ return fIndex; >+ } >+ >+ /* >+ * @see java.text.BreakIterator#getText() >+ */ >+ public CharacterIterator getText() { >+ return fIterator.getText(); >+ } >+ >+ /** >+ * Sets the text as <code>CharSequence</code>. >+ * @param newText the new text >+ */ >+ public void setText(CharSequence newText) { >+ fIterator.setText(newText); >+ first(); >+ } >+ >+ /* >+ * @see java.text.BreakIterator#setText(java.text.CharacterIterator) >+ */ >+ public void setText(CharacterIterator newText) { >+ fIterator.setText(newText); >+ first(); >+ } >+ >+ /* >+ * @see java.text.BreakIterator#setText(java.lang.String) >+ */ >+ public void setText(String newText) { >+ setText((CharSequence) newText); >+ } >+ >+ /** >+ * Enables breaks at word boundaries inside a camel case identifier. >+ * >+ * @param camelCaseBreakEnabled <code>true</code> to enable, >+ * <code>false</code> to disable. >+ */ >+ public void setCamelCaseBreakEnabled(boolean camelCaseBreakEnabled) { >+ fIterator.setCamelCaseBreakEnabled(camelCaseBreakEnabled); >+ } >+ >+ /** >+ * @return <code>true</code> if breaks at word boundaries inside >+ * a camel case identifier are enabled. >+ */ >+ public boolean isCamelCaseBreakEnabled() { >+ return fIterator.isCamelCaseBreakEnabled(); >+ } >+} >Index: src/org/eclipse/cdt/internal/ui/text/SequenceCharacterIterator.java >=================================================================== >RCS file: src/org/eclipse/cdt/internal/ui/text/SequenceCharacterIterator.java >diff -N src/org/eclipse/cdt/internal/ui/text/SequenceCharacterIterator.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/cdt/internal/ui/text/SequenceCharacterIterator.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,166 @@ >+/******************************************************************************* >+ * Copyright (c) 2000, 2005 IBM Corporation and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * IBM Corporation - initial API and implementation >+ *******************************************************************************/ >+package org.eclipse.cdt.internal.ui.text; >+ >+import java.text.CharacterIterator; >+ >+import org.eclipse.jface.text.Assert; >+ >+ >+/** >+ * A <code>CharSequence</code> based implementation of <code>CharacterIterator</code>. >+ * >+ * @since 3.0 >+ */ >+public class SequenceCharacterIterator implements CharacterIterator { >+ >+ private int fIndex= -1; >+ private final CharSequence fSequence; >+ private final int fFirst; >+ private final int fLast; >+ >+ private void invariant() { >+ Assert.isTrue(fIndex >= fFirst); >+ Assert.isTrue(fIndex <= fLast); >+ } >+ >+ /** >+ * Creates an iterator for the entire sequence. >+ * >+ * @param sequence the sequence backing this iterator >+ */ >+ public SequenceCharacterIterator(CharSequence sequence) { >+ this(sequence, 0); >+ } >+ >+ /** >+ * Creates an iterator. >+ * >+ * @param sequence the sequence backing this iterator >+ * @param first the first character to consider >+ * @throws IllegalArgumentException if the indices are out of bounds >+ */ >+ public SequenceCharacterIterator(CharSequence sequence, int first) throws IllegalArgumentException { >+ this(sequence, first, sequence.length()); >+ } >+ >+ /** >+ * Creates an iterator. >+ * >+ * @param sequence the sequence backing this iterator >+ * @param first the first character to consider >+ * @param last the last character index to consider >+ * @throws IllegalArgumentException if the indices are out of bounds >+ */ >+ public SequenceCharacterIterator(CharSequence sequence, int first, int last) throws IllegalArgumentException { >+ if (sequence == null) >+ throw new NullPointerException(); >+ if (first < 0 || first > last) >+ throw new IllegalArgumentException(); >+ if (last > sequence.length()) >+ throw new IllegalArgumentException(); >+ fSequence= sequence; >+ fFirst= first; >+ fLast= last; >+ fIndex= first; >+ invariant(); >+ } >+ >+ /* >+ * @see java.text.CharacterIterator#first() >+ */ >+ public char first() { >+ return setIndex(getBeginIndex()); >+ } >+ >+ /* >+ * @see java.text.CharacterIterator#last() >+ */ >+ public char last() { >+ if (fFirst == fLast) >+ return setIndex(getEndIndex()); >+ else >+ return setIndex(getEndIndex() - 1); >+ } >+ >+ /* >+ * @see java.text.CharacterIterator#current() >+ */ >+ public char current() { >+ if (fIndex >= fFirst && fIndex < fLast) >+ return fSequence.charAt(fIndex); >+ else >+ return DONE; >+ } >+ >+ /* >+ * @see java.text.CharacterIterator#next() >+ */ >+ public char next() { >+ return setIndex(Math.min(fIndex + 1, getEndIndex())); >+ } >+ >+ /* >+ * @see java.text.CharacterIterator#previous() >+ */ >+ public char previous() { >+ if (fIndex > getBeginIndex()) { >+ return setIndex(fIndex - 1); >+ } else { >+ return DONE; >+ } >+ } >+ >+ /* >+ * @see java.text.CharacterIterator#setIndex(int) >+ */ >+ public char setIndex(int position) { >+ if (position >= getBeginIndex() && position <= getEndIndex()) >+ fIndex= position; >+ else >+ throw new IllegalArgumentException(); >+ >+ invariant(); >+ return current(); >+ } >+ >+ /* >+ * @see java.text.CharacterIterator#getBeginIndex() >+ */ >+ public int getBeginIndex() { >+ return fFirst; >+ } >+ >+ /* >+ * @see java.text.CharacterIterator#getEndIndex() >+ */ >+ public int getEndIndex() { >+ return fLast; >+ } >+ >+ /* >+ * @see java.text.CharacterIterator#getIndex() >+ */ >+ public int getIndex() { >+ return fIndex; >+ } >+ >+ /* >+ * @see java.text.CharacterIterator#clone() >+ */ >+ public Object clone() { >+ try { >+ return super.clone(); >+ } catch (CloneNotSupportedException e) { >+ throw new InternalError(); >+ } >+ } >+} >#P org.eclipse.cdt.ui.tests >Index: ui/org/eclipse/cdt/ui/tests/AutomatedSuite.java >=================================================================== >RCS file: /home/tools/org.eclipse.cdt/all/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/AutomatedSuite.java,v >retrieving revision 1.35 >diff -u -r1.35 AutomatedSuite.java >--- ui/org/eclipse/cdt/ui/tests/AutomatedSuite.java 3 Jul 2006 13:01:42 -0000 1.35 >+++ ui/org/eclipse/cdt/ui/tests/AutomatedSuite.java 15 Jul 2006 05:33:47 -0000 >@@ -15,6 +15,8 @@ > import junit.framework.TestSuite; > > import org.eclipse.cdt.ui.tests.text.CAutoIndentTest; >+import org.eclipse.cdt.ui.tests.text.CBreakIteratorTest; >+import org.eclipse.cdt.ui.tests.text.CWordIteratorTest; > import org.eclipse.cdt.ui.tests.text.NumberRuleTest; > import org.eclipse.cdt.ui.tests.text.contentassist.CompletionFailedTest_MemberReference_Arrow_Prefix2; > import org.eclipse.cdt.ui.tests.text.contentassist.CompletionTest_ArgumentType_NoPrefix; >@@ -136,6 +138,10 @@ > addTest( CSelectionTestsDOMIndexer.suite() ); > addTest( CPPSelectionTestsCTagsIndexer.suite() ); > addTest( CSelectionTestsCTagsIndexer.suite() ); >+ >+ // Break iterator tests. >+ addTest(CBreakIteratorTest.suite()); >+ addTest(CWordIteratorTest.suite()); > } > > } >Index: META-INF/MANIFEST.MF >=================================================================== >RCS file: /home/tools/org.eclipse.cdt/all/org.eclipse.cdt.ui.tests/META-INF/MANIFEST.MF,v >retrieving revision 1.5 >diff -u -r1.5 MANIFEST.MF >--- META-INF/MANIFEST.MF 24 May 2006 18:54:03 -0000 1.5 >+++ META-INF/MANIFEST.MF 15 Jul 2006 05:33:47 -0000 >@@ -32,6 +32,7 @@ > org.eclipse.compare, > org.eclipse.ui.console, > org.eclipse.core.expressions, >- org.eclipse.cdt.make.core >+ org.eclipse.cdt.make.core, >+ com.ibm.icu > Eclipse-LazyStart: true > Bundle-Vendor: Eclipse.org >Index: ui/org/eclipse/cdt/ui/tests/text/CBreakIteratorTest.java >=================================================================== >RCS file: ui/org/eclipse/cdt/ui/tests/text/CBreakIteratorTest.java >diff -N ui/org/eclipse/cdt/ui/tests/text/CBreakIteratorTest.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ ui/org/eclipse/cdt/ui/tests/text/CBreakIteratorTest.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,122 @@ >+/******************************************************************************* >+ * Copyright (c) 2000, 2005 IBM Corporation and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * IBM Corporation - initial API and implementation >+ * Sergey Prigogin, Google >+ *******************************************************************************/ >+package org.eclipse.cdt.ui.tests.text; >+ >+import junit.framework.Test; >+import junit.framework.TestSuite; >+ >+import org.eclipse.cdt.internal.ui.text.CBreakIterator; >+ >+ >+public class CBreakIteratorTest extends BreakIteratorTest { >+ >+ public static Test suite() { >+ return new TestSuite(CBreakIteratorTest.class); >+ } >+ >+ /* >+ * @see junit.framework.TestCase#setUp() >+ */ >+ protected void setUp() throws Exception { >+ fBreakIterator= new CBreakIterator(); >+ } >+ >+ public void testNext1() { >+ assertNextPositions("word word", new int[] { 4, 5, 9 }); >+ } >+ >+ public void testNext2() { >+ assertNextPositions("wordWord word", new int[] { 4, 8, 9, 13 }); >+ } >+ >+ public void testNextSpace() { >+ assertNextPositions(" word ", new int[] { 1, 5, 6 }); >+ } >+ >+ public void testNextParen() { >+ assertNextPositions("word(params)", new int[] { 4, 5, 11, 12 }); >+ } >+ >+ public void testNextLn() { >+ String s= new String("word \n" + >+ " word2"); >+ assertNextPositions(s, new int[] { 4, 5, 6, 8, 13 }); >+ } >+ >+ public void testMultiNextLn() { >+ String s= new String("word \n" + >+ "\n" + >+ "\n" + >+ " word2"); >+ assertNextPositions(s, new int[] { 4, 5, 6, 7, 8, 10, 15 }); >+ } >+ >+ public void testMultiNextLn2() { >+ String s= new String("word \r\n" + >+ "\r\n" + >+ "\r\n" + >+ " word2"); >+ assertNextPositions(s, new int[] { 4, 5, 7, 9, 11, 13, 18 }); >+ } >+ >+ public void testNextCamelCaseWord() { >+ String s= new String(" _isURLConnection_pool "); >+ assertNextPositions(s, new int[] { 3, 4, 6, 9, 20, 24, 27 }); >+ } >+ >+ public void testPrevious1() { >+ String s= new String("word word"); >+ assertPreviousPositions(s, new int[] { 0, 4, 5 }); >+ } >+ >+ public void testPrevious2() { >+ String s= new String("wordWord word"); >+ assertPreviousPositions(s, new int[] { 0, 4, 8, 9 }); >+ } >+ >+ public void testPreviousSpace() { >+ String s= new String(" word "); >+ assertPreviousPositions(s, new int[] { 1, 5 }); >+ } >+ >+ public void testPreviousParen() { >+ String s= new String("word(params)"); >+ assertPreviousPositions(s, new int[] { 0, 4, 5, 11 }); >+ } >+ >+ public void testPreviousLn() { >+ String s= new String("word \n" + >+ " word2"); >+ assertPreviousPositions(s, new int[] { 0, 4, 5, 6, 8 }); >+ } >+ >+ public void testMultiPreviousLn() { >+ String s= new String("word \n" + >+ "\n" + >+ "\n" + >+ " word2"); >+ assertPreviousPositions(s, new int[] { 0, 4, 5, 6, 7, 8, 10 }); >+ } >+ >+ public void testMultiPreviousLn2() { >+ String s= new String("word \r\n" + >+ "\r\n" + >+ "\r\n" + >+ " word2"); >+ assertPreviousPositions(s, new int[] { 0, 4, 5, 7, 9, 11, 13 }); >+ } >+ >+ public void testPreviousCamelCaseWord() { >+ String s= new String(" _isURLConnection_pool "); >+ assertPreviousPositions(s, new int[] { 0, 3, 4, 6, 9, 20, 24 }); >+ } >+} >Index: ui/org/eclipse/cdt/ui/tests/text/BreakIteratorTest.java >=================================================================== >RCS file: ui/org/eclipse/cdt/ui/tests/text/BreakIteratorTest.java >diff -N ui/org/eclipse/cdt/ui/tests/text/BreakIteratorTest.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ ui/org/eclipse/cdt/ui/tests/text/BreakIteratorTest.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,88 @@ >+/******************************************************************************* >+ * Copyright (c) 2000, 2006 IBM Corporation and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * IBM Corporation - initial API and implementation >+ * Sergey Prigogin, Google >+ *******************************************************************************/ >+package org.eclipse.cdt.ui.tests.text; >+ >+import com.ibm.icu.text.BreakIterator; >+ >+import junit.framework.TestCase; >+ >+ >+public class BreakIteratorTest extends TestCase { >+ >+ protected BreakIterator fBreakIterator; >+ >+ public void assertNextPositions(CharSequence ci, int position) { >+ assertNextPositions(ci, new int[] {position}); >+ } >+ >+ public void assertNextPositions(CharSequence ci, int[] positions) { >+ fBreakIterator.setText(ci.toString()); >+ >+ // test next() >+ for (int i = 0; i < positions.length; i++) { >+ int pos= fBreakIterator.next(); >+ assertEquals(positions[i], pos); >+ } >+ >+ // test following() >+ int idx= 0; >+ for (int i = 0; i < positions.length; i++) { >+ int position= positions[i]; >+ while (idx < position) { >+ if (!illegalPos(ci, idx)) >+ assertEquals(position, fBreakIterator.following(idx)); >+ idx++; >+ } >+ } >+ >+ } >+ >+ /** >+ * Check if we are in a multibyte delimiter >+ * @param idx >+ * @return >+ */ >+ private boolean illegalPos(CharSequence seq, int idx) { >+ String DELIMS= "\n\r"; >+ if (idx == 0 || idx == seq.length()) >+ return false; >+ char one= seq.charAt(idx - 1); >+ char two= seq.charAt(idx); >+ return one != two && DELIMS.indexOf(one) != -1 && DELIMS.indexOf(two) != -1; >+ } >+ >+ public void assertPreviousPositions(CharSequence ci, int position) { >+ assertPreviousPositions(ci, new int[] {position}); >+ } >+ >+ public void assertPreviousPositions(CharSequence ci, int[] positions) { >+ fBreakIterator.setText(ci.toString()); >+ fBreakIterator.last(); >+ >+ for (int i = positions.length - 1; i >= 0; i--) { >+ int pos= fBreakIterator.previous(); >+ assertEquals(positions[i], pos); >+ } >+ >+ // test preceding() >+ int idx= ci.length(); >+ for (int i = positions.length - 1; i >= 0; i--) { >+ int position= positions[i]; >+ while (idx > position) { >+ if (!illegalPos(ci, idx)) >+ assertEquals(position, fBreakIterator.preceding(idx)); >+ idx--; >+ } >+ } >+ } >+ >+} >Index: ui/org/eclipse/cdt/ui/tests/text/CWordIteratorTest.java >=================================================================== >RCS file: ui/org/eclipse/cdt/ui/tests/text/CWordIteratorTest.java >diff -N ui/org/eclipse/cdt/ui/tests/text/CWordIteratorTest.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ ui/org/eclipse/cdt/ui/tests/text/CWordIteratorTest.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,123 @@ >+/******************************************************************************* >+ * Copyright (c) 2000, 2005 IBM Corporation and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * IBM Corporation - initial API and implementation >+ * Sergey Prigogin, Google >+******************************************************************************/ >+package org.eclipse.cdt.ui.tests.text; >+ >+import junit.framework.Test; >+import junit.framework.TestSuite; >+ >+import org.eclipse.cdt.internal.ui.text.CWordIterator; >+ >+ >+public class CWordIteratorTest extends BreakIteratorTest { >+ >+ public static Test suite() { >+ return new TestSuite(CBreakIteratorTest.class); >+ } >+ >+ /* >+ * @see junit.framework.TestCase#setUp() >+ */ >+ protected void setUp() throws Exception { >+ fBreakIterator= new CWordIterator(); >+ } >+ >+ public void testNext1() { >+ assertNextPositions("word word", new int[] { 5, 9 }); >+ } >+ >+ public void testNext2() { >+ assertNextPositions("wordWord word", new int[] { 4, 9, 13 }); >+ } >+ >+ public void testNextSpace() { >+ assertNextPositions(" word ", new int[] { 1, 6 }); >+ } >+ >+ public void testNextParen() { >+ assertNextPositions("word(params)", new int[] { 4, 5, 11, 12 }); >+ } >+ >+ public void testNextLn() { >+ String s= new String("word \n" + >+ " word2"); >+ assertNextPositions(s, new int[] { 5, 6, 8, 13 }); >+ } >+ >+ public void testMultiNextLn() { >+ String s= new String("word \n" + >+ "\n" + >+ "\n" + >+ " word2"); >+ assertNextPositions(s, new int[] { 5, 6, 7, 8, 10, 15 }); >+ } >+ >+ public void testMultiNextLn2() { >+ String s= new String("word \r\n" + >+ "\r\n" + >+ "\r\n" + >+ " word2"); >+ assertNextPositions(s, new int[] { 5, 7, 9, 11, 13, 18 }); >+ } >+ >+ public void testNextCamelCaseWord() { >+ String s= new String(" _isURLConnection_pool "); >+ assertNextPositions(s, new int[] { 3, 4, 6, 9, 20, 27 }); >+ } >+ >+ public void testPrevious1() { >+ String s= new String("word word"); >+ assertPreviousPositions(s, new int[] { 0, 5 }); >+ } >+ >+ public void testPrevious2() { >+ String s= new String("wordWord word"); >+ assertPreviousPositions(s, new int[] { 0, 4, 9 }); >+ } >+ >+ public void testPreviousSpace() { >+ String s= new String(" word "); >+ assertPreviousPositions(s, new int[] { 1 }); >+ } >+ >+ public void testPreviousParen() { >+ String s= new String("word(params)"); >+ assertPreviousPositions(s, new int[] { 0, 4, 5, 11 }); >+ } >+ >+ public void testPreviousLn() { >+ String s= new String("word \n" + >+ " word2"); >+ assertPreviousPositions(s, new int[] { 0, 5, 6, 8 }); >+ } >+ >+ public void testMultiPreviousLn() { >+ String s= new String("word \n" + >+ "\n" + >+ "\n" + >+ " word2"); >+ assertPreviousPositions(s, new int[] { 0, 5, 6, 7, 8, 10 }); >+ } >+ >+ public void testMultiPreviousLn2() { >+ String s= new String("word \r\n" + >+ "\r\n" + >+ "\r\n" + >+ " word2"); >+ assertPreviousPositions(s, new int[] { 0, 5, 7, 9, 11, 13 }); >+ } >+ >+ public void testPreviousCamelCaseWord() { >+ String s= new String(" _isURLConnection_pool "); >+ assertPreviousPositions(s, new int[] { 0, 3, 4, 6, 9, 20 }); >+ } >+ >+}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Flags:
bjorn.freeman-benson
:
iplog+
Actions:
View
|
Diff
Attachments on
bug 140489
:
40558
|
43422
| 46330