xref: /netbsd-src/external/gpl2/groff/dist/src/preproc/eqn/list.cpp (revision 89a07cf815a29524268025a1139fac4c5190f765)
1 /*	$NetBSD: list.cpp,v 1.1.1.1 2016/01/13 18:41:49 christos Exp $	*/
2 
3 // -*- C++ -*-
4 /* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
5      Written by James Clark (jjc@jclark.com)
6 
7 This file is part of groff.
8 
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.
13 
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.
18 
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. */
22 
23 #include "eqn.h"
24 #include "pbox.h"
25 
to_list_box()26 list_box *box::to_list_box()
27 {
28   return 0;
29 }
30 
to_list_box()31 list_box *list_box::to_list_box()
32 {
33   return this;
34 }
35 
append(box * pp)36 void list_box::append(box *pp)
37 {
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;
45     }
46     q->list.len = 0;
47     delete q;
48   }
49 }
50 
list_box(box * pp)51 list_box::list_box(box *pp) : list(pp), sty(-1)
52 {
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;
60     }
61     q->list.len = 0;
62     delete q;
63   }
64 }
65 
compute_spacing(int is_script,int left,int right)66 static int compute_spacing(int is_script, int left, int right)
67 {
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;
81   }
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;
91 }
92 
compute_metrics(int style)93 int list_box::compute_metrics(int style)
94 {
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;
109     }
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;
115   }
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);
124   }
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;
141 	}
142       }
143     }
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);
172   }
173   return res;
174 }
175 
compute_sublist_width(int n)176 void list_box::compute_sublist_width(int n)
177 {
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);
196   }
197   printf("\n");
198 }
199 
compute_subscript_kern()200 void list_box::compute_subscript_kern()
201 {
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);
209 }
210 
output()211 void list_box::output()
212 {
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);
220     }
221     list.p[i]->output();
222   }
223 }
224 
handle_char_type(int st,int ft)225 void list_box::handle_char_type(int st, int ft)
226 {
227   for (int i = 0; i < list.len; i++)
228     list.p[i]->handle_char_type(st, ft);
229 }
230 
debug_print()231 void list_box::debug_print()
232 {
233   list.list_debug_print(" ");
234 }
235 
check_tabs(int level)236 void list_box::check_tabs(int level)
237 {
238   list.list_check_tabs(level);
239 }
240