Line data Source code
1 : /* Copyright 1989-2023 Free Software Foundation, Inc.
2 : Written by James Clark (jjc@jclark.com)
3 :
4 : This file is part of groff, the GNU roff typesetting system.
5 :
6 : groff is free software; you can redistribute it and/or modify it under
7 : the terms of the GNU General Public License as published by the Free
8 : Software Foundation, either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : groff is distributed in the hope that it will be useful, but WITHOUT ANY
12 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 :
19 : #ifdef HAVE_CONFIG_H
20 : #include <config.h>
21 : #endif
22 :
23 : #include <stdcountof.h>
24 :
25 : #include <assert.h>
26 :
27 : #include "eqn.h"
28 : #include "pbox.h"
29 :
30 : const char *current_roman_font;
31 :
32 : char *gifont = 0 /* nullptr */;
33 : char *grfont = 0 /* nullptr */;
34 : char *gbfont = 0 /* nullptr */;
35 : int gsize = 0;
36 :
37 : int script_size_reduction = -1; // negative means reduce by a percentage
38 :
39 : int positive_space = -1;
40 : int negative_space = -1;
41 :
42 : int minimum_size = 5;
43 :
44 : static int fat_offset = 4;
45 : static int over_hang = 0;
46 : static int accent_width = 31;
47 : static int delimiter_factor = 900;
48 : static int delimiter_shortfall = 50;
49 :
50 : static int null_delimiter_space = 12;
51 : static int script_space = 5;
52 : static int thin_space = 17;
53 : static int half_space = 17;
54 : static int medium_space = 22;
55 : static int thick_space = 28;
56 : static int full_space = 28;
57 :
58 : static int num1 = 70;
59 : static int num2 = 40;
60 : // we don't use num3, because we don't have \atop
61 : static int denom1 = 70;
62 : static int denom2 = 36;
63 : static int axis_height = 26; // in 100ths of an em
64 : static int sup1 = 42;
65 : static int sup2 = 37;
66 : static int sup3 = 28;
67 : static int default_rule_thickness = 4;
68 : static int sub1 = 20;
69 : static int sub2 = 23;
70 : static int sup_drop = 38;
71 : static int sub_drop = 5;
72 : static int x_height = 45;
73 : static int big_op_spacing1 = 11;
74 : static int big_op_spacing2 = 17;
75 : static int big_op_spacing3 = 20;
76 : static int big_op_spacing4 = 60;
77 : static int big_op_spacing5 = 10;
78 :
79 : // These are for piles and matrices.
80 :
81 : static int baseline_sep = 140; // = num1 + denom1
82 : static int shift_down = 26; // = axis_height
83 : static int column_sep = 100; // = em space
84 : static int matrix_side_sep = 17; // = thin space
85 :
86 : static int body_height = 85;
87 : static int body_depth = 35;
88 :
89 : static int nroff = 0; // should we grok ndefine or tdefine?
90 :
91 : struct param {
92 : const char *name;
93 : int *ptr;
94 : } default_param_table[] = {
95 : { "fat_offset", &fat_offset },
96 : { "over_hang", &over_hang },
97 : { "accent_width", &accent_width },
98 : { "delimiter_factor", &delimiter_factor },
99 : { "delimiter_shortfall", &delimiter_shortfall },
100 : { "null_delimiter_space", &null_delimiter_space },
101 : { "script_space", &script_space },
102 : { "thin_space", &thin_space },
103 : { "medium_space", &medium_space },
104 : { "thick_space", &thick_space },
105 : { "half_space", &half_space },
106 : { "full_space", &full_space },
107 : { "num1", &num1 },
108 : { "num2", &num2 },
109 : { "denom1", &denom1 },
110 : { "denom2", &denom2 },
111 : { "axis_height", &axis_height },
112 : { "sup1", ¹ },
113 : { "sup2", ² },
114 : { "sup3", ³ },
115 : { "default_rule_thickness", &default_rule_thickness },
116 : { "sub1", &sub1 },
117 : { "sub2", &sub2 },
118 : { "sup_drop", &sup_drop },
119 : { "sub_drop", &sub_drop },
120 : { "x_height", &x_height },
121 : { "big_op_spacing1", &big_op_spacing1 },
122 : { "big_op_spacing2", &big_op_spacing2 },
123 : { "big_op_spacing3", &big_op_spacing3 },
124 : { "big_op_spacing4", &big_op_spacing4 },
125 : { "big_op_spacing5", &big_op_spacing5 },
126 : { "minimum_size", &minimum_size },
127 : { "baseline_sep", &baseline_sep },
128 : { "shift_down", &shift_down },
129 : { "column_sep", &column_sep },
130 : { "matrix_side_sep", &matrix_side_sep },
131 : { "draw_lines", &draw_flag },
132 : { "body_height", &body_height },
133 : { "body_depth", &body_depth },
134 : { "nroff", &nroff },
135 : };
136 :
137 : struct param *param_table = 0 /* nullptr */;
138 :
139 : // Use the size of default_param_table to iterate through both it and
140 : // param_table, because the former is known constant to the compiler.
141 :
142 22 : void set_param(const char *name, int value)
143 : {
144 798 : for (size_t i = 0; i <= countof(default_param_table); i++)
145 798 : if (strcmp(param_table[i].name, name) == 0) {
146 22 : *(param_table[i].ptr) = value;
147 22 : return;
148 : }
149 0 : error("'set' primitive does not recognize parameter name '%1'", name);
150 : }
151 :
152 1 : void reset_param(const char *name)
153 : {
154 9 : for (size_t i = 0; i < countof(default_param_table); i++)
155 9 : if (strcmp(param_table[i].name, name) == 0) {
156 1 : *param_table[i].ptr = *(default_param_table[i].ptr);
157 1 : return;
158 : }
159 0 : error("'reset' primitive does not recognize parameter name '%1'",
160 0 : name);
161 : }
162 :
163 1365 : int get_param(const char *name)
164 : {
165 21247 : for (size_t i = 0; i < countof(default_param_table); i++)
166 21247 : if (strcmp(param_table[i].name, name) == 0)
167 1365 : return *(param_table[i].ptr);
168 0 : assert(0 == "attempted to access parameter not in table");
169 : fatal("internal error: unrecognized parameter name '%1'", name);
170 : }
171 :
172 59 : void init_param_table()
173 : {
174 59 : param_table = new param[countof(default_param_table)];
175 2419 : for (size_t i = 0; i < countof(default_param_table); i++) {
176 2360 : param_table[i].name = default_param_table[i].name;
177 2360 : param_table[i].ptr = new int(*(default_param_table[i].ptr));
178 : }
179 59 : }
180 :
181 59 : void free_param_table()
182 : {
183 59 : if (param_table != 0 /* nullptr */) {
184 2419 : for (size_t i = 0; i < countof(default_param_table); i++)
185 2360 : delete param_table[i].ptr;
186 59 : delete[] param_table;
187 59 : param_table = 0 /* nullptr */;
188 : }
189 59 : }
190 :
191 197 : int script_style(int style)
192 : {
193 197 : return style > SCRIPT_STYLE ? style - 2 : style;
194 : }
195 :
196 182 : int cramped_style(int style)
197 : {
198 182 : return (style & 1) ? style - 1 : style;
199 : }
200 :
201 4 : void set_space(int n)
202 : {
203 4 : if (n < 0)
204 0 : negative_space = -n;
205 : else
206 4 : positive_space = n;
207 4 : }
208 :
209 : // Return 0 if the specified size is bad.
210 : // The caller is responsible for giving the error message.
211 :
212 3 : int set_gsize(const char *s)
213 : {
214 3 : const char *p = (*s == '+' || *s == '-') ? s + 1 : s;
215 : char *end;
216 3 : long n = strtol(p, &end, 10);
217 3 : if (n <= 0 || *end != '\0' || n > INT_MAX)
218 0 : return 0;
219 3 : if (p > s) {
220 2 : if (!gsize)
221 0 : gsize = 10;
222 2 : if (*s == '+') {
223 1 : if (gsize > INT_MAX - n)
224 0 : return 0;
225 1 : gsize += int(n);
226 : }
227 : else {
228 1 : if (gsize - n <= 0)
229 0 : return 0;
230 1 : gsize -= int(n);
231 : }
232 : }
233 : else
234 1 : gsize = int(n);
235 3 : return 1;
236 : }
237 :
238 0 : void set_script_reduction(int n)
239 : {
240 0 : script_size_reduction = n;
241 0 : }
242 :
243 368 : const char *get_gifont()
244 : {
245 368 : return gifont ? gifont : "I";
246 : }
247 :
248 393 : const char *get_grfont()
249 : {
250 393 : return grfont ? grfont : "R";
251 : }
252 :
253 0 : const char *get_gbfont()
254 : {
255 0 : return gbfont ? gbfont : "B";
256 : }
257 :
258 0 : void set_gifont(const char *s)
259 : {
260 0 : delete[] gifont;
261 0 : gifont = strsave(s);
262 0 : }
263 :
264 0 : void set_grfont(const char *s)
265 : {
266 0 : delete[] grfont;
267 0 : grfont = strsave(s);
268 0 : }
269 :
270 0 : void set_gbfont(const char *s)
271 : {
272 0 : delete[] gbfont;
273 0 : gbfont = strsave(s);
274 0 : }
275 :
276 : // this must be precisely 2 characters in length
277 : #define COMPATIBLE_REG "0C"
278 :
279 4066 : void start_string()
280 : {
281 4066 : if (output_format == troff) {
282 4066 : printf(".nr " COMPATIBLE_REG " \\n(.C\n");
283 4066 : printf(".cp 0\n");
284 4066 : printf(".ds " LINE_STRING "\n");
285 : }
286 4066 : }
287 :
288 177 : void output_string()
289 : {
290 177 : if (output_format == troff)
291 177 : printf("\\*(" LINE_STRING "\n");
292 0 : else if (output_format == mathml && !xhtml)
293 0 : putchar('\n');
294 177 : }
295 :
296 4065 : void restore_compatibility()
297 : {
298 4065 : if (output_format == troff)
299 4065 : printf(".cp \\n(" COMPATIBLE_REG "\n");
300 4065 : }
301 :
302 298 : void do_text(const char *s)
303 : {
304 298 : if (output_format == troff) {
305 298 : printf(".eo\n");
306 298 : printf(".as " LINE_STRING " \"%s\n", s);
307 298 : printf(".ec\n");
308 : }
309 0 : else if (output_format == mathml) {
310 0 : fputs(s, stdout);
311 0 : if (xhtml && strlen(s) > 0)
312 0 : printf("\n");
313 : }
314 298 : }
315 :
316 0 : void set_minimum_size(int n)
317 : {
318 0 : minimum_size = n;
319 0 : }
320 :
321 181 : void set_script_size()
322 : {
323 181 : if (minimum_size < 0)
324 0 : minimum_size = 0;
325 181 : if (script_size_reduction >= 0)
326 0 : printf(".ps \\n[.s]-%d>?%d\n", script_size_reduction, minimum_size);
327 : else
328 181 : printf(".ps (u;\\n[.ps]*7+5/10>?%dz)\n", minimum_size);
329 181 : }
330 :
331 : int box::next_uid = 0;
332 :
333 1786 : box::box() : spacing_type(ORDINARY_TYPE), uid(next_uid++)
334 : {
335 1786 : }
336 :
337 1786 : box::~box()
338 : {
339 1786 : }
340 :
341 184 : void box::top_level()
342 : {
343 184 : box *b = this;
344 184 : if (output_format == troff) {
345 : // debug_print();
346 : // putc('\n', stderr);
347 184 : printf(".nr " SAVED_FONT_REG " \\n[.f]\n");
348 184 : printf(".ft\n");
349 184 : printf(".nr " SAVED_PREV_FONT_REG " \\n[.f]\n");
350 184 : printf(".ft %s\n", get_gifont());
351 184 : printf(".nr " SAVED_SIZE_REG " \\n[.ps]\n");
352 184 : if (gsize > 0) {
353 : char buf[INT_DIGITS + 1];
354 106 : sprintf(buf, "%d", gsize);
355 106 : b = new size_box(strsave(buf), b);
356 : }
357 184 : current_roman_font = get_grfont();
358 : // This catches tabs used within \Z (which aren't allowed).
359 184 : b->diagnose_tab_stop_usage(0);
360 184 : int r = b->compute_metrics(DISPLAY_STYLE);
361 184 : printf(".ft \\n[" SAVED_PREV_FONT_REG "]\n");
362 184 : printf(".ft \\n[" SAVED_FONT_REG "]\n");
363 184 : printf(".nr " MARK_OR_LINEUP_FLAG_REG " %d\n", r);
364 184 : if (r == FOUND_MARK) {
365 0 : printf(".nr " SAVED_MARK_REG " \\n[" MARK_REG "]\n");
366 0 : printf(".nr " MARK_WIDTH_REG " 0\\n[" WIDTH_FORMAT "]\n", b->uid);
367 : }
368 184 : else if (r == FOUND_LINEUP)
369 0 : printf(".if r" SAVED_MARK_REG " .as1 " LINE_STRING " \\h'\\n["
370 : SAVED_MARK_REG "]u-\\n[" MARK_REG "]u'\n");
371 : else
372 184 : assert(r == FOUND_NOTHING);
373 : // If we use \R directly, the space will prevent it working in a
374 : // macro argument; so we hide it in a string instead.
375 184 : printf(".ds " SAVE_FONT_STRING " "
376 : "\\R'" SAVED_INLINE_FONT_REG " \\En[.f]'"
377 : "\\fP"
378 : "\\R'" SAVED_INLINE_PREV_FONT_REG " \\En[.f]'"
379 : "\\R'" SAVED_INLINE_SIZE_REG " \\En[.ps]'"
380 : "\\s0"
381 : "\\R'" SAVED_INLINE_PREV_SIZE_REG " \\En[.ps]'"
382 : "\n"
383 : ".ds " RESTORE_FONT_STRING " "
384 : "\\f[\\En[" SAVED_INLINE_PREV_FONT_REG "]]"
385 : "\\f[\\En[" SAVED_INLINE_FONT_REG "]]"
386 : "\\s'\\En[" SAVED_INLINE_PREV_SIZE_REG "]u'"
387 : "\\s'\\En[" SAVED_INLINE_SIZE_REG "]u'"
388 : "\n");
389 184 : printf(".as1 " LINE_STRING " \\&\\E*[" SAVE_FONT_STRING "]");
390 184 : printf("\\f[%s]", get_gifont());
391 184 : printf("\\s'\\En[" SAVED_SIZE_REG "]u'");
392 184 : current_roman_font = get_grfont();
393 184 : b->output();
394 184 : printf("\\E*[" RESTORE_FONT_STRING "]\n");
395 184 : if (r == FOUND_LINEUP)
396 0 : printf(".if r" SAVED_MARK_REG " .as1 " LINE_STRING " \\h'\\n["
397 : MARK_WIDTH_REG "]u-\\n[" SAVED_MARK_REG "]u-(\\n["
398 : WIDTH_FORMAT "]u-\\n[" MARK_REG "]u)'\n",
399 0 : b->uid);
400 184 : b->extra_space();
401 184 : if (!inline_flag)
402 32 : printf(".ne \\n[" HEIGHT_FORMAT "]u-%dM>?0+(\\n["
403 : DEPTH_FORMAT "]u-%dM>?0)\n",
404 32 : b->uid, body_height, b->uid, body_depth);
405 : }
406 0 : else if (output_format == mathml) {
407 0 : if (xhtml)
408 0 : printf(".MATHML ");
409 0 : printf("<math>");
410 0 : b->output();
411 0 : printf("</math>");
412 : }
413 184 : delete b;
414 184 : next_uid = 0;
415 184 : }
416 :
417 : // gpic defines this register so as to make geqn not produce '\x's
418 : #define EQN_NO_EXTRA_SPACE_REG "0x"
419 :
420 184 : void box::extra_space()
421 : {
422 184 : printf(".if !r" EQN_NO_EXTRA_SPACE_REG " "
423 : ".nr " EQN_NO_EXTRA_SPACE_REG " 0\n");
424 184 : if (positive_space >= 0 || negative_space >= 0) {
425 4 : if (positive_space > 0)
426 0 : printf(".if !\\n[" EQN_NO_EXTRA_SPACE_REG "] "
427 : ".as1 " LINE_STRING " \\x'-%dM'\n", positive_space);
428 4 : if (negative_space > 0)
429 0 : printf(".if !\\n[" EQN_NO_EXTRA_SPACE_REG "] "
430 : ".as1 " LINE_STRING " \\x'%dM'\n", negative_space);
431 4 : positive_space = negative_space = -1;
432 : }
433 : else {
434 180 : printf(".if !\\n[" EQN_NO_EXTRA_SPACE_REG "] "
435 : ".if \\n[" HEIGHT_FORMAT "]>%dM .as1 " LINE_STRING
436 : " \\x'-(\\n[" HEIGHT_FORMAT
437 : "]u-%dM)'\n",
438 180 : uid, body_height, uid, body_height);
439 180 : printf(".if !\\n[" EQN_NO_EXTRA_SPACE_REG "] "
440 : ".if \\n[" DEPTH_FORMAT "]>%dM .as1 " LINE_STRING
441 : " \\x'\\n[" DEPTH_FORMAT
442 : "]u-%dM'\n",
443 180 : uid, body_depth, uid, body_depth);
444 : }
445 184 : }
446 :
447 0 : int box::compute_metrics(int)
448 : {
449 0 : printf(".nr " WIDTH_FORMAT " 0\n", uid);
450 0 : printf(".nr " HEIGHT_FORMAT " 0\n", uid);
451 0 : printf(".nr " DEPTH_FORMAT " 0\n", uid);
452 0 : return FOUND_NOTHING;
453 : }
454 :
455 0 : void box::compute_subscript_kern()
456 : {
457 0 : printf(".nr " SUB_KERN_FORMAT " 0\n", uid);
458 0 : }
459 :
460 0 : void box::compute_skew()
461 : {
462 0 : printf(".nr " SKEW_FORMAT " 0\n", uid);
463 0 : }
464 :
465 0 : void box::output()
466 : {
467 0 : }
468 :
469 1133 : void box::diagnose_tab_stop_usage(int)
470 : {
471 1133 : }
472 :
473 0 : int box::is_char()
474 : {
475 0 : return 0;
476 : }
477 :
478 244 : int box::left_is_italic()
479 : {
480 244 : return 0;
481 : }
482 :
483 339 : int box::right_is_italic()
484 : {
485 339 : return 0;
486 : }
487 :
488 143 : void box::hint(unsigned)
489 : {
490 143 : }
491 :
492 0 : void box::handle_char_type(int, int)
493 : {
494 0 : }
495 :
496 :
497 282 : box_list::box_list(box *pp)
498 : {
499 282 : p = new box*[10];
500 3102 : for (int i = 0; i < 10; i++)
501 2820 : p[i] = 0;
502 282 : maxlen = 10;
503 282 : len = 1;
504 282 : p[0] = pp;
505 282 : }
506 :
507 823 : void box_list::append(box *pp)
508 : {
509 823 : if (len + 1 > maxlen) {
510 21 : box **oldp = p;
511 21 : maxlen *= 2;
512 21 : p = new box*[maxlen];
513 21 : memcpy(p, oldp, sizeof(box*)*len);
514 21 : delete[] oldp;
515 : }
516 823 : p[len++] = pp;
517 823 : }
518 :
519 564 : box_list::~box_list()
520 : {
521 1240 : for (int i = 0; i < len; i++)
522 958 : delete p[i];
523 282 : delete[] p;
524 282 : }
525 :
526 219 : void box_list::list_diagnose_tab_stop_usage(int level)
527 : {
528 1177 : for (int i = 0; i < len; i++)
529 958 : p[i]->diagnose_tab_stop_usage(level);
530 219 : }
531 :
532 :
533 338 : pointer_box::pointer_box(box *pp) : p(pp)
534 : {
535 338 : spacing_type = p->spacing_type;
536 338 : }
537 :
538 338 : pointer_box::~pointer_box()
539 : {
540 338 : delete p;
541 338 : }
542 :
543 0 : int pointer_box::compute_metrics(int style)
544 : {
545 0 : int r = p->compute_metrics(style);
546 0 : printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
547 0 : printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
548 0 : printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
549 0 : return r;
550 : }
551 :
552 32 : void pointer_box::compute_subscript_kern()
553 : {
554 32 : p->compute_subscript_kern();
555 32 : printf(".nr " SUB_KERN_FORMAT " \\n[" SUB_KERN_FORMAT "]\n", uid,
556 32 : p->uid);
557 32 : }
558 :
559 0 : void pointer_box::compute_skew()
560 : {
561 0 : p->compute_skew();
562 0 : printf(".nr " SKEW_FORMAT " 0\\n[" SKEW_FORMAT "]\n",
563 0 : uid, p->uid);
564 0 : }
565 :
566 163 : void pointer_box::diagnose_tab_stop_usage(int level)
567 : {
568 163 : p->diagnose_tab_stop_usage(level);
569 163 : }
570 :
571 386 : int simple_box::compute_metrics(int)
572 : {
573 386 : printf(".nr " WIDTH_FORMAT " 0\\w" DELIMITER_CHAR, uid);
574 386 : output();
575 386 : printf(DELIMITER_CHAR "\n");
576 386 : printf(".nr " HEIGHT_FORMAT " 0>?\\n[rst]\n", uid);
577 386 : printf(".nr " DEPTH_FORMAT " 0-\\n[rsb]>?0\n", uid);
578 386 : printf(".nr " SUB_KERN_FORMAT " 0-\\n[ssc]>?0\n", uid);
579 386 : printf(".nr " SKEW_FORMAT " 0\\n[skw]\n", uid);
580 386 : return FOUND_NOTHING;
581 : }
582 :
583 181 : void simple_box::compute_subscript_kern()
584 : {
585 : // do nothing, we already computed it in do_metrics
586 181 : }
587 :
588 2 : void simple_box::compute_skew()
589 : {
590 : // do nothing, we already computed it in do_metrics
591 2 : }
592 :
593 998 : int box::is_simple()
594 : {
595 998 : return 0;
596 : }
597 :
598 3942 : int simple_box::is_simple()
599 : {
600 3942 : return 1;
601 : }
602 :
603 26 : quoted_text_box::quoted_text_box(char *s) : text(s)
604 : {
605 26 : }
606 :
607 52 : quoted_text_box::~quoted_text_box()
608 : {
609 26 : free(text);
610 52 : }
611 :
612 52 : void quoted_text_box::output()
613 : {
614 52 : if (text) {
615 52 : if (output_format == troff)
616 52 : fputs(text, stdout);
617 0 : else if (output_format == mathml) {
618 0 : fputs("<mtext>", stdout);
619 0 : fputs(text, stdout);
620 0 : fputs("</mtext>", stdout);
621 : }
622 : }
623 52 : }
624 :
625 0 : tab_box::tab_box() : disabled(false)
626 : {
627 0 : }
628 :
629 : // We treat a tab_box as having width 0 for width computations.
630 :
631 0 : void tab_box::output()
632 : {
633 0 : if (!disabled)
634 0 : printf("\\t");
635 0 : }
636 :
637 0 : void tab_box::diagnose_tab_stop_usage(int level)
638 : {
639 0 : if (level > 0) {
640 0 : error("tabs allowed only at outermost lexical level");
641 0 : disabled = true;
642 : }
643 0 : }
644 :
645 20 : half_space_box::half_space_box()
646 : {
647 20 : spacing_type = SUPPRESS_TYPE;
648 20 : }
649 :
650 40 : void half_space_box::output()
651 : {
652 40 : if (output_format == troff)
653 40 : printf("\\h'%dM'", half_space);
654 0 : else if (output_format == mathml)
655 0 : printf("<mtext> </mtext>");
656 : else
657 : assert("unimplemented output format");
658 40 : }
659 :
660 63 : full_space_box::full_space_box()
661 : {
662 63 : spacing_type = SUPPRESS_TYPE;
663 63 : }
664 :
665 126 : void full_space_box::output()
666 : {
667 126 : if (output_format == troff)
668 126 : printf("\\h'%dM'", full_space);
669 0 : else if (output_format == mathml)
670 0 : printf("<mtext>  </mtext>");
671 : else
672 : assert("unimplemented output format");
673 126 : }
674 :
675 0 : thick_space_box::thick_space_box()
676 : {
677 0 : spacing_type = SUPPRESS_TYPE;
678 0 : }
679 :
680 0 : void thick_space_box::output()
681 : {
682 0 : if (output_format == troff)
683 0 : printf("\\h'%dM'", thick_space);
684 0 : else if (output_format == mathml)
685 0 : printf("<mtext>  </mtext>");
686 : else
687 : assert("unimplemented output format");
688 0 : }
689 :
690 0 : thin_space_box::thin_space_box()
691 : {
692 0 : spacing_type = SUPPRESS_TYPE;
693 0 : }
694 :
695 0 : void thin_space_box::output()
696 : {
697 0 : if (output_format == troff)
698 0 : printf("\\h'%dM'", thin_space);
699 0 : else if (output_format == mathml)
700 0 : printf("<mtext> </mtext>");
701 : else
702 : assert("unimplemented output format");
703 0 : }
704 :
705 0 : void box_list::list_debug_print(const char *sep)
706 : {
707 0 : p[0]->debug_print();
708 0 : for (int i = 1; i < len; i++) {
709 0 : fprintf(stderr, "%s", sep);
710 0 : p[i]->debug_print();
711 : }
712 0 : }
713 :
714 0 : void quoted_text_box::debug_print()
715 : {
716 0 : fprintf(stderr, "\"%s\"", (text ? text : ""));
717 0 : }
718 :
719 0 : void half_space_box::debug_print()
720 : {
721 0 : fprintf(stderr, "^");
722 0 : }
723 :
724 0 : void full_space_box::debug_print()
725 : {
726 0 : fprintf(stderr, "~");
727 0 : }
728 :
729 0 : void thick_space_box::debug_print()
730 : {
731 0 : fprintf(stderr, "~");
732 0 : }
733 :
734 0 : void thin_space_box::debug_print()
735 : {
736 0 : fprintf(stderr, "^");
737 0 : }
738 :
739 0 : void tab_box::debug_print()
740 : {
741 0 : fprintf(stderr, "<tab>");
742 0 : }
743 :
744 : // Local Variables:
745 : // fill-column: 72
746 : // mode: C++
747 : // End:
748 : // vim: set cindent noexpandtab shiftwidth=2 textwidth=72:
|