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 const & cntr = getParam("counter");
100 Counters & cnts = buffer().params().documentClass().counters();
101 docstring const & latexname = cnts.latexName(cntr);
104 docstring const & val = getParam("value");
105 os << "\\setcounter{" << latexname << "}{" << val << "}";
106 } else if (cmd == "addto") {
107 docstring const & val = getParam("value");
108 os << "\\addtocounter{" << latexname << "}{" << val << "}";
109 } else if (cmd == "reset") {
110 os << "\\setcounter{" << latexname << "}{0}";
111 } else if (cmd == "save") {
112 cnts.saveValue(cntr);
113 os << "\\setcounter{" << lyxSaveCounter()
114 << "}{\\value{" << latexname << "}}";
115 } else if (cmd == "restore") {
116 cnts.restoreValue(cntr);
117 os << "\\setcounter{" << latexname
118 << "}{\\value{" << lyxSaveCounter() << "}}";
123 void InsetCounter::toString(odocstream & os) const
125 os << "[Counter " << from_utf8(getCmdName()) << ": "
126 << getParam("counter") << "]";
130 int InsetCounter::plaintext(odocstringstream & os,
131 OutputParams const &, size_t) const
139 // save this code until we get it working in InsetInfo
140 const map<string, string> InsetCounter::valueTable =
142 {"Roman", N_("Roman Uppercase")},
143 {"roman", N_("Roman Lowercase")},
144 {"Alpha", N_("Uppercase Letter")},
145 {"alpha", N_("Lowercase Letter")},
146 {"arabic", N_("Arabic Numeral")}
150 docstring InsetCounter::value() const {
151 docstring const & cnt = getParam("counter");
152 string const & vtype = getCmdName();
153 int const val = buffer().params().documentClass().counters().value(cnt);
154 if (vtype == "Roman")
155 return romanCounter(val);
156 if (vtype == "roman")
157 return lowerromanCounter(val);
158 if (vtype == "Alpha")
159 return docstring(1, alphaCounter(val));
160 if (vtype == "alpha")
161 return docstring(1, loweralphaCounter(val));
162 if (vtype == "arabic")
163 return convert<docstring>(val);
165 return empty_docstring();
169 void InsetCounter::trackCounters(string const & cmd) const
171 Counters & cnts = buffer().params().documentClass().counters();
172 docstring cntr = getParam("counter");
174 docstring const & val = getParam("value");
175 cnts.set(cntr, convert<int>(val));
176 } else if (cmd == "addto") {
177 docstring const & val = getParam("value");
178 cnts.addto(cntr, convert<int>(val));
179 } else if (cmd == "reset") {
181 } else if (cmd == "save") {
182 cnts.saveValue(cntr);
183 } else if (cmd == "restore") {
184 cnts.restoreValue(cntr);
188 void InsetCounter::docbook(XMLStream &, OutputParams const &) const
190 // Here, we need to track counter values ourselves,
191 // since unlike in the LaTeX case, there is no external
192 // mechanism for doing that.
193 trackCounters(getCmdName());
197 docstring InsetCounter::xhtml(XMLStream &, OutputParams const &) const
199 // Here, we need to track counter values ourselves,
200 // since unlike in the LaTeX case, there is no external
201 // mechanism for doing that.
202 trackCounters(getCmdName());
207 void InsetCounter::updateBuffer(ParIterator const &, UpdateType, bool const)
209 string const cmd = getCmdName();
210 docstring cntr = getParam("counter");
211 Counters & cnts = buffer().params().documentClass().counters();
213 for (auto & i : counterTable) {
217 LASSERT(!label.empty(), return);
218 docstring const tlabel = translateIfPossible(from_ascii(label));
220 docstring guiname = translateIfPossible(cnts.guiName(cntr));
222 docstring const & val = getParam("value");
223 cnts.set(cntr, convert<int>(val));
224 screen_label_ = bformat(_("Counter: Set %1$s"), guiname);
225 tooltip_ = bformat(_("Set value of counter %1$s to %2$s"), cntr, val);
226 } else if (cmd == "addto") {
227 docstring const & val = getParam("value");
228 cnts.addto(cntr, convert<int>(val));
229 screen_label_ = bformat(_("Counter: Add to %1$s"), guiname);
230 tooltip_ = bformat(_("Add %1$s to value of counter %2$s"), val, cntr);
231 } else if (cmd == "reset") {
233 screen_label_ = bformat(_("Counter: Reset %1$s"), guiname);
234 tooltip_ = bformat(_("Reset value of counter %1$s"), cntr);
235 } else if (cmd == "save") {
236 cnts.saveValue(cntr);
237 screen_label_ = bformat(_("Counter: Save %1$s"), guiname);
238 tooltip_ = bformat(_("Save value of counter %1$s"), cntr);
239 } else if (cmd == "restore") {
240 cnts.restoreValue(cntr);
241 screen_label_ = bformat(_("Counter: Restore %1$s"), guiname);
242 tooltip_ = bformat(_("Restore value of counter %1$s"), cntr);
247 docstring InsetCounter::lyxSaveCounter() const
249 docstring cntr = getParam("counter");
250 return from_ascii("LyXSave") + cntr;
254 void InsetCounter::validate(LaTeXFeatures & features) const
256 // create save counter if needed
257 string const cmd = getCmdName();
258 docstring const lyxonly = getParam("lyxonly");
259 if ((cmd == "save" || cmd == "restore") && lyxonly != "true") {
260 features.addPreambleSnippet(from_ascii("\\newcounter{") + lyxSaveCounter() + "}");
262 InsetCommand::validate(features);
266 string InsetCounter::contextMenuName() const
268 return "context-counter";