]> git.lyx.org Git - lyx.git/blob - src/counters.C
b794679ffe6f1b5cd91cceffccb12c714a3bcab2
[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/std_sstream.h"
20 #include "support/tostr.h"
21
22 #include <boost/assert.hpp>
23
24 using std::endl;
25 using std::ostringstream;
26
27
28 Counter::Counter()
29 {
30         reset();
31 }
32
33
34 void Counter::set(int v)
35 {
36         value_ = v;
37 }
38
39
40 void Counter::addto(int v)
41 {
42         value_ += v;
43 }
44
45
46 int Counter::value() const
47 {
48         return value_;
49 }
50
51
52 void Counter::step()
53 {
54         ++value_;
55 }
56
57
58 void Counter::reset()
59 {
60         value_ = 0;
61 }
62
63
64 string Counter::master() const
65 {
66         return master_;
67 }
68
69
70 void Counter::setMaster(string const & m)
71 {
72         master_ = m;
73 }
74
75
76 void Counters::newCounter(string const & newc)
77 {
78         // First check if newc already exist
79         CounterList::iterator cit = counterList.find(newc);
80         // if already exist give warning and return
81         if (cit != counterList.end()) {
82                 lyxerr << "The new counter already exists." << endl;
83                 return;
84         }
85         counterList[newc];
86 }
87
88
89 void Counters::newCounter(string const & newc, string const & masterc)
90 {
91         // First check if newc already exists
92         CounterList::iterator cit = counterList.find(newc);
93         // if already existant give warning and return
94         if (cit != counterList.end()) {
95                 lyxerr << "The new counter already exists." << endl;
96                 return;
97         }
98         // then check if masterc exists
99         CounterList::iterator it = counterList.find(masterc);
100         // if not give warning and return
101         if (it == counterList.end()) {
102                 lyxerr << "The master counter does not exist." << endl;
103                 return;
104         }
105
106         counterList[newc].setMaster(masterc);
107 }
108
109
110 void Counters::set(string const & ctr, int val)
111 {
112         CounterList::iterator it = counterList.find(ctr);
113         if (it == counterList.end()) {
114                 lyxerr << "set: Counter does not exist: " << ctr << endl;
115                 return;
116         }
117         it->second.set(val);
118 }
119
120
121 void Counters::addto(string const & ctr, int val)
122 {
123         CounterList::iterator it = counterList.find(ctr);
124         if (it == counterList.end()) {
125                 lyxerr << "addto: Counter does not exist: " << ctr << endl;
126                 return;
127         }
128         it->second.addto(val);
129 }
130
131
132 int Counters::value(string const & ctr) const
133 {
134         CounterList::const_iterator cit = counterList.find(ctr);
135         if (cit == counterList.end()) {
136                 lyxerr << "value: Counter does not exist: " << ctr << endl;
137                 return 0;
138         }
139         return cit->second.value();
140 }
141
142
143 void Counters::step(string const & ctr)
144 {
145         CounterList::iterator it = counterList.find(ctr);
146         if (it == counterList.end()) {
147                 lyxerr << "step: Counter does not exist: " << ctr << endl;
148                 return;
149         }
150
151         it->second.step();
152         it = counterList.begin();
153         CounterList::iterator end = counterList.end();
154         for (; it != end; ++it) {
155                 if (it->second.master() == ctr) {
156                         it->second.reset();
157                 }
158         }
159 }
160
161
162 void Counters::reset()
163 {
164         CounterList::iterator it = counterList.begin();
165         CounterList::iterator end = counterList.end();
166         for (; it != end; ++it) {
167                 it->second.reset();
168         }
169 }
170
171
172 void Counters::reset(string const & match)
173 {
174         BOOST_ASSERT(!match.empty());
175
176         CounterList::iterator it = counterList.begin();
177         CounterList::iterator end = counterList.end();
178         for (; it != end; ++it) {
179                 if (it->first.find(match) != string::npos)
180                         it->second.reset();
181         }
182 }
183
184
185 void Counters::copy(Counters & from, Counters & to, string const & match)
186 {
187         CounterList::iterator it = counterList.begin();
188         CounterList::iterator end = counterList.end();
189         for (; it != end; ++it) {
190                 if (it->first.find(match) != string::npos || match == "") {
191                         to.set(it->first, from.value(it->first));
192                 }
193         }
194 }
195
196
197 namespace {
198
199 char loweralphaCounter(int n)
200 {
201         if (n < 1 || n > 26) 
202                 return '?';
203         return 'a' + n - 1;
204 }
205
206
207 char alphaCounter(int n)
208 {
209         if (n < 1 || n > 26)
210                 return '?';
211         return 'A' + n - 1;
212 }
213
214
215 char hebrewCounter(int n)
216 {
217         static const char hebrew[22] = {
218                 'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è',
219                 'é', 'ë', 'ì', 'î', 'ð', 'ñ', 'ò', 'ô', 'ö',
220                 '÷', 'ø', 'ù', 'ú'
221         };
222
223         if (n < 1 || n > 22)
224                 return '?';
225         return hebrew[n - 1];
226 }
227
228
229 string const lowerromanCounter(int n)
230 {
231         static char const * roman[20] = {
232                 "i",   "ii",  "iii", "iv", "v",
233                 "vi",  "vii", "viii", "ix", "x",
234                 "xi",  "xii", "xiii", "xiv", "xv",
235                 "xvi", "xvii", "xviii", "xix", "xx"
236         };
237
238         if (n < 1 || n > 20)
239                 return "??";
240         return roman[n - 1];
241 }
242
243
244 string const romanCounter(int n)
245 {
246         static char 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 "??";
255         return roman[n - 1];
256 }
257
258 } // namespace anon
259
260
261 string Counters::labelItem(string const & ctr, string const & numbertype)
262 {
263         if (counterList.find(ctr) == counterList.end()) {
264                 lyxerr << "Counter " << ctr << " does not exist." << endl;
265                 return string();
266         }
267
268         if (numbertype == "hebrew")
269                 return string(1, hebrewCounter(value(ctr)));
270
271         if (numbertype == "alph")
272                 return string(1, loweralphaCounter(value(ctr)));
273
274         if (numbertype == "Alph")
275                 return string(1, alphaCounter(value(ctr)));
276
277         if (numbertype == "roman")
278                 return lowerromanCounter(value(ctr));
279
280         if (numbertype == "Roman")
281                 return romanCounter(value(ctr));
282
283         return tostr(value(ctr));
284 }
285
286
287 string Counters::counterLabel(string const & format)
288 {
289         string label = format;
290         while (true) {
291                 size_t const i = label.find('\\', 0);
292                 if (i == string::npos)
293                         break;
294                 size_t const j = label.find('{', i + 1);
295                 if (j == string::npos)
296                         break;
297                 size_t const k = label.find('}', j + 1);
298                 if (k == string::npos)
299                         break;
300                 string const numbertype(label, i + 1, j - i - 1);
301                 string const counter(label, j + 1, k - j - 1);
302                 string const rep = labelItem(counter, numbertype);
303                 label = string(label, 0, i) + rep + string(label, k + 1, string::npos);
304                 //lyxerr << "  : " << " (" << counter  << ","
305                 //      << numbertype << ") -> " << label << endl;
306         }
307         //lyxerr << "counterLabel: " << format  << " -> "       << label << endl;
308         return label;
309 }
310
311
312 string Counters::enumLabel(string const & ctr, string const & langtype)
313 {
314         ostringstream os;
315
316         if (langtype == "hebrew") {
317                 if (ctr == "enumi")
318                         os << '.' << value("enumi");
319                 else if (ctr == "enumii")
320                         os << '(' << hebrewCounter(value("enumii")) << ')';
321                 else if (ctr == "enumiii")
322                         os << '.' << lowerromanCounter(value("enumiii"));
323                 else if (ctr == "enumiv")
324                         os << '.' << alphaCounter(value("enumiv"));
325         } else {
326                 if (ctr == "enumi")
327                         os << value("enumi") << '.';
328                 else if (ctr == "enumii")
329                         os << '(' << loweralphaCounter(value("enumii")) << ')';
330                 else if (ctr == "enumiii")
331                         os << lowerromanCounter(value("enumiii")) << '.';
332                 else if (ctr == "enumiv")
333                         os << alphaCounter(value("enumiv")) << '.';
334         }
335
336         return STRCONV(os.str());
337 }