X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2FInsetIndex.cpp;h=fe0890c4ae18beab7bc1f39f22bf2af1f6d2afb4;hb=997f0621c5346bb623cf86713c4fe1be0c941104;hp=7790ad91fb865ca79c91445185edcc90dd699084;hpb=6775d7c3a2bccdc064dc0fb37564b8941d956541;p=lyx.git diff --git a/src/insets/InsetIndex.cpp b/src/insets/InsetIndex.cpp index 7790ad91fb..fe0890c4ae 100644 --- a/src/insets/InsetIndex.cpp +++ b/src/insets/InsetIndex.cpp @@ -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 const levels = getVectorFromString(latexstr, from_ascii("!"), true); std::vector const levels_plain = @@ -128,19 +136,23 @@ void InsetIndex::latex(otexstream & ios, OutputParams const & runparams_in) cons vector::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("\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 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 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("\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"); }