delim.cpp revision 151497
174822Srwatson// -*- C++ -*- 2165890Srwatson/* Copyright (C) 1989, 1990, 1991, 1992, 2003 Free Software Foundation, Inc. 374822Srwatson Written by James Clark (jjc@jclark.com) 474822Srwatson 585845SrwatsonThis file is part of groff. 685845Srwatson 774822Srwatsongroff is free software; you can redistribute it and/or modify it under 874822Srwatsonthe terms of the GNU General Public License as published by the Free 974822SrwatsonSoftware Foundation; either version 2, or (at your option) any later 1074822Srwatsonversion. 1174822Srwatson 1274822Srwatsongroff is distributed in the hope that it will be useful, but WITHOUT ANY 1374822SrwatsonWARRANTY; without even the implied warranty of MERCHANTABILITY or 1474822SrwatsonFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1574822Srwatsonfor more details. 1674822Srwatson 1774822SrwatsonYou should have received a copy of the GNU General Public License along 1874822Srwatsonwith groff; see the file COPYING. If not, write to the Free Software 1974822SrwatsonFoundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ 2074822Srwatson 2174822Srwatson#include "eqn.h" 2274822Srwatson#include "pbox.h" 2374822Srwatson 2474822Srwatsonenum left_or_right_t { LEFT_DELIM = 01, RIGHT_DELIM = 02 }; 2574822Srwatson 2674822Srwatson// Small must be none-zero and must exist in each device. 2774822Srwatson// Small will be put in the roman font, others are assumed to be 28116192Sobrien// on the special font (so no font change will be necessary.) 2974822Srwatson 3074822Srwatsonstruct delimiter { 3174822Srwatson const char *name; 3274822Srwatson int flags; 33116192Sobrien const char *small; 34116192Sobrien const char *chain_format; 35116192Sobrien const char *ext; 3674822Srwatson const char *top; 3774822Srwatson const char *mid; 3874822Srwatson const char *bot; 3974822Srwatson} delim_table[] = { 4074822Srwatson { 4174822Srwatson "(", LEFT_DELIM|RIGHT_DELIM, "(", "\\[parenleft%s]", 4274822Srwatson "\\[parenleftex]", 4374822Srwatson "\\[parenlefttp]", 4474822Srwatson 0, 4574822Srwatson "\\[parenleftbt]", 4674822Srwatson }, 4774822Srwatson { 4874822Srwatson ")", LEFT_DELIM|RIGHT_DELIM, ")", "\\[parenright%s]", 4974822Srwatson "\\[parenrightex]", 5074822Srwatson "\\[parenrighttp]", 5174822Srwatson 0, 5274822Srwatson "\\[parenrightbt]", 5374822Srwatson }, 5474822Srwatson { 5574822Srwatson "[", LEFT_DELIM|RIGHT_DELIM, "[", "\\[bracketleft%s]", 56184629Strasz "\\[bracketleftex]", 5774822Srwatson "\\[bracketlefttp]", 5874822Srwatson 0, 5974822Srwatson "\\[bracketleftbt]", 6074822Srwatson }, 6174822Srwatson { 6274822Srwatson "]", LEFT_DELIM|RIGHT_DELIM, "]", "\\[bracketright%s]", 6374822Srwatson "\\[bracketrightex]", 6474822Srwatson "\\[bracketrighttp]", 6574822Srwatson 0, 6674822Srwatson "\\[bracketrightbt]", 6774822Srwatson }, 6874822Srwatson { 6974822Srwatson "{", LEFT_DELIM|RIGHT_DELIM, "{", "\\[braceleft%s]", 7074822Srwatson "\\[braceleftex]", 7174822Srwatson "\\[bracelefttp]", 7274822Srwatson "\\[braceleftmid]", 7374822Srwatson "\\[braceleftbt]", 7474822Srwatson }, 7574822Srwatson { 7674822Srwatson "}", LEFT_DELIM|RIGHT_DELIM, "}", "\\[braceright%s]", 7774822Srwatson "\\[bracerightex]", 7874822Srwatson "\\[bracerighttp]", 7974822Srwatson "\\[bracerightmid]", 8074822Srwatson "\\[bracerightbt]", 8174822Srwatson }, 8274822Srwatson { 8375571Srwatson "|", LEFT_DELIM|RIGHT_DELIM, "|", "\\[bar%s]", 8474822Srwatson "\\[barex]", 8574822Srwatson 0, 8674822Srwatson 0, 8774822Srwatson 0, 8875571Srwatson }, 8974822Srwatson { 9074822Srwatson "floor", LEFT_DELIM, "\\(lf", "\\[floorleft%s]", 9174822Srwatson "\\[bracketleftex]", 9274822Srwatson 0, 9374822Srwatson 0, 9475571Srwatson "\\[bracketleftbt]", 9574822Srwatson }, 9674822Srwatson { 9774822Srwatson "floor", RIGHT_DELIM, "\\(rf", "\\[floorright%s]", 9874822Srwatson "\\[bracketrightex]", 9975571Srwatson 0, 10074822Srwatson 0, 10174822Srwatson "\\[bracketrightbt]", 10274822Srwatson }, 10374822Srwatson { 10474822Srwatson "ceiling", LEFT_DELIM, "\\(lc", "\\[ceilingleft%s]", 10574822Srwatson "\\[bracketleftex]", 10674822Srwatson "\\[bracketlefttp]", 10774822Srwatson 0, 10874822Srwatson 0, 10974822Srwatson }, 11074822Srwatson { 11174822Srwatson "ceiling", RIGHT_DELIM, "\\(rc", "\\[ceilingright%s]", 11274822Srwatson "\\[bracketrightex]", 11374822Srwatson "\\[bracketrighttp]", 11474822Srwatson 0, 11574822Srwatson 0, 11674822Srwatson }, 11774822Srwatson { 11874822Srwatson "||", LEFT_DELIM|RIGHT_DELIM, "|", "\\[bar%s]", 11974822Srwatson "\\[bardblex]", 12074822Srwatson 0, 12174822Srwatson 0, 12274822Srwatson 0, 12374822Srwatson }, 12474822Srwatson { 12574822Srwatson "<", LEFT_DELIM|RIGHT_DELIM, "\\(la", "\\[angleleft%s]", 12674822Srwatson 0, 12774822Srwatson 0, 12874822Srwatson 0, 12974822Srwatson 0, 130118411Srwatson }, 131118411Srwatson { 132118411Srwatson ">", LEFT_DELIM|RIGHT_DELIM, "\\(ra", "\\[angleright%s]", 13374822Srwatson 0, 13474822Srwatson 0, 135118411Srwatson 0, 13674822Srwatson 0, 13774822Srwatson }, 138118411Srwatson { 139118411Srwatson "uparrow", LEFT_DELIM|RIGHT_DELIM, "\\(ua", "\\[arrowup%s]", 140132775Skan "\\[arrowvertex]", 14174822Srwatson "\\[arrowverttp]", 14274822Srwatson 0, 14374822Srwatson 0, 14474822Srwatson }, 14574822Srwatson { 14674822Srwatson "downarrow", LEFT_DELIM|RIGHT_DELIM, "\\(da", "\\[arrowdown%s]", 14774822Srwatson "\\[arrowvertex]", 14874822Srwatson 0, 14974822Srwatson 0, 15074822Srwatson "\\[arrowvertbt]", 15174822Srwatson }, 15274822Srwatson { 15374822Srwatson "updownarrow", LEFT_DELIM|RIGHT_DELIM, "\\(va", "\\[arrowupdown%s]", 15474822Srwatson "\\[arrowvertex]", 15574822Srwatson "\\[arrowverttp]", 15674822Srwatson 0, 15783366Sjulian "\\[arrowvertbt]", 15874822Srwatson }, 15974822Srwatson}; 16074822Srwatson 16174822Srwatsonconst int DELIM_TABLE_SIZE = int(sizeof(delim_table)/sizeof(delim_table[0])); 16274822Srwatson 163105179Srwatsonclass delim_box : public box { 164105179Srwatsonprivate: 165105179Srwatson char *left; 166105179Srwatson char *right; 167105179Srwatson box *p; 168105179Srwatsonpublic: 16974822Srwatson delim_box(char *, box *, char *); 17074822Srwatson ~delim_box(); 17174822Srwatson int compute_metrics(int); 17274822Srwatson void output(); 17374822Srwatson void check_tabs(int); 17475077Srwatson void debug_print(); 17574822Srwatson}; 17674822Srwatson 17774822Srwatsonbox *make_delim_box(char *l, box *pp, char *r) 17874822Srwatson{ 17974822Srwatson if (l != 0 && *l == '\0') { 18074822Srwatson a_delete l; 18174822Srwatson l = 0; 18274822Srwatson } 18374822Srwatson if (r != 0 && *r == '\0') { 18474822Srwatson a_delete r; 18574822Srwatson r = 0; 18674822Srwatson } 18783366Sjulian return new delim_box(l, pp, r); 18874822Srwatson} 18996755Strhodes 19074822Srwatsondelim_box::delim_box(char *l, box *pp, char *r) 19191814Sgreen: left(l), right(r), p(pp) 19274822Srwatson{ 19374822Srwatson} 19474822Srwatson 19574822Srwatsondelim_box::~delim_box() 19674822Srwatson{ 19774822Srwatson a_delete left; 19874822Srwatson a_delete right; 19974822Srwatson delete p; 20075571Srwatson} 20182770Sjedgar 20274822Srwatsonstatic void build_extensible(const char *ext, const char *top, const char *mid, 20375571Srwatson const char *bot) 20482770Sjedgar{ 20574822Srwatson assert(ext != 0); 20675571Srwatson printf(".nr " DELIM_WIDTH_REG " 0\\w" DELIMITER_CHAR "%s" DELIMITER_CHAR "\n", 20782770Sjedgar ext); 20874822Srwatson printf(".nr " EXT_HEIGHT_REG " 0\\n[rst]\n"); 20974822Srwatson printf(".nr " EXT_DEPTH_REG " 0-\\n[rsb]\n"); 21074822Srwatson if (top) { 21174822Srwatson printf(".nr " DELIM_WIDTH_REG " 0\\n[" DELIM_WIDTH_REG "]" 21274822Srwatson ">?\\w" DELIMITER_CHAR "%s" DELIMITER_CHAR "\n", 21374822Srwatson top); 21474822Srwatson printf(".nr " TOP_HEIGHT_REG " 0\\n[rst]\n"); 21574822Srwatson printf(".nr " TOP_DEPTH_REG " 0-\\n[rsb]\n"); 21674822Srwatson } 21774822Srwatson if (mid) { 21874822Srwatson printf(".nr " DELIM_WIDTH_REG " 0\\n[" DELIM_WIDTH_REG "]" 21974822Srwatson ">?\\w" DELIMITER_CHAR "%s" DELIMITER_CHAR "\n", 22074822Srwatson mid); 221184629Strasz printf(".nr " MID_HEIGHT_REG " 0\\n[rst]\n"); 222184629Strasz printf(".nr " MID_DEPTH_REG " 0-\\n[rsb]\n"); 22374822Srwatson } 22474822Srwatson if (bot) { 22574822Srwatson printf(".nr " DELIM_WIDTH_REG " 0\\n[" DELIM_WIDTH_REG "]" 22674822Srwatson ">?\\w" DELIMITER_CHAR "%s" DELIMITER_CHAR "\n", 22774822Srwatson bot); 22897724Salfred printf(".nr " BOT_HEIGHT_REG " 0\\n[rst]\n"); 22997724Salfred printf(".nr " BOT_DEPTH_REG " 0-\\n[rsb]\n"); 23074822Srwatson } 23174822Srwatson printf(".nr " TOTAL_HEIGHT_REG " 0"); 23274822Srwatson if (top) 23374822Srwatson printf("+\\n[" TOP_HEIGHT_REG "]+\\n[" TOP_DEPTH_REG "]"); 23474822Srwatson if (bot) 23574822Srwatson printf("+\\n[" BOT_HEIGHT_REG "]+\\n[" BOT_DEPTH_REG "]"); 23674822Srwatson if (mid) 23774822Srwatson printf("+\\n[" MID_HEIGHT_REG "]+\\n[" MID_DEPTH_REG "]"); 23874822Srwatson printf("\n"); 23974822Srwatson // determine how many extensible characters we need 24074822Srwatson printf(".nr " TEMP_REG " \\n[" DELTA_REG "]-\\n[" TOTAL_HEIGHT_REG "]"); 24183366Sjulian if (mid) 24274822Srwatson printf("/2"); 24374822Srwatson printf(">?0+\\n[" EXT_HEIGHT_REG "]+\\n[" EXT_DEPTH_REG "]-1/(\\n[" 24474822Srwatson EXT_HEIGHT_REG "]+\\n[" EXT_DEPTH_REG "])\n"); 24574822Srwatson 24674822Srwatson printf(".nr " TOTAL_HEIGHT_REG " +(\\n[" EXT_HEIGHT_REG "]+\\n[" 24774822Srwatson EXT_DEPTH_REG "]*\\n[" TEMP_REG "]"); 24874822Srwatson if (mid) 24974822Srwatson printf("*2"); 25096755Strhodes printf(")\n"); 25174822Srwatson printf(".ds " DELIM_STRING " \\Z" DELIMITER_CHAR 25291814Sgreen "\\v'-%dM-(\\n[" TOTAL_HEIGHT_REG "]u/2u)'\n", 25374822Srwatson axis_height); 25474822Srwatson if (top) 25574822Srwatson printf(".as " DELIM_STRING " \\v'\\n[" TOP_HEIGHT_REG "]u'" 25674822Srwatson "\\Z" DELIMITER_CHAR "%s" DELIMITER_CHAR 25774822Srwatson "\\v'\\n[" TOP_DEPTH_REG "]u'\n", 25874822Srwatson top); 25975077Srwatson 26075077Srwatson // this macro appends $2 copies of $3 to string $1 26175077Srwatson printf(".de " REPEAT_APPEND_STRING_MACRO "\n" 26275077Srwatson ".if \\\\$2 \\{.as \\\\$1 \"\\\\$3\n" 26375077Srwatson "." REPEAT_APPEND_STRING_MACRO " \\\\$1 \\\\$2-1 \"\\\\$3\"\n" 26475077Srwatson ".\\}\n" 26575077Srwatson "..\n"); 26675077Srwatson 267184629Strasz printf("." REPEAT_APPEND_STRING_MACRO " " DELIM_STRING " \\n[" TEMP_REG "] " 268184629Strasz "\\v'\\n[" EXT_HEIGHT_REG "]u'" 26975077Srwatson "\\Z" DELIMITER_CHAR "%s" DELIMITER_CHAR 27075077Srwatson "\\v'\\n[" EXT_DEPTH_REG "]u'\n", 27174822Srwatson ext); 27274822Srwatson 27397724Salfred if (mid) { 27497724Salfred printf(".as " DELIM_STRING " \\v'\\n[" MID_HEIGHT_REG "]u'" 27574822Srwatson "\\Z" DELIMITER_CHAR "%s" DELIMITER_CHAR 27674822Srwatson "\\v'\\n[" MID_DEPTH_REG "]u'\n", 27774822Srwatson mid); 27874822Srwatson printf("." REPEAT_APPEND_STRING_MACRO " " DELIM_STRING 27974822Srwatson " \\n[" TEMP_REG "] " 28074822Srwatson "\\v'\\n[" EXT_HEIGHT_REG "]u'" 28174822Srwatson "\\Z" DELIMITER_CHAR "%s" DELIMITER_CHAR 28274822Srwatson "\\v'\\n[" EXT_DEPTH_REG "]u'\n", 28374822Srwatson ext); 28474822Srwatson } 28574822Srwatson if (bot) 28674822Srwatson printf(".as " DELIM_STRING " \\v'\\n[" BOT_HEIGHT_REG "]u'" 28774822Srwatson "\\Z" DELIMITER_CHAR "%s" DELIMITER_CHAR 28874822Srwatson "\\v'\\n[" BOT_DEPTH_REG "]u'\n", 28974822Srwatson bot); 29074822Srwatson printf(".as " DELIM_STRING " " DELIMITER_CHAR "\n"); 29174822Srwatson} 29274822Srwatson 29374822Srwatsonstatic void define_extensible_string(char *delim, int uid, 29474822Srwatson left_or_right_t left_or_right) 29574822Srwatson{ 29674822Srwatson printf(".ds " DELIM_STRING "\n"); 29774822Srwatson delimiter *d = delim_table; 29874822Srwatson int delim_len = strlen(delim); 29974822Srwatson int i; 30074822Srwatson for (i = 0; i < DELIM_TABLE_SIZE; i++, d++) 30174822Srwatson if (strncmp(delim, d->name, delim_len) == 0 30274822Srwatson && (left_or_right & d->flags) != 0) 30374822Srwatson break; 30474822Srwatson if (i >= DELIM_TABLE_SIZE) { 30575571Srwatson error("there is no `%1' delimiter", delim); 30674822Srwatson printf(".nr " DELIM_WIDTH_REG " 0\n"); 307105179Srwatson return; 308105179Srwatson } 309105179Srwatson 31074822Srwatson printf(".nr " DELIM_WIDTH_REG " 0\\w" DELIMITER_CHAR "\\f[%s]%s\\fP" DELIMITER_CHAR "\n" 31174822Srwatson ".ds " DELIM_STRING " \\Z" DELIMITER_CHAR 31274822Srwatson "\\v'\\n[rsb]u+\\n[rst]u/2u-%dM'\\f[%s]%s\\fP" DELIMITER_CHAR "\n" 31374822Srwatson ".nr " TOTAL_HEIGHT_REG " \\n[rst]-\\n[rsb]\n" 31474822Srwatson ".if \\n[" TOTAL_HEIGHT_REG "]<\\n[" DELTA_REG "] " 31574822Srwatson "\\{", 31674822Srwatson current_roman_font, d->small, axis_height, 31774822Srwatson current_roman_font, d->small); 31874822Srwatson 31974822Srwatson char buf[256]; 32083366Sjulian sprintf(buf, d->chain_format, "\\\\n[" INDEX_REG "]"); 32174822Srwatson printf(".nr " INDEX_REG " 0\n" 32274822Srwatson ".de " TEMP_MACRO "\n" 32374822Srwatson ".ie c%s \\{\\\n" 32474822Srwatson ".nr " DELIM_WIDTH_REG " 0\\w" DELIMITER_CHAR "%s" DELIMITER_CHAR "\n" 32574822Srwatson ".ds " DELIM_STRING " \\Z" DELIMITER_CHAR 32674822Srwatson "\\v'\\\\n[rsb]u+\\\\n[rst]u/2u-%dM'%s" DELIMITER_CHAR "\n" 32774822Srwatson ".nr " TOTAL_HEIGHT_REG " \\\\n[rst]-\\\\n[rsb]\n" 32874822Srwatson ".if \\\\n[" TOTAL_HEIGHT_REG "]<\\n[" DELTA_REG "] " 32974822Srwatson "\\{.nr " INDEX_REG " +1\n" 33074822Srwatson "." TEMP_MACRO "\n" 33174822Srwatson ".\\}\\}\n" 33274822Srwatson ".el .nr " INDEX_REG " 0-1\n" 33374822Srwatson "..\n" 33474822Srwatson "." TEMP_MACRO "\n", 33574822Srwatson buf, buf, axis_height, buf); 33674822Srwatson if (d->ext) { 33774822Srwatson printf(".if \\n[" INDEX_REG "]<0 \\{.if c%s \\{\\\n", d->ext); 33874822Srwatson build_extensible(d->ext, d->top, d->mid, d->bot); 33974822Srwatson printf(".\\}\\}\n"); 34074822Srwatson } 34174822Srwatson printf(".\\}\n"); 34274822Srwatson printf(".as " DELIM_STRING " \\h'\\n[" DELIM_WIDTH_REG "]u'\n"); 34374822Srwatson printf(".nr " WIDTH_FORMAT " +\\n[" DELIM_WIDTH_REG "]\n", uid); 34474822Srwatson printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]" 34574822Srwatson ">?(\\n[" TOTAL_HEIGHT_REG "]/2+%dM)\n", 34674822Srwatson uid, uid, axis_height); 34783366Sjulian printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]" 34874822Srwatson ">?(\\n[" TOTAL_HEIGHT_REG "]/2-%dM)\n", 34974822Srwatson uid, uid, axis_height); 35074822Srwatson} 35174822Srwatson 35274822Srwatsonint delim_box::compute_metrics(int style) 35374822Srwatson{ 35474822Srwatson int r = p->compute_metrics(style); 35583366Sjulian printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid); 35674822Srwatson printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid); 35774822Srwatson printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid); 35874822Srwatson printf(".nr " DELTA_REG " \\n[" HEIGHT_FORMAT "]-%dM" 35974822Srwatson ">?(\\n[" DEPTH_FORMAT "]+%dM)\n", 36074822Srwatson p->uid, axis_height, p->uid, axis_height); 36174822Srwatson printf(".nr " DELTA_REG " 0\\n[" DELTA_REG "]*%d/500" 36283366Sjulian ">?(\\n[" DELTA_REG "]*2-%dM)\n", 36374822Srwatson delimiter_factor, delimiter_shortfall); 36474822Srwatson if (left) { 36574822Srwatson define_extensible_string(left, uid, LEFT_DELIM); 36674822Srwatson printf(".rn " DELIM_STRING " " LEFT_DELIM_STRING_FORMAT "\n", 36785581Srwatson uid); 36885581Srwatson if (r) 36985581Srwatson printf(".nr " MARK_REG " +\\n[" DELIM_WIDTH_REG "]\n"); 37085581Srwatson } 37191814Sgreen if (right) { 37274822Srwatson define_extensible_string(right, uid, RIGHT_DELIM); 37391814Sgreen printf(".rn " DELIM_STRING " " RIGHT_DELIM_STRING_FORMAT "\n", 37474822Srwatson uid); 37574822Srwatson } 37674822Srwatson return r; 37774822Srwatson} 37874822Srwatson 37983366Sjulianvoid delim_box::output() 38074822Srwatson{ 38174822Srwatson if (left) 38274822Srwatson printf("\\*[" LEFT_DELIM_STRING_FORMAT "]", uid); 38374822Srwatson p->output(); 38474822Srwatson if (right) 38574822Srwatson printf("\\*[" RIGHT_DELIM_STRING_FORMAT "]", uid); 38674822Srwatson} 38796755Strhodes 38874822Srwatsonvoid delim_box::check_tabs(int level) 38991814Sgreen{ 39074822Srwatson p->check_tabs(level); 39174822Srwatson} 39274822Srwatson 39374822Srwatsonvoid delim_box::debug_print() 39474822Srwatson{ 39574822Srwatson fprintf(stderr, "left \"%s\" { ", left ? left : ""); 39674822Srwatson p->debug_print(); 39774822Srwatson fprintf(stderr, " }"); 39874822Srwatson if (right) 399118411Srwatson fprintf(stderr, " right \"%s\"", right); 40074822Srwatson} 40174822Srwatson 40274822Srwatson