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. */
26 enum left_or_right_t
{ LEFT_DELIM
= 01, RIGHT_DELIM
= 02 };
28 // Small must be none-zero and must exist in each device.
29 // Small will be put in the roman font, others are assumed to be
30 // on the special font (so no font change will be necessary.)
36 const char *chain_format
;
43 "(", LEFT_DELIM
|RIGHT_DELIM
, "(", "\\[parenleft%s]",
50 ")", LEFT_DELIM
|RIGHT_DELIM
, ")", "\\[parenright%s]",
57 "[", LEFT_DELIM
|RIGHT_DELIM
, "[", "\\[bracketleft%s]",
64 "]", LEFT_DELIM
|RIGHT_DELIM
, "]", "\\[bracketright%s]",
71 "{", LEFT_DELIM
|RIGHT_DELIM
, "{", "\\[braceleft%s]",
78 "}", LEFT_DELIM
|RIGHT_DELIM
, "}", "\\[braceright%s]",
85 "|", LEFT_DELIM
|RIGHT_DELIM
, "|", "\\[bar%s]",
92 "floor", LEFT_DELIM
, "\\(lf", "\\[floorleft%s]",
99 "floor", RIGHT_DELIM
, "\\(rf", "\\[floorright%s]",
100 "\\[bracketrightex]",
103 "\\[bracketrightbt]",
106 "ceiling", LEFT_DELIM
, "\\(lc", "\\[ceilingleft%s]",
113 "ceiling", RIGHT_DELIM
, "\\(rc", "\\[ceilingright%s]",
114 "\\[bracketrightex]",
115 "\\[bracketrighttp]",
120 "||", LEFT_DELIM
|RIGHT_DELIM
, "|", "\\[bar%s]",
127 "<", LEFT_DELIM
|RIGHT_DELIM
, "\\(la", "\\[angleleft%s]",
134 ">", LEFT_DELIM
|RIGHT_DELIM
, "\\(ra", "\\[angleright%s]",
141 "uparrow", LEFT_DELIM
|RIGHT_DELIM
, "\\(ua", "\\[arrowup%s]",
148 "downarrow", LEFT_DELIM
|RIGHT_DELIM
, "\\(da", "\\[arrowdown%s]",
155 "updownarrow", LEFT_DELIM
|RIGHT_DELIM
, "\\(va", "\\[arrowupdown%s]",
163 const int DELIM_TABLE_SIZE
= int(sizeof(delim_table
)/sizeof(delim_table
[0]));
165 class delim_box
: public box
{
171 delim_box(char *, box
*, char *);
173 int compute_metrics(int);
175 void check_tabs(int);
179 box
*make_delim_box(char *l
, box
*pp
, char *r
)
181 if (l
!= 0 && *l
== '\0') {
185 if (r
!= 0 && *r
== '\0') {
189 return new delim_box(l
, pp
, r
);
192 delim_box::delim_box(char *l
, box
*pp
, char *r
)
193 : left(l
), right(r
), p(pp
)
197 delim_box::~delim_box()
204 static void build_extensible(const char *ext
, const char *top
, const char *mid
,
208 printf(".nr " DELIM_WIDTH_REG
" 0\\w" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\n",
210 printf(".nr " EXT_HEIGHT_REG
" 0\\n[rst]\n");
211 printf(".nr " EXT_DEPTH_REG
" 0-\\n[rsb]\n");
213 printf(".nr " DELIM_WIDTH_REG
" 0\\n[" DELIM_WIDTH_REG
"]"
214 ">?\\w" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\n",
216 printf(".nr " TOP_HEIGHT_REG
" 0\\n[rst]\n");
217 printf(".nr " TOP_DEPTH_REG
" 0-\\n[rsb]\n");
220 printf(".nr " DELIM_WIDTH_REG
" 0\\n[" DELIM_WIDTH_REG
"]"
221 ">?\\w" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\n",
223 printf(".nr " MID_HEIGHT_REG
" 0\\n[rst]\n");
224 printf(".nr " MID_DEPTH_REG
" 0-\\n[rsb]\n");
227 printf(".nr " DELIM_WIDTH_REG
" 0\\n[" DELIM_WIDTH_REG
"]"
228 ">?\\w" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\n",
230 printf(".nr " BOT_HEIGHT_REG
" 0\\n[rst]\n");
231 printf(".nr " BOT_DEPTH_REG
" 0-\\n[rsb]\n");
233 printf(".nr " TOTAL_HEIGHT_REG
" 0");
235 printf("+\\n[" TOP_HEIGHT_REG
"]+\\n[" TOP_DEPTH_REG
"]");
237 printf("+\\n[" BOT_HEIGHT_REG
"]+\\n[" BOT_DEPTH_REG
"]");
239 printf("+\\n[" MID_HEIGHT_REG
"]+\\n[" MID_DEPTH_REG
"]");
241 // determine how many extensible characters we need
242 printf(".nr " TEMP_REG
" \\n[" DELTA_REG
"]-\\n[" TOTAL_HEIGHT_REG
"]");
245 printf(">?0+\\n[" EXT_HEIGHT_REG
"]+\\n[" EXT_DEPTH_REG
"]-1/(\\n["
246 EXT_HEIGHT_REG
"]+\\n[" EXT_DEPTH_REG
"])\n");
248 printf(".nr " TOTAL_HEIGHT_REG
" +(\\n[" EXT_HEIGHT_REG
"]+\\n["
249 EXT_DEPTH_REG
"]*\\n[" TEMP_REG
"]");
253 printf(".ds " DELIM_STRING
" \\Z" DELIMITER_CHAR
254 "\\v'-%dM-(\\n[" TOTAL_HEIGHT_REG
"]u/2u)'\n",
257 printf(".as " DELIM_STRING
" \\v'\\n[" TOP_HEIGHT_REG
"]u'"
258 "\\Z" DELIMITER_CHAR
"%s" DELIMITER_CHAR
259 "\\v'\\n[" TOP_DEPTH_REG
"]u'\n",
262 // this macro appends $2 copies of $3 to string $1
263 printf(".de " REPEAT_APPEND_STRING_MACRO
"\n"
264 ".if \\\\$2 \\{.as \\\\$1 \"\\\\$3\n"
265 "." REPEAT_APPEND_STRING_MACRO
" \\\\$1 \\\\$2-1 \"\\\\$3\"\n"
269 printf("." REPEAT_APPEND_STRING_MACRO
" " DELIM_STRING
" \\n[" TEMP_REG
"] "
270 "\\v'\\n[" EXT_HEIGHT_REG
"]u'"
271 "\\Z" DELIMITER_CHAR
"%s" DELIMITER_CHAR
272 "\\v'\\n[" EXT_DEPTH_REG
"]u'\n",
276 printf(".as " DELIM_STRING
" \\v'\\n[" MID_HEIGHT_REG
"]u'"
277 "\\Z" DELIMITER_CHAR
"%s" DELIMITER_CHAR
278 "\\v'\\n[" MID_DEPTH_REG
"]u'\n",
280 printf("." REPEAT_APPEND_STRING_MACRO
" " DELIM_STRING
281 " \\n[" TEMP_REG
"] "
282 "\\v'\\n[" EXT_HEIGHT_REG
"]u'"
283 "\\Z" DELIMITER_CHAR
"%s" DELIMITER_CHAR
284 "\\v'\\n[" EXT_DEPTH_REG
"]u'\n",
288 printf(".as " DELIM_STRING
" \\v'\\n[" BOT_HEIGHT_REG
"]u'"
289 "\\Z" DELIMITER_CHAR
"%s" DELIMITER_CHAR
290 "\\v'\\n[" BOT_DEPTH_REG
"]u'\n",
292 printf(".as " DELIM_STRING
" " DELIMITER_CHAR
"\n");
295 static void define_extensible_string(char *delim
, int uid
,
296 left_or_right_t left_or_right
)
298 printf(".ds " DELIM_STRING
"\n");
299 delimiter
*d
= delim_table
;
300 int delim_len
= strlen(delim
);
302 for (i
= 0; i
< DELIM_TABLE_SIZE
; i
++, d
++)
303 if (strncmp(delim
, d
->name
, delim_len
) == 0
304 && (left_or_right
& d
->flags
) != 0)
306 if (i
>= DELIM_TABLE_SIZE
) {
307 error("there is no `%1' delimiter", delim
);
308 printf(".nr " DELIM_WIDTH_REG
" 0\n");
312 printf(".nr " DELIM_WIDTH_REG
" 0\\w" DELIMITER_CHAR
"\\f[%s]%s\\fP" DELIMITER_CHAR
"\n"
313 ".ds " DELIM_STRING
" \\Z" DELIMITER_CHAR
314 "\\v'\\n[rsb]u+\\n[rst]u/2u-%dM'\\f[%s]%s\\fP" DELIMITER_CHAR
"\n"
315 ".nr " TOTAL_HEIGHT_REG
" \\n[rst]-\\n[rsb]\n"
316 ".if \\n[" TOTAL_HEIGHT_REG
"]<\\n[" DELTA_REG
"] "
318 current_roman_font
, d
->small
, axis_height
,
319 current_roman_font
, d
->small
);
322 sprintf(buf
, d
->chain_format
, "\\\\n[" INDEX_REG
"]");
323 printf(".nr " INDEX_REG
" 0\n"
324 ".de " TEMP_MACRO
"\n"
326 ".nr " DELIM_WIDTH_REG
" 0\\w" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\n"
327 ".ds " DELIM_STRING
" \\Z" DELIMITER_CHAR
328 "\\v'\\\\n[rsb]u+\\\\n[rst]u/2u-%dM'%s" DELIMITER_CHAR
"\n"
329 ".nr " TOTAL_HEIGHT_REG
" \\\\n[rst]-\\\\n[rsb]\n"
330 ".if \\\\n[" TOTAL_HEIGHT_REG
"]<\\n[" DELTA_REG
"] "
331 "\\{.nr " INDEX_REG
" +1\n"
334 ".el .nr " INDEX_REG
" 0-1\n"
337 buf
, buf
, axis_height
, buf
);
339 printf(".if \\n[" INDEX_REG
"]<0 \\{.if c%s \\{\\\n", d
->ext
);
340 build_extensible(d
->ext
, d
->top
, d
->mid
, d
->bot
);
344 printf(".as " DELIM_STRING
" \\h'\\n[" DELIM_WIDTH_REG
"]u'\n");
345 printf(".nr " WIDTH_FORMAT
" +\\n[" DELIM_WIDTH_REG
"]\n", uid
);
346 printf(".nr " HEIGHT_FORMAT
" \\n[" HEIGHT_FORMAT
"]"
347 ">?(\\n[" TOTAL_HEIGHT_REG
"]/2+%dM)\n",
348 uid
, uid
, axis_height
);
349 printf(".nr " DEPTH_FORMAT
" \\n[" DEPTH_FORMAT
"]"
350 ">?(\\n[" TOTAL_HEIGHT_REG
"]/2-%dM)\n",
351 uid
, uid
, axis_height
);
354 int delim_box::compute_metrics(int style
)
356 int r
= p
->compute_metrics(style
);
357 printf(".nr " WIDTH_FORMAT
" 0\\n[" WIDTH_FORMAT
"]\n", uid
, p
->uid
);
358 printf(".nr " HEIGHT_FORMAT
" \\n[" HEIGHT_FORMAT
"]\n", uid
, p
->uid
);
359 printf(".nr " DEPTH_FORMAT
" \\n[" DEPTH_FORMAT
"]\n", uid
, p
->uid
);
360 printf(".nr " DELTA_REG
" \\n[" HEIGHT_FORMAT
"]-%dM"
361 ">?(\\n[" DEPTH_FORMAT
"]+%dM)\n",
362 p
->uid
, axis_height
, p
->uid
, axis_height
);
363 printf(".nr " DELTA_REG
" 0\\n[" DELTA_REG
"]*%d/500"
364 ">?(\\n[" DELTA_REG
"]*2-%dM)\n",
365 delimiter_factor
, delimiter_shortfall
);
367 define_extensible_string(left
, uid
, LEFT_DELIM
);
368 printf(".rn " DELIM_STRING
" " LEFT_DELIM_STRING_FORMAT
"\n",
371 printf(".nr " MARK_REG
" +\\n[" DELIM_WIDTH_REG
"]\n");
374 define_extensible_string(right
, uid
, RIGHT_DELIM
);
375 printf(".rn " DELIM_STRING
" " RIGHT_DELIM_STRING_FORMAT
"\n",
381 void delim_box::output()
384 printf("\\*[" LEFT_DELIM_STRING_FORMAT
"]", uid
);
387 printf("\\*[" RIGHT_DELIM_STRING_FORMAT
"]", uid
);
390 void delim_box::check_tabs(int level
)
392 p
->check_tabs(level
);
395 void delim_box::debug_print()
397 fprintf(stderr
, "left \"%s\" { ", left
? left
: "");
399 fprintf(stderr
, " }");
401 fprintf(stderr
, " right \"%s\"", right
);