X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FParagraph.cpp;h=c29ca4cb930110e780b8011b19ef7fea4d77a246;hb=04b8f5cdc4b26105ea855fb9ec5b23227dfd55cb;hp=5bfa687abb53ebbc0e9d94bdb1b20fca12eda1cd;hpb=0bf8b8a1d234c31cc2708e80e41c55dfefacec93;p=lyx.git diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp index 5bfa687abb..c29ca4cb93 100644 --- a/src/Paragraph.cpp +++ b/src/Paragraph.cpp @@ -363,19 +363,6 @@ public: otexstream & os, pos_type i, unsigned int & column); - /// - bool latexSpecialTypewriter( - char_type const c, - otexstream & os, - pos_type i, - unsigned int & column); - /// - bool latexSpecialPhrase( - otexstream & os, - pos_type & i, - pos_type end_pos, - unsigned int & column, - OutputParams const & runparams); /// void validate(LaTeXFeatures & features) const; @@ -384,9 +371,6 @@ public: bool onlyText(Buffer const & buf, Font const & outerfont, pos_type initial) const; - /// match a string against a particular point in the paragraph - bool isTextAt(string const & str, pos_type pos) const; - /// a vector of speller skip positions typedef vector SkipPositions; typedef SkipPositions::const_iterator SkipPositionsIterator; @@ -514,26 +498,6 @@ public: }; -namespace { - -struct special_phrase { - string phrase; - docstring macro; - bool builtin; -}; - -special_phrase const special_phrases[] = { - { "LyX", from_ascii("\\LyX{}"), false }, - { "TeX", from_ascii("\\TeX{}"), true }, - { "LaTeX2e", from_ascii("\\LaTeXe{}"), true }, - { "LaTeX", from_ascii("\\LaTeX{}"), true }, -}; - -size_t const phrases_nr = sizeof(special_phrases)/sizeof(special_phrase); - -} // namespace anon - - Paragraph::Private::Private(Paragraph * owner, Layout const & layout) : owner_(owner), inset_owner_(0), id_(-1), begin_of_body_(0), layout_(&layout) { @@ -546,6 +510,8 @@ Paragraph::Private::Private(Paragraph * owner, Layout const & layout) // FIXME: There should be a more intelligent way to generate and use the // paragraph ids per buffer instead a global static counter for all InsetText // in the running program. +// However, this per-session id is used in LFUN_PARAGRAPH_GOTO to +// switch to a different buffer, as used in the outliner for instance. static int paragraph_id = -1; Paragraph::Private::Private(Private const & p, Paragraph * owner) @@ -596,6 +562,18 @@ void Paragraph::addChangesToToc(DocIterator const & cdit, } +void Paragraph::addChangesToBuffer(Buffer const & buf) const +{ + d->changes_.updateBuffer(buf); +} + + +bool Paragraph::isChangeUpdateRequired() const +{ + return d->changes_.isUpdateRequired(); +} + + bool Paragraph::isDeleted(pos_type start, pos_type end) const { LASSERT(start >= 0 && start <= size(), return false); @@ -620,7 +598,7 @@ bool Paragraph::isMergedOnEndOfParDeletion(bool trackChanges) const if (!trackChanges) return true; - Change const change = d->changes_.lookup(size()); + Change const & change = d->changes_.lookup(size()); return change.inserted() && change.currentAuthor(); } @@ -951,10 +929,13 @@ int Paragraph::Private::writeScriptChars(otexstream & os, { // FIXME: modifying i here is not very nice... - // We only arrive here when a proper language for character text_[i] has - // not been specified (i.e., it could not be translated in the current - // latex encoding) or its latex translation has been forced, and it - // belongs to a known script. + // We only arrive here when character text_[i] could not be translated + // into the current latex encoding (or its latex translation has been forced,) + // and it belongs to a known script. + // TODO: We need \textcyr and \textgreek wrappers also for characters + // that can be encoded in the "LaTeX encoding" but not in the + // current *font encoding*. + // (See #9681 for details and test) // Parameter ltx contains the latex translation of text_[i] as specified // in the unicodesymbols file and is something like "\textXXX{}". // The latex macro name "textXXX" specifies the script to which text_[i] @@ -970,6 +951,10 @@ int Paragraph::Private::writeScriptChars(otexstream & os, bool closing_brace = true; if (script == "textgreek" && encoding.latexName() == "iso-8859-7") { // Correct encoding is being used, so we can avoid \textgreek. + // TODO: wrong test: we need to check the *font encoding* + // (i.e. the active language and its FontEncoding tag) + // instead of the LaTeX *input encoding*! + // See #9637 for details and test-cases. pos = brace1 + 1; length -= pos; closing_brace = false; @@ -1016,26 +1001,6 @@ int Paragraph::Private::writeScriptChars(otexstream & os, } -bool Paragraph::Private::isTextAt(string const & str, pos_type pos) const -{ - pos_type const len = str.length(); - - // is the paragraph large enough? - if (pos + len > int(text_.size())) - return false; - - // does the wanted text start at point? - for (string::size_type i = 0; i < str.length(); ++i) { - // Caution: direct comparison of characters works only - // because str is pure ASCII. - if (str[i] != text_[pos + i]) - return false; - } - - return fontlist_.hasChangeInRange(pos, len); -} - - void Paragraph::Private::latexInset(BufferParams const & bparams, otexstream & os, OutputParams & runparams, @@ -1195,7 +1160,9 @@ void Paragraph::Private::latexSpecialChar(otexstream & os, char_type const c = (runparams.use_polyglossia) ? owner_->getUChar(bparams, i) : text_[i]; - if (style.pass_thru || runparams.pass_thru) { + if (style.pass_thru || runparams.pass_thru + || contains(style.pass_thru_chars, c) + || contains(runparams.pass_thru_chars, c)) { if (c != '\0') { Encoding const * const enc = runparams.encoding; if (enc && !enc->encodable(c)) @@ -1210,16 +1177,11 @@ void Paragraph::Private::latexSpecialChar(otexstream & os, return; // If T1 font encoding is used, use the special // characters it provides. - // NOTE: some languages reset the font encoding - // internally + // NOTE: Some languages reset the font encoding internally to a + // non-standard font encoding. If we are using such a language, + // we do not output special T1 chars. if (!runparams.inIPA && !running_font.language()->internalFontEncoding() - && lyxrc.fontenc == "T1" && latexSpecialT1(c, os, i, column)) - return; - - // \tt font needs special treatment - if (!runparams.inIPA - && running_font.fontInfo().family() == TYPEWRITER_FAMILY - && latexSpecialTypewriter(c, os, i, column)) + && bparams.font_encoding() == "T1" && latexSpecialT1(c, os, i, column)) return; // Otherwise, we use what LaTeX provides us. @@ -1242,6 +1204,16 @@ void Paragraph::Private::latexSpecialChar(otexstream & os, break; case '-': os << '-'; + if (i + 1 < static_cast(text_.size()) && + (end_pos == -1 || i + 1 < end_pos) && + text_[i+1] == '-') { + // Prevent "--" becoming an endash and "---" becoming + // an emdash. + // Within \ttfamily, "--" is merged to "-" (no endash) + // so we avoid this rather irritating ligature as well + os << "{}"; + column += 2; + } break; case '\"': os << "\\char`\\\"{}"; @@ -1285,10 +1257,6 @@ void Paragraph::Private::latexSpecialChar(otexstream & os, break; default: - // LyX, LaTeX etc. - if (latexSpecialPhrase(os, i, end_pos, column, runparams)) - return; - if (c == '\0') return; @@ -1401,55 +1369,6 @@ bool Paragraph::Private::latexSpecialT3(char_type const c, otexstream & os, } -bool Paragraph::Private::latexSpecialTypewriter(char_type const c, otexstream & os, - pos_type i, unsigned int & column) -{ - switch (c) { - case '-': - // within \ttfamily, "--" is merged to "-" (no endash) - // so we avoid this rather irritating ligature - if (i + 1 < int(text_.size()) && text_[i + 1] == '-') { - os << "-{}"; - column += 2; - } else - os << '-'; - return true; - - // everything else has to be checked separately - // (depending on the encoding) - default: - return false; - } -} - - -/// \param end_pos -/// If [start_pos, end_pos) does not include entirely the special phrase, then -/// do not apply the macro transformation. -bool Paragraph::Private::latexSpecialPhrase(otexstream & os, pos_type & i, pos_type end_pos, - unsigned int & column, OutputParams const & runparams) -{ - // FIXME: if we have "LaTeX" with a font - // change in the middle (before the 'T', then - // the "TeX" part is still special cased. - // Really we should only operate this on - // "words" for some definition of word - - for (size_t pnr = 0; pnr < phrases_nr; ++pnr) { - if (!isTextAt(special_phrases[pnr].phrase, i) - || (end_pos != -1 && i + int(special_phrases[pnr].phrase.size()) > end_pos)) - continue; - if (runparams.moving_arg) - os << "\\protect"; - os << special_phrases[pnr].macro; - i += special_phrases[pnr].phrase.length() - 1; - column += special_phrases[pnr].macro.length() - 1; - return true; - } - return false; -} - - void Paragraph::Private::validate(LaTeXFeatures & features) const { if (layout_->inpreamble && inset_owner_) { @@ -1490,7 +1409,7 @@ void Paragraph::Private::validate(LaTeXFeatures & features) const } } string const snippet = to_utf8(ods.str()); - features.addPreambleSnippet(snippet); + features.addPreambleSnippet(snippet, true); } } @@ -1521,19 +1440,12 @@ void Paragraph::Private::validate(LaTeXFeatures & features) const icit->inset->validate(features); if (layout_->needprotect && icit->inset->lyxCode() == FOOT_CODE) - features.require("footmisc"); + features.require("NeedLyXFootnoteCode"); } } // then the contents for (pos_type i = 0; i < int(text_.size()) ; ++i) { - for (size_t pnr = 0; pnr < phrases_nr; ++pnr) { - if (!special_phrases[pnr].builtin - && isTextAt(special_phrases[pnr].phrase, i)) { - features.require(special_phrases[pnr].phrase); - break; - } - } BufferEncodings::validate(text_[i], features); } } @@ -1640,7 +1552,7 @@ void Paragraph::write(ostream & os, BufferParams const & bparams, int column = 0; for (pos_type i = 0; i <= size(); ++i) { - Change const change = lookupChange(i); + Change const & change = lookupChange(i); if (change != running_change) flushString(os, write_buffer); Changes::lyxMarkChange(os, bparams, column, running_change, change); @@ -1833,7 +1745,10 @@ Font const & Paragraph::getFontSettings(BufferParams const & bparams, FontSpan Paragraph::fontSpan(pos_type pos) const { - LBUFERR(pos < size()); + LBUFERR(pos <= size()); + + if (pos == size()) + return FontSpan(pos, pos); pos_type start = 0; FontList::const_iterator cit = d->fontlist_.begin(); @@ -1922,14 +1837,6 @@ Font const Paragraph::getLayoutFont } -/// Returns the height of the highest font in range -FontSize Paragraph::highestFontInRange - (pos_type startpos, pos_type endpos, FontSize def_size) const -{ - return d->fontlist_.highestInRange(startpos, endpos, def_size); -} - - char_type Paragraph::getUChar(BufferParams const & bparams, pos_type pos) const { char_type c = d->text_[pos]; @@ -2101,7 +2008,7 @@ docstring Paragraph::expandParagraphLabel(Layout const & layout, docstring parent(fmt, i + 1, j - i - 1); docstring label = from_ascii("??"); if (tclass.hasLayout(parent)) - docstring label = expandParagraphLabel(tclass[parent], bparams, + label = expandParagraphLabel(tclass[parent], bparams, process_appendix); fmt = docstring(fmt, 0, i) + label + docstring(fmt, j + 1, docstring::npos); @@ -2145,14 +2052,12 @@ void Paragraph::setBeginOfBody() pos_type end = size(); if (i < end && !(isNewline(i) || isEnvSeparator(i))) { ++i; - char_type previous_char = 0; - char_type temp = 0; if (i < end) { - previous_char = d->text_[i]; + char_type previous_char = d->text_[i]; if (!(isNewline(i) || isEnvSeparator(i))) { ++i; while (i < end && previous_char != ' ') { - temp = d->text_[i]; + char_type temp = d->text_[i]; if (isNewline(i) || isEnvSeparator(i)) break; ++i; @@ -2208,36 +2113,37 @@ string correction(string const & orig) } -string const corrected_env(string const & suffix, string const & env, - InsetCode code, bool const lastpar) +bool corrected_env(otexstream & os, string const & suffix, string const & env, + InsetCode code, bool const lastpar, int & col) { - string output = suffix + "{"; + string macro = suffix + "{"; if (noTrivlistCentering(code)) { if (lastpar) { // the last paragraph in non-trivlist-aligned // context is special (to avoid unwanted whitespace) - if (suffix == "\\begin") - return "\\" + correction(env) + "{}"; - return string(); + if (suffix == "\\begin") { + macro = "\\" + correction(env) + "{}"; + os << from_ascii(macro); + col += macro.size(); + return true; + } + return false; } - output += correction(env); + macro += correction(env); } else - output += env; - output += "}"; - if (suffix == "\\begin") - output += "\n"; - return output; -} - - -void adjust_column(string const & str, int & column) -{ - if (!contains(str, "\n")) - column += str.size(); - else { - string tmp; - column = rsplit(str, tmp, '\n').size(); + macro += env; + macro += "}"; + if (suffix == "\\par\\end") { + os << breakln; + col = 0; + } + os << from_ascii(macro); + col += macro.size(); + if (suffix == "\\begin") { + os << breakln; + col = 0; } + return true; } } // namespace anon @@ -2248,8 +2154,12 @@ int Paragraph::Private::startTeXParParams(BufferParams const & bparams, { int column = 0; - if (params_.noindent() && !layout_->pass_thru - && (layout_->toggle_indent != ITOGGLE_NEVER)) { + bool canindent = + (bparams.paragraph_separation == BufferParams::ParagraphIndentSeparation) ? + (layout_->toggle_indent != ITOGGLE_NEVER) : + (layout_->toggle_indent == ITOGGLE_ALWAYS); + + if (canindent && params_.noindent() && !layout_->pass_thru) { os << "\\noindent "; column += 10; } @@ -2288,28 +2198,19 @@ int Paragraph::Private::startTeXParParams(BufferParams const & bparams, case LYX_ALIGN_DECIMAL: break; case LYX_ALIGN_LEFT: { - string output; if (owner_->getParLanguage(bparams)->babel() != "hebrew") - output = corrected_env(begin_tag, "flushleft", code, lastpar); + corrected_env(os, begin_tag, "flushleft", code, lastpar, column); else - output = corrected_env(begin_tag, "flushright", code, lastpar); - os << from_ascii(output); - adjust_column(output, column); + corrected_env(os, begin_tag, "flushright", code, lastpar, column); break; } case LYX_ALIGN_RIGHT: { - string output; if (owner_->getParLanguage(bparams)->babel() != "hebrew") - output = corrected_env(begin_tag, "flushright", code, lastpar); + corrected_env(os, begin_tag, "flushright", code, lastpar, column); else - output = corrected_env(begin_tag, "flushleft", code, lastpar); - os << from_ascii(output); - adjust_column(output, column); + corrected_env(os, begin_tag, "flushleft", code, lastpar, column); break; } case LYX_ALIGN_CENTER: { - string output; - output = corrected_env(begin_tag, "center", code, lastpar); - os << from_ascii(output); - adjust_column(output, column); + corrected_env(os, begin_tag, "center", code, lastpar, column); break; } } @@ -2341,8 +2242,9 @@ bool Paragraph::Private::endTeXParParams(BufferParams const & bparams, break; } - string output; - string const end_tag = "\n\\par\\end"; + bool output = false; + int col = 0; + string const end_tag = "\\par\\end"; InsetCode code = ownerCode(); bool const lastpar = runparams.isLastPar; @@ -2355,26 +2257,23 @@ bool Paragraph::Private::endTeXParParams(BufferParams const & bparams, break; case LYX_ALIGN_LEFT: { if (owner_->getParLanguage(bparams)->babel() != "hebrew") - output = corrected_env(end_tag, "flushleft", code, lastpar); + output = corrected_env(os, end_tag, "flushleft", code, lastpar, col); else - output = corrected_env(end_tag, "flushright", code, lastpar); - os << from_ascii(output); + output = corrected_env(os, end_tag, "flushright", code, lastpar, col); break; } case LYX_ALIGN_RIGHT: { if (owner_->getParLanguage(bparams)->babel() != "hebrew") - output = corrected_env(end_tag, "flushright", code, lastpar); + output = corrected_env(os, end_tag, "flushright", code, lastpar, col); else - output = corrected_env(end_tag, "flushleft", code, lastpar); - os << from_ascii(output); + output = corrected_env(os, end_tag, "flushleft", code, lastpar, col); break; } case LYX_ALIGN_CENTER: { - output = corrected_env(end_tag, "center", code, lastpar); - os << from_ascii(output); + corrected_env(os, end_tag, "center", code, lastpar, col); break; } } - return !output.empty() || lastpar; + return output || lastpar; } @@ -2677,8 +2576,7 @@ void Paragraph::latex(BufferParams const & bparams, if (allowcust && d->endTeXParParams(bparams, os, runparams) && runparams.encoding != prev_encoding) { runparams.encoding = prev_encoding; - if (!runparams.isFullUnicode()) - os << setEncoding(prev_encoding->iconvName()); + os << setEncoding(prev_encoding->iconvName()); } LYXERR(Debug::LATEX, "Paragraph::latex... done " << this); @@ -3168,30 +3066,7 @@ docstring Paragraph::simpleLyXHTMLOnePar(Buffer const & buf, } } else { char_type c = getUChar(buf.masterBuffer()->params(), i); - - if (style.pass_thru || runparams.pass_thru) - xs << c; - else if (c == '-') { - docstring str; - int j = i + 1; - if (j < size() && d->text_[j] == '-') { - j += 1; - if (j < size() && d->text_[j] == '-') { - str += from_ascii("—"); - i += 2; - } else { - str += from_ascii("–"); - i += 1; - } - } - else - str += c; - // 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::ESCAPE_NONE << str; - } else - xs << c; + xs << c; } font_old = font.fontInfo(); } @@ -3266,16 +3141,13 @@ bool Paragraph::isHardHyphenOrApostrophe(pos_type pos) const if ((nextpos == psize || isSpace(nextpos)) && (pos == 0 || isSpace(prevpos))) return false; - return c == '\'' - || ((nextpos == psize || d->text_[nextpos] != '-') - && (pos == 0 || d->text_[prevpos] != '-')); + return true; } -bool Paragraph::isSameSpellRange(pos_type pos1, pos_type pos2) const +FontSpan const & Paragraph::getSpellRange(pos_type pos) const { - return pos1 == pos2 - || d->speller_state_.getRange(pos1) == d->speller_state_.getRange(pos2); + return d->speller_state_.getRange(pos); } @@ -3394,21 +3266,23 @@ docstring Paragraph::asString(pos_type beg, pos_type end, int options, const Out } -void Paragraph::forOutliner(docstring & os, size_t maxlen) const +void Paragraph::forOutliner(docstring & os, size_t const maxlen, + bool const shorten) const { + size_t tmplen = shorten ? maxlen + 1 : maxlen; if (!d->params_.labelString().empty()) os += d->params_.labelString() + ' '; - for (pos_type i = 0; i < size() && os.length() < maxlen; ++i) { + for (pos_type i = 0; i < size() && os.length() < tmplen; ++i) { if (isDeleted(i)) continue; char_type const c = d->text_[i]; if (isPrintable(c)) os += c; - else if (c == '\t' || c == '\n') - os += ' '; else if (c == META_INSET) - getInset(i)->forOutliner(os, maxlen); + getInset(i)->forOutliner(os, tmplen, false); } + if (shorten) + Text::shortenForOutliner(os, maxlen); }