X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FParagraph.cpp;h=1ec43ed1634621b2219c18c00520c8adbd5b7840;hb=da1c04ea9a13dcfe75ad7e727811e9d3004609aa;hp=e870583d4e3bab9322015e3f365bbcb3019eafa9;hpb=a8010a4dc63e1619090bfaff80556071d6f02957;p=lyx.git diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp index e870583d4e..1ec43ed163 100644 --- a/src/Paragraph.cpp +++ b/src/Paragraph.cpp @@ -42,6 +42,7 @@ #include "TexRow.h" #include "VSpace.h" +#include "frontends/alert.h" #include "frontends/FontMetrics.h" #include "insets/InsetBibitem.h" @@ -66,6 +67,7 @@ using std::ostream; namespace lyx { using support::contains; +using support::suffixIs; using support::rsplit; @@ -176,21 +178,21 @@ public: /// Output the surrogate pair formed by \p c and \p next to \p os. /// \return the number of characters written. int latexSurrogatePair(odocstream & os, value_type c, value_type next, - Encoding const &); + Encoding const &); /// Output a space in appropriate formatting (or a surrogate pair /// if the next character is a combining character). /// \return whether a surrogate pair was output. bool simpleTeXBlanks(Encoding const &, - odocstream &, TexRow & texrow, + odocstream &, TexRow & texrow, pos_type & i, unsigned int & column, Font const & font, Layout const & style); /// void simpleTeXSpecialChars(Buffer const &, BufferParams const &, - odocstream &, - TexRow & texrow, OutputParams const &, - Font & running_font, + odocstream &, + TexRow & texrow, OutputParams &, + Font & running_font, Font & basefont, Font const & outerfont, bool & open_font, @@ -210,7 +212,7 @@ public: /// ParagraphParameters params; -private: +//private: /// pos_type size() const { return owner_->size(); } /// match a string against a particular point in the paragraph @@ -445,7 +447,7 @@ void Paragraph::Pimpl::insertChar(pos_type pos, value_type c, Change const & cha // Update the font table. FontTable search_font(pos, Font()); - for (FontList::iterator it + for (FontList::iterator it = lower_bound(fontlist.begin(), fontlist.end(), search_font, matchFT()); it != fontlist.end(); ++it) { @@ -458,7 +460,7 @@ void Paragraph::Pimpl::insertChar(pos_type pos, value_type c, Change const & cha void Paragraph::Pimpl::insertInset(pos_type pos, Inset * inset, - Change const & change) + Change const & change) { BOOST_ASSERT(inset); BOOST_ASSERT(pos >= 0 && pos <= size()); @@ -480,7 +482,7 @@ bool Paragraph::Pimpl::eraseChar(pos_type pos, bool trackChanges) if (trackChanges) { Change change = changes_.lookup(pos); - // set the character to DELETED if + // set the character to DELETED if // a) it was previously unchanged or // b) it was inserted by a co-author @@ -580,8 +582,8 @@ int Paragraph::Pimpl::latexSurrogatePair(odocstream & os, value_type c, bool Paragraph::Pimpl::simpleTeXBlanks(Encoding const & encoding, - odocstream & os, TexRow & texrow, - pos_type & i, + odocstream & os, TexRow & texrow, + pos_type & i, unsigned int & column, Font const & font, Layout const & style) @@ -660,7 +662,7 @@ void Paragraph::Pimpl::simpleTeXSpecialChars(Buffer const & buf, BufferParams const & bparams, odocstream & os, TexRow & texrow, - OutputParams const & runparams, + OutputParams & runparams, Font & running_font, Font & basefont, Font const & outerfont, @@ -724,6 +726,11 @@ void Paragraph::Pimpl::simpleTeXSpecialChars(Buffer const & buf, break; } + if (lookupChange(i).type == Change::DELETED) { + if( ++runparams.inDeletedInset == 1) + runparams.changeOfDeletedInset = lookupChange(i); + } + if (inset->canTrackChanges()) { column += Changes::latexMarkChange(os, bparams, running_change, Change(Change::UNCHANGED)); @@ -737,30 +744,56 @@ void Paragraph::Pimpl::simpleTeXSpecialChars(Buffer const & buf, || inset->lyxCode() == Inset::MATH_CODE || inset->lyxCode() == Inset::URL_CODE) && running_font.isRightToLeft()) { - os << "\\L{"; + if (running_font.language()->lang() == "farsi") + os << "\\beginL{}"; + else + os << "\\L{"; close = true; } -#ifdef WITH_WARNINGS -#warning Bug: we can have an empty font change here! +// FIXME: Bug: we can have an empty font change here! // if there has just been a font change, we are going to close it // right now, which means stupid latex code like \textsf{}. AFAIK, // this does not harm dvi output. A minor bug, thus (JMarc) -#endif - // some insets cannot be inside a font change command + // Some insets cannot be inside a font change command. + // However, even such insets *can* be placed in \L or \R + // or their equivalents (for RTL language switches), so we don't + // close the language in those cases. + // ArabTeX, though, cannot handle this special behavior, it seems. + bool arabtex = basefont.language()->lang() == "arabic_arabtex" || + running_font.language()->lang() == "arabic_arabtex"; if (open_font && inset->noFontChange()) { - column += running_font.latexWriteEndChanges( + bool closeLanguage = arabtex || + basefont.isRightToLeft() == running_font.isRightToLeft(); + unsigned int count = running_font.latexWriteEndChanges( os, bparams, runparams, - basefont, basefont); - open_font = false; - basefont = owner_->getLayoutFont(bparams, outerfont); - running_font = basefont; + basefont, basefont, closeLanguage); + column += count; + // if any font properties were closed, update the running_font, + // making sure, however, to leave the language as it was + if (count > 0) { + // FIXME: probably a better way to keep track of the old + // language, than copying the entire font? + Font const copy_font(running_font); + basefont = owner_->getLayoutFont(bparams, outerfont); + running_font = basefont; + if (!closeLanguage) + running_font.setLanguage(copy_font.language()); + // leave font open if language is still open + open_font = (running_font.language() == basefont.language()); + if (closeLanguage) + runparams.local_font = &basefont; + } } int tmp = inset->latex(buf, os, runparams); - if (close) - os << '}'; + if (close) { + if (running_font.language()->lang() == "farsi") + os << "\\endL{}"; + else + os << '}'; + } if (tmp) { for (int j = 0; j < tmp; ++j) { @@ -771,6 +804,10 @@ void Paragraph::Pimpl::simpleTeXSpecialChars(Buffer const & buf, } else { column += os.tellp() - len; } + + if (lookupChange(i).type == Change::DELETED) { + --runparams.inDeletedInset; + } } break; @@ -1103,7 +1140,7 @@ void Paragraph::write(Buffer const & buf, ostream & os, } // First write the layout - os << "\n\\begin_layout " << layout()->name() << '\n'; + os << "\n\\begin_layout " << to_utf8(layout()->name()) << '\n'; params().write(os); @@ -1204,7 +1241,7 @@ int Paragraph::eraseChars(pos_type start, pos_type end, bool trackChanges) void Paragraph::insert(pos_type start, docstring const & str, - Font const & font, Change const & change) + Font const & font, Change const & change) { for (size_t i = 0, n = str.size(); i != n ; ++i) insertChar(start + i, str[i], font, change); @@ -1212,24 +1249,24 @@ void Paragraph::insert(pos_type start, docstring const & str, void Paragraph::insertChar(pos_type pos, Paragraph::value_type c, - bool trackChanges) + bool trackChanges) { pimpl_->insertChar(pos, c, Change(trackChanges ? - Change::INSERTED : Change::UNCHANGED)); + Change::INSERTED : Change::UNCHANGED)); } void Paragraph::insertChar(pos_type pos, Paragraph::value_type c, - Font const & font, bool trackChanges) + Font const & font, bool trackChanges) { pimpl_->insertChar(pos, c, Change(trackChanges ? - Change::INSERTED : Change::UNCHANGED)); + Change::INSERTED : Change::UNCHANGED)); setFont(pos, font); } void Paragraph::insertChar(pos_type pos, Paragraph::value_type c, - Font const & font, Change const & change) + Font const & font, Change const & change) { pimpl_->insertChar(pos, c, change); setFont(pos, font); @@ -1237,17 +1274,29 @@ void Paragraph::insertChar(pos_type pos, Paragraph::value_type c, void Paragraph::insertInset(pos_type pos, Inset * inset, - Change const & change) + Change const & change) { pimpl_->insertInset(pos, inset, change); } void Paragraph::insertInset(pos_type pos, Inset * inset, - Font const & font, Change const & change) + Font const & font, Change const & change) { pimpl_->insertInset(pos, inset, change); + // Set the font/language of the inset... setFont(pos, font); + // ... as well as the font/language of the text inside the inset + // FIXME: This is far from perfect. It basically overrides work being done + // in the InsetText constructor. Also, it doesn't work for Tables + // (precisely because each cell's font/language is set in the Table's + // constructor, so by now it's too late). The long-term solution should + // be moving current_font into Cursor, and getting rid of all this... + // (see http://thread.gmane.org/gmane.editors.lyx.devel/88869/focus=88944) + if (inset->asTextInset()) { + inset->asTextInset()->text_.current_font = font; + inset->asTextInset()->text_.real_current_font = font; + } } @@ -1621,8 +1670,7 @@ docstring Paragraph::expandLabel(Layout_ptr const & layout, size_t const j = fmt.find('@', i + 1); if (j != docstring::npos) { docstring parent(fmt, i + 1, j - i - 1); - // FIXME UNICODE - docstring label = expandLabel(tclass[to_utf8(parent)], bparams); + docstring label = expandLabel(tclass[parent], bparams); fmt = docstring(fmt, 0, i) + label + docstring(fmt, j + 1, docstring::npos); } } @@ -1634,9 +1682,13 @@ docstring Paragraph::expandLabel(Layout_ptr const & layout, void Paragraph::applyLayout(Layout_ptr const & new_layout) { layout(new_layout); - params().labelWidthString(docstring()); - params().align(LYX_ALIGN_LAYOUT); - params().spacing(Spacing(Spacing::Default)); + LyXAlignment const oldAlign = params().align(); + + if (!(oldAlign & layout()->alignpossible)) { + frontend::Alert::warning(_("Alignment not permitted"), + _("The new layout does not permit the alignment previously used.\nSetting to default.")); + params().align(LYX_ALIGN_LAYOUT); + } } @@ -1765,7 +1817,7 @@ void adjust_row_column(string const & str, TexRow & texrow, int & column) // This could go to ParagraphParameters if we want to int Paragraph::startTeXParParams(BufferParams const & bparams, - odocstream & os, TexRow & texrow, + odocstream & os, TexRow & texrow, bool moving_arg) const { int column = 0; @@ -1774,8 +1826,13 @@ int Paragraph::startTeXParParams(BufferParams const & bparams, os << "\\noindent "; column += 10; } + + LyXAlignment const curAlign = params().align(); - switch (params().align()) { + if (curAlign == layout()->align) + return column; + + switch (curAlign) { case LYX_ALIGN_NONE: case LYX_ALIGN_BLOCK: case LYX_ALIGN_LAYOUT: @@ -1791,7 +1848,7 @@ int Paragraph::startTeXParParams(BufferParams const & bparams, break; } - switch (params().align()) { + switch (curAlign) { case LYX_ALIGN_NONE: case LYX_ALIGN_BLOCK: case LYX_ALIGN_LAYOUT: @@ -1829,8 +1886,8 @@ int Paragraph::startTeXParParams(BufferParams const & bparams, // This could go to ParagraphParameters if we want to -int Paragraph::endTeXParParams(BufferParams const & bparams, - odocstream & os, TexRow & texrow, +int Paragraph::endTeXParParams(BufferParams const & bparams, + odocstream & os, TexRow & texrow, bool moving_arg) const { int column = 0; @@ -1982,12 +2039,13 @@ bool Paragraph::simpleTeXOnePar(Buffer const & buf, } if (!asdefault) - column += startTeXParParams(bparams, os, + column += startTeXParParams(bparams, os, texrow, runparams.moving_arg); } - Change const & change = pimpl_->lookupChange(i); + Change const & change = runparams.inDeletedInset ? runparams.changeOfDeletedInset + : pimpl_->lookupChange(i); if (bparams.outputChanges && runningChange != change) { if (open_font) { @@ -2009,7 +2067,7 @@ bool Paragraph::simpleTeXOnePar(Buffer const & buf, } ++column; - + value_type const c = getChar(i); // Fully instantiated font @@ -2032,11 +2090,11 @@ bool Paragraph::simpleTeXOnePar(Buffer const & buf, // Switch file encoding if necessary if (runparams.encoding->package() == Encoding::inputenc && font.language()->encoding()->package() == Encoding::inputenc) { - int const count = switchEncoding(os, bparams, + std::pair const enc_switch = switchEncoding(os, bparams, runparams.moving_arg, *(runparams.encoding), *(font.language()->encoding())); - if (count > 0) { - column += count; + if (enc_switch.first) { + column += enc_switch.second; runparams.encoding = font.language()->encoding(); } } @@ -2046,11 +2104,20 @@ bool Paragraph::simpleTeXOnePar(Buffer const & buf, font.language() != running_font.language()) && i != body_pos - 1) { - column += font.latexWriteStartChanges(os, bparams, - runparams, basefont, - last_font); + odocstringstream ods; + column += font.latexWriteStartChanges(ods, bparams, + runparams, basefont, + last_font); running_font = font; open_font = true; + docstring fontchange = ods.str(); + // check if the fontchange ends with a trailing blank + // (like "\small " (see bug 3382) + if (suffixIs(fontchange, ' ') && c == ' ') + os << fontchange.substr(0, fontchange.size() - 1) + << from_ascii("{}"); + else + os << fontchange; } if (c == ' ') { @@ -2080,6 +2147,10 @@ bool Paragraph::simpleTeXOnePar(Buffer const & buf, texrow, rp, running_font, basefont, outerfont, open_font, runningChange, *style, i, column, c); + + // Set the encoding to that returned from simpleTeXSpecialChars (see + // comment for encoding member in OutputParams.h) + runparams.encoding = rp.encoding; } // If we have an open font definition, we have to close it @@ -2095,11 +2166,9 @@ bool Paragraph::simpleTeXOnePar(Buffer const & buf, runparams, basefont, basefont); } #else -#ifdef WITH_WARNINGS -//#warning For now we ALWAYS have to close the foreign font settings if they are -//#warning there as we start another \selectlanguage with the next paragraph if -//#warning we are in need of this. This should be fixed sometime (Jug) -#endif +//FIXME: For now we ALWAYS have to close the foreign font settings if they are +//FIXME: there as we start another \selectlanguage with the next paragraph if +//FIXME: we are in need of this. This should be fixed sometime (Jug) running_font.latexWriteEndChanges(os, bparams, runparams, basefont, basefont); #endif @@ -2114,7 +2183,7 @@ bool Paragraph::simpleTeXOnePar(Buffer const & buf, } if (!asdefault) { - column += endTeXParParams(bparams, os, texrow, + column += endTeXParParams(bparams, os, texrow, runparams.moving_arg); } @@ -2220,7 +2289,7 @@ pos_type Paragraph::getFirstWord(Buffer const & buf, odocstream & os, OutputPara if (c == ' ') break; os << sgml::escapeChar(c); - } + } } return i; } @@ -2280,9 +2349,9 @@ void Paragraph::simpleDocBookOnePar(Buffer const & buf, value_type c = getChar(i); if (style->pass_thru) - os.put(c); + os.put(c); else - os << sgml::escapeChar(c); + os << sgml::escapeChar(c); } font_old = font; } @@ -2331,9 +2400,7 @@ Paragraph::getParLanguage(BufferParams const & bparams) const { if (!empty()) return getFirstFontSettings(bparams).language(); -#ifdef WITH_WARNINGS -#warning FIXME we should check the prev par as well (Lgb) -#endif + // FIXME: we should check the prev par as well (Lgb) return bparams.language; } @@ -2394,7 +2461,7 @@ docstring const Paragraph::asString(Buffer const & buffer, os << params().labelString() << ' '; for (pos_type i = beg; i < end; ++i) { - value_type const c = getUChar(buffer.params(), i); + value_type const c = getChar(i); if (isPrintable(c)) os.put(c); else if (c == META_INSET) @@ -2592,11 +2659,15 @@ bool Paragraph::hfillExpansion(Row const & row, pos_type pos) const } -bool Paragraph::checkBiblio(bool track_changes) +int Paragraph::checkBiblio(bool track_changes) { + //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 (layout()->labeltype != LABEL_BIBLIO) - return false; + return 0; bool hasbibitem = !insetlist.empty() // Insist on it being in pos 0 @@ -2606,33 +2677,58 @@ bool Paragraph::checkBiblio(bool track_changes) docstring oldkey; docstring oldlabel; - // remove bibitems in pos != 0 - // restore them later in pos 0 if necessary + // remove a bibitem in pos != 0 + // restore it later in pos 0 if necessary // (e.g. if a user inserts contents _before_ the item) - InsetList::const_iterator it = insetlist.begin(); - InsetList::const_iterator end = insetlist.end(); + // we're assuming there's only one of these, which there + // should be. + int erasedInsetPosition = -1; + InsetList::iterator it = insetlist.begin(); + InsetList::iterator end = insetlist.end(); for (; it != end; ++it) if (it->inset->lyxCode() == Inset::BIBITEM_CODE && it->pos > 0) { InsetBibitem * olditem = static_cast(it->inset); oldkey = olditem->getParam("key"); oldlabel = olditem->getParam("label"); - eraseChar(it->pos, track_changes); + erasedInsetPosition = it->pos; + eraseChar(erasedInsetPosition, track_changes); + break; } - if (hasbibitem) - return false; + //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. + if (hasbibitem) { + InsetBibitem * inset = + static_cast(insetlist.begin()->inset); + if (!oldkey.empty()) + inset->setParam("key", oldkey); + inset->setParam("label", oldlabel); + 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"))); // restore values of previously deleted item in this par. if (!oldkey.empty()) inset->setParam("key", oldkey); - if (!oldlabel.empty()) - inset->setParam("label", oldlabel); + inset->setParam("label", oldlabel); insertInset(0, static_cast(inset), Change(track_changes ? Change::INSERTED : Change::UNCHANGED)); - return true; + return 1; +} + + +void Paragraph::checkAuthors(AuthorList const & authorList) +{ + pimpl_->changes_.checkAuthors(authorList); } } // namespace lyx