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 "output_xhtml.h"
20 #include "texstream.h"
21 #include "TextClass.h"
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"
34 #include "DispatchResult.h"
37 #include "ParIterator.h"
38 #include "TocBackend.h"
40 #include "support/debug.h"
41 #include "support/textutils.h"
44 using namespace lyx::support;
50 InsetCounter::InsetCounter(Buffer * buf, InsetCommandParams const & p)
51 : InsetCommand(buf, p)
55 InsetCounter::InsetCounter(InsetCounter const & ir)
60 const vector<pair<string, string>> InsetCounter::counterTable =
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")},
70 bool InsetCounter::isCompatibleCommand(string const & s)
72 for (auto & i : counterTable) {
80 ParamInfo const & InsetCounter::findInfo(string const & /* cmdName */)
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);
92 void InsetCounter::latex(otexstream & os, OutputParams const &) const
94 bool const lyxonly = lowercase(getParam("lyxonly")) == "true";
98 string const cmd = getCmdName();
99 docstring cntr = getParam("counter");
100 Counters & cnts = buffer().params().documentClass().counters();
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() << "}}";
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
137 // save this code until we get it working in InsetInfo
138 const map<string, string> InsetCounter::valueTable =
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")}
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);
163 return empty_docstring();
167 void InsetCounter::trackCounters(string const & cmd) const
169 Counters & cnts = buffer().params().documentClass().counters();
170 docstring cntr = getParam("counter");
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") {
179 } else if (cmd == "save") {
180 cnts.saveValue(cntr);
181 } else if (cmd == "restore") {
182 cnts.restoreValue(cntr);
186 void InsetCounter::docbook(XMLStream &, OutputParams const &) const
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());
195 docstring InsetCounter::xhtml(XMLStream &, OutputParams const &) const
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());
205 void InsetCounter::updateBuffer(ParIterator const &, UpdateType, bool const)
207 string const cmd = getCmdName();
208 docstring cntr = getParam("counter");
209 Counters & cnts = buffer().params().documentClass().counters();
211 for (auto & i : counterTable) {
215 LASSERT(!label.empty(), return);
216 docstring const tlabel = translateIfPossible(from_ascii(label));
218 docstring guiname = translateIfPossible(cnts.guiName(cntr));
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") {
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);
245 docstring InsetCounter::lyxSaveCounter() const
247 docstring cntr = getParam("counter");
248 return from_ascii("LyXSave") + cntr;
252 void InsetCounter::validate(LaTeXFeatures & features) const
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() + "}");
260 InsetCommand::validate(features);
264 string InsetCounter::contextMenuName() const
266 return "context-counter";