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