diff options
author | nyamatongwe <unknown> | 2011-01-10 12:08:49 +1100 |
---|---|---|
committer | nyamatongwe <unknown> | 2011-01-10 12:08:49 +1100 |
commit | 7a55b6d47b75b665100a04ca16e6a210d436d235 (patch) | |
tree | 3501681428732495b06b4321cbb0c8d977e9e3ec /src | |
parent | b5f28ae72e7d19b28bb190189ba78a54ad9976a0 (diff) | |
download | scintilla-mirror-7a55b6d47b75b665100a04ca16e6a210d436d235.tar.gz |
Fixing double-click inside word selecting non-word characters. Bug #3111174.
A double-click on a visible character always selects that character and the word it is in.
From Jordan Russell.
Diffstat (limited to 'src')
-rw-r--r-- | src/Document.h | 2 | ||||
-rw-r--r-- | src/Editor.cxx | 70 | ||||
-rw-r--r-- | src/Editor.h | 4 |
3 files changed, 62 insertions, 14 deletions
diff --git a/src/Document.h b/src/Document.h index 78f00a766..ecdf5ff65 100644 --- a/src/Document.h +++ b/src/Document.h @@ -357,6 +357,7 @@ public: const WatcherWithUserData *GetWatchers() const { return watchers; } int GetLenWatchers() const { return lenWatchers; } + CharClassify::cc WordCharClass(unsigned char ch); bool IsWordPartSeparator(char ch); int WordPartLeft(int pos); int WordPartRight(int pos); @@ -368,7 +369,6 @@ public: int BraceMatch(int position, int maxReStyle); private: - CharClassify::cc WordCharClass(unsigned char ch); bool IsWordStartAt(int pos); bool IsWordEndAt(int pos); bool IsWordAt(int start, int end); diff --git a/src/Editor.cxx b/src/Editor.cxx index fb66c8a86..7f51ced64 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -133,6 +133,9 @@ Editor::Editor() { lastXChosen = 0; lineAnchor = 0; originalAnchorPos = 0; + wordSelectAnchorStartPos = 0; + wordSelectAnchorEndPos = 0; + wordSelectInitialCaretPos = -1; primarySelection = true; @@ -5853,6 +5856,30 @@ void Editor::LineSelection(int lineCurrent_, int lineAnchor_) { } } +void Editor::WordSelection(int pos) { + if (pos < wordSelectAnchorStartPos) { + // Extend backward to the word containing pos. + // Skip ExtendWordSelect if the line is empty or if pos is after the last character. + // This ensures that a series of empty lines isn't counted as a single "word". + if (!pdoc->IsLineEndPosition(pos)) + pos = pdoc->ExtendWordSelect(pdoc->MovePositionOutsideChar(pos + 1, 1), -1); + SetSelection(pos, wordSelectAnchorEndPos); + } else if (pos > wordSelectAnchorEndPos) { + // Extend forward to the word containing the character to the left of pos. + // Skip ExtendWordSelect if the line is empty or if pos is the first position on the line. + // This ensures that a series of empty lines isn't counted as a single "word". + if (pos > pdoc->LineStart(pdoc->LineFromPosition(pos))) + pos = pdoc->ExtendWordSelect(pdoc->MovePositionOutsideChar(pos - 1, -1), 1); + SetSelection(pos, wordSelectAnchorStartPos); + } else { + // Select only the anchored word + if (pos >= originalAnchorPos) + SetSelection(wordSelectAnchorEndPos, wordSelectAnchorStartPos); + else + SetSelection(wordSelectAnchorStartPos, wordSelectAnchorEndPos); + } +} + void Editor::DwellEnd(bool mouseMoved) { if (mouseMoved) ticksToDwell = dwellDelay; @@ -5914,13 +5941,33 @@ void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, b } if (selectionType == selWord) { - if (sel.MainCaret() >= originalAnchorPos) { // Moved forward - SetSelection(pdoc->ExtendWordSelect(sel.MainCaret(), 1), - pdoc->ExtendWordSelect(originalAnchorPos, -1)); - } else { // Moved backward - SetSelection(pdoc->ExtendWordSelect(sel.MainCaret(), -1), - pdoc->ExtendWordSelect(originalAnchorPos, 1)); + int charPos = originalAnchorPos; + if (sel.MainCaret() == originalAnchorPos) { + charPos = PositionFromLocation(pt, false, true); + charPos = MovePositionOutsideChar(charPos, -1); + } + + int startWord, endWord; + if ((sel.MainCaret() >= originalAnchorPos) && !pdoc->IsLineEndPosition(charPos)) { + startWord = pdoc->ExtendWordSelect(pdoc->MovePositionOutsideChar(charPos + 1, 1), -1); + endWord = pdoc->ExtendWordSelect(charPos, 1); + } else { + // Selecting backwards, or anchor beyond last character on line. In these cases, + // we select the word containing the character to the *left* of the anchor. + if (charPos > pdoc->LineStart(pdoc->LineFromPosition(charPos))) { + startWord = pdoc->ExtendWordSelect(charPos, -1); + endWord = pdoc->ExtendWordSelect(startWord, 1); + } else { + // Anchor at start of line; select nothing to begin with. + startWord = charPos; + endWord = charPos; + } } + + wordSelectAnchorStartPos = startWord; + wordSelectAnchorEndPos = endWord; + wordSelectInitialCaretPos = sel.MainCaret(); + WordSelection(wordSelectInitialCaretPos); } else if (selectionType == selLine) { lineAnchor = LineFromLocation(pt); SetSelection(pdoc->LineStart(lineAnchor + 1), pdoc->LineStart(lineAnchor)); @@ -6103,7 +6150,7 @@ void Editor::ButtonMove(Point pt) { } } else if (selectionType == selWord) { // Continue selecting by word - if (movePos.Position() == originalAnchorPos) { // Didn't move + if (movePos.Position() == wordSelectInitialCaretPos) { // Didn't move // No need to do anything. Previously this case was lumped // in with "Moved forward", but that can be harmful in this // case: a handler for the NotifyDoubleClick re-adjusts @@ -6113,12 +6160,9 @@ void Editor::ButtonMove(Point pt) { // the ButtonMove() called via Tick() for auto-scrolling // could result in the fancier word selection adjustment // being unmade. - } else if (movePos.Position() > originalAnchorPos) { // Moved forward - SetSelection(pdoc->ExtendWordSelect(movePos.Position(), 1), - pdoc->ExtendWordSelect(originalAnchorPos, -1)); - } else { // Moved backward - SetSelection(pdoc->ExtendWordSelect(movePos.Position(), -1), - pdoc->ExtendWordSelect(originalAnchorPos, 1)); + } else { + wordSelectInitialCaretPos = -1; + WordSelection(movePos.Position()); } } else { // Continue selecting by line diff --git a/src/Editor.h b/src/Editor.h index a618e1e40..97af7b089 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -201,6 +201,9 @@ protected: // ScintillaBase subclass needs access to much of Editor int lastXChosen; int lineAnchor; int originalAnchorPos; + int wordSelectAnchorStartPos; + int wordSelectAnchorEndPos; + int wordSelectInitialCaretPos; int targetStart; int targetEnd; int searchFlags; @@ -481,6 +484,7 @@ protected: // ScintillaBase subclass needs access to much of Editor bool PointInSelection(Point pt); bool PointInSelMargin(Point pt); void LineSelection(int lineCurrent_, int lineAnchor_); + void WordSelection(int pos); void DwellEnd(bool mouseMoved); void MouseLeave(); virtual void ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt); |