]> git.lyx.org Git - lyx.git/blob - src/insets/InsetIndex.cpp
fix warning
[lyx.git] / src / insets / InsetIndex.cpp
1 /**
2  * \file InsetIndex.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Lars Gullik Bjønnes
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10 #include <config.h>
11
12 #include "InsetIndex.h"
13
14 #include "Buffer.h"
15 #include "DispatchResult.h"
16 #include "Encoding.h"
17 #include "FuncRequest.h"
18 #include "FuncStatus.h"
19 #include "LaTeXFeatures.h"
20 #include "MetricsInfo.h"
21 #include "sgml.h"
22 #include "TocBackend.h"
23
24 #include "support/debug.h"
25 #include "support/docstream.h"
26 #include "support/gettext.h"
27 #include "support/lstrings.h"
28
29 #include "frontends/alert.h"
30
31 #include <ostream>
32
33 using namespace std;
34 using namespace lyx::support;
35
36 namespace lyx {
37
38 /////////////////////////////////////////////////////////////////////
39 //
40 // InsetIndex
41 //
42 ///////////////////////////////////////////////////////////////////////
43
44
45 InsetIndex::InsetIndex(Buffer const & buf)
46         : InsetCollapsable(buf)
47 {}
48
49
50 int InsetIndex::latex(odocstream & os,
51                       OutputParams const & runparams) const
52 {
53         os << "\\index";
54         os << '{';
55         int i = 7;
56
57         // get contents of InsetText as LaTeX and plaintext
58         odocstringstream ourlatex;
59         InsetText::latex(ourlatex, runparams);
60         odocstringstream ourplain;
61         InsetText::plaintext(ourplain, runparams);
62         docstring latexstr = ourlatex.str();
63         docstring plainstr = ourplain.str();
64
65         // this will get what follows | if anything does
66         docstring cmd;
67
68         // check for the | separator
69         // FIXME This would go wrong on an escaped "|", but
70         // how far do we want to go here?
71         size_t pos = latexstr.find(from_ascii("|"));
72         if (pos != docstring::npos) {
73                 // put the bit after "|" into cmd...
74                 cmd = latexstr.substr(pos + 1);
75                 // ...and erase that stuff from latexstr
76                 latexstr = latexstr.erase(pos);
77                 // ...and similarly from plainstr
78                 size_t ppos = plainstr.find(from_ascii("|"));
79                 if (ppos < plainstr.size())
80                         plainstr.erase(ppos);
81                 else
82                         LYXERR0("The `|' separator was not found in the plaintext version!");
83         }
84
85         // Separate the entires and subentries, i.e., split on "!"
86         // FIXME This would do the wrong thing with escaped ! characters
87         std::vector<docstring> const levels =
88                 getVectorFromString(latexstr, from_ascii("!"), true);
89         std::vector<docstring> const levels_plain =
90                 getVectorFromString(plainstr, from_ascii("!"), true);
91
92         vector<docstring>::const_iterator it = levels.begin();
93         vector<docstring>::const_iterator end = levels.end();
94         vector<docstring>::const_iterator it2 = levels_plain.begin();
95         bool first = true;
96         for (; it != end; ++it) {
97                 // write the separator except the first time
98                 if (!first) {
99                         os << '!';
100                         i += 1;
101                 } else
102                         first = false;
103
104                 // correctly sort macros and formatted strings
105                 // if we do find a command, prepend a plain text
106                 // version of the content to get sorting right,
107                 // e.g. \index{LyX@\LyX}, \index{text@\textbf{text}}
108                 // Don't do that if the user entered '@' himself, though.
109                 if (contains(*it, '\\') && !contains(*it, '@')) {
110                         // Plaintext might return nothing (e.g. for ERTs)
111                         docstring const spart = 
112                                 (it2 < levels_plain.end() && !(*it2).empty())
113                                 ? *it2 : *it;
114                         // Now we need to validate that all characters in
115                         // the sorting part are representable in the current
116                         // encoding. If not try the LaTeX macro which might
117                         // or might not be a good choice, and issue a warning.
118                         docstring spart2;
119                         for (size_t n = 0; n < spart.size(); ++n) {
120                                 try {
121                                         spart2 += runparams.encoding->latexChar(spart[n]);
122                                 } catch (EncodingException & /* e */) {
123                                         LYXERR0("Uncodable character in index entry. Sorting might be wrong!");
124                                 }
125                         }
126                         if (spart != spart2 && !runparams.dryrun) {
127                                 // FIXME: warning should be passed to the error dialog
128                                 frontend::Alert::warning(_("Index sorting failed"),
129                                 bformat(_("LyX's automatic index sorting algorithm faced\n"
130                                   "problems with the entry '%1$s'.\n"
131                                   "Please specify the sorting of this entry manually, as\n"
132                                   "explained in the User Guide."), spart));
133                         }
134                         // remove remaining \'s for the sorting part
135                         docstring const ppart =
136                                 subst(spart2, from_ascii("\\"), docstring());
137                         os << ppart;
138                         os << '@';
139                         i += ppart.size() + 1;
140                 }
141                 docstring const tpart = *it;
142                 os << tpart;
143                 i += tpart.size();
144                 if (it2 < levels_plain.end())
145                         ++it2;
146         }
147         // write the bit that followed "|"
148         if (!cmd.empty()) {
149                 os << "|" << cmd;
150                 i += cmd.size() + 1;
151         }
152         os << '}';
153         i += 1;
154         return i;
155 }
156
157
158 int InsetIndex::docbook(odocstream & os, OutputParams const & runparams) const
159 {
160         os << "<indexterm><primary>";
161         int const i = InsetText::docbook(os, runparams);
162         os << "</primary></indexterm>";
163         return i;
164 }
165
166
167 void InsetIndex::write(ostream & os) const
168 {
169         os << to_utf8(name()) << "\n";
170         InsetCollapsable::write(os);
171 }
172
173
174 void InsetIndex::addToToc(DocIterator const & cpit)
175 {
176         DocIterator pit = cpit;
177         pit.push_back(CursorSlice(*this));
178
179         Toc & toc = buffer().tocBackend().toc("index");
180         docstring str;
181         str = getNewLabel(str);
182         toc.push_back(TocItem(pit, 0, str));
183         // Proceed with the rest of the inset.
184         InsetCollapsable::addToToc(cpit);
185 }
186
187
188 /////////////////////////////////////////////////////////////////////
189 //
190 // InsetPrintIndex
191 //
192 ///////////////////////////////////////////////////////////////////////
193
194 InsetPrintIndex::InsetPrintIndex(InsetCommandParams const & p)
195         : InsetCommand(p, string())
196 {}
197
198
199 ParamInfo const & InsetPrintIndex::findInfo(string const & /* cmdName */)
200 {
201         static ParamInfo param_info_;
202         if (param_info_.empty())
203                 param_info_.add("name", ParamInfo::LATEX_REQUIRED);
204         return param_info_;
205 }
206
207
208 docstring InsetPrintIndex::screenLabel() const
209 {
210         return _("Index");
211 }
212
213
214 void InsetPrintIndex::validate(LaTeXFeatures & features) const
215 {
216         features.require("makeidx");
217 }
218
219
220 InsetCode InsetPrintIndex::lyxCode() const
221 {
222         return INDEX_PRINT_CODE;
223 }
224
225 } // namespace lyx