1114402Sru// -*- C++ -*- 2114402Sru/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. 3114402Sru Written by James Clark (jjc@jclark.com) 4114402Sru 5114402SruThis file is part of groff. 6114402Sru 7114402Srugroff is free software; you can redistribute it and/or modify it under 8114402Sruthe terms of the GNU General Public License as published by the Free 9114402SruSoftware Foundation; either version 2, or (at your option) any later 10114402Sruversion. 11114402Sru 12114402Srugroff is distributed in the hope that it will be useful, but WITHOUT ANY 13114402SruWARRANTY; without even the implied warranty of MERCHANTABILITY or 14114402SruFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15114402Srufor more details. 16114402Sru 17114402SruYou should have received a copy of the GNU General Public License along 18114402Sruwith groff; see the file COPYING. If not, write to the Free Software 19151497SruFoundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ 20114402Sru 21114402Sru#include "eqn.h" 22114402Sru#include "pbox.h" 23114402Sru 24114402Srulist_box *box::to_list_box() 25114402Sru{ 26114402Sru return 0; 27114402Sru} 28114402Sru 29114402Srulist_box *list_box::to_list_box() 30114402Sru{ 31114402Sru return this; 32114402Sru} 33114402Sru 34114402Sruvoid list_box::append(box *pp) 35114402Sru{ 36114402Sru list_box *q = pp->to_list_box(); 37114402Sru if (q == 0) 38114402Sru list.append(pp); 39114402Sru else { 40114402Sru for (int i = 0; i < q->list.len; i++) { 41114402Sru list.append(q->list.p[i]); 42114402Sru q->list.p[i] = 0; 43114402Sru } 44114402Sru q->list.len = 0; 45114402Sru delete q; 46114402Sru } 47114402Sru} 48114402Sru 49114402Srulist_box::list_box(box *pp) : list(pp), sty(-1) 50114402Sru{ 51114402Sru list_box *q = pp->to_list_box(); 52114402Sru if (q != 0) { 53114402Sru // flatten it 54114402Sru list.p[0] = q->list.p[0]; 55114402Sru for (int i = 1; i < q->list.len; i++) { 56114402Sru list.append(q->list.p[i]); 57114402Sru q->list.p[i] = 0; 58114402Sru } 59114402Sru q->list.len = 0; 60114402Sru delete q; 61114402Sru } 62114402Sru} 63114402Sru 64114402Srustatic int compute_spacing(int is_script, int left, int right) 65114402Sru{ 66114402Sru if (left == SUPPRESS_TYPE || right == SUPPRESS_TYPE) 67114402Sru return 0; 68114402Sru if (left == PUNCTUATION_TYPE) 69114402Sru return is_script ? 0 : thin_space; 70114402Sru if (left == OPENING_TYPE || right == CLOSING_TYPE) 71114402Sru return 0; 72114402Sru if (right == BINARY_TYPE || left == BINARY_TYPE) 73114402Sru return is_script ? 0 : medium_space; 74114402Sru if (right == RELATION_TYPE) { 75114402Sru if (left == RELATION_TYPE) 76114402Sru return 0; 77114402Sru else 78114402Sru return is_script ? 0 : thick_space; 79114402Sru } 80114402Sru if (left == RELATION_TYPE) 81114402Sru return is_script ? 0 : thick_space; 82114402Sru if (right == OPERATOR_TYPE) 83114402Sru return thin_space; 84114402Sru if (left == INNER_TYPE || right == INNER_TYPE) 85114402Sru return is_script ? 0 : thin_space; 86114402Sru if (left == OPERATOR_TYPE && right == ORDINARY_TYPE) 87114402Sru return thin_space; 88114402Sru return 0; 89114402Sru} 90114402Sru 91114402Sruint list_box::compute_metrics(int style) 92114402Sru{ 93114402Sru sty = style; 94114402Sru int i; 95114402Sru for (i = 0; i < list.len; i++) { 96114402Sru int t = list.p[i]->spacing_type; 97114402Sru // 5 98114402Sru if (t == BINARY_TYPE) { 99114402Sru int prevt; 100114402Sru if (i == 0 101114402Sru || (prevt = list.p[i-1]->spacing_type) == BINARY_TYPE 102114402Sru || prevt == OPERATOR_TYPE 103114402Sru || prevt == RELATION_TYPE 104114402Sru || prevt == OPENING_TYPE 105114402Sru || prevt == PUNCTUATION_TYPE) 106114402Sru list.p[i]->spacing_type = ORDINARY_TYPE; 107114402Sru } 108114402Sru // 7 109114402Sru else if ((t == RELATION_TYPE || t == CLOSING_TYPE 110114402Sru || t == PUNCTUATION_TYPE) 111114402Sru && i > 0 && list.p[i-1]->spacing_type == BINARY_TYPE) 112114402Sru list.p[i-1]->spacing_type = ORDINARY_TYPE; 113114402Sru } 114114402Sru for (i = 0; i < list.len; i++) { 115114402Sru unsigned flags = 0; 116114402Sru if (i - 1 >= 0 && list.p[i - 1]->right_is_italic()) 117114402Sru flags |= HINT_PREV_IS_ITALIC; 118114402Sru if (i + 1 < list.len && list.p[i + 1]->left_is_italic()) 119114402Sru flags |= HINT_NEXT_IS_ITALIC; 120114402Sru if (flags) 121114402Sru list.p[i]->hint(flags); 122114402Sru } 123114402Sru is_script = (style <= SCRIPT_STYLE); 124114402Sru int total_spacing = 0; 125114402Sru for (i = 1; i < list.len; i++) 126114402Sru total_spacing += compute_spacing(is_script, list.p[i-1]->spacing_type, 127114402Sru list.p[i]->spacing_type); 128114402Sru int res = 0; 129114402Sru for (i = 0; i < list.len; i++) 130114402Sru if (!list.p[i]->is_simple()) { 131114402Sru int r = list.p[i]->compute_metrics(style); 132114402Sru if (r) { 133114402Sru if (res) 134114402Sru error("multiple marks and lineups"); 135114402Sru else { 136114402Sru compute_sublist_width(i); 137114402Sru printf(".nr " MARK_REG " +\\n[" TEMP_REG"]\n"); 138114402Sru res = r; 139114402Sru } 140114402Sru } 141114402Sru } 142114402Sru printf(".nr " WIDTH_FORMAT " %dM", uid, total_spacing); 143114402Sru for (i = 0; i < list.len; i++) 144114402Sru if (!list.p[i]->is_simple()) 145114402Sru printf("+\\n[" WIDTH_FORMAT "]", list.p[i]->uid); 146114402Sru printf("\n"); 147114402Sru printf(".nr " HEIGHT_FORMAT " 0", uid); 148114402Sru for (i = 0; i < list.len; i++) 149114402Sru if (!list.p[i]->is_simple()) 150114402Sru printf(">?\\n[" HEIGHT_FORMAT "]", list.p[i]->uid); 151114402Sru printf("\n"); 152114402Sru printf(".nr " DEPTH_FORMAT " 0", uid); 153114402Sru for (i = 0; i < list.len; i++) 154114402Sru if (!list.p[i]->is_simple()) 155114402Sru printf(">?\\n[" DEPTH_FORMAT "]", list.p[i]->uid); 156114402Sru printf("\n"); 157114402Sru int have_simple = 0; 158114402Sru for (i = 0; i < list.len && !have_simple; i++) 159114402Sru have_simple = list.p[i]->is_simple(); 160114402Sru if (have_simple) { 161114402Sru printf(".nr " WIDTH_FORMAT " +\\w" DELIMITER_CHAR, uid); 162114402Sru for (i = 0; i < list.len; i++) 163114402Sru if (list.p[i]->is_simple()) 164114402Sru list.p[i]->output(); 165114402Sru printf(DELIMITER_CHAR "\n"); 166114402Sru printf(".nr " HEIGHT_FORMAT " \\n[rst]>?\\n[" HEIGHT_FORMAT "]\n", 167114402Sru uid, uid); 168114402Sru printf(".nr " DEPTH_FORMAT " 0-\\n[rsb]>?\\n[" DEPTH_FORMAT "]\n", 169114402Sru uid, uid); 170114402Sru } 171114402Sru return res; 172114402Sru} 173114402Sru 174114402Sruvoid list_box::compute_sublist_width(int n) 175114402Sru{ 176114402Sru int total_spacing = 0; 177114402Sru int i; 178114402Sru for (i = 1; i < n + 1 && i < list.len; i++) 179114402Sru total_spacing += compute_spacing(is_script, list.p[i-1]->spacing_type, 180114402Sru list.p[i]->spacing_type); 181114402Sru printf(".nr " TEMP_REG " %dM", total_spacing); 182114402Sru for (i = 0; i < n; i++) 183114402Sru if (!list.p[i]->is_simple()) 184114402Sru printf("+\\n[" WIDTH_FORMAT "]", list.p[i]->uid); 185114402Sru int have_simple = 0; 186114402Sru for (i = 0; i < n && !have_simple; i++) 187114402Sru have_simple = list.p[i]->is_simple(); 188114402Sru if (have_simple) { 189114402Sru printf("+\\w" DELIMITER_CHAR); 190114402Sru for (i = 0; i < n; i++) 191114402Sru if (list.p[i]->is_simple()) 192114402Sru list.p[i]->output(); 193114402Sru printf(DELIMITER_CHAR); 194114402Sru } 195114402Sru printf("\n"); 196114402Sru} 197114402Sru 198114402Sruvoid list_box::compute_subscript_kern() 199114402Sru{ 200114402Sru // We can only call compute_subscript_kern if we have called 201114402Sru // compute_metrics first. 202114402Sru if (list.p[list.len-1]->is_simple()) 203114402Sru list.p[list.len-1]->compute_metrics(sty); 204114402Sru list.p[list.len-1]->compute_subscript_kern(); 205114402Sru printf(".nr " SUB_KERN_FORMAT " \\n[" SUB_KERN_FORMAT "]\n", 206114402Sru uid, list.p[list.len-1]->uid); 207114402Sru} 208114402Sru 209114402Sruvoid list_box::output() 210114402Sru{ 211114402Sru for (int i = 0; i < list.len; i++) { 212114402Sru if (i > 0) { 213114402Sru int n = compute_spacing(is_script, 214114402Sru list.p[i-1]->spacing_type, 215114402Sru list.p[i]->spacing_type); 216114402Sru if (n > 0) 217114402Sru printf("\\h'%dM'", n); 218114402Sru } 219114402Sru list.p[i]->output(); 220114402Sru } 221114402Sru} 222114402Sru 223114402Sruvoid list_box::handle_char_type(int st, int ft) 224114402Sru{ 225114402Sru for (int i = 0; i < list.len; i++) 226114402Sru list.p[i]->handle_char_type(st, ft); 227114402Sru} 228114402Sru 229114402Sruvoid list_box::debug_print() 230114402Sru{ 231114402Sru list.list_debug_print(" "); 232114402Sru} 233114402Sru 234114402Sruvoid list_box::check_tabs(int level) 235114402Sru{ 236114402Sru list.list_check_tabs(level); 237114402Sru} 238