X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FParagraph.cpp;h=991ab14a7527d65083207e171b9e34b8fb720fce;hb=ea6aed5b8bf38366aaa1eb15ce1b9f13de76987f;hp=6aeab1aa7dce60f5cfd80b75e639be50800256d6;hpb=b922cfd3b351683fa452eeec4830258d72d47ab8;p=lyx.git diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp index 6aeab1aa7d..991ab14a75 100644 --- a/src/Paragraph.cpp +++ b/src/Paragraph.cpp @@ -49,6 +49,7 @@ #include "insets/InsetBibitem.h" #include "insets/InsetLabel.h" +#include "support/lassert.h" #include "support/convert.h" #include "support/debug.h" #include "support/gettext.h" @@ -82,6 +83,8 @@ public: Private(Paragraph * owner, Layout const & layout); /// "Copy constructor" Private(Private const &, Paragraph * owner); + /// Copy constructor from \p beg to \p end + Private(Private const &, Paragraph * owner, pos_type beg, pos_type end); /// void insertChar(pos_type pos, char_type c, Change const & change); @@ -246,10 +249,39 @@ Paragraph::Private::Private(Private const & p, Paragraph * owner) } +Paragraph::Private::Private(Private const & p, Paragraph * owner, + pos_type beg, pos_type end) + : owner_(owner), inset_owner_(p.inset_owner_), + insetlist_(p.insetlist_, beg, end), + params_(p.params_), changes_(p.changes_), + begin_of_body_(p.begin_of_body_), words_(p.words_), + layout_(p.layout_) +{ + id_ = paragraph_id++; + if (beg >= pos_type(p.text_.size())) + return; + text_ = p.text_.substr(beg, end - beg); + + FontList::const_iterator fcit = fontlist_.begin(); + FontList::const_iterator fend = fontlist_.end(); + for (; fcit != fend; ++fcit) { + if (fcit->pos() < beg) + continue; + if (fcit->pos() >= end) { + // Add last entry in the fontlist_. + fontlist_.set(text_.size() - 1, fcit->font()); + break; + } + // Add a new entry in the fontlist_. + fontlist_.set(fcit->pos() - beg, fcit->font()); + } +} + + bool Paragraph::isChanged(pos_type start, pos_type end) const { - BOOST_ASSERT(start >= 0 && start <= size()); - BOOST_ASSERT(end > start && end <= size() + 1); + LASSERT(start >= 0 && start <= size(), /**/); + LASSERT(end > start && end <= size() + 1, /**/); return d->changes_.isChanged(start, end); } @@ -294,7 +326,7 @@ void Paragraph::setChange(Change const & change) void Paragraph::setChange(pos_type pos, Change const & change) { - BOOST_ASSERT(pos >= 0 && pos <= size()); + LASSERT(pos >= 0 && pos <= size(), /**/); d->changes_.set(change, pos); // see comment in setChange(Change const &) above @@ -306,7 +338,7 @@ void Paragraph::setChange(pos_type pos, Change const & change) Change const & Paragraph::lookupChange(pos_type pos) const { - BOOST_ASSERT(pos >= 0 && pos <= size()); + LASSERT(pos >= 0 && pos <= size(), /**/); return d->changes_.lookup(pos); } @@ -314,8 +346,8 @@ Change const & Paragraph::lookupChange(pos_type pos) const void Paragraph::acceptChanges(BufferParams const & bparams, pos_type start, pos_type end) { - BOOST_ASSERT(start >= 0 && start <= size()); - BOOST_ASSERT(end > start && end <= size() + 1); + LASSERT(start >= 0 && start <= size(), /**/); + LASSERT(end > start && end <= size() + 1, /**/); for (pos_type pos = start; pos < end; ++pos) { switch (lookupChange(pos).type) { @@ -350,8 +382,8 @@ void Paragraph::acceptChanges(BufferParams const & bparams, pos_type start, void Paragraph::rejectChanges(BufferParams const & bparams, pos_type start, pos_type end) { - BOOST_ASSERT(start >= 0 && start <= size()); - BOOST_ASSERT(end > start && end <= size() + 1); + LASSERT(start >= 0 && start <= size(), /**/); + LASSERT(end > start && end <= size() + 1, /**/); for (pos_type pos = start; pos < end; ++pos) { switch (lookupChange(pos).type) { @@ -386,7 +418,7 @@ void Paragraph::rejectChanges(BufferParams const & bparams, void Paragraph::Private::insertChar(pos_type pos, char_type c, Change const & change) { - BOOST_ASSERT(pos >= 0 && pos <= int(text_.size())); + LASSERT(pos >= 0 && pos <= int(text_.size()), /**/); // track change changes_.insert(change, pos); @@ -412,11 +444,11 @@ void Paragraph::Private::insertChar(pos_type pos, char_type c, void Paragraph::insertInset(pos_type pos, Inset * inset, Change const & change) { - BOOST_ASSERT(inset); - BOOST_ASSERT(pos >= 0 && pos <= size()); + LASSERT(inset, /**/); + LASSERT(pos >= 0 && pos <= size(), /**/); d->insertChar(pos, META_INSET, change); - BOOST_ASSERT(d->text_[pos] == META_INSET); + LASSERT(d->text_[pos] == META_INSET, /**/); // Add a new entry in the insetlist_. d->insetlist_.insert(inset, pos); @@ -425,7 +457,7 @@ void Paragraph::insertInset(pos_type pos, Inset * inset, bool Paragraph::eraseChar(pos_type pos, bool trackChanges) { - BOOST_ASSERT(pos >= 0 && pos <= size()); + LASSERT(pos >= 0 && pos <= size(), /**/); // keep the logic here in sync with the logic of isMergedOnEndOfParDeletion() @@ -474,8 +506,8 @@ bool Paragraph::eraseChar(pos_type pos, bool trackChanges) int Paragraph::eraseChars(pos_type start, pos_type end, bool trackChanges) { - BOOST_ASSERT(start >= 0 && start <= size()); - BOOST_ASSERT(end >= start && end <= size() + 1); + LASSERT(start >= 0 && start <= size(), /**/); + LASSERT(end >= start && end <= size() + 1, /**/); pos_type i = start; for (pos_type count = end - start; count; --count) { @@ -498,7 +530,12 @@ int Paragraph::Private::latexSurrogatePair(odocstream & os, char_type c, // Is this correct WRT change tracking? docstring const latex1 = encoding.latexChar(next); docstring const latex2 = encoding.latexChar(c); - os << latex1 << '{' << latex2 << '}'; + if (docstring(1, next) == latex1) { + // the encoding supports the combination + os << latex2 << latex1; + return latex1.length() + latex2.length(); + } else + os << latex1 << '{' << latex2 << '}'; return latex1.length() + latex2.length() + 2; } @@ -560,9 +597,10 @@ int Paragraph::Private::writeScriptChars(odocstream & os, // We only arrive here when a proper language for character text_[i] has // not been specified (i.e., it could not be translated in the current - // latex encoding) and it belongs to a known script. - // Parameter ltx contains the latex translation of text_[i] as specified in - // the unicodesymbols file and is something like "\textXXX{}". + // latex encoding) or its latex translation has been forced, and it + // belongs to a known script. + // Parameter ltx contains the latex translation of text_[i] as specified + // in the unicodesymbols file and is something like "\textXXX{}". // The latex macro name "textXXX" specifies the script to which text_[i] // belongs and we use it in order to check whether characters from the // same script immediately follow, such that we can collect them in a @@ -571,8 +609,16 @@ int Paragraph::Private::writeScriptChars(odocstream & os, docstring::size_type const brace1 = ltx.find_first_of(from_ascii("{")); docstring::size_type const brace2 = ltx.find_last_of(from_ascii("}")); string script = to_ascii(ltx.substr(1, brace1 - 1)); - int length = ltx.substr(0, brace2).length(); - os << ltx.substr(0, brace2); + int pos = 0; + int length = brace2; + bool closing_brace = true; + if (script == "textgreek" && encoding.latexName() == "iso-8859-7") { + // Correct encoding is being used, so we can avoid \textgreek. + pos = brace1 + 1; + length -= pos; + closing_brace = false; + } + os << ltx.substr(pos, length); int size = text_.size(); while (i + 1 < size) { char_type const next = text_[i + 1]; @@ -606,8 +652,10 @@ int Paragraph::Private::writeScriptChars(odocstream & os, length += len; ++i; } - os << '}'; - ++length; + if (closing_brace) { + os << '}'; + ++length; + } return length; } @@ -647,7 +695,7 @@ void Paragraph::Private::latexInset( unsigned int & column) { Inset * inset = owner_->getInset(i); - BOOST_ASSERT(inset); + LASSERT(inset, /**/); if (style.pass_thru) { inset->plaintext(os, runparams); @@ -743,7 +791,16 @@ void Paragraph::Private::latexInset( } } - int tmp = inset->latex(os, runparams); + int tmp; + + try { + tmp = inset->latex(os, runparams); + } catch (EncodingException & e) { + // add location information and throw again. + e.par_id = id_; + e.pos = i; + throw(e); + } if (close) { if (running_font.language()->lang() == "farsi") @@ -787,6 +844,8 @@ void Paragraph::Private::latexSpecialChar( } if (runparams.verbatim) { + // FIXME UNICODE: This can fail if c cannot + // be encoded in the current encoding. os.put(c); return; } @@ -859,7 +918,6 @@ void Paragraph::Private::latexSpecialChar( break; default: - // LyX, LaTeX etc. if (latexSpecialPhrase(os, i, column, runparams)) return; @@ -908,11 +966,8 @@ bool Paragraph::Private::latexSpecialT1(char_type const c, odocstream & os, // but we should avoid ligatures if (i + 1 >= int(text_.size()) || text_[i + 1] != c) return true; - os << "\\,{}"; - column += 3; - // Alternative code: - //os << "\\textcompwordmark{}"; - //column += 19; + os << "\\textcompwordmark{}"; + column += 19; return true; case '|': os.put(c); @@ -928,37 +983,19 @@ bool Paragraph::Private::latexSpecialTypewriter(char_type const c, odocstream & { switch (c) { case '-': + // within \ttfamily, "--" is merged to "-" (no endash) + // so we avoid this rather irritating ligature if (i + 1 < int(text_.size()) && text_[i + 1] == '-') { - // "--" in Typewriter mode -> "-{}-" os << "-{}"; column += 2; } else os << '-'; return true; - // I assume this is hack treating typewriter as verbatim - // FIXME UNICODE: This can fail if c cannot be encoded - // in the current encoding. - - case '\0': - return true; - - // Those characters are not directly supported. - case '\\': - case '\"': - case '$': case '&': - case '%': case '#': case '{': - case '}': case '_': - case '~': - case '^': - case '*': case '[': - case ' ': - return false; - + // everything else has to be checked separately + // (depending on the encoding) default: - // With Typewriter font, these characters exist. - os.put(c); - return true; + return false; } } @@ -1054,6 +1091,14 @@ Paragraph::Paragraph(Paragraph const & par) } +Paragraph::Paragraph(Paragraph const & par, pos_type beg, pos_type end) + : itemdepth(par.itemdepth), + d(new Paragraph::Private(*par.d, this, beg, end)) +{ + registerWords(); +} + + Paragraph & Paragraph::operator=(Paragraph const & par) { // needed as we will destroy the private part before copying it @@ -1162,8 +1207,7 @@ void Paragraph::write(ostream & os, BufferParams const & bparams, if (c != '\0') os << to_utf8(docstring(1, c)); else - lyxerr << "ERROR (Paragraph::writeFile):" - " NULL char in structure." << endl; + LYXERR0("NUL char in structure."); ++column; break; } @@ -1212,7 +1256,7 @@ void Paragraph::appendString(docstring const & s, Font const & font, d->text_.append(s); // FIXME: Optimize this! - for (pos_type i = 0; i != end; ++i) { + for (pos_type i = oldsize; i != newsize; ++i) { // track change d->changes_.insert(change, i); } @@ -1273,8 +1317,8 @@ Font const Paragraph::getFontSettings(BufferParams const & bparams, pos_type pos) const { if (pos > size()) { - lyxerr << " pos: " << pos << " size: " << size() << endl; - BOOST_ASSERT(pos <= size()); + LYXERR0("pos: " << pos << " size: " << size()); + LASSERT(pos <= size(), /**/); } FontList::const_iterator cit = d->fontlist_.fontIterator(pos); @@ -1290,7 +1334,7 @@ Font const Paragraph::getFontSettings(BufferParams const & bparams, FontSpan Paragraph::fontSpan(pos_type pos) const { - BOOST_ASSERT(pos <= size()); + LASSERT(pos <= size(), /**/); pos_type start = 0; FontList::const_iterator cit = d->fontlist_.begin(); @@ -1309,8 +1353,7 @@ FontSpan Paragraph::fontSpan(pos_type pos) const } // This should not happen, but if so, we take no chances. - //lyxerr << "Paragraph::getEndPosOfFontSpan: This should not happen!" - // << endl; + // LYXERR0("Paragraph::getEndPosOfFontSpan: This should not happen!"); return FontSpan(pos, pos); } @@ -1333,7 +1376,7 @@ Font const Paragraph::getFirstFontSettings(BufferParams const & bparams) const Font const Paragraph::getFont(BufferParams const & bparams, pos_type pos, Font const & outerfont) const { - BOOST_ASSERT(pos >= 0); + LASSERT(pos >= 0, /**/); Font font = getFontSettings(bparams, pos); @@ -1378,8 +1421,7 @@ FontSize Paragraph::highestFontInRange } -char_type -Paragraph::getUChar(BufferParams const & bparams, pos_type pos) const +char_type Paragraph::getUChar(BufferParams const & bparams, pos_type pos) const { char_type c = d->text_[pos]; if (!lyxrc.rtl_support) @@ -1414,14 +1456,13 @@ Paragraph::getUChar(BufferParams const & bparams, pos_type pos) const } if (uc != c && getFontSettings(bparams, pos).isRightToLeft()) return uc; - else - return c; + return c; } void Paragraph::setFont(pos_type pos, Font const & font) { - BOOST_ASSERT(pos <= size()); + LASSERT(pos <= size(), /**/); // First, reduce font against layout/label font // Update: The setCharFont() routine in text2.cpp already @@ -1614,12 +1655,12 @@ void Paragraph::setBeginOfBody() } -bool Paragraph::forceEmptyLayout() const +bool Paragraph::forcePlainLayout() const { Inset const * const inset = inInset(); if (!inset) return true; - return inset->forceEmptyLayout(); + return inset->forcePlainLayout(); } @@ -1632,12 +1673,12 @@ bool Paragraph::allowParagraphCustomization() const } -bool Paragraph::useEmptyLayout() const +bool Paragraph::usePlainLayout() const { Inset const * const inset = inInset(); if (!inset) return false; - return inset->useEmptyLayout(); + return inset->usePlainLayout(); } @@ -1831,10 +1872,10 @@ bool Paragraph::latex(BufferParams const & bparams, bool return_value = false; - bool asdefault = forceEmptyLayout(); + bool asdefault = forcePlainLayout(); Layout const & style = asdefault ? - bparams.documentClass().emptyLayout() : + bparams.documentClass().plainLayout() : *d->layout_; // Current base font for all inherited font changes, without any @@ -1963,8 +2004,8 @@ bool Paragraph::latex(BufferParams const & bparams, // Switch file encoding if necessary (and allowed) if (!runparams.verbatim && - runparams.encoding->package() == Encoding::none && - font.language()->encoding()->package() == Encoding::none) { + runparams.encoding->package() != Encoding::none && + font.language()->encoding()->package() != Encoding::none) { pair const enc_switch = switchEncoding(os, bparams, runparams, *(font.language()->encoding())); if (enc_switch.first) { @@ -2048,7 +2089,7 @@ bool Paragraph::latex(BufferParams const & bparams, } } - // Set the encoding to that returned from simpleTeXSpecialChars (see + // Set the encoding to that returned from latexSpecialChar (see // comment for encoding member in OutputParams.h) runparams.encoding = rp.encoding; } @@ -2257,6 +2298,24 @@ bool Paragraph::isLetter(pos_type pos) const } +bool Paragraph::isChar(pos_type pos) const +{ + if (Inset const * inset = getInset(pos)) + return inset->isChar(); + char_type const c = d->text_[pos]; + return !isLetterChar(c) && !isDigit(c) && !lyx::isSpace(c); +} + + +bool Paragraph::isSpace(pos_type pos) const +{ + if (Inset const * inset = getInset(pos)) + return inset->isSpace(); + char_type const c = d->text_[pos]; + return lyx::isSpace(c); +} + + Language const * Paragraph::getParLanguage(BufferParams const & bparams) const { @@ -2305,25 +2364,26 @@ bool Paragraph::isMultiLingual(BufferParams const & bparams) const } -docstring Paragraph::asString(bool label) const +docstring Paragraph::asString(int options) const { - return asString(0, size(), label); + return asString(0, size(), options); } -docstring Paragraph::asString(pos_type beg, pos_type end, bool label) const +docstring Paragraph::asString(pos_type beg, pos_type end, int options) const { - odocstringstream os; - if (beg == 0 && label && !d->params_.labelString().empty()) + if (beg == 0 + && options & AS_STR_LABEL + && !d->params_.labelString().empty()) os << d->params_.labelString() << ' '; for (pos_type i = beg; i < end; ++i) { char_type const c = d->text_[i]; if (isPrintable(c)) os.put(c); - else if (c == META_INSET) + else if (c == META_INSET && options & AS_STR_INSETS) getInset(i)->textString(os); } @@ -2355,10 +2415,10 @@ void Paragraph::setLayout(Layout const & layout) } -void Paragraph::setEmptyOrDefaultLayout(DocumentClass const & tclass) +void Paragraph::setPlainOrDefaultLayout(DocumentClass const & tclass) { - if (useEmptyLayout()) - setLayout(tclass.emptyLayout()); + if (usePlainLayout()) + setLayout(tclass.plainLayout()); else setLayout(tclass.defaultLayout()); } @@ -2406,7 +2466,7 @@ bool Paragraph::allowEmpty() const char_type Paragraph::transformChar(char_type c, pos_type pos) const { - if (!Encodings::is_arabic(c)) + if (!Encodings::isArabicChar(c)) return c; char_type prev_char = ' '; @@ -2414,7 +2474,7 @@ char_type Paragraph::transformChar(char_type c, pos_type pos) const for (pos_type i = pos - 1; i >= 0; --i) { char_type const par_char = d->text_[i]; - if (!Encodings::isComposeChar_arabic(par_char)) { + if (!Encodings::isArabicComposeChar(par_char)) { prev_char = par_char; break; } @@ -2422,21 +2482,21 @@ char_type Paragraph::transformChar(char_type c, pos_type pos) const for (pos_type i = pos + 1, end = size(); i < end; ++i) { char_type const par_char = d->text_[i]; - if (!Encodings::isComposeChar_arabic(par_char)) { + if (!Encodings::isArabicComposeChar(par_char)) { next_char = par_char; break; } } - if (Encodings::is_arabic(next_char)) { - if (Encodings::is_arabic(prev_char) && - !Encodings::is_arabic_special(prev_char)) + if (Encodings::isArabicChar(next_char)) { + if (Encodings::isArabicChar(prev_char) && + !Encodings::isArabicSpecialChar(prev_char)) return Encodings::transformChar(c, Encodings::FORM_MEDIAL); else return Encodings::transformChar(c, Encodings::FORM_INITIAL); } else { - if (Encodings::is_arabic(prev_char) && - !Encodings::is_arabic_special(prev_char)) + if (Encodings::isArabicChar(prev_char) && + !Encodings::isArabicSpecialChar(prev_char)) return Encodings::transformChar(c, Encodings::FORM_FINAL); else return Encodings::transformChar(c, Encodings::FORM_ISOLATED); @@ -2501,8 +2561,8 @@ int Paragraph::checkBiblio(Buffer const & buffer) // There was no inset at the beginning, so we need to create one with // the key and label of the one we erased. - InsetBibitem * inset = new InsetBibitem(InsetCommandParams(BIBITEM_CODE)); - inset->setBuffer(const_cast(buffer)); + InsetBibitem * inset = + new InsetBibitem(buffer, InsetCommandParams(BIBITEM_CODE)); // restore values of previously deleted item in this par. if (!oldkey.empty()) inset->setParam("key", oldkey); @@ -2544,6 +2604,12 @@ InsetList const & Paragraph::insetList() const } +void Paragraph::setBuffer(Buffer & b) +{ + d->insetlist_.setBuffer(b); +} + + Inset * Paragraph::releaseInset(pos_type pos) { Inset * inset = d->insetlist_.release(pos); @@ -2752,7 +2818,7 @@ void Paragraph::registerWords() void Paragraph::updateWords(CursorSlice const & sl) { - BOOST_ASSERT(&sl.paragraph() == this); + LASSERT(&sl.paragraph() == this, /**/); deregisterWords(); collectWords(sl); registerWords();