/* Copyright (C) 1989, 1990 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.uucp)
This file is part of groff.
groff is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
groff is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
You should have received a copy of the GNU General Public License along
with groff; see the file LICENSE. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
enum left_or_right_t
{ LEFT_DELIM
= 01, RIGHT_DELIM
= 02 };
// Small must be none-zero and must exist in each device.
// Small will be put in the roman font, others are assumed to be
// on the special font (so no font change will be necessary.)
const char *chain_format
;
"(", LEFT_DELIM
|RIGHT_DELIM
, "(", "\\[parenleft%s]",
")", LEFT_DELIM
|RIGHT_DELIM
, ")", "\\[parenright%s]",
"[", LEFT_DELIM
|RIGHT_DELIM
, "[", "\\[bracketleft%s]",
"]", LEFT_DELIM
|RIGHT_DELIM
, "]", "\\[bracketright%s]",
"{", LEFT_DELIM
|RIGHT_DELIM
, "{", "\\[braceleft%s]",
"}", LEFT_DELIM
|RIGHT_DELIM
, "}", "\\[braceright%s]",
"|", LEFT_DELIM
|RIGHT_DELIM
, "|", "\\[bar%s]",
"floor", LEFT_DELIM
, "\\(lf", "\\[floorleft%s]",
"floor", RIGHT_DELIM
, "\\(rf", "\\[floorright%s]",
"ceiling", LEFT_DELIM
, "\\(lc", "\\[ceilingleft%s]",
"ceiling", RIGHT_DELIM
, "\\(rc", "\\[ceilingright%s]",
"||", LEFT_DELIM
|RIGHT_DELIM
, "|", "\\[bar%s]",
"<", LEFT_DELIM
|RIGHT_DELIM
, "\\(la", "\\[angleleft%s]",
">", LEFT_DELIM
|RIGHT_DELIM
, "\\(ra", "\\[angleright%s]",
const int DELIM_TABLE_SIZE
= int(sizeof(delim_table
)/sizeof(delim_table
[0]));
class delim_box
: public box
{
delim_box(char *, box
*, char *);
int compute_metrics(int);
box
*make_delim_box(char *l
, box
*pp
, char *r
)
if (l
!= 0 && *l
== '\0') {
if (r
!= 0 && *r
== '\0') {
return new delim_box(l
, pp
, r
);
delim_box::delim_box(char *l
, box
*pp
, char *r
)
: left(l
), right(r
), p(pp
)
static void build_extensible(const char *ext
, const char *top
, const char *mid
,
printf(".nr " DELIM_WIDTH_REG
" \\w" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\n",
printf(".nr " EXT_HEIGHT_REG
" 0\\n[rst]\n");
printf(".nr " EXT_DEPTH_REG
" 0-\\n[rsb]\n");
printf(".nr " DELIM_WIDTH_REG
" \\n[" DELIM_WIDTH_REG
"]"
">?\\w" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\n",
printf(".nr " TOP_HEIGHT_REG
" 0\\n[rst]\n");
printf(".nr " TOP_DEPTH_REG
" 0-\\n[rsb]\n");
printf(".nr " DELIM_WIDTH_REG
" \\n[" DELIM_WIDTH_REG
"]"
">?\\w" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\n",
printf(".nr " MID_HEIGHT_REG
" 0\\n[rst]\n");
printf(".nr " MID_DEPTH_REG
" 0-\\n[rsb]\n");
printf(".nr " DELIM_WIDTH_REG
" \\n[" DELIM_WIDTH_REG
"]"
">?\\w" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\n",
printf(".nr " BOT_HEIGHT_REG
" 0\\n[rst]\n");
printf(".nr " BOT_DEPTH_REG
" 0-\\n[rsb]\n");
printf(".nr " TOTAL_HEIGHT_REG
" 0");
printf("+\\n[" TOP_HEIGHT_REG
"]+\\n[" TOP_DEPTH_REG
"]");
printf("+\\n[" BOT_HEIGHT_REG
"]+\\n[" BOT_DEPTH_REG
"]");
printf("+\\n[" MID_HEIGHT_REG
"]+\\n[" MID_DEPTH_REG
"]");
// determine how many extensible characters we need
printf(".nr " TEMP_REG
" \\n[" DELTA_REG
"]-\\n[" TOTAL_HEIGHT_REG
"]");
printf(">?0+\\n[" EXT_HEIGHT_REG
"]+\\n[" EXT_DEPTH_REG
"]-1/(\\n["
EXT_HEIGHT_REG
"]+\\n[" EXT_DEPTH_REG
"])\n");
printf(".nr " TOTAL_HEIGHT_REG
" +(\\n[" EXT_HEIGHT_REG
"]+\\n["
EXT_DEPTH_REG
"]*\\n[" TEMP_REG
"]");
printf(".ds " DELIM_STRING
" \\Z" DELIMITER_CHAR
"\\v'-%dM-(\\n[" TOTAL_HEIGHT_REG
"]u/2u)'\n",
printf(".as " DELIM_STRING
" \\v'\\n[" TOP_HEIGHT_REG
"]u'"
"\\Z" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\\v'\\n[" TOP_DEPTH_REG
"]u'\n",
// this macro appends $2 copies of $3 to string $1
printf(".de " REPEAT_APPEND_STRING_MACRO
"\n"
".if \\\\$2 \\{.as \\\\$1 \"\\\\$3\n"
"." REPEAT_APPEND_STRING_MACRO
" \\\\$1 \\\\$2-1 \"\\\\$3\"\n"
printf("." REPEAT_APPEND_STRING_MACRO
" " DELIM_STRING
" \\n[" TEMP_REG
"] "
"\\v'\\n[" EXT_HEIGHT_REG
"]u'"
"\\Z" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\\v'\\n[" EXT_DEPTH_REG
"]u'\n",
printf(".as " DELIM_STRING
" \\v'\\n[" MID_HEIGHT_REG
"]u'"
"\\Z" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\\v'\\n[" MID_DEPTH_REG
"]u'\n",
printf("." REPEAT_APPEND_STRING_MACRO
" " DELIM_STRING
"\\v'\\n[" EXT_HEIGHT_REG
"]u'"
"\\Z" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\\v'\\n[" EXT_DEPTH_REG
"]u'\n",
printf(".as " DELIM_STRING
" \\v'\\n[" BOT_HEIGHT_REG
"]u'"
"\\Z" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\\v'\\n[" BOT_DEPTH_REG
"]u'\n",
printf(".as " DELIM_STRING
" " DELIMITER_CHAR
"\n");
static void define_extensible_string(char *delim
, int uid
,
left_or_right_t left_or_right
)
printf(".ds " DELIM_STRING
"\n");
delimiter
*d
= delim_table
;
for (int i
= 0; i
< DELIM_TABLE_SIZE
; i
++, d
++)
if (strcmp(delim
, d
->name
) == 0 && (left_or_right
& d
->flags
) != 0)
if (i
>= DELIM_TABLE_SIZE
) {
error("there is no `%1' delimiter", delim
);
printf(".nr " DELIM_WIDTH_REG
" 0\n");
printf(".nr " DELIM_WIDTH_REG
" \\w" DELIMITER_CHAR
"\\f[%s]%s\\fP" DELIMITER_CHAR
"\n"
".ds " DELIM_STRING
" \\Z" DELIMITER_CHAR
"\\v'\\n[rsb]u+\\n[rst]u/2u-%dM'\\f[%s]%s\\fP" DELIMITER_CHAR
"\n"
".nr " TOTAL_HEIGHT_REG
" \\n[rst]-\\n[rsb]\n"
".if \\n[" TOTAL_HEIGHT_REG
"]<\\n[" DELTA_REG
"] "
current_roman_font
, d
->small
, axis_height
,
current_roman_font
, d
->small
);
sprintf(buf
, d
->chain_format
, "\\\\n[" INDEX_REG
"]");
printf(".nr " INDEX_REG
" 0\n"
".nr " DELIM_WIDTH_REG
" \\w" DELIMITER_CHAR
"%s" DELIMITER_CHAR
"\n"
".ds " DELIM_STRING
" \\Z" DELIMITER_CHAR
"\\v'\\\\n[rsb]u+\\\\n[rst]u/2u-%dM'%s" DELIMITER_CHAR
"\n"
".nr " TOTAL_HEIGHT_REG
" \\\\n[rst]-\\\\n[rsb]\n"
".if \\\\n[" TOTAL_HEIGHT_REG
"]<\\n[" DELTA_REG
"] "
"\\{.nr " INDEX_REG
" +1\n"
".el .nr " INDEX_REG
" 0-1\n"
buf
, buf
, axis_height
, buf
);
printf(".if \\n[" INDEX_REG
"]<0 \\{.if c%s \\{\\\n", d
->ext
);
build_extensible(d
->ext
, d
->top
, d
->mid
, d
->bot
);
printf(".as " DELIM_STRING
" \\h'\\n[" DELIM_WIDTH_REG
"]u'\n");
printf(".nr " WIDTH_FORMAT
" +\\n[" DELIM_WIDTH_REG
"]\n", uid
);
printf(".nr " HEIGHT_FORMAT
" \\n[" HEIGHT_FORMAT
"]"
">?(\\n[" TOTAL_HEIGHT_REG
"]/2+%dM)\n",
printf(".nr " DEPTH_FORMAT
" \\n[" DEPTH_FORMAT
"]"
">?(\\n[" TOTAL_HEIGHT_REG
"]/2-%dM)\n",
int delim_box::compute_metrics(int style
)
int r
= p
->compute_metrics(style
);
printf(".nr " WIDTH_FORMAT
" \\n[" WIDTH_FORMAT
"]\n", uid
, p
->uid
);
printf(".nr " HEIGHT_FORMAT
" \\n[" HEIGHT_FORMAT
"]\n", uid
, p
->uid
);
printf(".nr " DEPTH_FORMAT
" \\n[" DEPTH_FORMAT
"]\n", uid
, p
->uid
);
printf(".nr " DELTA_REG
" \\n[" HEIGHT_FORMAT
"]-%dM"
">?(\\n[" DEPTH_FORMAT
"]+%dM)\n",
p
->uid
, axis_height
, p
->uid
, axis_height
);
printf(".nr " DELTA_REG
" \\n[" DELTA_REG
"]*%d/500"
">?(\\n[" DELTA_REG
"]*2-%dM)\n",
delimiter_factor
, delimiter_shortfall
);
define_extensible_string(left
, uid
, LEFT_DELIM
);
printf(".rn " DELIM_STRING
" " LEFT_DELIM_STRING_FORMAT
"\n",
printf(".nr " MARK_REG
" +\\n[" DELIM_WIDTH_REG
"]\n");
define_extensible_string(right
, uid
, RIGHT_DELIM
);
printf(".rn " DELIM_STRING
" " RIGHT_DELIM_STRING_FORMAT
"\n",
printf("\\*[" LEFT_DELIM_STRING_FORMAT
"]", uid
);
printf("\\*[" RIGHT_DELIM_STRING_FORMAT
"]", uid
);
void delim_box::check_tabs(int level
)
void delim_box::debug_print()
fprintf(stderr
, "left \"%s\" { ", left
);
fprintf(stderr
, " right \"%s\"", right
);