The main goal of those patches is to fix bug 2068: [Bug 2068] Spellcheck correction of words with ligatures doubles initial character http://bugzilla.lyx.org/show_bug.cgi?id=2068
The 1.4 version does just that, but the 1.5 version does some cleanup in some code from CutAndPaste.C that was used in spell and find (and which should not have lived there). Comments welcome. * src/CutAndPaste.C (setSelectionRange, replaceWord): remove. (replaceSelectionWithString): select the new string after replacement; add a bool parameter indicating in which sense the selection is made. * src/lyxfind.C (replace): adapt to above changes. (find): comment out debug message. * src/frontends/controllers/ControlSpellchecker.C (isLetter): rename parameter. (nextWord): take a LCursor as parameter; set the selection over the word that has been found. (check): adapt to changes above (the length of the word is not necessarily the length of the selection -- fixes bug 2068). (replace): use cap::replaceSelectionWithString JMarc
Index: src/lyxfind.C =================================================================== --- src/lyxfind.C (revision 14684) +++ src/lyxfind.C (working copy) @@ -274,7 +274,7 @@ void find(BufferView * bv, FuncRequest c if (!bv || ev.action != LFUN_WORD_FIND) return; - lyxerr << "find called, cmd: " << ev << std::endl; + //lyxerr << "find called, cmd: " << ev << std::endl; // data is of the form // "<search> Index: src/frontends/controllers/ControlSpellchecker.C =================================================================== --- src/frontends/controllers/ControlSpellchecker.C (revision 14684) +++ src/frontends/controllers/ControlSpellchecker.C (working copy) @@ -140,11 +140,12 @@ bool isLetter(DocIterator const & cur) } -WordLangTuple nextWord(DocIterator & cur, ptrdiff_t & progress, - BufferParams & bp) +WordLangTuple nextWord(LCursor & cur, ptrdiff_t & progress) { + BufferParams const & bp = cur.bv().buffer()->params(); bool inword = false; bool ignoreword = false; + cur.resetAnchor(); string word, lang_code; while (cur.depth()) { @@ -152,6 +153,7 @@ WordLangTuple nextWord(DocIterator & cur if (!inword) { inword = true; ignoreword = false; + cur.resetAnchor(); word.clear(); lang_code = cur.paragraph().getFontSettings(bp, cur.pos()).language()->code(); } @@ -166,9 +168,10 @@ WordLangTuple nextWord(DocIterator & cur } } else { // !isLetter(cur) if (inword) - if (!word.empty() && !ignoreword) + if (!word.empty() && !ignoreword) { + cur.setSelection(); return WordLangTuple(word, lang_code); - else + } else inword = false; } @@ -189,7 +192,7 @@ void ControlSpellchecker::check() SpellBase::Result res = SpellBase::OK; - DocIterator cur = kernel().bufferview()->cursor(); + LCursor cur = kernel().bufferview()->cursor(); while (cur && cur.pos() && isLetter(cur)) { cur.backwardPos(); } @@ -202,11 +205,10 @@ void ControlSpellchecker::check() for (total = start; it; it.forwardPos()) ++total; - BufferParams & bufferparams = kernel().buffer().params(); exitEarly_ = false; while (res == SpellBase::OK || res == SpellBase::IGNORED_WORD) { - word_ = nextWord(cur, start, bufferparams); + word_ = nextWord(cur, start); // end of document if (getWord().empty()) { @@ -240,7 +242,7 @@ void ControlSpellchecker::check() lyxerr[Debug::GUI] << "Found word \"" << getWord() << "\"" << endl; - int const size = getWord().size(); + int const size = cur.selEnd().pos() - cur.selBegin().pos(); cur.pos() -= size; kernel().bufferview()->putSelectionAt(cur, size, false); // if we used a lfun like in find/replace, dispatch would do
Index: src/CutAndPaste.C =================================================================== --- src/CutAndPaste.C (revision 14694) +++ src/CutAndPaste.C (working copy) @@ -651,33 +651,19 @@ void pasteSelection(LCursor & cur, Error } -void setSelectionRange(LCursor & cur, pos_type length) -{ - LyXText * text = cur.text(); - BOOST_ASSERT(text); - if (!length) - return; - cur.resetAnchor(); - while (length--) - text->cursorRight(cur); - cur.setSelection(); -} - - // simple replacing. The font of the first selected character is used -void replaceSelectionWithString(LCursor & cur, string const & str) +void replaceSelectionWithString(LCursor & cur, string const & str, bool backwards) { - LyXText * text = cur.text(); - BOOST_ASSERT(text); recordUndo(cur); + DocIterator selbeg = cur.selectionBegin(); // Get font setting before we cut - pos_type pos = cur.selEnd().pos(); - Paragraph & par = text->getPar(cur.selEnd().pit()); LyXFont const font = - par.getFontSettings(cur.buffer().params(), cur.selBegin().pos()); + selbeg.paragraph().getFontSettings(cur.buffer().params(), selbeg.pos()); // Insert the new string + pos_type pos = cur.selEnd().pos(); + Paragraph & par = cur.selEnd().paragraph(); string::const_iterator cit = str.begin(); string::const_iterator end = str.end(); for (; cit != end; ++cit, ++pos) @@ -685,6 +671,13 @@ void replaceSelectionWithString(LCursor // Cut the selection cutSelection(cur, true, false); + + // select the replacement + if (backwards) { + selbeg.pos() += str.length(); + cur.setSelection(selbeg, -str.length()); + } else + cur.setSelection(selbeg, str.length()); } @@ -695,21 +688,6 @@ void replaceSelection(LCursor & cur) } -// only used by the spellchecker -void replaceWord(LCursor & cur, string const & replacestring) -{ - LyXText * text = cur.text(); - BOOST_ASSERT(text); - - replaceSelectionWithString(cur, replacestring); - setSelectionRange(cur, replacestring.length()); - - // Go back so that replacement string is also spellchecked - for (string::size_type i = 0; i < replacestring.length() + 1; ++i) - text->cursorLeft(cur); -} - - void eraseSelection(LCursor & cur) { //lyxerr << "LCursor::eraseSelection begin: " << cur << endl; Index: src/CutAndPaste.h =================================================================== --- src/CutAndPaste.h (revision 14694) +++ src/CutAndPaste.h (working copy) @@ -41,13 +41,12 @@ std::string getSelection(Buffer const & /// void cutSelection(LCursor & cur, bool doclear, bool realcut); -/** - * Sets the selection from the current cursor position to length - * characters to the right. No safety checks. +/* Replace using the font of the first selected character and select + * the new string. When \c backwards == false, set anchor before + * cursor; otherwise set cursor before anchor. */ -void setSelectionRange(LCursor & cur, lyx::pos_type length); -/// simply replace using the font of the first selected character -void replaceSelectionWithString(LCursor & cur, std::string const & str); +void replaceSelectionWithString(LCursor & cur, std::string const & str, + bool backwards); /// replace selection helper void replaceSelection(LCursor & cur); @@ -71,9 +70,6 @@ void switchBetweenClasses(lyx::textclass lyx::textclass_type c2, InsetText & in, ErrorList &); -// only used by the spellchecker -void replaceWord(LCursor & cur, std::string const & replacestring); - /// std::string grabSelection(LCursor const & cur); /// Index: src/frontends/controllers/ControlSpellchecker.C =================================================================== --- src/frontends/controllers/ControlSpellchecker.C (revision 14694) +++ src/frontends/controllers/ControlSpellchecker.C (working copy) @@ -127,24 +127,25 @@ void ControlSpellchecker::clearParams() namespace { -bool isLetter(DocIterator const & cur) +bool isLetter(DocIterator const & dit) { - return cur.inTexted() - && cur.inset().allowSpellCheck() - && cur.pos() != cur.lastpos() - && (cur.paragraph().isLetter(cur.pos()) + return dit.inTexted() + && dit.inset().allowSpellCheck() + && dit.pos() != dit.lastpos() + && (dit.paragraph().isLetter(dit.pos()) // We want to pass the ' and escape chars to ispell || contains(lyxrc.isp_esc_chars + '\'', - cur.paragraph().getChar(cur.pos()))) - && !isDeletedText(cur.paragraph(), cur.pos()); + dit.paragraph().getChar(dit.pos()))) + && !isDeletedText(dit.paragraph(), dit.pos()); } -WordLangTuple nextWord(DocIterator & cur, ptrdiff_t & progress, - BufferParams & bp) +WordLangTuple nextWord(LCursor & cur, ptrdiff_t & progress) { + BufferParams const & bp = cur.bv().buffer()->params(); bool inword = false; bool ignoreword = false; + cur.resetAnchor(); string word, lang_code; while (cur.depth()) { @@ -152,6 +153,7 @@ WordLangTuple nextWord(DocIterator & cur if (!inword) { inword = true; ignoreword = false; + cur.resetAnchor(); word.clear(); lang_code = cur.paragraph().getFontSettings(bp, cur.pos()).language()->code(); } @@ -166,9 +168,10 @@ WordLangTuple nextWord(DocIterator & cur } } else { // !isLetter(cur) if (inword) - if (!word.empty() && !ignoreword) + if (!word.empty() && !ignoreword) { + cur.setSelection(); return WordLangTuple(word, lang_code); - else + } else inword = false; } @@ -189,7 +192,7 @@ void ControlSpellchecker::check() SpellBase::Result res = SpellBase::OK; - DocIterator cur = kernel().bufferview()->cursor(); + LCursor cur = kernel().bufferview()->cursor(); while (cur && cur.pos() && isLetter(cur)) { cur.backwardPos(); } @@ -202,11 +205,10 @@ void ControlSpellchecker::check() for (total = start; it; it.forwardPos()) ++total; - BufferParams & bufferparams = kernel().buffer().params(); exitEarly_ = false; while (res == SpellBase::OK || res == SpellBase::IGNORED_WORD) { - word_ = nextWord(cur, start, bufferparams); + word_ = nextWord(cur, start); // end of document if (getWord().empty()) { @@ -240,7 +242,7 @@ void ControlSpellchecker::check() lyxerr[Debug::GUI] << "Found word \"" << getWord() << "\"" << endl; - int const size = getWord().size(); + int const size = cur.selEnd().pos() - cur.selBegin().pos(); cur.pos() -= size; kernel().bufferview()->putSelectionAt(cur, size, false); // if we used a lfun like in find/replace, dispatch would do @@ -298,7 +300,7 @@ void ControlSpellchecker::replace(string lyxerr[Debug::GUI] << "ControlSpellchecker::replace(" << replacement << ")" << std::endl; BufferView & bufferview = *kernel().bufferview(); - cap::replaceWord(bufferview.cursor(), replacement); + cap::replaceSelectionWithString(bufferview.cursor(), replacement, true); kernel().buffer().markDirty(); bufferview.update(); // fix up the count Index: src/lyxfind.C =================================================================== --- src/lyxfind.C (revision 14694) +++ src/lyxfind.C (working copy) @@ -226,9 +226,7 @@ int replace(BufferView * bv, string cons return 0; LCursor & cur = bv->cursor(); - lyx::cap::replaceSelectionWithString(cur, replacestr); - lyx::cap::setSelectionRange(cur, replacestr.length()); - cur.top() = fw ? cur.selEnd() : cur.selBegin(); + lyx::cap::replaceSelectionWithString(cur, replacestr, fw); bv->buffer()->markDirty(); find(bv, searchstr, cs, mw, fw); bv->update(); @@ -274,7 +272,7 @@ void find(BufferView * bv, FuncRequest c if (!bv || ev.action != LFUN_WORD_FIND) return; - lyxerr << "find called, cmd: " << ev << std::endl; + //lyxerr << "find called, cmd: " << ev << std::endl; // data is of the form // "<search>