X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FParagraph.cpp;h=c7e65650e83d6d4f1484bf51830bde77ce8c7213;hb=dae6ca73df7acbf58f1bb6ad92cb71e386ad29c7;hp=d93594a6783c20f2190e69bf68977f624942eba7;hpb=c999e35e54eca6e0b736a034d415b6a90a866bc0;p=lyx.git diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp index d93594a678..c7e65650e8 100644 --- a/src/Paragraph.cpp +++ b/src/Paragraph.cpp @@ -69,8 +69,10 @@ using namespace lyx::support; namespace lyx { namespace { + /// Inset identifier (above 0x10ffff, for ucs-4) char_type const META_INSET = 0x200001; + } @@ -129,7 +131,8 @@ private: class SpellCheckerState { public: - SpellCheckerState() { + SpellCheckerState() + { needs_refresh_ = true; current_change_number_ = 0; } @@ -209,20 +212,24 @@ public: return empty_; } - bool needsRefresh() const { + bool needsRefresh() const + { return needs_refresh_; } - SpellChecker::ChangeNumber currentChangeNumber() const { + SpellChecker::ChangeNumber currentChangeNumber() const + { return current_change_number_; } - void refreshRange(pos_type & first, pos_type & last) const { + void refreshRange(pos_type & first, pos_type & last) const + { first = refresh_.first; last = refresh_.last; } - void needsRefresh(pos_type pos) { + void needsRefresh(pos_type pos) + { if (needs_refresh_ && pos != -1) { if (pos < refresh_.first) refresh_.first = pos; @@ -237,13 +244,13 @@ public: needs_refresh_ = pos != -1; } - void needsCompleteRefresh(SpellChecker::ChangeNumber change_number) { + void needsCompleteRefresh(SpellChecker::ChangeNumber change_number) + { needs_refresh_ = true; refresh_.first = 0; refresh_.last = -1; current_change_number_ = change_number; } - private: typedef vector Ranges; typedef Ranges::const_iterator RangesIterator; @@ -330,6 +337,7 @@ public: /// void latexSpecialChar( otexstream & os, + BufferParams const & bparams, OutputParams const & runparams, Font const & running_font, Change const & running_change, @@ -383,9 +391,10 @@ public: Language * getSpellLanguage(pos_type const from) const; Language * locateSpellRange(pos_type & from, pos_type & to, - SkipPositions & skips) const; + SkipPositions & skips) const; - bool hasSpellerChange() const { + bool hasSpellerChange() const + { SpellChecker::ChangeNumber speller_change_number = 0; if (theSpellChecker()) speller_change_number = theSpellChecker()->changeNumber(); @@ -404,14 +413,16 @@ public: speller_state_.setRange(fp, state); } - void requestSpellCheck(pos_type pos) { + void requestSpellCheck(pos_type pos) + { if (pos == -1) speller_state_.needsCompleteRefresh(speller_state_.currentChangeNumber()); else speller_state_.needsRefresh(pos); } - void readySpellCheck() { + void readySpellCheck() + { speller_state_.needsRefresh(-1); } @@ -574,16 +585,16 @@ Paragraph::Private::Private(Private const & p, Paragraph * owner, void Paragraph::addChangesToToc(DocIterator const & cdit, - Buffer const & buf) const + Buffer const & buf, bool output_active) const { - d->changes_.addToToc(cdit, buf); + d->changes_.addToToc(cdit, buf, output_active); } bool Paragraph::isDeleted(pos_type start, pos_type end) const { - LASSERT(start >= 0 && start <= size(), /**/); - LASSERT(end > start && end <= size() + 1, /**/); + LASSERT(start >= 0 && start <= size(), return false); + LASSERT(end > start && end <= size() + 1, return false); return d->changes_.isDeleted(start, end); } @@ -591,8 +602,8 @@ bool Paragraph::isDeleted(pos_type start, pos_type end) const bool Paragraph::isChanged(pos_type start, pos_type end) const { - LASSERT(start >= 0 && start <= size(), /**/); - LASSERT(end > start && end <= size() + 1, /**/); + LASSERT(start >= 0 && start <= size(), return false); + LASSERT(end > start && end <= size() + 1, return false); return d->changes_.isChanged(start, end); } @@ -637,7 +648,7 @@ void Paragraph::setChange(Change const & change) void Paragraph::setChange(pos_type pos, Change const & change) { - LASSERT(pos >= 0 && pos <= size(), /**/); + LASSERT(pos >= 0 && pos <= size(), return); d->changes_.set(change, pos); // see comment in setChange(Change const &) above @@ -649,15 +660,15 @@ void Paragraph::setChange(pos_type pos, Change const & change) Change const & Paragraph::lookupChange(pos_type pos) const { - LASSERT(pos >= 0 && pos <= size(), /**/); + LBUFERR(pos >= 0 && pos <= size()); return d->changes_.lookup(pos); } void Paragraph::acceptChanges(pos_type start, pos_type end) { - LASSERT(start >= 0 && start <= size(), /**/); - LASSERT(end > start && end <= size() + 1, /**/); + LASSERT(start >= 0 && start <= size(), return); + LASSERT(end > start && end <= size() + 1, return); for (pos_type pos = start; pos < end; ++pos) { switch (lookupChange(pos).type) { @@ -691,8 +702,8 @@ void Paragraph::acceptChanges(pos_type start, pos_type end) void Paragraph::rejectChanges(pos_type start, pos_type end) { - LASSERT(start >= 0 && start <= size(), /**/); - LASSERT(end > start && end <= size() + 1, /**/); + LASSERT(start >= 0 && start <= size(), return); + LASSERT(end > start && end <= size() + 1, return); for (pos_type pos = start; pos < end; ++pos) { switch (lookupChange(pos).type) { @@ -727,7 +738,7 @@ void Paragraph::rejectChanges(pos_type start, pos_type end) void Paragraph::Private::insertChar(pos_type pos, char_type c, Change const & change) { - LASSERT(pos >= 0 && pos <= int(text_.size()), /**/); + LASSERT(pos >= 0 && pos <= int(text_.size()), return); // track change changes_.insert(change, pos); @@ -756,10 +767,10 @@ void Paragraph::Private::insertChar(pos_type pos, char_type c, bool Paragraph::insertInset(pos_type pos, Inset * inset, - Change const & change) + Font const & font, Change const & change) { - LASSERT(inset, /**/); - LASSERT(pos >= 0 && pos <= size(), /**/); + LASSERT(inset, return false); + LASSERT(pos >= 0 && pos <= size(), return false); // Paragraph::insertInset() can be used in cut/copy/paste operation where // d->inset_owner_ is not set yet. @@ -767,13 +778,15 @@ bool Paragraph::insertInset(pos_type pos, Inset * inset, return false; d->insertChar(pos, META_INSET, change); - LASSERT(d->text_[pos] == META_INSET, /**/); + LASSERT(d->text_[pos] == META_INSET, return false); // Add a new entry in the insetlist_. d->insetlist_.insert(inset, pos); // Some insets require run of spell checker requestSpellCheck(pos); + + setFont(pos, font); return true; } @@ -835,8 +848,8 @@ bool Paragraph::eraseChar(pos_type pos, bool trackChanges) int Paragraph::eraseChars(pos_type start, pos_type end, bool trackChanges) { - LASSERT(start >= 0 && start <= size(), /**/); - LASSERT(end >= start && end <= size() + 1, /**/); + LASSERT(start >= 0 && start <= size(), return 0); + LASSERT(end >= start && end <= size() + 1, return 0); pos_type i = start; for (pos_type count = end - start; count; --count) { @@ -858,7 +871,13 @@ int Paragraph::Private::latexSurrogatePair(otexstream & os, char_type c, // FIXME: change tracking // Is this correct WRT change tracking? Encoding const & encoding = *(runparams.encoding); - docstring const latex1 = encoding.latexChar(next).first; + docstring latex1 = encoding.latexChar(next).first; + if (runparams.inIPA) { + string const tipashortcut = Encodings::TIPAShortcut(next); + if (!tipashortcut.empty()) { + latex1 = from_ascii(tipashortcut); + } + } docstring const latex2 = encoding.latexChar(c).first; if (docstring(1, next) == latex1) { // the encoding supports the combination @@ -1026,10 +1045,12 @@ void Paragraph::Private::latexInset(BufferParams const & bparams, unsigned int & column) { Inset * inset = owner_->getInset(i); - LASSERT(inset, /**/); + LBUFERR(inset); if (style.pass_thru) { - inset->plaintext(os.os(), runparams); + odocstringstream ods; + inset->plaintext(ods, runparams); + os << ods.str(); return; } @@ -1076,6 +1097,7 @@ void Paragraph::Private::latexInset(BufferParams const & bparams, odocstream::pos_type const len = os.os().tellp(); if (inset->forceLTR() + && !runparams.use_polyglossia && running_font.isRightToLeft() // ERT is an exception, it should be output with no // decorations at all @@ -1155,6 +1177,7 @@ void Paragraph::Private::latexInset(BufferParams const & bparams, void Paragraph::Private::latexSpecialChar(otexstream & os, + BufferParams const & bparams, OutputParams const & runparams, Font const & running_font, Change const & running_change, @@ -1163,7 +1186,10 @@ void Paragraph::Private::latexSpecialChar(otexstream & os, pos_type end_pos, unsigned int & column) { - char_type const c = text_[i]; + // With polyglossia, brackets and stuff need not be reversed + // in RTL scripts (see bug #8251) + char_type const c = (runparams.use_polyglossia) ? + owner_->getUChar(bparams, i) : text_[i]; if (style.pass_thru || runparams.pass_thru) { if (c != '\0') { @@ -1352,16 +1378,19 @@ bool Paragraph::Private::latexSpecialT1(char_type const c, otexstream & os, bool Paragraph::Private::latexSpecialT3(char_type const c, otexstream & os, - pos_type /*i*/, unsigned int & /*column*/) + pos_type /*i*/, unsigned int & column) { switch (c) { case '*': case '[': case ']': - case '|': case '\"': os.put(c); return true; + case '|': + os << "\\textvertline{}"; + column += 14; + return true; default: return false; } @@ -1436,18 +1465,25 @@ void Paragraph::Private::validate(LaTeXFeatures & features) const // we have to provide all the optional arguments here, even though // the last one is the only one we care about. // Separate handling of optional argument inset. - if (layout_->optargs != 0 || layout_->reqargs != 0) - latexArgInsets(*owner_, os, features.runparams(), - layout_->reqargs, layout_->optargs); - else - os << from_ascii(layout_->latexparam()); + if (!layout_->latexargs().empty()) { + OutputParams rp = features.runparams(); + rp.local_font = &owner_->getFirstFontSettings(bp); + latexArgInsets(*owner_, os, rp, layout_->latexargs()); + } + os << from_ascii(layout_->latexparam()); } docstring::size_type const length = ods.str().length(); // this will output "{" at the beginning, but not at the end owner_->latex(bp, f, os, features.runparams(), 0, -1, true); if (ods.str().length() > length) { - if (is_command) + if (is_command) { ods << '}'; + if (!layout_->postcommandargs().empty()) { + OutputParams rp = features.runparams(); + rp.local_font = &owner_->getFirstFontSettings(bp); + latexArgInsets(*owner_, os, rp, layout_->postcommandargs(), "post:"); + } + } string const snippet = to_utf8(ods.str()); features.addPreambleSnippet(snippet); } @@ -1749,12 +1785,10 @@ void Paragraph::insertChar(pos_type pos, char_type c, bool Paragraph::insertInset(pos_type pos, Inset * inset, - Font const & font, Change const & change) + Change const & change) { - bool const success = insertInset(pos, inset, change); - // Set the font/language of the inset... - setFont(pos, font); - return success; + Font no_font; + return insertInset(pos, inset, no_font, change); } @@ -1771,7 +1805,7 @@ Font const & Paragraph::getFontSettings(BufferParams const & bparams, { if (pos > size()) { LYXERR0("pos: " << pos << " size: " << size()); - LASSERT(pos <= size(), /**/); + LBUFERR(false); } FontList::const_iterator cit = d->fontlist_.fontIterator(pos); @@ -1796,9 +1830,9 @@ Font const & Paragraph::getFontSettings(BufferParams const & bparams, FontSpan Paragraph::fontSpan(pos_type pos) const { - LASSERT(pos <= size(), /**/); - pos_type start = 0; + LBUFERR(pos < size()); + pos_type start = 0; FontList::const_iterator cit = d->fontlist_.begin(); FontList::const_iterator end = d->fontlist_.end(); for (; cit != end; ++cit) { @@ -1815,8 +1849,8 @@ FontSpan Paragraph::fontSpan(pos_type pos) const } // This should not happen, but if so, we take no chances. - // LYXERR0("Paragraph::getEndPosOfFontSpan: This should not happen!"); - return FontSpan(pos, pos); + LYXERR0("Paragraph::fontSpan: position not found in fontinfo table!"); + LASSERT(false, return FontSpan(pos, pos)); } @@ -1847,7 +1881,7 @@ Font const & Paragraph::getFirstFontSettings(BufferParams const & bparams) const Font const Paragraph::getFont(BufferParams const & bparams, pos_type pos, Font const & outerfont) const { - LASSERT(pos >= 0, /**/); + LBUFERR(pos >= 0); Font font = getFontSettings(bparams, pos); @@ -1896,16 +1930,23 @@ FontSize Paragraph::highestFontInRange char_type Paragraph::getUChar(BufferParams const & bparams, pos_type pos) const { char_type c = d->text_[pos]; - if (!lyxrc.rtl_support) + if (!lyxrc.rtl_support || !getFontSettings(bparams, pos).isRightToLeft()) return c; + // FIXME: The arabic special casing is due to the difference of arabic + // round brackets input introduced in r18599. Check if this should be + // unified with Hebrew or at least if all bracket types should be + // handled the same (file format change in either case). + string const & lang = getFontSettings(bparams, pos).language()->lang(); + bool const arabic = lang == "arabic_arabtex" || lang == "arabic_arabi" + || lang == "farsi"; char_type uc = c; switch (c) { case '(': - uc = ')'; + uc = arabic ? c : ')'; break; case ')': - uc = '('; + uc = arabic ? c : '('; break; case '[': uc = ']'; @@ -1926,15 +1967,14 @@ char_type Paragraph::getUChar(BufferParams const & bparams, pos_type pos) const uc = '<'; break; } - if (uc != c && getFontSettings(bparams, pos).isRightToLeft()) - return uc; - return c; + + return uc; } void Paragraph::setFont(pos_type pos, Font const & font) { - LASSERT(pos <= size(), /**/); + LASSERT(pos <= size(), return); // First, reduce font against layout/label font // Update: The setCharFont() routine in text2.cpp already @@ -2046,8 +2086,7 @@ docstring Paragraph::expandParagraphLabel(Layout const & layout, bool const in_appendix = process_appendix && d->params_.appendix(); docstring fmt = translateIfPossible(layout.labelstring(in_appendix), lang); - if (fmt.empty() && layout.labeltype == LABEL_COUNTER - && !layout.counter.empty()) + if (fmt.empty() && !layout.counter.empty()) return tclass.counters().theCounter(layout.counter, lang); // handle 'inherited level parts' in 'fmt', @@ -2138,7 +2177,7 @@ bool Paragraph::usePlainLayout() const bool Paragraph::isPassThru() const { - return inInset().getLayout().isPassThru() || d->layout_->pass_thru; + return inInset().isPassThru() || d->layout_->pass_thru; } namespace { @@ -2397,6 +2436,10 @@ void Paragraph::latex(BufferParams const & bparams, os << '{'; ++column; } + if (!style.leftdelim().empty()) { + os << style.leftdelim(); + column += style.leftdelim().size(); + } if (allowcust) column += d->startTeXParParams(bparams, os, runparams); } @@ -2427,6 +2470,11 @@ void Paragraph::latex(BufferParams const & bparams, ++column; } + if (!style.leftdelim().empty()) { + os << style.leftdelim(); + column += style.leftdelim().size(); + } + if (allowcust) column += d->startTeXParParams(bparams, os, runparams); @@ -2566,7 +2614,7 @@ void Paragraph::latex(BufferParams const & bparams, } else { if (i >= start_pos && (end_pos == -1 || i < end_pos)) { try { - d->latexSpecialChar(os, rp, running_font, runningChange, + d->latexSpecialChar(os, bparams, rp, running_font, runningChange, style, i, end_pos, column); } catch (EncodingException & e) { if (runparams.dryrun) { @@ -2617,6 +2665,11 @@ void Paragraph::latex(BufferParams const & bparams, os << "}]~"; } + if (!style.rightdelim().empty()) { + os << style.rightdelim(); + column += style.rightdelim().size(); + } + if (allowcust && d->endTeXParParams(bparams, os, runparams) && runparams.encoding != prev_encoding) { runparams.encoding = prev_encoding; @@ -2778,6 +2831,19 @@ void Paragraph::simpleDocBookOnePar(Buffer const & buf, } +void doFontSwitch(XHTMLStream & xs, bool startrange, + bool & flag, FontState curstate, std::string tag, std::string attr = "") +{ + if (curstate == FONT_ON) { + xs << html::StartTag(tag, attr); + flag = true; + } else if (flag && !startrange) { + xs << html::EndTag(tag); + flag = false; + } +} + + docstring Paragraph::simpleLyXHTMLOnePar(Buffer const & buf, XHTMLStream & xs, OutputParams const & runparams, @@ -2788,6 +2854,11 @@ docstring Paragraph::simpleLyXHTMLOnePar(Buffer const & buf, bool emph_flag = false; bool bold_flag = false; + bool noun_flag = false; + bool ubar_flag = false; + bool dbar_flag = false; + bool sout_flag = false; + bool wave_flag = false; Layout const & style = *d->layout_; @@ -2808,25 +2879,50 @@ docstring Paragraph::simpleLyXHTMLOnePar(Buffer const & buf, if (isDeleted(i)) continue; - Font font = getFont(buf.params(), i, outerfont); + Font const font = getFont(buf.masterBuffer()->params(), i, outerfont); + bool const at_start = (i == initial); // emphasis - if (font_old.emph() != font.fontInfo().emph()) { - if (font.fontInfo().emph() == FONT_ON) { - xs << html::StartTag("em"); - emph_flag = true; - } else if (emph_flag && i != initial) { - xs << html::EndTag("em"); - emph_flag = false; - } - } + FontState curstate = font.fontInfo().emph(); + if (font_old.emph() != curstate) + doFontSwitch(xs, at_start, emph_flag, curstate, "em"); + + // noun + curstate = font.fontInfo().noun(); + if (font_old.noun() != curstate) + doFontSwitch(xs, at_start, noun_flag, curstate, "dfn", "class='lyxnoun'"); + + // underbar + curstate = font.fontInfo().underbar(); + if (font_old.underbar() != curstate) + doFontSwitch(xs, at_start, ubar_flag, curstate, "u"); + + // strikeout + curstate = font.fontInfo().strikeout(); + if (font_old.strikeout() != curstate) + doFontSwitch(xs, at_start, sout_flag, curstate, "del", "class='strikeout'"); + + // HTML does not really have an equivalent of the next two, so we will just + // output a single underscore with a class, and people can style it if they + // wish to do so + + // double underbar + curstate = font.fontInfo().uuline(); + if (font_old.uuline() != curstate) + doFontSwitch(xs, at_start, dbar_flag, curstate, "u", "class='dline'"); + + // wavy line + curstate = font.fontInfo().uwave(); + if (font_old.uwave() != curstate) + doFontSwitch(xs, at_start, wave_flag, curstate, "u", "class='wavyline'"); + // bold if (font_old.series() != font.fontInfo().series()) { if (font.fontInfo().series() == BOLD_SERIES) { - xs << html::StartTag("strong"); + xs << html::StartTag("b"); bold_flag = true; - } else if (bold_flag && i != initial) { - xs << html::EndTag("strong"); + } else if (bold_flag && !at_start) { + xs << html::EndTag("b"); bold_flag = false; } } @@ -2837,14 +2933,15 @@ docstring Paragraph::simpleLyXHTMLOnePar(Buffer const & buf, if (inset) { if (!runparams.for_toc || inset->isInToc()) { OutputParams np = runparams; + np.local_font = &font; if (!inset->getLayout().htmlisblock()) np.html_in_par = true; retval += inset->xhtml(xs, np); } } else { - char_type c = d->text_[i]; + char_type c = getUChar(buf.masterBuffer()->params(), i); - if (style.pass_thru) + if (style.pass_thru || runparams.pass_thru) xs << c; else if (c == '-') { docstring str; @@ -3079,7 +3176,8 @@ void Paragraph::forToc(docstring & os, size_t maxlen) const } -docstring Paragraph::stringify(pos_type beg, pos_type end, int options, OutputParams & runparams) const +docstring Paragraph::stringify(pos_type beg, pos_type end, int options, + OutputParams const & runparams) const { odocstringstream os; @@ -3088,13 +3186,16 @@ docstring Paragraph::stringify(pos_type beg, pos_type end, int options, OutputPa && !d->params_.labelString().empty()) os << d->params_.labelString() << ' '; + OutputParams op = runparams; + op.for_search = true; + for (pos_type i = beg; i < end; ++i) { char_type const c = d->text_[i]; if (isPrintable(c) || c == '\t' || (c == '\n' && (options & AS_STR_NEWLINES))) os.put(c); else if (c == META_INSET && (options & AS_STR_INSETS)) { - getInset(i)->plaintext(os, runparams); + getInset(i)->plaintext(os, op); } } @@ -3155,8 +3256,7 @@ void Paragraph::setPlainOrDefaultLayout(DocumentClass const & tclass) Inset const & Paragraph::inInset() const { - LASSERT(d->inset_owner_, throw ExceptionMessage(BufferException, - _("Memory problem"), _("Paragraph not properly initialized"))); + LBUFERR(d->inset_owner_); return *d->inset_owner_; } @@ -3712,7 +3812,7 @@ SpellChecker::Result Paragraph::spellCheck(pos_type & from, pos_type & to, wl = WordLangTuple(word, lang); - if (!word.size()) + if (word.empty()) return result; if (needsSpellCheck() || check_learned) { @@ -3809,7 +3909,7 @@ void Paragraph::Private::markMisspelledWords( void Paragraph::spellCheck() const { SpellChecker * speller = theSpellChecker(); - if (!speller || !size() ||!needsSpellCheck()) + if (!speller || empty() ||!needsSpellCheck()) return; pos_type start; pos_type endpos;