2 /* Copyright (C) 1989-2014 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 3 of the License, or
10 (at your option) any later 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
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
23 list_box *box::to_list_box()
28 list_box *list_box::to_list_box()
33 void list_box::append(box *pp)
35 list_box *q = pp->to_list_box();
39 for (int i = 0; i < q->list.len; i++) {
40 list.append(q->list.p[i]);
48 list_box::list_box(box *pp) : list(pp), sty(-1)
50 list_box *q = pp->to_list_box();
53 list.p[0] = q->list.p[0];
54 for (int i = 1; i < q->list.len; i++) {
55 list.append(q->list.p[i]);
63 static int compute_spacing(int is_script, int left, int right)
65 if (left == SUPPRESS_TYPE || right == SUPPRESS_TYPE)
67 if (left == PUNCTUATION_TYPE)
68 return is_script ? 0 : thin_space;
69 if (left == OPENING_TYPE || right == CLOSING_TYPE)
71 if (right == BINARY_TYPE || left == BINARY_TYPE)
72 return is_script ? 0 : medium_space;
73 if (right == RELATION_TYPE) {
74 if (left == RELATION_TYPE)
77 return is_script ? 0 : thick_space;
79 if (left == RELATION_TYPE)
80 return is_script ? 0 : thick_space;
81 if (right == OPERATOR_TYPE)
83 if (left == INNER_TYPE || right == INNER_TYPE)
84 return is_script ? 0 : thin_space;
85 if (left == OPERATOR_TYPE && right == ORDINARY_TYPE)
90 int list_box::compute_metrics(int style)
94 for (i = 0; i < list.len; i++) {
95 int t = list.p[i]->spacing_type;
97 if (t == BINARY_TYPE) {
100 || (prevt = list.p[i-1]->spacing_type) == BINARY_TYPE
101 || prevt == OPERATOR_TYPE
102 || prevt == RELATION_TYPE
103 || prevt == OPENING_TYPE
104 || prevt == PUNCTUATION_TYPE)
105 list.p[i]->spacing_type = ORDINARY_TYPE;
108 else if ((t == RELATION_TYPE || t == CLOSING_TYPE
109 || t == PUNCTUATION_TYPE)
110 && i > 0 && list.p[i-1]->spacing_type == BINARY_TYPE)
111 list.p[i-1]->spacing_type = ORDINARY_TYPE;
113 for (i = 0; i < list.len; i++) {
115 if (i - 1 >= 0 && list.p[i - 1]->right_is_italic())
116 flags |= HINT_PREV_IS_ITALIC;
117 if (i + 1 < list.len && list.p[i + 1]->left_is_italic())
118 flags |= HINT_NEXT_IS_ITALIC;
120 list.p[i]->hint(flags);
122 is_script = (style <= SCRIPT_STYLE);
123 int total_spacing = 0;
124 for (i = 1; i < list.len; i++)
125 total_spacing += compute_spacing(is_script, list.p[i-1]->spacing_type,
126 list.p[i]->spacing_type);
128 for (i = 0; i < list.len; i++)
129 if (!list.p[i]->is_simple()) {
130 int r = list.p[i]->compute_metrics(style);
133 error("multiple marks and lineups");
135 compute_sublist_width(i);
136 printf(".nr " MARK_REG " +\\n[" TEMP_REG"]\n");
141 printf(".nr " WIDTH_FORMAT " %dM", uid, total_spacing);
142 for (i = 0; i < list.len; i++)
143 if (!list.p[i]->is_simple())
144 printf("+\\n[" WIDTH_FORMAT "]", list.p[i]->uid);
146 printf(".nr " HEIGHT_FORMAT " 0", uid);
147 for (i = 0; i < list.len; i++)
148 if (!list.p[i]->is_simple())
149 printf(">?\\n[" HEIGHT_FORMAT "]", list.p[i]->uid);
151 printf(".nr " DEPTH_FORMAT " 0", uid);
152 for (i = 0; i < list.len; i++)
153 if (!list.p[i]->is_simple())
154 printf(">?\\n[" DEPTH_FORMAT "]", list.p[i]->uid);
157 for (i = 0; i < list.len && !have_simple; i++)
158 have_simple = list.p[i]->is_simple();
160 printf(".nr " WIDTH_FORMAT " +\\w" DELIMITER_CHAR, uid);
161 for (i = 0; i < list.len; i++)
162 if (list.p[i]->is_simple())
164 printf(DELIMITER_CHAR "\n");
165 printf(".nr " HEIGHT_FORMAT " \\n[rst]>?\\n[" HEIGHT_FORMAT "]\n",
167 printf(".nr " DEPTH_FORMAT " 0-\\n[rsb]>?\\n[" DEPTH_FORMAT "]\n",
173 void list_box::compute_sublist_width(int n)
175 int total_spacing = 0;
177 for (i = 1; i < n + 1 && i < list.len; i++)
178 total_spacing += compute_spacing(is_script, list.p[i-1]->spacing_type,
179 list.p[i]->spacing_type);
180 printf(".nr " TEMP_REG " %dM", total_spacing);
181 for (i = 0; i < n; i++)
182 if (!list.p[i]->is_simple())
183 printf("+\\n[" WIDTH_FORMAT "]", list.p[i]->uid);
185 for (i = 0; i < n && !have_simple; i++)
186 have_simple = list.p[i]->is_simple();
188 printf("+\\w" DELIMITER_CHAR);
189 for (i = 0; i < n; i++)
190 if (list.p[i]->is_simple())
192 printf(DELIMITER_CHAR);
197 void list_box::compute_subscript_kern()
199 // We can only call compute_subscript_kern if we have called
200 // compute_metrics first.
201 if (list.p[list.len-1]->is_simple())
202 list.p[list.len-1]->compute_metrics(sty);
203 list.p[list.len-1]->compute_subscript_kern();
204 printf(".nr " SUB_KERN_FORMAT " \\n[" SUB_KERN_FORMAT "]\n",
205 uid, list.p[list.len-1]->uid);
208 void list_box::output()
210 if (output_format == mathml)
212 for (int i = 0; i < list.len; i++) {
213 if (output_format == troff && i > 0) {
214 int n = compute_spacing(is_script,
215 list.p[i-1]->spacing_type,
216 list.p[i]->spacing_type);
218 printf("\\h'%dM'", n);
222 if (output_format == mathml)
226 void list_box::handle_char_type(int st, int ft)
228 for (int i = 0; i < list.len; i++)
229 list.p[i]->handle_char_type(st, ft);
232 void list_box::debug_print()
234 list.list_debug_print(" ");
237 void list_box::check_tabs(int level)
239 list.list_check_tabs(level);