1 /* $NetBSD: list.cpp,v 1.1.1.1 2016/01/13 18:41:49 christos Exp $ */ 2 3 // -*- C++ -*- 4 /* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. 5 Written by James Clark (jjc@jclark.com) 6 7 This file is part of groff. 8 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 12 version. 13 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 17 for more details. 18 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. */ 22 23 #include "eqn.h" 24 #include "pbox.h" 25 26 list_box *box::to_list_box() 27 { 28 return 0; 29 } 30 31 list_box *list_box::to_list_box() 32 { 33 return this; 34 } 35 36 void list_box::append(box *pp) 37 { 38 list_box *q = pp->to_list_box(); 39 if (q == 0) 40 list.append(pp); 41 else { 42 for (int i = 0; i < q->list.len; i++) { 43 list.append(q->list.p[i]); 44 q->list.p[i] = 0; 45 } 46 q->list.len = 0; 47 delete q; 48 } 49 } 50 51 list_box::list_box(box *pp) : list(pp), sty(-1) 52 { 53 list_box *q = pp->to_list_box(); 54 if (q != 0) { 55 // flatten it 56 list.p[0] = q->list.p[0]; 57 for (int i = 1; i < q->list.len; i++) { 58 list.append(q->list.p[i]); 59 q->list.p[i] = 0; 60 } 61 q->list.len = 0; 62 delete q; 63 } 64 } 65 66 static int compute_spacing(int is_script, int left, int right) 67 { 68 if (left == SUPPRESS_TYPE || right == SUPPRESS_TYPE) 69 return 0; 70 if (left == PUNCTUATION_TYPE) 71 return is_script ? 0 : thin_space; 72 if (left == OPENING_TYPE || right == CLOSING_TYPE) 73 return 0; 74 if (right == BINARY_TYPE || left == BINARY_TYPE) 75 return is_script ? 0 : medium_space; 76 if (right == RELATION_TYPE) { 77 if (left == RELATION_TYPE) 78 return 0; 79 else 80 return is_script ? 0 : thick_space; 81 } 82 if (left == RELATION_TYPE) 83 return is_script ? 0 : thick_space; 84 if (right == OPERATOR_TYPE) 85 return thin_space; 86 if (left == INNER_TYPE || right == INNER_TYPE) 87 return is_script ? 0 : thin_space; 88 if (left == OPERATOR_TYPE && right == ORDINARY_TYPE) 89 return thin_space; 90 return 0; 91 } 92 93 int list_box::compute_metrics(int style) 94 { 95 sty = style; 96 int i; 97 for (i = 0; i < list.len; i++) { 98 int t = list.p[i]->spacing_type; 99 // 5 100 if (t == BINARY_TYPE) { 101 int prevt; 102 if (i == 0 103 || (prevt = list.p[i-1]->spacing_type) == BINARY_TYPE 104 || prevt == OPERATOR_TYPE 105 || prevt == RELATION_TYPE 106 || prevt == OPENING_TYPE 107 || prevt == PUNCTUATION_TYPE) 108 list.p[i]->spacing_type = ORDINARY_TYPE; 109 } 110 // 7 111 else if ((t == RELATION_TYPE || t == CLOSING_TYPE 112 || t == PUNCTUATION_TYPE) 113 && i > 0 && list.p[i-1]->spacing_type == BINARY_TYPE) 114 list.p[i-1]->spacing_type = ORDINARY_TYPE; 115 } 116 for (i = 0; i < list.len; i++) { 117 unsigned flags = 0; 118 if (i - 1 >= 0 && list.p[i - 1]->right_is_italic()) 119 flags |= HINT_PREV_IS_ITALIC; 120 if (i + 1 < list.len && list.p[i + 1]->left_is_italic()) 121 flags |= HINT_NEXT_IS_ITALIC; 122 if (flags) 123 list.p[i]->hint(flags); 124 } 125 is_script = (style <= SCRIPT_STYLE); 126 int total_spacing = 0; 127 for (i = 1; i < list.len; i++) 128 total_spacing += compute_spacing(is_script, list.p[i-1]->spacing_type, 129 list.p[i]->spacing_type); 130 int res = 0; 131 for (i = 0; i < list.len; i++) 132 if (!list.p[i]->is_simple()) { 133 int r = list.p[i]->compute_metrics(style); 134 if (r) { 135 if (res) 136 error("multiple marks and lineups"); 137 else { 138 compute_sublist_width(i); 139 printf(".nr " MARK_REG " +\\n[" TEMP_REG"]\n"); 140 res = r; 141 } 142 } 143 } 144 printf(".nr " WIDTH_FORMAT " %dM", uid, total_spacing); 145 for (i = 0; i < list.len; i++) 146 if (!list.p[i]->is_simple()) 147 printf("+\\n[" WIDTH_FORMAT "]", list.p[i]->uid); 148 printf("\n"); 149 printf(".nr " HEIGHT_FORMAT " 0", uid); 150 for (i = 0; i < list.len; i++) 151 if (!list.p[i]->is_simple()) 152 printf(">?\\n[" HEIGHT_FORMAT "]", list.p[i]->uid); 153 printf("\n"); 154 printf(".nr " DEPTH_FORMAT " 0", uid); 155 for (i = 0; i < list.len; i++) 156 if (!list.p[i]->is_simple()) 157 printf(">?\\n[" DEPTH_FORMAT "]", list.p[i]->uid); 158 printf("\n"); 159 int have_simple = 0; 160 for (i = 0; i < list.len && !have_simple; i++) 161 have_simple = list.p[i]->is_simple(); 162 if (have_simple) { 163 printf(".nr " WIDTH_FORMAT " +\\w" DELIMITER_CHAR, uid); 164 for (i = 0; i < list.len; i++) 165 if (list.p[i]->is_simple()) 166 list.p[i]->output(); 167 printf(DELIMITER_CHAR "\n"); 168 printf(".nr " HEIGHT_FORMAT " \\n[rst]>?\\n[" HEIGHT_FORMAT "]\n", 169 uid, uid); 170 printf(".nr " DEPTH_FORMAT " 0-\\n[rsb]>?\\n[" DEPTH_FORMAT "]\n", 171 uid, uid); 172 } 173 return res; 174 } 175 176 void list_box::compute_sublist_width(int n) 177 { 178 int total_spacing = 0; 179 int i; 180 for (i = 1; i < n + 1 && i < list.len; i++) 181 total_spacing += compute_spacing(is_script, list.p[i-1]->spacing_type, 182 list.p[i]->spacing_type); 183 printf(".nr " TEMP_REG " %dM", total_spacing); 184 for (i = 0; i < n; i++) 185 if (!list.p[i]->is_simple()) 186 printf("+\\n[" WIDTH_FORMAT "]", list.p[i]->uid); 187 int have_simple = 0; 188 for (i = 0; i < n && !have_simple; i++) 189 have_simple = list.p[i]->is_simple(); 190 if (have_simple) { 191 printf("+\\w" DELIMITER_CHAR); 192 for (i = 0; i < n; i++) 193 if (list.p[i]->is_simple()) 194 list.p[i]->output(); 195 printf(DELIMITER_CHAR); 196 } 197 printf("\n"); 198 } 199 200 void list_box::compute_subscript_kern() 201 { 202 // We can only call compute_subscript_kern if we have called 203 // compute_metrics first. 204 if (list.p[list.len-1]->is_simple()) 205 list.p[list.len-1]->compute_metrics(sty); 206 list.p[list.len-1]->compute_subscript_kern(); 207 printf(".nr " SUB_KERN_FORMAT " \\n[" SUB_KERN_FORMAT "]\n", 208 uid, list.p[list.len-1]->uid); 209 } 210 211 void list_box::output() 212 { 213 for (int i = 0; i < list.len; i++) { 214 if (i > 0) { 215 int n = compute_spacing(is_script, 216 list.p[i-1]->spacing_type, 217 list.p[i]->spacing_type); 218 if (n > 0) 219 printf("\\h'%dM'", n); 220 } 221 list.p[i]->output(); 222 } 223 } 224 225 void list_box::handle_char_type(int st, int ft) 226 { 227 for (int i = 0; i < list.len; i++) 228 list.p[i]->handle_char_type(st, ft); 229 } 230 231 void list_box::debug_print() 232 { 233 list.list_debug_print(" "); 234 } 235 236 void list_box::check_tabs(int level) 237 { 238 list.list_check_tabs(level); 239 } 240