summaryrefslogtreecommitdiff
path: root/source/luametatex/source/tex/texalign.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/luametatex/source/tex/texalign.c')
-rw-r--r--source/luametatex/source/tex/texalign.c351
1 files changed, 341 insertions, 10 deletions
diff --git a/source/luametatex/source/tex/texalign.c b/source/luametatex/source/tex/texalign.c
index ac7712870..f35bb50b5 100644
--- a/source/luametatex/source/tex/texalign.c
+++ b/source/luametatex/source/tex/texalign.c
@@ -205,6 +205,19 @@
Todo: lefttabskip righttabskip middletabskip
*/
+typedef struct alignment_row_state {
+ halfword orientation;
+ scaled xoffset;
+ scaled yoffset;
+ scaled xmove;
+ scaled ymove;
+ halfword shift;
+ halfword source;
+ halfword target;
+ halfword anchor;
+ halfword attrlist;
+} alignment_row_state;
+
typedef struct alignment_state_info {
halfword cur_align; /*tex The current position in the preamble list. */
halfword cur_span; /*tex The start of the currently spanned columns in the preamble list. */
@@ -223,11 +236,14 @@ typedef struct alignment_state_info {
halfword no_align_level;
halfword no_tab_skips;
halfword attr_list;
- halfword cell_source;
- halfword wrap_source;
+ halfword cell_source;
+ halfword wrap_source; /*tex There's also a field in the row_state. */
halfword callback;
// halfword reverse; // todo
// halfword discard_skips; // todo
+ halfword row_state_set;
+ halfword padding;
+ alignment_row_state row_state;
} alignment_state_info ;
static alignment_state_info lmt_alignment_state = {
@@ -253,8 +269,38 @@ static alignment_state_info lmt_alignment_state = {
.callback = 0,
// .reverse = 0,
// .discard_skips = 0,
+ .row_state_set = 0,
+ .padding = 0,
+ .row_state = {
+ .attrlist = null,
+ .orientation = 0,
+ .xoffset = 0,
+ .yoffset = 0,
+ .xmove = 0,
+ .ymove = 0,
+ .shift = 0,
+ .source = 0,
+ .target = 0,
+ .anchor = 0,
+ }
};
+static void tex_aux_wipe_row_state(void)
+{
+ delete_attribute_reference(lmt_alignment_state.row_state.attrlist);
+ lmt_alignment_state.row_state.attrlist = null;
+ lmt_alignment_state.row_state.orientation = 0;
+ lmt_alignment_state.row_state.xoffset = 0;
+ lmt_alignment_state.row_state.yoffset = 0;
+ lmt_alignment_state.row_state.xmove = 0;
+ lmt_alignment_state.row_state.ymove = 0;
+ lmt_alignment_state.row_state.shift = 0;
+ lmt_alignment_state.row_state.source = 0;
+ lmt_alignment_state.row_state.target = 0;
+ lmt_alignment_state.row_state.anchor = 0;
+ lmt_alignment_state.row_state_set = 0;
+}
+
/*tex We could as well save these in the alignment stack. */
typedef enum saved_align_items {
@@ -313,6 +359,7 @@ static void tex_aux_push_alignment(void)
{
/*tex The new alignment stack node: */
halfword p = tex_new_node(align_stack_node, 0);
+ /* todo: just a memory copy */
align_stack_align_ptr(p) = lmt_alignment_state.align_ptr;
align_stack_cur_align(p) = lmt_alignment_state.cur_align;
align_stack_preamble(p) = preamble;
@@ -331,6 +378,18 @@ static void tex_aux_push_alignment(void)
align_stack_cur_pre_migrate_tail(p) = lmt_alignment_state.cur_pre_migrate_tail;
align_stack_no_tab_skips(p) = lmt_alignment_state.no_tab_skips;
align_stack_attr_list(p) = lmt_alignment_state.attr_list;
+ /* */
+ align_stack_row_attrlist(p) = lmt_alignment_state.row_state.attrlist;
+ align_stack_row_orientation(p) = lmt_alignment_state.row_state.orientation;
+ align_stack_row_yoffset(p) = lmt_alignment_state.row_state.xoffset;
+ align_stack_row_xoffset(p) = lmt_alignment_state.row_state.yoffset;
+ align_stack_row_ymove(p) = lmt_alignment_state.row_state.xmove;
+ align_stack_row_xmove(p) = lmt_alignment_state.row_state.ymove;
+ align_stack_row_shift(p) = lmt_alignment_state.row_state.shift;
+ align_stack_row_source(p) = lmt_alignment_state.row_state.source;
+ align_stack_row_target(p) = lmt_alignment_state.row_state.target;
+ align_stack_row_anchor(p) = lmt_alignment_state.row_state.anchor;
+ /* */
lmt_alignment_state.align_ptr = p;
lmt_alignment_state.cur_post_adjust_head = tex_new_temp_node();
lmt_alignment_state.cur_pre_adjust_head = tex_new_temp_node();
@@ -339,6 +398,8 @@ static void tex_aux_push_alignment(void)
/* */
lmt_alignment_state.cell_source = 0;
lmt_alignment_state.wrap_source = 0;
+ /* todo: put in align_stack, also wipe attr if needed */
+ tex_aux_wipe_row_state();
}
static void tex_aux_pop_alignment(void)
@@ -367,6 +428,18 @@ static void tex_aux_pop_alignment(void)
lmt_alignment_state.cur_pre_migrate_tail = align_stack_cur_pre_migrate_tail(p);
lmt_alignment_state.no_tab_skips = align_stack_no_tab_skips(p);
lmt_alignment_state.attr_list = align_stack_attr_list(p);
+ /* */
+ lmt_alignment_state.row_state.attrlist = align_stack_row_attrlist(p);
+ lmt_alignment_state.row_state.orientation = align_stack_row_orientation(p);
+ lmt_alignment_state.row_state.xoffset = align_stack_row_yoffset(p);
+ lmt_alignment_state.row_state.yoffset = align_stack_row_xoffset(p);
+ lmt_alignment_state.row_state.xmove = align_stack_row_ymove(p);
+ lmt_alignment_state.row_state.ymove = align_stack_row_xmove(p);
+ lmt_alignment_state.row_state.shift = align_stack_row_shift(p);
+ lmt_alignment_state.row_state.source = align_stack_row_source(p);
+ lmt_alignment_state.row_state.target = align_stack_row_target(p);
+ lmt_alignment_state.row_state.anchor = align_stack_row_anchor(p);
+ /* */
tex_flush_node(p);
}
@@ -590,7 +663,154 @@ static void tex_aux_trace_no_align(const char *s)
static void tex_aux_run_no_align(void)
{
- tex_scan_left_brace();
+ /* */
+ int brace = 0;
+ int done = lmt_alignment_state.row_state_set;
+ while (1) {
+ int add = 0;
+ AGAIN:
+ switch (tex_scan_character("atrsoxyATRSOXY", 1, 1, 1)) {
+ case 0:
+ goto DONE;
+ case 't': case 'T':
+ if (tex_scan_mandate_keyword("target", 1)) {
+ lmt_alignment_state.row_state.target = tex_scan_int(1, NULL);
+ done = 1;
+ }
+ break;
+ case 'a': case 'A':
+ switch (tex_scan_character("ntdNTD", 0, 0, 0)) {
+ case 'd': case 'D':
+ if (tex_scan_mandate_keyword("add", 2)) {
+ add = 1;
+ goto AGAIN;
+ }
+ break;
+ case 't': case 'T':
+ if (tex_scan_mandate_keyword("attr", 2)) {
+ halfword i = tex_scan_attribute_register_number();
+ halfword v = tex_scan_int(1, NULL);
+ if (eq_value(register_attribute_location(i)) != v) {
+ if (lmt_alignment_state.row_state.attrlist) {
+ lmt_alignment_state.row_state.attrlist = tex_patch_attribute_list(lmt_alignment_state.row_state.attrlist, i, v);
+ } else {
+ lmt_alignment_state.row_state.attrlist = tex_copy_attribute_list_set(tex_current_attribute_list(), i, v);
+ }
+ done = 1;
+ }
+ }
+ break;
+ case 'n': case 'N':
+ if (tex_scan_mandate_keyword("anchor", 2)) {
+ switch (tex_scan_character("sS", 0, 0, 0)) {
+ case 's': case 'S':
+ lmt_alignment_state.row_state.anchor = tex_scan_anchors(0);
+ break;
+ default:
+ lmt_alignment_state.row_state.anchor = tex_scan_anchor(0);
+ break;
+ }
+ done = 1;
+ }
+ break;
+ default:
+ tex_aux_show_keyword_error("attr|anchor|add");
+ goto DONE;
+ }
+ break;
+ case 'r': case 'R':
+ if (tex_scan_mandate_keyword("reset", 1)) {
+ tex_aux_wipe_row_state();
+ done = 0;
+ }
+ break;
+ case 's': case 'S':
+ switch (tex_scan_character("hoHO", 0, 0, 0)) {
+ case 'h': case 'H':
+ if (tex_scan_mandate_keyword("shift", 2)) {
+ lmt_alignment_state.row_state.shift = (add ? lmt_alignment_state.row_state.shift : 0)
+ + tex_scan_dimen(0, 0, 0, 0, NULL);
+ done = 1;
+ }
+ break;
+ case 'o': case 'O':
+ if (tex_scan_mandate_keyword("source", 2)) {
+ lmt_alignment_state.row_state.source = tex_scan_int(1, NULL);
+ done = 1;
+ }
+ break;
+ default:
+ tex_aux_show_keyword_error("shift|source");
+ goto DONE;
+ }
+ break;
+ case 'o': case 'O':
+ if (tex_scan_mandate_keyword("orientation", 1)) {
+ lmt_alignment_state.row_state.orientation = tex_scan_orientation(0);
+ done = 1;
+ }
+ break;
+ case 'x': case 'X':
+ switch (tex_scan_character("omOM", 0, 0, 0)) {
+ case 'o': case 'O' :
+ if (tex_scan_mandate_keyword("xoffset", 2)) {
+ lmt_alignment_state.row_state.xoffset = (add ? lmt_alignment_state.row_state.xoffset : 0)
+ + tex_scan_dimen(0, 0, 0, 0, NULL);
+ done = 1;
+ }
+ break;
+ case 'm': case 'M' :
+ if (tex_scan_mandate_keyword("xmove", 2)) {
+ lmt_alignment_state.row_state.xmove = (add ? lmt_alignment_state.row_state.xmove : 0)
+ + tex_scan_dimen(0, 0, 0, 0, NULL);
+ done = 1;
+ }
+ break;
+ default:
+ tex_aux_show_keyword_error("xoffset|xmove");
+ goto DONE;
+ }
+ break;
+ case 'y': case 'Y':
+ switch (tex_scan_character("omOM", 0, 0, 0)) {
+ case 'o': case 'O' :
+ if (tex_scan_mandate_keyword("yoffset", 2)) {
+ lmt_alignment_state.row_state.yoffset = (add ? lmt_alignment_state.row_state.yoffset : 0)
+ + tex_scan_dimen(0, 0, 0, 0, NULL);
+ done = 1;
+ }
+ break;
+ case 'm': case 'M' :
+ if (tex_scan_mandate_keyword("ymove", 2)) {
+ lmt_alignment_state.row_state.ymove = (add ? lmt_alignment_state.row_state.ymove : 0)
+ + tex_scan_dimen(0, 0, 0, 0, NULL);
+ done = 1;
+ }
+ break;
+ default:
+ tex_aux_show_keyword_error("yoffset|ymove");
+ goto DONE;
+ }
+ break;
+ case '{':
+ brace = 1;
+ goto DONE;
+ default:
+ goto DONE;
+ }
+ add = 0;
+ }
+ DONE:
+ lmt_alignment_state.row_state_set = done;
+ if (! lmt_alignment_state.row_state.attrlist) {
+ /* this alse sets the reference when not yet set */
+ lmt_alignment_state.row_state.attrlist = tex_current_attribute_list();
+ }
+ add_attribute_reference(lmt_alignment_state.row_state.attrlist);
+ /* */
+ if (! brace) {
+ tex_scan_left_brace();
+ }
tex_new_save_level(no_align_group);
++lmt_alignment_state.no_align_level;
tex_aux_trace_no_align("entering");
@@ -598,6 +818,7 @@ static void tex_aux_run_no_align(void)
tex_normal_paragraph(no_align_par_context);
}
}
+
static int tex_aux_nested_no_align(void)
{
int state = lmt_alignment_state.no_align_level > 0;
@@ -846,7 +1067,7 @@ static void tex_aux_initialize_span(halfword p)
if (cur_list.mode == -hmode) {
cur_list.space_factor = 1000;
} else {
- cur_list.prev_depth = ignore_depth;
+ cur_list.prev_depth = ignore_depth_criterium_par;
tex_normal_paragraph(span_par_context);
}
lmt_alignment_state.cur_span = p;
@@ -864,8 +1085,8 @@ static void tex_aux_initialize_span(halfword p)
static void tex_aux_initialize_row(void)
{
tex_push_nest();
- cur_list.mode = (- hmode - vmode) - cur_list.mode; /* weird code */
- if (cur_list.mode == -hmode) {
+ cur_list.mode = (- hmode - vmode) - cur_list.mode; /* weird code : - 3 - cur_list.mode : so a buogus line */
+ if (cur_list.mode == -hmode) {
cur_list.space_factor = 0;
} else {
cur_list.prev_depth = 0;
@@ -882,6 +1103,7 @@ static void tex_aux_initialize_row(void)
lmt_alignment_state.cur_post_migrate_tail = lmt_alignment_state.cur_post_migrate_head;
lmt_alignment_state.cur_pre_migrate_tail = lmt_alignment_state.cur_pre_migrate_head;
tex_aux_initialize_span(lmt_alignment_state.cur_align);
+ /* todo: wipe attr */
}
/*tex
@@ -1200,12 +1422,114 @@ static void tex_aux_finish_row(void)
tex_tail_append(row);
cur_list.space_factor = 1000;
}
+ /*tex
+ Currently this one can be overloaded by the one set on the row via the noalign trickery
+ which is probably okay.
+ */
if (lmt_alignment_state.wrap_source) {
box_source_anchor(row) = lmt_alignment_state.wrap_source;
- tex_set_box_geometry(row, anchor_geometry);
+ box_geometry(row) |= anchor_geometry;
}
+ /*
+ This also wipes (list) fields that we might set below, like |xoffset| that is used for
+ specific alignments purposes.
+ */
tex_aux_change_list_type(row, unset_node);
- tex_attach_attribute_list_attribute(row, lmt_alignment_state.attr_list);
+ /* */
+ tex_attach_attribute_list_attribute(row, lmt_alignment_state.row_state.attrlist ?
+ lmt_alignment_state.row_state.attrlist : lmt_alignment_state.attr_list);
+ /*tex
+ The next blob of code duplicates some of packaging code but because we fetch from different
+ fields we cannot share. Maybe, when I add this kind of features to other mechanisms (how
+ about cells!) then the next code will become some helper.
+ */
+ if (lmt_alignment_state.row_state_set) {
+ halfword orientation = lmt_alignment_state.row_state.orientation;
+ halfword anchor = lmt_alignment_state.row_state.anchor;
+ scaled shift = lmt_alignment_state.row_state.shift;
+ halfword source = lmt_alignment_state.row_state.source;
+ halfword target = lmt_alignment_state.row_state.target;
+ scaled xoffset = lmt_alignment_state.row_state.xoffset;
+ scaled yoffset = lmt_alignment_state.row_state.yoffset;
+ scaled xmove = lmt_alignment_state.row_state.xmove;
+ scaled ymove = lmt_alignment_state.row_state.ymove;
+ singleword geometry = box_geometry(row);
+ /* */
+ if (xoffset || yoffset || xmove || ymove) {
+ geometry |= offset_geometry;
+ }
+ if (orientation) {
+ geometry |= orientation_geometry;
+ }
+ /* */
+ if (tex_has_geometry(geometry, offset_geometry) || tex_has_geometry(geometry, orientation_geometry)) {
+ scaled wd = box_width(row);
+ scaled ht = box_height(row);
+ scaled dp = box_depth(row);
+ if (xmove) {
+ xoffset = tex_aux_checked_dimen1(xoffset + xmove);
+ wd = tex_aux_checked_dimen2(wd + xmove);
+ set_box_package_state(row, package_dimension_size_set); /* safeguard */
+ }
+ if (ymove) {
+ yoffset = tex_aux_checked_dimen1(yoffset + ymove);
+ ht = tex_aux_checked_dimen2(ht + ymove);
+ dp = tex_aux_checked_dimen2(dp - ymove);
+ }
+ box_w_offset(row) = wd;
+ box_h_offset(row) = ht;
+ box_d_offset(row) = dp;
+ switch (orientationonly(orientation)) {
+ case 0 : /* 0 */
+ break;
+ case 2 : /* 180 */
+ box_height(row) = dp;
+ box_depth(row) = ht;
+ geometry |= orientation_geometry;
+ break;
+ case 1 : /* 90 */
+ case 3 : /* 270 */
+ box_width(row) = ht + dp;
+ box_height(row) = wd;
+ box_depth(row) = 0;
+ geometry |= orientation_geometry;
+ break;
+ case 4 : /* 0 */
+ box_height(row) = ht + dp;
+ box_depth(row) = 0;
+ geometry |= orientation_geometry;
+ break;
+ case 5 : /* 180 */
+ box_height(row) = 0;
+ box_depth(row) = ht + dp;
+ geometry |= orientation_geometry;
+ break;
+ default :
+ break;
+ }
+ if (xoffset || yoffset) {
+ box_x_offset(row) = xoffset;
+ box_y_offset(row) = yoffset;
+ geometry |= offset_geometry;
+ }
+ }
+ if (shift) {
+ box_shift_amount(row) = shift;
+ }
+ if (source || target) {
+ box_source_anchor(row) = source;
+ box_target_anchor(row) = target;
+ geometry |= anchor_geometry;
+ }
+ box_anchor(row) = anchor;
+ box_orientation(row) = orientation;
+ box_geometry(row) = (singleword) geometry;
+ }
+ /*tex
+ We no longer need the row state so best wipe it now! Then we're ready for the next row.
+ */
+ tex_aux_wipe_row_state();
+ /* */
if (every_cr_par) {
tex_begin_token_list(every_cr_par, every_cr_text);
}
@@ -1438,10 +1762,12 @@ static void tex_aux_finish_align(void)
halfword preptr;
halfword colptr;
if (cur_list.mode == -vmode) {
- tex_aux_change_list_type(rowptr, hlist_node);
+ /* tex_aux_change_list_type(rowptr, hlist_node); */ /* too much */
+ node_type(rowptr) = hlist_node;
box_width(rowptr) = box_width(preroll);
} else {
- tex_aux_change_list_type(rowptr, vlist_node);
+ /* tex_aux_change_list_type(rowptr, vlist_node); */ /* too much */
+ node_type(rowptr) = vlist_node;
box_height(rowptr) = box_height(preroll);
}
node_subtype(rowptr) = align_row_list;
@@ -1609,6 +1935,11 @@ static void tex_aux_finish_align(void)
if (reverse) {
box_list(rowptr) = tex_reversed_node_list(box_list(rowptr));
}
+ if (has_box_package_state(rowptr, package_dimension_size_set)) {
+ if (box_w_offset(rowptr) > box_width(rowptr)) {
+ box_width(rowptr) = box_w_offset(rowptr);
+ }
+ }
}
break;
case rule_node: