]> git.lyx.org Git - lyx.git/blobdiff - src/paragraph.C
- Link against qt-mt333.lib which is what the current qt3 cvs produces
[lyx.git] / src / paragraph.C
index 7073f641ed2e325df6eb3506b262217732b733e6..81e4038a6ece70adf3056534b6ad38e223936089 100644 (file)
@@ -27,6 +27,7 @@
 #include "debug.h"
 #include "gettext.h"
 #include "language.h"
+#include "LaTeXFeatures.h"
 #include "lyxfont.h"
 #include "lyxrc.h"
 #include "lyxrow.h"
@@ -42,7 +43,7 @@
 
 #include "support/lstrings.h"
 #include "support/textutils.h"
-#include "support/tostr.h"
+#include "support/convert.h"
 
 #include <boost/tuple/tuple.hpp>
 #include <boost/bind.hpp>
@@ -53,7 +54,6 @@
 
 using lyx::pos_type;
 
-using lyx::support::contains;
 using lyx::support::subst;
 
 using std::distance;
@@ -70,10 +70,8 @@ ParagraphList::ParagraphList()
 
 
 Paragraph::Paragraph()
-       : y(0), height(0), begin_of_body_(0),
-         pimpl_(new Paragraph::Pimpl(this))
+       : begin_of_body_(0), pimpl_(new Paragraph::Pimpl(this))
 {
-       //lyxerr << "sizeof Paragraph::Pimpl: " << sizeof(Paragraph::Pimpl) << endl;
        itemdepth = 0;
        params().clear();
 }
@@ -81,8 +79,8 @@ Paragraph::Paragraph()
 
 Paragraph::Paragraph(Paragraph const & par)
        :       itemdepth(par.itemdepth), insetlist(par.insetlist),
