]> git.lyx.org Git - lyx.git/blobdiff - src/insets/InsetIndex.cpp
Rename LATEX debug level to OUTFILE and use it for DocBook, HTML, and XML messages.
[lyx.git] / src / insets / InsetIndex.cpp
index 7790ad91fb865ca79c91445185edcc90dd699084..fe0890c4ae18beab7bc1f39f22bf2af1f6d2afb4 100644 (file)
@@ -80,35 +80,41 @@ void InsetIndex::latex(otexstream & ios, OutputParams const & runparams_in) cons
                os << '{';
        }
 
+       // Get the LaTeX output from InsetText. We need to deconstruct this later
+       // in order to check if we need to generate a sorting key
        odocstringstream ourlatex;
        otexstream ots(ourlatex);
        InsetText::latex(ots, runparams);
-       if (runparams.for_search) {
+       if (runparams.for_searchAdv != OutputParams::NoSearch) {
                // No need for special handling, if we are only searching for some patterns
                os << ourlatex.str() << "}";
                return;
        }
-       // get contents of InsetText as LaTeX and plaintext
+
+       // For the sorting key, we use the plaintext version
        odocstringstream ourplain;
        InsetText::plaintext(ourplain, runparams);
-       // FIXME: do Tex/Row correspondence (I don't currently understand what is
-       // being generated from latexstr below)
+
+       // These are the LaTeX and plaintext representations
        docstring latexstr = ourlatex.str();
        docstring plainstr = ourplain.str();
 
-       // this will get what follows | if anything does
+       // This will get what follows | if anything does,
+       // the command (e.g., see, textbf) for pagination
+       // formatting
        docstring cmd;
 
-       // check for the | separator
-       // FIXME This would go wrong on an escaped "|", but
-       // how far do we want to go here?
+       // Check for the | separator to strip the cmd.
+       // This goes wrong on an escaped "|", but as the escape
+       // character can be changed in style files, we cannot
+       // prevent that.
        size_t pos = latexstr.find(from_ascii("|"));
        if (pos != docstring::npos) {
-               // put the bit after "|" into cmd...
+               // Put the bit after "|" into cmd...
                cmd = latexstr.substr(pos + 1);
                // ...and erase that stuff from latexstr
                latexstr = latexstr.erase(pos);
-               // ...and similarly from plainstr
+               // ...as well as from plainstr
                size_t ppos = plainstr.find(from_ascii("|"));
                if (ppos < plainstr.size())
                        plainstr.erase(ppos);
@@ -116,8 +122,10 @@ void InsetIndex::latex(otexstream & ios, OutputParams const & runparams_in) cons
                        LYXERR0("The `|' separator was not found in the plaintext version!");
        }
 
-       // Separate the entries and subentries, i.e., split on "!"
-       // FIXME This would do the wrong thing with escaped ! characters
+       // Separate the entries and subentries, i.e., split on "!".
+       // This goes wrong on an escaped "!", but as the escape
+       // character can be changed in style files, we cannot
+       // prevent that.
        std::vector<docstring> const levels =
                        getVectorFromString(latexstr, from_ascii("!"), true);
        std::vector<docstring> const levels_plain =
@@ -128,19 +136,23 @@ void InsetIndex::latex(otexstream & ios, OutputParams const & runparams_in) cons
        vector<docstring>::const_iterator it2 = levels_plain.begin();
        bool first = true;
        for (; it != end; ++it) {
-               // write the separator except the first time
+               // The separator needs to be put back when
+               // writing the levels, except for the first level
                if (!first)
                        os << '!';
                else
                        first = false;
 
-               // correctly sort macros and formatted strings
-               // if we do find a command, prepend a plain text
+               // Now here comes the reason for this whole procedure:
+               // We try to correctly sort macros and formatted strings.
+               // If we find a command, prepend a plain text
                // version of the content to get sorting right,
-               // e.g. \index{LyX@\LyX}, \index{text@\textbf{text}}
-               // Don't do that if the user entered '@' himself, though.
+               // e.g. \index{LyX@\LyX}, \index{text@\textbf{text}}.
+               // We do this on all levels.
+               // We don't do it if the level already contains a '@', though.
                if (contains(*it, '\\') && !contains(*it, '@')) {
-                       // Plaintext might return nothing (e.g. for ERTs)
+                       // Plaintext might return nothing (e.g. for ERTs).
+                       // In that case, we use LaTeX.
                        docstring const spart =
                                        (it2 < levels_plain.end() && !(*it2).empty())
                                        ? *it2 : *it;
@@ -155,23 +167,28 @@ void InsetIndex::latex(otexstream & ios, OutputParams const & runparams_in) cons
                        if (spart != spart_latexed.first && !runparams.dryrun) {
                                // FIXME: warning should be passed to the error dialog
                                frontend::Alert::warning(_("Index sorting failed"),
-                                                                                bformat(_("LyX's automatic index sorting algorithm faced\n"
-                                                                                                                  "problems with the entry '%1$s'.\n"
-                                                                                                                  "Please specify the sorting of this entry manually, as\n"
-                                                                                                                  "explained in the User Guide."), spart));
+                                                        bformat(_("LyX's automatic index sorting algorithm faced\n"
+                                                                  "problems with the entry '%1$s'.\n"
+                                                                  "Please specify the sorting of this entry manually, as\n"
+                                                                  "explained in the User Guide."), spart));
                        }
-                       // remove remaining \'s for the sorting part
-                       docstring const ppart =
-                                       subst(spart_latexed.first, from_ascii("\\"), docstring());
+                       // Remove remaining \'s from the sort key
+                       docstring ppart = subst(spart_latexed.first, from_ascii("\\"), docstring());
+                       // Plain quotes need to be escaped, however (#10649), as this
+                       // is the default escape character
+                       ppart = subst(ppart, from_ascii("\""), from_ascii("\\\""));
+
+                       // Now insert the sortkey, separated by '@'.
                        os << ppart;
                        os << '@';
                }
+               // Insert the actual level text
                docstring const tpart = *it;
                os << tpart;
                if (it2 < levels_plain.end())
                        ++it2;
        }
