Adapt src/pre-eqn (src/preproc/eqn)
[s-roff.git] / src / pre-eqn / list.cpp
blobc31cbe5bef571d0a6c5c0c53e972894b8a751b9e
1 /*@
2 * Copyright (c) 2014 Steffen (Daode) Nurpmeso <sdaoden@users.sf.net>.
4 * Copyright (C) 1989 - 1992, 2007 Free Software Foundation, Inc.
5 * Written by James Clark (jjc@jclark.com)
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.
22 #include "config.h"
23 #include "eqn-config.h"
25 #include "eqn.h"
26 #include "pbox.h"
28 list_box *box::to_list_box()
30 return 0;
33 list_box *list_box::to_list_box()
35 return this;
38 void list_box::append(box *pp)
40 list_box *q = pp->to_list_box();
41 if (q == 0)
42 list.append(pp);
43 else {
44 for (int i = 0; i < q->list.len; i++) {
45 list.append(q->list.p[i]);
46 q->list.p[i] = 0;
48 q->list.len = 0;
49 delete q;
53 list_box::list_box(box *pp) : list(pp), sty(-1)
55 list_box *q = pp->to_list_box();
56 if (q != 0) {
57 // flatten it
58 list.p[0] = q->list.p[0];
59 for (int i = 1; i < q->list.len; i++) {
60 list.append(q->list.p[i]);
61 q->list.p[i] = 0;
63 q->list.len = 0;
64 delete q;
68 static int compute_spacing(int is_script, int left, int right)
70 if (left == SUPPRESS_TYPE || right == SUPPRESS_TYPE)
71 return 0;
72 if (left == PUNCTUATION_TYPE)
73 return is_script ? 0 : thin_space;
74 if (left == OPENING_TYPE || right == CLOSING_TYPE)
75 return 0;
76 if (right == BINARY_TYPE || left == BINARY_TYPE)
77 return is_script ? 0 : medium_space;
78 if (right == RELATION_TYPE) {
79 if (left == RELATION_TYPE)
80 return 0;
81 else
82 return is_script ? 0 : thick_space;
84 if (left == RELATION_TYPE)
85 return is_script ? 0 : thick_space;
86 if (right == OPERATOR_TYPE)
87 return thin_space;
88 if (left == INNER_TYPE || right == INNER_TYPE)
89 return is_script ? 0 : thin_space;
90 if (left == OPERATOR_TYPE && right == ORDINARY_TYPE)
91 return thin_space;
92 return 0;
95 int list_box::compute_metrics(int style)
97 sty = style;
98 int i;
99 for (i = 0; i < list.len; i++) {
100 int t = list.p[i]->spacing_type;
101 // 5
102 if (t == BINARY_TYPE) {
103 int prevt;
104 if (i == 0
105 || (prevt = list.p[i-1]->spacing_type) == BINARY_TYPE
106 || prevt == OPERATOR_TYPE
107 || prevt == RELATION_TYPE
108 || prevt == OPENING_TYPE
109 || prevt == PUNCTUATION_TYPE)
110 list.p[i]->spacing_type = ORDINARY_TYPE;
112 // 7
113 else if ((t == RELATION_TYPE || t == CLOSING_TYPE
114 || t == PUNCTUATION_TYPE)
115 && i > 0 && list.p[i-1]->spacing_type == BINARY_TYPE)
116 list.p[i-1]->spacing_type = ORDINARY_TYPE;
118 for (i = 0; i < list.len; i++) {
119 unsigned flags = 0;
120 if (i - 1 >= 0 && list.p[i - 1]->right_is_italic())
121 flags |= HINT_PREV_IS_ITALIC;
122 if (i + 1 < list.len && list.p[i + 1]->left_is_italic())
123 flags |= HINT_NEXT_IS_ITALIC;
124 if (flags)
125 list.p[i]->hint(flags);
127 is_script = (style <= SCRIPT_STYLE);
128 int total_spacing = 0;
129 for (i = 1; i < list.len; i++)
130 total_spacing += compute_spacing(is_script, list.p[i-1]->spacing_type,
131 list.p[i]->spacing_type);
132 int res = 0;
133 for (i = 0; i < list.len; i++)
134 if (!list.p[i]->is_simple()) {
135 int r = list.p[i]->compute_metrics(style);
136 if (r) {
137 if (res)
138 error("multiple marks and lineups");
139 else {
140 compute_sublist_width(i);
141 printf(".nr " MARK_REG " +\\n[" TEMP_REG"]\n");
142 res = r;
146 printf(".nr " WIDTH_FORMAT " %dM", uid, total_spacing);
147 for (i = 0; i < list.len; i++)
148 if (!list.p[i]->is_simple())
149 printf("+\\n[" WIDTH_FORMAT "]", list.p[i]->uid);
150 printf("\n");
151 printf(".nr " HEIGHT_FORMAT " 0", uid);
152 for (i = 0; i < list.len; i++)
153 if (!list.p[i]->is_simple())
154 printf(">?\\n[" HEIGHT_FORMAT "]", list.p[i]->uid);
155 printf("\n");
156 printf(".nr " DEPTH_FORMAT " 0", uid);
157 for (i = 0; i < list.len; i++)
158 if (!list.p[i]->is_simple())
159 printf(">?\\n[" DEPTH_FORMAT "]", list.p[i]->uid);
160 printf("\n");
161 int have_simple = 0;
162 for (i = 0; i < list.len && !have_simple; i++)
163 have_simple = list.p[i]->is_simple();
164 if (have_simple) {
165 printf(".nr " WIDTH_FORMAT " +\\w" DELIMITER_CHAR, uid);
166 for (i = 0; i < list.len; i++)
167 if (list.p[i]->is_simple())
168 list.p[i]->output();
169 printf(DELIMITER_CHAR "\n");
170 printf(".nr " HEIGHT_FORMAT " \\n[rst]>?\\n[" HEIGHT_FORMAT "]\n",
171 uid, uid);
172 printf(".nr " DEPTH_FORMAT " 0-\\n[rsb]>?\\n[" DEPTH_FORMAT "]\n",
173 uid, uid);
175 return res;
178 void list_box::compute_sublist_width(int n)
180 int total_spacing = 0;
181 int i;
182 for (i = 1; i < n + 1 && i < list.len; i++)
183 total_spacing += compute_spacing(is_script, list.p[i-1]->spacing_type,
184 list.p[i]->spacing_type);
185 printf(".nr " TEMP_REG " %dM", total_spacing);
186 for (i = 0; i < n; i++)
187 if (!list.p[i]->is_simple())
188 printf("+\\n[" WIDTH_FORMAT "]", list.p[i]->uid);
189 int have_simple = 0;
190 for (i = 0; i < n && !have_simple; i++)
191 have_simple = list.p[i]->is_simple();
192 if (have_simple) {
193 printf("+\\w" DELIMITER_CHAR);
194 for (i = 0; i < n; i++)
195 if (list.p[i]->is_simple())
196 list.p[i]->output();
197 printf(DELIMITER_CHAR);
199 printf("\n");
202 void list_box::compute_subscript_kern()
204 // We can only call compute_subscript_kern if we have called
205 // compute_metrics first.
206 if (list.p[list.len-1]->is_simple())
207 list.p[list.len-1]->compute_metrics(sty);
208 list.p[list.len-1]->compute_subscript_kern();
209 printf(".nr " SUB_KERN_FORMAT " \\n[" SUB_KERN_FORMAT "]\n",
210 uid, list.p[list.len-1]->uid);
213 void list_box::output()
215 if (output_format == mathml)
216 printf("<mrow>");
217 for (int i = 0; i < list.len; i++) {
218 if (output_format == troff && i > 0) {
219 int n = compute_spacing(is_script,
220 list.p[i-1]->spacing_type,
221 list.p[i]->spacing_type);
222 if (n > 0)
223 printf("\\h'%dM'", n);
225 list.p[i]->output();
227 if (output_format == mathml)
228 printf("</mrow>");
231 void list_box::handle_char_type(int st, int ft)
233 for (int i = 0; i < list.len; i++)
234 list.p[i]->handle_char_type(st, ft);
237 void list_box::debug_print()
239 list.list_debug_print(" ");
242 void list_box::check_tabs(int level)
244 list.list_check_tabs(level);
247 // s-it2-mode