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. */
24 enum left_or_right_t
{ LEFT_DELIM
= 01, RIGHT_DELIM
= 02 };
26 // Small must be none-zero and must exist in each device.
27 // Small will be put in the roman font, others are assumed to be
28 // on the special font (so no font change will be necessary.)
34 const char *chain_format
;
41 "(", LEFT_DELIM
|RIGHT_DELIM
, "(", "\\[parenleft%s]",
48 ")", LEFT_DELIM
|RIGHT_DELIM
, ")", "\\[parenright%s]",
55 "[", LEFT_DELIM
|RIGHT_DELIM
, "[", "\\[bracketleft%s]",
62 "]", LEFT_DELIM
|RIGHT_DELIM
, "]", "\\[bracketright%s]",
69 "{", LEFT_DELIM
|RIGHT_DELIM
, "{", "\\[braceleft%s]",
76 "}", LEFT_DELIM
|RIGHT_DELIM
, "}", "\\[braceright%s]",
83 "|", LEFT_DELIM
|RIGHT_DELIM
, "|", "\\[bar%s]",
87 "floor", LEFT_DELIM
, "\\(lf", "\\[floorleft%s]",
94 "floor", RIGHT_DELIM
, "\\(rf", "\\[floorright%s]",
101 "ceiling", LEFT_DELIM
, "\\(lc", "\\[ceilingleft%s]",
106 "ceiling", RIGHT_DELIM
, "\\(rc", "\\[ceilingright%s]",
107 "\\[bracketrightex]",
108 "\\[bracketrighttp]",
111 "||", LEFT_DELIM
|RIGHT_DELIM
, "|", "\\[bar%s]",
115 "<", LEFT_DELIM
|RIGHT_DELIM
, "\\(la", "\\[angleleft%s]",
118 ">", LEFT_DELIM
|RIGHT_DELIM
, "\\(ra", "\\[angleright%s]",
121 "uparrow", LEFT_DELIM
|RIGHT_DELIM
, "\\(ua", "\\[arrowup%s]",
126 "downarrow", LEFT_DELIM
|RIGHT_DELIM
, "\\(da", "\\[arrowdown%s]",
133 "updownarrow", LEFT_DELIM
|RIGHT_DELIM
, "\\(va", "\\[arrowupdown%s]",
141 const int DELIM_TABLE_SIZE
= int(sizeof(delim_table
)/sizeof(delim_table
[0]));
143 class delim_box
: public box
{
149 delim_box(char *, box
*, char *);
151 int compute_metrics(int);
153 void check_tabs(int);
157 box
*make_delim_box(char *l
, box
*pp
, char *r
)
159 if (l
!= 0 && *l
== '\0') {
163 if (r
!= 0 && *r
== '\0') {
167 return new delim_box(l
, pp
, r
);
170 delim_box::delim_box(char *l
, box
*pp
, char *r
)
171 : left(l
), right(r
), p(pp
)
175 delim_box::~delim_box()
182 static void build_extensible(const char *ext
, const char *top
, const char *mid
,
186 printf(".nr " DELIM_WIDTH_REG
" 0\\w" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\n",
188 printf(".nr " EXT_HEIGHT_REG
" 0\\n[rst]\n");
189 printf(".nr " EXT_DEPTH_REG
" 0-\\n[rsb]\n");
191 printf(".nr " DELIM_WIDTH_REG
" 0\\n[" DELIM_WIDTH_REG
"]"
192 ">?\\w" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\n",
194 printf(".nr " TOP_HEIGHT_REG
" 0\\n[rst]\n");
195 printf(".nr " TOP_DEPTH_REG
" 0-\\n[rsb]\n");
198 printf(".nr " DELIM_WIDTH_REG
" 0\\n[" DELIM_WIDTH_REG
"]"
199 ">?\\w" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\n",
201 printf(".nr " MID_HEIGHT_REG
" 0\\n[rst]\n");
202 printf(".nr " MID_DEPTH_REG
" 0-\\n[rsb]\n");
205 printf(".nr " DELIM_WIDTH_REG
" 0\\n[" DELIM_WIDTH_REG
"]"
206 ">?\\w" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\n",
208 printf(".nr " BOT_HEIGHT_REG
" 0\\n[rst]\n");
209 printf(".nr " BOT_DEPTH_REG
" 0-\\n[rsb]\n");
211 printf(".nr " TOTAL_HEIGHT_REG
" 0");
213 printf("+\\n[" TOP_HEIGHT_REG
"]+\\n[" TOP_DEPTH_REG
"]");
215 printf("+\\n[" BOT_HEIGHT_REG
"]+\\n[" BOT_DEPTH_REG
"]");
217 printf("+\\n[" MID_HEIGHT_REG
"]+\\n[" MID_DEPTH_REG
"]");
219 // determine how many extensible characters we need
220 printf(".nr " TEMP_REG
" \\n[" DELTA_REG
"]-\\n[" TOTAL_HEIGHT_REG
"]");
223 printf(">?0+\\n[" EXT_HEIGHT_REG
"]+\\n[" EXT_DEPTH_REG
"]-1/(\\n["
224 EXT_HEIGHT_REG
"]+\\n[" EXT_DEPTH_REG
"])\n");
226 printf(".nr " TOTAL_HEIGHT_REG
" +(\\n[" EXT_HEIGHT_REG
"]+\\n["
227 EXT_DEPTH_REG
"]*\\n[" TEMP_REG
"]");
231 printf(".ds " DELIM_STRING
" \\Z" DELIMITER_CHAR
232 "\\v'-%dM-(\\n[" TOTAL_HEIGHT_REG
"]u/2u)'\n",
235 printf(".as " DELIM_STRING
" \\v'\\n[" TOP_HEIGHT_REG
"]u'"
236 "\\Z" DELIMITER_CHAR
"%s" DELIMITER_CHAR
237 "\\v'\\n[" TOP_DEPTH_REG
"]u'\n",
240 // this macro appends $2 copies of $3 to string $1
241 printf(".de " REPEAT_APPEND_STRING_MACRO
"\n"
242 ".if \\\\$2 \\{.as \\\\$1 \"\\\\$3\n"
243 "." REPEAT_APPEND_STRING_MACRO
" \\\\$1 \\\\$2-1 \"\\\\$3\"\n"
247 printf("." REPEAT_APPEND_STRING_MACRO
" " DELIM_STRING
" \\n[" TEMP_REG
"] "
248 "\\v'\\n[" EXT_HEIGHT_REG
"]u'"
249 "\\Z" DELIMITER_CHAR
"%s" DELIMITER_CHAR
250 "\\v'\\n[" EXT_DEPTH_REG
"]u'\n",
254 printf(".as " DELIM_STRING
" \\v'\\n[" MID_HEIGHT_REG
"]u'"
255 "\\Z" DELIMITER_CHAR
"%s" DELIMITER_CHAR
256 "\\v'\\n[" MID_DEPTH_REG
"]u'\n",
258 printf("." REPEAT_APPEND_STRING_MACRO
" " DELIM_STRING
259 " \\n[" TEMP_REG
"] "
260 "\\v'\\n[" EXT_HEIGHT_REG
"]u'"
261 "\\Z" DELIMITER_CHAR
"%s" DELIMITER_CHAR
262 "\\v'\\n[" EXT_DEPTH_REG
"]u'\n",
266 printf(".as " DELIM_STRING
" \\v'\\n[" BOT_HEIGHT_REG
"]u'"
267 "\\Z" DELIMITER_CHAR
"%s" DELIMITER_CHAR
268 "\\v'\\n[" BOT_DEPTH_REG
"]u'\n",
270 printf(".as " DELIM_STRING
" " DELIMITER_CHAR
"\n");
273 static void define_extensible_string(char *delim
, int uid
,
274 left_or_right_t left_or_right
)
276 printf(".ds " DELIM_STRING
"\n");
277 delimiter
*d
= delim_table
;
278 int delim_len
= strlen(delim
);
280 for (i
= 0; i
< DELIM_TABLE_SIZE
; i
++, d
++)
281 if (strncmp(delim
, d
->name
, delim_len
) == 0
282 && (left_or_right
& d
->flags
) != 0)
284 if (i
>= DELIM_TABLE_SIZE
) {
285 error("there is no `%1' delimiter", delim
);
286 printf(".nr " DELIM_WIDTH_REG
" 0\n");
290 printf(".nr " DELIM_WIDTH_REG
" 0\\w" DELIMITER_CHAR
"\\f[%s]%s\\fP" DELIMITER_CHAR
"\n"
291 ".ds " DELIM_STRING
" \\Z" DELIMITER_CHAR
292 "\\v'\\n[rsb]u+\\n[rst]u/2u-%dM'\\f[%s]%s\\fP" DELIMITER_CHAR
"\n"
293 ".nr " TOTAL_HEIGHT_REG
" \\n[rst]-\\n[rsb]\n"
294 ".if \\n[" TOTAL_HEIGHT_REG
"]<\\n[" DELTA_REG
"] "
296 current_roman_font
, d
->small
, axis_height
,
297 current_roman_font
, d
->small
);
300 sprintf(buf
, d
->chain_format
, "\\\\n[" INDEX_REG
"]");
301 printf(".nr " INDEX_REG
" 0\n"
302 ".de " TEMP_MACRO
"\n"
304 ".nr " DELIM_WIDTH_REG
" 0\\w" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\n"
305 ".ds " DELIM_STRING
" \\Z" DELIMITER_CHAR
306 "\\v'\\\\n[rsb]u+\\\\n[rst]u/2u-%dM'%s" DELIMITER_CHAR
"\n"
307 ".nr " TOTAL_HEIGHT_REG
" \\\\n[rst]-\\\\n[rsb]\n"
308 ".if \\\\n[" TOTAL_HEIGHT_REG
"]<\\n[" DELTA_REG
"] "
309 "\\{.nr " INDEX_REG
" +1\n"
312 ".el .nr " INDEX_REG
" 0-1\n"
315 buf
, buf
, axis_height
, buf
);
317 printf(".if \\n[" INDEX_REG
"]<0 \\{.if c%s \\{\\\n", d
->ext
);
318 build_extensible(d
->ext
, d
->top
, d
->mid
, d
->bot
);
322 printf(".as " DELIM_STRING
" \\h'\\n[" DELIM_WIDTH_REG
"]u'\n");
323 printf(".nr " WIDTH_FORMAT
" +\\n[" DELIM_WIDTH_REG
"]\n", uid
);
324 printf(".nr " HEIGHT_FORMAT
" \\n[" HEIGHT_FORMAT
"]"
325 ">?(\\n[" TOTAL_HEIGHT_REG
"]/2+%dM)\n",
326 uid
, uid
, axis_height
);
327 printf(".nr " DEPTH_FORMAT
" \\n[" DEPTH_FORMAT
"]"
328 ">?(\\n[" TOTAL_HEIGHT_REG
"]/2-%dM)\n",
329 uid
, uid
, axis_height
);
332 int delim_box::compute_metrics(int style
)
334 int r
= p
->compute_metrics(style
);
335 printf(".nr " WIDTH_FORMAT
" 0\\n[" WIDTH_FORMAT
"]\n", uid
, p
->uid
);
336 printf(".nr " HEIGHT_FORMAT
" \\n[" HEIGHT_FORMAT
"]\n", uid
, p
->uid
);
337 printf(".nr " DEPTH_FORMAT
" \\n[" DEPTH_FORMAT
"]\n", uid
, p
->uid
);
338 printf(".nr " DELTA_REG
" \\n[" HEIGHT_FORMAT
"]-%dM"
339 ">?(\\n[" DEPTH_FORMAT
"]+%dM)\n",
340 p
->uid
, axis_height
, p
->uid
, axis_height
);
341 printf(".nr " DELTA_REG
" 0\\n[" DELTA_REG
"]*%d/500"
342 ">?(\\n[" DELTA_REG
"]*2-%dM)\n",
343 delimiter_factor
, delimiter_shortfall
);
345 define_extensible_string(left
, uid
, LEFT_DELIM
);
346 printf(".rn " DELIM_STRING
" " LEFT_DELIM_STRING_FORMAT
"\n",
349 printf(".nr " MARK_REG
" +\\n[" DELIM_WIDTH_REG
"]\n");
352 define_extensible_string(right
, uid
, RIGHT_DELIM
);
353 printf(".rn " DELIM_STRING
" " RIGHT_DELIM_STRING_FORMAT
"\n",
359 void delim_box::output()
362 printf("\\*[" LEFT_DELIM_STRING_FORMAT
"]", uid
);
365 printf("\\*[" RIGHT_DELIM_STRING_FORMAT
"]", uid
);
368 void delim_box::check_tabs(int level
)
370 p
->check_tabs(level
);
373 void delim_box::debug_print()
375 fprintf(stderr
, "left \"%s\" { ", left
? left
: "");
377 fprintf(stderr
, " }");
379 fprintf(stderr
, " right \"%s\"", right
);