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