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