]> git.lyx.org Git - lyx.git/blobdiff - src/paragraph.C
minimal effort implementation of:
[lyx.git] / src / paragraph.C
index 795047c923b4b0adfe59725ef7cb1409b7bd3c90..6975c091f04510b1fbc97ea793775cbc825b8144 100644 (file)
 #include "support/lstrings.h"
 #include "support/textutils.h"
 #include "support/convert.h"
+#include "support/unicode.h"
 
 #include <boost/tuple/tuple.hpp>
 #include <boost/bind.hpp>
 
+#include <algorithm>
 #include <list>
 #include <stack>
 #include <sstream>
 
 using lyx::pos_type;
+using lyx::char_type;
 
 using lyx::support::subst;
 
@@ -65,10 +68,6 @@ using std::ostream;
 using std::ostringstream;
 
 
-ParagraphList::ParagraphList()
-{}
-
-
 Paragraph::Paragraph()
        : begin_of_body_(0), pimpl_(new Paragraph::Pimpl(this))
 {
@@ -80,7 +79,8 @@ Paragraph::Paragraph()
 Paragraph::Paragraph(Paragraph const & par)
        :       itemdepth(par.itemdepth), insetlist(par.insetlist),
                dim_(par.dim_),
-               rows_(par.rows_), layout_(par.layout_),
+               rows_(par.rows_), rowSignature_(par.rowSignature_),
+               layout_(par.layout_),
                text_(par.text_), begin_of_body_(par.begin_of_body_),
          pimpl_(new Paragraph::Pimpl(*par.pimpl_, this))
 {
@@ -106,6 +106,7 @@ Paragraph & Paragraph::operator=(Paragraph const & par)
 
                rows_ = par.rows_;
                dim_ = par.dim_;
+               rowSignature_ = par.rowSignature_;
                layout_ = par.layout();
                text_ = par.text_;
                begin_of_body_ = par.begin_of_body_;
@@ -156,12 +157,15 @@ void Paragraph::write(Buffer const & buf, ostream & os,
        lyx::time_type const curtime(lyx::current_time());
 
        int column = 0;
-       for (pos_type i = 0; i < size(); ++i) {
+       for (pos_type i = 0; i <= size(); ++i) {
 
-               Change change = pimpl_->lookupChangeFull(i);
+               Change change = pimpl_->lookupChange(i);
                Changes::lyxMarkChange(os, column, curtime, running_change, change);
                running_change = change;
 
+               if (i == size())
+                       break;
+
                // Write font changes
                LyXFont font2 = getFontSettings(bparams, i);
                if (font2 != font1) {
@@ -210,9 +214,11 @@ void Paragraph::write(Buffer const & buf, ostream & os,
                        }
                        // this check is to amend a bug. LyX sometimes
                        // inserts '\0' this could cause problems.
-                       if (c != '\0')
-                               os << c;
-                       else
+                       if (c != '\0') {
+                               std::vector<char> tmp = ucs4_to_utf8(c);
+                               tmp.push_back('\0');
+                               os << &tmp[0];
+                       } else
                                lyxerr << "ERROR (Paragraph::writeFile):"
                                        " NULL char in structure." << endl;
                        ++column;
@@ -220,15 +226,6 @@ void Paragraph::write(Buffer const & buf, ostream & os,
                }
        }
 
-       // to make reading work properly
-       if (!size()) {
-               running_change = pimpl_->lookupChange(0);
-               Changes::lyxMarkChange(os, column, curtime,
-                       Change(Change::UNCHANGED), running_change);
-       }
-       Changes::lyxMarkChange(os, column, curtime,
-               running_change, Change(Change::UNCHANGED));
-
        os << "\n\\end_layout\n";
 }
 
@@ -333,8 +330,15 @@ FontSpan Paragraph::fontSpan(lyx::pos_type pos) const
        Pimpl::FontList::const_iterator cit = pimpl_->fontlist.begin();
        Pimpl::FontList::const_iterator end = pimpl_->fontlist.end();
        for (; cit != end; ++cit) {
-               if (cit->pos() >= pos)
-                       return FontSpan(start, cit->pos());
+               if (cit->pos() >= pos) {
+                       if (pos >= beginOfBody())
+                               return FontSpan(std::max(start, beginOfBody()),
+                                               cit->pos());
+                       else
+                               return FontSpan(start,
+                                               std::min(beginOfBody() - 1,
+                                                        cit->pos()));
+               }
                start = cit->pos() + 1;
        }
 
@@ -346,12 +350,12 @@ FontSpan Paragraph::fontSpan(lyx::pos_type pos) const
 
 
 // Gets uninstantiated font setting at position 0
-LyXFont const Paragraph::getFirstFontSettings() const
+LyXFont const Paragraph::getFirstFontSettings(BufferParams const & bparams) const
 {
        if (!empty() && !pimpl_->fontlist.empty())
                return pimpl_->fontlist[0].font();
 
-       return LyXFont(LyXFont::ALL_INHERIT);
+       return LyXFont(LyXFont::ALL_INHERIT, bparams.language);
 }
 
 
@@ -378,7 +382,7 @@ LyXFont const Paragraph::getFont(BufferParams const & bparams, pos_type pos,
        LyXFont font = getFontSettings(bparams, pos);
        font.realize(layoutfont);
        font.realize(outerfont);
-       font.realize(bparams.getLyXTextClass().defaultfont());
+       font.realize(bparams.getFont());
 
        return font;
 }
@@ -390,7 +394,7 @@ LyXFont const Paragraph::getLabelFont
        LyXFont tmpfont = layout()->labelfont;
        tmpfont.setLanguage(getParLanguage(bparams));
        tmpfont.realize(outerfont);
-       tmpfont.realize(bparams.getLyXTextClass().defaultfont());
+       tmpfont.realize(bparams.getFont());
        return tmpfont;
 }
 
@@ -401,7 +405,7 @@ LyXFont const Paragraph::getLayoutFont
        LyXFont tmpfont = layout()->font;
        tmpfont.setLanguage(getParLanguage(bparams));
        tmpfont.realize(outerfont);
-       tmpfont.realize(bparams.getLyXTextClass().defaultfont());
+       tmpfont.realize(bparams.getFont());
        return tmpfont;
 }
 
@@ -559,9 +563,8 @@ int Paragraph::stripLeadingSpaces()
                return 0;
 
        int i = 0;
-       while (!empty() && (isNewline(0) || isLineSeparator(0))) {
-               // Set Change::Type to Change::INSERTED to quietly remove it
-               setChange(0, Change::INSERTED);
+       while (!empty() && (isNewline(0) || isLineSeparator(0))
+               && (lookupChange(0).type != Change::DELETED)) {
                erase(0);
                ++i;
        }
@@ -695,7 +698,7 @@ InsetBibitem * Paragraph::bibitem() const
 
 bool Paragraph::forceDefaultParagraphs() const
 {
-       return inInset() && inInset()->forceDefaultParagraphs(inInset());
+       return inInset() && inInset()->forceDefaultParagraphs(0);
 }
 
 
@@ -886,7 +889,7 @@ bool Paragraph::simpleTeXOnePar(Buffer const & buf,
 
        LyXFont basefont;
 
-       LaTeXFeatures features(buf, bparams, runparams.nice);
+       LaTeXFeatures features(buf, bparams, runparams);
 
        // output change tracking marks only if desired,
        // if dvipost is installed,
@@ -1002,7 +1005,7 @@ bool Paragraph::simpleTeXOnePar(Buffer const & buf,
                        open_font = true;
                }
 
-               Change::Type change = pimpl_->lookupChange(i);
+               Change::Type change = pimpl_->lookupChange(i).type;
 
                column += Changes::latexMarkChange(os, running_change,
                        change, output);
@@ -1119,201 +1122,6 @@ void reset(PAR_TAG & p1, PAR_TAG const & p2)
 } // anon
 
 
-// Handle internal paragraph parsing -- layout already processed.
-void Paragraph::simpleLinuxDocOnePar(Buffer const & buf,
-                                    ostream & os,
-                                    LyXFont const & outerfont,
-                                    OutputParams const & runparams,
-                                    lyx::depth_type /*depth*/) const
-{
-       LyXLayout_ptr const & style = layout();
-
-       string::size_type char_line_count = 5;     // Heuristic choice ;-)
-
-       // gets paragraph main font
-       LyXFont font_old;
-       bool desc_on;
-       if (style->labeltype == LABEL_MANUAL) {
-               font_old = style->labelfont;
-               desc_on = true;
-       } else {
-               font_old = style->font;
-               desc_on = false;
-       }
-
-       LyXFont::FONT_FAMILY family_type = LyXFont::ROMAN_FAMILY;
-       LyXFont::FONT_SERIES series_type = LyXFont::MEDIUM_SERIES;
-       LyXFont::FONT_SHAPE  shape_type  = LyXFont::UP_SHAPE;
-       bool is_em = false;
-
-       stack<PAR_TAG> tag_state;
-       // parsing main loop
-       for (pos_type i = 0; i < size(); ++i) {
-
-               PAR_TAG tag_close = PAR_NONE;
-               list < PAR_TAG > tag_open;
-
-               LyXFont const font = getFont(buf.params(), i, outerfont);
-
-               if (font_old.family() != font.family()) {
-                       switch (family_type) {
-                       case LyXFont::SANS_FAMILY:
-                               tag_close |= SF;
-                               break;
-                       case LyXFont::TYPEWRITER_FAMILY:
-                               tag_close |= TT;
-                               break;
-                       default:
-                               break;
-                       }
-
-                       family_type = font.family();
-
-                       switch (family_type) {
-                       case LyXFont::SANS_FAMILY:
-                               tag_open.push_back(SF);
-                               break;
-                       case LyXFont::TYPEWRITER_FAMILY:
-                               tag_open.push_back(TT);
-                               break;
-                       default:
-                               break;
-                       }
-               }
-
-               if (font_old.series() != font.series()) {
-                       switch (series_type) {
-                       case LyXFont::BOLD_SERIES:
-                               tag_close |= BF;
-                               break;
-                       default:
-                               break;
-                       }
-
-                       series_type = font.series();
-
-                       switch (series_type) {
-                       case LyXFont::BOLD_SERIES:
-                               tag_open.push_back(BF);
-                               break;
-                       default:
-                               break;
-                       }
-
-               }
-
-               if (font_old.shape() != font.shape()) {
-                       switch (shape_type) {
-                       case LyXFont::ITALIC_SHAPE:
-                               tag_close |= IT;
-                               break;
-                       case LyXFont::SLANTED_SHAPE:
-                               tag_close |= SL;
-                               break;
-                       default:
-                               break;
-                       }
-
-                       shape_type = font.shape();
-
-                       switch (shape_type) {
-                       case LyXFont::ITALIC_SHAPE:
-                               tag_open.push_back(IT);
-                               break;
-                       case LyXFont::SLANTED_SHAPE:
-                               tag_open.push_back(SL);
-                               break;
-                       default:
-                               break;
-                       }
-               }
-               // handle <em> tag
-               if (font_old.emph() != font.emph()) {
-                       if (font.emph() == LyXFont::ON) {
-                               tag_open.push_back(EM);
-                               is_em = true;
-                       }
-                       else if (is_em) {
-                               tag_close |= EM;
-                               is_em = false;
-                       }
-               }
-
-               list < PAR_TAG > temp;
-               while (!tag_state.empty() && tag_close) {
-                       PAR_TAG k =  tag_state.top();
-                       tag_state.pop();
-                       os << "</" << tag_name(k) << '>';
-                       if (tag_close & k)
-                               reset(tag_close,k);
-                       else
-                               temp.push_back(k);
-               }
-
-               for(list< PAR_TAG >::const_iterator j = temp.begin();
-                   j != temp.end(); ++j) {
-                       tag_state.push(*j);
-                       os << '<' << tag_name(*j) << '>';
-               }
-
-               for(list< PAR_TAG >::const_iterator j = tag_open.begin();
-                   j != tag_open.end(); ++j) {
-                       tag_state.push(*j);
-                       os << '<' << tag_name(*j) << '>';
-               }
-
-               value_type c = getChar(i);
-
-
-               if (c == Paragraph::META_INSET) {
-                       getInset(i)->linuxdoc(buf, os, runparams);
-                       font_old = font;
-                       continue;
-               }
-
-               if (style->latexparam() == "CDATA") {
-                       // "TeX"-Mode on == > SGML-Mode on.
-                       if (c != '\0')
-                               os << c;
-                       ++char_line_count;
-               } else {
-                       bool ws;
-                       string str;
-                       boost::tie(ws, str) = sgml::escapeChar(c);
-                       if (ws && !isFreeSpacing()) {
-                               // in freespacing mode, spaces are
-                               // non-breaking characters
-                               if (desc_on) { // if char is ' ' then...
-                                       ++char_line_count;
-                                       sgmlLineBreak(os, char_line_count, 6);
-                                       os << "</tag>";
-                                       desc_on = false;
-                               } else  {
-                                       sgmlLineBreak(os, char_line_count, 1);
-                                       os << c;
-                               }
-                       } else {
-                               os << str;
-                               char_line_count += str.length();
-                       }
-               }
-               font_old = font;
-       }
-
-       while (!tag_state.empty()) {
-               os << "</" << tag_name(tag_state.top()) << '>';
-               tag_state.pop();
-       }
-
-       // resets description flag correctly
-       if (desc_on) {
-               // <tag> not closed...
-               sgmlLineBreak(os, char_line_count, 6);
-               os << "</tag>";
-       }
-}
-
-
 bool Paragraph::emptyTag() const
 {
        for (pos_type i = 0; i < size(); ++i) {
@@ -1462,7 +1270,7 @@ bool Paragraph::isNewline(pos_type pos) const
 bool Paragraph::isLineSeparator(pos_type pos) const
 {
        value_type const c = getChar(pos);
-       return IsLineSeparatorChar(c)
+       return isLineSeparatorChar(c)
                || (c == Paragraph::META_INSET && getInset(pos) &&
                getInset(pos)->isLineSeparator());
 }
@@ -1475,7 +1283,7 @@ bool Paragraph::isLetter(pos_type pos) const
                return getInset(pos)->isLetter();
        else {
                value_type const c = getChar(pos);
-               return IsLetterChar(c) || IsDigit(c);
+               return isLetterChar(c) || isDigit(c);
        }
 }
 
@@ -1484,7 +1292,7 @@ Language const *
 Paragraph::getParLanguage(BufferParams const & bparams) const
 {
        if (!empty())
-               return getFirstFontSettings().language();
+               return getFirstFontSettings(bparams).language();
 #ifdef WITH_WARNINGS
 #warning FIXME we should check the prev par as well (Lgb)
 #endif
@@ -1495,7 +1303,7 @@ Paragraph::getParLanguage(BufferParams const & bparams) const
 bool Paragraph::isRightToLeftPar(BufferParams const & bparams) const
 {
        return lyxrc.rtl_support
-               && getParLanguage(bparams)->RightToLeft()
+               && getParLanguage(bparams)->rightToLeft()
                && ownerCode() != InsetBase::ERT_CODE;
 }
 
@@ -1548,7 +1356,7 @@ string const Paragraph::asString(Buffer const & buffer,
 
        for (pos_type i = 0; i < size(); ++i) {
                value_type c = getChar(i);
-               if (IsPrintable(c))
+               if (isPrintable(c))
                        s += c;
                else if (c == META_INSET &&
                         getInset(i)->lyxCode() == InsetBase::MATH_CODE) {
@@ -1587,10 +1395,10 @@ string const Paragraph::asString(Buffer const & buffer,
 
        for (pos_type i = beg; i < end; ++i) {
                value_type const c = getUChar(buffer.params(), i);
-               if (IsPrintable(c))
+               if (isPrintable(c))
                        os << c;
                else if (c == META_INSET)
-                       getInset(i)->plaintext(buffer, os, runparams);
+                       getInset(i)->textString(buffer, os, runparams);
        }
 
        return os.str();
@@ -1621,26 +1429,19 @@ void Paragraph::untrackChanges()
 }
 
 
-void Paragraph::cleanChanges()
+void Paragraph::cleanChanges(ChangeTracking ct)
 {
-       pimpl_->cleanChanges();
+       pimpl_->cleanChanges(ct);
 }
 
 
-Change::Type Paragraph::lookupChange(lyx::pos_type pos) const
+Change const Paragraph::lookupChange(lyx::pos_type pos) const
 {
-       BOOST_ASSERT(empty() || pos < size());
+       BOOST_ASSERT(pos <= size());
        return pimpl_->lookupChange(pos);
 }
 
 
-Change const Paragraph::lookupChangeFull(lyx::pos_type pos) const
-{
-       BOOST_ASSERT(empty() || pos < size());
-       return pimpl_->lookupChangeFull(pos);
-}
-
-
 bool Paragraph::isChanged(pos_type start, pos_type end) const
 {
        return pimpl_->isChanged(start, end);
@@ -1653,9 +1454,15 @@ bool Paragraph::isChangeEdited(pos_type start, pos_type end) const
 }
 
 
-void Paragraph::setChange(lyx::pos_type pos, Change::Type type)
+void Paragraph::setChangeType(lyx::pos_type pos, Change::Type type)
+{
+       pimpl_->setChangeType(pos, type);
+}
+
+
+void Paragraph::setChange(lyx::pos_type pos, Change change)
 {
-       pimpl_->setChange(pos, type);
+       pimpl_->setChange(pos, change);
 }
 
 
@@ -1803,20 +1610,20 @@ size_t Paragraph::pos2row(pos_type pos) const
 }
 
 
-unsigned char Paragraph::transformChar(unsigned char c, pos_type pos) const
+char_type Paragraph::transformChar(char_type c, pos_type pos) const
 {
        if (!Encodings::is_arabic(c))
-               if (lyxrc.font_norm_type == LyXRC::ISO_8859_6_8 && IsDigit(c))
+               if (lyxrc.font_norm_type == LyXRC::ISO_8859_6_8 && isDigit(c))
                        return c + (0xb0 - '0');
                else
                        return c;
 
-       unsigned char const prev_char = pos > 0 ? getChar(pos - 1) : ' ';
-       unsigned char next_char = ' ';
+       value_type const prev_char = pos > 0 ? getChar(pos - 1) : ' ';
+       value_type next_char = ' ';
 
        for (pos_type i = pos + 1, end = size(); i < end; ++i) {
-               unsigned char const par_char = getChar(i);
-               if (!Encodings::IsComposeChar_arabic(par_char)) {
+               value_type const par_char = getChar(i);
+               if (!Encodings::isComposeChar_arabic(par_char)) {
                        next_char = par_char;
                        break;
                }
@@ -1825,15 +1632,15 @@ unsigned char Paragraph::transformChar(unsigned char c, pos_type pos) const
        if (Encodings::is_arabic(next_char)) {
                if (Encodings::is_arabic(prev_char) &&
                        !Encodings::is_arabic_special(prev_char))
-                       return Encodings::TransformChar(c, Encodings::FORM_MEDIAL);
+                       return Encodings::transformChar(c, Encodings::FORM_MEDIAL);
                else
-                       return Encodings::TransformChar(c, Encodings::FORM_INITIAL);
+                       return Encodings::transformChar(c, Encodings::FORM_INITIAL);
        } else {
                if (Encodings::is_arabic(prev_char) &&
                        !Encodings::is_arabic_special(prev_char))
-                       return Encodings::TransformChar(c, Encodings::FORM_FINAL);
+                       return Encodings::transformChar(c, Encodings::FORM_FINAL);
                else
-                       return Encodings::TransformChar(c, Encodings::FORM_ISOLATED);
+                       return Encodings::transformChar(c, Encodings::FORM_ISOLATED);
        }
 }