2 /* Copyright (C) 1989, 1990, 1991, 1992, 2003, 2007
3 Free Software Foundation, Inc.
4 Written by James Clark (jjc@jclark.com)
6 This file is part of groff.
8 groff is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
13 groff is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License along
19 with groff; see the file COPYING. If not, write to the Free Software
20 Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
25 enum left_or_right_t
{ LEFT_DELIM
= 01, RIGHT_DELIM
= 02 };
27 // Small must be none-zero and must exist in each device.
28 // Small will be put in the roman font, others are assumed to be
29 // on the special font (so no font change will be necessary.)
35 const char *chain_format
;
42 "(", LEFT_DELIM
|RIGHT_DELIM
, "(", "\\[parenleft%s]",
49 ")", LEFT_DELIM
|RIGHT_DELIM
, ")", "\\[parenright%s]",
56 "[", LEFT_DELIM
|RIGHT_DELIM
, "[", "\\[bracketleft%s]",
63 "]", LEFT_DELIM
|RIGHT_DELIM
, "]", "\\[bracketright%s]",
70 "{", LEFT_DELIM
|RIGHT_DELIM
, "{", "\\[braceleft%s]",
77 "}", LEFT_DELIM
|RIGHT_DELIM
, "}", "\\[braceright%s]",
84 "|", LEFT_DELIM
|RIGHT_DELIM
, "|", "\\[bar%s]",
91 "floor", LEFT_DELIM
, "\\(lf", "\\[floorleft%s]",
98 "floor", RIGHT_DELIM
, "\\(rf", "\\[floorright%s]",
102 "\\[bracketrightbt]",
105 "ceiling", LEFT_DELIM
, "\\(lc", "\\[ceilingleft%s]",
112 "ceiling", RIGHT_DELIM
, "\\(rc", "\\[ceilingright%s]",
113 "\\[bracketrightex]",
114 "\\[bracketrighttp]",
119 "||", LEFT_DELIM
|RIGHT_DELIM
, "|", "\\[bar%s]",
126 "<", LEFT_DELIM
|RIGHT_DELIM
, "\\(la", "\\[angleleft%s]",
133 ">", LEFT_DELIM
|RIGHT_DELIM
, "\\(ra", "\\[angleright%s]",
140 "uparrow", LEFT_DELIM
|RIGHT_DELIM
, "\\(ua", "\\[arrowup%s]",
147 "downarrow", LEFT_DELIM
|RIGHT_DELIM
, "\\(da", "\\[arrowdown%s]",
154 "updownarrow", LEFT_DELIM
|RIGHT_DELIM
, "\\(va", "\\[arrowupdown%s]",
162 const int DELIM_TABLE_SIZE
= int(sizeof(delim_table
)/sizeof(delim_table
[0]));
164 class delim_box
: public box
{
170 delim_box(char *, box
*, char *);
172 int compute_metrics(int);
174 void check_tabs(int);
178 box
*make_delim_box(char *l
, box
*pp
, char *r
)
180 if (l
!= 0 && *l
== '\0') {
184 if (r
!= 0 && *r
== '\0') {
188 return new delim_box(l
, pp
, r
);
191 delim_box::delim_box(char *l
, box
*pp
, char *r
)
192 : left(l
), right(r
), p(pp
)
196 delim_box::~delim_box()
203 static void build_extensible(const char *ext
, const char *top
, const char *mid
,
207 printf(".nr " DELIM_WIDTH_REG
" 0\\w" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\n",
209 printf(".nr " EXT_HEIGHT_REG
" 0\\n[rst]\n");
210 printf(".nr " EXT_DEPTH_REG
" 0-\\n[rsb]\n");
212 printf(".nr " DELIM_WIDTH_REG
" 0\\n[" DELIM_WIDTH_REG
"]"
213 ">?\\w" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\n",
215 printf(".nr " TOP_HEIGHT_REG
" 0\\n[rst]\n");
216 printf(".nr " TOP_DEPTH_REG
" 0-\\n[rsb]\n");
219 printf(".nr " DELIM_WIDTH_REG
" 0\\n[" DELIM_WIDTH_REG
"]"
220 ">?\\w" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\n",
222 printf(".nr " MID_HEIGHT_REG
" 0\\n[rst]\n");
223 printf(".nr " MID_DEPTH_REG
" 0-\\n[rsb]\n");
226 printf(".nr " DELIM_WIDTH_REG
" 0\\n[" DELIM_WIDTH_REG
"]"
227 ">?\\w" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\n",
229 printf(".nr " BOT_HEIGHT_REG
" 0\\n[rst]\n");
230 printf(".nr " BOT_DEPTH_REG
" 0-\\n[rsb]\n");
232 printf(".nr " TOTAL_HEIGHT_REG
" 0");
234 printf("+\\n[" TOP_HEIGHT_REG
"]+\\n[" TOP_DEPTH_REG
"]");
236 printf("+\\n[" BOT_HEIGHT_REG
"]+\\n[" BOT_DEPTH_REG
"]");
238 printf("+\\n[" MID_HEIGHT_REG
"]+\\n[" MID_DEPTH_REG
"]");
240 // determine how many extensible characters we need
241 printf(".nr " TEMP_REG
" \\n[" DELTA_REG
"]-\\n[" TOTAL_HEIGHT_REG
"]");
244 printf(">?0+\\n[" EXT_HEIGHT_REG
"]+\\n[" EXT_DEPTH_REG
"]-1/(\\n["
245 EXT_HEIGHT_REG
"]+\\n[" EXT_DEPTH_REG
"])\n");
247 printf(".nr " TOTAL_HEIGHT_REG
" +(\\n[" EXT_HEIGHT_REG
"]+\\n["
248 EXT_DEPTH_REG
"]*\\n[" TEMP_REG
"]");
252 printf(".ds " DELIM_STRING
" \\Z" DELIMITER_CHAR
253 "\\v'-%dM-(\\n[" TOTAL_HEIGHT_REG
"]u/2u)'\n",
256 printf(".as " DELIM_STRING
" \\v'\\n[" TOP_HEIGHT_REG
"]u'"
257 "\\Z" DELIMITER_CHAR
"%s" DELIMITER_CHAR
258 "\\v'\\n[" TOP_DEPTH_REG
"]u'\n",
261 // this macro appends $2 copies of $3 to string $1
262 printf(".de " REPEAT_APPEND_STRING_MACRO
"\n"
263 ".if \\\\$2 \\{.as \\\\$1 \"\\\\$3\n"
264 "." REPEAT_APPEND_STRING_MACRO
" \\\\$1 \\\\$2-1 \"\\\\$3\"\n"
268 printf("." REPEAT_APPEND_STRING_MACRO
" " DELIM_STRING
" \\n[" TEMP_REG
"] "
269 "\\v'\\n[" EXT_HEIGHT_REG
"]u'"
270 "\\Z" DELIMITER_CHAR
"%s" DELIMITER_CHAR
271 "\\v'\\n[" EXT_DEPTH_REG
"]u'\n",
275 printf(".as " DELIM_STRING
" \\v'\\n[" MID_HEIGHT_REG
"]u'"
276 "\\Z" DELIMITER_CHAR
"%s" DELIMITER_CHAR
277 "\\v'\\n[" MID_DEPTH_REG
"]u'\n",
279 printf("." REPEAT_APPEND_STRING_MACRO
" " DELIM_STRING
280 " \\n[" TEMP_REG
"] "
281 "\\v'\\n[" EXT_HEIGHT_REG
"]u'"
282 "\\Z" DELIMITER_CHAR
"%s" DELIMITER_CHAR
283 "\\v'\\n[" EXT_DEPTH_REG
"]u'\n",
287 printf(".as " DELIM_STRING
" \\v'\\n[" BOT_HEIGHT_REG
"]u'"
288 "\\Z" DELIMITER_CHAR
"%s" DELIMITER_CHAR
289 "\\v'\\n[" BOT_DEPTH_REG
"]u'\n",
291 printf(".as " DELIM_STRING
" " DELIMITER_CHAR
"\n");
294 static void define_extensible_string(char *delim
, int uid
,
295 left_or_right_t left_or_right
)
297 printf(".ds " DELIM_STRING
"\n");
298 delimiter
*d
= delim_table
;
299 int delim_len
= strlen(delim
);
301 for (i
= 0; i
< DELIM_TABLE_SIZE
; i
++, d
++)
302 if (strncmp(delim
, d
->name
, delim_len
) == 0
303 && (left_or_right
& d
->flags
) != 0)
305 if (i
>= DELIM_TABLE_SIZE
) {
306 error("there is no `%1' delimiter", delim
);
307 printf(".nr " DELIM_WIDTH_REG
" 0\n");
311 printf(".nr " DELIM_WIDTH_REG
" 0\\w" DELIMITER_CHAR
"\\f[%s]%s\\fP" DELIMITER_CHAR
"\n"
312 ".ds " DELIM_STRING
" \\Z" DELIMITER_CHAR
313 "\\v'\\n[rsb]u+\\n[rst]u/2u-%dM'\\f[%s]%s\\fP" DELIMITER_CHAR
"\n"
314 ".nr " TOTAL_HEIGHT_REG
" \\n[rst]-\\n[rsb]\n"
315 ".if \\n[" TOTAL_HEIGHT_REG
"]<\\n[" DELTA_REG
"] "
317 current_roman_font
, d
->small
, axis_height
,
318 current_roman_font
, d
->small
);
321 sprintf(buf
, d
->chain_format
, "\\\\n[" INDEX_REG
"]");
322 printf(".nr " INDEX_REG
" 0\n"
323 ".de " TEMP_MACRO
"\n"
325 ".nr " DELIM_WIDTH_REG
" 0\\w" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\n"
326 ".ds " DELIM_STRING
" \\Z" DELIMITER_CHAR
327 "\\v'\\\\n[rsb]u+\\\\n[rst]u/2u-%dM'%s" DELIMITER_CHAR
"\n"
328 ".nr " TOTAL_HEIGHT_REG
" \\\\n[rst]-\\\\n[rsb]\n"
329 ".if \\\\n[" TOTAL_HEIGHT_REG
"]<\\n[" DELTA_REG
"] "
330 "\\{.nr " INDEX_REG
" +1\n"
333 ".el .nr " INDEX_REG
" 0-1\n"
336 buf
, buf
, axis_height
, buf
);
338 printf(".if \\n[" INDEX_REG
"]<0 \\{.if c%s \\{\\\n", d
->ext
);
339 build_extensible(d
->ext
, d
->top
, d
->mid
, d
->bot
);
343 printf(".as " DELIM_STRING
" \\h'\\n[" DELIM_WIDTH_REG
"]u'\n");
344 printf(".nr " WIDTH_FORMAT
" +\\n[" DELIM_WIDTH_REG
"]\n", uid
);
345 printf(".nr " HEIGHT_FORMAT
" \\n[" HEIGHT_FORMAT
"]"
346 ">?(\\n[" TOTAL_HEIGHT_REG
"]/2+%dM)\n",
347 uid
, uid
, axis_height
);
348 printf(".nr " DEPTH_FORMAT
" \\n[" DEPTH_FORMAT
"]"
349 ">?(\\n[" TOTAL_HEIGHT_REG
"]/2-%dM)\n",
350 uid
, uid
, axis_height
);
353 int delim_box::compute_metrics(int style
)
355 int r
= p
->compute_metrics(style
);
356 printf(".nr " WIDTH_FORMAT
" 0\\n[" WIDTH_FORMAT
"]\n", uid
, p
->uid
);
357 printf(".nr " HEIGHT_FORMAT
" \\n[" HEIGHT_FORMAT
"]\n", uid
, p
->uid
);
358 printf(".nr " DEPTH_FORMAT
" \\n[" DEPTH_FORMAT
"]\n", uid
, p
->uid
);
359 printf(".nr " DELTA_REG
" \\n[" HEIGHT_FORMAT
"]-%dM"
360 ">?(\\n[" DEPTH_FORMAT
"]+%dM)\n",
361 p
->uid
, axis_height
, p
->uid
, axis_height
);
362 printf(".nr " DELTA_REG
" 0\\n[" DELTA_REG
"]*%d/500"
363 ">?(\\n[" DELTA_REG
"]*2-%dM)\n",
364 delimiter_factor
, delimiter_shortfall
);
366 define_extensible_string(left
, uid
, LEFT_DELIM
);
367 printf(".rn " DELIM_STRING
" " LEFT_DELIM_STRING_FORMAT
"\n",
370 printf(".nr " MARK_REG
" +\\n[" DELIM_WIDTH_REG
"]\n");
373 define_extensible_string(right
, uid
, RIGHT_DELIM
);
374 printf(".rn " DELIM_STRING
" " RIGHT_DELIM_STRING_FORMAT
"\n",
380 void delim_box::output()
382 if (output_format
== troff
) {
384 printf("\\*[" LEFT_DELIM_STRING_FORMAT
"]", uid
);
387 printf("\\*[" RIGHT_DELIM_STRING_FORMAT
"]", uid
);
389 else if (output_format
== mathml
) {
390 printf("<mrow><mo>%s</mo>", left
);
392 printf("<mo>%s</mo></mrow>", right
);
396 void delim_box::check_tabs(int level
)
398 p
->check_tabs(level
);
401 void delim_box::debug_print()
403 fprintf(stderr
, "left \"%s\" { ", left
? left
: "");
405 fprintf(stderr
, " }");
407 fprintf(stderr
, " right \"%s\"", right
);