X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FParagraph.cpp;h=d44d0473e11f7ad8384429d5e82ace4b794040db;hb=0fd75fefc4aa1816f8d5a72ed0e30f8accdd0bfc;hp=b03766406453e2cd8af57e8df4f36465c2923638;hpb=f94e6274a99855ee39fc88de39c4ccb65440d8a7;p=lyx.git diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp index b037664064..d44d0473e1 100644 --- a/src/Paragraph.cpp +++ b/src/Paragraph.cpp @@ -51,6 +51,7 @@ #include "insets/InsetBibitem.h" #include "insets/InsetLabel.h" +#include "insets/InsetSpecialChar.h" #include "support/debug.h" #include "support/docstring_list.h" @@ -153,6 +154,12 @@ public: needsRefresh(pos); } + void refreshLast(pos_type pos) + { + if (pos < refresh_.last) + refresh_.last = pos; + } + SpellChecker::Result getState(pos_type pos) const { SpellChecker::Result result = SpellChecker::WORD_OK; @@ -333,14 +340,16 @@ public: /// match a string against a particular point in the paragraph bool isTextAt(string const & str, pos_type pos) const; - /// a vector of inset positions - typedef vector Positions; - typedef Positions::const_iterator PositionsIterator; + /// a vector of speller skip positions + typedef vector SkipPositions; + typedef SkipPositions::const_iterator SkipPositionsIterator; + void appendSkipPosition(SkipPositions & skips, pos_type const pos) const; + Language * getSpellLanguage(pos_type const from) const; Language * locateSpellRange(pos_type & from, pos_type & to, - Positions & softbreaks) const; + SkipPositions & skips) const; bool hasSpellerChange() const { SpellChecker::ChangeNumber speller_change_number = 0; @@ -391,22 +400,23 @@ public: last = endpos; } - int countSoftbreaks(PositionsIterator & it, PositionsIterator const et, + int countSkips(SkipPositionsIterator & it, SkipPositionsIterator const et, int & start) const { - int numbreaks = 0; - while (it != et && *it < start) { - ++start; - ++numbreaks; + int numskips = 0; + while (it != et && it->first < start) { + int skip = it->last - it->first + 1; + start += skip; + numskips += skip; ++it; } - return numbreaks; + return numskips; } void markMisspelledWords(pos_type const & first, pos_type const & last, SpellChecker::Result result, docstring const & word, - Positions const & softbreaks); + SkipPositions const & skips); InsetCode ownerCode() const { @@ -748,6 +758,8 @@ bool Paragraph::eraseChar(pos_type pos, bool trackChanges) if (!change.changed() || (change.inserted() && !change.currentAuthor())) { setChange(pos, Change(Change::DELETED)); + // request run of spell checker + requestSpellCheck(pos); return false; } @@ -779,6 +791,7 @@ bool Paragraph::eraseChar(pos_type pos, bool trackChanges) // Update list of misspelled positions d->speller_state_.decreasePosAfterPos(pos); + d->speller_state_.refreshLast(size()); return true; } @@ -1099,7 +1112,7 @@ void Paragraph::Private::latexInset(BufferParams const & bparams, texrow.start(owner_->id(), i + 1); column = 0; } else { - column += os.tellp() - len; + column += (unsigned int)(os.tellp() - len); } if (owner_->isDeleted(i)) @@ -2356,12 +2369,16 @@ void Paragraph::latex(BufferParams const & bparams, open_font = false; } + string const running_lang = runparams.use_polyglossia ? + running_font.language()->polyglossia() : running_font.language()->babel(); // close babel's font environment before opening CJK. - if (!running_font.language()->babel().empty() && + string const lang_end_command = runparams.use_polyglossia ? + "\\end{$$lang}" : lyxrc.language_command_end; + if (!running_lang.empty() && font.language()->encoding()->package() == Encoding::CJK) { - string end_tag = subst(lyxrc.language_command_end, + string end_tag = subst(lang_end_command, "$$lang", - running_font.language()->babel()); + running_lang); os << from_ascii(end_tag); column += end_tag.length(); } @@ -2499,7 +2516,7 @@ void Paragraph::latex(BufferParams const & bparams, if (allowcust && d->endTeXParParams(bparams, os, texrow, runparams) && runparams.encoding != prev_encoding) { runparams.encoding = prev_encoding; - if (!bparams.useXetex) + if (!runparams.isFullUnicode()) os << setEncoding(prev_encoding->iconvName()); } @@ -2713,13 +2730,9 @@ docstring Paragraph::simpleLyXHTMLOnePar(Buffer const & buf, Inset const * inset = getInset(i); if (inset) { - InsetCommand const * ic = inset->asInsetCommand(); - InsetLayout const & il = inset->getLayout(); - InsetMath const * im = inset->asInsetMath(); - if (!runparams.for_toc - || im || il.isInToc() || (ic && ic->isInToc())) { + if (!runparams.for_toc || inset->isInToc()) { OutputParams np = runparams; - if (!il.htmlisblock()) + if (!inset->getLayout().htmlisblock()) np.html_in_par = true; retval += inset->xhtml(xs, np); } @@ -2746,7 +2759,7 @@ docstring Paragraph::simpleLyXHTMLOnePar(Buffer const & buf, // We don't want to escape the entities. Note that // it is safe to do this, since str can otherwise // only be "-". E.g., it can't be "<". - xs << XHTMLStream::NextRaw() << str; + xs << XHTMLStream::ESCAPE_NONE << str; } else xs << c; } @@ -2891,6 +2904,8 @@ docstring Paragraph::asString(pos_type beg, pos_type end, int options) const os << d->params_.labelString() << ' '; for (pos_type i = beg; i < end; ++i) { + if ((options & AS_STR_SKIPDELETE) && isDeleted(i)) + continue; char_type const c = d->text_[i]; if (isPrintable(c) || c == '\t' || (c == '\n' && (options & AS_STR_NEWLINES))) @@ -3086,8 +3101,8 @@ int Paragraph::checkBiblio(Buffer const & buffer) InsetList::iterator end = d->insetlist_.end(); for (; it != end; ++it) if (it->inset->lyxCode() == BIBITEM_CODE - && it->pos > 0) { - InsetBibitem * olditem = static_cast(it->inset); + && it->pos > 0) { + InsetCommand * olditem = it->inset->asInsetCommand(); oldkey = olditem->getParam("key"); oldlabel = olditem->getParam("label"); erasedInsetPosition = it->pos; @@ -3103,8 +3118,7 @@ int Paragraph::checkBiblio(Buffer const & buffer) // There was an InsetBibitem at the beginning and we did have to // erase one. So we give its properties to the beginning inset. if (hasbibitem) { - InsetBibitem * inset = - static_cast(d->insetlist_.begin()->inset); + InsetCommand * inset = d->insetlist_.begin()->inset->asInsetCommand(); if (!oldkey.empty()) inset->setParam("key", oldkey); inset->setParam("label", oldlabel); @@ -3119,7 +3133,7 @@ int Paragraph::checkBiblio(Buffer const & buffer) if (!oldkey.empty()) inset->setParam("key", oldkey); inset->setParam("label", oldlabel); - insertInset(0, static_cast(inset), + insertInset(0, inset, Change(track_changes ? Change::INSERTED : Change::UNCHANGED)); return 1; @@ -3249,36 +3263,44 @@ void Paragraph::changeCase(BufferParams const & bparams, pos_type pos, } -bool Paragraph::find(docstring const & str, bool cs, bool mw, - pos_type pos, bool del) const +int Paragraph::find(docstring const & str, bool cs, bool mw, + pos_type start_pos, bool del) const { + pos_type pos = start_pos; int const strsize = str.length(); int i = 0; pos_type const parsize = d->text_.size(); - for (i = 0; pos + i < parsize; ++i) { - if (i >= strsize) - break; - if (cs && str[i] != d->text_[pos + i]) + for (i = 0; i < strsize && pos < parsize; ++i, ++pos) { + // Ignore ligature break and hyphenation chars while searching + while (pos < parsize - 1 && isInset(pos)) { + const InsetSpecialChar *isc = dynamic_cast(getInset(pos)); + if (isc == 0 + || (isc->kind() != InsetSpecialChar::HYPHENATION + && isc->kind() != InsetSpecialChar::LIGATURE_BREAK)) + break; + pos++; + } + if (cs && str[i] != d->text_[pos]) break; - if (!cs && uppercase(str[i]) != uppercase(d->text_[pos + i])) + if (!cs && uppercase(str[i]) != uppercase(d->text_[pos])) break; - if (!del && isDeleted(pos + i)) + if (!del && isDeleted(pos)) break; } if (i != strsize) - return false; + return 0; // if necessary, check whether string matches word if (mw) { - if (pos > 0 && !isWordSeparator(pos - 1)) - return false; - if (pos + strsize < parsize - && !isWordSeparator(pos + strsize)) - return false; + if (start_pos > 0 && !isWordSeparator(start_pos - 1)) + return 0; + if (pos < parsize + && !isWordSeparator(pos)) + return 0; } - return true; + return pos - start_pos; } @@ -3410,9 +3432,24 @@ void Paragraph::updateWords() } +void Paragraph::Private::appendSkipPosition(SkipPositions & skips, pos_type const pos) const +{ + SkipPositionsIterator begin = skips.begin(); + SkipPositions::iterator end = skips.end(); + if (pos > 0 && begin < end) { + --end; + if (end->last == pos - 1) { + end->last = pos; + return; + } + } + skips.insert(end, FontSpan(pos, pos)); +} + + Language * Paragraph::Private::locateSpellRange( pos_type & from, pos_type & to, - Positions & softbreaks) const + SkipPositions & skips) const { // skip leading white space while (from < to && owner_->isWordSeparator(from)) @@ -3429,7 +3466,9 @@ Language * Paragraph::Private::locateSpellRange( // hop to end of word while (last < to && !owner_->isWordSeparator(last)) { if (owner_->getInset(last)) { - softbreaks.insert(softbreaks.end(), last); + appendSkipPosition(skips, last); + } else if (owner_->isDeleted(last)) { + appendSkipPosition(skips, last); } ++last; } @@ -3437,6 +3476,9 @@ Language * Paragraph::Private::locateSpellRange( while (sameinset && last < to && owner_->isWordSeparator(last)) { if (Inset const * inset = owner_->getInset(last)) sameinset = inset->isChar() && inset->isLetter(); + if (sameinset && owner_->isDeleted(last)) { + appendSkipPosition(skips, last); + } if (sameinset) last++; } @@ -3504,7 +3546,7 @@ SpellChecker::Result Paragraph::spellCheck(pos_type & from, pos_type & to, if (from == to || from >= size()) return result; - docstring word = asString(from, to, AS_STR_INSETS); + docstring word = asString(from, to, AS_STR_INSETS + AS_STR_SKIPDELETE); Language * lang = d->getSpellLanguage(from); wl = WordLangTuple(word, lang); @@ -3552,7 +3594,7 @@ void Paragraph::Private::markMisspelledWords( pos_type const & first, pos_type const & last, SpellChecker::Result result, docstring const & word, - Positions const & softbreaks) + SkipPositions const & skips) { if (!SpellChecker::misspelled(result)) { setMisspelled(first, last, SpellChecker::WORD_OK); @@ -3562,9 +3604,9 @@ void Paragraph::Private::markMisspelledWords( SpellChecker * speller = theSpellChecker(); // locate and enumerate the error positions int nerrors = speller->numMisspelledWords(); - int numbreaks = 0; - PositionsIterator it = softbreaks.begin(); - PositionsIterator et = softbreaks.end(); + int numskipped = 0; + SkipPositionsIterator it = skips.begin(); + SkipPositionsIterator et = skips.end(); for (int index = 0; index < nerrors; ++index) { int wstart; int wlen = 0; @@ -3572,15 +3614,15 @@ void Paragraph::Private::markMisspelledWords( /// should not happen if speller supports range checks if (!wlen) continue; docstring const misspelled = word.substr(wstart, wlen); - wstart += first + numbreaks; + wstart += first + numskipped; if (snext < wstart) { /// mark the range of correct spelling - numbreaks += countSoftbreaks(it, et, wstart); + numskipped += countSkips(it, et, wstart); setMisspelled(snext, wstart - 1, SpellChecker::WORD_OK); } snext = wstart + wlen; - numbreaks += countSoftbreaks(it, et, snext); + numskipped += countSkips(it, et, snext); /// mark the range of misspelling setMisspelled(wstart, snext, result); LYXERR(Debug::GUI, "misspelled word: \"" << @@ -3607,16 +3649,16 @@ void Paragraph::spellCheck() const // loop until we leave the range for (pos_type first = start; first < endpos; ) { pos_type last = endpos; - Private::Positions softbreaks; - Language * lang = d->locateSpellRange(first, last, softbreaks); + Private::SkipPositions skips; + Language * lang = d->locateSpellRange(first, last, skips); if (first >= endpos) break; // start the spell checker on the unit of meaning - docstring word = asString(first, last, AS_STR_INSETS); + docstring word = asString(first, last, AS_STR_INSETS + AS_STR_SKIPDELETE); WordLangTuple wl = WordLangTuple(word, lang); SpellChecker::Result result = word.size() ? speller->check(wl) : SpellChecker::WORD_OK; - d->markMisspelledWords(first, last, result, word, softbreaks); + d->markMisspelledWords(first, last, result, word, skips); first = ++last; } } else {