X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FParagraph.cpp;h=d69fa55bb539459b0760adc24d19724a6da75ec3;hb=2b02b73f4a59bb73f9e819a960ea98c86ef8716f;hp=aad1ccf1424c10b20670abf5317348f8ed707220;hpb=39ad6e84f076cea65f140593e5b6647905219af3;p=lyx.git diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp index aad1ccf142..d69fa55bb5 100644 --- a/src/Paragraph.cpp +++ b/src/Paragraph.cpp @@ -66,6 +66,7 @@ #include "support/textutils.h" #include "output_docbook.h" +#include #include #include #include @@ -1087,7 +1088,7 @@ void Paragraph::Private::latexInset(BufferParams const & bparams, runparams.local_font = &basefont; } - if (fontswitch_inset && !closeLanguage && fontswitch_inset) { + if (fontswitch_inset && !closeLanguage) { // The directionality has been switched at inset. // Force markup inside. runparams.local_font = &basefont; @@ -1103,7 +1104,7 @@ void Paragraph::Private::latexInset(BufferParams const & bparams, // add location information and throw again. e.par_id = id_; e.pos = i; - throw(e); + throw; } if (close) @@ -2638,10 +2639,10 @@ void Paragraph::latex(BufferParams const & bparams, if (closeLanguage) // Force language closing current_font.setLanguage(basefont.language()); + Font const nextfont = (i == body_pos-1) ? basefont : current_font; column += running_font.latexWriteEndChanges( os, bparams, runparams, basefont, - (i == body_pos-1) ? basefont : current_font, - needPar); + nextfont, needPar); if (in_ct_deletion) { // We have to close and then reopen \lyxdeleted, // as strikeout needs to be on lowest level. @@ -2649,9 +2650,12 @@ void Paragraph::latex(BufferParams const & bparams, column += Changes::latexMarkChange(os, bparams, Change(Change::UNCHANGED), Change(Change::DELETED), rp); } - running_font = basefont; open_font = false; - langClosed = true; + // Has the language been closed in the latexWriteEndChanges() call above? + langClosed = running_font.language() != basefont.language() + && running_font.language() != nextfont.language() + && (running_font.language()->encoding()->package() != Encoding::CJK); + running_font = basefont; } // if necessary, close language environment before opening CJK @@ -2875,7 +2879,7 @@ void Paragraph::latex(BufferParams const & bparams, // add location information and throw again. e.par_id = id(); e.pos = i; - throw(e); + throw; } } } @@ -3332,7 +3336,9 @@ std::tuple, vector> computeDocBookFontSwit std::vector Paragraph::simpleDocBookOnePar(Buffer const & buf, OutputParams const & runparams, Font const & outerfont, - pos_type initial) const + pos_type initial, + bool is_last_par, + bool ignore_fonts) const { // Track whether we have opened these tags DocBookFontState fs; @@ -3348,43 +3354,71 @@ std::vector Paragraph::simpleDocBookOnePar(Buffer const & buf, vector tagsToClose; std::vector generatedParagraphs; + DocBookFontState old_fs = fs; odocstringstream os; auto * xs = new XMLStream(os); // XMLStream has no copy constructor: to create a new object, the only solution // is to hold a pointer to the XMLStream (xs = XMLStream(os) is not allowed once the first object is built). + // When a font tag ends with a space, output it after the closing font tag. This requires to store delayed + // characters at some point. + std::vector delayedChars; + // Parsing main loop. for (pos_type i = initial; i < size(); ++i) { // Don't show deleted material in the output. if (isDeleted(i)) continue; - // If this is an InsetNewline, generate a new paragraph. + // If this is an InsetNewline, generate a new paragraph. Also reset the fonts, so that tags are closed in + // this paragraph. if (getInset(i) != nullptr && getInset(i)->lyxCode() == NEWLINE_CODE) { + if (!ignore_fonts) + xs->closeFontTags(); + + // Output one paragraph (i.e. one string entry in generatedParagraphs). generatedParagraphs.push_back(os.str()); - os = odocstringstream(); + + // Create a new XMLStream for the new paragraph, completely independent from the previous one. This implies + // that the string stream must be reset. + os.str(from_ascii("")); delete xs; xs = new XMLStream(os); + + // Restore the fonts for the new paragraph, so that the right tags are opened for the new entry. + if (!ignore_fonts) { + font_old = outerfont.fontInfo(); + fs = old_fs; + } } - // Determine which tags should be opened or closed. + // Determine which tags should be opened or closed regarding fonts. Font const font = getFont(buf.masterBuffer()->params(), i, outerfont); - tie(tagsToOpen, tagsToClose) = computeDocBookFontSwitch(font_old, font, default_family, fs); - - // FIXME XHTML - // Other such tags? What about the other text ranges? - - vector::const_iterator cit = tagsToClose.begin(); - vector::const_iterator cen = tagsToClose.end(); - for (; cit != cen; ++cit) - *xs << *cit; + if (!ignore_fonts) { + tie(tagsToOpen, tagsToClose) = computeDocBookFontSwitch(font_old, font, default_family, fs); + + // FIXME XHTML + // Other such tags? What about the other text ranges? + + vector::const_iterator cit = tagsToClose.begin(); + vector::const_iterator cen = tagsToClose.end(); + for (; cit != cen; ++cit) + *xs << *cit; + + // Deal with the delayed characters *after* closing font tags. + if (!delayedChars.empty()) { + for (char_type c: delayedChars) + *xs << c; + delayedChars.clear(); + } - vector::const_iterator sit = tagsToOpen.begin(); - vector::const_iterator sen = tagsToOpen.end(); - for (; sit != sen; ++sit) - *xs << *sit; + vector::const_iterator sit = tagsToOpen.begin(); + vector::const_iterator sen = tagsToOpen.end(); + for (; sit != sen; ++sit) + *xs << *sit; - tagsToClose.clear(); - tagsToOpen.clear(); + tagsToClose.clear(); + tagsToOpen.clear(); + } if (Inset const * inset = getInset(i)) { if (!runparams.for_toc || inset->isInToc()) { @@ -3397,7 +3431,10 @@ std::vector Paragraph::simpleDocBookOnePar(Buffer const & buf, } } else { char_type c = getUChar(buf.masterBuffer()->params(), runparams, i); - *xs << c; + if (lyx::isSpace(c) && !ignore_fonts) + delayedChars.push_back(c); + else + *xs << c; } font_old = font.fontInfo(); } @@ -3405,8 +3442,17 @@ std::vector Paragraph::simpleDocBookOnePar(Buffer const & buf, // FIXME, this code is just imported from XHTML // I'm worried about what happens if a branch, say, is itself // wrapped in some font stuff. I think that will not work. - xs->closeFontTags(); - if (runparams.docbook_in_listing) + if (!ignore_fonts) + xs->closeFontTags(); + + // Deal with the delayed characters *after* closing font tags. + if (!delayedChars.empty()) + for (char_type c: delayedChars) + *xs << c; + + // In listings, new lines (i.e. \n characters in the output) are very important. Avoid generating one for the + // last line to get a clean output. + if (runparams.docbook_in_listing && !is_last_par) *xs << xml::CR(); // Finalise the last (and most likely only) paragraph. @@ -3848,8 +3894,8 @@ bool Paragraph::isHardHyphenOrApostrophe(pos_type pos) const char_type const c = d->text_[pos]; if (c != '-' && c != '\'') return false; - int nextpos = pos + 1; - int prevpos = pos > 0 ? pos - 1 : 0; + pos_type nextpos = pos + 1; + pos_type prevpos = pos > 0 ? pos - 1 : 0; if ((nextpos == psize || isSpace(nextpos)) && (pos == 0 || isSpace(prevpos))) return false; @@ -3890,9 +3936,6 @@ bool Paragraph::needsCProtection(bool const fragile) const Inset const * ins = getInset(i); if (ins->needsCProtection(maintext, fragile)) return true; - if (ins->getLayout().latextype() == InsetLayout::ENVIRONMENT) - // Environments need cprotection regardless the content - return true; // Now check math environments InsetMath const * im = getInset(i)->asInsetMath(); if (!im || im->cell(0).empty()) @@ -4326,10 +4369,8 @@ void Paragraph::changeCase(BufferParams const & bparams, pos_type pos, } int erasePos = pos - changes.size(); - for (size_t i = 0; i < changes.size(); i++) { - insertChar(pos, changes[i].first, - changes[i].second, - trackChanges); + for (auto const & change : changes) { + insertChar(pos, change.first, change.second, trackChanges); if (!eraseChar(erasePos, trackChanges)) { ++erasePos; ++pos; // advance @@ -4788,7 +4829,7 @@ void Paragraph::spellCheck() const // start the spell checker on the unit of meaning docstring word = asString(first, last, AS_STR_INSETS + AS_STR_SKIPDELETE); WordLangTuple wl = WordLangTuple(word, lang); - SpellChecker::Result result = word.size() ? + SpellChecker::Result result = !word.empty() ? speller->check(wl) : SpellChecker::WORD_OK; d->markMisspelledWords(first, last, result, word, skips); first = ++last;