]> git.lyx.org Git - lyx.git/blob - src/insets/InsetCounter.cpp
New counter manipulation inset.
[lyx.git] / src / insets / InsetCounter.cpp
1 /**
2  * \file InsetCounter.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Richard Kimberly Heck
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10 #include <config.h>
11
12 #include "InsetCounter.h"
13
14 #include "Buffer.h"
15 #include "BufferParams.h"
16 #include "Counters.h"
17 #include "LaTeXFeatures.h"
18 #include "OutputParams.h"
19 #include "output_xhtml.h"
20 #include "sgml.h"
21 #include "texstream.h"
22 #include "TextClass.h"
23
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"
30
31 #include <map>
32
33 /*
34 #include "Cursor.h"
35 #include "DispatchResult.h"
36 #include "Language.h"
37 #include "LyX.h"
38 #include "ParIterator.h"
39 #include "TocBackend.h"
40
41 #include "support/debug.h"
42 #include "support/textutils.h"
43 */
44
45 using namespace lyx::support;
46 using namespace std;
47
48 namespace lyx {
49
50
51 InsetCounter::InsetCounter(Buffer * buf, InsetCommandParams const & p)
52         : InsetCommand(buf, p)
53 {}
54
55
56 InsetCounter::InsetCounter(InsetCounter const & ir)
57         : InsetCommand(ir)
58 {}
59
60
61 const map<string, string> InsetCounter::counterTable =
62 {
63         {"set", N_("Set")},
64         {"addto", N_("Add To")},
65         {"reset", N_("Reset")},
66         {"save", N_("Save")},
67         {"restore", N_("Restore")},
68         {"value", N_("Value")}
69 };
70
71
72 bool InsetCounter::isCompatibleCommand(string const & s) {
73         return counterTable.count(s);
74 }
75
76
77 ParamInfo const & InsetCounter::findInfo(string const & /* cmdName */)
78 {
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);
85         }
86         return param_info_;
87 }
88
89
90 void InsetCounter::latex(otexstream & os, OutputParams const &) const
91 {
92         bool const lyxonly = lowercase(getParam("lyxonly")) == "true";
93         if (lyxonly)
94                 return;
95
96         string const cmd = getCmdName();
97         docstring cntr = getParam("counter");
98         Counters & cnts = buffer().params().documentClass().counters();
99         if (cmd == "set") {
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 << "\\value{" << cntr << "}";
117         }
118 }
119
120
121 void InsetCounter::toString(odocstream & os) const
122 {
123         os << "[Counter " << from_utf8(getCmdName()) << ": " 
124            <<  getParam("counter") << "]";
125 }
126
127
128 int InsetCounter::plaintext(odocstringstream & os,
129         OutputParams const &, size_t) const
130 {
131         toString(os);
132         return 0;
133 }
134
135
136 void InsetCounter::trackCounters(string const & cmd) const
137 {
138         Counters & cnts = buffer().params().documentClass().counters();
139         docstring cntr = getParam("counter");
140         if (cmd == "set") {
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") {
147                 cnts.reset(cntr);               
148         } else if (cmd == "save") {
149                 cnts.saveValue(cntr);
150         } else if (cmd == "restore") {
151                 cnts.restoreValue(cntr);
152         }
153 }
154
155
156 const map<string, string> InsetCounter::valueTable =
157 {
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")}
163 };
164
165
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);
180         LATTEST(false);
181         return empty_docstring();
182 }
183
184
185 int InsetCounter::docbook(odocstream & os, OutputParams const &) const
186 {
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);
196         } else
197                 trackCounters(cmd);
198
199         return 0;
200 }
201
202
203 docstring InsetCounter::xhtml(XHTMLStream & xs, OutputParams const &) const
204 {
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);
214         } else
215                 trackCounters(cmd);
216
217         return docstring();
218 }
219
220
221 void InsetCounter::updateBuffer(ParIterator const &, UpdateType, bool const)
222 {
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));
230
231         if (cmd == "set") {
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") {
242                 cnts.reset(cntr);               
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);
256         }
257         
258 }
259
260
261 docstring InsetCounter::lyxSaveCounter() const
262 {
263         docstring cntr = getParam("counter");
264         return from_ascii("LyXSave") + cntr;
265 }
266
267
268 void InsetCounter::validate(LaTeXFeatures & features) const
269 {
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() + "}");
275         }
276     InsetCommand::validate(features);
277 }
278
279
280 string InsetCounter::contextMenuName() const 
281
282         return "context-counter"; 
283 }
284 } // namespace lyx