]> git.lyx.org Git - lyx.git/blob - src/counters.C
5b0de5941712e2beb852940d7f38bd8cf84da4e2
[lyx.git] / src / counters.C
1 /* This file is part of
2  * ======================================================
3  *
4  *           LyX, The Document Processor
5  *
6  *           Copyright 1995 Matthias Ettrich
7  *           Copyright 1995-2001 The LyX Team.
8  *
9  *
10  * ====================================================== */
11
12 #ifdef __GNUG__
13 #pragma implementation
14 #endif
15
16 #include <config.h>
17
18 #include "counters.h"
19 #include "debug.h"
20 #include "support/lstrings.h"
21 #include "support/LAssert.h"
22
23 using std::endl;
24 using std::vector;
25
26
27 Counter::Counter()
28 {
29         reset();
30 }
31
32
33 void Counter::set(int v)
34 {
35         value_ = v;
36 }
37
38
39 void Counter::addto(int v)
40 {
41         value_ += v;
42 }
43
44
45 int Counter::value() const
46 {
47         return value_;
48 }
49
50
51 void Counter::step()
52 {
53         ++value_;
54 }
55
56
57 void Counter::reset()
58 {
59         value_ = 0;
60 }
61
62 string Counter::master() const
63 {
64         return master_;
65 }
66
67 void Counter::setMaster(string const & m)
68 {
69         master_ = m;
70 }
71
72
73 Counters::Counters()
74 {
75         // Ehh, should this take a textclass arg?
76
77         // Sectioning counters:
78         newCounter("part");
79         newCounter("chapter");
80         newCounter("section", "chapter");
81         newCounter("subsection", "section");
82         newCounter("subsubsection", "subsection");
83         newCounter("paragraph", "subsubsection");
84         newCounter("subparagraph", "paragraph");
85
86         // Enumeration counters:
87         newCounter("enumi");
88         newCounter("enumii", "enumi");
89         newCounter("enumiii", "enumii");
90         newCounter("enumiv", "enumiii");
91
92         // Biblio:
93         newCounter("bibitem");
94
95         // Float counters:
96         newCounter("figure");
97         newCounter("table");
98 }
99
100
101 void Counters::newCounter(string const & newc)
102 {
103         // First check if newc already exist
104         CounterList::iterator cit = counterList.find(newc);
105         // if already exist give warning and return
106         if (cit != counterList.end()) {
107                 lyxerr << "The new counter already exists." << endl;
108                 return;
109         }
110         counterList[newc];
111         cit = counterList.find(newc);
112         cit->second.setMaster("");
113 }
114
115
116 void Counters::newCounter(string const & newc, string const & masterc)
117 {
118         // First check if newc already exists
119         CounterList::iterator cit = counterList.find(newc);
120         // if already existant give warning and return
121         if (cit != counterList.end()) {
122                 lyxerr << "The new counter already exists." << endl;
123                 return;
124         }
125         // then check if masterc exists
126         CounterList::iterator it = counterList.find(masterc);
127         // if not give warning and return
128         if (it == counterList.end()) {
129                 lyxerr << "The master counter does not exist." << endl;
130                 return;
131         }
132
133         counterList[newc];
134         cit = counterList.find(newc);
135         cit->second.setMaster(masterc);
136 }
137
138
139 void Counters::set(string const & ctr, int val)
140 {
141         CounterList::iterator it = counterList.find(ctr);
142         if (it == counterList.end()) {
143                 lyxerr << "set: Counter does not exist: " << ctr << endl;
144                 return;
145         }
146         it->second.set(val);
147 }
148
149
150 void Counters::addto(string const & ctr, int val)
151 {
152         CounterList::iterator it = counterList.find(ctr);
153         if (it == counterList.end()) {
154                 lyxerr << "addto: Counter does not exist: " << ctr << endl;
155                 return;
156         }
157         it->second.addto(val);
158 }
159
160
161 int Counters::value(string const & ctr) const
162 {
163         CounterList::const_iterator cit = counterList.find(ctr);
164         if (cit == counterList.end()) {
165                 lyxerr << "value: Counter does not exist: " << ctr << endl;
166                 return 0;
167         }
168         return cit->second.value();
169 }
170
171
172 void Counters::step(string const & ctr)
173 {
174         CounterList::iterator it = counterList.find(ctr);
175         if (it == counterList.end()) {
176                 lyxerr << "step: Counter does not exist: " << ctr << endl;
177                 return;
178         }
179
180         it->second.step();
181         it = counterList.begin();
182         CounterList::iterator end = counterList.end();
183         for (; it != end; ++it) {
184                 if (it->second.master() == ctr) {
185                         it->second.reset();
186                 }
187         }
188 }
189
190
191 void Counters::reset()
192 {
193         CounterList::iterator it = counterList.begin();
194         CounterList::iterator end = counterList.end();
195         for (; it != end; ++it) {
196                 it->second.reset();
197         }
198 }
199
200
201 void Counters::reset(string const & match)
202 {
203         lyx::Assert(!match.empty());
204
205         CounterList::iterator it = counterList.begin();
206         CounterList::iterator end = counterList.end();
207         for (; it != end; ++it) {
208                 if (it->first.find(match) != string::npos)
209                         it->second.reset();
210         }
211 }
212
213
214 void Counters::copy(Counters & from, Counters & to, string const & match)
215 {
216         CounterList::iterator it = counterList.begin();
217         CounterList::iterator end = counterList.end();
218         for (; it != end; ++it) {
219                 if (it->first.find(match) != string::npos || match == "") {
220                         to.set(it->first, from.value(it->first));
221                 }
222         }
223 }
224
225
226 namespace {
227
228 inline
229 char loweralphaCounter(int n)
230 {
231         if (n < 1 || n > 26)
232                 return '?';
233         else
234                 return 'a' + n - 1;
235 }
236
237
238 inline
239 char alphaCounter(int n)
240 {
241         if (n < 1 || n > 26)
242                 return '?';
243         else
244                 return 'A' + n - 1;
245 }
246
247
248 inline
249 char hebrewCounter(int n)
250 {
251         static const char hebrew[22] = {
252                 'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è',
253                 'é', 'ë', 'ì', 'î', 'ð', 'ñ', 'ò', 'ô', 'ö',
254                 '÷', 'ø', 'ù', 'ú'
255         };
256         if (n < 1 || n > 22)
257                 return '?';
258         else
259                 return hebrew[n-1];
260 }
261
262
263 inline
264 string const romanCounter(int n)
265 {
266         static char const * roman[20] = {
267                 "i",   "ii",  "iii", "iv", "v",
268                 "vi",  "vii", "viii", "ix", "x",
269                 "xi",  "xii", "xiii", "xiv", "xv",
270                 "xvi", "xvii", "xviii", "xix", "xx"
271         };
272         if (n < 1 || n > 20)
273                 return "??";
274         else
275                 return roman[n-1];
276 }
277
278 } // namespace anon
279
280
281 string Counters::labelItem(string const & ctr,
282                            string const & numbertype,
283                            string const & langtype,
284                            bool first)
285 {
286         ostringstream s;
287         ostringstream o;
288
289         CounterList::iterator it = counterList.find(ctr);
290         if (it == counterList.end()) {
291                 lyxerr << "Counter does not exist." << endl;
292                 return "";
293         }
294
295         if (!first) {
296                 s << "." << value(ctr);
297         } else {
298                 if (numbertype == "sectioning" || numbertype == "appendix") {
299                         if (numbertype == "appendix") {
300                                 if (langtype == "hebrew") {
301                                         o << hebrewCounter(value(ctr));
302                                 } else {
303                                         o << alphaCounter(value(ctr));
304                                 }
305                         } else o << value(ctr);
306                 }
307                 s << o.str();
308         }
309         return s.str();
310 }
311
312
313 string Counters::numberLabel(string const & ctr,
314                              string const & numbertype,
315                              string const & langtype,
316                              int head)
317 {
318         ostringstream s, o;
319         if (numbertype == "sectioning" || numbertype == "appendix") {
320                 if (ctr == "chapter" && head == 0) {
321                         s << labelItem("chapter", numbertype, langtype, true);
322                 } else if (ctr == "section" && head <= 1) {
323                         s << numberLabel("chapter", numbertype, langtype, head)
324                           << labelItem("section", numbertype, langtype, head == 1);
325                 } else if (ctr == "subsection" && head <= 2) {
326                         s << numberLabel("section", numbertype, langtype, head)
327                           << labelItem("subsection", numbertype, langtype, head == 2);
328                 } else if (ctr == "subsubsection" && head <= 3) {
329                         s << numberLabel("subsection", numbertype, langtype, head)
330                           << labelItem("subsubsection", numbertype, langtype, head == 3);
331                 } else if (ctr == "paragraph" && head <= 4) {
332                         s << numberLabel("subsubsection", numbertype, langtype, head)
333                           << labelItem("paragraph", numbertype, langtype, head == 4);
334                 } else if (ctr == "subparagraph" && head <= 5) {
335                         s << numberLabel("paragraph", numbertype, langtype, head)
336                           << labelItem("subparagraph", numbertype, langtype, head == 5);
337                 } else if (ctr == "figure" || ctr == "table") {
338                         // figure, table, ...
339                         lyxerr << "Counter:" << ctr << endl;
340                         s << numberLabel("chapter", numbertype, langtype, head)
341                           << labelItem(ctr, numbertype, langtype, head == 1);
342                 }
343
344         } else if (numbertype == "enumeration") {
345                 ostringstream ei, eii, eiii, eiv;
346                 //string ei, eiii, eiv;
347                 //char eii;
348                 if (langtype == "hebrew") {
349                         ei << '.' << value("enumi");
350                         eii << '(' << hebrewCounter(value("enumii")) << ')';
351                         eiii << '.' << romanCounter(value("enumiii"));
352                         eiv << '.' << alphaCounter(value("enumiv"));
353                 } else {
354                         ei << value("enumi") << '.';
355                         eii << '(' << loweralphaCounter(value("enumii")) << ')';
356                         eiii << romanCounter(value("enumiii")) << '.';
357                         eiv << alphaCounter(value("enumiv")) << '.';
358                 }
359                 if (ctr == "enumii") {
360                         s << eii.str();
361                 } else if (ctr == "enumi") {
362                         s << ei.str();
363                 } else if (ctr == "enumiii") {
364                         s << eiii.str();
365                 } else if (ctr == "enumiv") {
366                         s << eiv.str();
367                 }
368         }
369         return s.str();
370 }