]> git.lyx.org Git - lyx.git/blobdiff - src/Paragraph.cpp
let the compiler do the maths to compute array size
[lyx.git] / src / Paragraph.cpp
index 0df5e364321dda2f2f0459f6d13455369077244c..9dda69e063063ccb1727c1df4daed8a82dbc1c9e 100644 (file)
@@ -112,7 +112,7 @@ public:
                if (range_.first > pos) {
                        range_.first += offset;
                        range_.last += offset;
-               } else if (range_.last > pos) {
+               } else if (range_.last >= pos) {
                        range_.last += offset;
                }
        }
@@ -1117,6 +1117,8 @@ void Paragraph::Private::latexInset(BufferParams const & bparams,
        int prev_rows = os.texrow().rows();
 
        try {
+               runparams.lastid = id_;
+               runparams.lastpos = i;
                inset->latex(os, runparams);
        } catch (EncodingException & e) {
                // add location information and throw again.
@@ -1156,10 +1158,12 @@ void Paragraph::Private::latexSpecialChar(otexstream & os,
        char_type const c = text_[i];
 
        if (style.pass_thru || runparams.pass_thru) {
-               if (c != '\0')
-                       // FIXME UNICODE: This can fail if c cannot
-                       // be encoded in the current encoding.
+               if (c != '\0') {
+                       Encoding const * const enc = runparams.encoding;
+                       if (enc && enc->latexChar(c, true).empty())
+                               throw EncodingException(c);
                        os.put(c);
+               }
                return;
        }
 
@@ -2371,8 +2375,8 @@ void Paragraph::latex(BufferParams const & bparams,
                                                            runparams);
                }
 
-               Change const & change = runparams.inDeletedInset ? runparams.changeOfDeletedInset
-                                                                : lookupChange(i);
+               Change const & change = runparams.inDeletedInset
+                       ? runparams.changeOfDeletedInset : lookupChange(i);
 
                if (bparams.outputChanges && runningChange != change) {
                        if (open_font) {
@@ -2727,10 +2731,11 @@ docstring Paragraph::simpleLyXHTMLOnePar(Buffer const & buf,
 
        bool emph_flag = false;
        bool bold_flag = false;
-       string closing_tag;
 
        Layout const & style = *d->layout_;
 
+       xs.startParagraph();
+
        if (!runparams.for_toc && runparams.html_make_pars) {
                // generate a magic label for this paragraph
                string const attr = "id='" + magicLabel() + "'";
@@ -2810,6 +2815,7 @@ docstring Paragraph::simpleLyXHTMLOnePar(Buffer const & buf,
        }
 
        xs.closeFontTags();
+       xs.endParagraph();
        return retval;
 }
 
@@ -2841,14 +2847,40 @@ bool Paragraph::isLineSeparator(pos_type pos) const
 
 bool Paragraph::isWordSeparator(pos_type pos) const
 {
-       if (Inset const * inset = getInset(pos))
-               return !inset->isLetter();
        if (pos == size())
                return true;
+       if (Inset const * inset = getInset(pos))
+               return !inset->isLetter();
+       // if we have a hard hyphen (no en- or emdash) or apostrophe
+       // we pass this to the spell checker
+       // FIXME: this method is subject to change, visit
+       // https://bugzilla.mozilla.org/show_bug.cgi?id=355178
+       // to get an impression how complex this is.
+       if (isHardHyphenOrApostrophe(pos))
+               return false;
+       char_type const c = d->text_[pos];
+       // We want to pass the escape chars to the spellchecker
+       docstring const escape_chars = from_utf8(lyxrc.spellchecker_esc_chars);
+       return !isLetterChar(c) && !isDigitASCII(c) && !contains(escape_chars, c);
+}
+
+
+bool Paragraph::isHardHyphenOrApostrophe(pos_type pos) const
+{
+       pos_type const psize = size();
+       if (pos >= psize)
+               return false;
        char_type const c = d->text_[pos];
-       // We want to pass the ' and escape chars to the spellchecker
-       static docstring const quote = from_utf8(lyxrc.spellchecker_esc_chars + '\'');
-       return (!isLetterChar(c) && !isDigitASCII(c) && !contains(quote, c));
+       if (c != '-' && c != '\'')
+               return false;
+       int nextpos = pos + 1;
+       int prevpos = pos > 0 ? pos - 1 : 0;
+       if ((nextpos == psize || isSpace(nextpos))
+               && (pos == 0 || isSpace(prevpos)))
+               return false;
+       return c == '\''
+               || ((nextpos == psize || d->text_[nextpos] != '-')
+               && (pos == 0 || d->text_[prevpos] != '-'));
 }
 
 
@@ -3340,12 +3372,12 @@ int Paragraph::find(docstring const & str, bool cs, bool mw,
        int i = 0;
        pos_type const parsize = d->text_.size();
        for (i = 0; i < strsize && pos < parsize; ++i, ++pos) {
-               // Ignore ligature break and hyphenation chars while searching
+               // Ignore "invisible" letters such as ligature breaks
+               // and hyphenation chars while searching
                while (pos < parsize - 1 && isInset(pos)) {
-                       const InsetSpecialChar *isc = dynamic_cast<const InsetSpecialChar*>(getInset(pos));
-                       if (isc == 0
-                           || (isc->kind() != InsetSpecialChar::HYPHENATION
-                               && isc->kind() != InsetSpecialChar::LIGATURE_BREAK))
+                       odocstringstream os;
+                       getInset(pos)->toString(os);
+                       if (!getInset(pos)->isLetter() || !os.str().empty())
                                break;
                        pos++;
                }
@@ -3639,6 +3671,7 @@ SpellChecker::Result Paragraph::spellCheck(pos_type & from, pos_type & to,
                return result;
 
        if (needsSpellCheck() || check_learned) {
+               pos_type end = to;
                if (!d->ignoreWord(word)) {
                        bool const trailing_dot = to < size() && d->text_[to] == '.';
                        result = speller->check(wl);
@@ -3650,28 +3683,33 @@ SpellChecker::Result Paragraph::spellCheck(pos_type & from, pos_type & to,
                                           word << "\" [" <<
                                           from << ".." << to << "]");
                                } else {
-                                       // spell check with dot appended failed
+                                       // spell check with dot appended failed too
                                        // restore original word/lang value
                                        word = asString(from, to, AS_STR_INSETS | AS_STR_SKIPDELETE);
                                        wl = WordLangTuple(word, lang);
                                }
                        }
                }
-               d->setMisspelled(from, to, result);
+               if (!SpellChecker::misspelled(result)) {
+                       // area up to the begin of the next word is not misspelled
+                       while (end < size() && isWordSeparator(end))
+                               ++end;
+               }
+               d->setMisspelled(from, end, result);
        } else {
                result = d->speller_state_.getState(from);
        }
 
-       bool const misspelled_ = SpellChecker::misspelled(result) ;
-       if (misspelled_ && do_suggestion)
-               speller->suggest(wl, suggestions);
-       else if (misspelled_)
+       if (do_suggestion)
+               suggestions.clear();
+
+       if (SpellChecker::misspelled(result)) {
                LYXERR(Debug::GUI, "misspelled word: \"" <<
                           word << "\" [" <<
                           from << ".." << to << "]");
-       else
-               suggestions.clear();
-
+               if (do_suggestion)
+                       speller->suggest(wl, suggestions);
+       }
        return result;
 }
 
@@ -3763,9 +3801,9 @@ void Paragraph::spellCheck() const
 bool Paragraph::isMisspelled(pos_type pos, bool check_boundary) const
 {
        bool result = SpellChecker::misspelled(d->speller_state_.getState(pos));
-       if (result || pos <= 0 || pos >= size())
+       if (result || pos <= 0 || pos > size())
                return result;
-       if (check_boundary && isWordSeparator(pos))
+       if (check_boundary && (pos == size() || isWordSeparator(pos)))
                result = SpellChecker::misspelled(d->speller_state_.getState(pos - 1));
        return result;
 }