]> git.lyx.org Git - lyx.git/blob - src/Bullet.C
2eef9c5bbd7c1d386a844d73cac983e875376b23
[lyx.git] / src / Bullet.C
1 /**
2  * \file Bullet.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 Allan Rae
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 /* Completes the implementation of the Bullet class
13  * It defines the various LaTeX commands etc. required to
14  * generate the bullets in the bullet-panel's.
15  */
16
17 #include <config.h>
18
19 #include "Bullet.h"
20
21 #include <boost/assert.hpp>
22
23 using std::string;
24
25
26 /** The four LaTeX itemize environment default bullets
27  */
28 extern
29 Bullet const ITEMIZE_DEFAULTS[4] = { Bullet(0, 8),//"\\(\\bullet\\)"
30                                      Bullet(0, 0),//"\\normalfont\\bfseries{--}"
31                                      Bullet(0, 6),//"\\(\\ast\\)"
32                                      Bullet(0, 10) };//"\\(\\cdot\\)"
33
34 // will need these later if still using full text as below
35 // \usepackage{latexsym,pifont,amssymb}
36 // and wasysym when that panel is created
37
38
39 Bullet::Bullet(int f, int c, int s)
40   : font(f), character(c), size(s), user_text(0)
41 {
42         if (f < MIN || f >= FONTMAX) {
43                 font = MIN;
44         }
45         if (c < MIN || c >= CHARMAX) {
46                 character = MIN;
47         }
48         if (s < MIN || s >= SIZEMAX) {
49                 size = MIN;
50         }
51         generateText();
52         testInvariant();
53 }
54
55
56
57 Bullet::Bullet(string const & t)
58         : font(MIN), character(MIN), size(MIN), user_text(1), text(t)
59 {
60         testInvariant();
61 }
62
63
64 void Bullet::setCharacter(int c)
65 {
66         if (c < MIN || c >= CHARMAX) {
67                 character = MIN;
68         } else {
69                 character = c;
70         }
71         user_text = 0;
72         testInvariant();
73 }
74
75
76 void Bullet::setFont(int f)
77 {
78         if (f < MIN || f >= FONTMAX) {
79                 font = MIN;
80         } else {
81                 font = f;
82         }
83         user_text = 0;
84         testInvariant();
85 }
86
87
88 void Bullet::setSize(int s)
89 {
90         if (s < MIN || s >= SIZEMAX) {
91                 size = MIN;
92         } else {
93                 size = s;
94         }
95         user_text = 0;
96         testInvariant();
97 }
98
99
100 void Bullet::setText(string const & t)
101 {
102         font = character = size = MIN;
103         user_text = 1;
104         text = t;
105         testInvariant();
106 }
107
108
109 int Bullet::getCharacter() const
110 {
111         return character;
112 }
113
114
115 int Bullet::getFont() const
116 {
117         return font;
118 }
119
120
121 int Bullet::getSize() const
122 {
123         return size;
124 }
125
126
127 Bullet & Bullet::operator=(Bullet const & b)
128 {
129         b.testInvariant();
130         font = b.font;
131         character = b.character;
132         size = b.size;
133         user_text = b.user_text;
134         text = b.text;
135         this->testInvariant();
136         return *this;
137 }
138
139
140 string const & Bullet::getText() const
141 {
142         if (user_text == 0) {
143                 generateText();
144         }
145         return text;
146 }
147
148
149 bool operator==(const Bullet & b1, const Bullet & b2)
150 {
151         bool result = false;
152
153         if (b1.user_text && b2.user_text) {
154                 /* both have valid text */
155                 if (b1.text == b2.text) {
156                         result = true;
157                 }
158         } else if (((b1.character == b2.character) &&
159                           (b1.font == b2.font)) &&
160                          (b1.size == b2.size)) {
161                 result = true;
162         }
163         return result;
164 }
165
166
167 /*--------------------Private Member Functions-------------------*/
168
169
170 void Bullet::generateText() const
171 {
172         // Assumption:
173         // user hasn't defined their own text and/or I haven't generated
174         // the text for the current font/character settings yet
175         // thus the calling member function should say:
176         //    if (user_text == 0) {
177         //       generateText();
178         //    }
179         // Since a function call is more expensive than a conditional
180         // this is more efficient. Besides this function is internal to
181         // the class so it's only the class author that has access --
182         // external users thus can't make mistakes.
183
184         if ((font >= 0) && (character >= 0)) {
185                 text = bulletEntry(font, character);
186                 if (size >= 0) {
187                         text = bulletSize(size) + text;
188                 }
189                 user_text = -1;
190                 // text is now defined and doesn't need to be recalculated
191                 // unless font/character or text is modified
192         }
193 }
194
195
196 string const Bullet::bulletSize(int s)
197 {
198         // use a parameter rather than hard code `size' in here
199         // in case some future function may want to retrieve
200         // an arbitrary entry.
201         // See additional comments in bulletEntry() below.
202
203         static char const * BulletSize[SIZEMAX] = {
204                 "\\tiny",  "\\scriptsize", "\\footnotesize", "\\small", "\\normalsize",
205                 "\\large", "\\Large",      "\\LARGE",        "\\huge",  "\\Huge"
206         };
207
208         return BulletSize[s];
209 }
210
211
212 string const Bullet::bulletEntry(int f, int c)
213 {
214         // Despite how this may at first appear the static local variables
215         // are only initialized once..
216         // This is a work-around to avoid the "Static Initialization Problem"
217         // and should work for all compilers. See "C++ FAQs" by Cline and Lomow,
218         // Addison-Wesley, 1994, FAQ-180 pp169-171 for an explanation.
219         // Doing things this way also makes it possible to generate `text' at
220         // the time of construction.  It also encapsulates the conversion
221         // of font, character and size entries to text.
222
223         // The single 2-dim array had to be changed to multiple 1-dim arrays
224         // to get around a compiler bug in an earler version of gcc (< 2.7.2.1)
225         // static string const BulletPanels[FONTMAX][CHARMAX] = {
226         static char const * BulletPanel0[CHARMAX] = {
227                 /* standard */
228                 "\\normalfont\\bfseries{--}", "\\(\\vdash\\)",
229                 "\\(\\dashv\\)", "\\(\\flat\\)", "\\(\\natural\\)",
230                 "\\(\\sharp\\)", "\\(\\ast\\)", "\\(\\star\\)",
231                 "\\(\\bullet\\)", "\\(\\circ\\)", "\\(\\cdot\\)",
232                 "\\(\\dagger\\)", "\\(\\bigtriangleup\\)",
233                 "\\(\\bigtriangledown\\)", "\\(\\triangleleft\\)",
234                 "\\(\\triangleright\\)", "\\(\\lhd\\)", "\\(\\rhd\\)",
235                 "\\(\\oplus\\)", "\\(\\ominus\\)", "\\(\\otimes\\)",
236                 "\\(\\oslash\\)", "\\(\\odot\\)", "\\(\\spadesuit\\)",
237                 "\\(\\diamond\\)", "\\(\\Diamond\\)", "\\(\\Box\\)",
238                 "\\(\\diamondsuit\\)", "\\(\\heartsuit\\)",
239                 "\\(\\clubsuit\\)", "\\(\\rightarrow\\)", "\\(\\leadsto\\)",
240                 "\\(\\rightharpoonup\\)", "\\(\\rightharpoondown\\)",
241                 "\\(\\Rightarrow\\)", "\\(\\succ\\)"
242         };
243         static char const * BulletPanel1[CHARMAX] = {
244                 /* amssymb */
245                 "\\(\\Rrightarrow\\)", "\\(\\rightarrowtail\\)",
246                 "\\(\\twoheadrightarrow\\)", "\\(\\rightsquigarrow\\)",
247                 "\\(\\looparrowright\\)", "\\(\\multimap\\)",
248                 "\\(\\boxtimes\\)", "\\(\\boxplus\\)", "\\(\\boxminus\\)",
249                 "\\(\\boxdot\\)", "\\(\\divideontimes\\)", "\\(\\Vvdash\\)",
250                 "\\(\\lessdot\\)", "\\(\\gtrdot\\)", "\\(\\maltese\\)",
251                 "\\(\\bigstar\\)", "\\(\\checkmark\\)", "\\(\\Vdash\\)",
252                 "\\(\\backsim\\)", "\\(\\thicksim\\)",
253                 "\\(\\centerdot\\)", "\\(\\circleddash\\)",
254                 "\\(\\circledast\\)", "\\(\\circledcirc\\)",
255                 "\\(\\vartriangleleft\\)", "\\(\\vartriangleright\\)",
256                 "\\(\\vartriangle\\)", "\\(\\triangledown\\)",
257                 "\\(\\lozenge\\)", "\\(\\square\\)", "\\(\\blacktriangleleft\\)",
258                 "\\(\\blacktriangleright\\)", "\\(\\blacktriangle\\)",
259                 "\\(\\blacktriangledown\\)", "\\(\\blacklozenge\\)",
260                 "\\(\\blacksquare\\)"
261         };
262         static char const * BulletPanel2[CHARMAX] = {
263                 /* psnfss1 */
264                 "\\ding{108}", "\\ding{109}",
265                 "\\ding{119}", "\\Pisymbol{psy}{197}",
266                 "\\Pisymbol{psy}{196}", "\\Pisymbol{psy}{183}",
267                 "\\ding{71}", "\\ding{70}",
268                 "\\ding{118}", "\\ding{117}",
269                 "\\Pisymbol{psy}{224}", "\\Pisymbol{psy}{215}",
270                 "\\ding{111}", "\\ding{112}",
271                 "\\ding{113}", "\\ding{114}",
272                 "\\Pisymbol{psy}{68}", "\\Pisymbol{psy}{209}",
273                 "\\ding{120}", "\\ding{121}",
274                 "\\ding{122}", "\\ding{110}",
275                 "\\ding{115}", "\\ding{116}",
276                 "\\Pisymbol{psy}{42}", "\\ding{67}",
277                 "\\ding{66}", "\\ding{82}",
278                 "\\ding{81}", "\\ding{228}",
279                 "\\ding{162}", "\\ding{163}",
280                 "\\ding{166}", "\\ding{167}",
281                 "\\ding{226}", "\\ding{227}"
282         };
283         static char const * BulletPanel3[CHARMAX] = {
284                 /* psnfss2 */
285                 "\\ding{37}", "\\ding{38}",
286                 "\\ding{34}", "\\ding{36}",
287                 "\\ding{39}", "\\ding{40}",
288                 "\\ding{41}", "\\ding{42}",
289                 "\\ding{43}", "\\ding{44}",
290                 "\\ding{45}", "\\ding{47}",
291                 "\\ding{53}", "\\ding{54}",
292                 "\\ding{59}", "\\ding{57}",
293                 "\\ding{62}", "\\ding{61}",
294                 "\\ding{55}", "\\ding{56}",
295                 "\\ding{58}", "\\ding{60}",
296                 "\\ding{63}", "\\ding{64}",
297                 "\\ding{51}", "\\ding{52}",
298                 "\\Pisymbol{psy}{170}", "\\Pisymbol{psy}{167}",
299                 "\\Pisymbol{psy}{168}", "\\Pisymbol{psy}{169}",
300                 "\\ding{164}", "\\ding{165}",
301                 "\\ding{171}", "\\ding{168}",
302                 "\\ding{169}", "\\ding{170}"
303         };
304         static char const * BulletPanel4[CHARMAX] = {
305                 /* psnfss3 */
306                 "\\ding{65}", "\\ding{76}",
307                 "\\ding{75}", "\\ding{72}",
308                 "\\ding{80}", "\\ding{74}",
309                 "\\ding{78}", "\\ding{77}",
310                 "\\ding{79}", "\\ding{85}",
311                 "\\ding{90}", "\\ding{98}",
312                 "\\ding{83}", "\\ding{84}",
313                 "\\ding{86}", "\\ding{87}",
314                 "\\ding{88}", "\\ding{89}",
315                 "\\ding{92}", "\\ding{91}",
316                 "\\ding{93}", "\\ding{105}",
317                 "\\ding{94}", "\\ding{99}",
318                 "\\ding{103}", "\\ding{104}",
319                 "\\ding{106}", "\\ding{107}",
320                 "\\ding{68}", "\\ding{69}",
321                 "\\ding{100}", "\\ding{101}",
322                 "\\ding{102}", "\\ding{96}",
323                 "\\ding{95}", "\\ding{97}"
324         };
325         static char const * BulletPanel5[CHARMAX] = {
326                 /* psnfss4 */
327                 "\\ding{223}", "\\ding{224}",
328                 "\\ding{225}", "\\ding{232}",
329                 "\\ding{229}", "\\ding{230}",
330                 "\\ding{238}", "\\ding{237}",
331                 "\\ding{236}", "\\ding{235}",
332                 "\\ding{234}", "\\ding{233}",
333                 "\\ding{239}", "\\ding{241}",
334                 "\\ding{250}", "\\ding{251}",
335                 "\\ding{49}", "\\ding{50}",
336                 "\\ding{217}", "\\ding{245}",
337                 "\\ding{243}", "\\ding{248}",
338                 "\\ding{252}", "\\ding{253}",
339                 "\\ding{219}", "\\ding{213}",
340                 "\\ding{221}", "\\ding{222}",
341                 "\\ding{220}", "\\ding{212}",
342                 "\\Pisymbol{psy}{174}", "\\Pisymbol{psy}{222}",
343                 "\\ding{254}", "\\ding{242}",
344                 "\\ding{231}", "\\Pisymbol{psy}{45}"
345         };  /* string const BulletPanels[][] */
346
347         static char const ** BulletPanels[FONTMAX] = {
348                 BulletPanel0, BulletPanel1,
349                 BulletPanel2, BulletPanel3,
350                 BulletPanel4, BulletPanel5
351         };
352
353         return BulletPanels[f][c];
354 }
355
356 void Bullet::testInvariant() const
357 {
358 #ifdef ENABLE_ASSERTIONS
359         BOOST_ASSERT(font >= MIN);
360         BOOST_ASSERT(font < FONTMAX);
361         BOOST_ASSERT(character >= MIN);
362         BOOST_ASSERT(character < CHARMAX);
363         BOOST_ASSERT(size >= MIN);
364         BOOST_ASSERT(size < SIZEMAX);
365         BOOST_ASSERT(user_text >= -1);
366         BOOST_ASSERT(user_text <= 1);
367         // now some relational/operational tests
368         if (user_text == 1) {
369                 BOOST_ASSERT(font == -1 && (character == -1 && size == -1));
370                 //        BOOST_ASSERT(!text.empty()); // this isn't necessarily an error
371         }
372         //      else if (user_text == -1) {
373         //        BOOST_ASSERT(!text.empty()); // this also isn't necessarily an error
374         //      }
375         //      else {
376         //        // user_text == 0
377         //        BOOST_ASSERT(text.empty()); // not usually true
378         //      }
379 #endif
380 }