X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FParagraph.cpp;h=150c28d6a9adafe53b8be2cdc7d224dbf3d297e9;hb=69036ced3765f40048d62be800c98af3ea2d1b4a;hp=653c2864879806644453375f99c2f958a08bb358;hpb=95fedfe6425c3147766ba601f2ce0e4e49b4dc1a;p=lyx.git diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp index 653c286487..150c28d6a9 100644 --- a/src/Paragraph.cpp +++ b/src/Paragraph.cpp @@ -189,9 +189,8 @@ public: FontList fontlist_; /// - unsigned int id_; - /// - static unsigned int paragraph_id; + int id_; + /// ParagraphParameters params_; @@ -208,17 +207,15 @@ public: /// TextContainer text_; - typedef std::set Words; + typedef set Words; + typedef map LangWordsMap; /// - Words words_; + LangWordsMap words_; /// Layout const * layout_; }; -// Initialization of the counter for the paragraph id's, -unsigned int Paragraph::Private::paragraph_id = 0; - namespace { struct special_phrase { @@ -240,20 +237,26 @@ size_t const phrases_nr = sizeof(special_phrases)/sizeof(special_phrase); Paragraph::Private::Private(Paragraph * owner, Layout const & layout) - : owner_(owner), inset_owner_(0), begin_of_body_(0), layout_(&layout) + : owner_(owner), inset_owner_(0), id_(-1), begin_of_body_(0), layout_(&layout) { - id_ = paragraph_id++; text_.reserve(100); } +// Initialization of the counter for the paragraph id's, +// +// 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. +static int paragraph_id = -1; + Paragraph::Private::Private(Private const & p, Paragraph * owner) : owner_(owner), inset_owner_(p.inset_owner_), fontlist_(p.fontlist_), params_(p.params_), changes_(p.changes_), insetlist_(p.insetlist_), begin_of_body_(p.begin_of_body_), text_(p.text_), words_(p.words_), layout_(p.layout_) { - id_ = paragraph_id++; + id_ = ++paragraph_id; } @@ -265,7 +268,7 @@ Paragraph::Private::Private(Private const & p, Paragraph * owner, begin_of_body_(p.begin_of_body_), words_(p.words_), layout_(p.layout_) { - id_ = paragraph_id++; + id_ = ++paragraph_id; if (beg >= pos_type(p.text_.size())) return; text_ = p.text_.substr(beg, end - beg); @@ -844,9 +847,7 @@ void Paragraph::Private::latexInset( } if (tmp) { - for (int j = 0; j < tmp; ++j) - texrow.newline(); - + texrow.newlines(tmp); texrow.start(owner_->id(), i + 1); column = 0; } else { @@ -1078,10 +1079,21 @@ void Paragraph::Private::validate(LaTeXFeatures & features) const 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)); + // we have to provide all the optional arguments here, even though + // the last one is the only one we care about. + owner_->latex(bp, f, ods, tr, features.runparams(), 0, -1, true); + docstring const d = ods.str(); + if (!d.empty()) { + // this will have "{" at the beginning, but not at the end + string const content = to_utf8(d); + string const cmd = layout_->latexname(); + features.addPreambleSnippet("\\" + cmd + content + "}"); + } + } + + if (features.runparams().flavor == OutputParams::HTML + && layout_->htmltitle()) { + features.setHTMLTitle(owner_->asString(AS_STR_INSETS)); } // check the params. @@ -1649,7 +1661,21 @@ void Paragraph::setLabelWidthString(docstring const & s) } -docstring Paragraph::expandLabel(Layout const & layout, +docstring Paragraph::expandLabel(Layout const & layout, + BufferParams const & bparams) const +{ + return expandParagraphLabel(layout, bparams, true); +} + + +docstring Paragraph::expandDocBookLabel(Layout const & layout, + BufferParams const & bparams) const +{ + return expandParagraphLabel(layout, bparams, false); +} + + +docstring Paragraph::expandParagraphLabel(Layout const & layout, BufferParams const & bparams, bool process_appendix) const { DocumentClass const & tclass = bparams.documentClass(); @@ -1670,7 +1696,7 @@ docstring Paragraph::expandLabel(Layout const & layout, docstring parent(fmt, i + 1, j - i - 1); docstring label = from_ascii("??"); if (tclass.hasLayout(parent)) - docstring label = expandLabel(tclass[parent], bparams, + docstring label = expandParagraphLabel(tclass[parent], bparams, process_appendix); fmt = docstring(fmt, 0, i) + label + docstring(fmt, j + 1, docstring::npos); @@ -1829,6 +1855,7 @@ int Paragraph::Private::startTeXParParams(BufferParams const & bparams, case LYX_ALIGN_BLOCK: case LYX_ALIGN_LAYOUT: case LYX_ALIGN_SPECIAL: + case LYX_ALIGN_DECIMAL: break; case LYX_ALIGN_LEFT: case LYX_ALIGN_RIGHT: @@ -1849,6 +1876,7 @@ int Paragraph::Private::startTeXParParams(BufferParams const & bparams, case LYX_ALIGN_BLOCK: case LYX_ALIGN_LAYOUT: case LYX_ALIGN_SPECIAL: + case LYX_ALIGN_DECIMAL: break; case LYX_ALIGN_LEFT: { string output; @@ -1897,6 +1925,7 @@ int Paragraph::Private::endTeXParParams(BufferParams const & bparams, case LYX_ALIGN_BLOCK: case LYX_ALIGN_LAYOUT: case LYX_ALIGN_SPECIAL: + case LYX_ALIGN_DECIMAL: break; case LYX_ALIGN_LEFT: case LYX_ALIGN_RIGHT: @@ -1917,6 +1946,7 @@ int Paragraph::Private::endTeXParParams(BufferParams const & bparams, case LYX_ALIGN_BLOCK: case LYX_ALIGN_LAYOUT: case LYX_ALIGN_SPECIAL: + case LYX_ALIGN_DECIMAL: break; case LYX_ALIGN_LEFT: { string output; @@ -1950,26 +1980,24 @@ int Paragraph::Private::endTeXParParams(BufferParams const & bparams, // This one spits out the text of the paragraph -bool Paragraph::latex(BufferParams const & bparams, +void Paragraph::latex(BufferParams const & bparams, Font const & outerfont, odocstream & os, TexRow & texrow, OutputParams const & runparams, - int start_pos, int end_pos) const + int start_pos, int end_pos, bool force) const { LYXERR(Debug::LATEX, "Paragraph::latex... " << this); - if (layout().inpreamble) - return true; - - bool return_value = false; - - bool const allowcust = allowParagraphCustomization(); - // FIXME This check should not be needed. Perhaps issue an // error if it triggers. Layout const & style = inInset().forcePlainLayout() ? bparams.documentClass().plainLayout() : *d->layout_; + if (!force && style.inpreamble) + return; + + bool const allowcust = allowParagraphCustomization(); + // Current base font for all inherited font changes, without any // change caused by an individual character, except for the language: // It is set to the language of the first character. @@ -1983,8 +2011,10 @@ bool Paragraph::latex(BufferParams const & bparams, unsigned int column = 0; if (body_pos > 0) { - os << '['; - column += 1; + // 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); @@ -2030,8 +2060,8 @@ bool Paragraph::latex(BufferParams const & bparams, runparams); runningChange = Change(Change::UNCHANGED); - os << "] "; - column +=2; + os << "}] "; + column +=3; } if (style.isCommand()) { os << '{'; @@ -2202,9 +2232,8 @@ bool Paragraph::latex(BufferParams const & bparams, if (open_font) { #ifdef FIXED_LANGUAGE_END_DETECTION if (next_) { - running_font - .latexWriteEndChanges(os, bparams, runparams, - basefont, + running_font.latexWriteEndChanges(os, bparams, + runparams, basefont, next_->getFont(bparams, 0, outerfont)); } else { running_font.latexWriteEndChanges(os, bparams, @@ -2224,8 +2253,7 @@ bool Paragraph::latex(BufferParams const & bparams, // Needed if there is an optional argument but no contents. if (body_pos > 0 && body_pos == size()) { - os << "]~"; - return_value = false; + os << "}]~"; } if (allowcust && d->endTeXParParams(bparams, os, texrow, runparams) @@ -2236,7 +2264,6 @@ bool Paragraph::latex(BufferParams const & bparams, } LYXERR(Debug::LATEX, "Paragraph::latex... done " << this); - return return_value; } @@ -2312,7 +2339,7 @@ pos_type Paragraph::firstWordLyXHTML(XHTMLStream & xs, OutputParams const & runp char_type c = d->text_[i]; if (c == ' ') break; - xs << html::escapeChar(c); + xs << c; } } return i; @@ -2400,33 +2427,44 @@ docstring Paragraph::simpleLyXHTMLOnePar(Buffer const & buf, bool emph_flag = false; bool bold_flag = false; - std::string closing_tag; + string closing_tag; Layout const & style = *d->layout_; + + if (!runparams.for_toc && runparams.html_make_pars) { + // generate a magic label for this paragraph + string const attr = "id='" + magicLabel() + "'"; + xs << html::CompTag("a", attr); + } + FontInfo font_old = style.labeltype == LABEL_MANUAL ? style.labelfont : style.font; // parsing main loop for (pos_type i = initial; i < size(); ++i) { + // let's not show deleted material in the output + if (isDeleted(i)) + continue; + Font font = getFont(buf.params(), i, outerfont); // emphasis if (font_old.emph() != font.fontInfo().emph()) { if (font.fontInfo().emph() == FONT_ON) { - xs << StartTag("em"); + xs << html::StartTag("em"); emph_flag = true; } else if (emph_flag && i != initial) { - xs << EndTag("em"); + xs << html::EndTag("em"); emph_flag = false; } } // bold if (font_old.series() != font.fontInfo().series()) { if (font.fontInfo().series() == BOLD_SERIES) { - xs << StartTag("strong"); + xs << html::StartTag("strong"); bold_flag = true; } else if (bold_flag && i != initial) { - xs << EndTag("strong"); + xs << html::EndTag("strong"); bold_flag = false; } } @@ -2435,11 +2473,16 @@ docstring Paragraph::simpleLyXHTMLOnePar(Buffer const & buf, Inset const * inset = getInset(i); if (inset) { + InsetCommand const * ic = inset->asInsetCommand(); InsetLayout const & il = inset->getLayout(); - OutputParams np = runparams; - if (!il.htmlisblock()) - np.html_in_par = true; - retval += inset->xhtml(xs, np); + InsetMath const * im = inset->asInsetMath(); + if (!runparams.for_toc + || im || 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]; @@ -2564,7 +2607,7 @@ void Paragraph::changeLanguage(BufferParams const & bparams, bool Paragraph::isMultiLingual(BufferParams const & bparams) const { - Language const * doc_language = bparams.language; + Language const * doc_language = bparams.language; FontList::const_iterator cit = d->fontlist_.begin(); FontList::const_iterator end = d->fontlist_.end(); @@ -2577,6 +2620,20 @@ bool Paragraph::isMultiLingual(BufferParams const & bparams) const } +void Paragraph::getLanguages(std::set & languages) const +{ + FontList::const_iterator cit = d->fontlist_.begin(); + FontList::const_iterator end = d->fontlist_.end(); + + for (; cit != end; ++cit) { + Language const * lang = cit->font().language(); + if (lang != ignore_language && + lang != latex_language) + languages.insert(lang); + } +} + + docstring Paragraph::asString(int options) const { return asString(0, size(), options); @@ -2588,8 +2645,8 @@ docstring Paragraph::asString(pos_type beg, pos_type end, int options) const odocstringstream os; if (beg == 0 - && options & AS_STR_LABEL - && !d->params_.labelString().empty()) + && options & AS_STR_LABEL + && !d->params_.labelString().empty()) os << d->params_.labelString() << ' '; for (pos_type i = beg; i < end; ++i) { @@ -2643,6 +2700,12 @@ int Paragraph::id() const } +void Paragraph::setId(int id) +{ + d->id_ = id; +} + + Layout const & Paragraph::layout() const { return *d->layout_; @@ -3011,10 +3074,15 @@ bool Paragraph::isSeparator(pos_type pos) const void Paragraph::deregisterWords() { - Private::Words::const_iterator it; - WordList & wl = theWordList(); - for (it = d->words_.begin(); it != d->words_.end(); ++it) - wl.remove(*it); + Private::LangWordsMap::const_iterator itl = d->words_.begin(); + Private::LangWordsMap::const_iterator ite = d->words_.end(); + for (; itl != ite; ++itl) { + WordList * wl = theWordList(itl->first); + Private::Words::const_iterator it = (itl->second).begin(); + Private::Words::const_iterator et = (itl->second).end(); + for (; it != et; ++it) + wl->remove(*it); + } d->words_.clear(); } @@ -3058,15 +3126,22 @@ void Paragraph::locateWord(pos_type & from, pos_type & to, void Paragraph::collectWords() { + // This is the value that needs to be exposed in the preferences + // to resolve bug #6760. + static int minlength = 6; pos_type n = size(); for (pos_type pos = 0; pos < n; ++pos) { if (isWordSeparator(pos)) continue; pos_type from = pos; locateWord(from, pos, WHOLE_WORD); - if (pos - from >= 6) { + if (pos - from >= minlength) { docstring word = asString(from, pos, AS_STR_NONE); - d->words_.insert(word); + FontList::const_iterator cit = d->fontlist_.fontIterator(pos); + if (cit == d->fontlist_.end()) + return; + Language const * lang = cit->font().language(); + d->words_[*lang].insert(word); } } } @@ -3074,10 +3149,15 @@ void Paragraph::collectWords() void Paragraph::registerWords() { - Private::Words::const_iterator it; - WordList & wl = theWordList(); - for (it = d->words_.begin(); it != d->words_.end(); ++it) - wl.insert(*it); + Private::LangWordsMap::const_iterator itl = d->words_.begin(); + Private::LangWordsMap::const_iterator ite = d->words_.end(); + for (; itl != ite; ++itl) { + WordList * wl = theWordList(itl->first); + Private::Words::const_iterator it = (itl->second).begin(); + Private::Words::const_iterator et = (itl->second).end(); + for (; it != et; ++it) + wl->insert(*it); + } } @@ -3096,21 +3176,40 @@ bool Paragraph::spellCheck(pos_type & from, pos_type & to, WordLangTuple & wl, if (!speller) return false; + if (!d->layout_->spellcheck || !inInset().allowSpellCheck()) + return false; + locateWord(from, to, WHOLE_WORD); if (from == to || from >= pos_type(d->text_.size())) return false; docstring word = asString(from, to, AS_STR_INSETS); - string const lang_code = lyxrc.spellchecker_alt_lang.empty() - ? getFontSettings(d->inset_owner_->buffer().params(), from).language()->code() - : lyxrc.spellchecker_alt_lang; - wl = WordLangTuple(word, lang_code); - SpellChecker::Result res = speller->check(wl); + // Ignore words with digits + // FIXME: make this customizable + // (note that hunspell ignores words with digits by default) + bool const ignored = hasDigit(word); + Language * lang = const_cast(getFontSettings( + d->inset_owner_->buffer().params(), from).language()); + if (lang == d->inset_owner_->buffer().params().language + && !lyxrc.spellchecker_alt_lang.empty()) { + string lang_code; + string const lang_variety = + split(lyxrc.spellchecker_alt_lang, lang_code, '-'); + lang->setCode(lang_code); + lang->setVariety(lang_variety); + } + wl = WordLangTuple(word, lang); + SpellChecker::Result res = ignored ? + SpellChecker::OK : speller->check(wl); +#if 0 +// FIXME: the code below makes aspell abort if a word in an unknown +// language is checked. // Just ignore any error that the spellchecker reports. // FIXME: we should through out an exception and catch it in the GUI to // display the error. if (!speller->error().empty()) return false; +#endif bool const misspelled = res != SpellChecker::OK && res != SpellChecker::IGNORED_WORD; @@ -3137,4 +3236,12 @@ bool Paragraph::isMisspelled(pos_type pos) const } +string Paragraph::magicLabel() const +{ + stringstream ss; + ss << "magicparlabel-" << id(); + return ss.str(); +} + + } // namespace lyx