X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FParagraph.cpp;h=e46faab4b922848e6487ea7077d4ab64f138aa4b;hb=97e5041a4abfec0820b8c8662577e83ce0e6c3cd;hp=2477165dede936fdbb083f732b49047b3c044650;hpb=249e6b7ac0578d4ac03c085ba67a1d75af9980e2;p=lyx.git diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp index 2477165ded..e46faab4b9 100644 --- a/src/Paragraph.cpp +++ b/src/Paragraph.cpp @@ -19,6 +19,7 @@ #include "Paragraph.h" +#include "LayoutFile.h" #include "Buffer.h" #include "BufferParams.h" #include "Changes.h" @@ -48,8 +49,10 @@ #include "insets/InsetBibitem.h" #include "insets/InsetLabel.h" +#include "support/lassert.h" #include "support/convert.h" #include "support/debug.h" +#include "support/ExceptionMessage.h" #include "support/gettext.h" #include "support/lstrings.h" #include "support/Messages.h" @@ -78,9 +81,11 @@ class Paragraph::Private { public: /// - Private(Paragraph * owner); + 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); @@ -104,18 +109,18 @@ public: /// specified by the latex macro \p ltx, to \p os starting from \p i. /// \return the number of characters written. int writeScriptChars(odocstream & os, docstring const & ltx, - Change &, Encoding const &, pos_type & i); + Change const &, Encoding const &, pos_type & i); /// This could go to ParagraphParameters if we want to. int startTeXParParams(BufferParams const &, odocstream &, TexRow &, - bool) const; + OutputParams const &) const; /// This could go to ParagraphParameters if we want to. int endTeXParParams(BufferParams const &, odocstream &, TexRow &, - bool) const; + OutputParams const &) const; /// - void latexInset(Buffer const &, BufferParams const &, + void latexInset(BufferParams const &, odocstream &, TexRow & texrow, OutputParams &, Font & running_font, @@ -130,9 +135,9 @@ public: /// void latexSpecialChar( odocstream & os, - OutputParams & runparams, - Font & running_font, - Change & running_change, + OutputParams const & runparams, + Font const & running_font, + Change const & running_change, Layout const & style, pos_type & i, unsigned int & column); @@ -141,20 +146,20 @@ public: bool latexSpecialT1( char_type const c, odocstream & os, - pos_type & i, + pos_type i, unsigned int & column); /// bool latexSpecialTypewriter( char_type const c, odocstream & os, - pos_type & i, + pos_type i, unsigned int & column); /// bool latexSpecialPhrase( odocstream & os, pos_type & i, unsigned int & column, - OutputParams & runparams); + OutputParams const & runparams); /// void validate(LaTeXFeatures & features, @@ -171,7 +176,7 @@ public: Paragraph * owner_; /// In which Inset? - Inset * inset_owner_; + Inset const * inset_owner_; /// FontList fontlist_; @@ -189,9 +194,6 @@ public: /// InsetList insetlist_; - /// - LayoutPtr layout_; - /// end of label pos_type begin_of_body_; @@ -202,6 +204,8 @@ public: typedef std::set Words; /// Words words_; + /// + Layout const * layout_; }; @@ -228,8 +232,8 @@ size_t const phrases_nr = sizeof(special_phrases)/sizeof(special_phrase); } // namespace anon -Paragraph::Private::Private(Paragraph * owner) - : owner_(owner), inset_owner_(0), begin_of_body_(0) +Paragraph::Private::Private(Paragraph * owner, Layout const & layout) + : owner_(owner), inset_owner_(0), begin_of_body_(0), layout_(&layout) { id_ = paragraph_id++; text_.reserve(100); @@ -239,17 +243,53 @@ Paragraph::Private::Private(Paragraph * owner) Paragraph::Private::Private(Private const & p, Paragraph * owner) : owner_(owner), inset_owner_(p.inset_owner_), fontlist_(p.fontlist_), params_(p.params_), changes_(p.changes_), insetlist_(p.insetlist_), - layout_(p.layout_), begin_of_body_(p.begin_of_body_), text_(p.text_), - words_(p.words_) + begin_of_body_(p.begin_of_body_), text_(p.text_), words_(p.words_), + layout_(p.layout_) +{ + id_ = paragraph_id++; +} + + +Paragraph::Private::Private(Private const & p, Paragraph * owner, + pos_type beg, pos_type end) + : owner_(owner), inset_owner_(p.inset_owner_), + params_(p.params_), changes_(p.changes_), + insetlist_(p.insetlist_, beg, end), + 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()); + } +} + + +void Paragraph::addChangesToToc(DocIterator const & cdit, + Buffer const & buf) const +{ + d->changes_.addToToc(cdit, buf); } 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 +334,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 +346,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 +354,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 +390,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 +426,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); @@ -409,23 +449,29 @@ void Paragraph::Private::insertChar(pos_type pos, char_type c, } -void Paragraph::insertInset(pos_type pos, Inset * inset, +bool 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(), /**/); + + // Paragraph::insertInset() can be used in cut/copy/paste operation where + // d->inset_owner_ is not set yet. + if (d->inset_owner_ && !d->inset_owner_->insetAllowed(inset->lyxCode())) + return false; 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); + return true; } bool Paragraph::eraseChar(pos_type pos, bool trackChanges) { - BOOST_ASSERT(pos >= 0 && pos <= size()); + LASSERT(pos >= 0 && pos <= size(), return false); // keep the logic here in sync with the logic of isMergedOnEndOfParDeletion() @@ -474,8 +520,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 +544,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; } @@ -552,7 +603,7 @@ bool Paragraph::Private::simpleTeXBlanks(OutputParams const & runparams, int Paragraph::Private::writeScriptChars(odocstream & os, docstring const & ltx, - Change & runningChange, + Change const & runningChange, Encoding const & encoding, pos_type & i) { @@ -560,9 +611,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 +623,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 +666,10 @@ int Paragraph::Private::writeScriptChars(odocstream & os, length += len; ++i; } - os << '}'; - ++length; + if (closing_brace) { + os << '}'; + ++length; + } return length; } @@ -632,7 +694,7 @@ bool Paragraph::Private::isTextAt(string const & str, pos_type pos) const } -void Paragraph::Private::latexInset(Buffer const & buf, +void Paragraph::Private::latexInset( BufferParams const & bparams, odocstream & os, TexRow & texrow, @@ -647,10 +709,10 @@ void Paragraph::Private::latexInset(Buffer const & buf, unsigned int & column) { Inset * inset = owner_->getInset(i); - BOOST_ASSERT(inset); + LASSERT(inset, /**/); if (style.pass_thru) { - inset->plaintext(buf, os, runparams); + inset->plaintext(os, runparams); return; } @@ -743,7 +805,16 @@ void Paragraph::Private::latexInset(Buffer const & buf, } } - int tmp = inset->latex(buf, 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") @@ -769,9 +840,9 @@ void Paragraph::Private::latexInset(Buffer const & buf, void Paragraph::Private::latexSpecialChar( odocstream & os, - OutputParams & runparams, - Font & running_font, - Change & running_change, + OutputParams const & runparams, + Font const & running_font, + Change const & running_change, Layout const & style, pos_type & i, unsigned int & column) @@ -787,6 +858,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 +932,6 @@ void Paragraph::Private::latexSpecialChar( break; default: - // LyX, LaTeX etc. if (latexSpecialPhrase(os, i, column, runparams)) return; @@ -898,7 +970,7 @@ void Paragraph::Private::latexSpecialChar( bool Paragraph::Private::latexSpecialT1(char_type const c, odocstream & os, - pos_type & i, unsigned int & column) + pos_type i, unsigned int & column) { switch (c) { case '>': @@ -908,15 +980,17 @@ 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); return true; + case '\"': + // soul.sty breaks with \char`\" + os << "\\textquotedbl{}"; + column += 14; + return true; default: return false; } @@ -924,47 +998,29 @@ bool Paragraph::Private::latexSpecialT1(char_type const c, odocstream & os, bool Paragraph::Private::latexSpecialTypewriter(char_type const c, odocstream & os, - pos_type & i, unsigned int & column) + pos_type i, unsigned int & column) { 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; } } bool Paragraph::Private::latexSpecialPhrase(odocstream & os, pos_type & i, - unsigned int & column, OutputParams & runparams) + unsigned int & column, OutputParams const & runparams) { // FIXME: if we have "LaTeX" with a font // change in the middle (before the 'T', then @@ -1034,8 +1090,12 @@ void Paragraph::Private::validate(LaTeXFeatures & features, // ///////////////////////////////////////////////////////////////////// -Paragraph::Paragraph() - : d(new Paragraph::Private(this)) +namespace { + Layout const emptyParagraphLayout; +} + +Paragraph::Paragraph() + : d(new Paragraph::Private(this, emptyParagraphLayout)) { itemdepth = 0; d->params_.clear(); @@ -1050,6 +1110,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 @@ -1072,9 +1140,8 @@ Paragraph::~Paragraph() } -void Paragraph::write(Buffer const & buf, ostream & os, - BufferParams const & bparams, - depth_type & dth) const +void Paragraph::write(ostream & os, BufferParams const & bparams, + depth_type & dth) const { // The beginning or end of a deeper (i.e. nested) area? if (dth != d->params_.depth()) { @@ -1111,7 +1178,7 @@ void Paragraph::write(Buffer const & buf, ostream & os, break; // Write font changes - Font font2 = getFontSettings(bparams, i); + Font const & font2 = getFontSettings(bparams, i); if (font2 != font1) { font2.lyxWriteChanges(font1, os); column = 0; @@ -1126,12 +1193,12 @@ void Paragraph::write(Buffer const & buf, ostream & os, // international char, let it write // code directly so it's shorter in // the file - inset->write(buf, os); + inset->write(os); } else { if (i) os << '\n'; os << "\\begin_inset "; - inset->write(buf, os); + inset->write(os); os << "\n\\end_inset\n\n"; column = 0; } @@ -1159,8 +1226,7 @@ void Paragraph::write(Buffer const & buf, ostream & os, 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; } @@ -1209,7 +1275,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); } @@ -1243,18 +1309,13 @@ void Paragraph::insertChar(pos_type pos, char_type c, } -void Paragraph::insertInset(pos_type pos, Inset * inset, +bool Paragraph::insertInset(pos_type pos, Inset * inset, Font const & font, Change const & change) { - insertInset(pos, inset, change); + bool const success = insertInset(pos, inset, change); // Set the font/language of the inset... setFont(pos, font); -} - - -bool Paragraph::insetAllowed(InsetCode code) -{ - return !d->inset_owner_ || d->inset_owner_->insetAllowed(code); + return success; } @@ -1266,12 +1327,12 @@ void Paragraph::resetFonts(Font const & font) } // Gets uninstantiated font setting at position. -Font const Paragraph::getFontSettings(BufferParams const & bparams, +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); @@ -1281,13 +1342,22 @@ Font const Paragraph::getFontSettings(BufferParams const & bparams, if (pos == size() && !empty()) return getFontSettings(bparams, pos - 1); - return Font(inherit_font, getParLanguage(bparams)); + // Optimisation: avoid a full font instantiation if there is no + // language change from previous call. + static Font previous_font; + static Language const * previous_lang = 0; + Language const * lang = getParLanguage(bparams); + if (lang != previous_lang) { + previous_lang = lang; + previous_font = Font(inherit_font, lang); + } + return previous_font; } 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(); @@ -1306,19 +1376,27 @@ 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); } // Gets uninstantiated font setting at position 0 -Font const Paragraph::getFirstFontSettings(BufferParams const & bparams) const +Font const & Paragraph::getFirstFontSettings(BufferParams const & bparams) const { if (!empty() && !d->fontlist_.empty()) return d->fontlist_.begin()->font(); - return Font(inherit_font, bparams.language); + // Optimisation: avoid a full font instantiation if there is no + // language change from previous call. + static Font previous_font; + static Language const * previous_lang = 0; + if (bparams.language != previous_lang) { + previous_lang = bparams.language; + previous_font = Font(inherit_font, bparams.language); + } + + return previous_font; } @@ -1330,18 +1408,19 @@ 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); pos_type const body_pos = beginOfBody(); + FontInfo & fi = font.fontInfo(); if (pos < body_pos) - font.fontInfo().realize(d->layout_->labelfont); + fi.realize(d->layout_->labelfont); else - font.fontInfo().realize(d->layout_->font); + fi.realize(d->layout_->font); - font.fontInfo().realize(outerfont.fontInfo()); - font.fontInfo().realize(bparams.getFont().fontInfo()); + fi.realize(outerfont.fontInfo()); + fi.realize(bparams.getFont().fontInfo()); return font; } @@ -1375,8 +1454,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) @@ -1411,14 +1489,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 @@ -1456,7 +1533,8 @@ bool Paragraph::stripLeadingSpaces(bool trackChanges) bool Paragraph::hasSameLayout(Paragraph const & par) const { - return par.d->layout_ == d->layout_ && d->params_.sameLayout(par.d->params_); + return par.d->layout_ == d->layout_ + && d->params_.sameLayout(par.d->params_); } @@ -1520,21 +1598,21 @@ docstring const Paragraph::translateIfPossible(docstring const & s, } -docstring Paragraph::expandLabel(LayoutPtr const & layout, +docstring Paragraph::expandLabel(Layout const & layout, BufferParams const & bparams, bool process_appendix) const { - TextClass const & tclass = bparams.textClass(); + DocumentClass const & tclass = bparams.documentClass(); docstring fmt; if (process_appendix && d->params_.appendix()) - fmt = translateIfPossible(layout->labelstring_appendix(), + fmt = translateIfPossible(layout.labelstring_appendix(), bparams); else - fmt = translateIfPossible(layout->labelstring(), bparams); + fmt = translateIfPossible(layout.labelstring(), bparams); - if (fmt.empty() && layout->labeltype == LABEL_COUNTER - && !layout->counter.empty()) - fmt = "\\the" + layout->counter; + if (fmt.empty() && layout.labeltype == LABEL_COUNTER + && !layout.counter.empty()) + fmt = "\\the" + layout.counter; // handle 'inherited level parts' in 'fmt', // i.e. the stuff between '@' in '@Section@.\arabic{subsection}' @@ -1556,9 +1634,9 @@ docstring Paragraph::expandLabel(LayoutPtr const & layout, } -void Paragraph::applyLayout(LayoutPtr const & new_layout) +void Paragraph::applyLayout(Layout const & new_layout) { - d->layout_ = new_layout; + d->layout_ = &new_layout; LyXAlignment const oldAlign = d->params_.align(); if (!(oldAlign & d->layout_->alignpossible)) { @@ -1610,21 +1688,21 @@ void Paragraph::setBeginOfBody() } -bool Paragraph::forceEmptyLayout() const +bool Paragraph::forcePlainLayout() const { - return inInset() && inInset()->forceEmptyLayout(); + return inInset().forcePlainLayout(); } bool Paragraph::allowParagraphCustomization() const { - return inInset() && inInset()->allowParagraphCustomization(0); + return inInset().allowParagraphCustomization(); } -bool Paragraph::useEmptyLayout() const +bool Paragraph::usePlainLayout() const { - return inInset() && inInset()->useEmptyLayout(); + return inInset().usePlainLayout(); } @@ -1635,7 +1713,9 @@ namespace { bool noTrivlistCentering(InsetCode code) { - return code == FLOAT_CODE || code == WRAP_CODE; + return code == FLOAT_CODE + || code == WRAP_CODE + || code == CELL_CODE; } @@ -1652,12 +1732,19 @@ string correction(string const & orig) string const corrected_env(string const & suffix, string const & env, - InsetCode code) + InsetCode code, bool const lastpar) { string output = suffix + "{"; - if (noTrivlistCentering(code)) + if (noTrivlistCentering(code)) { + if (lastpar) { + // the last paragraph in non-trivlist-aligned + // context is special (to avoid unwanted whitespace) + if (suffix == "\\begin") + return "\\" + correction(env) + "{}"; + return string(); + } output += correction(env); - else + } else output += env; output += "}"; if (suffix == "\\begin") @@ -1682,7 +1769,7 @@ void adjust_row_column(string const & str, TexRow & texrow, int & column) int Paragraph::Private::startTeXParParams(BufferParams const & bparams, odocstream & os, TexRow & texrow, - bool moving_arg) const + OutputParams const & runparams) const { int column = 0; @@ -1705,13 +1792,17 @@ int Paragraph::Private::startTeXParParams(BufferParams const & bparams, case LYX_ALIGN_LEFT: case LYX_ALIGN_RIGHT: case LYX_ALIGN_CENTER: - if (moving_arg) { + if (runparams.moving_arg) { os << "\\protect"; column += 8; } break; } + string const begin_tag = "\\begin"; + InsetCode code = owner_->ownerCode(); + bool const lastpar = runparams.isLastPar; + switch (curAlign) { case LYX_ALIGN_NONE: case LYX_ALIGN_BLOCK: @@ -1721,24 +1812,24 @@ int Paragraph::Private::startTeXParParams(BufferParams const & bparams, case LYX_ALIGN_LEFT: { string output; if (owner_->getParLanguage(bparams)->babel() != "hebrew") - output = corrected_env("\\begin", "flushleft", owner_->ownerCode()); + output = corrected_env(begin_tag, "flushleft", code, lastpar); else - output = corrected_env("\\begin", "flushright", owner_->ownerCode()); + output = corrected_env(begin_tag, "flushright", code, lastpar); os << from_ascii(output); adjust_row_column(output, texrow, column); break; } case LYX_ALIGN_RIGHT: { string output; if (owner_->getParLanguage(bparams)->babel() != "hebrew") - output = corrected_env("\\begin", "flushright", owner_->ownerCode()); + output = corrected_env(begin_tag, "flushright", code, lastpar); else - output = corrected_env("\\begin", "flushleft", owner_->ownerCode()); + output = corrected_env(begin_tag, "flushleft", code, lastpar); os << from_ascii(output); adjust_row_column(output, texrow, column); break; } case LYX_ALIGN_CENTER: { string output; - output = corrected_env("\\begin", "center", owner_->ownerCode()); + output = corrected_env(begin_tag, "center", code, lastpar); os << from_ascii(output); adjust_row_column(output, texrow, column); break; @@ -1751,7 +1842,7 @@ int Paragraph::Private::startTeXParParams(BufferParams const & bparams, int Paragraph::Private::endTeXParParams(BufferParams const & bparams, odocstream & os, TexRow & texrow, - bool moving_arg) const + OutputParams const & runparams) const { int column = 0; @@ -1764,13 +1855,17 @@ int Paragraph::Private::endTeXParParams(BufferParams const & bparams, case LYX_ALIGN_LEFT: case LYX_ALIGN_RIGHT: case LYX_ALIGN_CENTER: - if (moving_arg) { + if (runparams.moving_arg) { os << "\\protect"; column = 8; } break; } + string const end_tag = "\n\\par\\end"; + InsetCode code = owner_->ownerCode(); + bool const lastpar = runparams.isLastPar; + switch (params_.align()) { case LYX_ALIGN_NONE: case LYX_ALIGN_BLOCK: @@ -1780,24 +1875,24 @@ int Paragraph::Private::endTeXParParams(BufferParams const & bparams, case LYX_ALIGN_LEFT: { string output; if (owner_->getParLanguage(bparams)->babel() != "hebrew") - output = corrected_env("\n\\par\\end", "flushleft", owner_->ownerCode()); + output = corrected_env(end_tag, "flushleft", code, lastpar); else - output = corrected_env("\n\\par\\end", "flushright", owner_->ownerCode()); + output = corrected_env(end_tag, "flushright", code, lastpar); os << from_ascii(output); adjust_row_column(output, texrow, column); break; } case LYX_ALIGN_RIGHT: { string output; if (owner_->getParLanguage(bparams)->babel() != "hebrew") - output = corrected_env("\n\\par\\end", "flushright", owner_->ownerCode()); + output = corrected_env(end_tag, "flushright", code, lastpar); else - output = corrected_env("\n\\par\\end", "flushleft", owner_->ownerCode()); + output = corrected_env(end_tag, "flushleft", code, lastpar); os << from_ascii(output); adjust_row_column(output, texrow, column); break; } case LYX_ALIGN_CENTER: { string output; - output = corrected_env("\n\\par\\end", "center", owner_->ownerCode()); + output = corrected_env(end_tag, "center", code, lastpar); os << from_ascii(output); adjust_row_column(output, texrow, column); break; @@ -1809,29 +1904,20 @@ int Paragraph::Private::endTeXParParams(BufferParams const & bparams, // This one spits out the text of the paragraph -bool Paragraph::latex(Buffer const & buf, - BufferParams const & bparams, +bool Paragraph::latex(BufferParams const & bparams, Font const & outerfont, odocstream & os, TexRow & texrow, OutputParams const & runparams) const { - LYXERR(Debug::LATEX, "SimpleTeXOnePar... " << this); + LYXERR(Debug::LATEX, "Paragraph::latex... " << this); bool return_value = false; - LayoutPtr style; - - // well we have to check if we are in an inset with unlimited - // length (all in one row) if that is true then we don't allow - // any special options in the paragraph and also we don't allow - // any environment other than the default layout of the text class - // to be valid! - bool asdefault = forceEmptyLayout(); + bool asdefault = forcePlainLayout(); - if (asdefault) - style = bparams.textClass().defaultLayout(); - else - style = d->layout_; + Layout const & style = asdefault ? + bparams.documentClass().plainLayout() : + *d->layout_; // Current base font for all inherited font changes, without any // change caused by an individual character, except for the language: @@ -1866,13 +1952,13 @@ bool Paragraph::latex(Buffer const & buf, // if the paragraph is empty, the loop will not be entered at all if (empty()) { - if (style->isCommand()) { + if (style.isCommand()) { os << '{'; ++column; } if (!asdefault) column += d->startTeXParParams(bparams, os, texrow, - runparams.moving_arg); + runparams); } for (pos_type i = 0; i < size(); ++i) { @@ -1895,7 +1981,7 @@ bool Paragraph::latex(Buffer const & buf, os << "}] "; column +=3; } - if (style->isCommand()) { + if (style.isCommand()) { os << '{'; ++column; } @@ -1903,7 +1989,7 @@ bool Paragraph::latex(Buffer const & buf, if (!asdefault) column += d->startTeXParParams(bparams, os, texrow, - runparams.moving_arg); + runparams); } Change const & change = runparams.inDeletedInset ? runparams.changeOfDeletedInset @@ -1959,8 +2045,8 @@ bool Paragraph::latex(Buffer const & buf, // 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) { @@ -1995,13 +2081,13 @@ bool Paragraph::latex(Buffer const & buf, if (c == ' ') { // FIXME: integrate this case in latexSpecialChar // Do not print the separation of the optional argument - // if style->pass_thru is false. This works because + // if style.pass_thru is false. This works because // latexSpecialChar ignores spaces if - // style->pass_thru is false. + // style.pass_thru is false. if (i != body_pos - 1) { if (d->simpleTeXBlanks( runparams, os, texrow, - i, column, font, *style)) { + i, column, font, style)) { // A surrogate pair was output. We // must not call latexSpecialChar // in this iteration, since it would output @@ -2013,22 +2099,22 @@ bool Paragraph::latex(Buffer const & buf, } OutputParams rp = runparams; - rp.free_spacing = style->free_spacing; + rp.free_spacing = style.free_spacing; rp.local_font = &font; - rp.intitle = style->intitle; + rp.intitle = style.intitle; // Two major modes: LaTeX or plain // Handle here those cases common to both modes // and then split to handle the two modes separately. if (c == META_INSET) - d->latexInset(buf, bparams, os, + d->latexInset(bparams, os, texrow, rp, running_font, basefont, outerfont, open_font, - runningChange, *style, i, column); + runningChange, style, i, column); else { try { d->latexSpecialChar(os, rp, running_font, runningChange, - *style, i, column); + style, i, column); } catch (EncodingException & e) { if (runparams.dryrun) { os << "<" << _("LyX Warning: ") @@ -2044,7 +2130,7 @@ bool Paragraph::latex(Buffer const & buf, } } - // 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; } @@ -2080,10 +2166,10 @@ bool Paragraph::latex(Buffer const & buf, if (!asdefault) { column += d->endTeXParParams(bparams, os, texrow, - runparams.moving_arg); + runparams); } - LYXERR(Debug::LATEX, "SimpleTeXOnePar...done " << this); + LYXERR(Debug::LATEX, "Paragraph::latex... done " << this); return return_value; } @@ -2112,7 +2198,8 @@ bool Paragraph::emptyTag() const } -string Paragraph::getID(Buffer const & buf, OutputParams const & runparams) const +string Paragraph::getID(Buffer const & buf, OutputParams const & runparams) + const { for (pos_type i = 0; i < size(); ++i) { if (Inset const * inset = getInset(i)) { @@ -2128,12 +2215,13 @@ string Paragraph::getID(Buffer const & buf, OutputParams const & runparams) cons } -pos_type Paragraph::getFirstWord(Buffer const & buf, odocstream & os, OutputParams const & runparams) const +pos_type Paragraph::firstWord(odocstream & os, OutputParams const & runparams) + const { pos_type i; for (i = 0; i < size(); ++i) { if (Inset const * inset = getInset(i)) { - inset->docbook(buf, os, runparams); + inset->docbook(os, runparams); } else { char_type c = d->text_[i]; if (c == ' ') @@ -2170,11 +2258,11 @@ void Paragraph::simpleDocBookOnePar(Buffer const & buf, { bool emph_flag = false; - LayoutPtr const & style = d->layout_; + Layout const & style = *d->layout_; FontInfo font_old = - style->labeltype == LABEL_MANUAL ? style->labelfont : style->font; + style.labeltype == LABEL_MANUAL ? style.labelfont : style.font; - if (style->pass_thru && !d->onlyText(buf, outerfont, initial)) + if (style.pass_thru && !d->onlyText(buf, outerfont, initial)) os << "]]>"; // parsing main loop @@ -2193,11 +2281,11 @@ void Paragraph::simpleDocBookOnePar(Buffer const & buf, } if (Inset const * inset = getInset(i)) { - inset->docbook(buf, os, runparams); + inset->docbook(os, runparams); } else { char_type c = d->text_[i]; - if (style->pass_thru) + if (style.pass_thru) os.put(c); else os << sgml::escapeChar(c); @@ -2209,9 +2297,9 @@ void Paragraph::simpleDocBookOnePar(Buffer const & buf, os << ""; } - if (style->free_spacing) + if (style.free_spacing) os << '\n'; - if (style->pass_thru && !d->onlyText(buf, outerfont, initial)) + if (style.pass_thru && !d->onlyText(buf, outerfont, initial)) os << "lyxCode() == HFILL_CODE; + return inset && (inset->lyxCode() == SPACE_CODE && + inset->isStretchableSpace()); } @@ -2250,6 +2339,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 { @@ -2298,36 +2405,34 @@ bool Paragraph::isMultiLingual(BufferParams const & bparams) const } -// Convert the paragraph to a string. -// Used for building the table of contents -docstring const Paragraph::asString(Buffer const & buffer, bool label) const +docstring Paragraph::asString(int options) const { - return asString(buffer, 0, size(), label); + return asString(0, size(), options); } -docstring const Paragraph::asString(Buffer const & buffer, - 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)) + if (isPrintable(c) || c == '\t') os.put(c); - else if (c == META_INSET) - getInset(i)->textString(buffer, os); + else if (c == META_INSET && options & AS_STR_INSETS) + getInset(i)->textString(os); } return os.str(); } -void Paragraph::setInsetOwner(Inset * inset) +void Paragraph::setInsetOwner(Inset const * inset) { d->inset_owner_ = inset; } @@ -2339,30 +2444,32 @@ int Paragraph::id() const } -LayoutPtr const & Paragraph::layout() const +Layout const & Paragraph::layout() const { - return d->layout_; + return *d->layout_; } -void Paragraph::setLayout(LayoutPtr const & layout) +void Paragraph::setLayout(Layout const & layout) { - d->layout_ = layout; + d->layout_ = &layout; } -void Paragraph::setEmptyOrDefaultLayout(TextClass const & tclass) +void Paragraph::setPlainOrDefaultLayout(DocumentClass const & tclass) { - if (useEmptyLayout()) - setLayout(tclass.emptyLayout()); + if (usePlainLayout()) + setLayout(tclass.plainLayout()); else setLayout(tclass.defaultLayout()); } -Inset * Paragraph::inInset() const +Inset const & Paragraph::inInset() const { - return d->inset_owner_; + LASSERT(d->inset_owner_, throw ExceptionMessage(BufferException, + _("Memory problem"), _("Paragraph not properly initiliazed"))); + return *d->inset_owner_; } @@ -2402,7 +2509,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 = ' '; @@ -2410,7 +2517,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; } @@ -2418,21 +2525,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); @@ -2440,11 +2547,11 @@ char_type Paragraph::transformChar(char_type c, pos_type pos) const } -int Paragraph::checkBiblio(bool track_changes) +int Paragraph::checkBiblio(Buffer const & buffer) { - //FIXME From JS: - //This is getting more and more a mess. ...We really should clean - //up this bibitem issue for 1.6. See also bug 2743. + // FIXME From JS: + // This is getting more and more a mess. ...We really should clean + // up this bibitem issue for 1.6. See also bug 2743. // Add bibitem insets if necessary if (d->layout_->labeltype != LABEL_BIBLIO) @@ -2455,6 +2562,8 @@ int Paragraph::checkBiblio(bool track_changes) && d->text_[0] == META_INSET && d->insetlist_.begin()->inset->lyxCode() == BIBITEM_CODE; + bool track_changes = buffer.params().trackChanges; + docstring oldkey; docstring oldlabel; @@ -2477,13 +2586,13 @@ int Paragraph::checkBiblio(bool track_changes) break; } - //There was an InsetBibitem at the beginning, and we didn't - //have to erase one. + // There was an InsetBibitem at the beginning, and we didn't + // have to erase one. if (hasbibitem && erasedInsetPosition < 0) return 0; - //There was an InsetBibitem at the beginning and we did have to - //erase one. So we give its properties to the beginning inset. + // 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); @@ -2493,9 +2602,10 @@ int Paragraph::checkBiblio(bool track_changes) return -erasedInsetPosition; } - //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))); + // 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(buffer, InsetCommandParams(BIBITEM_CODE)); // restore values of previously deleted item in this par. if (!oldkey.empty()) inset->setParam("key", oldkey); @@ -2537,6 +2647,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); @@ -2699,7 +2815,7 @@ void Paragraph::deregisterWords() } -void Paragraph::collectWords(Buffer const & buf, CursorSlice const & sl) +void Paragraph::collectWords(CursorSlice const & sl) { // find new words bool inword = false; @@ -2726,8 +2842,7 @@ void Paragraph::collectWords(Buffer const & buf, CursorSlice const & sl) from.text()->getWord(from, to, WHOLE_WORD); if (to.pos() - from.pos() < 6) continue; - docstring word - = asString(buf, from.pos(), to.pos(), false); + docstring word = asString(from.pos(), to.pos(), false); d->words_.insert(word); //lyxerr << word << " "; } @@ -2744,11 +2859,11 @@ void Paragraph::registerWords() } -void Paragraph::updateWords(Buffer const & buf, CursorSlice const & sl) +void Paragraph::updateWords(CursorSlice const & sl) { - BOOST_ASSERT(&sl.paragraph() == this); + LASSERT(&sl.paragraph() == this, /**/); deregisterWords(); - collectWords(buf, sl); + collectWords(sl); registerWords(); }