diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CDoubleClickSelector.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CDoubleClickSelector.java index d7e37c17e37..d74f6083529 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CDoubleClickSelector.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CDoubleClickSelector.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000 2006 IBM Corporation and others. + * Copyright (c) 2000, 2007 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 @@ -12,7 +12,6 @@ *******************************************************************************/ package org.eclipse.cdt.internal.ui.text; -import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextDoubleClickStrategy; @@ -23,111 +22,35 @@ import org.eclipse.jface.text.ITextViewer; */ public class CDoubleClickSelector implements ITextDoubleClickStrategy { - protected ITextViewer fText; - protected int fPos; - protected int fStartPos; - protected int fEndPos; - private CPairMatcher fPairMatcher; - - - protected static char[] fgBrackets= {'{', '}', '(', ')', '[', ']', '"', '"'}; + protected static char[] fgBrackets= {'{', '}', '(', ')', '[', ']', '<', '>'}; + private CPairMatcher fPairMatcher= new CPairMatcher(fgBrackets); public CDoubleClickSelector() { super(); - fPairMatcher= new CPairMatcher(fgBrackets); } - - /** - * @see ITextDoubleClickStrategy#doubleClicked + /* + * @see org.eclipse.jface.text.ITextDoubleClickStrategy#doubleClicked(org.eclipse.jface.text.ITextViewer) */ - public void doubleClicked(ITextViewer text) { - fPos= text.getSelectedRange().x; + public void doubleClicked(ITextViewer textViewer) { + int offset= textViewer.getSelectedRange().x; - - if (fPos < 0) + if (offset < 0) return; + IDocument document= textViewer.getDocument(); - fText= text; - - - if (!selectBracketBlock()) - selectWord(); - - fText= null; - } - - - protected boolean matchBracketsAt() { - IRegion region= fPairMatcher.match(fText.getDocument(), fPos); - if (region != null && region.getLength() > 0) { - fStartPos= region.getOffset(); - fEndPos= fStartPos + region.getLength() - 1; - return true; - } - return false; - } - - - protected boolean matchWord() { - IDocument doc= fText.getDocument(); - try { - int pos= fPos; - char c; - - - while (pos >= 0) { - c= doc.getChar(pos); - if (!Character.isJavaIdentifierPart(c)) - break; - --pos; - } - fStartPos= pos; - - - pos= fPos; - int length= doc.getLength(); - - - while (pos < length) { - c= doc.getChar(pos); - if (!Character.isJavaIdentifierPart(c)) - break; - ++pos; - } - fEndPos= pos; - - - return true; - - - } catch (BadLocationException x) { - } - return false; - } - - - protected boolean selectBracketBlock() { - if (matchBracketsAt()) { - if (fStartPos == fEndPos) - fText.setSelectedRange(fStartPos, 0); - else - fText.setSelectedRange(fStartPos + 1, fEndPos - fStartPos - 1); - - - return true; - } - return false; - } - - - protected void selectWord() { - if (matchWord()) { - if (fStartPos == fEndPos) - fText.setSelectedRange(fStartPos, 0); - else - fText.setSelectedRange(fStartPos + 1, fEndPos - fStartPos - 1); + IRegion region= fPairMatcher.match(document, offset); + if (region != null && region.getLength() >= 2) { + textViewer.setSelectedRange(region.getOffset() + 1, region.getLength() - 2); + } else { + region= selectWord(document, offset); + textViewer.setSelectedRange(region.getOffset(), region.getLength()); } } + + protected IRegion selectWord(IDocument document, int offset) { + return CWordFinder.findWord(document, offset); + } + } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CPairMatcher.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CPairMatcher.java index cecf3e03c84..4444f1d69b1 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CPairMatcher.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CPairMatcher.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000 2006 IBM Corporation and others. + * Copyright (c) 2000, 2007 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 @@ -12,132 +12,17 @@ *******************************************************************************/ package org.eclipse.cdt.internal.ui.text; -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.IRegion; -import org.eclipse.jface.text.Region; -import org.eclipse.jface.text.TextUtilities; -import org.eclipse.jface.text.source.ICharacterPairMatcher; +import org.eclipse.jface.text.source.DefaultCharacterPairMatcher; import org.eclipse.cdt.ui.text.ICPartitions; /** * Helper class for match pairs of characters. */ -public class CPairMatcher implements ICharacterPairMatcher { - - protected char[] fPairs; - protected IDocument fDocument; - protected int fOffset; - - protected int fStartPos; - protected int fEndPos; - protected int fAnchor; +public class CPairMatcher extends DefaultCharacterPairMatcher { public CPairMatcher(char[] pairs) { - fPairs = pairs; + super(pairs, ICPartitions.C_PARTITIONING); } - /* - * @see org.eclipse.jface.text.source.ICharacterPairMatcher#match(org.eclipse.jface.text.IDocument, int) - */ - public IRegion match(IDocument document, int offset) { - - fOffset = offset; - - if (fOffset < 0) - return null; - - fDocument = document; - - if (matchPairsAt() && fStartPos != fEndPos) - return new Region(fStartPos, fEndPos - fStartPos + 1); - - return null; - } - - /* - * @see org.eclipse.jface.text.source.ICharacterPairMatcher#getAnchor() - */ - public int getAnchor() { - return fAnchor; - } - - /* - * @see org.eclipse.jface.text.source.ICharacterPairMatcher#clear() - */ - public void clear() { - } - - /* - * @see org.eclipse.jface.text.source.ICharacterPairMatcher#dispose() - */ - public void dispose() { - clear(); - fDocument = null; - } - - protected boolean matchPairsAt() { - - int i; - int pairIndex1= fPairs.length; - int pairIndex2= fPairs.length; - - fStartPos= -1; - fEndPos= -1; - - // get the chars preceding and following the start position - try { - - char prevChar= fDocument.getChar(Math.max(fOffset - 1, 0)); - - // search for opening peer character next to the activation point - for (i= 0; i < fPairs.length; i= i + 2) { - if (prevChar == fPairs[i]) { - fStartPos= fOffset - 1; - pairIndex1= i; - } - } - - // search for closing peer character next to the activation point - for (i= 1; i < fPairs.length; i= i + 2) { - if (prevChar == fPairs[i]) { - fEndPos= fOffset - 1; - pairIndex2= i; - } - } - - if (fEndPos > -1) { - fAnchor= RIGHT; - fStartPos= searchForOpeningPeer(fEndPos, fPairs[pairIndex2 - 1], fPairs[pairIndex2], fDocument); - if (fStartPos > -1) - return true; - fEndPos= -1; - } else if (fStartPos > -1) { - fAnchor= LEFT; - fEndPos= searchForClosingPeer(fStartPos, fPairs[pairIndex1], fPairs[pairIndex1 + 1], fDocument); - if (fEndPos > -1) - return true; - fStartPos= -1; - } - - } catch (BadLocationException x) { - } - - return false; - } - - - protected int searchForClosingPeer(int offset, char openingPeer, char closingPeer, IDocument document) throws BadLocationException { - CHeuristicScanner scanner= new CHeuristicScanner(document, ICPartitions.C_PARTITIONING, TextUtilities.getContentType(document, ICPartitions.C_PARTITIONING, offset, false)); - return scanner.findClosingPeer(offset + 1, openingPeer, closingPeer); - } - - protected int searchForOpeningPeer(int offset, char openingPeer, char closingPeer, IDocument document) throws BadLocationException { - CHeuristicScanner scanner= new CHeuristicScanner(document, ICPartitions.C_PARTITIONING, TextUtilities.getContentType(document, ICPartitions.C_PARTITIONING, offset, false)); - int peer= scanner.findOpeningPeer(offset - 1, openingPeer, closingPeer); - if (peer == CHeuristicScanner.NOT_FOUND) - return -1; - return peer; - } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java index 23de0133e7d..f3896552928 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java @@ -25,6 +25,7 @@ import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.AbstractInformationControlManager; import org.eclipse.jface.text.DefaultInformationControl; +import org.eclipse.jface.text.DefaultTextDoubleClickStrategy; import org.eclipse.jface.text.IAutoEditStrategy; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IInformationControl; @@ -451,6 +452,14 @@ public class CSourceViewerConfiguration extends TextSourceViewerConfiguration { * @see SourceViewerConfiguration#getDoubleClickStrategy(ISourceViewer, String) */ public ITextDoubleClickStrategy getDoubleClickStrategy(ISourceViewer sourceViewer, String contentType) { + if (ICPartitions.C_MULTI_LINE_COMMENT.equals(contentType) || + ICPartitions.C_SINGLE_LINE_COMMENT.equals(contentType)) + return new DefaultTextDoubleClickStrategy(); + else if (ICPartitions.C_STRING.equals(contentType) || + ICPartitions.C_CHARACTER.equals(contentType)) + return new CStringDoubleClickSelector(getConfiguredDocumentPartitioning(sourceViewer)); + else if (ICPartitions.C_PREPROCESSOR.equals(contentType)) + return new CStringDoubleClickSelector(getConfiguredDocumentPartitioning(sourceViewer), new CDoubleClickSelector()); return new CDoubleClickSelector(); } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CStringDoubleClickSelector.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CStringDoubleClickSelector.java new file mode 100644 index 00000000000..624846c332d --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CStringDoubleClickSelector.java @@ -0,0 +1,109 @@ +/******************************************************************************* + * Copyright (c) 2007 Wind River Systems, Inc. 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: + * Anton Leherbauer (Wind River Systems) - initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.internal.ui.text; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextDoubleClickStrategy; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.ITypedRegion; +import org.eclipse.jface.text.Region; +import org.eclipse.jface.text.TextUtilities; + +import org.eclipse.cdt.ui.text.ICPartitions; + +import org.eclipse.cdt.internal.ui.editor.CDocumentSetupParticipant; + +/** + * Double click strategy aware of string and character syntax rules. + * + * @since 4.0 + */ +public class CStringDoubleClickSelector extends CDoubleClickSelector { + + private String fPartitioning; + private ITextDoubleClickStrategy fFallbackStrategy; + + /** + * Creates a new string double click selector for the given document partitioning. + * + * @param partitioning the document partitioning + */ + public CStringDoubleClickSelector(String partitioning) { + this(partitioning, null); + } + + /** + * Creates a new string double click selector for the given document partitioning. + * + * @param partitioning the document partitioning + * @param doubleClickStrategy the fallback double click strategy + */ + public CStringDoubleClickSelector(String partitioning, + ITextDoubleClickStrategy doubleClickStrategy) { + fPartitioning= partitioning; + fFallbackStrategy= doubleClickStrategy; + } + + /* + * @see ITextDoubleClickStrategy#doubleClicked(ITextViewer) + */ + public void doubleClicked(ITextViewer textViewer) { + int offset= textViewer.getSelectedRange().x; + + if (offset < 0) + return; + + IDocument document= textViewer.getDocument(); + + IRegion region= matchString(document, offset); + if (region != null) { + if (region.getLength() >= 2) { + textViewer.setSelectedRange(region.getOffset() + 1, region.getLength() - 2); + } + } else if (fFallbackStrategy != null) { + fFallbackStrategy.doubleClicked(textViewer); + } else { + region= selectWord(document, offset); + if (region != null) { + textViewer.setSelectedRange(region.getOffset(), region.getLength()); + } + } + } + + private IRegion matchString(IDocument document, int offset) { + try { + if ((document.getChar(offset) == '"') || (document.getChar(offset) == '\'') || + (document.getChar(offset - 1) == '"') || (document.getChar(offset - 1) == '\'')) + { + ITypedRegion region= TextUtilities.getPartition(document, fPartitioning, offset, true); + // little hack: in case this strategy is used in preprocessor partitions, the string + // partition inside the preprocessor partition must be computed in an extra step + if (ICPartitions.C_PREPROCESSOR.equals(region.getType())) { + String ppDirective= document.get(region.getOffset(), region.getLength()); + int hashIdx= ppDirective.indexOf('#'); + document= new Document(ppDirective.substring(hashIdx+1)); + new CDocumentSetupParticipant().setup(document); + int delta= region.getOffset() + hashIdx + 1; + region= TextUtilities.getPartition(document, fPartitioning, offset - delta, true); + return new Region(region.getOffset() + delta, region.getLength()); + } + return region; + } + } catch (BadLocationException e) { + } + + return null; + } +}