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
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 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.
23 #include "eqn-config.h"
28 list_box
*box::to_list_box()
33 list_box
*list_box::to_list_box()
38 void list_box::append(box
*pp
)
40 list_box
*q
= pp
->to_list_box();
44 for (int i
= 0; i
< q
->list
.len
; i
++) {
45 list
.append(q
->list
.p
[i
]);
53 list_box::list_box(box
*pp
) : list(pp
), sty(-1)
55 list_box
*q
= pp
->to_list_box();
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
]);
68 static int compute_spacing(int is_script
, int left
, int right
)
70 if (left
== SUPPRESS_TYPE
|| right
== SUPPRESS_TYPE
)
72 if (left
== PUNCTUATION_TYPE
)
73 return is_script
? 0 : thin_space
;
74 if (left
== OPENING_TYPE
|| right
== CLOSING_TYPE
)
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
)
82 return is_script
? 0 : thick_space
;
84 if (left
== RELATION_TYPE
)
85 return is_script
? 0 : thick_space
;
86 if (right
== OPERATOR_TYPE
)
88 if (left
== INNER_TYPE
|| right
== INNER_TYPE
)
89 return is_script
? 0 : thin_space
;
90 if (left
== OPERATOR_TYPE
&& right
== ORDINARY_TYPE
)
95 int list_box::compute_metrics(int style
)
99 for (i
= 0; i
< list
.len
; i
++) {
100 int t
= list
.p
[i
]->spacing_type
;
102 if (t
== BINARY_TYPE
) {
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
;
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
++) {
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
;
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
);
133 for (i
= 0; i
< list
.len
; i
++)
134 if (!list
.p
[i
]->is_simple()) {
135 int r
= list
.p
[i
]->compute_metrics(style
);
138 error("multiple marks and lineups");
140 compute_sublist_width(i
);
141 printf(".nr " MARK_REG
" +\\n[" TEMP_REG
"]\n");
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
);
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
);
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
);
162 for (i
= 0; i
< list
.len
&& !have_simple
; i
++)
163 have_simple
= list
.p
[i
]->is_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())
169 printf(DELIMITER_CHAR
"\n");
170 printf(".nr " HEIGHT_FORMAT
" \\n[rst]>?\\n[" HEIGHT_FORMAT
"]\n",
172 printf(".nr " DEPTH_FORMAT
" 0-\\n[rsb]>?\\n[" DEPTH_FORMAT
"]\n",
178 void list_box::compute_sublist_width(int n
)
180 int total_spacing
= 0;
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
);
190 for (i
= 0; i
< n
&& !have_simple
; i
++)
191 have_simple
= list
.p
[i
]->is_simple();
193 printf("+\\w" DELIMITER_CHAR
);
194 for (i
= 0; i
< n
; i
++)
195 if (list
.p
[i
]->is_simple())
197 printf(DELIMITER_CHAR
);
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
)
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
);
223 printf("\\h'%dM'", n
);
227 if (output_format
== mathml
)
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
);