No empty .Rs/.Re
[netbsd-mini2440.git] / gnu / dist / groff / src / preproc / eqn / list.cpp
blob139d1ffe76ac010181f4fbfb29459d6139c6b757
1 /* $NetBSD$ */
3 // -*- C++ -*-
4 /* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
5 Written by James Clark (jjc@jclark.com)
7 This file is part of groff.
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.
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.
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. */
23 #include "eqn.h"
24 #include "pbox.h"
26 list_box *box::to_list_box()
28 return 0;
31 list_box *list_box::to_list_box()
33 return this;
36 void list_box::append(box *pp)
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;
46 q->list.len = 0;
47 delete q;
51 list_box::list_box(box *pp) : list(pp), sty(-1)
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;
61 q->list.len = 0;
62 delete q;
66 static int compute_spacing(int is_script, int left, int right)
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;
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;
93 int list_box::compute_metrics(int style)
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;
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;
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);
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;
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);
173 return res;
176 void list_box::compute_sublist_width(int n)
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);
197 printf("\n");
200 void list_box::compute_subscript_kern()
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);
211 void list_box::output()
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);
221 list.p[i]->output();
225 void list_box::handle_char_type(int st, int ft)
227 for (int i = 0; i < list.len; i++)
228 list.p[i]->handle_char_type(st, ft);
231 void list_box::debug_print()
233 list.list_debug_print(" ");
236 void list_box::check_tabs(int level)
238 list.list_check_tabs(level);