]> git.lyx.org Git - lyx.git/blob - src/Bullet.cpp
00a13ecd5c57856768f98ed3041ab002a68b6bd2
[lyx.git] / src / Bullet.cpp
1 /**
2  * \file Bullet.cpp
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 "support/lassert.h"
22
23 using namespace std;
24
25 namespace lyx {
26
27
28 /** The four LaTeX itemize environment default bullets
29  */
30 extern
31 Bullet const ITEMIZE_DEFAULTS[4] = { Bullet(0, 8),//"\\(\\bullet\\)"
32                                      Bullet(0, 0),//"\\normalfont\\bfseries{--}"
33                                      Bullet(0, 6),//"\\(\\ast\\)"
34                                      Bullet(0, 10) };//"\\(\\cdot\\)"
35
36 // will need these later if still using full text as below
37 // \usepackage{latexsym,pifont,amssymb}
38 // and wasysym when that panel is created
39
40
41 Bullet::Bullet(int f, int c, int s)
42         : font(f), character(c), size(s), user_text(0)
43 {
44         if (f < MIN || f >= FONTMAX)
45                 font = MIN;
46         if (c < MIN || c >= CHARMAX)
47                 character = MIN;
48         if (s < MIN || s >= SIZEMAX)
49                 size = MIN;
50         generateText();
51         testInvariant();
52 }
53
54
55
56 Bullet::Bullet(docstring const & t)
57         : font(MIN), character(MIN), size(MIN), user_text(1), text(t), label(t)
58 {
59         testInvariant();
60 }
61
62
63 void Bullet::setCharacter(int c)
64 {
65         if (c < MIN || c >= CHARMAX)
66                 character = MIN;
67         else
68                 character = c;
69         user_text = 0;
70         testInvariant();
71 }
72
73
74 void Bullet::setFont(int f)
75 {
76         if (f < MIN || f >= FONTMAX)
77                 font = MIN;
78         else
79                 font = f;
80         user_text = 0;
81         testInvariant();
82 }
83
84
85 void Bullet::setSize(int s)
86 {
87         if (s < MIN || s >= SIZEMAX)
88                 size = MIN;
89         else
90                 size = s;
91         user_text = 0;
92         testInvariant();
93 }
94
95
96 void Bullet::setText(docstring const & t)
97 {
98         font = character = size = MIN;
99         user_text = 1;
100         text = t;
101         label = t;
102         testInvariant();
103 }
104
105
106 int Bullet::getCharacter() const
107 {
108         return character;
109 }
110
111
112 int Bullet::getFont() const
113 {
114         return font;
115 }
116
117
118 int Bullet::getSize() const
119 {
120         return size;
121 }
122
123
124 FontSize Bullet::getFontSize() const
125 {
126
127         if (size >= 0)
128                 return bulletFontSize(size);
129         else
130                 return INHERIT_SIZE;
131 }
132
133
134 Bullet & Bullet::operator=(Bullet const & b)
135 {
136         b.testInvariant();
137         font = b.font;
138         character = b.character;
139         size = b.size;
140         user_text = b.user_text;
141         text = b.text;
142         label = b.label;
143         this->testInvariant();
144         return *this;
145 }
146
147
148 docstring const & Bullet::getText() const
149 {
150         if (user_text == 0)
151                 generateText();
152         return text;
153 }
154
155
156 docstring const & Bullet::getLabel() const
157 {
158         if (user_text == 0)
159                 generateText();
160         return label;
161 }
162
163
164 bool operator==(const Bullet & b1, const Bullet & b2)
165 {
166         bool result = false;
167
168         if (b1.user_text && b2.user_text) {
169                 /* both have valid text */
170                 if (b1.text == b2.text)
171                         result = true;
172         } else if (b1.character == b2.character && b1.font == b2.font &&
173                          b1.size == b2.size) {
174                 result = true;
175         }
176         return result;
177 }
178
179
180 /*--------------------Private Member Functions-------------------*/
181
182
183 void Bullet::generateText() const
184 {
185         // Assumption:
186         // user hasn't defined their own text and/or I haven't generated
187         // the text for the current font/character settings yet
188         // thus the calling member function should say:
189         //    if (user_text == 0) {
190         //       generateText();
191         //    }
192         // Since a function call is more expensive than a conditional
193         // this is more efficient. Besides this function is internal to
194         // the class so it's only the class author that has access --
195         // external users thus can't make mistakes.
196
197         if ((font >= 0) && (character >= 0)) {
198                 text = bulletEntry(font, character);
199                 label = bulletLabel(font, character);
200                 if (size >= 0)
201                         text = bulletSize(size) + text;
202                 user_text = -1;
203                 // text is now defined and doesn't need to be recalculated
204                 // unless font/character or text is modified
205         }
206 }
207
208
209 docstring const Bullet::bulletSize(int s)
210 {
211         // use a parameter rather than hard code `size' in here
212         // in case some future function may want to retrieve
213         // an arbitrary entry.
214         // See additional comments in bulletEntry() below.
215
216         static char const * BulletSize[SIZEMAX] = {
217                 "\\tiny",  "\\scriptsize", "\\footnotesize", "\\small", "\\normalsize",
218                 "\\large", "\\Large",      "\\LARGE",        "\\huge",  "\\Huge"
219         };
220
221         return from_ascii(BulletSize[s]);
222 }
223
224
225 docstring const Bullet::bulletEntry(int f, int c)
226 {
227         // Despite how this may at first appear the static local variables
228         // are only initialized once..
229         // This is a work-around to avoid the "Static Initialization Problem"
230         // and should work for all compilers. See "C++ FAQs" by Cline and Lomow,
231         // Addison-Wesley, 1994, FAQ-180 pp169-171 for an explanation.
232         // Doing things this way also makes it possible to generate `text' at
233         // the time of construction.  It also encapsulates the conversion
234         // of font, character and size entries to text.
235
236         // The single 2-dim array had to be changed to multiple 1-dim arrays
237         // to get around a compiler bug in an earler version of gcc (< 2.7.2.1)
238         // static string const BulletPanels[FONTMAX][CHARMAX] = {
239         static char const * BulletPanel0[CHARMAX] = {
240                 /* standard */
241                 "\\normalfont\\bfseries{--}", "\\(\\vdash\\)",
242                 "\\(\\dashv\\)", "\\(\\flat\\)", "\\(\\natural\\)",
243                 "\\(\\sharp\\)", "\\(\\ast\\)", "\\(\\star\\)",
244                 "\\(\\bullet\\)", "\\(\\circ\\)", "\\(\\cdot\\)",
245                 "\\(\\dagger\\)", "\\(\\bigtriangleup\\)",
246                 "\\(\\bigtriangledown\\)", "\\(\\triangleleft\\)",
247                 "\\(\\triangleright\\)", "\\(\\lhd\\)", "\\(\\rhd\\)",
248                 "\\(\\oplus\\)", "\\(\\ominus\\)", "\\(\\otimes\\)",
249                 "\\(\\oslash\\)", "\\(\\odot\\)", "\\(\\spadesuit\\)",
250                 "\\(\\diamond\\)", "\\(\\Diamond\\)", "\\(\\Box\\)",
251                 "\\(\\diamondsuit\\)", "\\(\\heartsuit\\)",
252                 "\\(\\clubsuit\\)", "\\(\\rightarrow\\)", "\\(\\leadsto\\)",
253                 "\\(\\rightharpoonup\\)", "\\(\\rightharpoondown\\)",
254                 "\\(\\Rightarrow\\)", "\\(\\succ\\)"
255         };
256         static char const * BulletPanel1[CHARMAX] = {
257                 /* amssymb */
258                 "\\(\\Rrightarrow\\)", "\\(\\rightarrowtail\\)",
259                 "\\(\\twoheadrightarrow\\)", "\\(\\rightsquigarrow\\)",
260                 "\\(\\looparrowright\\)", "\\(\\multimap\\)",
261                 "\\(\\boxtimes\\)", "\\(\\boxplus\\)", "\\(\\boxminus\\)",
262                 "\\(\\boxdot\\)", "\\(\\divideontimes\\)", "\\(\\Vvdash\\)",
263                 "\\(\\lessdot\\)", "\\(\\gtrdot\\)", "\\(\\maltese\\)",
264                 "\\(\\bigstar\\)", "\\(\\checkmark\\)", "\\(\\Vdash\\)",
265                 "\\(\\backsim\\)", "\\(\\thicksim\\)",
266                 "\\(\\centerdot\\)", "\\(\\circleddash\\)",
267                 "\\(\\circledast\\)", "\\(\\circledcirc\\)",
268                 "\\(\\vartriangleleft\\)", "\\(\\vartriangleright\\)",
269                 "\\(\\vartriangle\\)", "\\(\\triangledown\\)",
270                 "\\(\\lozenge\\)", "\\(\\square\\)", "\\(\\blacktriangleleft\\)",
271                 "\\(\\blacktriangleright\\)", "\\(\\blacktriangle\\)",
272                 "\\(\\blacktriangledown\\)", "\\(\\blacklozenge\\)",
273                 "\\(\\blacksquare\\)"
274         };
275         static char const * BulletPanel2[CHARMAX] = {
276                 /* psnfss1 */
277                 "\\ding{108}", "\\ding{109}",
278                 "\\ding{119}", "\\Pisymbol{psy}{197}",
279                 "\\Pisymbol{psy}{196}", "\\Pisymbol{psy}{183}",
280                 "\\ding{71}", "\\ding{70}",
281                 "\\ding{118}", "\\ding{117}",
282                 "\\Pisymbol{psy}{224}", "\\Pisymbol{psy}{215}",
283                 "\\ding{111}", "\\ding{112}",
284                 "\\ding{113}", "\\ding{114}",
285                 "\\Pisymbol{psy}{68}", "\\Pisymbol{psy}{209}",
286                 "\\ding{120}", "\\ding{121}",
287                 "\\ding{122}", "\\ding{110}",
288                 "\\ding{115}", "\\ding{116}",
289                 "\\Pisymbol{psy}{42}", "\\ding{67}",
290                 "\\ding{66}", "\\ding{82}",
291                 "\\ding{81}", "\\ding{228}",
292                 "\\ding{162}", "\\ding{163}",
293                 "\\ding{166}", "\\ding{167}",
294                 "\\ding{226}", "\\ding{227}"
295         };
296         static char const * BulletPanel3[CHARMAX] = {
297                 /* psnfss2 */
298                 "\\ding{37}", "\\ding{38}",
299                 "\\ding{34}", "\\ding{36}",
300                 "\\ding{39}", "\\ding{40}",
301                 "\\ding{41}", "\\ding{42}",
302                 "\\ding{43}", "\\ding{44}",
303                 "\\ding{45}", "\\ding{47}",
304                 "\\ding{53}", "\\ding{54}",
305                 "\\ding{59}", "\\ding{57}",
306                 "\\ding{62}", "\\ding{61}",
307                 "\\ding{55}", "\\ding{56}",
308                 "\\ding{58}", "\\ding{60}",
309                 "\\ding{63}", "\\ding{64}",
310                 "\\ding{51}", "\\ding{52}",
311                 "\\Pisymbol{psy}{170}", "\\Pisymbol{psy}{167}",
312                 "\\Pisymbol{psy}{168}", "\\Pisymbol{psy}{169}",
313                 "\\ding{164}", "\\ding{165}",
314                 "\\ding{171}", "\\ding{168}",
315                 "\\ding{169}", "\\ding{170}"
316         };
317         static char const * BulletPanel4[CHARMAX] = {
318                 /* psnfss3 */
319                 "\\ding{65}", "\\ding{76}",
320                 "\\ding{75}", "\\ding{72}",
321                 "\\ding{80}", "\\ding{74}",
322                 "\\ding{78}", "\\ding{77}",
323                 "\\ding{79}", "\\ding{85}",
324                 "\\ding{90}", "\\ding{98}",
325                 "\\ding{83}", "\\ding{84}",
326                 "\\ding{86}", "\\ding{87}",
327                 "\\ding{88}", "\\ding{89}",
328                 "\\ding{92}", "\\ding{91}",
329                 "\\ding{93}", "\\ding{105}",
330                 "\\ding{94}", "\\ding{99}",
331                 "\\ding{103}", "\\ding{104}",
332                 "\\ding{106}", "\\ding{107}",
333                 "\\ding{68}", "\\ding{69}",
334                 "\\ding{100}", "\\ding{101}",
335                 "\\ding{102}", "\\ding{96}",
336                 "\\ding{95}", "\\ding{97}"
337         };
338         static char const * BulletPanel5[CHARMAX] = {
339                 /* psnfss4 */
340                 "\\ding{223}", "\\ding{224}",
341                 "\\ding{225}", "\\ding{232}",
342                 "\\ding{229}", "\\ding{230}",
343                 "\\ding{238}", "\\ding{237}",
344                 "\\ding{236}", "\\ding{235}",
345                 "\\ding{234}", "\\ding{233}",
346                 "\\ding{239}", "\\ding{241}",
347                 "\\ding{250}", "\\ding{251}",
348                 "\\ding{49}", "\\ding{50}",
349                 "\\ding{217}", "\\ding{245}",
350                 "\\ding{243}", "\\ding{248}",
351                 "\\ding{252}", "\\ding{253}",
352                 "\\ding{219}", "\\ding{213}",
353                 "\\ding{221}", "\\ding{222}",
354                 "\\ding{220}", "\\ding{212}",
355                 "\\Pisymbol{psy}{174}", "\\Pisymbol{psy}{222}",
356                 "\\ding{254}", "\\ding{242}",
357                 "\\ding{231}", "\\Pisymbol{psy}{45}"
358         };  /* string const BulletPanels[][] */
359
360         static char const ** BulletPanels[FONTMAX] = {
361                 BulletPanel0, BulletPanel1,
362                 BulletPanel2, BulletPanel3,
363                 BulletPanel4, BulletPanel5
364         };
365
366         return from_ascii(BulletPanels[f][c]);
367 }
368
369
370 FontSize Bullet::bulletFontSize(int s)
371 {
372         // see comment at bulletSize
373         static FontSize BulletFontSize[SIZEMAX] = {
374                 TINY_SIZE, SCRIPT_SIZE, FOOTNOTE_SIZE, SMALL_SIZE, NORMAL_SIZE,
375                 LARGE_SIZE, LARGER_SIZE, LARGEST_SIZE, HUGE_SIZE, HUGER_SIZE
376         };
377
378         return BulletFontSize[s];
379 }
380
381
382 docstring const Bullet::bulletLabel(int f, int c)
383 {
384         // see comment at bulletEntry
385         static int UnicodeBulletPanel0[CHARMAX] = {
386                 /* standard */
387                 0x02013, 0x22A2,
388                 0x022A3, 0x0266D, 0x0266E,
389                 0x0266F, 0x02217, 0x022C6,
390                 0x02022, 0x02218, 0x022C5,
391                 0x02020, 0x025B3,
392                 0x025BD, 0x025C3,
393                 0x025B9, 0x025C1, 0x025B7,
394                 0x02295, 0x02296, 0x02297,
395                 0x02298, 0x02299, 0x02660,
396                 0x022C4, 0x025C7,  /* \square */ 0x025FB,
397                 0x02662, 0x02661,
398                 0x02663, 0x02192, 0x02933,
399                 0x021C0, 0x021C1,
400                 0x021D2, 0x0227B
401         };
402         static int UnicodeBulletPanel1[CHARMAX] = {
403                 /* amssymb */
404                 0x021DB, 0x021A3,
405                 0x021A0, 0x021DD,
406                 0x021AC, 0x022B8,
407                 0x022A0, 0x0229E, 0x0229F,
408                 0x022A1, 0x022C7, 0x022AA,
409                 0x022D6, 0x022D7, 0x02720,
410                 0x02605, 0x02713, 0x022A9,
411                 0x0223D, 0x0223C,
412                 0x02B1D, 0x0229D,
413                 0x0229B, 0x025CE,
414                 0x022B2, 0x022B3,
415                 0x025B3, 0x025BD,
416                 0x025CA, 0x025FB, 0x025C0,
417                 0x025B6, 0x025B4,
418                 0x025BE, 0x029EB,
419                 0x025FC
420         };
421         static int UnicodeBulletPanel2[CHARMAX] = {
422                 /* psnfss1 */
423                 0x025CF, 0x0274D,
424                 0x025D7, 0x02295,
425                 0x02297, 0x02022,
426                 0x02727, 0x02726,
427                 0x02756, 0x025C6,
428                 0x025CA, 0x022C5,
429                 0x02751, 0x02752,
430                 0x0274F, 0x02750,
431                 0x02206, 0x02207,
432                 0x02758, 0x02759,
433                 0x0275A, 0x025A0,
434                 0x025B2, 0x025BC,
435                 0x02217, 0x02723,
436                 0x02722, 0x02732,
437                 0x02731, 0x027A4,
438                 0x02762, 0x02763,
439                 0x02766, 0x02767,
440                 0x027A2, 0x027A3
441         };
442         static int UnicodeBulletPanel3[CHARMAX] = {
443                 /* psnfss2 */
444                 0x0260E, 0x02706,
445                 0x02702, 0x02704,
446                 0x02707, 0x02708,
447                 0x02709, 0x0261B,
448                 0x0261E, 0x0270C,
449                 0x0270D, 0x0270F,
450                 0x02715, 0x02716,
451                 0x0271B, 0x02719,
452                 0x0271E, 0x0271D,
453                 0x02717, 0x02718,
454                 0x0271A, 0x0271C,
455                 0x0271F, 0x02720,
456                 0x02713, 0x02714,
457                 0x02660, 0x02663,
458                 0x02666, 0x02665,
459                 0x02764, 0x02765,
460                 0x02660, 0x02663,
461                 0x02666, 0x02665
462         };
463         static int UnicodeBulletPanel4[CHARMAX] = {
464                 /* psnfss3 */
465                 0x02721, 0x0272C,
466                 0x0272B, 0x02B51,
467                 0x02730, 0x0272A,
468                 0x0272E, 0x0272D,
469                 0x0272F, 0x02735,
470                 0x0273A, 0x02742,
471                 0x02733, 0x02734,
472                 0x02736, 0x02737,
473                 0x02738, 0x02739,
474                 0x0273C, 0x0273B,
475                 0x0273D, 0x02749,
476                 0x0273E, 0x02743,
477                 0x02747, 0x02748,
478                 0x0274A, 0x0274B,
479                 0x02724, 0x02725,
480                 0x02744, 0x02745,
481                 0x02746, 0x02740,
482                 0x0273F, 0x02741
483         };
484         static int UnicodeBulletPanel5[CHARMAX] = {
485                 /* psnfss4 */
486                 0x0279F, 0x027A0,
487                 0x027A1, 0x027A8,
488                 0x027A5, 0x027A6,
489                 0x027AE, 0x027AD,
490                 0x027AC, 0x027AB,
491                 0x027AA, 0x027A9,
492                 0x027AF, 0x027B1,
493                 0x027BA, 0x027BB,
494                 0x02711, 0x02712,
495                 0x02799, 0x027B5,
496                 0x027B3, 0x027B8,
497                 0x027BC, 0x027BD,
498                 0x0279B, 0x02192,
499                 0x0279D, 0x0279E,
500                 0x0279C, 0x02794,
501                 0x02192, 0x021D2,
502                 0x027BE, 0x027B2,
503                 0x027A7, 0x02212
504         };  /* string const BulletPanels[][] */
505
506         static int * UnicodeBulletPanels[FONTMAX] = {
507                 UnicodeBulletPanel0, UnicodeBulletPanel1,
508                 UnicodeBulletPanel2, UnicodeBulletPanel3,
509                 UnicodeBulletPanel4, UnicodeBulletPanel5
510         };
511
512         return docstring(1, char_type(UnicodeBulletPanels[f][c]));
513 }
514
515
516 void Bullet::testInvariant() const
517 {
518 #ifdef ENABLE_ASSERTIONS
519         LATTEST(font >= MIN);
520         LATTEST(font < FONTMAX);
521         LATTEST(character >= MIN);
522         LATTEST(character < CHARMAX);
523         LATTEST(size >= MIN);
524         LATTEST(size < SIZEMAX);
525         LATTEST(user_text >= -1);
526         LATTEST(user_text <= 1);
527         // now some relational/operational tests
528         if (user_text == 1) {
529                 LATTEST(font == -1 && (character == -1 && size == -1));
530                 //        LATTEST(!text.empty()); // this isn't necessarily an error
531         }
532         //      else if (user_text == -1) {
533         //        LATTEST(!text.empty()); // this also isn't necessarily an error
534         //      }
535         //      else {
536         //        // user_text == 0
537         //        LATTEST(text.empty()); // not usually true
538         //      }
539 #endif
540 }
541
542
543 } // namespace lyx