]> git.lyx.org Git - lyx.git/blobdiff - src/Paragraph.cpp
fix linking error in the frontend
[lyx.git] / src / Paragraph.cpp
index e870583d4e3bab9322015e3f365bbcb3019eafa9..1ec43ed1634621b2219c18c00520c8adbd5b7840 100644 (file)
@@ -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<bool, int> 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<InsetBibitem *>(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<InsetBibitem *>(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 *>(inset),
                    Change(track_changes ? Change::INSERTED : Change::UNCHANGED));
 
-       return true;
+       return 1;
+}
+
+
+void Paragraph::checkAuthors(AuthorList const & authorList)
+{
+       pimpl_->changes_.checkAuthors(authorList);
 }
 
 } // namespace lyx