2 * \file InsetCounter.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Richard Kimberly Heck
8 * Full author contact details are available in file CREDITS.
12 #include "InsetCounter.h"
15 #include "BufferParams.h"
17 #include "LaTeXFeatures.h"
18 #include "OutputParams.h"
19 #include "output_xhtml.h"
21 #include "texstream.h"
22 #include "TextClass.h"
24 #include "support/convert.h"
25 #include "support/counter_reps.h"
26 #include "support/docstream.h"
27 #include "support/gettext.h"
28 #include "support/lassert.h"
29 #include "support/lstrings.h"
35 #include "DispatchResult.h"
38 #include "ParIterator.h"
39 #include "TocBackend.h"
41 #include "support/debug.h"
42 #include "support/textutils.h"
45 using namespace lyx::support;
51 InsetCounter::InsetCounter(Buffer * buf, InsetCommandParams const & p)
52 : InsetCommand(buf, p)
56 InsetCounter::InsetCounter(InsetCounter const & ir)
61 const map<string, string> InsetCounter::counterTable =
64 {"addto", N_("Add To")},
65 {"reset", N_("Reset")},
67 {"restore", N_("Restore")},
68 {"value", N_("Value")}
72 bool InsetCounter::isCompatibleCommand(string const & s) {
73 return counterTable.count(s);
77 ParamInfo const & InsetCounter::findInfo(string const & /* cmdName */)
79 static ParamInfo param_info_;
80 if (param_info_.empty()) {
81 param_info_.add("counter", ParamInfo::LYX_INTERNAL);
82 param_info_.add("value", ParamInfo::LYX_INTERNAL);
83 param_info_.add("vtype", ParamInfo::LYX_INTERNAL);
84 param_info_.add("lyxonly", ParamInfo::LYX_INTERNAL);
90 void InsetCounter::latex(otexstream & os, OutputParams const &) const
92 bool const lyxonly = lowercase(getParam("lyxonly")) == "true";
96 string const cmd = getCmdName();
97 docstring cntr = getParam("counter");
98 Counters & cnts = buffer().params().documentClass().counters();
100 docstring const & val = getParam("value");
101 os << "\\setcounter{" << cntr << "}{" << val << "}";
102 } else if (cmd == "addto") {
103 docstring const & val = getParam("value");
104 os << "\\addtocounter{" << cntr << "}{" << val << "}";
105 } else if (cmd == "reset") {
106 os << "\\setcounter{" << cntr << "}{0}";
107 } else if (cmd == "save") {
108 cnts.saveValue(cntr);
109 os << "\\setcounter{" << lyxSaveCounter()
110 << "}{\\value{" << cntr << "}}";
111 } else if (cmd == "restore") {
112 cnts.restoreValue(cntr);
113 os << "\\setcounter{" << cntr
114 << "{\\value{" << lyxSaveCounter() << "}}";
115 } else if (cmd == "value") {
116 os << "\\the" << cntr << "{}";
121 void InsetCounter::toString(odocstream & os) const
123 os << "[Counter " << from_utf8(getCmdName()) << ": "
124 << getParam("counter") << "]";
128 int InsetCounter::plaintext(odocstringstream & os,
129 OutputParams const &, size_t) const
136 void InsetCounter::trackCounters(string const & cmd) const
138 Counters & cnts = buffer().params().documentClass().counters();
139 docstring cntr = getParam("counter");
141 docstring const & val = getParam("value");
142 cnts.set(cntr, convert<int>(val));
143 } else if (cmd == "addto") {
144 docstring const & val = getParam("value");
145 cnts.addto(cntr, convert<int>(val));
146 } else if (cmd == "reset") {
148 } else if (cmd == "save") {
149 cnts.saveValue(cntr);
150 } else if (cmd == "restore") {
151 cnts.restoreValue(cntr);
156 const map<string, string> InsetCounter::valueTable =
158 {"Roman", N_("Roman Uppercase")},
159 {"roman", N_("Roman Lowercase")},
160 {"Alpha", N_("Uppercase Letter")},
161 {"alpha", N_("Lowercase Letter")},
162 {"arabic", N_("Arabic Numeral")}
166 docstring InsetCounter::value() const {
167 docstring const & cnt = getParam("counter");
168 string const & vtype = getCmdName();
169 int const val = buffer().params().documentClass().counters().value(cnt);
170 if (vtype == "Roman")
171 return romanCounter(val);
172 if (vtype == "roman")
173 return lowerromanCounter(val);
174 if (vtype == "Alpha")
175 return docstring(1, alphaCounter(val));
176 if (vtype == "alpha")
177 return docstring(1, loweralphaCounter(val));
178 if (vtype == "arabic")
179 return convert<docstring>(val);
181 return empty_docstring();
185 int InsetCounter::docbook(odocstream & os, OutputParams const &) const
187 // Here, we need to track counter values ourselves,
188 // since unlike in the LaTeX case, there is no external
189 // mechanism for doing that.
190 string const cmd = getCmdName();
191 if (cmd == "value") {
192 docstring cntr = getParam("counter");
193 Counters & cnts = buffer().params().documentClass().counters();
194 if (cnts.hasCounter(cntr))
195 os << cnts.value(cntr);
203 docstring InsetCounter::xhtml(XHTMLStream & xs, OutputParams const &) const
205 // Here, we need to track counter values ourselves,
206 // since unlike in the LaTeX case, there is no external
207 // mechanism for doing that.
208 string const cmd = getCmdName();
209 if (cmd == "value") {
210 docstring cntr = getParam("counter");
211 Counters & cnts = buffer().params().documentClass().counters();
212 if (cnts.hasCounter(cntr))
213 xs << cnts.value(cntr);
221 void InsetCounter::updateBuffer(ParIterator const &, UpdateType, bool const)
223 string const cmd = getCmdName();
224 docstring cntr = getParam("counter");
225 Counters & cnts = buffer().params().documentClass().counters();
226 map<string, string>::const_iterator cit = counterTable.find(cmd);
227 LASSERT(cit != counterTable.end(), return);
228 string const label = cit->second;
229 docstring const tlabel = translateIfPossible(from_ascii(label));
232 docstring const & val = getParam("value");
233 cnts.set(cntr, convert<int>(val));
234 screen_label_ = bformat(_("Counter: Set %1$s"), cntr);
235 tooltip_ = bformat(_("Set value of counter %1$s to %2$s"), cntr, val);
236 } else if (cmd == "addto") {
237 docstring const & val = getParam("value");
238 cnts.addto(cntr, convert<int>(val));
239 screen_label_ = bformat(_("Counter: Add to %1$s"), cntr);
240 tooltip_ = bformat(_("Add to value of counter %1$s"), cntr);
241 } else if (cmd == "reset") {
243 screen_label_ = bformat(_("Counter: Reset %1$s"), cntr);
244 tooltip_ = bformat(_("Reset value of counter %1$s"), cntr);
245 } else if (cmd == "save") {
246 cnts.saveValue(cntr);
247 screen_label_ = bformat(_("Counter: Save %1$s"), cntr);
248 tooltip_ = bformat(_("Save value of counter %1$s"), cntr);
249 } else if (cmd == "restore") {
250 cnts.restoreValue(cntr);
251 screen_label_ = bformat(_("Counter: Restore %1$s"), cntr);
252 tooltip_ = bformat(_("Restore value of counter %1$s"), cntr);
253 } else if (cmd == "value") {
254 screen_label_ = bformat(_("Counter: Value %1$s"), cntr);
255 tooltip_ = bformat(_("Print value of counter %1$s"), cntr);
261 docstring InsetCounter::lyxSaveCounter() const
263 docstring cntr = getParam("counter");
264 return from_ascii("LyXSave") + cntr;
268 void InsetCounter::validate(LaTeXFeatures & features) const
270 // create save counter if needed
271 string const cmd = getCmdName();
272 docstring const lyxonly = getParam("lyxonly");
273 if ((cmd == "save" || cmd == "restore") && lyxonly != "true") {
274 features.addPreambleSnippet(from_ascii("\\newcounter{") + lyxSaveCounter() + "}");
276 InsetCommand::validate(features);
280 string InsetCounter::contextMenuName() const
282 return "context-counter";