-       // write the bit that followed "|"
+       // At last, re-insert the command, separated by "|"
        if (!cmd.empty()) {
                os << "|" << cmd;
        }
@@ -189,21 +206,22 @@ void InsetIndex::latex(otexstream & ios, OutputParams const & runparams_in) cons
 void InsetIndex::docbook(XMLStream & xs, OutputParams const & runparams) const
 {
        // Get the content of the inset as LaTeX, as some things may be encoded as ERT (like {}).
+       // TODO: if there is an ERT within the index term, its conversion should be tried, in case it becomes useful;
+       //  otherwise, ERTs should become comments. For now, they are just copied as-is, which is barely satisfactory.
        odocstringstream odss;
        otexstream ots(odss);
        InsetText::latex(ots, runparams);
        docstring latexString = trim(odss.str());
 
-       // Check whether there are unsupported things.
-       if (latexString.find(from_utf8("@")) != latexString.npos) {
-               docstring error = from_utf8("Unsupported feature: an index entry contains an @. "
+       // Check whether there are unsupported things. @ is supported, but only for sorting, without specific formatting.
+       if (latexString.find(from_utf8("@\\")) != lyx::docstring::npos) {
+               docstring error = from_utf8("Unsupported feature: an index entry contains an @\\. "
                                                                        "Complete entry: \"") + latexString + from_utf8("\"");
                LYXERR0(error);
                xs << XMLStream::ESCAPE_NONE << (from_utf8("<!-- Output Error: ") + error + from_utf8(" -->\n"));
-               // TODO: implement @ using the sortas attribute (on primary, secondary, tertiary).
        }
 
-       // Handle several indices.
+       // Handle several indices (indicated in the inset instead of the raw latexString).
        docstring indexType = from_utf8("");
        if (buffer().masterBuffer()->params().use_indices) {
                indexType += " type=\"" + params_.index + "\"";
@@ -212,14 +230,25 @@ void InsetIndex::docbook(XMLStream & xs, OutputParams const & runparams) const
        // Split the string into its main constituents: terms, and command (see, see also, range).
        size_t positionVerticalBar = latexString.find(from_ascii("|")); // What comes before | is (sub)(sub)entries.
        docstring indexTerms = latexString.substr(0, positionVerticalBar);
-       docstring command = latexString.substr(positionVerticalBar + 1);
+       docstring command;
+       if (positionVerticalBar != lyx::docstring::npos) {
+               command =  latexString.substr(positionVerticalBar + 1);
+       }
+
+       // Handle sorting issues, with @.
+       vector<docstring> sortingElements = getVectorFromString(indexTerms, from_ascii("@"), false);
+       docstring sortAs;
+       if (sortingElements.size() == 2) {
+               sortAs = sortingElements[0];
+               indexTerms = sortingElements[1];
+       }
 
        // Handle primary, secondary, and tertiary terms (entries, subentries, and subsubentries, for LaTeX).
        vector<docstring> terms = getVectorFromString(indexTerms, from_ascii("!"), false);
 
-       // Handle ranges. Happily, (| and |) can only be at the end of the string! However, | may be trapped by the
-       bool hasStartRange = latexString.find(from_ascii("|(")) != latexString.npos;
-       bool hasEndRange = latexString.find(from_ascii("|)")) != latexString.npos;
+       // Handle ranges. Happily, (| and |) can only be at the end of the string!
+       bool hasStartRange = latexString.find(from_ascii("|(")) != lyx::docstring::npos;
+       bool hasEndRange = latexString.find(from_ascii("|)")) != lyx::docstring::npos;
        if (hasStartRange || hasEndRange) {
                // Remove the ranges from the command if they do not appear at the beginning.
                size_t index = 0;
@@ -258,7 +287,7 @@ void InsetIndex::docbook(XMLStream & xs, OutputParams const & runparams) const
                } else {
                        see = list;
 
-                       if (see.find(from_ascii(",")) != see.npos) {
+                       if (see.find(from_ascii(",")) != std::string::npos) {
                                docstring error = from_utf8("Several index terms found as \"see\"! Only one is acceptable. "
                                                                                        "Complete entry: \"") + latexString + from_utf8("\"");
                                LYXERR0(error);
@@ -275,6 +304,12 @@ void InsetIndex::docbook(XMLStream & xs, OutputParams const & runparams) const
        // If there are such things in the index entry, then this code may miserably fail. For example, for "Peter|(textbf",
        // no range will be detected.
        // TODO: Could handle formatting as significance="preferred"?
+       if (!command.empty()) {
+               docstring error = from_utf8("Unsupported feature: an index entry contains a | with an unsupported command, ")
+                                         + command + from_utf8(". ") + from_utf8("Complete entry: \"") + latexString + from_utf8("\"");
+               LYXERR0(error);
+               xs << XMLStream::ESCAPE_NONE << (from_utf8("<!-- Output Error: ") + error + from_utf8(" -->\n"));
+       }
 
     // Write all of this down.
        if (terms.empty() && !hasEndRange) {
@@ -335,7 +370,12 @@ void InsetIndex::docbook(XMLStream & xs, OutputParams const & runparams) const
                } else {
                        xs << xml::StartTag("indexterm", attrs);
                        if (!terms.empty()) { // hasEndRange has no content.
-                               xs << xml::StartTag("primary");
+                               docstring attr;
+                               if (!sortAs.empty()) {
+                                       attr = from_utf8("sortas='") + sortAs + from_utf8("'");
+                               }
+
+                               xs << xml::StartTag("primary", attr);
                                xs << terms[0];
                                xs << xml::EndTag("primary");
                        }