From e15a8f3551f86a2ffa835c344256f2b4703fefb2 Mon Sep 17 00:00:00 2001 From: Juergen Spitzmueller Date: Mon, 30 Jan 2017 07:44:55 +0100 Subject: [PATCH] Extend LATEXIFY command param handling and add literal param. File format change. This allows for the relevant InsetCommand-based dialogs (such as citation text before/after, Bibitem label, hyperlink name etc.) to provide both the input of verbatim code or text that is transformed to proper LaTeX code. Some dialogs (Nomencl, Href) already had some methods (although they could not be toggled), which are now centralized and streamlined. The initial work of this patch has been done by Georg Baum (see http://www.lyx.org/trac/attachment/ticket/2751/x.diff) Fixes: #2751, #8227. --- development/FORMAT | 5 + lib/lyx2lyx/lyx_2_3.py | 52 ++++++++- src/BufferParams.cpp | 15 +-- src/frontends/qt4/GuiBibitem.cpp | 5 + src/frontends/qt4/GuiCitation.cpp | 4 + src/frontends/qt4/GuiHyperlink.cpp | 6 + src/frontends/qt4/GuiNomenclature.cpp | 5 + src/frontends/qt4/GuiPrintindex.cpp | 5 + src/frontends/qt4/ui/BibitemUi.ui | 138 ++++++++++++---------- src/frontends/qt4/ui/CitationUi.ui | 10 ++ src/frontends/qt4/ui/HyperlinkUi.ui | 146 ++++++++++++++++------- src/frontends/qt4/ui/NomenclUi.ui | 69 ++++++----- src/frontends/qt4/ui/PrintindexUi.ui | 162 +++++++++++++++----------- src/insets/InsetBibitem.cpp | 56 +++------ src/insets/InsetCitation.cpp | 25 ++-- src/insets/InsetCitation.h | 2 - src/insets/InsetCommand.cpp | 20 ++++ src/insets/InsetCommand.h | 2 + src/insets/InsetCommandParams.cpp | 38 +++++- src/insets/InsetHyperlink.cpp | 56 +++------ src/insets/InsetIndex.cpp | 16 ++- src/insets/InsetIndex.h | 2 + src/insets/InsetNomencl.cpp | 2 + src/tex2lyx/text.cpp | 27 +++-- src/version.h | 4 +- 25 files changed, 538 insertions(+), 334 deletions(-) diff --git a/development/FORMAT b/development/FORMAT index 3c464f339f..d03a6b4547 100644 --- a/development/FORMAT +++ b/development/FORMAT @@ -7,6 +7,11 @@ changes happened in particular if possible. A good example would be ----------------------- +2017-01-28 Jürgen Spitzmüller + * Format incremented to 532: literal command inset parameter. + With this, inset command params with ParamInfo::HANDLING_LATEXIFY + can be passed to LaTeX either verbatim or latexified. + 2017-01-21 Jürgen Spitzmüller * Format incremented to 531: Support for qualified citation lists. \begin_inset CommandInset citation diff --git a/lib/lyx2lyx/lyx_2_3.py b/lib/lyx2lyx/lyx_2_3.py index 044bc755f1..23bdda8e0b 100644 --- a/lib/lyx2lyx/lyx_2_3.py +++ b/lib/lyx2lyx/lyx_2_3.py @@ -1547,6 +1547,54 @@ def revert_qualicites(document): i += 1 +command_insets = ["bibitem", "citation", "href", "index_print", "nomenclature"] +def convert_literalparam(document): + " Add param literal " + + # These already had some sort of latexify method + latexified_insets = ["href", "index_print", "nomenclature"] + + for inset in command_insets: + i = 0 + while True: + i = find_token(document.body, '\\begin_inset CommandInset %s' % inset, i) + if i == -1: + break + j = find_end_of_inset(document.body, i) + if j == -1: + document.warning("Malformed LyX document: Can't find end of %s inset at line %d" % (inset, i)) + i += 1 + continue + while i < j and document.body[i].strip() != '': + i += 1 + if inset in latexified_insets: + document.body.insert(i, "literal \"false\"") + else: + document.body.insert(i, "literal \"true\"") + + + +def revert_literalparam(document): + " Remove param literal " + + for inset in command_insets: + i = 0 + while True: + i = find_token(document.body, '\\begin_inset CommandInset %s' % inset, i) + if i == -1: + break + j = find_end_of_inset(document.body, i) + if j == -1: + document.warning("Malformed LyX document: Can't find end of %s inset at line %d" % (inset, i)) + i += 1 + continue + k = find_token(document.body, 'literal', i, j) + if k == -1: + i += 1 + continue + del document.body[k] + + ## # Conversion hub # @@ -1575,10 +1623,12 @@ convert = [ [528, []], [529, []], [530, []], - [531, []] + [531, []], + [532, [convert_literalparam]] ] revert = [ + [531, [revert_literalparam]], [530, [revert_qualicites]], [529, [revert_bibpackopts]], [528, [revert_citekeyonly]], diff --git a/src/BufferParams.cpp b/src/BufferParams.cpp index 2736c26977..e044d4e45a 100644 --- a/src/BufferParams.cpp +++ b/src/BufferParams.cpp @@ -1961,20 +1961,7 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features, IndicesList::const_iterator iit = indiceslist().begin(); IndicesList::const_iterator iend = indiceslist().end(); for (; iit != iend; ++iit) { - pair indexname_latex = - features.runparams().encoding->latexString(iit->index(), - features.runparams().dryrun); - if (!indexname_latex.second.empty()) { - // issue a warning about omitted characters - // FIXME: should be passed to the error dialog - frontend::Alert::warning(_("Uncodable characters"), - bformat(_("The following characters that are used in an index name are not\n" - "representable in the current encoding and therefore have been omitted:\n%1$s."), - indexname_latex.second)); - } - os << "\\newindex["; - os << indexname_latex.first; - os << "]{"; + os << "\\newindex{"; os << escape(iit->shortcut()); os << "}\n"; } diff --git a/src/frontends/qt4/GuiBibitem.cpp b/src/frontends/qt4/GuiBibitem.cpp index 052be00f36..b29f8a8704 100644 --- a/src/frontends/qt4/GuiBibitem.cpp +++ b/src/frontends/qt4/GuiBibitem.cpp @@ -32,6 +32,8 @@ GuiBibitem::GuiBibitem(QWidget * parent) : InsetParamsWidget(parent) this, SIGNAL(changed())); connect(labelED, SIGNAL(textChanged(QString)), this, SIGNAL(changed())); + connect(literalCB, SIGNAL(clicked()), + this, SIGNAL(changed())); } @@ -41,6 +43,7 @@ void GuiBibitem::paramsToDialog(Inset const * inset) InsetCommandParams const & params = ic->params(); keyED->setText(toqstr(params["key"])); labelED->setText(toqstr(params["label"])); + literalCB->setChecked(params["literal"] == "true"); } @@ -49,6 +52,8 @@ docstring GuiBibitem::dialogToParams() const InsetCommandParams params(insetCode()); params["key"] = qstring_to_ucs4(keyED->text()); params["label"] = qstring_to_ucs4(labelED->text()); + params["literal"] = literalCB->isChecked() + ? from_ascii("true") : from_ascii("false"); return from_utf8(InsetCommand::params2string(params)); } diff --git a/src/frontends/qt4/GuiCitation.cpp b/src/frontends/qt4/GuiCitation.cpp index 2178dd1101..826a814cd6 100644 --- a/src/frontends/qt4/GuiCitation.cpp +++ b/src/frontends/qt4/GuiCitation.cpp @@ -127,6 +127,8 @@ GuiCitation::GuiCitation(GuiView & lv) this, SLOT(on_citationStyleCO_currentIndexChanged(int))); connect(starredCB, SIGNAL(clicked()), this, SLOT(updateStyles())); + connect(literalCB, SIGNAL(clicked()), + this, SLOT(changed())); connect(forceuppercaseCB, SIGNAL(clicked()), this, SLOT(updateStyles())); connect(textBeforeED, SIGNAL(textChanged(QString)), @@ -585,6 +587,7 @@ void GuiCitation::applyParams(int const choice, bool full, bool force, params_["pretextlist"] = getStringFromVector(getPreTexts(), from_ascii("\t")); params_["posttextlist"] = getStringFromVector(getPostTexts(), from_ascii("\t")); } + params_["literal"] = literalCB->isChecked() ? from_ascii("true") : from_ascii("false"); dispatchParams(); } @@ -726,6 +729,7 @@ void GuiCitation::init() documentBuffer().params().fullAuthorList()); textBeforeED->setText(toqstr(params_["before"])); textAfterED->setText(toqstr(params_["after"])); + literalCB->setChecked(params_["literal"] == "true"); setPreTexts(getVectorFromString(params_["pretextlist"], from_ascii("\t"))); setPostTexts(getVectorFromString(params_["posttextlist"], from_ascii("\t"))); diff --git a/src/frontends/qt4/GuiHyperlink.cpp b/src/frontends/qt4/GuiHyperlink.cpp index 3111d193c4..4bf50a094a 100644 --- a/src/frontends/qt4/GuiHyperlink.cpp +++ b/src/frontends/qt4/GuiHyperlink.cpp @@ -40,6 +40,8 @@ GuiHyperlink::GuiHyperlink(QWidget * parent) : InsetParamsWidget(parent) this, SIGNAL(changed())); connect(nameED, SIGNAL(textChanged(const QString &)), this, SIGNAL(changed())); + connect(literalCB, SIGNAL(clicked()), + this, SIGNAL(changed())); connect(webRB, SIGNAL(clicked()), this, SIGNAL(changed())); connect(emailRB, SIGNAL(clicked()), @@ -58,6 +60,7 @@ void GuiHyperlink::paramsToDialog(Inset const * inset) targetED->setText(toqstr(params["target"])); nameED->setText(toqstr(params["name"])); + literalCB->setChecked(params["literal"] == "true"); docstring const & type = params["type"]; if (type.empty()) webRB->setChecked(true); @@ -75,6 +78,7 @@ bool GuiHyperlink::initialiseParams(std::string const & data) return false; targetED->setText(toqstr(params["target"])); nameED->setText(toqstr(params["name"])); + literalCB->setChecked(params["literal"] == "true"); if (params["type"] == from_utf8("mailto:")) emailRB->setChecked(true); else if (params["type"] == from_utf8("file:")) @@ -97,6 +101,8 @@ docstring GuiHyperlink::dialogToParams() const params["type"] = from_utf8("mailto:"); else if (fileRB->isChecked()) params["type"] = from_utf8("file:"); + params["literal"] = literalCB->isChecked() + ? from_ascii("true") : from_ascii("false"); params.setCmdName("href"); return from_utf8(InsetHyperlink::params2string(params)); } diff --git a/src/frontends/qt4/GuiNomenclature.cpp b/src/frontends/qt4/GuiNomenclature.cpp index 0a52bd1403..3afad18a83 100644 --- a/src/frontends/qt4/GuiNomenclature.cpp +++ b/src/frontends/qt4/GuiNomenclature.cpp @@ -29,6 +29,8 @@ GuiNomenclature::GuiNomenclature(QWidget * parent) : InsetParamsWidget(parent) this, SIGNAL(changed())); connect(descriptionTE, SIGNAL(textChanged()), this, SIGNAL(changed())); + connect(literalCB, SIGNAL(clicked()), + this, SIGNAL(changed())); setFocusProxy(descriptionTE); } @@ -41,6 +43,7 @@ void GuiNomenclature::paramsToDialog(Inset const * inset) prefixED->setText(toqstr(params["prefix"])); symbolED->setText(toqstr(params["symbol"])); + literalCB->setChecked(params["literal"] == "true"); QString description = toqstr(params["description"]); description.replace("\\\\","\n"); descriptionTE->setPlainText(description); @@ -56,6 +59,8 @@ docstring GuiNomenclature::dialogToParams() const QString description = descriptionTE->toPlainText(); description.replace('\n',"\\\\"); params["description"] = qstring_to_ucs4(description); + params["literal"] = literalCB->isChecked() + ? from_ascii("true") : from_ascii("false"); return from_utf8(InsetNomencl::params2string(params)); } diff --git a/src/frontends/qt4/GuiPrintindex.cpp b/src/frontends/qt4/GuiPrintindex.cpp index c667584aab..be8c0cd9b6 100644 --- a/src/frontends/qt4/GuiPrintindex.cpp +++ b/src/frontends/qt4/GuiPrintindex.cpp @@ -43,6 +43,7 @@ GuiPrintindex::GuiPrintindex(GuiView & lv) connect(cancelPB, SIGNAL(clicked()), this, SLOT(slotClose())); connect(indicesCO, SIGNAL(activated(int)), this, SLOT(change_adaptor())); connect(subindexCB, SIGNAL(clicked()), this, SLOT(change_adaptor())); + connect(literalCB, SIGNAL(clicked()), this, SLOT(change_adaptor())); bc().setPolicy(ButtonPolicy::NoRepeatedApplyReadOnlyPolicy); bc().setOK(okPB); @@ -78,6 +79,7 @@ void GuiPrintindex::updateContents() int const pos = indicesCO->findData(toqstr(cur_index)); indicesCO->setCurrentIndex(pos); subindexCB->setChecked(params_.getCmdName() == "printsubindex"); + literalCB->setChecked(params_["literal"] == "true"); } @@ -95,6 +97,8 @@ void GuiPrintindex::applyView() params_["type"] = docstring(); else params_["type"] = qstring_to_ucs4(index); + params_["literal"] = literalCB->isChecked() + ? from_ascii("true") : from_ascii("false"); } @@ -105,6 +109,7 @@ void GuiPrintindex::paramsToDialog(InsetCommandParams const & /*icp*/) indicesCO->findData(toqstr(params_["type"])); subindexCB->setChecked(params_.getCmdName() == "printsubindex"); indicesCO->setCurrentIndex(pos); + literalCB->setChecked(params_["literal"] == "true"); bc().setValid(isValid()); } diff --git a/src/frontends/qt4/ui/BibitemUi.ui b/src/frontends/qt4/ui/BibitemUi.ui index 0dfc146bc3..559a199887 100644 --- a/src/frontends/qt4/ui/BibitemUi.ui +++ b/src/frontends/qt4/ui/BibitemUi.ui @@ -1,3 +1,4 @@ + BibitemUi @@ -5,71 +6,90 @@ 0 0 - 211 - 74 + 218 + 121 - - - 9 - - - 6 - - - - - - 0 - 0 - - - - The bibliography key - - - - - - - - 0 - 0 - - - - The label as it appears in the document - - - - - - - The label as it appears in the document - - - &Label: - - - labelED - - - + - - - The bibliography key - - - &Key: - - - keyED - - + + + + + The bibliography key + + + Ke&y: + + + keyED + + + + + + + The label as it appears in the document + + + &Label: + + + labelED + + + + + + + + + + + + + + + + + + + 0 + 0 + + + + The bibliography key + + + + + + + + 0 + 0 + + + + The label as it appears in the document + + + + + + + Pass content of the `Label' field literally to LaTeX. Check this if you want to enter LaTeX code. + + + Li&teral + + + + diff --git a/src/frontends/qt4/ui/CitationUi.ui b/src/frontends/qt4/ui/CitationUi.ui index 6b43968a1a..cdd5189305 100644 --- a/src/frontends/qt4/ui/CitationUi.ui +++ b/src/frontends/qt4/ui/CitationUi.ui @@ -359,6 +359,16 @@ 0 + + + + Pass content of `Text before' and `Text after' fields literally to LaTeX. Check this if you want to enter LaTeX code. + + + Li&teral + + + diff --git a/src/frontends/qt4/ui/HyperlinkUi.ui b/src/frontends/qt4/ui/HyperlinkUi.ui index c423e16250..5bbf954a4b 100644 --- a/src/frontends/qt4/ui/HyperlinkUi.ui +++ b/src/frontends/qt4/ui/HyperlinkUi.ui @@ -1,3 +1,4 @@ + HyperlinkUi @@ -5,55 +6,101 @@ 0 0 - 343 - 130 + 290 + 188 - - - - URL - - - &Target: - - - targetED - - - - - - - URL - - + + + + + + + + URL + + + &Target: + + + targetED + + + + + + + Name associated with the URL + + + &Name: + + + nameED + + + + + + + + + + + + + + + + + + URL + + + + + + + Name associated with the URL + + + + + + + + + Pass content of the `Name' field literally to LaTeX. Check this if you want to enter LaTeX code. + + + Li&teral + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + - - - Name associated with the URL - - - &Name: - - - nameED - - - - - - - Name associated with the URL - - - - Specify the link target @@ -65,7 +112,16 @@ 6 - + + 9 + + + 9 + + + 9 + + 9 @@ -87,7 +143,7 @@ Link to an email address - &Email + E&mail @@ -97,14 +153,14 @@ Link to a file - &File + Fi&le - + Qt::Horizontal diff --git a/src/frontends/qt4/ui/NomenclUi.ui b/src/frontends/qt4/ui/NomenclUi.ui index c7431d09b9..9baff247d6 100644 --- a/src/frontends/qt4/ui/NomenclUi.ui +++ b/src/frontends/qt4/ui/NomenclUi.ui @@ -1,3 +1,4 @@ + NomenclUi @@ -6,46 +7,17 @@ 0 0 254 - 172 + 222 Nomenclature - - - 9 - - - 6 - - - - - - - - Sort &as: - - - prefixED - - - - - - - &Description: - - - descriptionTE - - - + - &Symbol: + Sy&mbol: symbolED @@ -59,6 +31,16 @@ + + + + Des&cription: + + + descriptionTE + + + @@ -66,6 +48,29 @@ + + + + Sort &as: + + + prefixED + + + + + + + + + + Pass content of the `Symbol' and `Description' fields literally to LaTeX. Check this if you want to enter LaTeX code. + + + Li&teral + + + diff --git a/src/frontends/qt4/ui/PrintindexUi.ui b/src/frontends/qt4/ui/PrintindexUi.ui index ea49cbf434..74fa0a8a84 100644 --- a/src/frontends/qt4/ui/PrintindexUi.ui +++ b/src/frontends/qt4/ui/PrintindexUi.ui @@ -1,97 +1,119 @@ - + + PrintindexUi - - + + 0 0 - 262 - 130 + 287 + 148 - + - + true - - - 9 - - - 6 - - - - - &Cancel - - - true - - - - - - - &OK - - - false - - - - - - - Qt::Horizontal - - - - 78 - 29 - - - - - - - - Check if this index should be part (e.g., a section) of the former one. - - - &Subindex - - - - - - - 0 - - + + + + 6 + + 0 + + + 0 + + + 0 + + + 0 + - - - A&vailable indexes: + + + Avai&lable indexes: - + indicesCO - - + + Select the index that shall be printed at this place of the document. + + + + + + Check if this index should be part (e.g., a section) of the former one. + + + &Subindex + + + + + + + Pass index names literally to LaTeX. Check this if you want to use LaTeX code in index names. + + + Li&teral + + + + + + + + + + + Qt::Horizontal + + + + 78 + 29 + + + + + + + + &OK + + + false + + + + + + + &Cancel + + + true + + + + + @@ -100,7 +122,7 @@ cancelPB - qt_i18n.h + qt_i18n.h diff --git a/src/insets/InsetBibitem.cpp b/src/insets/InsetBibitem.cpp index d0a28e73fe..18a261a3e0 100644 --- a/src/insets/InsetBibitem.cpp +++ b/src/insets/InsetBibitem.cpp @@ -108,6 +108,7 @@ ParamInfo const & InsetBibitem::findInfo(string const & /* cmdName */) ParamInfo::HANDLING_LATEXIFY); param_info_.add("key", ParamInfo::LATEX_REQUIRED, ParamInfo::HANDLING_ESCAPE); + param_info_.add("literal", ParamInfo::LYX_INTERNAL); } return param_info_; } @@ -129,54 +130,24 @@ void InsetBibitem::doDispatch(Cursor & cur, FuncRequest & cmd) docstring const & old_key = params()["key"]; docstring const & old_label = params()["label"]; + docstring const & old_literal = params()["literal"]; docstring label = p["label"]; - - // definitions for escaping - static docstring const backslash = from_ascii("\\"); - static docstring const lbrace = from_ascii("{"); - static docstring const rbrace = from_ascii("}"); - static char_type const chars_escape[6] = { - '&', '_', '$', '%', '#', '^'}; - static char_type const brackets_escape[2] = {'[', ']'}; - - if (!label.empty()) { - int previous; - // The characters in chars_name[] need to be changed to a command when - // they are in the name field. - for (int k = 0; k < 6; k++) - for (size_t i = 0, pos; - (pos = label.find(chars_escape[k], i)) != string::npos; - i = pos + 2) { - if (pos == 0) - previous = 0; - else - previous = pos - 1; - // only if not already escaped - if (label[previous] != '\\') - label.replace(pos, 1, backslash + chars_escape[k] + lbrace + rbrace); - } - // The characters '[' and ']' need to be put into braces - for (int k = 0; k < 2; k++) - for (size_t i = 0, pos; - (pos = label.find(brackets_escape[k], i)) != string::npos; - i = pos + 2) { - if (pos == 0) - previous = 0; - else - previous = pos - 1; - // only if not already escaped - if (label[previous] != '{') - label.replace(pos, 1, lbrace + brackets_escape[k] + rbrace); - } - } + docstring literal = p["literal"]; if (old_label != label) { p["label"] = label; cur.forceBufferUpdate(); buffer().invalidateBibinfoCache(); } - setParam("label", p["label"]); + + if (old_literal != literal) { + p["literal"] = literal; + cur.forceBufferUpdate(); + buffer().invalidateBibinfoCache(); + } + setParam("literal", p["literal"]); + if (p["key"] != old_key) { updateCommand(p["key"]); cur.bv().buffer().changeRefsIfUnique(old_key, params()["key"]); @@ -301,9 +272,8 @@ docstring bibitemWidest(Buffer const & buffer, OutputParams const & runparams) } if (!lbl.empty()) { - pair latex_lbl = - runparams.encoding->latexString(lbl, runparams.dryrun); - return latex_lbl.first; + InsetCommandParams p(BIBITEM_CODE); + return p.prepareCommand(runparams, lbl, ParamInfo::HANDLING_LATEXIFY); } return from_ascii("99"); diff --git a/src/insets/InsetCitation.cpp b/src/insets/InsetCitation.cpp index 6f238f964d..b16077ffd9 100644 --- a/src/insets/InsetCitation.cpp +++ b/src/insets/InsetCitation.cpp @@ -66,11 +66,16 @@ ParamInfo const & InsetCitation::findInfo(string const & /* cmdName */) // we have to allow both here. InsetCitation takes care that // LaTeX output is nevertheless correct. if (param_info_.empty()) { - param_info_.add("after", ParamInfo::LATEX_OPTIONAL); - param_info_.add("before", ParamInfo::LATEX_OPTIONAL); + param_info_.add("after", ParamInfo::LATEX_OPTIONAL, + ParamInfo::HANDLING_LATEXIFY); + param_info_.add("before", ParamInfo::LATEX_OPTIONAL, + ParamInfo::HANDLING_LATEXIFY); param_info_.add("key", ParamInfo::LATEX_REQUIRED); - param_info_.add("pretextlist", ParamInfo::LATEX_OPTIONAL); - param_info_.add("posttextlist", ParamInfo::LATEX_OPTIONAL); + param_info_.add("pretextlist", ParamInfo::LATEX_OPTIONAL, + ParamInfo::HANDLING_LATEXIFY); + param_info_.add("posttextlist", ParamInfo::LATEX_OPTIONAL, + ParamInfo::HANDLING_LATEXIFY); + param_info_.add("literal", ParamInfo::LYX_INTERNAL); } return param_info_; } @@ -568,8 +573,10 @@ void InsetCitation::latex(otexstream & os, OutputParams const & runparams) const if (qualified) os << "s"; - docstring before = getParam("before"); - docstring after = getParam("after"); + docstring before = params().prepareCommand(runparams, getParam("before"), + param_info_["before"].handling()); + docstring after = params().prepareCommand(runparams, getParam("after"), + param_info_["after"].handling()); if (!before.empty() && cs.textBefore) { if (qualified) os << '(' << protectArgument(before, '(', ')') @@ -592,8 +599,10 @@ void InsetCitation::latex(otexstream & os, OutputParams const & runparams) const map pres = getQualifiedLists(getParam("pretextlist")); map posts = getQualifiedLists(getParam("posttextlist")); for (docstring const & k: keys) { - docstring bef = pres[k]; - docstring aft = posts[k]; + docstring bef = params().prepareCommand(runparams, pres[k], + param_info_["pretextlist"].handling()); + docstring aft = params().prepareCommand(runparams, posts[k], + param_info_["posttextlist"].handling()); if (!bef.empty()) os << '[' << protectArgument(bef) << "][" << protectArgument(aft) << ']'; diff --git a/src/insets/InsetCitation.h b/src/insets/InsetCitation.h index 57b0b3da9e..992a85ee21 100644 --- a/src/insets/InsetCitation.h +++ b/src/insets/InsetCitation.h @@ -64,8 +64,6 @@ public: /// void forOutliner(docstring &, size_t const, bool const) const; /// - void validate(LaTeXFeatures &) const {} - /// void updateBuffer(ParIterator const & it, UpdateType); /// void addToToc(DocIterator const & di, bool output_active, diff --git a/src/insets/InsetCommand.cpp b/src/insets/InsetCommand.cpp index 879d9a35e0..2e24d4d4e1 100644 --- a/src/insets/InsetCommand.cpp +++ b/src/insets/InsetCommand.cpp @@ -14,6 +14,7 @@ #include "InsetCommand.h" #include "Buffer.h" +#include "BufferEncodings.h" #include "BufferView.h" #include "Cursor.h" #include "DispatchResult.h" @@ -157,6 +158,25 @@ int InsetCommand::docbook(odocstream &, OutputParams const &) const } +void InsetCommand::validate(LaTeXFeatures & features) const +{ + if (params()["literal"] == "true") + return; + + ParamInfo::const_iterator it = params().info().begin(); + ParamInfo::const_iterator end = params().info().end(); + for (; it != end; ++it) { + if (it->handling() == ParamInfo::HANDLING_LATEXIFY) { + docstring const text = params()[it->name()]; + // Validate the contents (if we LaTeXify, specific + // macros might require packages) + for (pos_type i = 0; i < int(text.size()) ; ++i) + BufferEncodings::validate(text[i], features); + } + } +} + + void InsetCommand::doDispatch(Cursor & cur, FuncRequest & cmd) { switch (cmd.action()) { diff --git a/src/insets/InsetCommand.h b/src/insets/InsetCommand.h index ba7a945339..0514e09ffe 100644 --- a/src/insets/InsetCommand.h +++ b/src/insets/InsetCommand.h @@ -87,6 +87,8 @@ public: /// int docbook(odocstream &, OutputParams const & runparams) const; /// + void validate(LaTeXFeatures & features) const; + /// bool setMouseHover(BufferView const * bv, bool mouse_hover) const; /// bool clickable(BufferView const &, int, int) const { return hasSettings(); } diff --git a/src/insets/InsetCommandParams.cpp b/src/insets/InsetCommandParams.cpp index 79e3bd795b..5ea28ff3fc 100644 --- a/src/insets/InsetCommandParams.cpp +++ b/src/insets/InsetCommandParams.cpp @@ -422,20 +422,50 @@ docstring InsetCommandParams::prepareCommand(OutputParams const & runparams, docstring const & command, ParamInfo::ParamHandling handling) const { + if (handling == ParamInfo::HANDLING_LATEXIFY) + if ((*this)["literal"] == "true") + handling = ParamInfo::HANDLING_NONE; docstring result; switch (handling) { case ParamInfo::HANDLING_LATEXIFY: { + // First handle backslash + result = subst(command, from_ascii("\\"), from_ascii("\\textbackslash{}")); + // Then get LaTeX macros pair command_latexed = - runparams.encoding->latexString(command, runparams.dryrun); + runparams.encoding->latexString(result, runparams.dryrun); result = command_latexed.first; if (!command_latexed.second.empty()) { - // issue a warning about omitted characters + // Issue a warning about omitted characters // FIXME: should be passed to the error dialog frontend::Alert::warning(_("Uncodable characters"), bformat(_("The following characters that are used in the inset %1$s are not\n" "representable in the current encoding and therefore have been omitted:\n%2$s."), from_utf8(insetType()), command_latexed.second)); } + // Now escape special commands + static docstring const backslash = from_ascii("\\"); + static char_type const chars_escape[6] = { + '&', '_', '$', '%', '#', '^'}; + + if (!result.empty()) { + int previous; + // The characters in chars_name[] need to be changed to a command when + // they are LaTeXified. + for (int k = 0; k < 6; k++) + for (size_t i = 0, pos; + (pos = result.find(chars_escape[k], i)) != string::npos; + i = pos + 2) { + //(Only) \\^ needs to be terminated + docstring const term = (k == 5) ? from_ascii("{}") : docstring(); + if (pos == 0) + previous = 0; + else + previous = pos - 1; + // only if not already escaped + if (result[previous] != '\\') + result.replace(pos, 1, backslash + chars_escape[k] + term); + } + } break; } case ParamInfo::HANDLING_ESCAPE: @@ -470,10 +500,10 @@ docstring InsetCommandParams::getCommand(OutputParams const & runparams) const break; } case ParamInfo::LATEX_OPTIONAL: { - docstring const data = + docstring data = prepareCommand(runparams, (*this)[name], it->handling()); if (!data.empty()) { - s += '[' + data + ']'; + s += '[' + protectArgument(data) + ']'; noparam = false; } else if (writeEmptyOptional(it)) { s += "[]"; diff --git a/src/insets/InsetHyperlink.cpp b/src/insets/InsetHyperlink.cpp index 3160c0b001..8405c48440 100644 --- a/src/insets/InsetHyperlink.cpp +++ b/src/insets/InsetHyperlink.cpp @@ -48,9 +48,11 @@ ParamInfo const & InsetHyperlink::findInfo(string const & /* cmdName */) { static ParamInfo param_info_; if (param_info_.empty()) { - param_info_.add("name", ParamInfo::LATEX_OPTIONAL); + param_info_.add("name", ParamInfo::LATEX_OPTIONAL, + ParamInfo::HANDLING_LATEXIFY); param_info_.add("target", ParamInfo::LATEX_REQUIRED); param_info_.add("type", ParamInfo::LATEX_REQUIRED); + param_info_.add("literal", ParamInfo::LYX_INTERNAL); } return param_info_; } @@ -119,11 +121,7 @@ void InsetHyperlink::latex(otexstream & os, { docstring url = getParam("target"); docstring name = getParam("name"); - static docstring const backslash = from_ascii("\\"); - static docstring const braces = from_ascii("{}"); static char_type const chars_url[2] = {'%', '#'}; - static char_type const chars_name[6] = { - '&', '_', '$', '%', '#', '^'}; // For the case there is no name given, the target is set as name. // Do this before !url.empty() and !name.empty() to handle characters @@ -151,7 +149,7 @@ void InsetHyperlink::latex(otexstream & os, for (size_t i = 0, pos; (pos = url.find(chars_url[k], i)) != string::npos; i = pos + 2) - url.replace(pos, 1, backslash + chars_url[k]); + url.replace(pos, 1, from_ascii("\\") + chars_url[k]); // add "http://" when the type is web (type = empty) // and no "://" or "run:" is given @@ -163,46 +161,19 @@ void InsetHyperlink::latex(otexstream & os, } // end if (!url.empty()) - // The characters in chars_name[] need to be changed to a command when - // they are in the name field. if (!name.empty()) { - // handle the "\" character, but only when the following character - // is not also a "\", because "\\" is valid code - docstring const textbackslash = from_ascii("\\textbackslash{}"); - for (size_t i = 0, pos; - (pos = name.find('\\', i)) != string::npos; - i = pos + 2) { - if (name[pos + 1] != '\\') - name.replace(pos, 1, textbackslash); - } - // The characters in chars_name[] need to be changed to a command - // when they are in the name field. - // Therefore the treatment of "\" must be the first thing - for (int k = 0; k < 6; k++) - for (size_t i = 0, pos; - (pos = name.find(chars_name[k], i)) != string::npos; - i = pos + 2) - name.replace(pos, 1, backslash + chars_name[k] + braces); - + name = params().prepareCommand(runparams, getParam("name"), + ParamInfo::HANDLING_LATEXIFY); // replace the tilde by the \sim character as suggested in the // LaTeX FAQ for URLs - docstring const sim = from_ascii("$\\sim$"); - for (size_t i = 0, pos; - (pos = name.find('~', i)) != string::npos; - i = pos + 1) - name.replace(pos, 1, sim); - pair name_latexed = - runparams.encoding->latexString(name, runparams.dryrun); - name = name_latexed.first; - if (!name_latexed.second.empty() && !runparams.silent) { - // issue a warning about omitted characters - // FIXME: should be passed to the error dialog - frontend::Alert::warning(_("Uncodable characters"), - bformat(_("The following characters that are used in the href inset are not\n" - "representable in the current encoding and therefore have been omitted:\n%1$s."), - name_latexed.second)); + if (getParam("literal") != from_ascii("true")) { + docstring const sim = from_ascii("$\\sim$"); + for (size_t i = 0, pos; + (pos = name.find('~', i)) != string::npos; + i = pos + 1) + name.replace(pos, 1, sim); } - } // end if (!name.empty()) + } if (runparams.moving_arg) os << "\\protect"; @@ -287,6 +258,7 @@ docstring InsetHyperlink::toolTip(BufferView const & /*bv*/, int /*x*/, int /*y* void InsetHyperlink::validate(LaTeXFeatures & features) const { features.require("hyperref"); + InsetCommand::validate(features); } diff --git a/src/insets/InsetIndex.cpp b/src/insets/InsetIndex.cpp index d5d487f78e..38472f0bdc 100644 --- a/src/insets/InsetIndex.cpp +++ b/src/insets/InsetIndex.cpp @@ -436,8 +436,10 @@ ParamInfo const & InsetPrintIndex::findInfo(string const & /* cmdName */) static ParamInfo param_info_; if (param_info_.empty()) { param_info_.add("type", ParamInfo::LATEX_OPTIONAL, - ParamInfo::HANDLING_ESCAPE); - param_info_.add("name", ParamInfo::LATEX_REQUIRED); + ParamInfo::HANDLING_ESCAPE); + param_info_.add("name", ParamInfo::LATEX_OPTIONAL, + ParamInfo::HANDLING_LATEXIFY); + param_info_.add("literal", ParamInfo::LYX_INTERNAL); } return param_info_; } @@ -560,6 +562,15 @@ bool InsetPrintIndex::getStatus(Cursor & cur, FuncRequest const & cmd, } +void InsetPrintIndex::updateBuffer(ParIterator const &, UpdateType) +{ + Index const * index = + buffer().masterParams().indiceslist().findShortcut(getParam("type")); + if (index) + setParam("name", index->index()); +} + + void InsetPrintIndex::latex(otexstream & os, OutputParams const & runparams_in) const { if (!buffer().masterBuffer()->params().use_indices) { @@ -577,6 +588,7 @@ void InsetPrintIndex::validate(LaTeXFeatures & features) const features.require("makeidx"); if (buffer().masterBuffer()->params().use_indices) features.require("splitidx"); + InsetCommand::validate(features); } diff --git a/src/insets/InsetIndex.h b/src/insets/InsetIndex.h index 80d8149bc4..3ee17509dc 100644 --- a/src/insets/InsetIndex.h +++ b/src/insets/InsetIndex.h @@ -111,6 +111,8 @@ public: /// bool getStatus(Cursor &, FuncRequest const &, FuncStatus &) const; /// + void updateBuffer(ParIterator const & it, UpdateType); + /// std::string contextMenuName() const; /// Updates needed features for this inset. void validate(LaTeXFeatures & features) const; diff --git a/src/insets/InsetNomencl.cpp b/src/insets/InsetNomencl.cpp index 1613542db3..c8904e67e0 100644 --- a/src/insets/InsetNomencl.cpp +++ b/src/insets/InsetNomencl.cpp @@ -68,6 +68,7 @@ ParamInfo const & InsetNomencl::findInfo(string const & /* cmdName */) ParamInfo::HANDLING_LATEXIFY); param_info_.add("description", ParamInfo::LATEX_REQUIRED, ParamInfo::HANDLING_LATEXIFY); + param_info_.add("literal", ParamInfo::LYX_INTERNAL); } return param_info_; } @@ -134,6 +135,7 @@ int InsetNomencl::docbookGlossary(odocstream & os) const void InsetNomencl::validate(LaTeXFeatures & features) const { features.require("nomencl"); + InsetCommand::validate(features); } diff --git a/src/tex2lyx/text.cpp b/src/tex2lyx/text.cpp index b6f5f1799d..b3cbc46c66 100644 --- a/src/tex2lyx/text.cpp +++ b/src/tex2lyx/text.cpp @@ -1682,8 +1682,8 @@ void parse_environment(Parser & p, ostream & os, bool outer, p.skip_spaces(true); os << "btprint " << '"' << "btPrintAll" << '"' << "\n"; } - os << "bibfiles " << '"' << bibfile << '"' << "\n"; - os << "options " << '"' << bibstyle << '"' << "\n"; + os << "bibfiles " << '"' << bibfile << "\"\n" + << "options " << '"' << bibstyle << "\"\n"; parse_text_in_inset(p, os, FLAG_END, outer, parent_context); end_inset(os); p.skip_spaces(); @@ -2760,7 +2760,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, } else { begin_command_inset(os, "bibitem", "bibitem"); os << "label \"" << label << "\"\n" - "key \"" << key << "\"\n"; + << "key \"" << key << "\"\n" + << "literal \"true\"\n"; end_inset(os); } } @@ -3439,6 +3440,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, os << "target \"" << target << "\"\n"; if (type == "mailto:" || type == "file:") os << "type \"" << type << "\"\n"; + os << "literal \"true\"\n"; end_inset(os); skip_spaces_braces(p); } @@ -3585,7 +3587,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, os << "before " << '"' << before << '"' << "\n"; os << "key \"" << convert_command_inset_arg(p.verbatim_item()) - << "\"\n"; + << "\"\n" + << "literal \"true\"\n"; end_inset(os); // Need to set the cite engine if natbib is loaded by // the document class directly @@ -3637,9 +3640,10 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, before.erase(before.length() - 1, 1); } begin_command_inset(os, "citation", command); - os << "after " << '"' << after << '"' << "\n"; - os << "before " << '"' << before << '"' << "\n"; - os << "key " << '"' << citation << '"' << "\n"; + os << "after " << '"' << after << "\"\n" + << "before " << '"' << before << "\"\n" + << "key " << '"' << citation << "\"\n" + << "literal \"true\"\n"; end_inset(os); // Need to set the cite engine if jurabib is loaded by // the document class directly @@ -3656,8 +3660,9 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, // the BibTeX inset if (key != "*") { begin_command_inset(os, "citation", t.cs()); - os << "after " << '"' << after << '"' << "\n"; - os << "key " << '"' << key << '"' << "\n"; + os << "after " << '"' << after << "\"\n" + << "key " << '"' << key << "\"\n" + << "literal \"true\"\n"; end_inset(os); } else if (t.cs() == "nocite") btprint = key; @@ -3687,7 +3692,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, << convert_command_inset_arg(p.verbatim_item()); os << "\"\ndescription \"" << convert_command_inset_arg(p.verbatim_item()) - << "\"\n"; + << "\"\n" + << "literal \"true\"\n"; end_inset(os); preamble.registerAutomaticallyLoadedPackage("nomencl"); } @@ -3717,6 +3723,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, os << "type \"idx\"\n"; else os << "type \"" << indexname << "\"\n"; + os << "literal \"true\"\n"; } end_inset(os); skip_spaces_braces(p); diff --git a/src/version.h b/src/version.h index a0a611d20a..4056e9ddee 100644 --- a/src/version.h +++ b/src/version.h @@ -32,8 +32,8 @@ extern char const * const lyx_version_info; // Do not remove the comment below, so we get merge conflict in // independent branches. Instead add your own. -#define LYX_FORMAT_LYX 531 // spitz: qualified citation lists -#define LYX_FORMAT_TEX2LYX 531 +#define LYX_FORMAT_LYX 532 // gb/spitz add literal command inset parameter +#define LYX_FORMAT_TEX2LYX 532 #if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX #ifndef _MSC_VER