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