1
4
5# include "luametatex.h"
6
7
36
37insert_state_info lmt_insert_state = {
38 .inserts = NULL,
39 .insert_data = {
40 .minimum = min_insert_size,
41 .maximum = max_insert_size,
42 .size = memory_data_unset,
43 .step = stp_insert_size,
44 .allocated = 0,
45 .itemsize = sizeof(insert_record),
46 .top = 0,
47 .ptr = 0,
48 .initial = memory_data_unset,
49 .offset = 0,
50 },
51 .mode = unset_insert_mode,
52 .storing = 0,
53};
54
55typedef enum saved_insert_entries {
56 saved_insert_index_entry = 0,
57 saved_insert_n_of_records = 1,
58} saved_insert_entries;
59
60# define saved_insert_index saved_value_1(saved_insert_index_entry)
61
62inline static void saved_inserts_initialize(void)
63{
64 saved_type(0) = saved_record_0;
65 saved_record(0) = insert_save_type;
66}
67
68void tex_show_insert_group(void)
69{
70 tex_print_str_esc("insert");
71 tex_print_int(saved_insert_index);
72}
73
74int tex_show_insert_record(void)
75{
76 tex_print_str("insert ");
77 switch (save_type(lmt_save_state.save_stack_data.ptr)) {
78 case saved_record_0:
79 tex_print_format("index %i", saved_insert_index);
80 break;
81 default:
82 return 0;
83 }
84 return 1;
85}
86
87void tex_initialize_inserts(void)
88{
89 insert_record *tmp = aux_allocate_clear_array(sizeof(insert_record), lmt_insert_state.insert_data.minimum, 1);
90 if (tmp) {
91 lmt_insert_state.inserts = tmp;
92 lmt_insert_state.insert_data.allocated = lmt_insert_state.insert_data.minimum * sizeof(insert_record);
93 lmt_insert_state.insert_data.top = lmt_insert_state.insert_data.minimum;
94 lmt_insert_state.insert_data.ptr = 0;
95 } else {
96 tex_overflow_error("inserts", lmt_insert_state.insert_data.minimum);
97 }
98}
99
100
104
105int tex_valid_insert_id(halfword n)
106{
107 switch (lmt_insert_state.mode) {
108 case index_insert_mode:
109 return (n >= 0 && n <= max_box_register_index);
110 case class_insert_mode:
111 if (n <= 0) {
112 tex_handle_error(
113 normal_error_type,
114 "In \\insertmode 2 you can't use zero as index.",
115 NULL
116 );
117 } else if (n <= lmt_insert_state.insert_data.ptr) {
118 return 1;
119 } else if (n < lmt_insert_state.insert_data.top) {
120 lmt_insert_state.insert_data.ptr = n;
121 return 1;
122 } else if (n < lmt_insert_state.insert_data.maximum && lmt_insert_state.insert_data.top < lmt_insert_state.insert_data.maximum) {
123 insert_record *tmp ;
124 int top = n + lmt_insert_state.insert_data.step;
125 if (top > lmt_insert_state.insert_data.maximum) {
126 top = lmt_insert_state.insert_data.maximum;
127 }
128 tmp = aux_reallocate_array(lmt_insert_state.inserts, sizeof(insert_record), top, 1);
129 if (tmp) {
130 size_t extra = ((size_t) top - lmt_insert_state.insert_data.top) * sizeof(insert_record);
131 memset(&tmp[lmt_insert_state.insert_data.top + 1], 0, extra);
132
133 lmt_insert_state.inserts = tmp;
134 lmt_insert_state.insert_data.allocated += (int) extra;
135 lmt_insert_state.insert_data.top = top;
136 lmt_insert_state.insert_data.ptr = n;
137 return 1;
138 }
139 }
140 tex_overflow_error("inserts", lmt_insert_state.insert_data.maximum);
141 }
142 return 0;
143}
144
145scaled tex_get_insert_limit(halfword i)
146{
147 if (tex_valid_insert_id(i)) {
148 return lmt_insert_state.mode == index_insert_mode ? insert_maxheight(i) : lmt_insert_state.inserts[i].limit;
149 } else {
150 return 0;
151 }
152}
153
154halfword tex_get_insert_multiplier(halfword i)
155{
156 if (tex_valid_insert_id(i)) {
157 return lmt_insert_state.mode == index_insert_mode ? insert_multiplier(i) : lmt_insert_state.inserts[i].multiplier;
158 } else {
159 return 0;
160 }
161}
162
163halfword tex_get_insert_penalty(halfword i)
164{
165 if (tex_valid_insert_id(i)) {
166 return lmt_insert_state.mode == index_insert_mode ? floating_penalty_par : lmt_insert_state.inserts[i].penalty;
167 } else {
168 return 0;
169 }
170}
171
172halfword tex_get_insert_maxdepth(halfword i)
173{
174 if (tex_valid_insert_id(i)) {
175 return lmt_insert_state.mode == index_insert_mode ? split_max_depth_par : lmt_insert_state.inserts[i].maxdepth;
176 } else {
177 return 0;
178 }
179}
180
181halfword tex_get_insert_distance(halfword i)
182{
183 if (tex_valid_insert_id(i)) {
184 return lmt_insert_state.mode == index_insert_mode ? insert_distance(i) : lmt_insert_state.inserts[i].distance;
185 } else {
186 return 0;
187 }
188}
189
190inline static halfword tex_aux_insert_box(halfword i)
191{
192 if (tex_valid_insert_id(i)) {
193 return lmt_insert_state.mode == index_insert_mode ? insert_content(i) : lmt_insert_state.inserts[i].content;
194 } else {
195 return null;
196 }
197}
198
199scaled tex_get_insert_height(halfword i)
200{
201 halfword b = tex_aux_insert_box(i);
202 return b ? box_height(b) : 0;
203}
204
205scaled tex_get_insert_depth(halfword i)
206{
207 halfword b = tex_aux_insert_box(i);
208 return b ? box_depth(b) : 0;
209}
210
211scaled tex_get_insert_width(halfword i)
212{
213 halfword b = tex_aux_insert_box(i);
214 return b ? box_width(b) : 0;
215}
216
217halfword tex_get_insert_content(halfword i)
218{
219 return tex_aux_insert_box(i);
220}
221
222halfword tex_get_insert_storage(halfword i)
223{
224 if (lmt_insert_state.mode == class_insert_mode && tex_valid_insert_id(i)) {
225 return has_insert_option(i, insert_option_storing);
226 } else {
227 return 0;
228 }
229}
230
231void tex_set_insert_limit(halfword i, scaled v)
232{
233 if (tex_valid_insert_id(i)) {
234 switch (lmt_insert_state.mode) {
235 case index_insert_mode: insert_maxheight(i) = v; break;
236 case class_insert_mode: lmt_insert_state.inserts[i].limit = v; break;
237 }
238 }
239}
240
241void tex_set_insert_multiplier(halfword i, halfword v) {
242 if (tex_valid_insert_id(i)) {
243 switch (lmt_insert_state.mode) {
244 case index_insert_mode: insert_multiplier(i) = v; break;
245 case class_insert_mode: lmt_insert_state.inserts[i].multiplier = v; break;
246 }
247 }
248}
249
250void tex_set_insert_penalty(halfword i, halfword v) {
251 if (tex_valid_insert_id(i) && lmt_insert_state.mode == class_insert_mode) {
252 lmt_insert_state.inserts[i].options = set_insert_option(lmt_insert_state.inserts[i].options, insert_option_penalty);
253 lmt_insert_state.inserts[i].penalty = v;
254 }
255}
256
257void tex_set_insert_maxdepth(halfword i, halfword v) {
258 if (tex_valid_insert_id(i) && lmt_insert_state.mode == class_insert_mode) {
259 lmt_insert_state.inserts[i].options = set_insert_option(lmt_insert_state.inserts[i].options, insert_option_maxdepth);
260 lmt_insert_state.inserts[i].maxdepth = v;
261 }
262}
263
264void tex_set_insert_distance(halfword i, halfword v) {
265 if (tex_valid_insert_id(i)) {
266 int d = null;
267 switch (lmt_insert_state.mode) {
268 case index_insert_mode:
269 d = insert_distance(i);
270 insert_distance(i) = v;
271 break;
272 case class_insert_mode:
273 d = lmt_insert_state.inserts[i].distance;
274 lmt_insert_state.inserts[i].distance = v;
275 break;
276 }
277 tex_flush_node(d);
278 }
279}
280
281void tex_set_insert_height(halfword i, scaled v) {
282 halfword b = tex_aux_insert_box(i);
283 if (b) {
284 box_height(b) = v;
285 }
286}
287
288void tex_set_insert_depth(halfword i, scaled v) {
289 halfword b = tex_aux_insert_box(i);
290 if (b) {
291 box_depth(b) = v;
292 }
293}
294
295void tex_set_insert_width(halfword i, scaled v) {
296 halfword b = tex_aux_insert_box(i);
297 if (b) {
298 box_width(b) = v;
299 }
300}
301
302void tex_set_insert_content(halfword i, halfword v) {
303 switch (lmt_insert_state.mode) {
304 case index_insert_mode: insert_content(i) = v; break;
305 case class_insert_mode: if (tex_valid_insert_id(i)) { lmt_insert_state.inserts[i].content = v; } break;
306 }
307}
308
309void tex_set_insert_storage(halfword i, halfword v)
310{
311 if (lmt_insert_state.mode == class_insert_mode && tex_valid_insert_id(i)) {
312 lmt_insert_state.inserts[i].options = v
313 ? set_insert_option(lmt_insert_state.inserts[i].options, insert_option_storing)
314 : unset_insert_option(lmt_insert_state.inserts[i].options, insert_option_storing);
315 }
316}
317
318void tex_wipe_insert(halfword i) {
319 if (lmt_insert_state.mode == class_insert_mode && i >= 0 && i <= lmt_insert_state.insert_data.ptr) {
320
321 halfword b = lmt_insert_state.inserts[i].content;
322 if (b) {
323 tex_flush_node(b);
324 lmt_insert_state.inserts[i].content = null;
325 }
326 }
327}
328
329halfword lmt_get_insert_distance(halfword i, int slot)
330{
331 int callback_id = lmt_callback_defined(insert_distance_callback);
332 if (callback_id != 0) {
333 halfword replacement = null;
334 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "dd->N", i, slot, &replacement);
335 if (replacement) {
336 return replacement;
337 } else {
338 halfword distance = null;
339 switch (lmt_insert_state.mode) {
340 case index_insert_mode:
341 distance = insert_distance(i);
342 break;
343 case class_insert_mode:
344 if (tex_valid_insert_id(i)) {
345 distance = lmt_insert_state.inserts[i].distance;
346 }
347 break;
348 }
349 if (distance) {
350 return tex_copy_node(distance);
351 }
352 }
353 }
354 return tex_new_glue_spec_node(null);
355}
356
357halfword tex_get_insert_progress(halfword i)
358{
359 if (tex_valid_insert_id(i)) {
360 halfword p = page_insert_head;
361 while (p && i >= insert_index(node_next(p))) {
362 p = node_next(p);
363 if (p == page_insert_head) {
364 break;
365 }
366 }
367 return insert_index(p) == i ? insert_total_height(p) : 0;
368 } else {
369 return 0;
370 }
371}
372
373
374
375halfword tex_scan_insert_index(void)
376{
377 halfword index = 0;
378 switch (lmt_insert_state.mode) {
379 case unset_insert_mode:
380 lmt_insert_state.mode = index_insert_mode;
381
382 case index_insert_mode:
383 index = tex_scan_box_register_number();
384 if (index == output_box_par) {
385 tex_handle_error(
386 normal_error_type,
387 "You can't \\insert%i",
388 output_box_par,
389 "I'm changing to \\insert0; box \\outputbox is special."
390 );
391 index = 0;
392 }
393 break;
394 case class_insert_mode:
395 index = tex_scan_integer(0, NULL);
396 if (! tex_valid_insert_id(index)) {
397 index = 0;
398 }
399 break;
400 }
401 return index;
402}
403
404void tex_set_insert_mode(halfword mode)
405{
406 if (lmt_insert_state.mode == unset_insert_mode && (mode == index_insert_mode || mode == class_insert_mode)) {
407 lmt_insert_state.mode = mode;
408 } else if (mode != lmt_insert_state.mode) {
409 tex_handle_error(
410 normal_error_type,
411 "Bad \\insertmode (%i)",
412 mode,
413 "This mode can be set once and has value 1 or 2. It will be automatically\n"
414 "set when \\insert is used."
415 );
416 }
417}
418
419int tex_insert_is_void(halfword i)
420{
421 halfword b = tex_aux_insert_box(i);
422 return (! b) || box_list(b) == null;
423}
424
425
426
427int tex_insert_stored(void)
428{
429 return lmt_insert_state.head != null;
430}
431
432void tex_insert_restore(halfword n)
433{
434 if (lmt_insert_state.tail) {
435 tex_couple_nodes(lmt_insert_state.tail, n);
436 } else {
437 lmt_insert_state.head = n;
438 }
439 lmt_insert_state.tail = n;
440}
441
442void tex_insert_store(halfword i, halfword n)
443{
444 if (tex_get_insert_storage(i)) {
445 tex_insert_restore(n);
446 }
447}
448
449
450
451void tex_dump_insert_data(dumpstream f) {
452 dump_int(f, lmt_insert_state.mode);
453 dump_int(f, lmt_insert_state.insert_data.ptr);
454 dump_int(f, lmt_insert_state.insert_data.top);
455 dump_things(f, lmt_insert_state.inserts[0], lmt_insert_state.insert_data.ptr);
456}
457
458void tex_undump_insert_data(dumpstream f) {
459 insert_record *tmp;
460 undump_int(f, lmt_insert_state.mode);
461 undump_int(f, lmt_insert_state.insert_data.ptr);
462 undump_int(f, lmt_insert_state.insert_data.top);
463 tmp = aux_allocate_clear_array(sizeof(insert_record), lmt_insert_state.insert_data.top, 1);
464 if (tmp) {
465 lmt_insert_state.inserts = tmp;
466 lmt_insert_state.insert_data.allocated = lmt_insert_state.insert_data.top * sizeof(insert_record);
467 undump_things(f, lmt_insert_state.inserts[0], lmt_insert_state.insert_data.ptr);
468 } else {
469 tex_overflow_error("inserts", lmt_insert_state.insert_data.top);
470 }
471}
472
473
476
477void tex_run_insert(void)
478{
479 saved_inserts_initialize();
480 saved_insert_index = tex_scan_insert_index();
481 lmt_save_state.save_stack_data.ptr += saved_insert_n_of_records;
482 tex_new_save_level(insert_group);
483 tex_scan_left_brace();
484 tex_normal_paragraph(insert_par_context);
485 tex_push_nest();
486 cur_list.mode = internal_vmode;
487 cur_list.prev_depth = ignore_depth_criterion_par;
488}
489
490void tex_finish_insert_group(void)
491{
492 if (! tex_wrapped_up_paragraph(insert_par_context, 0)) {
493 halfword p, q;
494 scaled d;
495 halfword f;
496 tex_end_paragraph(insert_group, insert_par_context);
497 q = tex_new_glue_node(split_top_skip_par, top_skip_code);
498 d = split_max_depth_par;
499 f = floating_penalty_par;
500 tex_unsave();
501 lmt_save_state.save_stack_data.ptr -= saved_insert_n_of_records;
502
503
504
505
506
507 p = node_next(cur_list.head);
508 tex_pop_nest();
509 p = tex_vpack(p, 0, packing_additional, max_dimension, direction_unknown, holding_none_option, NULL);
510 {
511 halfword index = saved_insert_index;
512 halfword insert = tex_new_node(insert_node, 0);
513 halfword maxdepth = tex_get_insert_maxdepth(index);
514 halfword floating = tex_get_insert_penalty(index);
515 if (tex_get_insert_storage(index)) {
516 tex_insert_store(index, insert);
517 } else {
518 tex_tail_append(insert);
519 }
520
524 insert_index(insert) = index;
525 insert_total_height(insert) = box_total(p);
526 insert_list(insert) = box_list(p);
527 insert_split_top(insert) = q;
528 insert_max_depth(insert) = has_insert_option(index, insert_option_maxdepth) ? d : maxdepth;
529 insert_float_cost(insert) = has_insert_option(index, insert_option_penalty) ? f : floating;
530 box_list(p) = null;
531 tex_flush_node(p);
532 if (tracing_inserts_par > 0) {
533 tex_begin_diagnostic();
534 tex_print_levels();
535 tex_print_format("[insert: setting, index %i, height %p, penalty %i]",
536 index, insert_total_height(insert), insert_float_cost(insert));
537 if (tracing_inserts_par > 1) {
538 tex_print_node_list(insert_list(insert), "insert", show_box_depth_par, show_box_breadth_par);
539 }
540 tex_end_diagnostic();
541 }
542 }
543
544 if (lmt_nest_state.nest_data.ptr == 0) {
545 tex_build_page(insert_page_context, 0);
546 }
547 }
548}
549 |