]> git.lyx.org Git - lyx.git/blob - src/counters.C
8415c45081c5aa0483227dbbd1e282cc593168ad
[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         newCounter("algorithm");
99 }
100
101
102 void Counters::newCounter(string const & newc)
103 {
104         // First check if newc already exist
105         CounterList::iterator cit = counterList.find(newc);
106         // if already exist give warning and return
107         if (cit != counterList.end()) {
108                 lyxerr << "The new counter already exists." << endl;
109                 return;
110         }
111         counterList[newc];
112         cit = counterList.find(newc);
113         cit->second.setMaster("");
114 }
115
116
117 void Counters::newCounter(string const & newc, string const & masterc)
118 {
119         // First check if newc already exists
120         CounterList::iterator cit = counterList.find(newc);
121         // if already existant give warning and return
122         if (cit != counterList.end()) {
123                 lyxerr << "The new counter already exists." << endl;
124                 return;
125         }
126         // then check if masterc exists
127         CounterList::iterator it = counterList.find(masterc);
128         // if not give warning and return
129         if (it == counterList.end()) {
130                 lyxerr << "The master counter does not exist." << endl;
131                 return;
132         }
133
134         counterList[newc];
135         cit = counterList.find(newc);
136         cit->second.setMaster(masterc);
137 }
138
139
140 void Counters::set(string const & ctr, int val)
141 {
142         CounterList::iterator it = counterList.find(ctr);
143         if (it == counterList.end()) {
144                 lyxerr << "set: Counter does not exist: " << ctr << endl;
145                 return;
146         }
147         it->second.set(val);
148 }
149
150
151 void Counters::addto(string const & ctr, int val)
152 {
153         CounterList::iterator it = counterList.find(ctr);
154         if (it == counterList.end()) {
155                 lyxerr << "addto: Counter does not exist: " << ctr << endl;
156                 return;
157         }
158         it->second.addto(val);
159 }
160
161
162 int Counters::value(string const & ctr) const
163 {
164         CounterList::const_iterator cit = counterList.find(ctr);
165         if (cit == counterList.end()) {
166                 lyxerr << "value: Counter does not exist: " << ctr << endl;
167                 return 0;
168         }
169         return cit->second.value();
170 }
171
172
173 void Counters::step(string const & ctr)
174 {
175         CounterList::iterator it = counterList.find(ctr);
176         if (it == counterList.end()) {
177                 lyxerr << "step: Counter does not exist: " << ctr << endl;
178                 return;
179         }
180
181         it->second.step();
182         it = counterList.begin();
183         CounterList::iterator end = counterList.end();
184         for (; it != end; ++it) {
185                 if (it->second.master() == ctr) {
186                         it->second.reset();
187                 }
188         }
189 }
190
191
192 void Counters::reset()
193 {
194         CounterList::iterator it = counterList.begin();
195         CounterList::iterator end = counterList.end();
196         for (; it != end; ++it) {
197                 it->second.reset();
198         }
199 }
200
201
202 void Counters::reset(string const & match)
203 {
204         lyx::Assert(!match.empty());
205
206         CounterList::iterator it = counterList.begin();
207         CounterList::iterator end = counterList.end();
208         for (; it != end; ++it) {
209                 if (it->first.find(match) != string::npos)
210                         it->second.reset();
211         }
212 }
213
214
215 void Counters::copy(Counters & from, Counters & to, string const & match)
216 {
217         CounterList::iterator it = counterList.begin();
218         CounterList::iterator end = counterList.end();
219         for (; it != end; ++it) {
220                 if (it->first.find(match) != string::npos || match == "") {
221                         to.set(it->first, from.value(it->first));
222                 }
223         }
224 }
225
226
227 namespace {
228
229 inline
230 char loweralphaCounter(int n)
231 {
232         if (n < 1 || n > 26)
233                 return '?';
234         else
235                 return 'a' + n - 1;
236 }
237
238
239 inline
240 char alphaCounter(int n)
241 {
242         if (n < 1 || n > 26)
243                 return '?';
244         else
245                 return 'A' + n - 1;
246 }
247
248
249 inline
250 char hebrewCounter(int n)
251 {
252         static const char hebrew[22] = {
253                 'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è',
254                 'é', 'ë', 'ì', 'î', 'ð', 'ñ', 'ò', 'ô', 'ö',
255                 '÷', 'ø', 'ù', 'ú'
256         };
257         if (n < 1 || n > 22)
258                 return '?';
259         else
260                 return hebrew[n-1];
261 }
262
263
264 inline
265 string const romanCounter(int n)
266 {
267         static char const * roman[20] = {
268                 "i",   "ii",  "iii", "iv", "v",
269                 "vi",  "vii", "viii", "ix", "x",
270                 "xi",  "xii", "xiii", "xiv", "xv",
271                 "xvi", "xvii", "xviii", "xix", "xx"
272         };
273         if (n < 1 || n > 20)
274                 return "??";
275         else
276                 return roman[n-1];
277 }
278
279 } // namespace anon
280
281
282 string Counters::labelItem(string const & ctr,
283                            string const & numbertype,
284                            string const & langtype,
285                            bool first)
286 {
287         ostringstream s;
288         ostringstream o;
289
290         CounterList::iterator it = counterList.find(ctr);
291         if (it == counterList.end()) {
292                 lyxerr << "Counter does not exist." << endl;
293                 return "";
294         }
295
296         if (!first) {
297                 s << "." << value(ctr);
298         } else {
299                 if (numbertype == "sectioning" || numbertype == "appendix") {
300                         if (numbertype == "appendix") {
301                                 if (langtype == "hebrew") {
302                                         o << hebrewCounter(value(ctr));
303                                 } else {
304                                         o << alphaCounter(value(ctr));
305                                 }
306                         } else o << value(ctr);
307                 }
308                 s << o.str();
309         }
310         return s.str();
311 }
312
313
314 string Counters::numberLabel(string const & ctr,
315                              string const & numbertype,
316                              string const & langtype,
317                              int head)
318 {
319         ostringstream s, o;
320         if (numbertype == "sectioning" || numbertype == "appendix") {
321                 if (ctr == "chapter" && head == 0) {
322                         s << labelItem("chapter", numbertype, langtype, true);
323                 } else if (ctr == "section" && head <= 1) {
324                         s << numberLabel("chapter", numbertype, langtype, head)
325                           << labelItem("section", numbertype, langtype, head == 1);
326                 } else if (ctr == "subsection" && head <= 2) {
327                         s << numberLabel("section", numbertype, langtype, head)
328                           << labelItem("subsection", numbertype, langtype, head == 2);
329                 } else if (ctr == "subsubsection" && head <= 3) {
330                         s << numberLabel("subsection", numbertype, langtype, head)
331                           << labelItem("subsubsection", numbertype, langtype, head == 3);
332                 } else if (ctr == "paragraph" && head <= 4) {
333                         s << numberLabel("subsubsection", numbertype, langtype, head)
334                           << labelItem("paragraph", numbertype, langtype, head == 4);
335                 } else if (ctr == "subparagraph" && head <= 5) {
336                         s << numberLabel("paragraph", numbertype, langtype, head)
337                           << labelItem("subparagraph", numbertype, langtype, head == 5);
338                 } else if (ctr == "figure" || ctr == "table") {
339                         // figure, table, ...
340                         lyxerr << "Counter:" << ctr << endl;
341                         s << numberLabel("chapter", numbertype, langtype, head)
342                           << labelItem(ctr, numbertype, langtype, head == 1);
343                 }
344
345         } else if (numbertype == "enumeration") {
346                 ostringstream ei, eii, eiii, eiv;
347                 //string ei, eiii, eiv;
348                 //char eii;
349                 if (langtype == "hebrew") {
350                         ei << '.' << value("enumi");
351                         eii << '(' << hebrewCounter(value("enumii")) << ')';
352                         eiii << '.' << romanCounter(value("enumiii"));
353                         eiv << '.' << alphaCounter(value("enumiv"));
354                 } else {
355                         ei << value("enumi") << '.';
356                         eii << '(' << loweralphaCounter(value("enumii")) << ')';
357                         eiii << romanCounter(value("enumiii")) << '.';
358                         eiv << alphaCounter(value("enumiv")) << '.';
359                 }
360                 if (ctr == "enumii") {
361                         s << eii.str();
362                 } else if (ctr == "enumi") {
363                         s << ei.str();
364                 } else if (ctr == "enumiii") {
365                         s << eiii.str();
366                 } else if (ctr == "enumiv") {
367                         s << eiv.str();
368                 }
369         }
370         return s.str();
371 }