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
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
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. */
27 class char_box
: public simple_box
{
32 char_box(unsigned char);
37 int right_is_italic();
39 void handle_char_type(int, int);
42 class special_char_box
: public simple_box
{
45 special_char_box(const char *);
50 void handle_char_type(int, int);
53 const char *spacing_type_table
[] = {
66 const int DIGIT_TYPE
= 0;
67 const int LETTER_TYPE
= 1;
69 const char *font_type_table
[] = {
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
);
109 p
= new char_info
[1];
110 special_char_table
.define(ch
, p
);
113 p
->spacing_type
= st
;
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
++)
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)
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)
159 void box::set_spacing_type(char *type
)
161 int t
= lookup_spacing_type(type
);
163 error("unrecognised type `%1'", 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
)
179 if (flags
& HINT_NEXT_IS_ITALIC
)
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
);
189 fputs("\\,", stdout
);
191 fputs("\\e", stdout
);
195 fputs("\\/", stdout
);
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()
219 void char_box::debug_print()
229 special_char_box::special_char_box(const char *t
)
232 spacing_type
= get_special_char_spacing_type(s
);
235 special_char_box::~special_char_box()
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
)
250 int special_char_box::is_char()
255 void special_char_box::debug_print()
257 fprintf(stderr
, "\\[%s]", s
);
261 void char_box::handle_char_type(int st
, int ft
)
264 char_table
[c
].spacing_type
= st
;
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
)
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
);
284 box
*b
= split_text(ch
);
285 b
->handle_char_type(st
, ft
);
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
{
297 int compute_metrics(int style
);
299 void compute_subscript_kern();
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()
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
);
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()
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()
361 box
*split_text(char *text
)
371 b
= new special_char_box("pl");
374 b
= new special_char_box("mi");
377 b
= new special_char_box("eq");
380 b
= new special_char_box("fm");
384 b
= new special_char_box("<=");
391 b
= new special_char_box(">=");
398 lex_error("bad escape");
411 b
= new special_char_box(buf
);
414 lex_error("bad escape");
418 lex_error("bad escape");
425 while (*s
!= ']' && *s
!= '\0')
428 lex_error("bad escape");
431 b
= new special_char_box(ch
);
441 char *escape_start
= s
- 2;
448 for (++s
; *s
!= '\0' && *s
!= ']'; s
++)
453 lex_error("bad escape");
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
);
469 b
= new special_char_box(buf
);
473 b
= new special_char_box("ga");
476 b
= new special_char_box("aa");
480 b
= new char_box('\\');
490 b
= new quoted_text_box(strsave(buf
));
494 lex_error("unquoted escape");
495 b
= new quoted_text_box(strsave(s
- 2));
507 b
= new quoted_text_box(0);
508 b
= new prime_box(b
);
515 lb
= new list_box(fb
);
528 return new quoted_text_box(0);