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 =
63 {"set", N_("Set counter to ...")},
64 {"addto", N_("Increase counter by ...")},
65 {"reset", N_("Reset counter to 0")},
66 {"save", N_("Save current counter value")},
67 {"restore", N_("Restore saved counter value")},
71 bool InsetCounter::isCompatibleCommand(string const & s) {
72 return counterTable.count(s);
76 ParamInfo const & InsetCounter::findInfo(string const & /* cmdName */)
78 static ParamInfo param_info_;
79 if (param_info_.empty()) {
80 param_info_.add("counter", ParamInfo::LYX_INTERNAL);
81 param_info_.add("value", ParamInfo::LYX_INTERNAL);
82 param_info_.add("lyxonly", ParamInfo::LYX_INTERNAL);
88 void InsetCounter::latex(otexstream & os, OutputParams const &) const
90 bool const lyxonly = lowercase(getParam("lyxonly")) == "true";
94 string const cmd = getCmdName();
95 docstring cntr = getParam("counter");
96 Counters & cnts = buffer().params().documentClass().counters();
98 docstring const & val = getParam("value");
99 os << "\\setcounter{" << cntr << "}{" << val << "}";
100 } else if (cmd == "addto") {
101 docstring const & val = getParam("value");
102 os << "\\addtocounter{" << cntr << "}{" << val << "}";
103 } else if (cmd == "reset") {
104 os << "\\setcounter{" << cntr << "}{0}";
105 } else if (cmd == "save") {
106 cnts.saveValue(cntr);
107 os << "\\setcounter{" << lyxSaveCounter()
108 << "}{\\value{" << cntr << "}}";
109 } else if (cmd == "restore") {
110 cnts.restoreValue(cntr);
111 os << "\\setcounter{" << cntr
112 << "{\\value{" << lyxSaveCounter() << "}}";
117 void InsetCounter::toString(odocstream & os) const
119 os << "[Counter " << from_utf8(getCmdName()) << ": "
120 << getParam("counter") << "]";
124 int InsetCounter::plaintext(odocstringstream & os,
125 OutputParams const &, size_t) const
133 // save this code until we get it working in InsetInfo
134 const map<string, string> InsetCounter::valueTable =
136 {"Roman", N_("Roman Uppercase")},
137 {"roman", N_("Roman Lowercase")},
138 {"Alpha", N_("Uppercase Letter")},
139 {"alpha", N_("Lowercase Letter")},
140 {"arabic", N_("Arabic Numeral")}
144 docstring InsetCounter::value() const {
145 docstring const & cnt = getParam("counter");
146 string const & vtype = getCmdName();
147 int const val = buffer().params().documentClass().counters().value(cnt);
148 if (vtype == "Roman")
149 return romanCounter(val);
150 if (vtype == "roman")
151 return lowerromanCounter(val);
152 if (vtype == "Alpha")
153 return docstring(1, alphaCounter(val));
154 if (vtype == "alpha")
155 return docstring(1, loweralphaCounter(val));
156 if (vtype == "arabic")
157 return convert<docstring>(val);
159 return empty_docstring();
163 void InsetCounter::trackCounters(string const & cmd) const
165 Counters & cnts = buffer().params().documentClass().counters();
166 docstring cntr = getParam("counter");
168 docstring const & val = getParam("value");
169 cnts.set(cntr, convert<int>(val));
170 } else if (cmd == "addto") {
171 docstring const & val = getParam("value");
172 cnts.addto(cntr, convert<int>(val));
173 } else if (cmd == "reset") {
175 } else if (cmd == "save") {
176 cnts.saveValue(cntr);
177 } else if (cmd == "restore") {
178 cnts.restoreValue(cntr);
182 int InsetCounter::docbook(odocstream &, OutputParams const &) const
184 // Here, we need to track counter values ourselves,
185 // since unlike in the LaTeX case, there is no external
186 // mechanism for doing that.
187 trackCounters(getCmdName());
192 docstring InsetCounter::xhtml(XHTMLStream &, OutputParams const &) const
194 // Here, we need to track counter values ourselves,
195 // since unlike in the LaTeX case, there is no external
196 // mechanism for doing that.
197 trackCounters(getCmdName());
202 void InsetCounter::updateBuffer(ParIterator const &, UpdateType, bool const)
204 string const cmd = getCmdName();
205 docstring cntr = getParam("counter");
206 Counters & cnts = buffer().params().documentClass().counters();
207 map<string, string>::const_iterator cit = counterTable.find(cmd);
208 LASSERT(cit != counterTable.end(), return);
209 string const label = cit->second;
210 docstring const tlabel = translateIfPossible(from_ascii(label));
213 docstring const & val = getParam("value");
214 cnts.set(cntr, convert<int>(val));
215 screen_label_ = bformat(_("Counter: Set %1$s"), cntr);
216 tooltip_ = bformat(_("Set value of counter %1$s to %2$s"), cntr, val);
217 } else if (cmd == "addto") {
218 docstring const & val = getParam("value");
219 cnts.addto(cntr, convert<int>(val));
220 screen_label_ = bformat(_("Counter: Add to %1$s"), cntr);
221 tooltip_ = bformat(_("Add %1$s to value of counter %2$s"), val, cntr);
222 } else if (cmd == "reset") {
224 screen_label_ = bformat(_("Counter: Reset %1$s"), cntr);
225 tooltip_ = bformat(_("Reset value of counter %1$s"), cntr);
226 } else if (cmd == "save") {
227 cnts.saveValue(cntr);
228 screen_label_ = bformat(_("Counter: Save %1$s"), cntr);
229 tooltip_ = bformat(_("Save value of counter %1$s"), cntr);
230 } else if (cmd == "restore") {
231 cnts.restoreValue(cntr);
232 screen_label_ = bformat(_("Counter: Restore %1$s"), cntr);
233 tooltip_ = bformat(_("Restore value of counter %1$s"), cntr);
238 docstring InsetCounter::lyxSaveCounter() const
240 docstring cntr = getParam("counter");
241 return from_ascii("LyXSave") + cntr;
245 void InsetCounter::validate(LaTeXFeatures & features) const
247 // create save counter if needed
248 string const cmd = getCmdName();
249 docstring const lyxonly = getParam("lyxonly");
250 if ((cmd == "save" || cmd == "restore") && lyxonly != "true") {
251 features.addPreambleSnippet(from_ascii("\\newcounter{") + lyxSaveCounter() + "}");
253 InsetCommand::validate(features);
257 string InsetCounter::contextMenuName() const
259 return "context-counter";