1
4
5# include "luametatex.h"
6
7
18
19
23
24
28
29static inline scaled tex_aux_local_boxes_width(halfword n)
30{
31 scaled width = 0;
32 while (n) {
33 if (node_type(n) == hlist_node) {
34 width += box_width(n);
35 } else {
36
37 }
38 n = node_next(n);
39 }
40 return width;
41}
42
43void tex_add_local_boxes(halfword p)
44{
45 if (local_left_box_par) {
46 halfword copy = tex_copy_node_list(local_left_box_par, null);
47 tex_set_local_left_width(p, tex_aux_local_boxes_width(copy));
48 par_box_left(p) = copy;
49 }
50 if (local_right_box_par) {
51 halfword copy = tex_copy_node_list(local_right_box_par, null);
52 tex_set_local_right_width(p, tex_aux_local_boxes_width(copy));
53 par_box_right(p) = copy;
54 }
55 if (local_middle_box_par) {
56 halfword copy = tex_copy_node_list(local_middle_box_par, null);
57 par_box_middle(p) = copy;
58 }
59}
60
61
65
66halfword tex_get_local_boxes(halfword location)
67{
68 switch (location) {
69 case local_left_box_code : return tex_use_local_boxes(local_left_box_par, local_left_box_code);
70 case local_right_box_code : return tex_use_local_boxes(local_right_box_par, local_right_box_code);
71 case local_middle_box_code: return tex_use_local_boxes(local_middle_box_par, local_middle_box_code);
72 }
73 return null;
74}
75
76
77
78void tex_set_local_boxes(halfword b, halfword location)
79{
80 switch (location) {
81 case local_left_box_code : tex_flush_node_list(local_left_box_par ); local_left_box_par = b; break;
82 case local_right_box_code : tex_flush_node_list(local_right_box_par ); local_right_box_par = b; break;
83 case local_middle_box_code: tex_flush_node_list(local_middle_box_par); local_middle_box_par = b; break;
84 }
85}
86
87
88
89static halfword tex_aux_reset_boxes(halfword head, halfword index)
90{
91 if (head && index) {
92 halfword current = head;
93 while (current) {
94 halfword next = node_next(current);
95 if (node_type(current) == hlist_node && box_index(current) == index) {
96 if (current == head) {
97 head = node_next(head);
98 node_prev(head) = null;
99 next = head;
100 } else {
101 tex_try_couple_nodes(node_prev(current), next);
102 }
103 tex_flush_node(current);
104 break;
105 } else {
106 current = next;
107 }
108 }
109 return head;
110 } else {
111 tex_flush_node_list(head);
112 return null;
113 }
114}
115
116void tex_reset_local_boxes(halfword index, halfword location)
117{
118 switch (location) {
119 case local_left_box_code : local_left_box_par = tex_aux_reset_boxes(local_left_box_par, index); break;
120 case local_right_box_code : local_right_box_par = tex_aux_reset_boxes(local_right_box_par, index); break;
121 case local_middle_box_code: local_right_box_par = tex_aux_reset_boxes(local_middle_box_par, index); break;
122 }
123}
124
125void tex_reset_local_box(halfword location)
126{
127 switch (location) {
128 case local_left_box_code : update_tex_local_left_box (null); break;
129 case local_right_box_code : update_tex_local_right_box (null); break;
130 case local_middle_box_code : update_tex_local_middle_box(null); break;
131 case local_reset_boxes_code: update_tex_local_left_box (null);
132 update_tex_local_right_box (null);
133 update_tex_local_middle_box(null); break;
134 }
135}
136
137static halfword tex_aux_update_boxes(halfword head, halfword b, halfword index)
138{
139 if (head && index) {
140 halfword current = head;
141 while (current) {
142 halfword next = node_next(current);
143 if (node_type(current) == hlist_node && box_index(current) == index) {
144 tex_try_couple_nodes(b, node_next(current));
145 if (current == head) {
146 head = b;
147 } else {
148 tex_couple_nodes(node_prev(current), b);
149 }
150 tex_flush_node(current);
151 break;
152 } else if (next) {
153 current = next;
154 } else {
155 tex_couple_nodes(current, b);
156 break;
157 }
158 }
159 return head;
160 }
161 return b;
162}
163
164void tex_update_local_boxes(halfword b, halfword index, halfword location)
165{
166 switch (location) {
167 case local_left_box_code:
168 if (b) {
169 halfword c = local_left_box_par ? tex_copy_node_list(local_left_box_par, null) : null;
170 b = tex_aux_update_boxes(c, b, index);
171 } else if (index) {
172 halfword c = local_left_box_par ? tex_copy_node_list(local_left_box_par, null) : null;
173 b = tex_aux_reset_boxes(c, index);
174 }
175 update_tex_local_left_box(b);
176 break;
177 case local_right_box_code:
178 if (b) {
179 halfword c = local_right_box_par ? tex_copy_node_list(local_right_box_par, null) : null;
180 b = tex_aux_update_boxes(c, b, index);
181 } else if (index) {
182 halfword c = local_right_box_par ? tex_copy_node_list(local_right_box_par, null) : null;
183 b = tex_aux_reset_boxes(c, index);
184 }
185 update_tex_local_right_box(b);
186 break;
187 default:
188 if (b) {
189 halfword c = local_middle_box_par ? tex_copy_node_list(local_middle_box_par, null) : null;
190 b = tex_aux_update_boxes(c, b, index);
191 } else if (index) {
192 halfword c = local_middle_box_par ? tex_copy_node_list(local_middle_box_par, null) : null;
193 b = tex_aux_reset_boxes(c, index);
194 }
195 update_tex_local_middle_box(b);
196 break;
197 }
198}
199
200
201
202
203
204static halfword tex_aux_replace_local_box(halfword b, halfword index, halfword par_box)
205{
206 if (b) {
207 halfword c = par_box ? tex_copy_node_list(par_box, null) : null;
208 b = tex_aux_update_boxes(c, b, index);
209 } else if (index) {
210 halfword c = par_box ? tex_copy_node_list(par_box, null) : null;
211 b = tex_aux_reset_boxes(c, index);
212 }
213 if (par_box) {
214 tex_flush_node_list(par_box);
215 }
216 return b;
217}
218
219void tex_replace_local_boxes(halfword par, halfword b, halfword index, halfword location)
220{
221 switch (location) {
222 case local_left_box_code:
223 par_box_left(par) = tex_aux_replace_local_box(b, index, par_box_left(par));
224 par_box_left_width(par) = tex_aux_local_boxes_width(b);
225 break;
226 case local_right_box_code:
227 par_box_right(par) = tex_aux_replace_local_box(b, index, par_box_right(par));
228 par_box_right_width(par) = tex_aux_local_boxes_width(b);
229 break;
230 case local_middle_box_code:
231 par_box_middle(par) = tex_aux_replace_local_box(b, index, par_box_middle(par));
232
233 break;
234 }
235}
236
237
238
239halfword tex_use_local_boxes(halfword p, halfword location)
240{
241 if (p) {
242 p = tex_hpack(tex_copy_node_list(p, null), 0, packing_additional, direction_unknown, holding_none_option, box_limit_none);
243 switch (location) {
244 case local_left_box_code : node_subtype(p) = local_left_list ; break;
245 case local_right_box_code : node_subtype(p) = local_right_list ; break;
246 case local_middle_box_code: node_subtype(p) = local_middle_list; break;
247 }
248 }
249 return p;
250}
251
252
253
254void tex_scan_local_boxes_keys(quarterword *options, halfword *index)
255{
256 *options = 0;
257 *index = 0;
258 while (1) {
259 switch (tex_scan_character("iklpIKLP", 0, 1, 0)) {
260 case 'i': case 'I':
261 if (tex_scan_mandate_keyword("index", 1)) {
262 *index = tex_scan_box_index();
263 }
264 break;
265 case 'k': case 'K':
266 if (tex_scan_mandate_keyword("keep", 1)) {
267 *options |= local_box_keep_option;
268 }
269 break;
270 case 'l': case 'L':
271 if (tex_scan_mandate_keyword("local", 1)) {
272 *options |= local_box_local_option;
273 }
274 break;
275 case 'p': case 'P':
276 if (tex_scan_mandate_keyword("par", 1)) {
277 *options |= local_box_par_option;
278 }
279 break;
280 default:
281 return;
282 }
283 }
284}
285
286halfword tex_valid_box_index(halfword n)
287{
288 return box_index_in_range(n);
289}
290
291scaled tex_get_local_left_width (halfword p) { return par_box_left_width(p); }
292scaled tex_get_local_right_width (halfword p) { return par_box_right_width(p); }
293halfword tex_get_local_interline_penalty (halfword p) { return par_inter_line_penalty(p); }
294halfword tex_get_local_broken_penalty (halfword p) { return par_broken_penalty(p); }
295halfword tex_get_local_tolerance (halfword p) { return par_tolerance(p); }
296halfword tex_get_local_pre_tolerance (halfword p) { return par_pre_tolerance(p); }
297
298void tex_set_local_left_width (halfword p, scaled width ) { par_box_left_width(p) = width; }
299void tex_set_local_right_width (halfword p, scaled width ) { par_box_right_width(p) = width; }
300void tex_set_local_interline_penalty (halfword p, halfword penalty ) { par_inter_line_penalty(p) = penalty; }
301void tex_set_local_broken_penalty (halfword p, halfword penalty ) { par_broken_penalty(p) = penalty; }
302void tex_set_local_tolerance (halfword p, halfword tolerance) { par_tolerance(p) = tolerance; }
303void tex_set_local_pre_tolerance (halfword p, halfword tolerance) { par_pre_tolerance(p) = tolerance; }
304
305typedef enum saved_localbox_entries {
306 saved_localbox_location_entry = 0,
307 saved_localbox_index_entry = 0,
308 saved_localbox_options_entry = 0,
309 saved_localbox_n_of_records = 1,
310} saved_localbox_entries;
311
312static inline void saved_localbox_initialize(void)
313{
314 saved_type(0) = saved_record_0;
315 saved_record(0) = local_box_save_type;
316}
317
318static inline int saved_localbox_okay(void)
319{
320 return saved_type(0) == saved_record_0 && saved_record(0) == local_box_save_type;
321}
322
323# define saved_localbox_location saved_value_1(saved_localbox_location_entry)
324# define saved_localbox_index saved_value_2(saved_localbox_index_entry)
325# define saved_localbox_options saved_value_3(saved_localbox_options_entry)
326
327int tex_show_localbox_record(void)
328{
329 tex_print_str("localbox ");
330 switch (saved_type(0)) {
331 case saved_record_0:
332 tex_print_format("location %i, index %i, options %i", saved_value_1(0), saved_value_2(0), saved_value_3(0));
333 break;
334 default:
335 return 0;
336 }
337 return 1;
338}
339
340void tex_aux_scan_local_box(int code) {
341 quarterword options = 0;
342 halfword index = 0;
343 tex_scan_local_boxes_keys(&options, &index);
344 saved_localbox_initialize();
345 saved_localbox_location = code;
346 saved_localbox_index = index;
347 saved_localbox_options = options;
348 lmt_save_state.save_stack_data.ptr += saved_localbox_n_of_records;
349 tex_new_save_level(local_box_group);
350 tex_scan_left_brace();
351 tex_push_nest();
352 cur_list.mode = restricted_hmode;
353 cur_list.space_factor = default_space_factor;
354}
355
356void tex_aux_finish_local_box(void)
357{
358 tex_unsave();
359 lmt_save_state.save_stack_data.ptr -= saved_localbox_n_of_records;
360 if (saved_localbox_okay()) {
361
362 halfword location = saved_localbox_location;
363 quarterword options = (quarterword) saved_localbox_options;
364 halfword index = saved_localbox_index;
365 int islocal = (options & local_box_local_option) == local_box_local_option;
366 int keep = (options & local_box_keep_option) == local_box_keep_option;
367 int atpar = (options & local_box_par_option) == local_box_par_option;
368 halfword p = node_next(cur_list.head);
369 tex_pop_nest();
370 if (p) {
371
372 node_prev(p) = null;
373 if (tex_list_has_glyph(p)) {
374 tex_handle_hyphenation(p, null);
375 p = tex_handle_glyphrun(p, local_box_group, text_direction_par);
376 }
377 if (p) {
378 p = lmt_hpack_filter_callback(p, 0, packing_additional, local_box_group, direction_unknown, null);
379 }
380
384 p = tex_hpack(p, 0, packing_additional, direction_unknown, holding_none_option, box_limit_none);
385 node_subtype(p) = local_list;
386 box_index(p) = index;
387
388 } else {
389
390 }
391
392 if (islocal) {
393
394 } else {
395 tex_update_local_boxes(p, index, location);
396 }
397 if (cur_mode == hmode || cur_mode == mmode) {
398 if (atpar) {
399 halfword par = tex_find_par_par(cur_list.head);
400 if (par) {
401 if (p && ! islocal) {
402 p = tex_copy_node(p);
403 }
404 tex_replace_local_boxes(par, p, index, location);
405 }
406 } else {
407
411 tex_tail_append(tex_new_par_node(local_box_par_subtype));
412 if (! keep) {
413
414 update_tex_internal_par_state(internal_par_state_par + 1);
415 }
416 }
417 }
418 } else {
419 tex_confusion("build local box");
420 }
421}
422 |