No empty .Rs/.Re
[netbsd-mini2440.git] / gnu / dist / groff / src / preproc / eqn / text.cpp
blobdbd5e2ad0e5462b553d4d74441ed28617baaf3ca
1 /* $NetBSD$ */
3 // -*- C++ -*-
4 /* Copyright (C) 1989, 1990, 1991, 1992, 2003 Free Software Foundation, Inc.
5 Written by James Clark (jjc@jclark.com)
7 This file is part of groff.
9 groff is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 2, or (at your option) any later
12 version.
14 groff is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
19 You should have received a copy of the GNU General Public License along
20 with groff; see the file COPYING. If not, write to the Free Software
21 Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
23 #include "eqn.h"
24 #include "pbox.h"
25 #include "ptable.h"
27 class char_box : public simple_box {
28 unsigned char c;
29 char next_is_italic;
30 char prev_is_italic;
31 public:
32 char_box(unsigned char);
33 void debug_print();
34 void output();
35 int is_char();
36 int left_is_italic();
37 int right_is_italic();
38 void hint(unsigned);
39 void handle_char_type(int, int);
42 class special_char_box : public simple_box {
43 char *s;
44 public:
45 special_char_box(const char *);
46 ~special_char_box();
47 void output();
48 void debug_print();
49 int is_char();
50 void handle_char_type(int, int);
53 const char *spacing_type_table[] = {
54 "ordinary",
55 "operator",
56 "binary",
57 "relation",
58 "opening",
59 "closing",
60 "punctuation",
61 "inner",
62 "suppress",
66 const int DIGIT_TYPE = 0;
67 const int LETTER_TYPE = 1;
69 const char *font_type_table[] = {
70 "digit",
71 "letter",
75 struct char_info {
76 int spacing_type;
77 int font_type;
78 char_info();
81 char_info::char_info()
82 : spacing_type(ORDINARY_TYPE), font_type(DIGIT_TYPE)
86 static char_info char_table[256];
88 declare_ptable(char_info)
89 implement_ptable(char_info)
91 PTABLE(char_info) special_char_table;
93 static int get_special_char_spacing_type(const char *ch)
95 char_info *p = special_char_table.lookup(ch);
96 return p ? p->spacing_type : ORDINARY_TYPE;
99 static int get_special_char_font_type(const char *ch)
101 char_info *p = special_char_table.lookup(ch);
102 return p ? p->font_type : DIGIT_TYPE;
105 static void set_special_char_type(const char *ch, int st, int ft)
107 char_info *p = special_char_table.lookup(ch);
108 if (!p) {
109 p = new char_info[1];
110 special_char_table.define(ch, p);
112 if (st >= 0)
113 p->spacing_type = st;
114 if (ft >= 0)
115 p->font_type = ft;
118 void init_char_table()
120 set_special_char_type("pl", 2, -1); // binary
121 set_special_char_type("mi", 2, -1);
122 set_special_char_type("eq", 3, -1); // relation
123 set_special_char_type("<=", 3, -1);
124 set_special_char_type(">=", 3, -1);
125 char_table['}'].spacing_type = 5; // closing
126 char_table[')'].spacing_type = 5;
127 char_table[']'].spacing_type = 5;
128 char_table['{'].spacing_type = 4; // opening
129 char_table['('].spacing_type = 4;
130 char_table['['].spacing_type = 4;
131 char_table[','].spacing_type = 6; // punctuation
132 char_table[';'].spacing_type = 6;
133 char_table[':'].spacing_type = 6;
134 char_table['.'].spacing_type = 6;
135 char_table['>'].spacing_type = 3;
136 char_table['<'].spacing_type = 3;
137 char_table['*'].spacing_type = 2; // binary
138 for (int i = 0; i < 256; i++)
139 if (csalpha(i))
140 char_table[i].font_type = LETTER_TYPE;
143 static int lookup_spacing_type(const char *type)
145 for (int i = 0; spacing_type_table[i] != 0; i++)
146 if (strcmp(spacing_type_table[i], type) == 0)
147 return i;
148 return -1;
151 static int lookup_font_type(const char *type)
153 for (int i = 0; font_type_table[i] != 0; i++)
154 if (strcmp(font_type_table[i], type) == 0)
155 return i;
156 return -1;
159 void box::set_spacing_type(char *type)
161 int t = lookup_spacing_type(type);
162 if (t < 0)
163 error("unrecognised type `%1'", type);
164 else
165 spacing_type = t;
166 a_delete type;
169 char_box::char_box(unsigned char cc)
170 : c(cc), next_is_italic(0), prev_is_italic(0)
172 spacing_type = char_table[c].spacing_type;
175 void char_box::hint(unsigned flags)
177 if (flags & HINT_PREV_IS_ITALIC)
178 prev_is_italic = 1;
179 if (flags & HINT_NEXT_IS_ITALIC)
180 next_is_italic = 1;
183 void char_box::output()
185 int font_type = char_table[c].font_type;
186 if (font_type != LETTER_TYPE)
187 printf("\\f[%s]", current_roman_font);
188 if (!prev_is_italic)
189 fputs("\\,", stdout);
190 if (c == '\\')
191 fputs("\\e", stdout);
192 else
193 putchar(c);
194 if (!next_is_italic)
195 fputs("\\/", stdout);
196 else
197 fputs("\\&", stdout); // suppress ligaturing and kerning
198 if (font_type != LETTER_TYPE)
199 fputs("\\fP", stdout);
202 int char_box::left_is_italic()
204 int font_type = char_table[c].font_type;
205 return font_type == LETTER_TYPE;
208 int char_box::right_is_italic()
210 int font_type = char_table[c].font_type;
211 return font_type == LETTER_TYPE;
214 int char_box::is_char()
216 return 1;
219 void char_box::debug_print()
221 if (c == '\\') {
222 putc('\\', stderr);
223 putc('\\', stderr);
225 else
226 putc(c, stderr);
229 special_char_box::special_char_box(const char *t)
231 s = strsave(t);
232 spacing_type = get_special_char_spacing_type(s);
235 special_char_box::~special_char_box()
237 a_delete s;
240 void special_char_box::output()
242 int font_type = get_special_char_font_type(s);
243 if (font_type != LETTER_TYPE)
244 printf("\\f[%s]", current_roman_font);
245 printf("\\,\\[%s]\\/", s);
246 if (font_type != LETTER_TYPE)
247 printf("\\fP");
250 int special_char_box::is_char()
252 return 1;
255 void special_char_box::debug_print()
257 fprintf(stderr, "\\[%s]", s);
261 void char_box::handle_char_type(int st, int ft)
263 if (st >= 0)
264 char_table[c].spacing_type = st;
265 if (ft >= 0)
266 char_table[c].font_type = ft;
269 void special_char_box::handle_char_type(int st, int ft)
271 set_special_char_type(s, st, ft);
274 void set_char_type(const char *type, char *ch)
276 assert(ch != 0);
277 int st = lookup_spacing_type(type);
278 int ft = lookup_font_type(type);
279 if (st < 0 && ft < 0) {
280 error("bad character type `%1'", type);
281 a_delete ch;
282 return;
284 box *b = split_text(ch);
285 b->handle_char_type(st, ft);
286 delete b;
289 /* We give primes special treatment so that in ``x' sub 2'', the ``2''
290 will be tucked under the prime */
292 class prime_box : public pointer_box {
293 box *pb;
294 public:
295 prime_box(box *);
296 ~prime_box();
297 int compute_metrics(int style);
298 void output();
299 void compute_subscript_kern();
300 void debug_print();
301 void handle_char_type(int, int);
304 box *make_prime_box(box *pp)
306 return new prime_box(pp);
309 prime_box::prime_box(box *pp) : pointer_box(pp)
311 pb = new special_char_box("fm");
314 prime_box::~prime_box()
316 delete pb;
319 int prime_box::compute_metrics(int style)
321 int res = p->compute_metrics(style);
322 pb->compute_metrics(style);
323 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]"
324 "+\\n[" WIDTH_FORMAT "]\n",
325 uid, p->uid, pb->uid);
326 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]"
327 ">?\\n[" HEIGHT_FORMAT "]\n",
328 uid, p->uid, pb->uid);
329 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]"
330 ">?\\n[" DEPTH_FORMAT "]\n",
331 uid, p->uid, pb->uid);
332 return res;
335 void prime_box::compute_subscript_kern()
337 p->compute_subscript_kern();
338 printf(".nr " SUB_KERN_FORMAT " 0\\n[" WIDTH_FORMAT "]"
339 "+\\n[" SUB_KERN_FORMAT "]>?0\n",
340 uid, pb->uid, p->uid);
343 void prime_box::output()
345 p->output();
346 pb->output();
349 void prime_box::handle_char_type(int st, int ft)
351 p->handle_char_type(st, ft);
352 pb->handle_char_type(st, ft);
355 void prime_box::debug_print()
357 p->debug_print();
358 putc('\'', stderr);
361 box *split_text(char *text)
363 list_box *lb = 0;
364 box *fb = 0;
365 char *s = text;
366 while (*s != '\0') {
367 char c = *s++;
368 box *b = 0;
369 switch (c) {
370 case '+':
371 b = new special_char_box("pl");
372 break;
373 case '-':
374 b = new special_char_box("mi");
375 break;
376 case '=':
377 b = new special_char_box("eq");
378 break;
379 case '\'':
380 b = new special_char_box("fm");
381 break;
382 case '<':
383 if (*s == '=') {
384 b = new special_char_box("<=");
385 s++;
386 break;
388 goto normal_char;
389 case '>':
390 if (*s == '=') {
391 b = new special_char_box(">=");
392 s++;
393 break;
395 goto normal_char;
396 case '\\':
397 if (*s == '\0') {
398 lex_error("bad escape");
399 break;
401 c = *s++;
402 switch (c) {
403 case '(':
405 char buf[3];
406 if (*s != '\0') {
407 buf[0] = *s++;
408 if (*s != '\0') {
409 buf[1] = *s++;
410 buf[2] = '\0';
411 b = new special_char_box(buf);
413 else {
414 lex_error("bad escape");
417 else {
418 lex_error("bad escape");
421 break;
422 case '[':
424 char *ch = s;
425 while (*s != ']' && *s != '\0')
426 s++;
427 if (*s == '\0')
428 lex_error("bad escape");
429 else {
430 *s++ = '\0';
431 b = new special_char_box(ch);
434 break;
435 case 'f':
436 case 'g':
437 case 'k':
438 case 'n':
439 case '*':
441 char *escape_start = s - 2;
442 switch (*s) {
443 case '(':
444 if (*++s != '\0')
445 ++s;
446 break;
447 case '[':
448 for (++s; *s != '\0' && *s != ']'; s++)
450 break;
452 if (*s == '\0')
453 lex_error("bad escape");
454 else {
455 ++s;
456 char *buf = new char[s - escape_start + 1];
457 memcpy(buf, escape_start, s - escape_start);
458 buf[s - escape_start] = '\0';
459 b = new quoted_text_box(buf);
462 break;
463 case '-':
464 case '_':
466 char buf[2];
467 buf[0] = c;
468 buf[1] = '\0';
469 b = new special_char_box(buf);
471 break;
472 case '`':
473 b = new special_char_box("ga");
474 break;
475 case '\'':
476 b = new special_char_box("aa");
477 break;
478 case 'e':
479 case '\\':
480 b = new char_box('\\');
481 break;
482 case '^':
483 case '|':
484 case '0':
486 char buf[3];
487 buf[0] = '\\';
488 buf[1] = c;
489 buf[2] = '\0';
490 b = new quoted_text_box(strsave(buf));
491 break;
493 default:
494 lex_error("unquoted escape");
495 b = new quoted_text_box(strsave(s - 2));
496 s = strchr(s, '\0');
497 break;
499 break;
500 default:
501 normal_char:
502 b = new char_box(c);
503 break;
505 while (*s == '\'') {
506 if (b == 0)
507 b = new quoted_text_box(0);
508 b = new prime_box(b);
509 s++;
511 if (b != 0) {
512 if (lb != 0)
513 lb->append(b);
514 else if (fb != 0) {
515 lb = new list_box(fb);
516 lb->append(b);
518 else
519 fb = b;
522 a_delete text;
523 if (lb != 0)
524 return lb;
525 else if (fb != 0)
526 return fb;
527 else
528 return new quoted_text_box(0);