]> git.lyx.org Git - lyx.git/blobdiff - src/Paragraph.cpp
That didn't really work. So revert to old CSS for gray notes.
[lyx.git] / src / Paragraph.cpp
index 6dce930e9a47e2bc0d036e2bbba67a8bece1c86a..0266c2e6ff9cf19a5b7875a12ebee99a7fceed7e 100644 (file)
@@ -5,6 +5,7 @@
  *
  * \author Asger Alstrup
  * \author Lars Gullik Bjønnes
+ * \author Richard Heck (XHTML output)
  * \author Jean-Marc Lasgouttes
  * \author Angus Leeming
  * \author John Levon
@@ -163,8 +164,7 @@ public:
                OutputParams const & runparams);
 
        ///
-       void validate(LaTeXFeatures & features,
-                     Layout const & layout) const;
+       void validate(LaTeXFeatures & features) const;
 
        /// Checks if the paragraph contains only text and no inset or font change.
        bool onlyText(Buffer const & buf, Font const & outerfont,
@@ -593,8 +593,8 @@ bool Paragraph::Private::simpleTeXBlanks(OutputParams const & runparams,
                }
        }
 
-       if (lyxrc.plaintext_linelen > 0
-           && column > lyxrc.plaintext_linelen
+       if (runparams.linelen > 0
+           && column > runparams.linelen
            && i
            && text_[i - 1] != ' '
            && (i + 1 < int(text_.size()))
@@ -771,7 +771,7 @@ void Paragraph::Private::latexInset(
 
        if (inset->canTrackChanges()) {
                column += Changes::latexMarkChange(os, bparams, running_change,
-                       Change(Change::UNCHANGED));
+                       Change(Change::UNCHANGED), runparams);
                running_change = Change(Change::UNCHANGED);
        }
 
@@ -1070,15 +1070,26 @@ bool Paragraph::Private::latexSpecialPhrase(odocstream & os, pos_type & i,
 }
 
 
-void Paragraph::Private::validate(LaTeXFeatures & features,
-                               Layout const & layout) const
+void Paragraph::Private::validate(LaTeXFeatures & features) const
 {
+       if (layout_->inpreamble && inset_owner_) {
+               Buffer const & buf = inset_owner_->buffer();
+               BufferParams const & bp = buf.params();
+               Font f;
+               TexRow tr;
+               odocstringstream ods;
+               owner_->latex(bp, f, ods, tr, features.runparams());
+               docstring d = ods.str();
+               if (!d.empty())
+                       features.addPreambleSnippet(to_utf8(d));
+       }
+       
        // check the params.
        if (!params_.spacing().isDefault())
                features.require("setspace");
 
        // then the layouts
-       features.useLayout(layout.name());
+       features.useLayout(layout_->name());
 
        // then the fonts
        fontlist_.validate(features);
@@ -1093,7 +1104,7 @@ void Paragraph::Private::validate(LaTeXFeatures & features,
        for (; icit != iend; ++icit) {
                if (icit->inset) {
                        icit->inset->validate(features);
-                       if (layout.needprotect &&
+                       if (layout_->needprotect &&
                            icit->inset->lyxCode() == FOOT_CODE)
                                features.require("NeedLyXFootnoteCode");
                }
@@ -1168,6 +1179,18 @@ Paragraph::~Paragraph()
 }
 
 
+namespace {
+
+// this shall be called just before every "os << ..." action.
+void flushString(ostream & os, docstring & s)
+{
+       os << to_utf8(s);
+       s.erase();
+}
+
+}
+
+
 void Paragraph::write(ostream & os, BufferParams const & bparams,
        depth_type & dth) const
 {
@@ -1195,10 +1218,16 @@ void Paragraph::write(ostream & os, BufferParams const & bparams,
 
        Change running_change = Change(Change::UNCHANGED);
 
+       // this string is used as a buffer to avoid repetitive calls
+       // to to_utf8(), which turn out to be expensive (JMarc)
+       docstring write_buffer;
+
        int column = 0;
        for (pos_type i = 0; i <= size(); ++i) {
 
                Change const change = lookupChange(i);
+               if (change != running_change)
+                       flushString(os, write_buffer);
                Changes::lyxMarkChange(os, bparams, column, running_change, change);
                running_change = change;
 
@@ -1209,6 +1238,7 @@ void Paragraph::write(ostream & os, BufferParams const & bparams,
                Font font2 = getFontSettings(bparams, i);
                font2.setMisspelled(false);
                if (font2 != font1) {
+                       flushString(os, write_buffer);
                        font2.lyxWriteChanges(font1, os);
                        column = 0;
                        font1 = font2;
@@ -1218,6 +1248,7 @@ void Paragraph::write(ostream & os, BufferParams const & bparams,
                switch (c) {
                case META_INSET:
                        if (Inset const * inset = getInset(i)) {
+                               flushString(os, write_buffer);
                                if (inset->directWrite()) {
                                        // international char, let it write
                                        // code directly so it's shorter in
@@ -1234,10 +1265,12 @@ void Paragraph::write(ostream & os, BufferParams const & bparams,
                        }
                        break;
                case '\\':
+                       flushString(os, write_buffer);
                        os << "\n\\backslash\n";
                        column = 0;
                        break;
                case '.':
+                       flushString(os, write_buffer);
                        if (i + 1 < size() && d->text_[i + 1] == ' ') {
                                os << ".\n";
                                column = 0;
@@ -1247,13 +1280,14 @@ void Paragraph::write(ostream & os, BufferParams const & bparams,
                default:
                        if ((column > 70 && c == ' ')
                            || column > 79) {
+                               flushString(os, write_buffer);
                                os << '\n';
                                column = 0;
                        }
                        // this check is to amend a bug. LyX sometimes
                        // inserts '\0' this could cause problems.
                        if (c != '\0')
-                               os << to_utf8(docstring(1, c));
+                               write_buffer.push_back(c);
                        else
                                LYXERR0("NUL char in structure.");
                        ++column;
@@ -1261,13 +1295,14 @@ void Paragraph::write(ostream & os, BufferParams const & bparams,
                }
        }
 
+       flushString(os, write_buffer);
        os << "\n\\end_layout\n";
 }
 
 
 void Paragraph::validate(LaTeXFeatures & features) const
 {
-       d->validate(features, *d->layout_);
+       d->validate(features);
 }
 
 
@@ -1923,6 +1958,9 @@ bool Paragraph::latex(BufferParams const & bparams,
 {
        LYXERR(Debug::LATEX, "Paragraph::latex...     " << this);
 
+       if (layout().inpreamble)
+               return true;
+
        bool return_value = false;
 
        bool const allowcust = allowParagraphCustomization();
@@ -1988,7 +2026,8 @@ bool Paragraph::latex(BufferParams const & bparams,
                                running_font = basefont;
 
                                column += Changes::latexMarkChange(os, bparams,
-                                               runningChange, Change(Change::UNCHANGED));
+                                               runningChange, Change(Change::UNCHANGED),
+                                               runparams);
                                runningChange = Change(Change::UNCHANGED);
 
                                os << "] ";
@@ -2017,7 +2056,8 @@ bool Paragraph::latex(BufferParams const & bparams,
                        basefont = getLayoutFont(bparams, outerfont);
                        running_font = basefont;
 
-                       column += Changes::latexMarkChange(os, bparams, runningChange, change);
+                       column += Changes::latexMarkChange(os, bparams, runningChange,
+                                                          change, runparams);
                        runningChange = change;
                }
 
@@ -2179,7 +2219,8 @@ bool Paragraph::latex(BufferParams const & bparams,
 #endif
        }
 
-       column += Changes::latexMarkChange(os, bparams, runningChange, Change(Change::UNCHANGED));
+       column += Changes::latexMarkChange(os, bparams, runningChange,
+                                          Change(Change::UNCHANGED), runparams);
 
        // Needed if there is an optional argument but no contents.
        if (body_pos > 0 && body_pos == size()) {
@@ -2187,8 +2228,12 @@ bool Paragraph::latex(BufferParams const & bparams,
                return_value = false;
        }
 
-       if (allowcust && d->endTeXParParams(bparams, os, texrow, runparams))
+       if (allowcust && d->endTeXParParams(bparams, os, texrow, runparams)
+           && runparams.encoding != prev_encoding) {
                runparams.encoding = prev_encoding;
+               if (!bparams.useXetex)
+                       os << setEncoding(prev_encoding->iconvName());
+       }
 
        LYXERR(Debug::LATEX, "Paragraph::latex... done " << this);
        return return_value;
@@ -2256,18 +2301,18 @@ pos_type Paragraph::firstWordDocBook(odocstream & os, OutputParams const & runpa
 }
 
 
-pos_type Paragraph::firstWordLyXHTML(odocstream & os, OutputParams const & runparams)
+pos_type Paragraph::firstWordLyXHTML(XHTMLStream & xs, OutputParams const & runparams)
        const
 {
        pos_type i;
        for (i = 0; i < size(); ++i) {
                if (Inset const * inset = getInset(i)) {
-                       inset->xhtml(os, runparams);
+                       inset->xhtml(xs, runparams);
                } else {
                        char_type c = d->text_[i];
                        if (c == ' ')
                                break;
-                       os << html::escapeChar(c);
+                       xs << c;
                }
        }
        return i;
@@ -2346,26 +2391,29 @@ void Paragraph::simpleDocBookOnePar(Buffer const & buf,
 
 
 docstring Paragraph::simpleLyXHTMLOnePar(Buffer const & buf,
-                                   odocstream & os,
+                                   XHTMLStream & xs,
                                    OutputParams const & runparams,
                                    Font const & outerfont,
+                                               bool fortoc,
                                    pos_type initial) const
 {
        docstring retval;
 
-       // FIXME We really need to manage the tag nesting here.
-       // Probably in the same sort of way as in output_xhtml.
        bool emph_flag = false;
        bool bold_flag = false;
        std::string closing_tag;
 
        Layout const & style = *d->layout_;
+
+       if (!fortoc) {
+               // generate a magic label for this paragraph
+               string const attr = "id='" + magicLabel() + "'";
+               xs << CompTag("a", attr);
+       }
+
        FontInfo font_old =
                style.labeltype == LABEL_MANUAL ? style.labelfont : style.font;
 
-       //if (style.pass_thru && !d->onlyText(buf, outerfont, initial))
-       //      os << "]]>";
-
        // parsing main loop
        for (pos_type i = initial; i < size(); ++i) {
                Font font = getFont(buf.params(), i, outerfont);
@@ -2373,32 +2421,41 @@ docstring Paragraph::simpleLyXHTMLOnePar(Buffer const & buf,
                // emphasis
                if (font_old.emph() != font.fontInfo().emph()) {
                        if (font.fontInfo().emph() == FONT_ON) {
-                               os << "<em>";
+                               xs << StartTag("em");
                                emph_flag = true;
                        } else if (emph_flag && i != initial) {
-                               os << "</em>";
+                               xs << EndTag("em");
                                emph_flag = false;
                        }
                }
                // bold
                if (font_old.series() != font.fontInfo().series()) {
                        if (font.fontInfo().series() == BOLD_SERIES) {
-                               os << "<strong>";
+                               xs << StartTag("strong");
                                bold_flag = true;
                        } else if (bold_flag && i != initial) {
-                               os << "</strong>";
+                               xs << EndTag("strong");
                                bold_flag = false;
                        }
                }
-               // FIXME Other such tags? 
-
-               if (Inset const * inset = getInset(i)) {
-                       retval += inset->xhtml(os, runparams);
+               // FIXME XHTML
+               // Other such tags? What about the other text ranges?
+
+               Inset const * inset = getInset(i);
+               if (inset) {
+                       InsetCommand const * ic = inset->asInsetCommand();
+                       InsetLayout const & il = inset->getLayout();
+                       if (!fortoc || il.isInToc() || (ic && ic->isInToc())) {
+                               OutputParams np = runparams;
+                               if (!il.htmlisblock())
+                                       np.html_in_par = true;
+                               retval += inset->xhtml(xs, np);
+                       }
                } else {
                        char_type c = d->text_[i];
 
                        if (style.pass_thru)
-                               os.put(c);
+                               xs << c;
                        else if (c == '-') {
                                docstring str;
                                int j = i + 1;
@@ -2414,19 +2471,17 @@ docstring Paragraph::simpleLyXHTMLOnePar(Buffer const & buf,
                                }
                                else
                                        str += c;
-                               os << str;
+                               // We don't want to escape the entities. Note that
+                               // it is safe to do this, since str can otherwise
+                               // only be "-". E.g., it can't be "<".
+                               xs << XHTMLStream::NextRaw() << str;
                        } else
-                               os << html::escapeChar(c);
+                               xs << c;
                }
                font_old = font.fontInfo();
        }
 
-       // FIXME This could be out of order. See above.
-       if (emph_flag)
-               os << "</em>";
-       if (bold_flag)
-               os << "</strong>";
-
+       xs.closeFontTags();
        return retval;
 }
 
@@ -2766,7 +2821,7 @@ 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(buffer, InsetCommandParams(BIBITEM_CODE));
+               new InsetBibitem(const_cast<Buffer *>(&buffer), InsetCommandParams(BIBITEM_CODE));
        // restore values of previously deleted item in this par.
        if (!oldkey.empty())
                inset->setParam("key", oldkey);
@@ -3015,8 +3070,6 @@ void Paragraph::locateWord(pos_type & from, pos_type & to,
 void Paragraph::collectWords()
 {
        pos_type n = size();
-       WordLangTuple wl;
-       docstring_list suggestions;
        for (pos_type pos = 0; pos < n; ++pos) {
                if (isWordSeparator(pos))
                        continue;
@@ -3026,11 +3079,6 @@ void Paragraph::collectWords()
                        docstring word = asString(from, pos, AS_STR_NONE);
                        d->words_.insert(word);
                }
-               if (lyxrc.spellcheck_continuously
-                   && spellCheck(from, pos, wl, suggestions)) {
-                       for (size_t i = 0; i != suggestions.size(); ++i)
-                               d->words_.insert(suggestions[i]);
-               }
        }
 }
 
@@ -3100,4 +3148,12 @@ bool Paragraph::isMisspelled(pos_type pos) const
 }
 
 
+string Paragraph::magicLabel() const
+{
+       stringstream ss;
+       ss << "magicparlabel-" << id();
+       return ss.str();
+}
+
+
 } // namespace lyx