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 vector<pair<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)
73 for (auto & i : counterTable) {
81 ParamInfo const & InsetCounter::findInfo(string const & /* cmdName */)
83 static ParamInfo param_info_;
84 if (param_info_.empty()) {
85 param_info_.add("counter", ParamInfo::LYX_INTERNAL);
86 param_info_.add("value", ParamInfo::LYX_INTERNAL);
87 param_info_.add("lyxonly", ParamInfo::LYX_INTERNAL);
93 void InsetCounter::latex(otexstream & os, OutputParams const &) const
95 bool const lyxonly = lowercase(getParam("lyxonly")) == "true";
99 string const cmd = getCmdName();
100 docstring cntr = getParam("counter");
101 Counters & cnts = buffer().params().documentClass().counters();
103 docstring const & val = getParam("value");
104 os << "\\setcounter{" << cntr << "}{" << val << "}";
105 } else if (cmd == "addto") {
106 docstring const & val = getParam("value");
107 os << "\\addtocounter{" << cntr << "}{" << val << "}";
108 } else if (cmd == "reset") {
109 os << "\\setcounter{" << cntr << "}{0}";
110 } else if (cmd == "save") {
111 cnts.saveValue(cntr);
112 os << "\\setcounter{" << lyxSaveCounter()
113 << "}{\\value{" << cntr << "}}";
114 } else if (cmd == "restore") {
115 cnts.restoreValue(cntr);
116 os << "\\setcounter{" << cntr
117 << "{\\value{" << lyxSaveCounter() << "}}";
122 void InsetCounter::toString(odocstream & os) const
124 os << "[Counter " << from_utf8(getCmdName()) << ": "
125 << getParam("counter") << "]";
129 int InsetCounter::plaintext(odocstringstream & os,
130 OutputParams const &, size_t) const
138 // save this code until we get it working in InsetInfo
139 const map<string, string> InsetCounter::valueTable =
141 {"Roman", N_("Roman Uppercase")},
142 {"roman", N_("Roman Lowercase")},
143 {"Alpha", N_("Uppercase Letter")},
144 {"alpha", N_("Lowercase Letter")},
145 {"arabic", N_("Arabic Numeral")}
149 docstring InsetCounter::value() const {
150 docstring const & cnt = getParam("counter");
151 string const & vtype = getCmdName();
152 int const val = buffer().params().documentClass().counters().value(cnt);
153 if (vtype == "Roman")
154 return romanCounter(val);
155 if (vtype == "roman")
156 return lowerromanCounter(val);
157 if (vtype == "Alpha")
158 return docstring(1, alphaCounter(val));
159 if (vtype == "alpha")
160 return docstring(1, loweralphaCounter(val));
161 if (vtype == "arabic")
162 return convert<docstring>(val);
164 return empty_docstring();
168 void InsetCounter::trackCounters(string const & cmd) const
170 Counters & cnts = buffer().params().documentClass().counters();
171 docstring cntr = getParam("counter");
173 docstring const & val = getParam("value");
174 cnts.set(cntr, convert<int>(val));
175 } else if (cmd == "addto") {
176 docstring const & val = getParam("value");
177 cnts.addto(cntr, convert<int>(val));
178 } else if (cmd == "reset") {
180 } else if (cmd == "save") {
181 cnts.saveValue(cntr);
182 } else if (cmd == "restore") {
183 cnts.restoreValue(cntr);
187 int InsetCounter::docbook(odocstream &, OutputParams const &) const
189 // Here, we need to track counter values ourselves,
190 // since unlike in the LaTeX case, there is no external
191 // mechanism for doing that.
192 trackCounters(getCmdName());
197 docstring InsetCounter::xhtml(XHTMLStream &, 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";