diff options
Diffstat (limited to 'source/luametatex/source/tex/texadjust.c')
-rw-r--r-- | source/luametatex/source/tex/texadjust.c | 321 |
1 files changed, 200 insertions, 121 deletions
diff --git a/source/luametatex/source/tex/texadjust.c b/source/luametatex/source/tex/texadjust.c index f57853caf..11d2da6ad 100644 --- a/source/luametatex/source/tex/texadjust.c +++ b/source/luametatex/source/tex/texadjust.c @@ -4,26 +4,35 @@ # include "luametatex.h" -static void tex_scan_adjust_keys(halfword *options, halfword *code, halfword *index, scaled *depthbefore, scaled *depthafter, halfword *attrlist) +typedef struct adjust_properties { + halfword options; + halfword code; + halfword index; + scaled depthbefore; + scaled depthafter; + halfword attrlist; +} adjust_properties; + +static void tex_scan_adjust_keys(adjust_properties *properties) { - *code = post_adjust_code; - *options = adjust_option_none; - *index = 0; - *depthbefore = 0; - *depthafter = 0; - *attrlist = null; + properties->code = post_adjust_code; + properties->options = adjust_option_none; + properties->index = 0; + properties->depthbefore = 0; + properties->depthafter = 0; + properties->attrlist = null; while (1) { switch (tex_scan_character("abdipABDIP", 0, 1, 0)) { case 'p': case 'P': switch (tex_scan_character("roRO", 0, 0, 0)) { case 'r': case 'R': if (tex_scan_mandate_keyword("pre", 2)) { - *code = pre_adjust_code; + properties->code = pre_adjust_code; } break; case 'o': case 'O': if (tex_scan_mandate_keyword("post", 2)) { - *code = post_adjust_code; + properties->code = post_adjust_code; } break; default: @@ -35,12 +44,12 @@ static void tex_scan_adjust_keys(halfword *options, halfword *code, halfword *in switch (tex_scan_character("aeAE", 0, 0, 0)) { case 'a': case 'A': if (tex_scan_mandate_keyword("baseline", 2)) { - *options |= adjust_option_baseline; + properties->options |= adjust_option_baseline; } break; case 'e': case 'E': if (tex_scan_mandate_keyword("before", 2)) { - *options |= adjust_option_before; + properties->options |= adjust_option_before; } break; default: @@ -50,9 +59,9 @@ static void tex_scan_adjust_keys(halfword *options, halfword *code, halfword *in break; case 'i': case 'I': if (tex_scan_mandate_keyword("index", 1)) { - *index = tex_scan_int(0, NULL); - if (! tex_valid_adjust_index(*index)) { - *index = 0; /* for now no error */ + properties->index = tex_scan_int(0, NULL); + if (! tex_valid_adjust_index(properties->index)) { + properties->index = 0; /* for now no error */ } } break; @@ -60,7 +69,7 @@ static void tex_scan_adjust_keys(halfword *options, halfword *code, halfword *in switch (tex_scan_character("ftFT", 0, 0, 0)) { case 'f': case 'F': if (tex_scan_mandate_keyword("after", 2)) { - *options &= ~(adjust_option_before | *options); + properties->options &= ~(adjust_option_before | properties->options); } break; case 't': case 'T': @@ -68,10 +77,10 @@ static void tex_scan_adjust_keys(halfword *options, halfword *code, halfword *in halfword i = tex_scan_attribute_register_number(); halfword v = tex_scan_int(1, NULL); if (eq_value(register_attribute_location(i)) != v) { - if (*attrlist) { - *attrlist = tex_patch_attribute_list(*attrlist, i, v); + if (properties->attrlist) { + properties->attrlist = tex_patch_attribute_list(properties->attrlist, i, v); } else { - *attrlist = tex_copy_attribute_list_set(tex_current_attribute_list(), i, v); + properties->attrlist = tex_copy_attribute_list_set(tex_current_attribute_list(), i, v); } } } @@ -86,24 +95,24 @@ static void tex_scan_adjust_keys(halfword *options, halfword *code, halfword *in switch (tex_scan_character("abclABCL", 0, 1, 0)) { /* so a space is permitted */ case 'a': case 'A': if (tex_scan_mandate_keyword("after", 1)) { - *options |= adjust_option_depth_after; - *depthafter = tex_scan_dimen(0, 0, 0, 0, NULL); + properties->options |= adjust_option_depth_after; + properties->depthafter = tex_scan_dimen(0, 0, 0, 0, NULL); } break; case 'b': case 'B': if (tex_scan_mandate_keyword("before", 1)) { - *options |= adjust_option_depth_before; - *depthbefore = tex_scan_dimen(0, 0, 0, 0, NULL); + properties->options |= adjust_option_depth_before; + properties->depthbefore = tex_scan_dimen(0, 0, 0, 0, NULL); } break; case 'c': case 'C': if (tex_scan_mandate_keyword("check", 1)) { - *options |= adjust_option_depth_check; + properties->options |= adjust_option_depth_check; } break; case 'l': case 'L': if (tex_scan_mandate_keyword("last", 1)) { - *options |= adjust_option_depth_last; + properties->options |= adjust_option_depth_last; } break; default: @@ -125,21 +134,17 @@ int tex_valid_adjust_index(halfword n) return n >= 0; } -void tex_run_vadjust(void) +void tex_set_vadjust(halfword target) { - halfword code = post_adjust_code; - halfword options = adjust_option_none; - halfword index = 0; - scaled depthbefore = 0; - scaled depthafter = 0; - halfword attrlist = null; - tex_scan_adjust_keys(&options, &code, &index, &depthbefore, &depthafter, &attrlist); - tex_set_saved_record(saved_adjust_item_location, adjust_location_save_type, 0, code); - tex_set_saved_record(saved_adjust_item_options, adjust_options_save_type, 0, options); - tex_set_saved_record(saved_adjust_item_index, adjust_index_save_type, 0, index); - tex_set_saved_record(saved_adjust_item_attr_list, adjust_attr_list_save_type, 0, attrlist); - tex_set_saved_record(saved_adjust_item_depth_before, adjust_depth_before_save_type, 0, depthbefore); - tex_set_saved_record(saved_adjust_item_depth_after, adjust_depth_after_save_type, 0, depthafter); + adjust_properties properties; + tex_scan_adjust_keys(&properties); + tex_set_saved_record(saved_adjust_item_location, adjust_location_save_type, 0, properties.code); + tex_set_saved_record(saved_adjust_item_options, adjust_options_save_type, 0, properties.options); + tex_set_saved_record(saved_adjust_item_index, adjust_index_save_type, 0, properties.index); + tex_set_saved_record(saved_adjust_item_attr_list, adjust_attr_list_save_type, 0, properties.attrlist); + tex_set_saved_record(saved_adjust_item_depth_before, adjust_depth_before_save_type, 0, properties.depthbefore); + tex_set_saved_record(saved_adjust_item_depth_after, adjust_depth_after_save_type, 0, properties.depthafter); + tex_set_saved_record(saved_adjust_item_target, adjust_target_save_type, 0, target); lmt_save_state.save_stack_data.ptr += saved_adjust_n_of_items; tex_new_save_level(vadjust_group); tex_scan_left_brace(); @@ -149,29 +154,37 @@ void tex_run_vadjust(void) cur_list.prev_depth = ignore_depth_criterium_par; } +void tex_run_vadjust(void) +{ + tex_set_vadjust(-1); +} + void tex_finish_vadjust_group(void) { if (! tex_wrapped_up_paragraph(vadjust_par_context)) { - halfword box, topskip, adjust; /*tex for short-term use */ + halfword box, adjust, target; /*tex for short-term use */ tex_end_paragraph(vadjust_group, vadjust_par_context); - topskip = tex_new_glue_node(split_top_skip_par, top_skip_code); /* cheat */ tex_unsave(); lmt_save_state.save_stack_data.ptr -= saved_adjust_n_of_items; box = tex_vpack(node_next(cur_list.head), 0, packing_additional, max_dimen, direction_unknown, holding_none_option); tex_pop_nest(); adjust = tex_new_node(adjust_node, (quarterword) saved_value(saved_adjust_item_location)); - tex_tail_append(adjust); + target = saved_value(saved_adjust_item_target); adjust_list(adjust) = box_list(box); adjust_options(adjust) = (halfword) saved_value(saved_adjust_item_options); adjust_index(adjust) = (halfword) saved_value(saved_adjust_item_index); adjust_depth_before(adjust) = (halfword) saved_value(saved_adjust_item_depth_before); adjust_depth_after(adjust) = (halfword) saved_value(saved_adjust_item_depth_after); tex_attach_attribute_list_attribute(adjust, (halfword) saved_value(saved_adjust_item_attr_list)); - tex_flush_node(topskip); + if (target < 1) { + tex_tail_append(adjust); + } else { + tex_adjust_attach(target, adjust); + } box_list(box) = null; tex_flush_node(box); /* we never do the callback ... maybe move it outside */ - if (lmt_nest_state.nest_data.ptr == 0) { + if (target < 0 && lmt_nest_state.nest_data.ptr == 0) { if (! lmt_page_builder_state.output_active) { lmt_page_filter_callback(vadjust_page_context, 0); } @@ -182,7 +195,7 @@ void tex_finish_vadjust_group(void) /*tex Append or prepend vadjust nodes. Here head is a temp node! */ -halfword tex_append_adjust_list(halfword head, halfword tail, halfword adjust) +halfword tex_append_adjust_list(halfword head, halfword tail, halfword adjust, const char *detail) { while (adjust && node_type(adjust) == adjust_node) { halfword next = node_next(adjust); @@ -193,7 +206,7 @@ halfword tex_append_adjust_list(halfword head, halfword tail, halfword adjust) } if (tracing_adjusts_par > 1) { tex_begin_diagnostic(); - tex_print_format("[adjust: index %i, location %s, append]", adjust_index(adjust), tex_aux_subtype_str(adjust)); + tex_print_format("[adjust: index %i, location %s, append, %s]", adjust_index(adjust), tex_aux_subtype_str(adjust), detail); tex_print_node_list(adjust_list(adjust), "adjust",show_box_depth_par, show_box_breadth_par); tex_end_diagnostic(); } @@ -203,7 +216,7 @@ halfword tex_append_adjust_list(halfword head, halfword tail, halfword adjust) return tail; } -halfword tex_prepend_adjust_list(halfword head, halfword tail, halfword adjust) +halfword tex_prepend_adjust_list(halfword head, halfword tail, halfword adjust, const char *detail) { while (adjust && node_type(adjust) == adjust_node) { halfword next = node_next(adjust); @@ -216,7 +229,7 @@ halfword tex_prepend_adjust_list(halfword head, halfword tail, halfword adjust) } if (tracing_adjusts_par > 1) { tex_begin_diagnostic(); - tex_print_format("[adjust: index %i, location %s, prepend]", adjust_index(adjust), tex_aux_subtype_str(adjust)); + tex_print_format("[adjust: index %i, location %s, prepend, %s]", adjust_index(adjust), tex_aux_subtype_str(adjust), detail); tex_print_node_list(adjust_list(adjust), "adjust", show_box_depth_par, show_box_breadth_par); tex_end_diagnostic(); } @@ -227,84 +240,86 @@ halfword tex_prepend_adjust_list(halfword head, halfword tail, halfword adjust) void tex_inject_adjust_list(halfword adjust, int obeyoptions, halfword nextnode, const line_break_properties *properties) { - adjust = node_next(adjust); - if (adjust) { - while (adjust && node_type(adjust) == adjust_node) { - halfword list = adjust_list(adjust); - halfword next = node_next(adjust); - if (list) { - halfword prevnode = cur_list.tail; - if (tracing_adjusts_par > 1) { - tex_begin_diagnostic(); - tex_print_format("[adjust: index %i, location %s, inject]", adjust_index(adjust), tex_aux_subtype_str(adjust)); - tex_print_node_list(adjust_list(adjust), "adjust", show_box_depth_par, show_box_breadth_par); - tex_end_diagnostic(); - } - if (obeyoptions && has_adjust_option(adjust, adjust_option_baseline)) { - /*tex - Here we attach data to a line. On the todo is to prepend and append to - the lines (nicer when we number lines). - */ - if (node_type(list) == hlist_node || node_type(list) == vlist_node) { - if (nextnode) { - /*tex - This is the |pre| case where |nextnode| is the line to be appended - after the adjust box |list|. - */ - if (node_type(nextnode) == hlist_node || node_type(nextnode) == vlist_node) { - if (box_height(nextnode) > box_height(list)) { - box_height(list) = box_height(nextnode); - } - if (box_depth(list) > box_depth(nextnode)) { - box_depth(nextnode) = box_depth(list); - } - /* not ok yet */ - box_y_offset(nextnode) += box_height(nextnode); - tex_check_box_geometry(nextnode); - /* till here */ - box_height(nextnode) = 0; - box_depth(list) = 0; + if (adjust && node_type(adjust) == temp_node) { + adjust = node_next(adjust); + } + while (adjust && node_type(adjust) == adjust_node) { + halfword next = node_next(adjust); + halfword list = adjust_list(adjust); + if (tracing_adjusts_par > 1) { + tex_begin_diagnostic(); + tex_print_format("[adjust: index %i, location %s, inject]", adjust_index(adjust), tex_aux_subtype_str(adjust)); + tex_print_node_list(adjust_list(adjust), "adjust", show_box_depth_par, show_box_breadth_par); + tex_end_diagnostic(); + } + if (list) { + if (obeyoptions && has_adjust_option(adjust, adjust_option_baseline)) { + /*tex + Here we attach data to a line. On the todo is to prepend and append to + the lines (nicer when we number lines). + */ + if (node_type(list) == hlist_node || node_type(list) == vlist_node) { + if (nextnode) { + /*tex + This is the |pre| case where |nextnode| is the line to be appended + after the adjust box |list|. + */ + if (node_type(nextnode) == hlist_node || node_type(nextnode) == vlist_node) { + if (box_height(nextnode) > box_height(list)) { + box_height(list) = box_height(nextnode); } - } else { - /*tex - Here we have the |post| case where the line will end up before the - adjusted content. - */ - if (node_type(prevnode) == hlist_node || node_type(prevnode) == vlist_node) { - if (box_height(prevnode) < box_height(list)) { - box_height(prevnode) = box_height(list); - } - if (box_depth(list) < box_depth(prevnode)) { - box_depth(list) = box_depth(prevnode); - } - box_height(list) = 0; - box_depth(prevnode) = 0; + if (box_depth(list) > box_depth(nextnode)) { + box_depth(nextnode) = box_depth(list); + } + /* not ok yet */ + box_y_offset(nextnode) += box_height(nextnode); + tex_check_box_geometry(nextnode); + /* till here */ + box_height(nextnode) = 0; + box_depth(list) = 0; + } + } else { + /*tex + Here we have the |post| case where the line will end up before the + adjusted content. + */ + halfword prevnode = cur_list.tail; + if (node_type(prevnode) == hlist_node || node_type(prevnode) == vlist_node) { + if (box_height(prevnode) < box_height(list)) { + box_height(prevnode) = box_height(list); + } + if (box_depth(list) < box_depth(prevnode)) { + box_depth(list) = box_depth(prevnode); } + box_height(list) = 0; + box_depth(prevnode) = 0; } } } - if (obeyoptions && has_adjust_option(adjust, adjust_option_depth_before)) { - cur_list.prev_depth = adjust_depth_before(adjust); - } - if (obeyoptions && has_adjust_option(adjust, adjust_option_depth_check)) { - tex_append_to_vlist(list, -1, properties); - } else { - tex_couple_nodes(prevnode, list); - } - if (obeyoptions && has_adjust_option(adjust, adjust_option_depth_after)) { - cur_list.prev_depth = adjust_depth_after(adjust); - } else if (obeyoptions && has_adjust_option(adjust, adjust_option_depth_last)) { - cur_list.prev_depth = box_depth(list); - } - cur_list.tail = tex_tail_of_node_list(cur_list.tail); - if (! lmt_page_builder_state.output_active) { - lmt_append_line_filter_callback(post_adjust_append_line_context, adjust_index(adjust)); - } + } + if (obeyoptions && has_adjust_option(adjust, adjust_option_depth_before)) { + cur_list.prev_depth = adjust_depth_before(adjust); + } + if (obeyoptions && has_adjust_option(adjust, adjust_option_depth_check)) { + tex_append_to_vlist(list, -1, properties); + } else { + tex_tail_append_list(list); + // tex_couple_nodes(prevnode, list); + // cur_list.tail = tex_tail_of_node_list(list); + } + if (obeyoptions && has_adjust_option(adjust, adjust_option_depth_after)) { + cur_list.prev_depth = adjust_depth_after(adjust); + } else if (obeyoptions && has_adjust_option(adjust, adjust_option_depth_last)) { + cur_list.prev_depth = box_depth(list); + } +// cur_list.tail = tex_tail_of_node_list(cur_list.tail); + if (! lmt_page_builder_state.output_active) { + lmt_append_line_filter_callback(post_adjust_append_line_context, adjust_index(adjust)); } adjust_list(adjust) = null; - tex_flush_node(adjust); - adjust = next; } + tex_flush_node(adjust); + adjust = next; } } @@ -313,6 +328,12 @@ void tex_adjust_attach(halfword box, halfword adjust) if (adjust_list(adjust)) { node_prev(adjust) = null; node_next(adjust) = null; + if (tracing_adjusts_par > 1) { + tex_begin_diagnostic(); + tex_print_format("[adjust: index %i, location %s, attach]", adjust_index(adjust), tex_aux_subtype_str(adjust)); + tex_print_node_list(adjust_list(adjust), "attach",show_box_depth_par, show_box_breadth_par); + tex_end_diagnostic(); + } switch (node_subtype(adjust)) { case pre_adjust_code: if (! box_pre_adjusted(box)) { @@ -356,9 +377,9 @@ void tex_adjust_passon(halfword box, halfword adjust) case pre_adjust_code: if (lmt_packaging_state.pre_adjust_tail) { if (lmt_packaging_state.pre_adjust_tail != pre_adjust_head && has_adjust_option(adjust, adjust_option_before)) { - lmt_packaging_state.pre_adjust_tail = tex_prepend_adjust_list(pre_adjust_head, lmt_packaging_state.pre_adjust_tail, adjust); + lmt_packaging_state.pre_adjust_tail = tex_prepend_adjust_list(pre_adjust_head, lmt_packaging_state.pre_adjust_tail, adjust, "passon"); } else { - lmt_packaging_state.pre_adjust_tail = tex_append_adjust_list(pre_adjust_head, lmt_packaging_state.pre_adjust_tail, adjust); + lmt_packaging_state.pre_adjust_tail = tex_append_adjust_list(pre_adjust_head, lmt_packaging_state.pre_adjust_tail, adjust, "passon"); } } else { tex_normal_error("vadjust pre", "invalid list"); @@ -367,9 +388,9 @@ void tex_adjust_passon(halfword box, halfword adjust) case post_adjust_code: if (lmt_packaging_state.post_adjust_tail) { if (lmt_packaging_state.post_adjust_tail != post_adjust_head && has_adjust_option(adjust, adjust_option_before)) { - lmt_packaging_state.post_adjust_tail = tex_prepend_adjust_list(post_adjust_head, lmt_packaging_state.post_adjust_tail, adjust); + lmt_packaging_state.post_adjust_tail = tex_prepend_adjust_list(post_adjust_head, lmt_packaging_state.post_adjust_tail, adjust, "passon"); } else { - lmt_packaging_state.post_adjust_tail = tex_append_adjust_list(post_adjust_head, lmt_packaging_state.post_adjust_tail, adjust); + lmt_packaging_state.post_adjust_tail = tex_append_adjust_list(post_adjust_head, lmt_packaging_state.post_adjust_tail, adjust, "passon"); } } else { tex_normal_error("vadjust post", "invalid list"); @@ -384,6 +405,64 @@ void tex_adjust_passon(halfword box, halfword adjust) } } +static void tex_aux_show_flush_adjust(halfword adjust, const char *what, const char *detail) +{ + if (tracing_adjusts_par > 1) { + tex_begin_diagnostic(); + tex_print_format("[adjust: index %i, location %s, flush, %s]", adjust_index(adjust), tex_aux_subtype_str(adjust), detail); + tex_print_node_list(adjust_list(adjust), what, show_box_depth_par, show_box_breadth_par); + tex_end_diagnostic(); + } +} + +halfword tex_flush_adjust_append(halfword adjust, halfword tail) +{ + while (adjust) { + halfword p = adjust; + halfword h = adjust_list(adjust); + if (h) { + int ishmode = is_h_mode(cur_list.mode); + tex_aux_show_flush_adjust(p, "append", ishmode ? "repack" : "direct"); + if (ishmode) { + halfword n = tex_new_node(adjust_node, post_adjust_code); + // tex_attach_attribute_list_copy(n, post_adjusted); + adjust_list(n) = h; + h = n; + } + tex_try_couple_nodes(tail, h); + tail = tex_tail_of_node_list(h); + adjust_list(p) = null; + } + adjust = node_next(p); + tex_flush_node(p); + } + return tail; +} + +halfword tex_flush_adjust_prepend(halfword adjust, halfword tail) +{ + while (adjust) { + halfword p = adjust; + halfword h = adjust_list(adjust); + if (h) { + int ishmode = is_h_mode(cur_list.mode); + tex_aux_show_flush_adjust(p, "prepend", ishmode ? "repack" : "direct"); + if (ishmode) { + halfword n = tex_new_node(adjust_node, pre_adjust_code); + // tex_attach_attribute_list_copy(n, pre_adjusted); + adjust_list(n) = h; + h = n; + } + tex_try_couple_nodes(tail, h); + tail = tex_tail_of_node_list(h); + adjust_list(p) = null; + } + adjust = node_next(p); + tex_flush_node(p); + } + return tail; +} + void tex_initialize_adjust(void) { } |