-               rows(par.rows), y(par.y), height(par.height),
-               width(par.width), layout_(par.layout_),
+               dim_(par.dim_),
+               rows_(par.rows_), layout_(par.layout_),
                text_(par.text_), begin_of_body_(par.begin_of_body_),
          pimpl_(new Paragraph::Pimpl(*par.pimpl_, this))
 {
@@ -106,10 +104,8 @@ Paragraph & Paragraph::operator=(Paragraph const & par)
                for (; it != end; ++it)
                        it->inset = it->inset->clone().release();
 
-               rows = par.rows;
-               y = par.y;
-               height = par.height;
-               width = par.width;
+               rows_ = par.rows_;
+               dim_ = par.dim_;
                layout_ = par.layout();
                text_ = par.text_;
                begin_of_body_ = par.begin_of_body_;
@@ -138,12 +134,12 @@ void Paragraph::write(Buffer const & buf, ostream & os,
        if (dth != params().depth()) {
                if (params().depth() > dth) {
                        while (params().depth() > dth) {
-                               os << "\n\\begin_deeper ";
+                               os << "\n\\begin_deeper";
                                ++dth;
                        }
                } else {
                        while (params().depth() < dth) {
-                               os << "\n\\end_deeper ";
+                               os << "\n\\end_deeper";
                                --dth;
                        }
                }
@@ -161,10 +157,6 @@ void Paragraph::write(Buffer const & buf, ostream & os,
 
        int column = 0;
        for (pos_type i = 0; i < size(); ++i) {
-               if (!i) {
-                       os << '\n';
-                       column = 0;
-               }
 
                Change change = pimpl_->lookupChangeFull(i);
                Changes::lyxMarkChange(os, column, curtime, running_change, change);
@@ -190,15 +182,17 @@ void Paragraph::write(Buffer const & buf, ostream & os,
                                        // the file
                                        inset->write(buf, os);
                                } else {
-                                       os << "\n\\begin_inset ";
+                                       if (i)
+                                               os << '\n';
+                                       os << "\\begin_inset ";
                                        inset->write(buf, os);
-                                       os << "\n\\end_inset \n\n";
+                                       os << "\n\\end_inset\n\n";
                                        column = 0;
                                }
                }
                break;
                case '\\':
-                       os << "\n\\backslash \n";
+                       os << "\n\\backslash\n";
                        column = 0;
                        break;
                case '.':
@@ -307,7 +301,7 @@ void Paragraph::insertInset(pos_type pos, InsetBase * inset,
 }
 
 
-bool Paragraph::insetAllowed(InsetOld_code code)
+bool Paragraph::insetAllowed(InsetBase_code code)
 {
        return !pimpl_->inset_owner || pimpl_->inset_owner->insetAllowed(code);
 }
@@ -408,8 +402,8 @@ LyXFont const Paragraph::getFont(BufferParams const & bparams, pos_type pos,
 }
 
 
-LyXFont const Paragraph::getLabelFont(BufferParams const & bparams,
-                                     LyXFont const & outerfont) const
+LyXFont const Paragraph::getLabelFont
+       (BufferParams const & bparams, LyXFont const & outerfont) const
 {
        LyXFont tmpfont = layout()->labelfont;
        tmpfont.setLanguage(getParLanguage(bparams));
@@ -419,8 +413,8 @@ LyXFont const Paragraph::getLabelFont(BufferParams const & bparams,
 }
 
 
-LyXFont const Paragraph::getLayoutFont(BufferParams const & bparams,
-                                      LyXFont const & outerfont) const
+LyXFont const Paragraph::getLayoutFont
+       (BufferParams const & bparams, LyXFont const & outerfont) const
 {
        LyXFont tmpfont = layout()->font;
        tmpfont.setLanguage(getParLanguage(bparams));
@@ -431,9 +425,8 @@ LyXFont const Paragraph::getLayoutFont(BufferParams const & bparams,
 
 
 /// Returns the height of the highest font in range
-LyXFont_size
-Paragraph::highestFontInRange(pos_type startpos, pos_type endpos,
-                             LyXFont_size def_size) const
+LyXFont_size Paragraph::highestFontInRange
+       (pos_type startpos, pos_type endpos, LyXFont_size def_size) const
 {
        if (pimpl_->fontlist.empty())
                return def_size;
@@ -722,12 +715,6 @@ bool Paragraph::forceDefaultParagraphs() const
 }
 
 
-bool Paragraph::autoBreakRows() const
-{
-       return inInset() && static_cast<InsetText *>(inInset())->getAutoBreakRows();
-}
-
-
 namespace {
 
 // paragraphs inside floats need different alignment tags to avoid
@@ -914,21 +901,30 @@ bool Paragraph::simpleTeXOnePar(Buffer const & buf,
        }
 
        LyXFont basefont;
+       
+       LaTeXFeatures features(buf, bparams, runparams.nice);
+       
+       // output change tracking marks only if desired,
+       // if dvipost is installed,
+       // and with dvi/ps (other formats don't work)
+       bool const output = bparams.output_changes
+               && runparams.flavor == OutputParams::LATEX
+               && features.isAvailable("dvipost");
 
        // Maybe we have to create a optional argument.
        pos_type body_pos = beginOfBody();
        unsigned int column = 0;
 
        if (body_pos > 0) {
-               os << '[';
-               ++column;
+               // the optional argument is kept in curly brackets in
+               // case it contains a ']'
+               os << "[{";
+               column += 2;
                basefont = getLabelFont(bparams, outerfont);
        } else {
                basefont = getLayoutFont(bparams, outerfont);
        }
 
-       bool const moving_arg = runparams.moving_arg | style->needprotect;
-
        // Which font is currently active?
        LyXFont running_font(basefont);
        // Do we have an open font change?
@@ -945,7 +941,8 @@ bool Paragraph::simpleTeXOnePar(Buffer const & buf,
                        ++column;
                }
                if (!asdefault)
-                       column += startTeXParParams(bparams, os, moving_arg);
+                       column += startTeXParParams(bparams, os,
+                                                   runparams.moving_arg);
        }
 
        for (pos_type i = 0; i < size(); ++i) {
@@ -959,8 +956,8 @@ bool Paragraph::simpleTeXOnePar(Buffer const & buf,
                                }
                                basefont = getLayoutFont(bparams, outerfont);
                                running_font = basefont;
-                               os << ']';
-                               ++column;
+                               os << "}] ";
+                               column +=3;
                        }
                        if (style->isCommand()) {
                                os << '{';
@@ -969,7 +966,7 @@ bool Paragraph::simpleTeXOnePar(Buffer const & buf,
 
                        if (!asdefault)
                                column += startTeXParParams(bparams, os,
-                                                           moving_arg);
+                                                           runparams.moving_arg);
                }
 
                value_type c = getChar(i);
@@ -1023,24 +1020,28 @@ bool Paragraph::simpleTeXOnePar(Buffer const & buf,
 
                Change::Type change = pimpl_->lookupChange(i);
 
-               column += Changes::latexMarkChange(os, running_change, change);
+               column += Changes::latexMarkChange(os, running_change, 
+                       change, output);
                running_change = change;
 
-               OutputParams rp = runparams;
-               rp.moving_arg = moving_arg;
-               rp.free_spacing = style->free_spacing;
-               rp.lang = font.language()->babel();
-               rp.intitle = style->intitle;
-               pimpl_->simpleTeXSpecialChars(buf, bparams,
-                                             os, texrow, rp,
-                                             font, running_font,
-                                             basefont, outerfont, open_font,
-                                             running_change,
-                                             *style, i, column, c);
+               // do not output text which is marked deleted
+               // if change tracking output is not desired
+               if (output || running_change != Change::DELETED) {
+                       OutputParams rp = runparams;
+                       rp.free_spacing = style->free_spacing;
+                       rp.local_language = font.language()->babel();
+                       rp.intitle = style->intitle;
+                       pimpl_->simpleTeXSpecialChars(buf, bparams,
+                                               os, texrow, rp,
+                                               font, running_font,
+                                               basefont, outerfont, open_font,
+                                               running_change,
+                                               *style, i, column, c);
+               }
        }
 
        column += Changes::latexMarkChange(os,
-                       running_change, Change::UNCHANGED);
+                       running_change, Change::UNCHANGED, output);
 
        // If we have an open font definition, we have to close it
        if (open_font) {
@@ -1071,7 +1072,7 @@ bool Paragraph::simpleTeXOnePar(Buffer const & buf,
        }
 
        if (!asdefault) {
-               column += endTeXParParams(bparams, os, moving_arg);
+               column += endTeXParParams(bparams, os, runparams.moving_arg);
        }
 
        lyxerr[Debug::LATEX] << "SimpleTeXOnePar...done " << this << endl;
@@ -1277,7 +1278,7 @@ void Paragraph::simpleLinuxDocOnePar(Buffer const & buf,
                        os << '<' << tag_name(*j) << '>';
                }
 
-               char c = getChar(i);
+               value_type c = getChar(i);
 
 
                if (c == Paragraph::META_INSET) {
@@ -1329,14 +1330,39 @@ void Paragraph::simpleLinuxDocOnePar(Buffer const & buf,
 }
 
 
-string Paragraph::getDocbookId() const
+bool Paragraph::emptyTag() const
+{
+       for (pos_type i = 0; i < size(); ++i) {
+               if (isInset(i)) {
+                       InsetBase const * inset = getInset(i);
+                       InsetBase::Code lyx_code = inset->lyxCode();
+                       if (lyx_code != InsetBase::TOC_CODE &&
+                           lyx_code != InsetBase::INCLUDE_CODE &&
+                           lyx_code != InsetBase::GRAPHICS_CODE &&
+                           lyx_code != InsetBase::ERT_CODE &&
+                           lyx_code != InsetBase::FLOAT_CODE &&
+                           lyx_code != InsetBase::TABULAR_CODE) {
+                               return false;
+                       }
+               } else {
+                       value_type c = getChar(i);
+                       if (c != ' ' && c != '\t')
+                               return false;
+               }
+       }
+       return true;
+}
+
+
+string Paragraph::getID(Buffer const & buf, OutputParams const & runparams) const
 {
        for (pos_type i = 0; i < size(); ++i) {
                if (isInset(i)) {
                        InsetBase const * inset = getInset(i);
                        InsetBase::Code lyx_code = inset->lyxCode();
                        if (lyx_code == InsetBase::LABEL_CODE) {
-                               return static_cast<InsetCommand const *>(inset)->getContents();
+                               string const id = static_cast<InsetCommand const *>(inset)->getContents();
+                               return "id=\"" + sgml::cleanID(buf, runparams, id) + "\"";
                        }
                }
 
@@ -1345,122 +1371,100 @@ string Paragraph::getDocbookId() const
 }
 
 
+pos_type Paragraph::getFirstWord(Buffer const & buf, ostream & os, OutputParams const & runparams) const
+{
+       pos_type i;
+       for (i = 0; i < size(); ++i) {
+               if (isInset(i)) {
+                       InsetBase const * inset = getInset(i);
+                       inset->docbook(buf, os, runparams);
+               } else {
+                       value_type c = getChar(i);
+                       if (c == ' ')
+                               break;
+                       bool ws;
+                       string str;
+                       boost::tie(ws, str) = sgml::escapeChar(c);
+
+                       os << str;
+               }
+       }
+       return i;
+}
+
+
+bool Paragraph::onlyText(Buffer const & buf, LyXFont const & outerfont, pos_type initial) const
+{
+       LyXFont font_old;
+
+       for (pos_type i = initial; i < size(); ++i) {
+               LyXFont font = getFont(buf.params(), i, outerfont);
+               if (isInset(i))
+                       return false;
+               if (i != initial && font != font_old)
+                       return false;
+               font_old = font;
+       }
+
+       return true;
+}
+
+
 void Paragraph::simpleDocBookOnePar(Buffer const & buf,
                                    ostream & os,
-                                   LyXFont const & outerfont,
                                    OutputParams const & runparams,
-                                   lyx::depth_type depth) const
+                                   LyXFont const & outerfont,
+                                   pos_type initial) const
 {
        bool emph_flag = false;
 
        LyXLayout_ptr const & style = layout();
-       LyXLayout_ptr const & defaultstyle =
-               buf.params().getLyXTextClass().defaultLayout();
-
        LyXFont font_old =
                style->labeltype == LABEL_MANUAL ? style->labelfont : style->font;
 
-       int char_line_count = depth;
-       bool label_closed = true;
-       bool para_closed = true;
-
-       if (style->latextype == LATEX_ITEM_ENVIRONMENT) {
-               string ls = "";
-               Counters & counters = buf.params().getLyXTextClass().counters();
-               if (!style->free_spacing)
-                       os << string(depth,' ');
-               if (!style->labeltag().empty()) {
-                       os << "<" << style->labeltag() << ">\n";
-                       label_closed = false;
-               } else {
-                       if (!defaultstyle->latexparam().empty()) {
-                               counters.step("para");
-                               ls = tostr(counters.value("para"));
-                               ls = " id=\""
-                                       + subst(defaultstyle->latexparam(), "#", ls) + '"';
-                       }
-                       os << "<" << style->itemtag() << ">\n"
-                          << string(depth, ' ') << "<"
-                          << defaultstyle->latexname() << ls << ">\n";
-                       para_closed = false;
-               }
-       }
+       if (style->pass_thru && !onlyText(buf, outerfont, initial))
+               os << "]]>";
 
        // parsing main loop
-       for (pos_type i = 0; i < size(); ++i) {
+       for (pos_type i = initial; i < size(); ++i) {
                LyXFont font = getFont(buf.params(), i, outerfont);
 
                // handle <emphasis> tag
                if (font_old.emph() != font.emph()) {
                        if (font.emph() == LyXFont::ON) {
-                               if (style->latexparam() == "CDATA")
-                                       os << "]]>";
                                os << "<emphasis>";
-                               if (style->latexparam() == "CDATA")
-                                       os << "<![CDATA[";
                                emph_flag = true;
-                       } else if (i) {
-                               if (style->latexparam() == "CDATA")
-                                       os << "]]>";
+                       } else if (i != initial) {
                                os << "</emphasis>";
-                               if (style->latexparam() == "CDATA")
-                                       os << "<![CDATA[";
                                emph_flag = false;
                        }
                }
 
                if (isInset(i)) {
                        InsetBase const * inset = getInset(i);
-                       if (style->latexparam() == "CDATA")
-                               os << "]]>";
                        inset->docbook(buf, os, runparams);
-                       if (style->latexparam() == "CDATA")
-                               os << "<![CDATA[";
                } else {
-                       char c = getChar(i);
+                       value_type c = getChar(i);
                        bool ws;
                        string str;
                        boost::tie(ws, str) = sgml::escapeChar(c);
 
-                       if (style->pass_thru) {
+                       if (style->pass_thru)
                                os << c;
-                       } else if (isFreeSpacing() || c != ' ') {
-                                       os << str;
-                       } else if (!style->labeltag().empty() && !label_closed) {
-                               ++char_line_count;
-                               os << "\n</" << style->labeltag() << "><"
-                                  << style->itemtag() << "><"
-                                  << defaultstyle->latexname() << ">";
-                               label_closed = true;
-                               para_closed = false;
-                       } else {
-                               os << ' ';
-                       }
+                       else
+                               os << str;
                }
                font_old = font;
        }
 
        if (emph_flag) {
-               if (style->latexparam() == "CDATA")
-                       os << "]]>";
                os << "</emphasis>";
-               if (style->latexparam() == "CDATA")
-                       os << "<![CDATA[";
        }
 
-       // resets description flag correctly
-       if (!label_closed) {
-               // <term> not closed...
-               os << "</" << style->labeltag() << ">\n<"
-                  << style->itemtag() << "><"
-                  << defaultstyle->latexname() << ">&nbsp;";
-       }
-       if (!para_closed) {
-               os << "\n" << string(depth, ' ') << "</"
-                  << defaultstyle->latexname() << ">\n";
-       }
        if (style->free_spacing)
                os << '\n';
+       if (style->pass_thru && !onlyText(buf, outerfont, initial))
+               os << "<![CDATA[";
 }
 
 
@@ -1479,15 +1483,15 @@ bool IsInsetChar(char c)
 
 bool Paragraph::isHfill(pos_type pos) const
 {
-       return
-               isInset(pos) && getInset(pos)->lyxCode() == InsetBase::HFILL_CODE;
+       return isInset(pos)
+               && getInset(pos)->lyxCode() == InsetBase::HFILL_CODE;
 }
 
 
 bool Paragraph::isNewline(pos_type pos) const
 {
-       return
-               isInset(pos) && getInset(pos)->lyxCode() == InsetBase::NEWLINE_CODE;
+       return isInset(pos)
+               && getInset(pos)->lyxCode() == InsetBase::NEWLINE_CODE;
 }
 
 
@@ -1506,34 +1510,15 @@ bool Paragraph::isLineSeparator(pos_type pos) const
 }
 
 
-bool Paragraph::isKomma(pos_type pos) const
-{
-       return IsKommaChar(getChar(pos));
-}
-
-
 /// Used by the spellchecker
 bool Paragraph::isLetter(pos_type pos) const
-{
-       value_type const c = getChar(pos);
-       if (IsLetterChar(c))
-               return true;
-       if (isInset(pos))
-               return getInset(pos)->isLetter();
-       // We want to pass the ' and escape chars to ispell
-       string const extra = lyxrc.isp_esc_chars + '\'';
-       return contains(extra, c);
-}
-
-
-bool Paragraph::isWord(pos_type pos) const
 {
        if (isInset(pos))
                return getInset(pos)->isLetter();
-       value_type const c = getChar(pos);
-       return !(IsSeparatorChar(c)
-                 || IsKommaChar(c)
-                 || IsInsetChar(c));
+       else {
+               value_type const c = getChar(pos);
+               return IsLetterChar(c) || IsDigit(c);
+       }
 }
 
 
@@ -1734,25 +1719,6 @@ void Paragraph::rejectChange(pos_type start, pos_type end)
 }
 
 
-Paragraph::value_type Paragraph::getChar(pos_type pos) const
-{
-       // This is in the critical path!
-       pos_type const siz = text_.size();
-
-       BOOST_ASSERT(0 <= pos);
-       BOOST_ASSERT(pos <= siz);
-
-       if (pos == siz) {
-               lyxerr << "getChar() on pos " << pos << " in par id "
-                      << id() << " of size " << siz
-                      << "  is a bit silly !" << endl;
-               BOOST_ASSERT(false);
-       }
-
-       return text_[pos];
-}
-
-
 int Paragraph::id() const
 {
        return pimpl_->id_;
@@ -1827,34 +1793,34 @@ bool Paragraph::allowEmpty() const
 }
 
 
-RowList::iterator Paragraph::getRow(pos_type pos)
+Row & Paragraph::getRow(pos_type pos)
 {
-       RowList::iterator rit = rows.end();
-       RowList::iterator const begin = rows.begin();
+       RowList::iterator rit = rows_.end();
+       RowList::iterator const begin = rows_.begin();
 
        for (--rit; rit != begin && rit->pos() > pos; --rit)
                ;
 
-       return rit;
+       return *rit;
 }
 
 
-RowList::const_iterator Paragraph::getRow(pos_type pos) const
+Row const & Paragraph::getRow(pos_type pos) const
 {
-       RowList::const_iterator rit = rows.end();
-       RowList::const_iterator const begin = rows.begin();
+       RowList::const_iterator rit = rows_.end();
+       RowList::const_iterator const begin = rows_.begin();
 
        for (--rit; rit != begin && rit->pos() > pos; --rit)
                ;
 
-       return rit;
+       return *rit;
 }
 
 
-size_t Paragraph::row(pos_type pos) const
+size_t Paragraph::pos2row(pos_type pos) const
 {
-       RowList::const_iterator rit = rows.end();
-       RowList::const_iterator const begin = rows.begin();
+       RowList::const_iterator rit = rows_.end();
+       RowList::const_iterator const begin = rows_.begin();
 
        for (--rit; rit != begin && rit->pos() > pos; --rit)
                ;
@@ -1896,3 +1862,22 @@ unsigned char Paragraph::transformChar(unsigned char c, pos_type pos) const
                        return Encodings::TransformChar(c, Encodings::FORM_ISOLATED);
        }
 }
+
+
+void Paragraph::dump() const
+{
+       lyxerr << "Paragraph::dump: rows.size(): " << rows_.size() << endl;
+       for (size_t i = 0; i != rows_.size(); ++i) {
+               lyxerr << "  row " << i << ":   ";
+               rows_[i].dump();
+       }
+}
+
+//void Paragraph::metrics(MetricsInfo & mi, Dimension & dim, LyXText & text)
+//{
+//}
+//
+//
+//void draw(PainterInfo & pi, int x, int y, LyXText & text) const
+//{
+//}