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 
Bullet(int f,int c,int s)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 
Bullet(docstring const & t)56 Bullet::Bullet(docstring const & t)
57 	: font(MIN), character(MIN), size(MIN), user_text(1), text(t)
58 {
59 	testInvariant();
60 }
61 
62 
setCharacter(int c)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 
setFont(int f)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 
setSize(int s)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 
setText(docstring const & t)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 
getCharacter() const105 int Bullet::getCharacter() const
106 {
107 	return character;
108 }
109 
110 
getFont() const111 int Bullet::getFont() const
112 {
113 	return font;
114 }
115 
116 
getSize() const117 int Bullet::getSize() const
118 {
119 	return size;
120 }
121 
122 
operator =(Bullet const & b)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 
getText() const136 docstring const & Bullet::getText() const
137 {
138 	if (user_text == 0)
139 		generateText();
140 	return text;
141 }
142 
143 
operator ==(const Bullet & b1,const Bullet & b2)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 
generateText() const163 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 
bulletSize(int s)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 
bulletEntry(int f,int c)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 
testInvariant() const348 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
376