2 /* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
3 Written by James Clark (jjc@jclark.com)
5 This file is part of groff.
7 groff is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
12 groff is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License along
18 with groff; see the file COPYING. If not, write to the Free Software
19 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
25 class char_box
: public simple_box
{
30 char_box(unsigned char);
35 int right_is_italic();
37 void handle_char_type(int, int);
40 class special_char_box
: public simple_box
{
43 special_char_box(const char *);
48 void handle_char_type(int, int);
51 const char *spacing_type_table
[] = {
64 const int DIGIT_TYPE
= 0;
65 const int LETTER_TYPE
= 1;
67 const char *font_type_table
[] = {
79 char_info::char_info()
80 : spacing_type(ORDINARY_TYPE
), font_type(DIGIT_TYPE
)
84 static char_info char_table
[256];
86 declare_ptable(char_info
)
87 implement_ptable(char_info
)
89 PTABLE(char_info
) special_char_table
;
91 static int get_special_char_spacing_type(const char *ch
)
93 char_info
*p
= special_char_table
.lookup(ch
);
94 return p
? p
->spacing_type
: ORDINARY_TYPE
;
97 static int get_special_char_font_type(const char *ch
)
99 char_info
*p
= special_char_table
.lookup(ch
);
100 return p
? p
->font_type
: DIGIT_TYPE
;
103 static void set_special_char_type(const char *ch
, int st
, int ft
)
105 char_info
*p
= special_char_table
.lookup(ch
);
108 special_char_table
.define(ch
, p
);
111 p
->spacing_type
= st
;
116 void init_char_table()
118 set_special_char_type("pl", 2, -1); // binary
119 set_special_char_type("mi", 2, -1);
120 set_special_char_type("eq", 3, -1); // relation
121 set_special_char_type("<=", 3, -1);
122 set_special_char_type(">=", 3, -1);
123 char_table
['}'].spacing_type
= 5; // closing
124 char_table
[')'].spacing_type
= 5;
125 char_table
[']'].spacing_type
= 5;
126 char_table
['{'].spacing_type
= 4; // opening
127 char_table
['('].spacing_type
= 4;
128 char_table
['['].spacing_type
= 4;
129 char_table
[','].spacing_type
= 6; // punctuation
130 char_table
[';'].spacing_type
= 6;
131 char_table
[':'].spacing_type
= 6;
132 char_table
['.'].spacing_type
= 6;
133 char_table
['>'].spacing_type
= 3;
134 char_table
['<'].spacing_type
= 3;
135 char_table
['*'].spacing_type
= 2; // binary
136 for (int i
= 0; i
< 256; i
++)
138 char_table
[i
].font_type
= LETTER_TYPE
;
141 static int lookup_spacing_type(const char *type
)
143 for (int i
= 0; spacing_type_table
[i
] != 0; i
++)
144 if (strcmp(spacing_type_table
[i
], type
) == 0)
149 static int lookup_font_type(const char *type
)
151 for (int i
= 0; font_type_table
[i
] != 0; i
++)
152 if (strcmp(font_type_table
[i
], type
) == 0)
157 void box::set_spacing_type(char *type
)
159 int t
= lookup_spacing_type(type
);
161 error("unrecognised type `%1'", type
);
167 char_box::char_box(unsigned char cc
)
168 : c(cc
), next_is_italic(0), prev_is_italic(0)
170 spacing_type
= char_table
[c
].spacing_type
;
173 void char_box::hint(unsigned flags
)
175 if (flags
& HINT_PREV_IS_ITALIC
)
177 if (flags
& HINT_NEXT_IS_ITALIC
)
181 void char_box::output()
183 int font_type
= char_table
[c
].font_type
;
184 if (font_type
!= LETTER_TYPE
)
185 printf("\\f[%s]", current_roman_font
);
187 fputs("\\,", stdout
);
189 fputs("\\e", stdout
);
193 fputs("\\/", stdout
);
195 fputs("\\&", stdout
); // suppress ligaturing and kerning
196 if (font_type
!= LETTER_TYPE
)
197 fputs("\\fP", stdout
);
200 int char_box::left_is_italic()
202 int font_type
= char_table
[c
].font_type
;
203 return font_type
== LETTER_TYPE
;
206 int char_box::right_is_italic()
208 int font_type
= char_table
[c
].font_type
;
209 return font_type
== LETTER_TYPE
;
212 int char_box::is_char()
217 void char_box::debug_print()
227 special_char_box::special_char_box(const char *t
)
230 spacing_type
= get_special_char_spacing_type(s
);
233 special_char_box::~special_char_box()
238 void special_char_box::output()
240 int font_type
= get_special_char_font_type(s
);
241 if (font_type
!= LETTER_TYPE
)
242 printf("\\f[%s]", current_roman_font
);
243 printf("\\,\\[%s]\\/", s
);
244 if (font_type
!= LETTER_TYPE
)
248 int special_char_box::is_char()
253 void special_char_box::debug_print()
255 fprintf(stderr
, "\\[%s]", s
);
259 void char_box::handle_char_type(int st
, int ft
)
262 char_table
[c
].spacing_type
= st
;
264 char_table
[c
].font_type
= ft
;
267 void special_char_box::handle_char_type(int st
, int ft
)
269 set_special_char_type(s
, st
, ft
);
272 void set_char_type(const char *type
, char *ch
)
275 int st
= lookup_spacing_type(type
);
276 int ft
= lookup_font_type(type
);
277 if (st
< 0 && ft
< 0) {
278 error("bad character type `%1'", type
);
282 box
*b
= split_text(ch
);
283 b
->handle_char_type(st
, ft
);
287 /* We give primes special treatment so that in ``x' sub 2'', the ``2''
288 will be tucked under the prime */
290 class prime_box
: public pointer_box
{
295 int compute_metrics(int style
);
297 void compute_subscript_kern();
299 void handle_char_type(int, int);
302 box
*make_prime_box(box
*pp
)
304 return new prime_box(pp
);
307 prime_box::prime_box(box
*pp
) : pointer_box(pp
)
309 pb
= new special_char_box("fm");
312 prime_box::~prime_box()
317 int prime_box::compute_metrics(int style
)
319 int res
= p
->compute_metrics(style
);
320 pb
->compute_metrics(style
);
321 printf(".nr " WIDTH_FORMAT
" 0\\n[" WIDTH_FORMAT
"]"
322 "+\\n[" WIDTH_FORMAT
"]\n",
323 uid
, p
->uid
, pb
->uid
);
324 printf(".nr " HEIGHT_FORMAT
" \\n[" HEIGHT_FORMAT
"]"
325 ">?\\n[" HEIGHT_FORMAT
"]\n",
326 uid
, p
->uid
, pb
->uid
);
327 printf(".nr " DEPTH_FORMAT
" \\n[" DEPTH_FORMAT
"]"
328 ">?\\n[" DEPTH_FORMAT
"]\n",
329 uid
, p
->uid
, pb
->uid
);
333 void prime_box::compute_subscript_kern()
335 p
->compute_subscript_kern();
336 printf(".nr " SUB_KERN_FORMAT
" 0\\n[" WIDTH_FORMAT
"]"
337 "+\\n[" SUB_KERN_FORMAT
"]>?0\n",
338 uid
, pb
->uid
, p
->uid
);
341 void prime_box::output()
347 void prime_box::handle_char_type(int st
, int ft
)
349 p
->handle_char_type(st
, ft
);
350 pb
->handle_char_type(st
, ft
);
353 void prime_box::debug_print()
359 box
*split_text(char *text
)
369 b
= new special_char_box("pl");
372 b
= new special_char_box("mi");
375 b
= new special_char_box("eq");
378 b
= new special_char_box("fm");
382 b
= new special_char_box("<=");
389 b
= new special_char_box(">=");
396 lex_error("bad escape");
409 b
= new special_char_box(buf
);
412 lex_error("bad escape");
416 lex_error("bad escape");
423 while (*s
!= ']' && *s
!= '\0')
426 lex_error("bad escape");
429 b
= new special_char_box(ch
);
439 char *escape_start
= s
- 2;
446 for (++s
; *s
!= '\0' && *s
!= ']'; s
++)
451 lex_error("bad escape");
454 char *buf
= new char[s
- escape_start
+ 1];
455 memcpy(buf
, escape_start
, s
- escape_start
);
456 buf
[s
- escape_start
] = '\0';
457 b
= new quoted_text_box(buf
);
467 b
= new special_char_box(buf
);
471 b
= new special_char_box("ga");
474 b
= new special_char_box("aa");
478 b
= new char_box('\\');
488 b
= new quoted_text_box(strsave(buf
));
492 lex_error("unquoted escape");
493 b
= new quoted_text_box(strsave(s
- 2));
505 b
= new quoted_text_box(0);
506 b
= new prime_box(b
);
513 lb
= new list_box(fb
);
526 return new quoted_text_box(0);