2 /* Copyright (C) 1989, 1990, 1991, 1992, 2003 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, 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]",
90 "floor", LEFT_DELIM
, "\\(lf", "\\[floorleft%s]",
97 "floor", RIGHT_DELIM
, "\\(rf", "\\[floorright%s]",
101 "\\[bracketrightbt]",
104 "ceiling", LEFT_DELIM
, "\\(lc", "\\[ceilingleft%s]",
111 "ceiling", RIGHT_DELIM
, "\\(rc", "\\[ceilingright%s]",
112 "\\[bracketrightex]",
113 "\\[bracketrighttp]",
118 "||", LEFT_DELIM
|RIGHT_DELIM
, "|", "\\[bar%s]",
125 "<", LEFT_DELIM
|RIGHT_DELIM
, "\\(la", "\\[angleleft%s]",
132 ">", LEFT_DELIM
|RIGHT_DELIM
, "\\(ra", "\\[angleright%s]",
139 "uparrow", LEFT_DELIM
|RIGHT_DELIM
, "\\(ua", "\\[arrowup%s]",
146 "downarrow", LEFT_DELIM
|RIGHT_DELIM
, "\\(da", "\\[arrowdown%s]",
153 "updownarrow", LEFT_DELIM
|RIGHT_DELIM
, "\\(va", "\\[arrowupdown%s]",
161 const int DELIM_TABLE_SIZE
= int(sizeof(delim_table
)/sizeof(delim_table
[0]));
163 class delim_box
: public box
{
169 delim_box(char *, box
*, char *);
171 int compute_metrics(int);
173 void check_tabs(int);
177 box
*make_delim_box(char *l
, box
*pp
, char *r
)
179 if (l
!= 0 && *l
== '\0') {
183 if (r
!= 0 && *r
== '\0') {
187 return new delim_box(l
, pp
, r
);
190 delim_box::delim_box(char *l
, box
*pp
, char *r
)
191 : left(l
), right(r
), p(pp
)
195 delim_box::~delim_box()
202 static void build_extensible(const char *ext
, const char *top
, const char *mid
,
206 printf(".nr " DELIM_WIDTH_REG
" 0\\w" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\n",
208 printf(".nr " EXT_HEIGHT_REG
" 0\\n[rst]\n");
209 printf(".nr " EXT_DEPTH_REG
" 0-\\n[rsb]\n");
211 printf(".nr " DELIM_WIDTH_REG
" 0\\n[" DELIM_WIDTH_REG
"]"
212 ">?\\w" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\n",
214 printf(".nr " TOP_HEIGHT_REG
" 0\\n[rst]\n");
215 printf(".nr " TOP_DEPTH_REG
" 0-\\n[rsb]\n");
218 printf(".nr " DELIM_WIDTH_REG
" 0\\n[" DELIM_WIDTH_REG
"]"
219 ">?\\w" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\n",
221 printf(".nr " MID_HEIGHT_REG
" 0\\n[rst]\n");
222 printf(".nr " MID_DEPTH_REG
" 0-\\n[rsb]\n");
225 printf(".nr " DELIM_WIDTH_REG
" 0\\n[" DELIM_WIDTH_REG
"]"
226 ">?\\w" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\n",
228 printf(".nr " BOT_HEIGHT_REG
" 0\\n[rst]\n");
229 printf(".nr " BOT_DEPTH_REG
" 0-\\n[rsb]\n");
231 printf(".nr " TOTAL_HEIGHT_REG
" 0");
233 printf("+\\n[" TOP_HEIGHT_REG
"]+\\n[" TOP_DEPTH_REG
"]");
235 printf("+\\n[" BOT_HEIGHT_REG
"]+\\n[" BOT_DEPTH_REG
"]");
237 printf("+\\n[" MID_HEIGHT_REG
"]+\\n[" MID_DEPTH_REG
"]");
239 // determine how many extensible characters we need
240 printf(".nr " TEMP_REG
" \\n[" DELTA_REG
"]-\\n[" TOTAL_HEIGHT_REG
"]");
243 printf(">?0+\\n[" EXT_HEIGHT_REG
"]+\\n[" EXT_DEPTH_REG
"]-1/(\\n["
244 EXT_HEIGHT_REG
"]+\\n[" EXT_DEPTH_REG
"])\n");
246 printf(".nr " TOTAL_HEIGHT_REG
" +(\\n[" EXT_HEIGHT_REG
"]+\\n["
247 EXT_DEPTH_REG
"]*\\n[" TEMP_REG
"]");
251 printf(".ds " DELIM_STRING
" \\Z" DELIMITER_CHAR
252 "\\v'-%dM-(\\n[" TOTAL_HEIGHT_REG
"]u/2u)'\n",
255 printf(".as " DELIM_STRING
" \\v'\\n[" TOP_HEIGHT_REG
"]u'"
256 "\\Z" DELIMITER_CHAR
"%s" DELIMITER_CHAR
257 "\\v'\\n[" TOP_DEPTH_REG
"]u'\n",
260 // this macro appends $2 copies of $3 to string $1
261 printf(".de " REPEAT_APPEND_STRING_MACRO
"\n"
262 ".if \\\\$2 \\{.as \\\\$1 \"\\\\$3\n"
263 "." REPEAT_APPEND_STRING_MACRO
" \\\\$1 \\\\$2-1 \"\\\\$3\"\n"
267 printf("." REPEAT_APPEND_STRING_MACRO
" " DELIM_STRING
" \\n[" TEMP_REG
"] "
268 "\\v'\\n[" EXT_HEIGHT_REG
"]u'"
269 "\\Z" DELIMITER_CHAR
"%s" DELIMITER_CHAR
270 "\\v'\\n[" EXT_DEPTH_REG
"]u'\n",
274 printf(".as " DELIM_STRING
" \\v'\\n[" MID_HEIGHT_REG
"]u'"
275 "\\Z" DELIMITER_CHAR
"%s" DELIMITER_CHAR
276 "\\v'\\n[" MID_DEPTH_REG
"]u'\n",
278 printf("." REPEAT_APPEND_STRING_MACRO
" " DELIM_STRING
279 " \\n[" TEMP_REG
"] "
280 "\\v'\\n[" EXT_HEIGHT_REG
"]u'"
281 "\\Z" DELIMITER_CHAR
"%s" DELIMITER_CHAR
282 "\\v'\\n[" EXT_DEPTH_REG
"]u'\n",
286 printf(".as " DELIM_STRING
" \\v'\\n[" BOT_HEIGHT_REG
"]u'"
287 "\\Z" DELIMITER_CHAR
"%s" DELIMITER_CHAR
288 "\\v'\\n[" BOT_DEPTH_REG
"]u'\n",
290 printf(".as " DELIM_STRING
" " DELIMITER_CHAR
"\n");
293 static void define_extensible_string(char *delim
, int uid
,
294 left_or_right_t left_or_right
)
296 printf(".ds " DELIM_STRING
"\n");
297 delimiter
*d
= delim_table
;
298 int delim_len
= strlen(delim
);
300 for (i
= 0; i
< DELIM_TABLE_SIZE
; i
++, d
++)
301 if (strncmp(delim
, d
->name
, delim_len
) == 0
302 && (left_or_right
& d
->flags
) != 0)
304 if (i
>= DELIM_TABLE_SIZE
) {
305 error("there is no `%1' delimiter", delim
);
306 printf(".nr " DELIM_WIDTH_REG
" 0\n");
310 printf(".nr " DELIM_WIDTH_REG
" 0\\w" DELIMITER_CHAR
"\\f[%s]%s\\fP" DELIMITER_CHAR
"\n"
311 ".ds " DELIM_STRING
" \\Z" DELIMITER_CHAR
312 "\\v'\\n[rsb]u+\\n[rst]u/2u-%dM'\\f[%s]%s\\fP" DELIMITER_CHAR
"\n"
313 ".nr " TOTAL_HEIGHT_REG
" \\n[rst]-\\n[rsb]\n"
314 ".if \\n[" TOTAL_HEIGHT_REG
"]<\\n[" DELTA_REG
"] "
316 current_roman_font
, d
->small
, axis_height
,
317 current_roman_font
, d
->small
);
320 sprintf(buf
, d
->chain_format
, "\\\\n[" INDEX_REG
"]");
321 printf(".nr " INDEX_REG
" 0\n"
322 ".de " TEMP_MACRO
"\n"
324 ".nr " DELIM_WIDTH_REG
" 0\\w" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\n"
325 ".ds " DELIM_STRING
" \\Z" DELIMITER_CHAR
326 "\\v'\\\\n[rsb]u+\\\\n[rst]u/2u-%dM'%s" DELIMITER_CHAR
"\n"
327 ".nr " TOTAL_HEIGHT_REG
" \\\\n[rst]-\\\\n[rsb]\n"
328 ".if \\\\n[" TOTAL_HEIGHT_REG
"]<\\n[" DELTA_REG
"] "
329 "\\{.nr " INDEX_REG
" +1\n"
332 ".el .nr " INDEX_REG
" 0-1\n"
335 buf
, buf
, axis_height
, buf
);
337 printf(".if \\n[" INDEX_REG
"]<0 \\{.if c%s \\{\\\n", d
->ext
);
338 build_extensible(d
->ext
, d
->top
, d
->mid
, d
->bot
);
342 printf(".as " DELIM_STRING
" \\h'\\n[" DELIM_WIDTH_REG
"]u'\n");
343 printf(".nr " WIDTH_FORMAT
" +\\n[" DELIM_WIDTH_REG
"]\n", uid
);
344 printf(".nr " HEIGHT_FORMAT
" \\n[" HEIGHT_FORMAT
"]"
345 ">?(\\n[" TOTAL_HEIGHT_REG
"]/2+%dM)\n",
346 uid
, uid
, axis_height
);
347 printf(".nr " DEPTH_FORMAT
" \\n[" DEPTH_FORMAT
"]"
348 ">?(\\n[" TOTAL_HEIGHT_REG
"]/2-%dM)\n",
349 uid
, uid
, axis_height
);
352 int delim_box::compute_metrics(int style
)
354 int r
= p
->compute_metrics(style
);
355 printf(".nr " WIDTH_FORMAT
" 0\\n[" WIDTH_FORMAT
"]\n", uid
, p
->uid
);
356 printf(".nr " HEIGHT_FORMAT
" \\n[" HEIGHT_FORMAT
"]\n", uid
, p
->uid
);
357 printf(".nr " DEPTH_FORMAT
" \\n[" DEPTH_FORMAT
"]\n", uid
, p
->uid
);
358 printf(".nr " DELTA_REG
" \\n[" HEIGHT_FORMAT
"]-%dM"
359 ">?(\\n[" DEPTH_FORMAT
"]+%dM)\n",
360 p
->uid
, axis_height
, p
->uid
, axis_height
);
361 printf(".nr " DELTA_REG
" 0\\n[" DELTA_REG
"]*%d/500"
362 ">?(\\n[" DELTA_REG
"]*2-%dM)\n",
363 delimiter_factor
, delimiter_shortfall
);
365 define_extensible_string(left
, uid
, LEFT_DELIM
);
366 printf(".rn " DELIM_STRING
" " LEFT_DELIM_STRING_FORMAT
"\n",
369 printf(".nr " MARK_REG
" +\\n[" DELIM_WIDTH_REG
"]\n");
372 define_extensible_string(right
, uid
, RIGHT_DELIM
);
373 printf(".rn " DELIM_STRING
" " RIGHT_DELIM_STRING_FORMAT
"\n",
379 void delim_box::output()
382 printf("\\*[" LEFT_DELIM_STRING_FORMAT
"]", uid
);
385 printf("\\*[" RIGHT_DELIM_STRING_FORMAT
"]", uid
);
388 void delim_box::check_tabs(int level
)
390 p
->check_tabs(level
);
393 void delim_box::debug_print()
395 fprintf(stderr
, "left \"%s\" { ", left
? left
: "");
397 fprintf(stderr
, " }");
399 fprintf(stderr
, " right \"%s\"", right
);