Update to groff 1.19.2.
[dragonfly.git] / contrib / groff-1.19 / src / preproc / eqn / list.cpp
blob003562afa5010bc33ebb028c689347021b20c2a7
1 // -*- C++ -*-
2 /* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
3 Written by James Clark (jjc@jclark.com)
5 This file is part of groff.
7 groff is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
12 groff is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 You should have received a copy of the GNU General Public License along
18 with groff; see the file COPYING. If not, write to the Free Software
19 Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
21 #include "eqn.h"
22 #include "pbox.h"
24 list_box *box::to_list_box()
26 return 0;
29 list_box *list_box::to_list_box()
31 return this;
34 void list_box::append(box *pp)
36 list_box *q = pp->to_list_box();
37 if (q == 0)
38 list.append(pp);
39 else {
40 for (int i = 0; i < q->list.len; i++) {
41 list.append(q->list.p[i]);
42 q->list.p[i] = 0;
44 q->list.len = 0;
45 delete q;
49 list_box::list_box(box *pp) : list(pp), sty(-1)
51 list_box *q = pp->to_list_box();
52 if (q != 0) {
53 // flatten it
54 list.p[0] = q->list.p[0];
55 for (int i = 1; i < q->list.len; i++) {
56 list.append(q->list.p[i]);
57 q->list.p[i] = 0;
59 q->list.len = 0;
60 delete q;
64 static int compute_spacing(int is_script, int left, int right)
66 if (left == SUPPRESS_TYPE || right == SUPPRESS_TYPE)
67 return 0;
68 if (left == PUNCTUATION_TYPE)
69 return is_script ? 0 : thin_space;
70 if (left == OPENING_TYPE || right == CLOSING_TYPE)
71 return 0;
72 if (right == BINARY_TYPE || left == BINARY_TYPE)
73 return is_script ? 0 : medium_space;
74 if (right == RELATION_TYPE) {
75 if (left == RELATION_TYPE)
76 return 0;
77 else
78 return is_script ? 0 : thick_space;
80 if (left == RELATION_TYPE)
81 return is_script ? 0 : thick_space;
82 if (right == OPERATOR_TYPE)
83 return thin_space;
84 if (left == INNER_TYPE || right == INNER_TYPE)
85 return is_script ? 0 : thin_space;
86 if (left == OPERATOR_TYPE && right == ORDINARY_TYPE)
87 return thin_space;
88 return 0;
91 int list_box::compute_metrics(int style)
93 sty = style;
94 int i;
95 for (i = 0; i < list.len; i++) {
96 int t = list.p[i]->spacing_type;
97 // 5
98 if (t == BINARY_TYPE) {
99 int prevt;
100 if (i == 0
101 || (prevt = list.p[i-1]->spacing_type) == BINARY_TYPE
102 || prevt == OPERATOR_TYPE
103 || prevt == RELATION_TYPE
104 || prevt == OPENING_TYPE
105 || prevt == PUNCTUATION_TYPE)
106 list.p[i]->spacing_type = ORDINARY_TYPE;
108 // 7
109 else if ((t == RELATION_TYPE || t == CLOSING_TYPE
110 || t == PUNCTUATION_TYPE)
111 && i > 0 && list.p[i-1]->spacing_type == BINARY_TYPE)
112 list.p[i-1]->spacing_type = ORDINARY_TYPE;
114 for (i = 0; i < list.len; i++) {
115 unsigned flags = 0;
116 if (i - 1 >= 0 && list.p[i - 1]->right_is_italic())
117 flags |= HINT_PREV_IS_ITALIC;
118 if (i + 1 < list.len && list.p[i + 1]->left_is_italic())
119 flags |= HINT_NEXT_IS_ITALIC;
120 if (flags)
121 list.p[i]->hint(flags);
123 is_script = (style <= SCRIPT_STYLE);
124 int total_spacing = 0;
125 for (i = 1; i < list.len; i++)
126 total_spacing += compute_spacing(is_script, list.p[i-1]->spacing_type,
127 list.p[i]->spacing_type);
128 int res = 0;
129 for (i = 0; i < list.len; i++)
130 if (!list.p[i]->is_simple()) {
131 int r = list.p[i]->compute_metrics(style);
132 if (r) {
133 if (res)
134 error("multiple marks and lineups");
135 else {
136 compute_sublist_width(i);
137 printf(".nr " MARK_REG " +\\n[" TEMP_REG"]\n");
138 res = r;
142 printf(".nr " WIDTH_FORMAT " %dM", uid, total_spacing);
143 for (i = 0; i < list.len; i++)
144 if (!list.p[i]->is_simple())
145 printf("+\\n[" WIDTH_FORMAT "]", list.p[i]->uid);
146 printf("\n");
147 printf(".nr " HEIGHT_FORMAT " 0", uid);
148 for (i = 0; i < list.len; i++)
149 if (!list.p[i]->is_simple())
150 printf(">?\\n[" HEIGHT_FORMAT "]", list.p[i]->uid);
151 printf("\n");
152 printf(".nr " DEPTH_FORMAT " 0", uid);
153 for (i = 0; i < list.len; i++)
154 if (!list.p[i]->is_simple())
155 printf(">?\\n[" DEPTH_FORMAT "]", list.p[i]->uid);
156 printf("\n");
157 int have_simple = 0;
158 for (i = 0; i < list.len && !have_simple; i++)
159 have_simple = list.p[i]->is_simple();
160 if (have_simple) {
161 printf(".nr " WIDTH_FORMAT " +\\w" DELIMITER_CHAR, uid);
162 for (i = 0; i < list.len; i++)
163 if (list.p[i]->is_simple())
164 list.p[i]->output();
165 printf(DELIMITER_CHAR "\n");
166 printf(".nr " HEIGHT_FORMAT " \\n[rst]>?\\n[" HEIGHT_FORMAT "]\n",
167 uid, uid);
168 printf(".nr " DEPTH_FORMAT " 0-\\n[rsb]>?\\n[" DEPTH_FORMAT "]\n",
169 uid, uid);
171 return res;
174 void list_box::compute_sublist_width(int n)
176 int total_spacing = 0;
177 int i;
178 for (i = 1; i < n + 1 && i < list.len; i++)
179 total_spacing += compute_spacing(is_script, list.p[i-1]->spacing_type,
180 list.p[i]->spacing_type);
181 printf(".nr " TEMP_REG " %dM", total_spacing);
182 for (i = 0; i < n; i++)
183 if (!list.p[i]->is_simple())
184 printf("+\\n[" WIDTH_FORMAT "]", list.p[i]->uid);
185 int have_simple = 0;
186 for (i = 0; i < n && !have_simple; i++)
187 have_simple = list.p[i]->is_simple();
188 if (have_simple) {
189 printf("+\\w" DELIMITER_CHAR);
190 for (i = 0; i < n; i++)
191 if (list.p[i]->is_simple())
192 list.p[i]->output();
193 printf(DELIMITER_CHAR);
195 printf("\n");
198 void list_box::compute_subscript_kern()
200 // We can only call compute_subscript_kern if we have called
201 // compute_metrics first.
202 if (list.p[list.len-1]->is_simple())
203 list.p[list.len-1]->compute_metrics(sty);
204 list.p[list.len-1]->compute_subscript_kern();
205 printf(".nr " SUB_KERN_FORMAT " \\n[" SUB_KERN_FORMAT "]\n",
206 uid, list.p[list.len-1]->uid);
209 void list_box::output()
211 for (int i = 0; i < list.len; i++) {
212 if (i > 0) {
213 int n = compute_spacing(is_script,
214 list.p[i-1]->spacing_type,
215 list.p[i]->spacing_type);
216 if (n > 0)
217 printf("\\h'%dM'", n);
219 list.p[i]->output();
223 void list_box::handle_char_type(int st, int ft)
225 for (int i = 0; i < list.len; i++)
226 list.p[i]->handle_char_type(st, ft);
229 void list_box::debug_print()
231 list.list_debug_print(" ");
234 void list_box::check_tabs(int level)
236 list.list_check_tabs(level);