]> git.lyx.org Git - lyx.git/blobdiff - src/Paragraph.cpp
The mode changing math insets already provide the needed info, so
[lyx.git] / src / Paragraph.cpp
index 1cbb3f31638578e36e1a1a827d10c11592e1f611..eb966b8029cc7e616f0c180f9ee52e28508e9c57 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "Paragraph.h"
 
+#include "LayoutFile.h"
 #include "Buffer.h"
 #include "BufferParams.h"
 #include "Changes.h"
@@ -48,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"
@@ -78,7 +80,7 @@ class Paragraph::Private
 {
 public:
        ///
-       Private(Paragraph * owner);
+       Private(Paragraph * owner, Layout const & layout);
        /// "Copy constructor"
        Private(Private const &, Paragraph * owner);
 
@@ -189,9 +191,6 @@ public:
        ///
        InsetList insetlist_;
 
-       ///
-       LayoutPtr layout_;
-
        /// end of label
        pos_type begin_of_body_;
 
@@ -202,6 +201,8 @@ public:
        typedef std::set<docstring> Words;
        ///
        Words words_;
+       ///
+       Layout const * layout_;
 };
 
 
@@ -228,8 +229,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,8 +240,8 @@ 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++;
 }
@@ -248,8 +249,8 @@ Paragraph::Private::Private(Private const & p, Paragraph * owner)
 
 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 +295,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 +307,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 +315,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 +351,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 +387,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 +413,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 +426,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 +475,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) {
@@ -647,7 +648,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 +744,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")
@@ -1034,8 +1044,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();
@@ -1158,8 +1172,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;
                }
@@ -1208,7 +1221,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);
        }
@@ -1269,8 +1282,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);
@@ -1286,7 +1299,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();
@@ -1305,8 +1318,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);
 }
 
@@ -1329,7 +1341,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);
 
@@ -1374,8 +1386,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)
@@ -1410,14 +1421,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
@@ -1455,7 +1465,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_);
 }
 
 
@@ -1519,21 +1530,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
 {
        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}'
@@ -1555,9 +1566,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)) {
@@ -1611,19 +1622,28 @@ void Paragraph::setBeginOfBody()
 
 bool Paragraph::forceEmptyLayout() const
 {
-       return inInset() && inInset()->forceEmptyLayout();
+       Inset const * const inset = inInset();
+       if (!inset)
+               return true;
+       return inset->forceEmptyLayout();
 }
 
 
 bool Paragraph::allowParagraphCustomization() const
 {
-       return inInset() && inInset()->allowParagraphCustomization(0);
+       Inset const * const inset = inInset();
+       if (!inset)
+               return true;
+       return inset->allowParagraphCustomization();
 }
 
 
 bool Paragraph::useEmptyLayout() const
 {
-       return inInset() && inInset()->useEmptyLayout();
+       Inset const * const inset = inInset();
+       if (!inset)
+               return false;
+       return inset->useEmptyLayout();
 }
 
 
@@ -1817,19 +1837,11 @@ bool Paragraph::latex(BufferParams const & bparams,
 
        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();
 
-       if (asdefault)
-               style = bparams.documentClass().emptyLayout();
-        else
-               style = d->layout_;
+       Layout const & style = asdefault ?
+               bparams.documentClass().emptyLayout() :
+               *d->layout_;
 
        // Current base font for all inherited font changes, without any
        // change caused by an individual character, except for the language:
@@ -1864,7 +1876,7 @@ bool Paragraph::latex(BufferParams const & bparams,
 
        // if the paragraph is empty, the loop will not be entered at all
        if (empty()) {
-               if (style->isCommand()) {
+               if (style.isCommand()) {
                        os << '{';
                        ++column;
                }
@@ -1893,7 +1905,7 @@ bool Paragraph::latex(BufferParams const & bparams,
                                os << "}] ";
                                column +=3;
                        }
-                       if (style->isCommand()) {
+                       if (style.isCommand()) {
                                os << '{';
                                ++column;
                        }
@@ -1993,13 +2005,13 @@ bool Paragraph::latex(BufferParams const & bparams,
                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
@@ -2011,9 +2023,9 @@ bool Paragraph::latex(BufferParams const & bparams,
                }
 
                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
@@ -2022,11 +2034,11 @@ bool Paragraph::latex(BufferParams const & bparams,
                        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: ")
@@ -2170,11 +2182,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
@@ -2197,7 +2209,7 @@ void Paragraph::simpleDocBookOnePar(Buffer const & buf,
                } 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 +2221,9 @@ void Paragraph::simpleDocBookOnePar(Buffer const & buf,
                os << "</emphasis>";
        }
 
-       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 << "<![CDATA[";
 }
 
@@ -2219,7 +2231,8 @@ void Paragraph::simpleDocBookOnePar(Buffer const & buf,
 bool Paragraph::isHfill(pos_type pos) const
 {
        Inset const * inset = getInset(pos);
-       return inset && inset->lyxCode() == HFILL_CODE;
+       return inset && (inset->lyxCode() == SPACE_CODE &&
+                        inset->isStretchableSpace());
 }
 
 
@@ -2298,25 +2311,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);
        }
 
@@ -2336,15 +2350,15 @@ 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;
 }
 
 
@@ -2399,7 +2413,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 = ' ';
@@ -2407,7 +2421,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;
                }
@@ -2415,21 +2429,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);
@@ -2494,8 +2508,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 &>(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);
@@ -2699,7 +2713,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;
@@ -2743,11 +2757,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();
 }