2 * Copyright (c) 2014 - 2017 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
4 * Copyright (C) 1989 - 1992, 2003, 2007
5 * Free Software Foundation, Inc.
6 * Written by James Clark (jjc@jclark.com)
8 * This is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2, or (at your option) any later
13 * This is distributed in the hope that it will be useful, but WITHOUT ANY
14 * WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 * You should have received a copy of the GNU General Public License along
19 * with groff; see the file COPYING. If not, write to the Free Software
20 * Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.
24 #include "eqn-config.h"
37 struct map entity_table
[] = { // FIXME const
38 // Classic troff special characters
39 {"%", "­"}, // ISOnum
40 {"'", "´"}, // ISOdia
41 {"!=", "≠"}, // ISOtech
42 {"**", "∗"}, // ISOtech
43 {"*a", "α"}, // ISOgrk3
45 {"*b", "β"}, // ISOgrk3
47 {"*d", "δ"}, // ISOgrk3
48 {"*D", "Δ"}, // ISOgrk3
49 {"*e", "ε"}, // ISOgrk3
51 {"*f", "φ"}, // ISOgrk3
52 {"*F", "Φ"}, // ISOgrk3
53 {"*g", "γ"}, // ISOgrk3
54 {"*G", "Γ"}, // ISOgrk3
55 {"*h", "θ"}, // ISOgrk3
56 {"*H", "Θ"}, // ISOgrk3
57 {"*i", "ι"}, // ISOgrk3
59 {"*k", "κ"}, // ISOgrk3
61 {"*l", "λ"}, // ISOgrk3
62 {"*L", "Λ"}, // ISOgrk3
63 {"*m", "μ"}, // ISOgrk3
65 {"*n", "ν"}, // ISOgrk3
69 {"*p", "π"}, // ISOgrk3
70 {"*P", "Π"}, // ISOgrk3
71 {"*q", "ψ"}, // ISOgrk3
72 {"*Q", "&PSI;"}, // ISOgrk3
73 {"*r", "ρ"}, // ISOgrk3
75 {"*s", "σ"}, // ISOgrk3
76 {"*S", "Σ"}, // ISOgrk3
77 {"*t", "τ"}, // ISOgrk3
78 {"*T", "Τ"}, // ISOgrk3
79 {"*u", "υ"}, // ISOgrk3
80 {"*U", "Υ"}, // ISOgrk3
81 {"*w", "ω"}, // ISOgrk3
82 {"*W", "Ω"}, // ISOgrk3
83 {"*x", "χ"}, // ISOgrk3
84 {"*X", "Χ"}, // ISOgrk3
85 {"*y", "η"}, // ISOgrk3
86 {"*Y", "Η"}, // ISOgrk3
87 {"*z", "ζ"}, // ISOgrk3
88 {"*Z", "Ζ"}, // ISOgrk3
89 {"+-", "±"}, // ISOnum
90 {"->", "→"}, // ISOnum
91 {"12", "½"}, // ISOnum
92 {"14", "¼"}, // ISOnum
93 {"34", "¾"}, // ISOnum
94 {"<-", "←"}, // ISOnum
95 {"==", "≡"}, // ISOtech
96 {"Fi", "ffi"}, // ISOpub
97 {"Fl", "ffl"}, // ISOpub
98 {"aa", "´"}, // ISOdia
99 {"ap", "∼"}, // ISOtech
100 {"bl", "&phonexb;"}, // ISOpub
101 {"br", "│"}, // ISObox
102 {"bs", "☎"}, // ISOpub (for the Bell logo)
103 {"bu", "•"}, // ISOpub
104 {"bv", "|"}, // ISOnum
105 {"ca", "∩"}, // ISOtech
106 {"ci", "○"}, // ISOpub
107 {"co", "©"}, // ISOnum
108 {"ct", "¢"}, // ISOnum
109 {"cu", "∪"}, // ISOtech
110 {"da", "↓"}, // ISOnum
111 {"de", "°"}, // ISOnum
112 {"dg", "†"}, // ISOpub
113 {"dd", "‡"}, // ISOpub
114 {"di", "÷"}, // ISOnum
115 {"em", "—"}, // ISOpub
116 {"eq", "="}, // ISOnum
117 {"es", "∅"}, // ISOamso
118 {"ff", "ff"}, // ISOpub
119 {"fi", "fi"}, // ISOpub
120 {"fl", "fl"}, // ISOpub
121 {"fm", "′"}, // ISOtech
122 {"ge", "≥"}, // ISOtech
123 {"gr", "∇"}, // ISOtech
124 {"hy", "‐"}, // ISOnum
125 {"ib", "⊆"}, // ISOtech
126 {"if", "∞"}, // ISOtech
127 {"ip", "⊇"}, // ISOtech
128 {"is", "∫"}, // ISOtech
129 {"le", "≤"}, // ISOtech
130 // Some pile characters go here
131 {"mi", "−"}, // ISOtech
132 {"mo", "∈"}, // ISOtech
133 {"mu", "×"}, // ISOnum
134 {"no", "¬"}, // ISOnum
135 {"or", "|"}, // ISOnum
136 {"pl", "+"}, // ISOnum
137 {"pt", "∝"}, // ISOtech
138 {"rg", "™"}, // ISOnum
139 // More pile characters go here
140 {"rn", "¯"}, // ISOdia
141 {"ru", "_"}, // ISOnum
142 {"sb", "⊂"}, // ISOtech
143 {"sc", "§"}, // ISOnum
145 {"sp", "⊃"}, // ISOtech
146 {"sq", "▪"}, // ISOpub
147 {"sr", "√"}, // ISOtech
148 {"ts", "ς"}, // ISOgrk3
149 {"ua", "↑"}, // ISOnum
151 {"~=", "≅"}, // ISOtech
152 // Extended specials supported by groff; see groff_char(7).
153 // These are listed in the order they occur on that man page.
154 {"-D", "Ð"}, // ISOlat: Icelandic uppercase eth
155 {"Sd", "ð"}, // ISOlat1: Icelandic lowercase eth
156 {"TP", "Þ"}, // ISOlat1: Icelandic uppercase thorn
157 {"Tp", "þ"}, // ISOlat1: Icelandic lowercase thorn
158 {"ss", "ß"}, // ISOlat1
160 // ff, fi, fl, ffi, ffl from old troff go here
161 {"AE", "Æ"}, // ISOlat1
162 {"ae", "æ"}, // ISOlat1
163 {"OE", "Œ"}, // ISOlat2
164 {"oe", "œ"}, // ISOlat2
165 {"IJ", "ij"}, // ISOlat2: Dutch IJ ligature
166 {"ij", "IJ"}, // ISOlat2: Dutch ij ligature
167 {".i", "ı"}, // ISOlat2,ISOamso
168 {".j", "&jnodot;"}, // ISOamso (undocumented but in 1.19)
169 // Accented characters
170 {"'A", "Á"}, // ISOlat1
171 {"'C", "Ć"}, // ISOlat2
172 {"'E", "É"}, // ISOlat1
173 {"'I", "Í"}, // ISOlat1
174 {"'O", "Ó"}, // ISOlat1
175 {"'U", "Ú"}, // ISOlat1
176 {"'Y", "Ý"}, // ISOlat1
177 {"'a", "á"}, // ISOlat1
178 {"'c", "ć"}, // ISOlat2
179 {"'e", "é"}, // ISOlat1
180 {"'i", "í"}, // ISOlat1
181 {"'o", "ó"}, // ISOlat1
182 {"'u", "ú"}, // ISOlat1
183 {"'y", "ý"}, // ISOlat1
184 {":A", "Ä"}, // ISOlat1
185 {":E", "Ë"}, // ISOlat1
186 {":I", "Ï"}, // ISOlat1
187 {":O", "Ö"}, // ISOlat1
188 {":U", "Ü"}, // ISOlat1
189 {":Y", "Ÿ"}, // ISOlat2
190 {":a", "ä"}, // ISOlat1
191 {":e", "ë"}, // ISOlat1
192 {":i", "ï"}, // ISOlat1
193 {":o", "ö"}, // ISOlat1
194 {":u", "ü"}, // ISOlat1
195 {":y", "ÿ"}, // ISOlat1
196 {"^A", "Â"}, // ISOlat1
197 {"^E", "Ê"}, // ISOlat1
198 {"^I", "Î"}, // ISOlat1
199 {"^O", "Ô"}, // ISOlat1
200 {"^U", "Û"}, // ISOlat1
201 {"^a", "â"}, // ISOlat1
202 {"^e", "ê"}, // ISOlat1
203 {"^i", "î"}, // ISOlat1
204 {"^o", "ô"}, // ISOlat1
205 {"^u", "û"}, // ISOlat1
206 {"`A", "À"}, // ISOlat1
207 {"`E", "È"}, // ISOlat1
208 {"`I", "Ì"}, // ISOlat1
209 {"`O", "Ò"}, // ISOlat1
210 {"`U", "Ù"}, // ISOlat1
211 {"`a", "à"}, // ISOlat1
212 {"`e", "è"}, // ISOlat1
213 {"`i", "ì"}, // ISOlat1
214 {"`o", "ò"}, // ISOlat1
215 {"`u", "ù"}, // ISOlat1
216 {"~A", "Ã"}, // ISOlat1
217 {"~N", "Ñ"}, // ISOlat1
218 {"~O", "Õ"}, // ISOlat1
219 {"~a", "ã"}, // ISOlat1
220 {"~n", "ñ"}, // ISOlat1
221 {"~o", "õ"}, // ISOlat1
222 {"vS", "Š"}, // ISOlat2
223 {"vs", "š"}, // ISOlat2
224 {"vZ", "Ž"}, // ISOlat2
225 {"vz", "ž"}, // ISOlat2
226 {",C", "Ç"}, // ISOlat1
227 {",c", "ç"}, // ISOlat1
228 {"/L", "Ł"}, // ISOlat2: Polish L with a slash
229 {"/l", "ł"}, // ISOlat2: Polish l with a slash
230 {"/O", "Ø"}, // ISOlat1
231 {"/o", "ø"}, // ISOlat1
232 {"oA", "Å"}, // ISOlat1
233 {"oa", "å"}, // ISOlat1
235 {"a\"","˝"}, // ISOdia: double acute accent (Hungarian umlaut)
236 {"a-", "¯"}, // ISOdia: macron or bar accent
237 {"a.", "˙"}, // ISOdia: dot above
238 {"a^", "ˆ"}, // ISOdia: circumflex accent
239 {"aa", "´"}, // ISOdia: acute accent
240 {"ga", "`"}, // ISOdia: grave accent
241 {"ab", "˘"}, // ISOdia: breve accent
242 {"ac", "¸"}, // ISOdia: cedilla accent
243 {"ad", "¨"}, // ISOdia: umlaut or dieresis
244 {"ah", "ˇ"}, // ISOdia: caron (aka hacek accent)
245 {"ao", "˚"}, // ISOdia: ring or circle accent
246 {"a~", "˜"}, // ISOdia: tilde accent
247 {"ho", "˛"}, // ISOdia: hook or ogonek accent
248 {"ha", "^"}, // ASCII circumflex, hat, caret
249 {"ti", "~"}, // ASCII tilde, large tilde
251 {"Bq", "‚"}, // ISOpub: low double comma quote
252 {"bq", "„"}, // ISOpub: low single comma quote
253 {"lq", "“"}, // ISOnum
254 {"rq", "”"}, // ISOpub
255 {"oq", "‘"}, // ISOnum: single open quote
256 {"cq", "’"}, // ISOnum: single closing quote (ASCII 39)
257 {"aq", "&zerosp;'"}, // apostrophe quote
258 {"dq", "\""}, // double quote (ASCII 34)
259 {"Fo", "«"}, // ISOnum
260 {"Fc", "»"}, // ISOnum
264 {"r!", "¡"}, // ISOnum
265 {"r?", "¿"}, // ISOnum
266 // Old troff \(em goes here
267 {"en", "–"}, // ISOpub: en dash
268 // Old troff \(hy goes here
270 {"lB", "["}, // ISOnum: left (square) bracket
271 {"rB", "]"}, // ISOnum: right (square) bracket
272 {"lC", "{"}, // ISOnum: left (curly) brace
273 {"rC", "}"}, // ISOnum: right (curly) brace
274 {"la", "⟨"}, // ISOtech: left angle bracket
275 {"ra", "⟩"}, // ISOtech: right angle bracket
276 // Old troff \(bv goes here
277 // Bracket-pile characters could go here.
279 // Old troff \(<- and \(-> go here
280 {"<>", "↔"}, // ISOamsa
281 {"da", "↓"}, // ISOnum
282 {"ua", "↑"}, // ISOnum
283 {"lA", "⇐"}, // ISOtech
284 {"rA", "⇒"}, // ISOtech
285 {"hA", "⇔"}, // ISOtech: horizontal double-headed arrow
286 {"dA", "⇓"}, // ISOamsa
287 {"uA", "⇑"}, // ISOamsa
288 {"vA", "⇕"}, // ISOamsa: vertical double-headed double arrow
291 {"-h", "ℏ"}, // ISOamso: h-bar (Planck's constant)
292 // Old troff \(or goes here
293 {"ba", "|"}, // ISOnum
294 // Old troff \(br, \{u, \(ul, \(bv go here
295 {"bb", "¦"}, // ISOnum
297 {"rs", "\"}, // ISOnum
299 // Old troff \(ci, \(bu, \(dd, \(dg go here
300 {"lz", "◊"}, // ISOpub
301 // Old troff sq goes here
302 {"ps", "¶"}, // ISOnum: paragraph or pilcrow sign
303 {"sc", "§"}, // ISOnum (in old troff)
304 // Old troff \(lh, \{h go here
305 {"at", "@"}, // ISOnum
306 {"sh", "#"}, // ISOnum
308 {"OK", "✓"}, // ISOpub
310 // Old troff \(co, \{g go here
311 {"tm", "™"}, // ISOnum
313 {"Do", "$"}, // ISOnum
314 {"ct", "¢"}, // ISOnum
317 {"Ye", "¥"}, // ISOnum
318 {"Po", "£"}, // ISOnum
319 {"Cs", "¤"}, // ISOnum: currency sign
320 {"Fn", "&fnof"}, // ISOtech
322 // Old troff de goes here
323 {"%0", "‰"}, // ISOtech: per thousand, per mille sign
324 // Old troff \(fm goes here
325 {"sd", "″"}, // ISOtech
326 {"mc", "µ"}, // ISOnum
327 {"Of", "ª"}, // ISOnum
328 {"Om", "º"}, // ISOnum
330 {"AN", "∧"}, // ISOtech
331 {"OR", "∨"}, // ISOtech
332 // Old troff \(no goes here
333 {"te", "∃"}, // ISOtech: there exists, existential quantifier
334 {"fa", "∀"}, // ISOtech: for all, universal quantifier
335 {"st", "&bepsi"}, // ISOamsr: such that
336 {"3d", "∴"}, // ISOtech
337 {"tf", "∴"}, // ISOtech
338 // Mathematical symbols
339 // Old troff "12", "14", "34" goes here
340 {"S1", "¹"}, // ISOnum
341 {"S2", "²"}, // ISOnum
342 {"S3", "³"}, // ISOnum
343 // Old troff \(pl", \-, \(+- go here
344 {"t+-", "±"}, // ISOnum
345 {"-+", "∓"}, // ISOtech
346 {"pc", "·"}, // ISOnum
347 {"md", "·"}, // ISOnum
348 // Old troff \(mu goes here
349 {"tmu", "×"}, // ISOnum
350 {"c*", "⊗"}, // ISOamsb: multiply sign in a circle
351 {"c+", "⊕"}, // ISOamsb: plus sign in a circle
352 // Old troff \(di goes here
353 {"tdi", "÷"}, // ISOnum
354 {"f/", "―"}, // ISOnum: horizintal bar for fractions
355 // Old troff \(** goes here
356 {"<=", "≤"}, // ISOtech
357 {">=", "≥"}, // ISOtech
358 {"<<", "≪"}, // ISOamsr
359 {">>", "≫"}, // ISOamsr
360 {"!=", "≠"}, // ISOtech
361 // Old troff \(eq and \(== go here
362 {"=~", "≅"}, // ISOamsr
363 // Old troff \(ap goes here
364 {"~~", "≈"}, // ISOtech
365 // This appears to be an error in the groff table.
366 // It clashes with the Bell Labs use of ~= for a congruence sign
367 // {"~=", "≈"}, // ISOamsr
368 // Old troff \(pt, \(es, \(mo go here
369 {"nm", "∉"}, // ISOtech
370 {"nb", "⊄"}, // ISOamsr
371 {"nc", "⊅"}, // ISOamsn
372 {"ne", "≢"}, // ISOamsn
373 // Old troff \(sb, \(sp, \(ib, \(ip, \(ca, \(cu go here
374 {"/_", "∠"}, // ISOamso
375 {"pp", "⊥"}, // ISOtech
376 // Old troff \(is goes here
377 {"sum", "∑"}, // ISOamsb
378 {"product", "∏"}, // ISOamsb
379 {"gr", "∇"}, // ISOtech
380 // Old troff \(sr. \{n, \(if go here
381 {"Ah", "ℵ"}, // ISOtech
382 {"Im", "ℑ"}, // ISOamso: Fraktur I, imaginary
383 {"Re", "ℜ"}, // ISOamso: Fraktur R, real
384 {"wp", "℘"}, // ISOamso
385 {"pd", "∂"}, // ISOtech: partial differentiation sign
386 // Their table duplicates the Greek letters here.
387 // We list only the variant forms here, mapping them into
388 // the ISO Greek 4 variants (which may or may not be correct :-()
389 {"+f", "&b.phiv;"}, // ISOgrk4: variant phi
390 {"+h", "&b.thetas;"}, // ISOgrk4: variant theta
391 {"+p", "&b.omega;"}, // ISOgrk4: variant pi, looking like omega
393 {"CL", "♣"}, // ISOpub: club suit
394 {"SP", "♠"}, // ISOpub: spade suit
395 {"HE", "♥"}, // ISOpub: heart suit
396 {"DI", "♦"}, // ISOpub: diamond suit
399 const char *special_to_entity(const char *sp
)
402 for (mp
= entity_table
; mp
< entity_table
+ NELEM(entity_table
); ++mp
)
403 if (!strcmp(mp
->from
, sp
))
416 char_box(unsigned char);
420 int left_is_italic();
421 int right_is_italic();
423 void handle_char_type(int, int);
426 class special_char_box
432 special_char_box(const char *);
437 void handle_char_type(int, int);
452 const char *spacing_type_table
[] = { // FIXME const
465 const int DIGIT_TYPE
= 0;
466 const int LETTER_TYPE
= 1;
468 const char *font_type_table
[] = { // FIXME const
482 char_info::char_info()
483 : spacing_type(ORDINARY_TYPE
), font_type(DIGIT_TYPE
)
487 static char_info char_table
[256];
489 declare_ptable(char_info
)
490 implement_ptable(char_info
)
492 PTABLE(char_info
) special_char_table
;
494 static int get_special_char_spacing_type(const char *ch
)
496 char_info
*p
= special_char_table
.lookup(ch
);
497 return p
? p
->spacing_type
: ORDINARY_TYPE
;
500 static int get_special_char_font_type(const char *ch
)
502 char_info
*p
= special_char_table
.lookup(ch
);
503 return p
? p
->font_type
: DIGIT_TYPE
;
506 static void set_special_char_type(const char *ch
, int st
, int ft
)
508 char_info
*p
= special_char_table
.lookup(ch
);
510 p
= new char_info
[1];
511 special_char_table
.define(ch
, p
);
514 p
->spacing_type
= st
;
519 void init_char_table()
521 set_special_char_type("pl", s_binary
, -1);
522 set_special_char_type("mi", s_binary
, -1);
523 set_special_char_type("eq", s_relation
, -1);
524 set_special_char_type("<=", s_relation
, -1);
525 set_special_char_type(">=", s_relation
, -1);
526 char_table
['}'].spacing_type
= s_closing
;
527 char_table
[')'].spacing_type
= s_closing
;
528 char_table
[']'].spacing_type
= s_closing
;
529 char_table
['{'].spacing_type
= s_opening
;
530 char_table
['('].spacing_type
= s_opening
;
531 char_table
['['].spacing_type
= s_opening
;
532 char_table
[','].spacing_type
= s_punctuation
;
533 char_table
[';'].spacing_type
= s_punctuation
;
534 char_table
[':'].spacing_type
= s_punctuation
;
535 char_table
['.'].spacing_type
= s_punctuation
;
536 char_table
['>'].spacing_type
= s_relation
;
537 char_table
['<'].spacing_type
= s_relation
;
538 char_table
['*'].spacing_type
= s_binary
;
539 for (int i
= 0; i
< 256; i
++)
541 char_table
[i
].font_type
= LETTER_TYPE
;
544 static int lookup_spacing_type(const char *type
)
546 for (int i
= 0; spacing_type_table
[i
] != 0; i
++)
547 if (strcmp(spacing_type_table
[i
], type
) == 0)
552 static int lookup_font_type(const char *type
)
554 for (int i
= 0; font_type_table
[i
] != 0; i
++)
555 if (strcmp(font_type_table
[i
], type
) == 0)
560 void box::set_spacing_type(char *type
)
562 int t
= lookup_spacing_type(type
);
564 error("unrecognised type `%1'", type
);
570 char_box::char_box(unsigned char cc
)
571 : c(cc
), next_is_italic(0), prev_is_italic(0)
573 spacing_type
= char_table
[c
].spacing_type
;
576 void char_box::hint(unsigned flags
)
578 if (flags
& HINT_PREV_IS_ITALIC
)
580 if (flags
& HINT_NEXT_IS_ITALIC
)
584 void char_box::output()
586 if (output_format
== troff
) {
587 int font_type
= char_table
[c
].font_type
;
588 if (font_type
!= LETTER_TYPE
)
589 printf("\\f[%s]", current_roman_font
);
591 fputs("\\,", stdout
);
593 fputs("\\e", stdout
);
597 fputs("\\/", stdout
);
599 fputs("\\&", stdout
); // suppress ligaturing and kerning
600 if (font_type
!= LETTER_TYPE
)
601 fputs("\\fP", stdout
);
603 else if (output_format
== mathml
) {
606 else if (char_table
[c
].spacing_type
)
620 else if (char_table
[c
].spacing_type
)
627 int char_box::left_is_italic()
629 int font_type
= char_table
[c
].font_type
;
630 return font_type
== LETTER_TYPE
;
633 int char_box::right_is_italic()
635 int font_type
= char_table
[c
].font_type
;
636 return font_type
== LETTER_TYPE
;
639 int char_box::is_char()
644 void char_box::debug_print()
654 special_char_box::special_char_box(const char *t
)
657 spacing_type
= get_special_char_spacing_type(s
);
660 special_char_box::~special_char_box()
665 void special_char_box::output()
667 if (output_format
== troff
) {
668 int font_type
= get_special_char_font_type(s
);
669 if (font_type
!= LETTER_TYPE
)
670 printf("\\f[%s]", current_roman_font
);
671 printf("\\,\\[%s]\\/", s
);
672 if (font_type
!= LETTER_TYPE
)
675 else if (output_format
== mathml
) {
676 const char *entity
= special_to_entity(s
);
678 printf("<mo>%s</mo>", entity
);
680 printf("<merror>unknown eqn/troff special char %s</merror>", s
);
684 int special_char_box::is_char()
689 void special_char_box::debug_print()
691 fprintf(stderr
, "\\[%s]", s
);
694 void char_box::handle_char_type(int st
, int ft
)
697 char_table
[c
].spacing_type
= st
;
699 char_table
[c
].font_type
= ft
;
702 void special_char_box::handle_char_type(int st
, int ft
)
704 set_special_char_type(s
, st
, ft
);
707 void set_char_type(const char *type
, char *ch
)
710 int st
= lookup_spacing_type(type
);
711 int ft
= lookup_font_type(type
);
712 if (st
< 0 && ft
< 0) {
713 error("bad character type `%1'", type
);
717 box
*b
= split_text(ch
);
718 b
->handle_char_type(st
, ft
);
722 /* We give primes special treatment so that in ``x' sub 2'', the ``2''
723 will be tucked under the prime */
733 int compute_metrics(int style
);
735 void compute_subscript_kern();
737 void handle_char_type(int, int);
740 box
*make_prime_box(box
*pp
)
742 return new prime_box(pp
);
745 prime_box::prime_box(box
*pp
) : pointer_box(pp
)
747 pb
= new special_char_box("fm");
750 prime_box::~prime_box()
755 int prime_box::compute_metrics(int style
)
757 int res
= p
->compute_metrics(style
);
758 pb
->compute_metrics(style
);
759 printf(".nr " WIDTH_FORMAT
" 0\\n[" WIDTH_FORMAT
"]"
760 "+\\n[" WIDTH_FORMAT
"]\n",
761 uid
, p
->uid
, pb
->uid
);
762 printf(".nr " HEIGHT_FORMAT
" \\n[" HEIGHT_FORMAT
"]"
763 ">?\\n[" HEIGHT_FORMAT
"]\n",
764 uid
, p
->uid
, pb
->uid
);
765 printf(".nr " DEPTH_FORMAT
" \\n[" DEPTH_FORMAT
"]"
766 ">?\\n[" DEPTH_FORMAT
"]\n",
767 uid
, p
->uid
, pb
->uid
);
771 void prime_box::compute_subscript_kern()
773 p
->compute_subscript_kern();
774 printf(".nr " SUB_KERN_FORMAT
" 0\\n[" WIDTH_FORMAT
"]"
775 "+\\n[" SUB_KERN_FORMAT
"]>?0\n",
776 uid
, pb
->uid
, p
->uid
);
779 void prime_box::output()
785 void prime_box::handle_char_type(int st
, int ft
)
787 p
->handle_char_type(st
, ft
);
788 pb
->handle_char_type(st
, ft
);
791 void prime_box::debug_print()
797 box
*split_text(char *text
)
807 b
= new special_char_box("pl");
810 b
= new special_char_box("mi");
813 b
= new special_char_box("eq");
816 b
= new special_char_box("fm");
820 b
= new special_char_box("<=");
827 b
= new special_char_box(">=");
834 lex_error("bad escape");
847 b
= new special_char_box(buf
);
850 lex_error("bad escape");
854 lex_error("bad escape");
861 while (*s
!= ']' && *s
!= '\0')
864 lex_error("bad escape");
867 b
= new special_char_box(ch
);
877 char *escape_start
= s
- 2;
884 for (++s
; *s
!= '\0' && *s
!= ']'; s
++)
889 lex_error("bad escape");
892 char *buf
= new char[s
- escape_start
+ 1];
893 memcpy(buf
, escape_start
, s
- escape_start
);
894 buf
[s
- escape_start
] = '\0';
895 b
= new quoted_text_box(buf
);
905 b
= new special_char_box(buf
);
909 b
= new special_char_box("ga");
912 b
= new special_char_box("aa");
916 b
= new char_box('\\');
926 b
= new quoted_text_box(strsave(buf
));
930 lex_error("unquoted escape");
931 b
= new quoted_text_box(strsave(s
- 2));
943 b
= new quoted_text_box(0);
944 b
= new prime_box(b
);
951 lb
= new list_box(fb
);
964 return new quoted_text_box(0);