]> git.lyx.org Git - lyx.git/blob - src/counters.C
624d71cc33837354904ae625fa4a9d90a0cb3850
[lyx.git] / src / counters.C
1 /**
2  * \file counters.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Lars Gullik Bjønnes
7  * \author Martin Vermeer
8  * \author André Pönitz
9  *
10  * Full author contact details are available in file CREDITS.
11  */
12
13 #include <config.h>
14
15 #include "counters.h"
16 #include "debug.h"
17
18 #include "support/lstrings.h"
19 #include "support/convert.h"
20
21 #include <boost/assert.hpp>
22
23 #include <sstream>
24
25 using lyx::docstring;
26
27 using std::endl;
28 using std::ostringstream;
29 using std::string;
30
31
32 Counter::Counter()
33 {
34         reset();
35 }
36
37
38 void Counter::set(int v)
39 {
40         value_ = v;
41 }
42
43
44 void Counter::addto(int v)
45 {
46         value_ += v;
47 }
48
49
50 int Counter::value() const
51 {
52         return value_;
53 }
54
55
56 void Counter::step()
57 {
58         ++value_;
59 }
60
61
62 void Counter::reset()
63 {
64         value_ = 0;
65 }
66
67
68 docstring Counter::master() const
69 {
70         return master_;
71 }
72
73
74 void Counter::setMaster(docstring const & m)
75 {
76         master_ = m;
77 }
78
79
80 void Counters::newCounter(docstring const & newc)
81 {
82         // First check if newc already exist
83         CounterList::iterator const cit = counterList.find(newc);
84         // if already exist give warning and return
85         if (cit != counterList.end()) {
86                 lyxerr << "New counter already exists: "
87                        << lyx::to_utf8(newc)
88                        << endl;
89                 return;
90         }
91         counterList[newc];
92 }
93
94
95 void Counters::newCounter(docstring const & newc,
96                           docstring const & masterc)
97 {
98         // First check if newc already exists
99         CounterList::iterator const cit = counterList.find(newc);
100         // if already existant give warning and return
101         if (cit != counterList.end()) {
102                 lyxerr << "New counter already exists: "
103                        << lyx::to_utf8(newc)
104                        << endl;
105                 return;
106         }
107         // then check if masterc exists
108         CounterList::iterator const it = counterList.find(masterc);
109         // if not give warning and return
110         if (it == counterList.end()) {
111                 lyxerr << "Master counter does not exist: "
112                        << lyx::to_utf8(masterc)
113                        << endl;
114                 return;
115         }
116
117         counterList[newc].setMaster(masterc);
118 }
119
120
121 void Counters::set(docstring const & ctr, int const val)
122 {
123         CounterList::iterator const it = counterList.find(ctr);
124         if (it == counterList.end()) {
125                 lyxerr << "set: Counter does not exist: "
126                        << lyx::to_utf8(ctr) << endl;
127                 return;
128         }
129         it->second.set(val);
130 }
131
132
133 void Counters::addto(docstring const & ctr, int const val)
134 {
135         CounterList::iterator const it = counterList.find(ctr);
136         if (it == counterList.end()) {
137                 lyxerr << "addto: Counter does not exist: "
138                        << lyx::to_utf8(ctr) << endl;
139                 return;
140         }
141         it->second.addto(val);
142 }
143
144
145 int Counters::value(docstring const & ctr) const
146 {
147         CounterList::const_iterator const cit = counterList.find(ctr);
148         if (cit == counterList.end()) {
149                 lyxerr << "value: Counter does not exist: "
150                        << lyx::to_utf8(ctr) << endl;
151                 return 0;
152         }
153         return cit->second.value();
154 }
155
156
157 void Counters::step(docstring const & ctr)
158 {
159         CounterList::iterator it = counterList.find(ctr);
160         if (it == counterList.end()) {
161                 lyxerr << "step: Counter does not exist: "
162                        << lyx::to_utf8(ctr) << endl;
163                 return;
164         }
165
166         it->second.step();
167         it = counterList.begin();
168         CounterList::iterator const end = counterList.end();
169         for (; it != end; ++it) {
170                 if (it->second.master() == ctr) {
171                         it->second.reset();
172                 }
173         }
174 }
175
176
177 void Counters::reset()
178 {
179         CounterList::iterator it = counterList.begin();
180         CounterList::iterator const end = counterList.end();
181         for (; it != end; ++it) {
182                 it->second.reset();
183         }
184 }
185
186
187 void Counters::reset(docstring const & match)
188 {
189         BOOST_ASSERT(!match.empty());
190
191         CounterList::iterator it = counterList.begin();
192         CounterList::iterator end = counterList.end();
193         for (; it != end; ++it) {
194                 if (it->first.find(match) != string::npos)
195                         it->second.reset();
196         }
197 }
198
199
200 void Counters::copy(Counters & from, Counters & to, docstring const & match)
201 {
202         CounterList::iterator it = counterList.begin();
203         CounterList::iterator end = counterList.end();
204         for (; it != end; ++it) {
205                 if (it->first.find(match) != string::npos || match == "") {
206                         to.set(it->first, from.value(it->first));
207                 }
208         }
209 }
210
211
212 namespace {
213
214 char loweralphaCounter(int const n)
215 {
216         if (n < 1 || n > 26)
217                 return '?';
218         return 'a' + n - 1;
219 }
220
221
222 char alphaCounter(int const n)
223 {
224         if (n < 1 || n > 26)
225                 return '?';
226         return 'A' + n - 1;
227 }
228
229
230 char hebrewCounter(int const n)
231 {
232         static const char hebrew[22] = {
233                 'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è',
234                 'é', 'ë', 'ì', 'î', 'ð', 'ñ', 'ò', 'ô', 'ö',
235                 '÷', 'ø', 'ù', 'ú'
236         };
237
238         if (n < 1 || n > 22)
239                 return '?';
240         return hebrew[n - 1];
241 }
242
243
244 docstring const lowerromanCounter(int const n)
245 {
246         static char const * const roman[20] = {
247                 "i",   "ii",  "iii", "iv", "v",
248                 "vi",  "vii", "viii", "ix", "x",
249                 "xi",  "xii", "xiii", "xiv", "xv",
250                 "xvi", "xvii", "xviii", "xix", "xx"
251         };
252
253         if (n < 1 || n > 20)
254                 return lyx::from_ascii("??");
255         return lyx::from_ascii(roman[n - 1]);
256 }
257
258
259 docstring const romanCounter(int const n)
260 {
261         static char const * const roman[20] = {
262                 "I",   "II",  "III", "IV", "V",
263                 "VI",  "VII", "VIII", "IX", "X",
264                 "XI",  "XII", "XIII", "XIV", "XV",
265                 "XVI", "XVII", "XVIII", "XIX", "XX"
266         };
267
268         if (n < 1 || n > 20)
269                 return lyx::from_ascii("??");
270         return lyx::from_ascii(roman[n - 1]);
271 }
272
273 } // namespace anon
274
275
276 docstring Counters::labelItem(docstring const & ctr,
277                               docstring const & numbertype)
278 {
279         if (counterList.find(ctr) == counterList.end()) {
280                 lyxerr << "Counter "
281                        << lyx::to_utf8(ctr)
282                        << " does not exist." << endl;
283                 return docstring();
284         }
285
286         if (numbertype == "hebrew")
287                 return docstring(1, hebrewCounter(value(ctr)));
288
289         if (numbertype == "alph")
290                 return docstring(1, loweralphaCounter(value(ctr)));
291
292         if (numbertype == "Alph")
293                 return docstring(1, alphaCounter(value(ctr)));
294
295         if (numbertype == "roman")
296                 return lowerromanCounter(value(ctr));
297
298         if (numbertype == "Roman")
299                 return romanCounter(value(ctr));
300
301         return convert<docstring>(value(ctr));
302 }
303
304
305 docstring Counters::counterLabel(docstring const & format)
306 {
307         docstring label = format;
308         while (true) {
309 #ifdef WITH_WARNINGS
310 #warning Using boost::regex or boost::spirit would make this code a lot simpler... (Lgb)
311 #endif
312
313                 size_t const i = label.find('\\', 0);
314                 if (i == docstring::npos)
315                         break;
316                 size_t const j = label.find('{', i + 1);
317                 if (j == docstring::npos)
318                         break;
319                 size_t const k = label.find('}', j + 1);
320                 if (k == string::npos)
321                         break;
322                 docstring const numbertype(label, i + 1, j - i - 1);
323                 docstring const counter(label, j + 1, k - j - 1);
324                 docstring const rep = labelItem(counter, numbertype);
325                 label = docstring(label, 0, i) + rep + docstring(label, k + 1, string::npos);
326                 //lyxerr << "  : " << " (" << counter  << ","
327                 //      << numbertype << ") -> " << label << endl;
328         }
329         //lyxerr << "counterLabel: " << format  << " -> "       << label << endl;
330         return label;
331 }