]> git.lyx.org Git - lyx.git/blob - src/insets/InsetCounter.cpp
Add empty line after last \bibitem in bibliography (#12041)
[lyx.git] / src / insets / InsetCounter.cpp
1 /**
2  * \file InsetCounter.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Richard Kimberly Heck
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10 #include <config.h>
11
12 #include "InsetCounter.h"
13
14 #include "Buffer.h"
15 #include "BufferParams.h"
16 #include "Counters.h"
17 #include "LaTeXFeatures.h"
18 #include "output_xhtml.h"
19 #include "xml.h"
20 #include "texstream.h"
21 #include "TextClass.h"
22
23 #include "support/convert.h"
24 #include "support/counter_reps.h"
25 #include "support/docstream.h"
26 #include "support/gettext.h"
27 #include "support/lassert.h"
28 #include "support/lstrings.h"
29
30 #include <map>
31
32 /*
33 #include "Cursor.h"
34 #include "DispatchResult.h"
35 #include "Language.h"
36 #include "LyX.h"
37 #include "ParIterator.h"
38 #include "TocBackend.h"
39
40 #include "support/debug.h"
41 #include "support/textutils.h"
42 */
43
44 using namespace lyx::support;
45 using namespace std;
46
47 namespace lyx {
48
49
50 InsetCounter::InsetCounter(Buffer * buf, InsetCommandParams const & p)
51         : InsetCommand(buf, p)
52 {}
53
54
55 InsetCounter::InsetCounter(InsetCounter const & ir)
56         : InsetCommand(ir)
57 {}
58
59
60 const vector<pair<string, string>> InsetCounter::counterTable =
61 {
62         {"set", N_("Set counter to ...")},
63         {"addto", N_("Increase counter by ...")},
64         {"reset", N_("Reset counter to 0")},
65         {"save", N_("Save current counter value")},
66         {"restore", N_("Restore saved counter value")},
67 };
68
69
70 bool InsetCounter::isCompatibleCommand(string const & s)
71 {
72         for (auto & i : counterTable) {
73                 if (i.first == s)
74                         return true;
75         }
76         return false;
77 }
78
79
80 ParamInfo const & InsetCounter::findInfo(string const & /* cmdName */)
81 {
82         static ParamInfo param_info_;
83         if (param_info_.empty()) {
84                 param_info_.add("counter", ParamInfo::LYX_INTERNAL);
85                 param_info_.add("value", ParamInfo::LYX_INTERNAL);
86                 param_info_.add("lyxonly", ParamInfo::LYX_INTERNAL);
87         }
88         return param_info_;
89 }
90
91
92 void InsetCounter::latex(otexstream & os, OutputParams const &) const
93 {
94         bool const lyxonly = lowercase(getParam("lyxonly")) == "true";
95         if (lyxonly)
96                 return;
97
98         string const cmd = getCmdName();
99         docstring cntr = getParam("counter");
100         Counters & cnts = buffer().params().documentClass().counters();
101         if (cmd == "set") {
102                 docstring const & val = getParam("value");
103                 os << "\\setcounter{" << cntr << "}{" << val << "}";
104         } else if (cmd == "addto") {
105                 docstring const & val = getParam("value");
106                 os << "\\addtocounter{" << cntr << "}{" << val << "}";
107         } else if (cmd == "reset") {
108                 os << "\\setcounter{" << cntr << "}{0}";
109         } else if (cmd == "save") {
110                 cnts.saveValue(cntr);
111                 os << "\\setcounter{" << lyxSaveCounter()
112                    << "}{\\value{" << cntr << "}}";
113         } else if (cmd == "restore") {
114                 cnts.restoreValue(cntr);
115                 os << "\\setcounter{" << cntr
116                    << "}{\\value{" << lyxSaveCounter() << "}}";
117         }
118 }
119
120
121 void InsetCounter::toString(odocstream & os) const
122 {
123         os << "[Counter " << from_utf8(getCmdName()) << ": "
124            <<  getParam("counter") << "]";
125 }
126
127
128 int InsetCounter::plaintext(odocstringstream & os,
129         OutputParams const &, size_t) const
130 {
131         toString(os);
132         return 0;
133 }
134
135
136 #if 0
137 // save this code until we get it working in InsetInfo
138 const map<string, string> InsetCounter::valueTable =
139 {
140         {"Roman", N_("Roman Uppercase")},
141         {"roman", N_("Roman Lowercase")},
142         {"Alpha", N_("Uppercase Letter")},
143         {"alpha", N_("Lowercase Letter")},
144         {"arabic", N_("Arabic Numeral")}
145 };
146
147
148 docstring InsetCounter::value() const {
149         docstring const & cnt = getParam("counter");
150         string const & vtype = getCmdName();
151         int const val = buffer().params().documentClass().counters().value(cnt);
152         if (vtype   == "Roman")
153                 return romanCounter(val);
154         if (vtype   == "roman")
155                 return lowerromanCounter(val);
156         if (vtype   == "Alpha")
157                 return docstring(1, alphaCounter(val));
158         if (vtype   == "alpha")
159                 return docstring(1, loweralphaCounter(val));
160         if (vtype   == "arabic")
161                 return convert<docstring>(val);
162         LATTEST(false);
163         return empty_docstring();
164 }
165 #endif
166
167 void InsetCounter::trackCounters(string const & cmd) const
168 {
169         Counters & cnts = buffer().params().documentClass().counters();
170         docstring cntr = getParam("counter");
171         if (cmd == "set") {
172                 docstring const & val = getParam("value");
173                 cnts.set(cntr, convert<int>(val));
174         } else if (cmd == "addto") {
175                 docstring const & val = getParam("value");
176                 cnts.addto(cntr, convert<int>(val));
177         } else if (cmd == "reset") {
178                 cnts.reset(cntr);
179         } else if (cmd == "save") {
180                 cnts.saveValue(cntr);
181         } else if (cmd == "restore") {
182                 cnts.restoreValue(cntr);
183         }
184 }
185
186 void InsetCounter::docbook(XMLStream &, OutputParams const &) const
187 {
188         // Here, we need to track counter values ourselves,
189         // since unlike in the LaTeX case, there is no external
190         // mechanism for doing that.
191         trackCounters(getCmdName());
192 }
193
194
195 docstring InsetCounter::xhtml(XMLStream &, OutputParams const &) const
196 {
197         // Here, we need to track counter values ourselves,
198         // since unlike in the LaTeX case, there is no external
199         // mechanism for doing that.
200         trackCounters(getCmdName());
201         return docstring();
202 }
203
204
205 void InsetCounter::updateBuffer(ParIterator const &, UpdateType, bool const)
206 {
207         string const cmd = getCmdName();
208         docstring cntr = getParam("counter");
209         Counters & cnts = buffer().params().documentClass().counters();
210         string label;
211         for (auto & i : counterTable) {
212                 if (i.first == cmd)
213                         label = i.second;
214         }
215         LASSERT(!label.empty(), return);
216         docstring const tlabel = translateIfPossible(from_ascii(label));
217
218         docstring guiname = translateIfPossible(cnts.guiName(cntr));
219         if (cmd == "set") {
220                 docstring const & val = getParam("value");
221                 cnts.set(cntr, convert<int>(val));
222                 screen_label_ = bformat(_("Counter: Set %1$s"), guiname);
223                 tooltip_ = bformat(_("Set value of counter %1$s to %2$s"), cntr, val);
224         } else if (cmd == "addto") {
225                 docstring const & val = getParam("value");
226                 cnts.addto(cntr, convert<int>(val));
227                 screen_label_ = bformat(_("Counter: Add to %1$s"), guiname);
228                 tooltip_ = bformat(_("Add %1$s to value of counter %2$s"), val, cntr);
229         } else if (cmd == "reset") {
230                 cnts.reset(cntr);
231                 screen_label_ = bformat(_("Counter: Reset %1$s"), guiname);
232                 tooltip_ = bformat(_("Reset value of counter %1$s"), cntr);
233         } else if (cmd == "save") {
234                 cnts.saveValue(cntr);
235                 screen_label_ = bformat(_("Counter: Save %1$s"), guiname);
236                 tooltip_ = bformat(_("Save value of counter %1$s"), cntr);
237         } else if (cmd == "restore") {
238                 cnts.restoreValue(cntr);
239                 screen_label_ = bformat(_("Counter: Restore %1$s"), guiname);
240                 tooltip_ = bformat(_("Restore value of counter %1$s"), cntr);
241         }
242 }
243
244
245 docstring InsetCounter::lyxSaveCounter() const
246 {
247         docstring cntr = getParam("counter");
248         return from_ascii("LyXSave") + cntr;
249 }
250
251
252 void InsetCounter::validate(LaTeXFeatures & features) const
253 {
254         // create save counter if needed
255         string const cmd = getCmdName();
256         docstring const lyxonly = getParam("lyxonly");
257         if ((cmd == "save" || cmd == "restore") && lyxonly != "true") {
258                 features.addPreambleSnippet(from_ascii("\\newcounter{") + lyxSaveCounter() + "}");
259         }
260     InsetCommand::validate(features);
261 }
262
263
264 string InsetCounter::contextMenuName() const
265 {
266     return "context-counter";
267 }
268 } // namespace lyx