Commit | Line | Data |
---|---|---|
cad317cf C |
1 | // -*- C++ -*- |
2 | /* Copyright (C) 1989, 1990 Free Software Foundation, Inc. | |
3 | Written by James Clark (jjc@jclark.uucp) | |
4 | ||
5 | This file is part of groff. | |
6 | ||
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 1, or (at your option) any later | |
10 | version. | |
11 | ||
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. | |
16 | ||
17 | You should have received a copy of the GNU General Public License along | |
18 | with groff; see the file LICENSE. If not, write to the Free Software | |
19 | Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
20 | ||
21 | #include "eqn.h" | |
22 | #include "pbox.h" | |
23 | ||
24 | list_box *box::to_list_box() | |
25 | { | |
26 | return 0; | |
27 | } | |
28 | ||
29 | list_box *list_box::to_list_box() | |
30 | { | |
31 | return this; | |
32 | } | |
33 | ||
34 | void list_box::append(box *pp) | |
35 | { | |
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; | |
43 | } | |
44 | q->list.len = 0; | |
45 | delete q; | |
46 | } | |
47 | } | |
48 | ||
49 | list_box::list_box(box *pp) : list(pp), sty(-1) | |
50 | { | |
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; | |
58 | } | |
59 | q->list.len = 0; | |
60 | delete q; | |
61 | } | |
62 | } | |
63 | ||
64 | static int compute_spacing(int is_script, int left, int right) | |
65 | { | |
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; | |
79 | } | |
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; | |
89 | } | |
90 | ||
91 | int list_box::compute_metrics(int style) | |
92 | { | |
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; | |
107 | } | |
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; | |
113 | } | |
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); | |
122 | } | |
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; | |
139 | } | |
140 | } | |
141 | } | |
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 (int 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); | |
170 | } | |
171 | return res; | |
172 | } | |
173 | ||
174 | void list_box::compute_sublist_width(int n) | |
175 | { | |
176 | int total_spacing = 0; | |
177 | for (int 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); | |
184 | int have_simple = 0; | |
185 | for (i = 0; i < n && !have_simple; i++) | |
186 | have_simple = list.p[i]->is_simple(); | |
187 | if (have_simple) { | |
188 | printf("+\\w" DELIMITER_CHAR); | |
189 | for (int i = 0; i < n; i++) | |
190 | if (list.p[i]->is_simple()) | |
191 | list.p[i]->output(); | |
192 | printf(DELIMITER_CHAR); | |
193 | } | |
194 | printf("\n"); | |
195 | } | |
196 | ||
197 | void list_box::compute_subscript_kern() | |
198 | { | |
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); | |
206 | } | |
207 | ||
208 | void list_box::output() | |
209 | { | |
210 | for (int i = 0; i < list.len; i++) { | |
211 | if (i > 0) { | |
212 | int n = compute_spacing(is_script, | |
213 | list.p[i-1]->spacing_type, | |
214 | list.p[i]->spacing_type); | |
215 | if (n > 0) | |
216 | printf("\\h'%dM'", n); | |
217 | } | |
218 | list.p[i]->output(); | |
219 | } | |
220 | } | |
221 | ||
222 | void list_box::handle_char_type(int st, int ft) | |
223 | { | |
224 | for (int i = 0; i < list.len; i++) | |
225 | list.p[i]->handle_char_type(st, ft); | |
226 | } | |
227 | ||
228 | void list_box::debug_print() | |
229 | { | |
230 | list.list_debug_print(" "); | |
231 | } | |
232 | ||
233 | void list_box::check_tabs(int level) | |
234 | { | |
235 | list.list_check_tabs(level); | |
236 | } |