diff options
author | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2015-12-16 14:50:11 +0000 |
---|---|---|
committer | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2015-12-16 14:50:11 +0000 |
commit | 621273b5ef8cc9e83d9aca07bf012f727ba26f15 (patch) | |
tree | 0b5cb28eec37e3e0e93a09729cbc30834166a5f9 /Build/source/texk/web2c/luatexdir/tex/packaging.w | |
parent | f04f01782aebac8cb2fcde278c02a4fb3be4bb12 (diff) |
web2c/luatexdir: LuaTeX beta-0.86.0 (Sync with the upstream).
git-svn-id: svn://tug.org/texlive/trunk@39116 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/tex/packaging.w')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/tex/packaging.w | 1577 |
1 files changed, 898 insertions, 679 deletions
diff --git a/Build/source/texk/web2c/luatexdir/tex/packaging.w b/Build/source/texk/web2c/luatexdir/tex/packaging.w index 173b7894cb2..b1e8c44425e 100644 --- a/Build/source/texk/web2c/luatexdir/tex/packaging.w +++ b/Build/source/texk/web2c/luatexdir/tex/packaging.w @@ -1,4 +1,4 @@ -4% packaging.w +% packaging.w % % Copyright 2009-2010 Taco Hoekwater <taco@@luatex.org> % @@ -19,7 +19,6 @@ @ @c - #include "ptexlib.h" @ @c @@ -29,101 +28,210 @@ #define space_factor cur_list.space_factor_field #define box(A) eqtb[box_base+(A)].hh.rh -#define text_direction int_par(text_direction_code) -#define body_direction int_par(body_direction_code) #define every_hbox equiv(every_hbox_loc) #define every_vbox equiv(every_vbox_loc) #define box_max_depth dimen_par(box_max_depth_code) - -@ We're essentially done with the parts of \TeX\ that are concerned with -the input (|get_next|) and the output (|ship_out|). So it's time to -get heavily into the remaining part, which does the real work of typesetting. - -After lists are constructed, \TeX\ wraps them up and puts them into boxes. -Two major subroutines are given the responsibility for this task: |hpack| -applies to horizontal lists (hlists) and |vpack| applies to vertical lists -(vlists). The main duty of |hpack| and |vpack| is to compute the dimensions -of the resulting boxes, and to adjust the glue if one of those dimensions -is pre-specified. The computed sizes normally enclose all of the material -inside the new box; but some items may stick out if negative glue is used, -if the box is overfull, or if a \.{\\vbox} includes other boxes that have -been shifted left. - -The subroutine call |hpack(p,w,m)| returns a pointer to an |hlist_node| -for a box containing the hlist that starts at |p|. Parameter |w| specifies -a width; and parameter |m| is either `|exactly|' or `|additional|'. Thus, -|hpack(p,w,exactly)| produces a box whose width is exactly |w|, while -|hpack(p,w,additional)| yields a box whose width is the natural width plus -|w|. It is convenient to define a macro called `|natural|' to cover the -most common case, so that we can say |hpack(p,natural)| to get a box that -has the natural width of list |p|. - -Similarly, |vpack(p,w,m)| returns a pointer to a |vlist_node| for a -box containing the vlist that starts at |p|. In this case |w| represents -a height instead of a width; the parameter |m| is interpreted as in |hpack|. - - -@ The parameters to |hpack| and |vpack| correspond to \TeX's primitives -like `\.{\\hbox} \.{to} \.{300pt}', `\.{\\hbox} \.{spread} \.{10pt}'; note -that `\.{\\hbox}' with no dimension following it is equivalent to -`\.{\\hbox} \.{spread} \.{0pt}'. The |scan_spec| subroutine scans such -constructions in the user's input, including the mandatory left brace that -follows them, and it puts the specification onto |save_stack| so that the -desired box can later be obtained by executing the following code: -$$\vbox{\halign{#\hfil\cr -|save_ptr:=save_ptr-1;|\cr -|hpack(p,saved_value(0),saved_level(0)).|\cr}}$$ +@ We're essentially done with the parts of \TeX\ that are concerned with the +input (|get_next|) and the output (|ship_out|). So it's time to get heavily into +the remaining part, which does the real work of typesetting. + +After lists are constructed, \TeX\ wraps them up and puts them into boxes. Two +major subroutines are given the responsibility for this task: |hpack| applies to +horizontal lists (hlists) and |vpack| applies to vertical lists (vlists). The +main duty of |hpack| and |vpack| is to compute the dimensions of the resulting +boxes, and to adjust the glue if one of those dimensions is pre-specified. The +computed sizes normally enclose all of the material inside the new box; but some +items may stick out if negative glue is used, if the box is overfull, or if a +\.{\\vbox} includes other boxes that have been shifted left. + +The subroutine call |hpack(p,w,m)| returns a pointer to an |hlist_node| for a box +containing the hlist that starts at |p|. Parameter |w| specifies a width; and +parameter |m| is either `|exactly|' or `|additional|'. Thus, |hpack(p,w,exactly)| +produces a box whose width is exactly |w|, while |hpack(p,w,additional)| yields a +box whose width is the natural width plus |w|. It is convenient to define a macro +called `|natural|' to cover the most common case, so that we can say +|hpack(p,natural)| to get a box that has the natural width of list |p|. + +Similarly, |vpack(p,w,m)| returns a pointer to a |vlist_node| for a box +containing the vlist that starts at |p|. In this case |w| represents a height +instead of a width; the parameter |m| is interpreted as in |hpack|. + +@ The parameters to |hpack| and |vpack| correspond to \TeX's primitives like +`\.{\\hbox} \.{to} \.{300pt}', `\.{\\hbox} \.{spread} \.{10pt}'; note that +`\.{\\hbox}' with no dimension following it is equivalent to `\.{\\hbox} +\.{spread} \.{0pt}'. The |scan_spec| subroutine scans such constructions in the +user's input, including the mandatory left brace that follows them, and it puts +the specification onto |save_stack| so that the desired box can later be obtained +by executing the following code: $$\vbox{\halign{#\hfil\cr +|save_ptr:=save_ptr-1;|\cr |hpack(p,saved_value(0),saved_level(0)).|\cr}}$$ @c +/* + void scan_spec(group_code c) + { + int spec_code; + if (scan_keyword("to")) { + spec_code = exactly; + scan_normal_dimen(); + } else if (scan_keyword("spread")) { + spec_code = additional; + scan_normal_dimen(); + } else { + spec_code = additional; + cur_val = 0; + } + set_saved_record(0, saved_boxspec, spec_code, cur_val); + save_ptr++; + new_save_level(c); + scan_left_brace(); + } +*/ + void scan_spec(group_code c) { /* scans a box specification and left brace */ int spec_code; - if (scan_keyword("to")) { - spec_code = exactly; - scan_normal_dimen(); - } else if (scan_keyword("spread")) { - spec_code = additional; - scan_normal_dimen(); - } else { + boolean done = false ; + do { + get_x_token(); + } while ((cur_cmd == spacer_cmd) || (cur_cmd == relax_cmd)); + if (cur_cmd == left_brace_cmd) { spec_code = additional; cur_val = 0; + done = true; + } else { + /* todo: attr */ + back_input(); + if (scan_keyword("to")) { + spec_code = exactly; + scan_normal_dimen(); + } else if (scan_keyword("spread")) { + spec_code = additional; + scan_normal_dimen(); + } else { + spec_code = additional; + cur_val = 0; + } } set_saved_record(0, saved_boxspec, spec_code, cur_val); save_ptr++; new_save_level(c); - scan_left_brace(); + if (!done) { + scan_left_brace(); + } } - @ When scanning, special care is necessary to ensure that the special -|save_stack| codes are placed just below the new group code, because -scanning can change |save_stack| when \.{\\csname} appears. +|save_stack| codes are placed just below the new group code, because scanning can +change |save_stack| when \.{\\csname} appears. -This coincides with the text on |dir| and |attr| keywords, as these -are exaclty the uses of \.{\\hbox}, \.{\\vbox}, and \.{\\vtop} in the -input stream (the others are \.{\\vcenter}, \.{\\valign}, and -\.{\\halign}). +This coincides with the text on |dir| and |attr| keywords, as these are exaclty +the uses of \.{\\hbox}, \.{\\vbox}, and \.{\\vtop} in the input stream (the +others are \.{\\vcenter}, \.{\\valign}, and \.{\\halign}). @c -void scan_full_spec(group_code c, int spec_direction) -{ /* scans a box specification and left brace */ - int s; /* temporarily saved value */ +/* + void scan_full_spec(group_code c, int spec_direction) + { + int s; + int i; + int v; + int spec_code; + halfword attr_list; + if (attr_list_cache == cache_disabled) + update_attribute_cache(); + attr_list = attr_list_cache; + s = saved_value(0); + CONTINUE: + while (cur_cmd == relax_cmd || cur_cmd == spacer_cmd) { + get_x_token(); + if (cur_cmd != relax_cmd && cur_cmd != spacer_cmd) + back_input(); + } + if (scan_keyword("attr")) { + scan_register_num(); + i = cur_val; + scan_optional_equals(); + scan_int(); + v = cur_val; + if ((attr_list != null) && (attr_list == attr_list_cache)) { + attr_list = copy_attribute_list(attr_list_cache); + add_node_attr_ref(attr_list); + } + attr_list = do_set_attribute(attr_list, i, v); + goto CONTINUE; + } + if (scan_keyword("dir")) { + scan_direction(); + spec_direction = cur_val; + goto CONTINUE; + } + if (attr_list == attr_list_cache) { + add_node_attr_ref(attr_list); + } + if (scan_keyword("to")) { + spec_code = exactly; + } else if (scan_keyword("spread")) { + spec_code = additional; + } else { + spec_code = additional; + cur_val = 0; + goto FOUND; + } + scan_normal_dimen(); + FOUND: + set_saved_record(0, saved_boxcontext, 0, s); + set_saved_record(1, saved_boxspec, spec_code, cur_val); + if (spec_direction != -1) { + set_saved_record(2, saved_boxdir, spec_direction, text_dir_ptr); + text_dir_ptr = new_dir(spec_direction); + } else { + set_saved_record(2, saved_boxdir, spec_direction, null); + } + set_saved_record(3, saved_boxattr, 0, attr_list); + save_ptr += 4; + new_save_level(c); + scan_left_brace(); + eq_word_define(int_base + body_direction_code, spec_direction); + eq_word_define(int_base + par_direction_code, spec_direction); + eq_word_define(int_base + text_direction_code, spec_direction); + } +*/ + +/* scans a box specification and left brace */ + +void scan_full_spec(group_code c, int spec_direction, int just_pack) +{ + int s; int i; int v; int spec_code; + boolean done = false ; halfword attr_list; if (attr_list_cache == cache_disabled) update_attribute_cache(); attr_list = attr_list_cache; - assert(saved_type(0) == saved_boxcontext); - s = saved_value(0); /* the box context */ + s = saved_value(0); /* the box context */ + do { + get_x_token(); + } while ((cur_cmd == spacer_cmd) || (cur_cmd == relax_cmd)); + if (cur_cmd == left_brace_cmd) { + goto QUICK; + } else { + back_input(); + goto KEYWORDS; + } CONTINUE: while (cur_cmd == relax_cmd || cur_cmd == spacer_cmd) { get_x_token(); - if (cur_cmd != relax_cmd && cur_cmd != spacer_cmd) + if (cur_cmd == left_brace_cmd) { + goto QUICK; + } else if (cur_cmd != relax_cmd && cur_cmd != spacer_cmd) { back_input(); + break; + } } + KEYWORDS: if (scan_keyword("attr")) { scan_register_num(); i = cur_val; @@ -132,7 +240,7 @@ void scan_full_spec(group_code c, int spec_direction) v = cur_val; if ((attr_list != null) && (attr_list == attr_list_cache)) { attr_list = copy_attribute_list(attr_list_cache); - add_node_attr_ref(attr_list); /* will be used once */ + add_node_attr_ref(attr_list); /* will be used once */ } attr_list = do_set_attribute(attr_list, i, v); goto CONTINUE; @@ -155,6 +263,12 @@ void scan_full_spec(group_code c, int spec_direction) goto FOUND; } scan_normal_dimen(); + goto FOUND; + QUICK: + spec_code = additional; + cur_val = 0; + add_node_attr_ref(attr_list); + done = true; FOUND: set_saved_record(0, saved_boxcontext, 0, s); set_saved_record(1, saved_boxspec, spec_code, cur_val); @@ -166,42 +280,43 @@ void scan_full_spec(group_code c, int spec_direction) set_saved_record(2, saved_boxdir, spec_direction, null); } set_saved_record(3, saved_boxattr, 0, attr_list); - save_ptr += 4; + set_saved_record(4, saved_boxpack, 0, just_pack); + save_ptr += 5; new_save_level(c); - scan_left_brace(); + if (! done) { + scan_left_brace(); + } + /* no gain: if (body_direction != spec_direction) etc */ eq_word_define(int_base + body_direction_code, spec_direction); eq_word_define(int_base + par_direction_code, spec_direction); eq_word_define(int_base + text_direction_code, spec_direction); } - @ To figure out the glue setting, |hpack| and |vpack| determine how much -stretchability and shrinkability are present, considering all four orders -of infinity. The highest order of infinity that has a nonzero coefficient -is then used as if no other orders were present. - -For example, suppose that the given list contains six glue nodes with -the respective stretchabilities 3pt, 8fill, 5fil, 6pt, $-3$fil, $-8$fill. -Then the total is essentially 2fil; and if a total additional space of 6pt -is to be achieved by stretching, the actual amounts of stretch will be -0pt, 0pt, 15pt, 0pt, $-9$pt, and 0pt, since only `fil' glue will be -considered. (The `fill' glue is therefore not really stretching infinitely -with respect to `fil'; nobody would actually want that to happen.) - -The arrays |total_stretch| and |total_shrink| are used to determine how much -glue of each kind is present. A global variable |last_badness| is used -to implement \.{\\badness}. +stretchability and shrinkability are present, considering all four orders of +infinity. The highest order of infinity that has a nonzero coefficient is then +used as if no other orders were present. + +For example, suppose that the given list contains six glue nodes with the +respective stretchabilities 3pt, 8fill, 5fil, 6pt, $-3$fil, $-8$fill. Then the +total is essentially 2fil; and if a total additional space of 6pt is to be +achieved by stretching, the actual amounts of stretch will be 0pt, 0pt, 15pt, +0pt, $-9$pt, and 0pt, since only `fil' glue will be considered. (The `fill' glue +is therefore not really stretching infinitely with respect to `fil'; nobody would +actually want that to happen.) + +The arrays |total_stretch| and |total_shrink| are used to determine how much glue +of each kind is present. A global variable |last_badness| is used to implement +\.{\\badness}. @c scaled total_stretch[5]; scaled total_shrink[5]; /* glue found by |hpack| or |vpack| */ int last_badness; /* badness of the most recently packaged box */ - -@ If the global variable |adjust_tail| is non-null, the |hpack| routine -also removes all occurrences of |ins_node|, |mark_node|, and |adjust_node| -items and appends the resulting material onto the list that ends at -location |adjust_tail|. +@ If the global variable |adjust_tail| is non-null, the |hpack| routine also +removes all occurrences of |ins_node|, |mark_node|, and |adjust_node| items and +appends the resulting material onto the list that ends at location |adjust_tail|. @c halfword adjust_tail; /* tail of adjustment list */ @@ -213,7 +328,6 @@ halfword adjust_tail; /* tail of adjustment list */ @c halfword pre_adjust_tail; -int font_expand_ratio; /* current expansion ratio */ halfword last_leftmost_char; halfword last_rightmost_char; @@ -230,18 +344,17 @@ void set_prev_char_p(halfword p) @ @c scaled char_stretch(halfword p) { - scaled dw; - int ef; - internal_font_number f; - int c, m; - f = font(p); - c = character(p); - m = font_max_stretch(f); - ef = get_ef_code(f, c); - if ((m > 0) && (ef > 0)) { - dw = calc_char_width(f, c, m) - char_width(f, c); - if (dw > 0) - return round_xn_over_d(dw, ef, 1000); + internal_font_number f = font(p); + int m = font_max_stretch(f); + if (m > 0) { + int c = character(p); + int ef = get_ef_code(f, c); + if (ef > 0) { + scaled dw = calc_char_width(f, c, m) - char_width(f, c); + if (dw > 0) { + return round_xn_over_d(dw, ef, 1000); + } + } } return 0; } @@ -249,18 +362,17 @@ scaled char_stretch(halfword p) @ @c scaled char_shrink(halfword p) { - scaled dw; - int ef; - internal_font_number f; - int c, m; - f = font(p); - c = character(p); - m = font_max_shrink(f); - ef = get_ef_code(f, c); - if ((m > 0) && (ef > 0)) { - dw = char_width(f, c) - calc_char_width(f, c, -m); - if (dw > 0) - return round_xn_over_d(dw, ef, 1000); + internal_font_number f = font(p); + int m = font_max_shrink(f); + if (m > 0) { + int c = character(p); + int ef = get_ef_code(f, c); + if (ef > 0) { + scaled dw = char_width(f, c) - calc_char_width(f, c, -m); + if (dw > 0) { + return round_xn_over_d(dw, ef, 1000); + } + } } return 0; } @@ -271,19 +383,23 @@ scaled kern_stretch(halfword p) halfword l, r; scaled d; int m; - if ((prev_char_p == null) || (vlink(prev_char_p) != p) - || (vlink(p) == null)) + if ((prev_char_p == null) || (vlink(prev_char_p) != p) || (vlink(p) == null)) return 0; l = prev_char_p; + /* we need a left char */ + if (!is_char_node(l)) + return 0; r = vlink(p); - if (!((is_char_node(l) && is_char_node(r) && - (font(l) == font(r)) && (font_max_stretch(font(l)) != 0)))) + /* and a right char */ + if (!is_char_node(r)) + return 0; + /* and a reason to kern */ + if ((font(l) != font(r)) || (font_max_stretch(font(l)) == 0)) return 0; m = font_max_stretch(font(l)); d = get_kern(font(l), character(l), character(r)); d = round_xn_over_d(d, 1000 + m, 1000); - return round_xn_over_d(d - width(p), - get_ef_code(font(l), character(l)), 1000); + return round_xn_over_d(d - width(p), get_ef_code(font(l), character(l)), 1000); } @ @c @@ -292,29 +408,30 @@ scaled kern_shrink(halfword p) halfword l, r; scaled d; int m; - if ((prev_char_p == null) || (vlink(prev_char_p) != p) - || (vlink(p) == null)) + if ((prev_char_p == null) || (vlink(prev_char_p) != p) || (vlink(p) == null)) return 0; l = prev_char_p; + /* we need a left char */ + if (!is_char_node(l)) + return 0; r = vlink(p); - if (!((is_char_node(l) && is_char_node(r) && - (font(l) == font(r)) && (font_max_shrink(font(l)) != 0)))) + /* and a right char */ + if (!is_char_node(r)) + return 0; + /* and a reason to kern */ + if ((font(l) != font(r)) || (font_max_shrink(font(l)) == 0)) return 0; m = font_max_stretch(font(l)); d = get_kern(font(l), character(l), character(r)); d = round_xn_over_d(d, 1000 - m, 1000); - return round_xn_over_d(width(p) - d, - get_ef_code(font(l), character(l)), 1000); + return round_xn_over_d(width(p) - d, get_ef_code(font(l), character(l)), 1000); } @ @c void do_subst_font(halfword p, int ex_ratio) { - internal_font_number f; - halfword r; - int ef, ex_shrink, ex_stretch; if (type(p) == disc_node) { - r = vlink(pre_break(p)); + halfword r = vlink(pre_break(p)); while (r != null) { if (is_char_node(r)) do_subst_font(r, ex_ratio); @@ -334,22 +451,21 @@ void do_subst_font(halfword p, int ex_ratio) } return; } - if (is_char_node(p)) { - r = p; - } else { + if (! is_char_node(p)) { normal_error("font expansion", "invalid node type"); return; - } - f = font(r); - ef = get_ef_code(f, character(r)); - if (ef == 0) - return; - if ((font_max_stretch(f) > 0) && (ex_ratio > 0)) { - ex_stretch = ext_xn_over_d(ex_ratio * ef, font_max_stretch(f), 1000000); - ex_glyph(p) = fix_expand_value(f, ex_stretch)*1000; - } else if ((font_max_shrink(f) > 0) && (ex_ratio < 0)) { - ex_shrink = ext_xn_over_d(ex_ratio * ef, font_max_shrink(f), 1000000); - ex_glyph(p) = fix_expand_value(f, ex_shrink)*1000; + } else { + internal_font_number f = font(p); + int ef = get_ef_code(f, character(p)); + if (ef == 0) + return; + if ((font_max_stretch(f) > 0) && (ex_ratio > 0)) { + int ex_stretch = ext_xn_over_d(ex_ratio * ef, font_max_stretch(f), 1000000); + ex_glyph(p) = fix_expand_value(f, ex_stretch)*1000; + } else if ((font_max_shrink(f) > 0) && (ex_ratio < 0)) { + int ex_shrink = ext_xn_over_d(ex_ratio * ef, font_max_shrink(f), 1000000); + ex_glyph(p) = fix_expand_value(f, ex_shrink)*1000; + } } } @@ -393,49 +509,52 @@ halfword new_margin_kern(scaled w, halfword p, int side) return k; } - -@ Here is |hpack|, which is place where we do font substituting when -font expansion is being used. +@ Here is |hpack|, which is place where we do font substituting when font +expansion is being used. @c halfword hpack(halfword p, scaled w, int m, int pack_direction) { halfword r; /* the box node that will be returned */ halfword q; /* trails behind |p| */ - scaled h, d, x; /* height, depth, and natural width */ + scaled h = 0; /* height */ + scaled d = 0; /* depth */ + scaled x = 0; /* natural width */ scaled_whd whd; scaled s; /* shift amount */ halfword g; /* points to a glue specification */ int o; /* order of infinity */ - halfword dir_ptr1; /* for managing the direction stack */ + halfword dir_ptr1 = null; /* for managing the direction stack */ int hpack_dir; /* the current direction */ - int disc_level; + int disc_level = 0; halfword pack_interrupt[8]; scaled font_stretch = 0; scaled font_shrink = 0; + int font_expand_ratio = 0; /* current expansion ratio */ scaled k = 0; last_badness = 0; - r = new_node(hlist_node, min_quarterword); + r = new_node(hlist_node, min_quarterword); /* the box node that will be returned */ if (pack_direction == -1) { - box_dir(r) = text_direction; + hpack_dir = text_direction; } else { - box_dir(r) = pack_direction; + hpack_dir = pack_direction; } - hpack_dir = box_dir(r); - dir_ptr1 = null; - push_dir(hpack_dir,dir_ptr1); - q = r + list_offset; + box_dir(r) = hpack_dir; + /* + potential optimimization, save a little but neglectable in practice (not so + many empty boxes are used) + + if (p == null) { + width(r) = w; + return r; + } + */ + push_dir(dir_ptr1,hpack_dir); /* push null */ + q = r + list_offset; /* hm, adding something to a node address? */ vlink(q) = p; if (m == cal_expand_ratio) { - prev_char_p = null; - font_stretch = 0; - font_shrink = 0; - font_expand_ratio = 0; + prev_char_p = null; /* why not always */ } - h = 0; - /* Clear dimensions to zero */ - d = 0; - x = 0; total_stretch[normal] = 0; total_shrink[normal] = 0; total_stretch[sfi] = 0; @@ -447,7 +566,6 @@ halfword hpack(halfword p, scaled w, int m, int pack_direction) total_stretch[filll] = 0; total_shrink[filll] = 0; - disc_level = 0; RESWITCH: while ((p != null) || (disc_level > 0)) { if (p == null) { @@ -455,15 +573,19 @@ halfword hpack(halfword p, scaled w, int m, int pack_direction) p = pack_interrupt[disc_level]; goto RESWITCH; } - /* Examine node |p| in the hlist, taking account of its effect - on the dimensions of the new box, or moving it to the adjustment list; - then advance |p| to the next node */ + /* + Examine node |p| in the hlist, taking account of its effect + on the dimensions of the new box, or moving it to the adjustment list; + then advance |p| to the next node + */ while (is_char_node(p)) { - /* Incorporate character dimensions into the dimensions of - the hbox that will contain~it, then move to the next node */ - /* The following code is part of \TeX's inner loop; i.e., adding another - character of text to the user's input will cause each of these instructions - to be exercised one more time. + /* + Incorporate character dimensions into the dimensions of the hbox + that will contain~it, then move to the next node. + + The following code is part of \TeX's inner loop; i.e., adding + another character of text to the user's input will cause each of + these instructions to be exercised one more time. */ if (m >= cal_expand_ratio) { prev_char_p = p; @@ -484,151 +606,160 @@ halfword hpack(halfword p, scaled w, int m, int pack_direction) } if (p != null) { switch (type(p)) { - case hlist_node: - case vlist_node: - /* Incorporate box dimensions into the dimensions of the hbox that will contain~it */ - /* The code here implicitly uses the fact that running dimensions are - indicated by |null_flag|, which will be ignored in the calculations - because it is a highly negative number. */ - s = shift_amount(p); - whd = pack_width_height_depth(hpack_dir, box_dir(p), p, false); - x += whd.wd; - if (whd.ht - s > h) - h = whd.ht - s; - if (whd.dp + s > d) - d = whd.dp + s; - break; - case rule_node: - case unset_node: - x += width(p); - if (type(p) >= rule_node) - s = 0; - else - s = shift_amount(p); - if (height(p) - s > h) - h = height(p) - s; - if (depth(p) + s > d) - d = depth(p) + s; - break; - case ins_node: - case mark_node: - case adjust_node: - if (adjust_tail != null || pre_adjust_tail != null) { - /* Transfer node |p| to the adjustment list */ + case hlist_node: + case vlist_node: /* - Although node |q| is not necessarily the immediate predecessor of node |p|, - it always points to some node in the list preceding |p|. Thus, we can delete - nodes by moving |q| when necessary. The algorithm takes linear time, and the - extra computation does not intrude on the inner loop unless it is necessary - to make a deletion. - */ - while (vlink(q) != p) - q = vlink(q); - if (type(p) == adjust_node) { - if (adjust_pre(p) != 0) - update_adjust_list(pre_adjust_tail); - else - update_adjust_list(adjust_tail); - p = vlink(p); - adjust_ptr(vlink(q)) = null; - flush_node(vlink(q)); + Incorporate box dimensions into the dimensions of the hbox + that will contain~it + + The code here implicitly uses the fact that running dimensions are + indicated by |null_flag|, which will be ignored in the calculations + because it is a highly negative number. + */ + s = shift_amount(p); + whd = pack_width_height_depth(hpack_dir, box_dir(p), p, false); + x += whd.wd; + if (whd.ht - s > h) + h = whd.ht - s; + if (whd.dp + s > d) + d = whd.dp + s; + break; + /* + case rule_node: + case unset_node: + x += width(p); + if (type(p) >= rule_node) // always + s = 0; + else + s = shift_amount(p); + if (height(p) - s > h) + h = height(p) - s; + if (depth(p) + s > d) + d = depth(p) + s; + break; + */ + case rule_node: + case unset_node: + x += width(p); + if (height(p) > h) + h = height(p); + if (depth(p) > d) + d = depth(p); + break; + /* */ + case glue_node: + /* Incorporate glue into the horizontal totals */ + g = glue_ptr(p); + x += width(g); + o = stretch_order(g); + total_stretch[o] = total_stretch[o] + stretch(g); + o = shrink_order(g); + total_shrink[o] = total_shrink[o] + shrink(g); + if (subtype(p) >= a_leaders) { + g = leader_ptr(p); + if (height(g) > h) + h = height(g); + if (depth(g) > d) + d = depth(g); + } + break; + case kern_node: + if (subtype(p) == normal) { + if (m == cal_expand_ratio) { + font_stretch = font_stretch + kern_stretch(p); + font_shrink = font_shrink + kern_shrink(p); + } else if (m == subst_ex_font) { + if (font_expand_ratio > 0) + k = kern_stretch(p); + else if (font_expand_ratio < 0) + k = kern_shrink(p); + if (k != 0) + width(p) = get_kern(font(prev_char_p), character(prev_char_p), character(vlink(p))); + } + } + x += width(p); + break; + case disc_node: + if (m == subst_ex_font) + do_subst_font(p, font_expand_ratio); + if ((subtype(p) != select_disc) && (vlink(no_break(p)) != null)) { + pack_interrupt[disc_level] = vlink(p); + incr(disc_level); + p = no_break(p); + } + break; + case dir_node: + /* Adjust the dir stack for the |hpack| routine */ + if (dir_dir(p) >= 0) { + hpack_dir = dir_dir(p); + push_dir_node(dir_ptr1,p); } else { - vlink(adjust_tail) = p; - adjust_tail = p; - p = vlink(p); + pop_dir_node(dir_ptr1); + if (dir_ptr1 != null) + hpack_dir = dir_dir(dir_ptr1); } - vlink(q) = p; - p = q; - } - break; - case dir_node: - /* DIR: Adjust the dir stack for the |hpack| routine */ - if (dir_dir(p) >= 0) { - hpack_dir = dir_dir(p); - push_dir_node(p,dir_ptr1); - } else { - pop_dir_node(dir_ptr1); - if (dir_ptr1 != null) - hpack_dir = dir_dir(dir_ptr1); - } - break; - case math_node: - /* begin mathskip code */ - if (glue_ptr(p) == zero_glue) { - x += surround(p); break; - } else { - /* fall through: mathskip */ - } - /* end mathskip code */ - case glue_node: - /* Incorporate glue into the horizontal totals */ - g = glue_ptr(p); - x += width(g); - o = stretch_order(g); - total_stretch[o] = total_stretch[o] + stretch(g); - o = shrink_order(g); - total_shrink[o] = total_shrink[o] + shrink(g); - if (subtype(p) >= a_leaders) { - g = leader_ptr(p); - if (height(g) > h) - h = height(g); - if (depth(g) > d) - d = depth(g); - } - break; - case margin_kern_node: - if (m == cal_expand_ratio) { - int f = font(margin_char(p)); - do_subst_font(margin_char(p), 1000); - if (f != font(margin_char(p))) - font_stretch = - font_stretch - width(p) - char_pw(margin_char(p), - subtype(p)); - font(margin_char(p)) = f; - do_subst_font(margin_char(p), -1000); - if (f != font(margin_char(p))) - font_shrink = - font_shrink - width(p) - char_pw(margin_char(p), - subtype(p)); - font(margin_char(p)) = f; - } else if (m == subst_ex_font) { - do_subst_font(margin_char(p), font_expand_ratio); - width(p) = -char_pw(margin_char(p), subtype(p)); - } - x += width(p); - break; - case kern_node: - if (subtype(p) == normal) { + case math_node: + /* begin mathskip code */ + if (glue_ptr(p) == zero_glue) { + x += surround(p); + break; + } else { + /* fall through: mathskip */ + } + /* end mathskip code */ + case margin_kern_node: if (m == cal_expand_ratio) { - font_stretch = font_stretch + kern_stretch(p); - font_shrink = font_shrink + kern_shrink(p); + int f = font(margin_char(p)); + do_subst_font(margin_char(p), 1000); + if (f != font(margin_char(p))) + font_stretch = font_stretch - width(p) - char_pw(margin_char(p), subtype(p)); + font(margin_char(p)) = f; + do_subst_font(margin_char(p), -1000); + if (f != font(margin_char(p))) + font_shrink = font_shrink - width(p) - char_pw(margin_char(p), subtype(p)); + font(margin_char(p)) = f; } else if (m == subst_ex_font) { - if (font_expand_ratio > 0) - k = kern_stretch(p); - else if (font_expand_ratio < 0) - k = kern_shrink(p); - else - pdfassert(0); - if (k != 0) - width(p) = get_kern(font(prev_char_p), - character(prev_char_p), - character(vlink(p))); + do_subst_font(margin_char(p), font_expand_ratio); + width(p) = -char_pw(margin_char(p), subtype(p)); } - } - x += width(p); - break; - case disc_node: - if (m == subst_ex_font) - do_subst_font(p, font_expand_ratio); - if ((subtype(p) != select_disc) && (vlink(no_break(p)) != null)) { - pack_interrupt[disc_level] = vlink(p); - incr(disc_level); - p = no_break(p); - } - break; - default: - break; + x += width(p); + break; + case ins_node: + case mark_node: + case adjust_node: + /* + Transfer node |p| to the adjustment list. + + Although node |q| is not necessarily the immediate predecessor of node |p|, + it always points to some node in the list preceding |p|. Thus, we can delete + nodes by moving |q| when necessary. The algorithm takes linear time, and the + extra computation does not intrude on the inner loop unless it is necessary + to make a deletion. + */ + if (adjust_tail != null || pre_adjust_tail != null) { + while (vlink(q) != p) + q = vlink(q); + if (type(p) == adjust_node) { + if (adjust_pre(p) != 0) + update_adjust_list(pre_adjust_tail); + else + update_adjust_list(adjust_tail); + p = vlink(p); + adjust_ptr(vlink(q)) = null; + flush_node(vlink(q)); + } else { + vlink(adjust_tail) = p; + adjust_tail = p; + p = vlink(p); + } + vlink(q) = p; + p = q; + } + break; + /* */ + default: + break; } p = vlink(p); } @@ -641,27 +772,32 @@ halfword hpack(halfword p, scaled w, int m, int pack_direction) vlink(pre_adjust_tail) = null; height(r) = h; depth(r) = d; - /* Determine the value of |width(r)| and the appropriate glue setting; - then |return| or |goto common_ending| */ - /* When we get to the present part of the program, |x| is the natural width - of the box being packaged. */ + /* + Determine the value of |width(r)| and the appropriate glue setting; then + |return| or |goto common_ending|. + + When we get to the present part of the program, |x| is the natural width + of the box being packaged. + */ if (m == additional) w = x + w; width(r) = w; - x = w - x; /* now |x| is the excess to be made up */ + x = w - x; + /* now |x| is the excess to be made up */ if (x == 0) { glue_sign(r) = normal; glue_order(r) = normal; set_glue_ratio_zero(glue_set(r)); goto EXIT; } else if (x > 0) { - /* Determine horizontal glue stretch setting, then |return| - or \hbox{|goto common_ending|} */ - - /* If |hpack| is called with |m=cal_expand_ratio| we calculate - |font_expand_ratio| and return without checking for overfull or underfull box. */ - - /* Determine the stretch order */ + /* + Determine horizontal glue stretch setting, then |return| + or \hbox{|goto common_ending|}. + + If |hpack| is called with |m=cal_expand_ratio| we calculate + |font_expand_ratio| and return without checking for overfull or + underfull box. + */ if (total_stretch[filll] != 0) o = filll; else if (total_stretch[fill] != 0) @@ -682,13 +818,16 @@ halfword hpack(halfword p, scaled w, int m, int pack_direction) if (total_stretch[o] != 0) { glue_set(r) = unfloat((double) x / total_stretch[o]); } else { + /* there's nothing to stretch */ glue_sign(r) = normal; - set_glue_ratio_zero(glue_set(r)); /* there's nothing to stretch */ + set_glue_ratio_zero(glue_set(r)); } if (o == normal) { if (list_ptr(r) != null) { - /* Report an underfull hbox and |goto common_ending|, if this box - is sufficiently bad */ + /* + Report an underfull hbox and |goto common_ending|, if this box + is sufficiently bad. + */ last_badness = badness(x, total_stretch[normal]); if (last_badness > int_par(hbadness_code)) { int callback_id = callback_defined(hpack_quality_callback); @@ -720,9 +859,10 @@ halfword hpack(halfword p, scaled w, int m, int pack_direction) } goto EXIT; } else { - /* Determine horizontal glue shrink setting, then |return| - or \hbox{|goto common_ending|} */ - /* Determine the shrink order */ + /* + Determine horizontal glue shrink setting, then |return| + or \hbox{|goto common_ending|}, + */ if (total_shrink[filll] != 0) o = filll; else if (total_shrink[fill] != 0) @@ -743,15 +883,19 @@ halfword hpack(halfword p, scaled w, int m, int pack_direction) if (total_shrink[o] != 0) { glue_set(r) = unfloat((double) (-x) / (double) total_shrink[o]); } else { + /* there's nothing to shrink */ glue_sign(r) = normal; - set_glue_ratio_zero(glue_set(r)); /* there's nothing to shrink */ + set_glue_ratio_zero(glue_set(r)); } if ((total_shrink[o] < -x) && (o == normal) && (list_ptr(r) != null)) { int overshoot = -x - total_shrink[normal] ; last_badness = 1000000; - set_glue_ratio_one(glue_set(r)); /* use the maximum shrinkage */ - /* Report an overfull hbox and |goto common_ending|, if this box - is sufficiently bad */ + /* use the maximum shrinkage */ + set_glue_ratio_one(glue_set(r)); + /* + Report an overfull hbox and |goto common_ending|, if this box + is sufficiently bad. + */ if ((overshoot > dimen_par(hfuzz_code)) || (int_par(hbadness_code) < 100)) { int callback_id = callback_defined(hpack_quality_callback); halfword rule = null; @@ -778,7 +922,10 @@ halfword hpack(halfword p, scaled w, int m, int pack_direction) } } else if (o == normal) { if (list_ptr(r) != null) { - /* Report a tight hbox and |goto common_ending|, if this box is sufficiently bad */ + /* + Report a tight hbox and |goto common_ending|, if this box is + sufficiently bad. + */ last_badness = badness(-x, total_shrink[normal]); if (last_badness > int_par(hbadness_code)) { int callback_id = callback_defined(hpack_quality_callback); @@ -804,7 +951,10 @@ halfword hpack(halfword p, scaled w, int m, int pack_direction) } COMMON_ENDING: - /* Finish issuing a diagnostic message for an overfull or underfull hbox */ + /* + Finish issuing a diagnostic message for an overfull or underfull + hbox. + */ if (output_active) { tprint(") has occurred while \\output is active"); } else { @@ -829,7 +979,6 @@ halfword hpack(halfword p, scaled w, int m, int pack_direction) begin_diagnostic(); show_box(r); end_diagnostic(true); - EXIT: if ((m == cal_expand_ratio) && (font_expand_ratio != 0)) { font_expand_ratio = fix_int(font_expand_ratio, -1000, 1000); @@ -844,16 +993,40 @@ halfword hpack(halfword p, scaled w, int m, int pack_direction) } @ @c -halfword filtered_hpack(halfword p, halfword qt, scaled w, int m, int grp, - int pac) +/* +halfword filtered_hpack(halfword p, halfword qt, scaled w, int m, int grp, int pac) { halfword q; new_hyphenation(p, qt); - (void) new_ligkern(p, qt); /* don't care about the tail in this case */ + (void) new_ligkern(p, qt); // we don't care about the tail in this case q = vlink(p); q = lua_hpack_filter(q, w, m, grp, pac); return hpack(q, w, m, pac); } +*/ + +halfword filtered_hpack(halfword p, halfword qt, scaled w, int m, int grp, int pac, int just_pack) +{ + halfword q; + if (just_pack) { + q = vlink(p); + } else if (type(p) == temp_node && vlink(p) == null) { + q = vlink(p); + /* + q = new_node(hlist_node, min_quarterword); + box_dir(q) = (pac == -1) ? text_direction : pac; + width(q) = w; + return q; + */ + } else { + new_hyphenation(p, qt); + (void) new_ligkern(p, qt); /* we don't care about the tail in this case */ + q = vlink(p); + /* maybe here: alink(p) = null */ + q = lua_hpack_filter(q, w, m, grp, pac); /* ignores empty anyway */ /* maybe also pass tail */ + } + return hpack(q, w, m, pac); +} @ here is a function to calculate the natural whd of a (horizontal) node list @@ -861,10 +1034,10 @@ halfword filtered_hpack(halfword p, halfword qt, scaled w, int m, int grp, scaled_whd natural_sizes(halfword p, halfword pp, glue_ratio g_mult, int g_sign, int g_order, int pack_direction) { - scaled s; /* shift amount */ - halfword g; /* points to a glue specification */ + scaled s; /* shift amount */ + halfword g; /* points to a glue specification */ int hpack_dir; - scaled_whd xx; /* for recursion */ + scaled_whd xx; /* for recursion */ scaled_whd whd, siz = { 0, 0, 0 }; if (pack_direction == -1) { hpack_dir = text_direction; @@ -883,76 +1056,82 @@ scaled_whd natural_sizes(halfword p, halfword pp, glue_ratio g_mult, } if (p != pp && p != null) { switch (type(p)) { - case hlist_node: - case vlist_node: - s = shift_amount(p); - whd = pack_width_height_depth(hpack_dir, box_dir(p), p, false); - siz.wd += whd.wd; - if (whd.ht - s > siz.ht) - siz.ht = whd.ht - s; - if (whd.dp + s > siz.dp) - siz.dp = whd.dp + s; - break; - case rule_node: - case unset_node: - siz.wd += width(p); - if (type(p) >= rule_node) - s = 0; - else + case hlist_node: + case vlist_node: s = shift_amount(p); - if (height(p) - s > siz.ht) - siz.ht = height(p) - s; - if (depth(p) + s > siz.dp) - siz.dp = depth(p) + s; - break; - case math_node: - /* begin mathskip code */ - if (glue_ptr(p) == zero_glue) { - siz.wd += surround(p); + whd = pack_width_height_depth(hpack_dir, box_dir(p), p, false); + siz.wd += whd.wd; + if (whd.ht - s > siz.ht) + siz.ht = whd.ht - s; + if (whd.dp + s > siz.dp) + siz.dp = whd.dp + s; break; - } else { - /* fall through: mathskip */ - } - /* end mathskip code */ - case glue_node: - g = glue_ptr(p); - siz.wd += width(g); - if (g_sign != normal) { - if (g_sign == stretching) { - if (stretch_order(g) == g_order) { - siz.wd += - float_round(float_cast(g_mult) * - float_cast(stretch(g))); + /* + case rule_node: + case unset_node: + siz.wd += width(p); + if (type(p) >= rule_node) // always true + s = 0; + else + s = shift_amount(p); + if (height(p) - s > siz.ht) + siz.ht = height(p) - s; + if (depth(p) + s > siz.dp) + siz.dp = depth(p) + s; + break; + */ + case rule_node: + case unset_node: + siz.wd += width(p); + if (height(p) > siz.ht) + siz.ht = height(p); + if (depth(p) > siz.dp) + siz.dp = depth(p); + break; + /* */ + case math_node: + /* begin mathskip code */ + if (glue_ptr(p) == zero_glue) { + siz.wd += surround(p); + break; + } else { + /* fall through: mathskip */ + } + /* end mathskip code */ + case glue_node: + g = glue_ptr(p); + siz.wd += width(g); + if (g_sign != normal) { + if (g_sign == stretching) { + if (stretch_order(g) == g_order) { + siz.wd += float_round(float_cast(g_mult) * float_cast(stretch(g))); + } + } else if (shrink_order(g) == g_order) { + siz.wd -= float_round(float_cast(g_mult) * float_cast(shrink(g))); } - } else if (shrink_order(g) == g_order) { - siz.wd -= - float_round(float_cast(g_mult) * - float_cast(shrink(g))); } - } - if (subtype(p) >= a_leaders) { - g = leader_ptr(p); - if (height(g) > siz.ht) - siz.ht = height(g); - if (depth(g) > siz.dp) - siz.dp = depth(g); - } - break; - case margin_kern_node: - case kern_node: - siz.wd += width(p); - break; - case disc_node: - xx = natural_sizes(no_break(p), null, g_mult, g_sign, g_order, - hpack_dir); - siz.wd += xx.wd; - if (xx.ht > siz.ht) - siz.ht = xx.ht; - if (xx.dp > siz.dp) - siz.dp = xx.dp; - break; - default: - break; + if (subtype(p) >= a_leaders) { + g = leader_ptr(p); + if (height(g) > siz.ht) + siz.ht = height(g); + if (depth(g) > siz.dp) + siz.dp = depth(g); + } + break; + case margin_kern_node: + case kern_node: + siz.wd += width(p); + break; + case disc_node: + xx = natural_sizes(no_break(p), null, g_mult, g_sign, g_order, hpack_dir); + siz.wd += xx.wd; + if (xx.ht > siz.ht) + siz.ht = xx.ht; + if (xx.dp > siz.dp) + siz.dp = xx.dp; + break; + default: + break; } p = vlink(p); } @@ -961,29 +1140,31 @@ scaled_whd natural_sizes(halfword p, halfword pp, glue_ratio g_mult, return siz; } +@ In order to provide a decent indication of where an overfull or underfull box +originated, we use a global variable |pack_begin_line| that is set nonzero only +when |hpack| is being called by the paragraph builder or the alignment finishing +routine. -@ In order to provide a decent indication of where an overfull or underfull -box originated, we use a global variable |pack_begin_line| that is -set nonzero only when |hpack| is being called by the paragraph builder -or the alignment finishing routine. +@ The source file line where the current paragraph or alignment began; a negative +value denotes alignment: @c -int pack_begin_line; /* source file line where the current paragraph - or alignment began; a negative value denotes alignment */ - +int pack_begin_line; -@ The |vpack| subroutine is actually a special case of a slightly more -general routine called |vpackage|, which has four parameters. The fourth -parameter, which is |max_dimen| in the case of |vpack|, specifies the -maximum depth of the page box that is constructed. The depth is first -computed by the normal rules; if it exceeds this limit, the reference -point is simply moved down until the limiting depth is attained. +@ The |vpack| subroutine is actually a special case of a slightly more general +routine called |vpackage|, which has four parameters. The fourth parameter, which +is |max_dimen| in the case of |vpack|, specifies the maximum depth of the page +box that is constructed. The depth is first computed by the normal rules; if it +exceeds this limit, the reference point is simply moved down until the limiting +depth is attained. @c halfword vpackage(halfword p, scaled h, int m, scaled l, int pack_direction) { halfword r; /* the box node that will be returned */ - scaled w, d, x; /* width, depth, and natural height */ + scaled w = 0; /* width */ + scaled d = 0; /* depth */ + scaled x = 0; /* natural height */ scaled_whd whd; scaled s; /* shift amount */ halfword g; /* points to a glue specification */ @@ -998,10 +1179,6 @@ halfword vpackage(halfword p, scaled h, int m, scaled l, int pack_direction) subtype(r) = min_quarterword; shift_amount(r) = 0; list_ptr(r) = p; - w = 0; - /* Clear dimensions to zero */ - d = 0; - x = 0; total_stretch[normal] = 0; total_shrink[normal] = 0; total_stretch[sfi] = 0; @@ -1014,16 +1191,21 @@ halfword vpackage(halfword p, scaled h, int m, scaled l, int pack_direction) total_shrink[filll] = 0; while (p != null) { - /* Examine node |p| in the vlist, taking account of its effect - on the dimensions of the new box; then advance |p| to the next node */ + /* + Examine node |p| in the vlist, taking account of its effect + on the dimensions of the new box; then advance |p| to the next + node. + */ if (is_char_node(p)) { confusion("vpack"); } else { switch (type(p)) { case hlist_node: case vlist_node: - /* Incorporate box dimensions into the dimensions of - the vbox that will contain~it */ + /* + Incorporate box dimensions into the dimensions of + the vbox that will contain it. + */ s = shift_amount(p); whd = pack_width_height_depth(box_dir(r), box_dir(p), p, false); if (whd.wd + s > w) @@ -1031,17 +1213,27 @@ halfword vpackage(halfword p, scaled h, int m, scaled l, int pack_direction) x += d + whd.ht; d = whd.dp; break; + /* case rule_node: case unset_node: x += d + height(p); d = depth(p); - if (type(p) >= rule_node) + if (type(p) >= rule_node) // always s = 0; else s = shift_amount(p); if (width(p) + s > w) w = width(p) + s; break; + */ + case rule_node: + case unset_node: + x += d + height(p); + d = depth(p); + if (width(p) > w) + w = width(p); + break; + /* */ case glue_node: /* Incorporate glue into the vertical totals */ x += d; @@ -1075,23 +1267,28 @@ halfword vpackage(halfword p, scaled h, int m, scaled l, int pack_direction) } else { depth(r) = d; } - /* Determine the value of |height(r)| and the appropriate glue setting; - then |return| or |goto common_ending| */ - /* When we get to the present part of the program, |x| is the natural height - of the box being packaged. */ + /* + Determine the value of |height(r)| and the appropriate glue setting; + then |return| or |goto common_ending|. + + When we get to the present part of the program, |x| is the natural + height of the box being packaged. + */ if (m == additional) h = x + h; height(r) = h; - x = h - x; /* now |x| is the excess to be made up */ + x = h - x; + /* now |x| is the excess to be made up */ if (x == 0) { glue_sign(r) = normal; glue_order(r) = normal; set_glue_ratio_zero(glue_set(r)); return r; } else if (x > 0) { - /* Determine vertical glue stretch setting, then |return| - or \hbox{|goto common_ending|} */ - /* Determine the stretch order */ + /* + Determine vertical glue stretch setting, then |return| + or \hbox{|goto common_ending|}. + */ if (total_stretch[filll] != 0) o = filll; else if (total_stretch[fill] != 0) @@ -1113,8 +1310,10 @@ halfword vpackage(halfword p, scaled h, int m, scaled l, int pack_direction) } if (o == normal) { if (list_ptr(r) != null) { - /* Report an underfull vbox and |goto common_ending|, if this box - is sufficiently bad */ + /* + Report an underfull vbox and |goto common_ending|, if this box + is sufficiently bad. + */ last_badness = badness(x, total_stretch[normal]); if (last_badness > int_par(vbadness_code)) { int callback_id = callback_defined(vpack_quality_callback); @@ -1141,9 +1340,10 @@ halfword vpackage(halfword p, scaled h, int m, scaled l, int pack_direction) return r; } else { - /* Determine vertical glue shrink setting, then |return| - or \hbox{|goto common_ending|} */ - /* Determine the shrink order */ + /* + Determine vertical glue shrink setting, then |return| + or \hbox{|goto common_ending|}. + */ if (total_shrink[filll] != 0) o = filll; else if (total_shrink[fill] != 0) @@ -1160,14 +1360,19 @@ halfword vpackage(halfword p, scaled h, int m, scaled l, int pack_direction) if (total_shrink[o] != 0) { glue_set(r) = unfloat((double) (-x) / total_shrink[o]); } else { + /* there's nothing to shrink */ glue_sign(r) = normal; - set_glue_ratio_zero(glue_set(r)); /* there's nothing to shrink */ + set_glue_ratio_zero(glue_set(r)); } if ((total_shrink[o] < -x) && (o == normal) && (list_ptr(r) != null)) { int overshoot = -x - total_shrink[normal]; last_badness = 1000000; - set_glue_ratio_one(glue_set(r)); /* use the maximum shrinkage */ - /* Report an overfull vbox and |goto common_ending|, if this box is sufficiently bad */ + /* use the maximum shrinkage */ + set_glue_ratio_one(glue_set(r)); + /* + Report an overfull vbox and |goto common_ending|, if this box + is sufficiently bad. + */ if ((overshoot > dimen_par(vfuzz_code)) || (int_par(vbadness_code) < 100)) { int callback_id = callback_defined(vpack_quality_callback); if (callback_id > 0) { @@ -1183,7 +1388,10 @@ halfword vpackage(halfword p, scaled h, int m, scaled l, int pack_direction) } } else if (o == normal) { if (list_ptr(r) != null) { - /* Report a tight vbox and |goto common_ending|, if this box is sufficiently bad */ + /* + Report a tight vbox and |goto common_ending|, if this box is + sufficiently bad. + */ last_badness = badness(-x, total_shrink[normal]); if (last_badness > int_par(vbadness_code)) { int callback_id = callback_defined(vpack_quality_callback); @@ -1207,7 +1415,8 @@ halfword vpackage(halfword p, scaled h, int m, scaled l, int pack_direction) if (output_active) { tprint(") has occurred while \\output is active"); } else { - if (pack_begin_line != 0) { /* it's actually negative */ + if (pack_begin_line != 0) { + /* it's actually negative */ tprint(") in alignment at lines "); print_int(abs(pack_begin_line)); tprint("--"); @@ -1225,12 +1434,12 @@ halfword vpackage(halfword p, scaled h, int m, scaled l, int pack_direction) } @ @c -halfword filtered_vpackage(halfword p, scaled h, int m, scaled l, int grp, - int pack_direction) +halfword filtered_vpackage(halfword p, scaled h, int m, scaled l, int grp, int pack_direction, int just_pack) { - halfword q; - q = p; - q = lua_vpack_filter(q, h, m, l, grp, pack_direction); + halfword q = p; + if (!just_pack) + /* if (q != null) */ + q = lua_vpack_filter(q, h, m, l, grp, pack_direction); return vpackage(q, h, m, l, pack_direction); } @@ -1249,42 +1458,37 @@ void finish_vcenter(void) @ @c void package(int c) { - scaled h; /* height of box */ - halfword p; /* first node in a box */ - scaled d; /* max depth */ - int grp; - halfword saved0, saved2, saved3; - grp = cur_group; - d = box_max_depth; + halfword saved0, saved2, saved3, saved4; + int grp = cur_group; + scaled d = box_max_depth; /* max depth */ unsave(); - save_ptr -= 4; + save_ptr -= 5; saved0 = saved_value(0); saved2 = saved_value(2); saved3 = saved_value(3); + saved4 = saved_value(4); if (cur_list.mode_field == -hmode) { - cur_box = filtered_hpack(cur_list.head_field, - cur_list.tail_field, saved_value(1), - saved_level(1), grp, saved_level(2)); + cur_box = filtered_hpack(cur_list.head_field, cur_list.tail_field, + saved_value(1), saved_level(1), grp, saved_level(2), saved4); subtype(cur_box) = hbox_list; } else { cur_box = filtered_vpackage(vlink(cur_list.head_field), - saved_value(1), saved_level(1), d, grp, - saved_level(2)); + saved_value(1), saved_level(1), d, grp, saved_level(2), saved4); if (c == vtop_code) { - /* Readjust the height and depth of |cur_box|, for \.{\\vtop} */ - /* The height of a `\.{\\vtop}' box is inherited from the first item on its list, - if that item is an |hlist_node|, |vlist_node|, or |rule_node|; otherwise - the \.{\\vtop} height is zero. - */ - - h = 0; - p = list_ptr(cur_box); - if (p != null) - if (type(p) <= rule_node) - h = height(p); + /* + Read just the height and depth of |cur_box|, for \.{\\vtop}. The + height of a `\.{\\vtop}' box is inherited from the first item on + its list, if that item is an |hlist_node|, |vlist_node|, or + |rule_node|; otherwise the \.{\\vtop} height is zero. + */ + scaled h = 0; + halfword p = list_ptr(cur_box); + if ((p != null) && (type(p) <= rule_node)) { + /* hlist, vlist, rule */ + h = height(p); + } depth(cur_box) = depth(cur_box) - h + height(cur_box); height(cur_box) = h; - } } if (saved2 != null) { @@ -1298,10 +1502,8 @@ void package(int c) box_end(saved0); } - - -@ When a box is being appended to the current vertical list, the -baselineskip calculation is handled by the |append_to_vlist| routine. +@ When a box is being appended to the current vertical list, the baselineskip +calculation is handled by the |append_to_vlist| routine. @c void append_to_vlist(halfword b, int location) @@ -1332,7 +1534,8 @@ void append_to_vlist(halfword b, int location) p = new_param_glue(line_skip_code); } else { p = new_skip_param(baseline_skip_code); - width(temp_ptr) = d; /* |temp_ptr=glue_ptr(p)| */ + /* |temp_ptr=glue_ptr(p)| */ + width(temp_ptr) = d; } couple_nodes(cur_list.tail_field, p); cur_list.tail_field = p; @@ -1347,31 +1550,29 @@ void append_to_vlist(halfword b, int location) } } - -@ When |saving_vdiscards| is positive then the glue, kern, and penalty -nodes removed by the page builder or by \.{\\vsplit} from the top of a -vertical list are saved in special lists instead of being discarded. +@ When |saving_vdiscards| is positive then the glue, kern, and penalty nodes +removed by the page builder or by \.{\\vsplit} from the top of a vertical list +are saved in special lists instead of being discarded. @c -#define tail_page_disc disc_ptr[copy_code] /* last item removed by page builder */ -#define page_disc disc_ptr[last_box_code] /* first item removed by page builder */ -#define split_disc disc_ptr[vsplit_code] /* first item removed by \.{\\vsplit} */ +#define tail_page_disc disc_ptr[copy_code] /* last item removed by page builder */ +#define page_disc disc_ptr[last_box_code] /* first item removed by page builder */ +#define split_disc disc_ptr[vsplit_code] /* first item removed by \.{\\vsplit} */ -halfword disc_ptr[(vsplit_code + 1)]; /* list pointers */ +halfword disc_ptr[(vsplit_code + 1)]; /* list pointers */ +@ The |vsplit| procedure, which implements \TeX's \.{\\vsplit} operation, is +considerably simpler than |line_break| because it doesn't have to worry about +hyphenation, and because its mission is to discover a single break instead of an +optimum sequence of breakpoints. But before we get into the details of |vsplit|, +we need to consider a few more basic things. -@ The |vsplit| procedure, which implements \TeX's \.{\\vsplit} operation, -is considerably simpler than |line_break| because it doesn't have to -worry about hyphenation, and because its mission is to discover a single -break instead of an optimum sequence of breakpoints. But before we get -into the details of |vsplit|, we need to consider a few more basic things. - -A subroutine called |prune_page_top| takes a pointer to a vlist and -returns a pointer to a modified vlist in which all glue, kern, and penalty nodes -have been deleted before the first box or rule node. However, the first -box or rule is actually preceded by a newly created glue node designed so that -the topmost baseline will be at distance |split_top_skip| from the top, -whenever this is possible without backspacing. +A subroutine called |prune_page_top| takes a pointer to a vlist and returns a +pointer to a modified vlist in which all glue, kern, and penalty nodes have been +deleted before the first box or rule node. However, the first box or rule is +actually preceded by a newly created glue node designed so that the topmost +baseline will be at distance |split_top_skip| from the top, whenever this is +possible without backspacing. When the second argument |s| is |false| the deleted nodes are destroyed, otherwise they are collected in a list starting at |split_disc|. @@ -1379,11 +1580,10 @@ otherwise they are collected in a list starting at |split_disc|. @c halfword prune_page_top(halfword p, boolean s) { - halfword prev_p; /* lags one step behind |p| */ - halfword q, r; /* temporary variables for list manipulation */ - prev_p = temp_head; + halfword q; + halfword prev_p = temp_head; /* lags one step behind |p| */ + halfword r = null; vlink(temp_head) = p; - r = null; while (p != null) { switch (type(p)) { case hlist_node: @@ -1392,7 +1592,8 @@ halfword prune_page_top(halfword p, boolean s) /* Insert glue for |split_top_skip| and set~|p:=null| */ q = new_skip_param(split_top_skip_code); vlink(prev_p) = q; - vlink(q) = p; /* now |temp_ptr=glue_ptr(q)| */ + vlink(q) = p; + /* now |temp_ptr=glue_ptr(q)| */ if (width(temp_ptr) > height(p)) width(temp_ptr) = width(temp_ptr) - height(p); else @@ -1431,52 +1632,49 @@ halfword prune_page_top(halfword p, boolean s) return vlink(temp_head); } - -@ The next subroutine finds the best place to break a given vertical list -so as to obtain a box of height~|h|, with maximum depth~|d|. -A pointer to the beginning of the vertical list is given, -and a pointer to the optimum breakpoint is returned. The list is effectively -followed by a forced break, i.e., a penalty node with the |eject_penalty|; -if the best break occurs at this artificial node, the value |null| is returned. +@ The next subroutine finds the best place to break a given vertical list so as +to obtain a box of height~|h|, with maximum depth~|d|. A pointer to the beginning +of the vertical list is given, and a pointer to the optimum breakpoint is +returned. The list is effectively followed by a forced break, i.e., a penalty +node with the |eject_penalty|; if the best break occurs at this artificial node, +the value |null| is returned. @c -scaled active_height[10]; /* distance from first active node to~|cur_p| */ - +scaled active_height[10]; /* distance from first active node to~|cur_p| */ -@ An array of six |scaled| distances is used to keep track of the height -from the beginning of the list to the current place, just as in |line_break|. -In fact, we use one of the same arrays, only changing its name to reflect -its new significance. +@ An array of six |scaled| distances is used to keep track of the height from the +beginning of the list to the current place, just as in |line_break|. In fact, we +use one of the same arrays, only changing its name to reflect its new +significance. @c #define do_all_six(A) A(1);A(2);A(3);A(4);A(5);A(6);A(7) #define set_height_zero(A) active_height[A]=0 /* initialize the height to zero */ +@ A global variable |best_height_plus_depth| will be set to the natural size of +the box that corresponds to the optimum breakpoint found by |vert_break|. (This +value is used by the insertion-splitting algorithm of the page builder.) -@ A global variable |best_height_plus_depth| will be set to the natural size -of the box that corresponds to the optimum breakpoint found by |vert_break|. -(This value is used by the insertion-splitting algorithm of the page builder.) +@ height of the best box, without stretching or shrinking @c -scaled best_height_plus_depth; /* height of the best box, without stretching or shrinking */ +scaled best_height_plus_depth; + +/* finds optimum page break */ halfword vert_break(halfword p, scaled h, scaled d) -{ /* finds optimum page break */ - halfword prev_p; /* if |p| is a glue node, |type(prev_p)| determines - whether |p| is a legal breakpoint */ +{ + halfword prev_p = p; /* if |p| is a glue node, |type(prev_p)| determines whether |p| is a + legal breakpoint, an initial glue node is not a legal breakpoint */ halfword q, r; /* glue specifications */ - int pi; /* penalty value */ + int pi = 0; /* penalty value */ int b; /* badness at a trial breakpoint */ - int least_cost; /* the smallest badness plus penalties found so far */ - halfword best_place; /* the most recent break that leads to |least_cost| */ - scaled prev_dp; /* depth of previous box in the list */ int t; /* |type| of the node following a kern */ - prev_p = p; /* an initial glue node is not a legal breakpoint */ + int least_cost; /* the smallest badness plus penalties found so far */ + halfword best_place = null; /* the most recent break that leads to |least_cost| */ + scaled prev_dp = 0; /* depth of previous box in the list */ least_cost = awful_bad; do_all_six(set_height_zero); - prev_dp = 0; - best_place = null; - pi = 0; while (1) { /* If node |p| is a legal breakpoint, check if this break is the best known, and |goto done| if |p| is null or @@ -1596,13 +1794,11 @@ halfword vert_break(halfword p, scaled h, scaled d) } cur_height = cur_height + prev_dp + width(q); prev_dp = 0; - NOT_FOUND: if (prev_dp > d) { cur_height = cur_height + prev_dp - d; prev_dp = d; } - prev_p = p; p = vlink(prev_p); } @@ -1610,30 +1806,31 @@ halfword vert_break(halfword p, scaled h, scaled d) return best_place; } +@ Now we are ready to consider |vsplit| itself. Most of its work is accomplished +by the two subroutines that we have just considered. -@ Now we are ready to consider |vsplit| itself. Most of -its work is accomplished by the two subroutines that we have just considered. +Given the number of a vlist box |n|, and given a desired page height |h|, the +|vsplit| function finds the best initial segment of the vlist and returns a box +for a page of height~|h|. The remainder of the vlist, if any, replaces the +original box, after removing glue and penalties and adjusting for +|split_top_skip|. Mark nodes in the split-off box are used to set the values of +|split_first_mark| and |split_bot_mark|; we use the fact that +|split_first_mark(x)=null| if and only if |split_bot_mark(x)=null|. -Given the number of a vlist box |n|, and given a desired page height |h|, -the |vsplit| function finds the best initial segment of the vlist and -returns a box for a page of height~|h|. The remainder of the vlist, if -any, replaces the original box, after removing glue and penalties and -adjusting for |split_top_skip|. Mark nodes in the split-off box are used to -set the values of |split_first_mark| and |split_bot_mark|; we use the -fact that |split_first_mark(x)=null| if and only if |split_bot_mark(x)=null|. - -The original box becomes ``void'' if and only if it has been entirely -extracted. The extracted box is ``void'' if and only if the original -box was void (or if it was, erroneously, an hlist box). +The original box becomes ``void'' if and only if it has been entirely extracted. +The extracted box is ``void'' if and only if the original box was void (or if it +was, erroneously, an hlist box). @c +/* extracts a page of height |h| from box |n| */ + halfword vsplit(halfword n, scaled h) -{ /* extracts a page of height |h| from box |n| */ - halfword v; /* the box to be split */ - int vdir; /* the direction of the box to be split */ - halfword p; /* runs through the vlist */ - halfword q; /* points to where the break occurs */ - halfword i; /* for traversing marks lists */ +{ + halfword v; /* the box to be split */ + int vdir; /* the direction of the box to be split */ + halfword p; /* runs through the vlist */ + halfword q; /* points to where the break occurs */ + halfword i; /* for traversing marks lists */ v = box(n); vdir = box_dir(v); flush_node_list(split_disc); @@ -1653,13 +1850,13 @@ halfword vsplit(halfword n, scaled h) error(); return null; } - q = vert_break(list_ptr(v), h, dimen_par(split_max_depth_code)); - /* Look at all the marks in nodes before the break, and set the final - link to |null| at the break */ - /* It's possible that the box begins with a penalty node that is the - ``best'' break, so we must be careful to handle this special case correctly. */ - + /* + Look at all the marks in nodes before the break, and set the final + link to |null| at the break. It's possible that the box begins with + a penalty node that is the ``best'' break, so we must be careful to + handle this special case correctly. + */ p = list_ptr(v); if (p == q) { list_ptr(v) = null; @@ -1668,11 +1865,9 @@ halfword vsplit(halfword n, scaled h) if (type(p) == mark_node) { if (split_first_mark(mark_class(p)) == null) { set_split_first_mark(mark_class(p), mark_ptr(p)); - set_split_bot_mark(mark_class(p), - split_first_mark(mark_class(p))); + set_split_bot_mark(mark_class(p), split_first_mark(mark_class(p))); set_token_ref_count(split_first_mark(mark_class(p)), - token_ref_count(split_first_mark - (mark_class(p))) + 2); + token_ref_count(split_first_mark(mark_class(p))) + 2); } else { delete_token_ref(split_bot_mark(mark_class(p))); set_split_bot_mark(mark_class(p), mark_ptr(p)); @@ -1686,137 +1881,161 @@ halfword vsplit(halfword n, scaled h) p = vlink(p); } } - q = prune_page_top(q, int_par(saving_vdiscards_code) > 0); p = list_ptr(v); list_ptr(v) = null; flush_node(v); - if (q == null) - box(n) = null; /* the |eq_level| of the box stays the same */ - else + if (q == null) { + /* the |eq_level| of the box stays the same */ + box(n) = null; + } else { box(n) = - filtered_vpackage(q, 0, additional, dimen_par(max_depth_code), - split_keep_group, vdir); - return filtered_vpackage(p, h, exactly, - dimen_par(split_max_depth_code), split_off_group, - vdir); + filtered_vpackage(q, 0, additional, dimen_par(max_depth_code), split_keep_group, vdir, 0); + } + return filtered_vpackage(p, h, exactly, dimen_par(split_max_depth_code), split_off_group, vdir, 0); } - -@ Now that we can see what eventually happens to boxes, we can consider -the first steps in their creation. The |begin_box| routine is called when -|box_context| is a context specification, |cur_chr| specifies the type of -box desired, and |cur_cmd=make_box|. +@ Now that we can see what eventually happens to boxes, we can consider the first +steps in their creation. The |begin_box| routine is called when |box_context| is +a context specification, |cur_chr| specifies the type of box desired, and +|cur_cmd=make_box|. @c void begin_box(int box_context) { - halfword q; /* run through the current list */ - halfword k; /* 0 or |vmode| or |hmode| */ - int n; /* a box number */ + halfword q; /* run through the current list */ + halfword k; /* 0 or |vmode| or |hmode| */ + int n; /* a box number */ int spec_direction = -1; + int just_pack = 0; switch (cur_chr) { - case box_code: - scan_register_num(); - cur_box = box(cur_val); - box(cur_val) = null; /* the box becomes void, at the same level */ - break; - case copy_code: - scan_register_num(); - cur_box = copy_node_list(box(cur_val)); - break; - case last_box_code: - /* If the current list ends with a box node, delete it from - the list and make |cur_box| point to it; otherwise set |cur_box:=null| */ - cur_box = null; - if (abs(cur_list.mode_field) == mmode) { - you_cant(); - help1("Sorry; this \\lastbox will be void."); - error(); - } else if ((cur_list.mode_field == vmode) - && (cur_list.head_field == cur_list.tail_field)) { - you_cant(); - help2("Sorry...I usually can't take things from the current page.", - "This \\lastbox will therefore be void."); - error(); - } else { - if (cur_list.head_field != cur_list.tail_field) { /* todo: new code, needs testing */ - if ((type(cur_list.tail_field) == hlist_node) - || (type(cur_list.tail_field) == vlist_node)) { - /* Remove the last box ... */ - q = alink(cur_list.tail_field); - if (q == null || vlink(q) != cur_list.tail_field) { - q = cur_list.head_field; - while (vlink(q) != cur_list.tail_field) - q = vlink(q); + case box_code: + scan_register_num(); + cur_box = box(cur_val); + /* the box becomes void, at the same level */ + box(cur_val) = null; + break; + case copy_code: + scan_register_num(); + cur_box = copy_node_list(box(cur_val)); + break; + case last_box_code: + /* + If the current list ends with a box node, delete it from + the list and make |cur_box| point to it; otherwise set + |cur_box:=null|. + */ + cur_box = null; + if (abs(cur_list.mode_field) == mmode) { + you_cant(); + help1("Sorry; this \\lastbox will be void."); + error(); + } else if ((cur_list.mode_field == vmode) && (cur_list.head_field == cur_list.tail_field)) { + you_cant(); + help2("Sorry...I usually can't take things from the current page.", + "This \\lastbox will therefore be void."); + error(); + } else { + if (cur_list.head_field != cur_list.tail_field) { + /* todo: new code, needs testing */ + + /* maybe: ((type(cur_list.tail_field) == hlist_node) < rule_node) */ + + if ((type(cur_list.tail_field) == hlist_node) || (type(cur_list.tail_field) == vlist_node)) { + /* Remove the last box ... */ + q = alink(cur_list.tail_field); + if (q == null || vlink(q) != cur_list.tail_field) { + q = cur_list.head_field; + while (vlink(q) != cur_list.tail_field) + q = vlink(q); + } + uncouple_node(cur_list.tail_field); + cur_box = cur_list.tail_field; + shift_amount(cur_box) = 0; + cur_list.tail_field = q; + vlink(cur_list.tail_field) = null; } - uncouple_node(cur_list.tail_field); - cur_box = cur_list.tail_field; - shift_amount(cur_box) = 0; - cur_list.tail_field = q; - vlink(cur_list.tail_field) = null; } } - } - break; - case vsplit_code: - /* Split off part of a vertical box, make |cur_box| point to it */ - /* Here we deal with things like `\.{\\vsplit 13 to 100pt}'. */ - scan_register_num(); - n = cur_val; - if (!scan_keyword("to")) { - print_err("Missing `to' inserted"); - help2("I'm working on `\\vsplit<box number> to <dimen>';", - "will look for the <dimen> next."); - error(); - } - scan_normal_dimen(); - cur_box = vsplit(n, cur_val); - break; - default: - /* Initiate the construction of an hbox or vbox, then |return| */ - /* Here is where we enter restricted horizontal mode or internal vertical - mode, in order to make a box. */ - k = cur_chr - vtop_code; - set_saved_record(0, saved_boxcontext, 0, box_context); - switch (abs(cur_list.mode_field)) { - case vmode: - spec_direction = body_direction; - break; - case hmode: - spec_direction = text_direction; break; - case mmode: - spec_direction = math_direction; + case vsplit_code: + /* + Split off part of a vertical box, make |cur_box| point to it. Here we + deal with things like `\.{\\vsplit 13 to 100pt}'. + */ + scan_register_num(); + n = cur_val; + if (!scan_keyword("to")) { + print_err("Missing `to' inserted"); + help2("I'm working on `\\vsplit<box number> to <dimen>';", + "will look for the <dimen> next."); + error(); + } + scan_normal_dimen(); + cur_box = vsplit(n, cur_val); break; - } - if (k == hmode) { - if ((box_context < box_flag) && (abs(cur_list.mode_field) == vmode)) - scan_full_spec(adjusted_hbox_group, spec_direction); - else - scan_full_spec(hbox_group, spec_direction); - } else { + default: + /* + Initiate the construction of an hbox or vbox, then |return|. Here is + where we enter restricted horizontal mode or internal vertical mode, + in order to make a box. + */ + switch (cur_chr) { + case tpack_code: + cur_chr = vtop_code; + just_pack = 1; + break; + case vpack_code: + cur_chr = vtop_code + vmode; + just_pack = 1; + break; + case hpack_code: + cur_chr = vtop_code + hmode; + just_pack = 1; + break; + } + /* */ + k = cur_chr - vtop_code; + set_saved_record(0, saved_boxcontext, 0, box_context); + switch (abs(cur_list.mode_field)) { + case vmode: + spec_direction = body_direction; + break; + case hmode: + spec_direction = text_direction; + break; + case mmode: + spec_direction = math_direction; + break; + } + if (k == hmode) { + if ((box_context < box_flag) && (abs(cur_list.mode_field) == vmode)) + scan_full_spec(adjusted_hbox_group, spec_direction,just_pack); + else + scan_full_spec(hbox_group, spec_direction,just_pack); + } else { + if (k == vmode) { + scan_full_spec(vbox_group, spec_direction,just_pack); + } else { + scan_full_spec(vtop_group, spec_direction,just_pack); + k = vmode; + } + normal_paragraph(); + } + push_nest(); + cur_list.mode_field = -k; if (k == vmode) { - scan_full_spec(vbox_group, spec_direction); + prev_depth = ignore_depth; + if (every_vbox != null) + begin_token_list(every_vbox, every_vbox_text); } else { - scan_full_spec(vtop_group, spec_direction); - k = vmode; + space_factor = 1000; + if (every_hbox != null) + begin_token_list(every_hbox, every_hbox_text); } - normal_paragraph(); - } - push_nest(); - cur_list.mode_field = -k; - if (k == vmode) { - prev_depth = ignore_depth; - if (every_vbox != null) - begin_token_list(every_vbox, every_vbox_text); - } else { - space_factor = 1000; - if (every_hbox != null) - begin_token_list(every_hbox, every_hbox_text); - } - return; - break; + return; + break; } - box_end(box_context); /* in simple cases, we use the box immediately */ + /* in simple cases, we use the box immediately */ + box_end(box_context); } |