]> git.lyx.org Git - features.git/blobdiff - src/Paragraph.cpp
Add basic support for cprotect
[features.git] / src / Paragraph.cpp
index 4a83d932678a1572c7a1aa0734d58aaf54acb1be..b7ce543cafc3f2e41211350a5a23c960a12de1e1 100644 (file)
@@ -1238,10 +1238,8 @@ void Paragraph::Private::latexSpecialChar(otexstream & os,
                if (i + 1 < static_cast<pos_type>(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
+                       // Prevent "--" becoming an en dash and "---" an em dash.
+                       // (Within \ttfamily, "---" is merged to en dash + hyphen.)
                        os << "{}";
                        column += 2;
                }
@@ -1289,7 +1287,13 @@ void Paragraph::Private::latexSpecialChar(otexstream & os,
 
        case 0x2013:
        case 0x2014:
-               if (bparams.use_dash_ligatures && !bparams.useNonTeXFonts) {
+               // XeTeX's dash behaviour is determined via a global setting
+               if (bparams.use_dash_ligatures
+                   && owner_->getFontSettings(bparams, i).fontInfo().family() != TYPEWRITER_FAMILY
+                   && !runparams.inIPA
+                       // TODO #10961: && not in inset Flex Code
+                       // TODO #10961: && not in layout LyXCode
+                   && (!bparams.useNonTeXFonts || runparams.flavor != OutputParams::XETEX)) {
                        if (c == 0x2013) {
                                // en-dash
                                os << "--";
@@ -1426,43 +1430,18 @@ bool Paragraph::Private::latexSpecialT3(char_type const c, otexstream & os,
 void Paragraph::Private::validate(LaTeXFeatures & features) const
 {
        if (layout_->inpreamble && inset_owner_) {
-               bool const is_command = layout_->latextype == LATEX_COMMAND;
-               Buffer const & buf = inset_owner_->buffer();
-               BufferParams const & bp = features.runparams().is_child
-                       ? buf.masterParams() : buf.params();
-               Font f;
-               // Using a string stream here circumvents the encoding
+               // FIXME: Using a string stream here circumvents the encoding
                // switching machinery of odocstream. Therefore the
                // output is wrong if this paragraph contains content
                // that needs to switch encoding.
+               Buffer const & buf = inset_owner_->buffer();
                otexstringstream os;
                os << layout_->preamble();
-               if (is_command) {
-                       os << '\\' << from_ascii(layout_->latexname());
-                       // 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_->latexargs().empty()) {
-                               OutputParams rp = features.runparams();
-                               rp.local_font = &owner_->getFirstFontSettings(bp);
-                               latexArgInsets(*owner_, os, rp, layout_->latexargs());
-                       }
-                       os << from_ascii(layout_->latexparam());
-               }
                size_t const length = os.length();
-               // this will output "{" at the beginning, but not at the end
-               owner_->latex(bp, f, os, features.runparams(), 0, -1, true);
-               if (os.length() > length) {
-                       if (is_command) {
-                               os << '}';
-                               if (!layout_->postcommandargs().empty()) {
-                                       OutputParams rp = features.runparams();
-                                       rp.local_font = &owner_->getFirstFontSettings(bp);
-                                       latexArgInsets(*owner_, os, rp, layout_->postcommandargs(), "post:");
-                               }
-                       }
+               TeXOnePar(buf, buf.text(), buf.getParFromID(owner_->id()).pit(), os,
+                         features.runparams(), string(), 0, -1, true);
+               if (os.length() > length)
                        features.addPreambleSnippet(os.release(), true);
-               }
        }
 
        if (features.runparams().flavor == OutputParams::HTML
@@ -1490,6 +1469,16 @@ void Paragraph::Private::validate(LaTeXFeatures & features) const
        for (; icit != iend; ++icit) {
                if (icit->inset) {
                        features.inDeletedInset(owner_->isDeleted(icit->pos));
+                       if (icit->inset->lyxCode() == FOOT_CODE) {
+                               // FIXME: an item inset would make things much easier.
+                               if ((layout_->latextype == LATEX_LIST_ENVIRONMENT
+                                    || (layout_->latextype == LATEX_ITEM_ENVIRONMENT
+                                        && layout_->margintype == MARGIN_FIRST_DYNAMIC))
+                                   && (icit->pos < begin_of_body_
+                                       || (icit->pos == begin_of_body_
+                                           && (icit->pos == 0 || text_[icit->pos - 1] != ' '))))
+                                       features.saveNoteEnv("description");
+                       }
                        icit->inset->validate(features);
                        features.inDeletedInset(false);
                        if (layout_->needprotect &&
@@ -1499,7 +1488,8 @@ void Paragraph::Private::validate(LaTeXFeatures & features) const
        }
 
        // then the contents
-       BufferParams const bp = features.buffer().masterParams();
+       BufferParams const bp = features.runparams().is_child
+               ? features.buffer().masterParams() : features.buffer().params();
        for (pos_type i = 0; i < int(text_.size()) ; ++i) {
                char_type c = text_[i];
                if (c == 0x0022) {
@@ -1509,6 +1499,12 @@ void Paragraph::Private::validate(LaTeXFeatures & features) const
                                 || ((&owner_->getFontSettings(bp, i))->language()->internalFontEncoding()))
                                features.require("textquotedbl");
                }
+               if (!bp.use_dash_ligatures
+                   && (c == 0x2013 || c == 0x2014)
+                   && bp.useNonTeXFonts
+                   && features.runparams().flavor == OutputParams::XETEX)
+                       // XeTeX's dash behaviour is determined via a global setting
+                       features.require("xetexdashbreakstate");
                BufferEncodings::validate(c, features);
        }
 }
@@ -1698,6 +1694,8 @@ void Paragraph::write(ostream & os, BufferParams const & bparams,
 void Paragraph::validate(LaTeXFeatures & features) const
 {
        d->validate(features);
+       if (needsCProtection())
+               features.require("cprotect");
 }
 
 
@@ -2398,7 +2396,9 @@ void Paragraph::latex(BufferParams const & bparams,
 
        // if the paragraph is empty, the loop will not be entered at all
        if (empty()) {
-               if (style.isCommand()) {
+               // For InTitle commands, we have already opened a group
+               // in output_latex::TeXOnePar.
+               if (style.isCommand() && !style.intitle) {
                        os << '{';
                        ++column;
                }
@@ -2436,7 +2436,9 @@ void Paragraph::latex(BufferParams const & bparams,
                                os << "}] ";
                                column +=3;
                        }
-                       if (style.isCommand()) {
+                       // For InTitle commands, we have already opened a group
+                       // in output_latex::TeXOnePar.
+                       if (style.isCommand() && !style.intitle) {
                                os << '{';
                                ++column;
                        }
@@ -2661,7 +2663,7 @@ void Paragraph::latex(BufferParams const & bparams,
                                        ParagraphList const & pars =
                                                textinset->text().paragraphs();
                                        pit_type const pit = pars.size() - 1;
-                                       Font const last_font =
+                                       Font const lastfont =
                                                pit < 0 || pars[pit].empty()
                                                ? pars[pit].getLayoutFont(
                                                                bparams,
@@ -2669,7 +2671,7 @@ void Paragraph::latex(BufferParams const & bparams,
                                                : pars[pit].getFont(bparams,
                                                        pars[pit].size() - 1,
                                                        outerfont);
-                                       if (last_font.fontInfo().size() !=
+                                       if (lastfont.fontInfo().size() !=
                                            basefont.fontInfo().size()) {
                                                ++parInline;
                                                incremented = true;
@@ -3376,6 +3378,17 @@ bool Paragraph::isHardHyphenOrApostrophe(pos_type pos) const
 }
 
 
+bool Paragraph::needsCProtection() const
+{
+       pos_type size = d->text_.size();
+       for (pos_type i = 0; i < size; ++i)
+               if (isInset(i))
+                       return getInset(i)->needsCProtection();
+
+       return false;
+}
+
+
 FontSpan const & Paragraph::getSpellRange(pos_type pos) const
 {
        return d->speller_state_.getRange(pos);
@@ -3435,28 +3448,22 @@ void Paragraph::changeLanguage(BufferParams const & bparams,
 bool Paragraph::isMultiLingual(BufferParams const & bparams) const
 {
        Language const * doc_language = bparams.language;
-       FontList::const_iterator cit = d->fontlist_.begin();
-       FontList::const_iterator end = d->fontlist_.end();
-
-       for (; cit != end; ++cit)
-               if (cit->font().language() != ignore_language &&
-                   cit->font().language() != latex_language &&
-                   cit->font().language() != doc_language)
+       for (auto const & f : d->fontlist_)
+               if (f.font().language() != ignore_language &&
+                   f.font().language() != latex_language &&
+                   f.font().language() != doc_language)
                        return true;
        return false;
 }
 
 
-void Paragraph::getLanguages(std::set<Language const *> & languages) const
+void Paragraph::getLanguages(std::set<Language const *> & langs) 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();
+       for (auto const & f : d->fontlist_) {
+               Language const * lang = f.font().language();
                if (lang != ignore_language &&
                    lang != latex_language)
-                       languages.insert(lang);
+                       langs.insert(lang);
        }
 }
 
@@ -3503,6 +3510,8 @@ void Paragraph::forOutliner(docstring & os, size_t const maxlen,
        size_t tmplen = shorten ? maxlen + 1 : maxlen;
        if (label && !labelString().empty())
                os += labelString() + ' ';
+       if (!layout().isTocCaption())
+               return;
        for (pos_type i = 0; i < size() && os.length() < tmplen; ++i) {
                if (isDeleted(i))
                        continue;
@@ -4148,6 +4157,15 @@ SpellChecker::Result Paragraph::spellCheck(pos_type & from, pos_type & to,
 }
 
 
+void Paragraph::anonymize()
+{
+       // This is a very crude anonymization for now
+       for (char_type & c : d->text_)
+               if (isLetterChar(c) || isNumber(c))
+                       c = 'a';
+}
+
+
 void Paragraph::Private::markMisspelledWords(
        pos_type const & first, pos_type const & last,
        SpellChecker::Result result,