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>