diff options
Diffstat (limited to 'systems/tex-extensions/clasen/tight2.patch')
-rw-r--r-- | systems/tex-extensions/clasen/tight2.patch | 1461 |
1 files changed, 1461 insertions, 0 deletions
diff --git a/systems/tex-extensions/clasen/tight2.patch b/systems/tex-extensions/clasen/tight2.patch new file mode 100644 index 0000000000..d9a15af1f9 --- /dev/null +++ b/systems/tex-extensions/clasen/tight2.patch @@ -0,0 +1,1461 @@ +*** tex.web.orig Mon Sep 14 23:03:05 1998 +--- tex.web Sun Sep 20 10:00:49 1998 +*************** +*** 184,190 **** + known as `\TeX' [cf.~Stanford Computer Science report CS1027, + November 1984]. + +! @d banner=='This is TeX, Version 3.14159' {printed when \TeX\ starts} + + @ Different \PASCAL s have slightly different conventions, and the present + @!@:PASCAL H}{\ph@> +--- 184,190 ---- + known as `\TeX' [cf.~Stanford Computer Science report CS1027, + November 1984]. + +! @d banner=='This is *not* TeX, Version 3.14159' {printed when \TeX\ starts} + + @ Different \PASCAL s have slightly different conventions, and the present + @!@:PASCAL H}{\ph@> +*************** +*** 4951,4957 **** + @d right_hyphen_min_code=52 {minimum right hyphenation fragment size} + @d holding_inserts_code=53 {do not remove insertion nodes from \.{\\box255}} + @d error_context_lines_code=54 {maximum intermediate line pairs shown} +! @d int_pars=55 {total number of integer parameters} + @d count_base=int_base+int_pars {256 user \.{\\count} registers} + @d del_code_base=count_base+256 {256 delimiter code mappings} + @d dimen_base=del_code_base+256 {beginning of region 6} +--- 4951,4961 ---- + @d right_hyphen_min_code=52 {minimum right hyphenation fragment size} + @d holding_inserts_code=53 {do not remove insertion nodes from \.{\\box255}} + @d error_context_lines_code=54 {maximum intermediate line pairs shown} +! @d glue_overshrink_code=55 { 1000 times the amount by which to overshrink} +! @d extra_adj_demerits_code=56 { additional demerits for jumping > 2 } +! @d font_demerits_code=57 +! @d extra_font_demerits_code=58 +! @d int_pars=59 {total number of integer parameters} + @d count_base=int_base+int_pars {256 user \.{\\count} registers} + @d del_code_base=count_base+256 {256 delimiter code mappings} + @d dimen_base=del_code_base+256 {beginning of region 6} +*************** +*** 5014,5019 **** +--- 5018,5028 ---- + @d right_hyphen_min==int_par(right_hyphen_min_code) + @d holding_inserts==int_par(holding_inserts_code) + @d error_context_lines==int_par(error_context_lines_code) ++ @d glue_overshrink==int_par(glue_overshrink_code) ++ @d extra_adj_demerits==int_par(extra_adj_demerits_code) ++ @d font_demerits==int_par(font_demerits_code) ++ @d extra_font_demerits==int_par(extra_font_demerits_code) ++ + + @<Assign the values |depth_threshold:=show_box_depth|...@>= + depth_threshold:=show_box_depth; +*************** +*** 5078,5083 **** +--- 5087,5096 ---- + right_hyphen_min_code:print_esc("righthyphenmin"); + holding_inserts_code:print_esc("holdinginserts"); + error_context_lines_code:print_esc("errorcontextlines"); ++ glue_overshrink_code:print_esc("glueovershrink"); ++ extra_adj_demerits_code:print_esc("extraadjdemerits"); ++ font_demerits_code:print_esc("fontdemerits"); ++ extra_font_demerits_code:print_esc("extrafontdemerits"); + othercases print("[unknown integer parameter!]") + endcases; + end; +*************** +*** 5198,5203 **** +--- 5211,5224 ---- + @!@:holding_inserts_}{\.{\\holdinginserts} primitive@> + primitive("errorcontextlines",assign_int,int_base+error_context_lines_code);@/ + @!@:error_context_lines_}{\.{\\errorcontextlines} primitive@> ++ primitive("glueovershrink",assign_int,int_base+glue_overshrink_code);@/ ++ @!@:glue_overshrink_}{\.{\\glueovershrink} primitive@> ++ primitive("extraadjdemerits",assign_int,int_base+extra_adj_demerits_code);@/ ++ @!@:extra_adj_demerits_}{\.{\\extraadjdemerits} primitive@> ++ primitive("fontdemerits",assign_int,int_base+font_demerits_code);@/ ++ @!@:font_demerits_}{\.{\\fontdemerits} primitive@> ++ primitive("extrafontdemerits",assign_int,int_base+extra_font_demerits_code);@/ ++ @!@:extra_font_demerits_}{\.{\\extrafontdemerits} primitive@> + + @ @<Cases of |print_cmd_chr|...@>= + assign_int: if chr_code<count_base then print_param(chr_code-int_base) +*************** +*** 5658,5663 **** +--- 5679,5686 ---- + @!@:expand_after_}{\.{\\expandafter} primitive@> + primitive("font",def_font,0);@/ + @!@:font_}{\.{\\font} primitive@> ++ primitive("fontvariant",def_font,1);@/ ++ @!@:font_variant_}{\.{\\fontvariant} primitive@> + primitive("fontdimen",assign_font_dimen,0);@/ + @!@:font_dimen_}{\.{\\fontdimen} primitive@> + primitive("halign",halign,0);@/ +*************** +*** 5732,5738 **** + break_penalty: print_esc("penalty"); + char_num: print_esc("char"); + cs_name: print_esc("csname"); +! def_font: print_esc("font"); + delim_num: print_esc("delimiter"); + divide: print_esc("divide"); + end_cs_name: print_esc("endcsname"); +--- 5755,5761 ---- + break_penalty: print_esc("penalty"); + char_num: print_esc("char"); + cs_name: print_esc("csname"); +! def_font: if chr_code=0 then print_esc("font") else print_esc("fontvariant"); + delim_num: print_esc("delimiter"); + divide: print_esc("divide"); + end_cs_name: print_esc("endcsname"); +*************** +*** 8376,8384 **** + end; + scanned_result(equiv(m))(tok_val); + end +! else begin back_input; scan_font_ident; + scanned_result(font_id_base+cur_val)(ident_val); +! end + + @ Users refer to `\.{\\the\\spacefactor}' only in horizontal + mode, and to `\.{\\the\\prevdepth}' only in vertical mode; so we put the +--- 8399,8411 ---- + end; + scanned_result(equiv(m))(tok_val); + end +! else if m=0 then begin +! back_input; scan_font_ident; + scanned_result(font_id_base+cur_val)(ident_val); +! end else begin +! print_err("Improper "); print_cmd_chr(def_font, m); +! error; +! end + + @ Users refer to `\.{\\the\\spacefactor}' only in horizontal + mode, and to `\.{\\the\\prevdepth}' only in vertical mode; so we put the +*************** +*** 10672,10677 **** +--- 10699,10706 ---- + @<Types...@>= + @!internal_font_number=font_base..font_max; {|font| in a |char_node|} + @!font_index=0..font_mem_size; {index into |font_info|} ++ @!four_fonts = packed array[0..3] of quarterword; ++ {a version of |four_quarters| with addressable quarters} + + @ Here now is the (rather formidable) array of font arrays. + +*************** +*** 10709,10714 **** +--- 10738,10745 ---- + {right boundary character, |non_char| if there is none} + @!font_false_bchar:array[internal_font_number] of min_quarterword..non_char; + {|font_bchar| if it doesn't exist in the font, otherwise |non_char|} ++ @!font_variants:array[internal_font_number] of four_fonts; ++ {we use four variants per font} + + @ Besides the arrays just enumerated, we have directory arrays that make it + easy to get at the individual entries in |font_info|. For example, the +*************** +*** 10760,10765 **** +--- 10791,10797 ---- + font_glue[null_font]:=null; font_params[null_font]:=7; + param_base[null_font]:=-1; + for k:=0 to 6 do font_info[k].sc:=0; ++ for k:=0 to 3 do font_variants[null_font][k]:=null_font; + + @ @<Put each...@>= + primitive("nullfont",set_font,null_font); +*************** +*** 12854,12865 **** + + @< Glob...@>= + @!adjust_tail:pointer; {tail of adjustment list} + + @ @<Set init...@>=adjust_tail:=null; last_badness:=0; + + @ Here now is |hpack|, which contains few if any surprises. + +! @p function hpack(@!p:pointer;@!w:scaled;@!m:small_number):pointer; + label reswitch, common_ending, exit; + var r:pointer; {the box node that will be returned} + @!q:pointer; {trails behind |p|} +--- 12886,12905 ---- + + @< Glob...@>= + @!adjust_tail:pointer; {tail of adjustment list} ++ @!line_font_variant:small_number; {used for communication between ++ |line_break| and |hpack|} + + @ @<Set init...@>=adjust_tail:=null; last_badness:=0; + + @ Here now is |hpack|, which contains few if any surprises. + +! @p function effective_glue_overshrink : integer; +! begin +! if glue_overshrink<1000 then effective_glue_overshrink:=1000 +! else effective_glue_overshrink:=glue_overshrink; +! end; +! +! function hpack(@!p:pointer;@!w:scaled;@!m:small_number):pointer; + label reswitch, common_ending, exit; + var r:pointer; {the box node that will be returned} + @!q:pointer; {trails behind |p|} +*************** +*** 12870,12875 **** +--- 12910,12916 ---- + @!f:internal_font_number; {the font in a |char_node|} + @!i:four_quarters; {font information about a |char_node|} + @!hd:eight_bits; {height and depth indices for a character} ++ @!max_shrink:scaled; + begin last_badness:=0; r:=get_node(box_node_size); type(r):=hlist_node; + subtype(r):=min_quarterword; shift_amount(r):=0; + q:=r+list_offset; link(q):=p;@/ +*************** +*** 12937,12945 **** + character of text to the user's input will cause each of these instructions + to be exercised one more time. + @^inner loop@> + + @<Incorporate character dimensions into the dimensions of the hbox...@>= +! begin f:=font(p); i:=char_info(f)(character(p)); hd:=height_depth(i); + x:=x+char_width(f)(i);@/ + s:=char_height(f)(hd);@+if s>h then h:=s; + s:=char_depth(f)(hd);@+if s>d then d:=s; +--- 12978,12998 ---- + character of text to the user's input will cause each of these instructions + to be exercised one more time. + @^inner loop@> ++ This is also the place where the proper font variants are selected. ++ ++ @d very_condensed_font=0 ++ @d condensed_font=1 ++ @d normal_font=2 ++ @d extended_font=3 ++ @d very_extended_font=4 + + @<Incorporate character dimensions into the dimensions of the hbox...@>= +! begin +! if line_font_variant<normal_font then +! font(p):=font_variants[font(p)][line_font_variant] +! else if line_font_variant>normal_font then +! font(p):=font_variants[font(p)][line_font_variant-1]; +! f:=font(p); i:=char_info(f)(character(p)); hd:=height_depth(i); + x:=x+char_width(f)(i);@/ + s:=char_height(f)(hd);@+if s>h then h:=s; + s:=char_depth(f)(hd);@+if s>d then d:=s; +*************** +*** 13036,13049 **** + pack_begin_line:=0; + + @ @<Finish issuing a diagnostic message for an overfull or underfull hbox@>= +! if output_active then print(") has occurred while \output is active") + else begin if pack_begin_line<>0 then +! begin if pack_begin_line>0 then print(") in paragraph at lines ") +! else print(") in alignment at lines "); + print_int(abs(pack_begin_line)); + print("--"); + end +! else print(") detected at line "); + print_int(line); + end; + print_ln;@/ +--- 13089,13109 ---- + pack_begin_line:=0; + + @ @<Finish issuing a diagnostic message for an overfull or underfull hbox@>= +! case line_font_variant of +! very_condensed_font: print(") (very condensed)"); +! condensed_font: print(") (condensed)"); +! normal_font: print(") (normal)"); +! extended_font: print(") (extended)"); +! very_extended_font: print(") (very extended)"); +! endcases; +! if output_active then print(" has occurred while \output is active") + else begin if pack_begin_line<>0 then +! begin if pack_begin_line>0 then print(" in paragraph at lines ") +! else print(" in alignment at lines "); + print_int(abs(pack_begin_line)); + print("--"); + end +! else print(" detected at line "); + print_int(line); + end; + print_ln;@/ +*************** +*** 13058,13066 **** + else begin glue_sign(r):=normal; + set_glue_ratio_zero(glue_set(r)); {there's nothing to shrink} + end; +! if (total_shrink[o]<-x)and(o=normal)and(list_ptr(r)<>null) then + begin 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@>; + end +--- 13118,13127 ---- + else begin glue_sign(r):=normal; + set_glue_ratio_zero(glue_set(r)); {there's nothing to shrink} + end; +! max_shrink:=xn_over_d(total_shrink[o],effective_glue_overshrink,1000); +! if (max_shrink<-x)and(o=normal)and(list_ptr(r)<>null) then + begin last_badness:=1000000; +! glue_set(r):=unfloat(effective_glue_overshrink/1000); + @<Report an overfull hbox and |goto common_ending|, if this box + is sufficiently bad@>; + end +*************** +*** 13077,13091 **** + else o:=normal + + @ @<Report an overfull hbox and |goto common_ending|, if...@>= +! if (-x-total_shrink[normal]>hfuzz)or(hbadness<100) then +! begin if (overfull_rule>0)and(-x-total_shrink[normal]>hfuzz) then + begin while link(q)<>null do q:=link(q); + link(q):=new_rule; + width(link(q)):=overfull_rule; + end; + print_ln; print_nl("Overfull \hbox ("); + @.Overfull \\hbox...@> +! print_scaled(-x-total_shrink[normal]); print("pt too wide"); + goto common_ending; + end + +--- 13138,13152 ---- + else o:=normal + + @ @<Report an overfull hbox and |goto common_ending|, if...@>= +! if (-x-max_shrink>hfuzz)or(hbadness<100) then +! begin if (overfull_rule>0)and(-x-max_shrink>hfuzz) then + begin while link(q)<>null do q:=link(q); + link(q):=new_rule; + width(link(q)):=overfull_rule; + end; + print_ln; print_nl("Overfull \hbox ("); + @.Overfull \\hbox...@> +! print_scaled(-x-max_shrink); print("pt too wide"); + goto common_ending; + end + +*************** +*** 16038,16056 **** + @ When looking for optimal line breaks, \TeX\ creates a ``break node'' for + each break that is {\sl feasible}, in the sense that there is a way to end + a line at the given place without requiring any line to stretch more than +! a given tolerance. A break node is characterized by three things: the position + of the break (which is a pointer to a |glue_node|, |math_node|, |penalty_node|, + or |disc_node|); the ordinal number of the line that will follow this +! breakpoint; and the fitness classification of the line that has just +! ended, i.e., |tight_fit|, |decent_fit|, |loose_fit|, or |very_loose_fit|. +! +! @d tight_fit=3 {fitness classification for lines shrinking 0.5 to 1.0 of their + shrinkability} +! @d loose_fit=1 {fitness classification for lines stretching 0.5 to 1.0 of their + stretchability} +! @d very_loose_fit=0 {fitness classification for lines stretching more than + their stretchability} +! @d decent_fit=2 {fitness classification for all other lines} + + @ The algorithm essentially determines the best possible way to achieve + each feasible combination of position, line, and fitness. Thus, it answers +--- 16099,16124 ---- + @ When looking for optimal line breaks, \TeX\ creates a ``break node'' for + each break that is {\sl feasible}, in the sense that there is a way to end + a line at the given place without requiring any line to stretch more than +! a given tolerance. A break node is characterized by four things: the position + of the break (which is a pointer to a |glue_node|, |math_node|, |penalty_node|, + or |disc_node|); the ordinal number of the line that will follow this +! breakpoint, the fitness classification of the line that has just +! ended, i.e., |very_tight_fit|, |tight_fit|, |decent_fit|, +! |loose_fit|, |very_loose_fit|, or |extremely_loose_fit|, and the font variant +! to be used, |very_condensed_font|, |condensed_font|, |normal_font|, +! |extended_font| or |very_extended_font|. +! +! @d very_tight_fit=5 {fitness classification for lines shrinking more than their +! shrinkability} +! @d tight_fit=4 {fitness classification for lines shrinking 0.5 to 1.0 of their + shrinkability} +! @d decent_fit=3 {fitness classification for all other lines} +! @d loose_fit=2 {fitness classification for lines stretching 0.5 to 1.0 of their + stretchability} +! @d very_loose_fit=1 {fitness classification for lines stretching 1.0 to 2.0 of + their stretchability} +! @d extremely_loose_fit=0 {fitness classification for lines stretching more +! than 2.0 of their stretchability} + + @ The algorithm essentially determines the best possible way to achieve + each feasible combination of position, line, and fitness. Thus, it answers +*************** +*** 16063,16069 **** + + An ``active node'' and a ``passive node'' are created in |mem| for each + feasible breakpoint that needs to be considered. Active nodes are three +! words long and passive nodes are two words long. We need active nodes only + for breakpoints near the place in the paragraph that is currently being + examined, so they are recycled within a comparatively short time after + they are created. +--- 16131,16137 ---- + + An ``active node'' and a ``passive node'' are created in |mem| for each + feasible breakpoint that needs to be considered. Active nodes are three +! words long and passive nodes are too. We need active nodes only + for breakpoints near the place in the paragraph that is currently being + examined, so they are recycled within a comparatively short time after + they are created. +*************** +*** 16095,16101 **** + to each other. + + @d active_node_size=3 {number of words in active nodes} +! @d fitness==subtype {|very_loose_fit..tight_fit| on final line for this break} + @d break_node==rlink {pointer to the corresponding passive node} + @d line_number==llink {line that begins at this breakpoint} + @d total_demerits(#)==mem[#+2].int {the quantity that \TeX\ minimizes} +--- 16163,16170 ---- + to each other. + + @d active_node_size=3 {number of words in active nodes} +! @d fitness==subtype {|extremely_loose_fit..very_tight_fit| on final line for this +! break} + @d break_node==rlink {pointer to the corresponding passive node} + @d line_number==llink {line that begins at this breakpoint} + @d total_demerits(#)==mem[#+2].int {the quantity that \TeX\ minimizes} +*************** +*** 16107,16113 **** + type(last_active):=hyphenated; line_number(last_active):=max_halfword; + subtype(last_active):=0; {the |subtype| is never examined by the algorithm} + +! @ The passive node for a given breakpoint contains only four fields: + + \yskip\hang|link| points to the passive node created just before this one, + if any, otherwise it is |null|. +--- 16176,16182 ---- + type(last_active):=hyphenated; line_number(last_active):=max_halfword; + subtype(last_active):=0; {the |subtype| is never examined by the algorithm} + +! @ The passive node for a given breakpoint contains only five fields: + + \yskip\hang|link| points to the passive node created just before this one, + if any, otherwise it is |null|. +*************** +*** 16122,16137 **** + one created during the current pass. (This field is used only when + printing out detailed statistics about the line-breaking calculations.) + + \yskip\noindent + There is a global variable called |passive| that points to the most + recently created passive node. Another global variable, |printed_node|, + is used to help print out the paragraph when detailed information about + the line-breaking computation is being displayed. + +! @d passive_node_size=2 {number of words in passive nodes} + @d cur_break==rlink {in passive node, points to position of this breakpoint} + @d prev_break==llink {points to passive node that should precede this one} + @d serial==info {serial number for symbolic identification} + + @<Glob...@>= + @!passive:pointer; {most recent node on passive list} +--- 16191,16211 ---- + one created during the current pass. (This field is used only when + printing out detailed statistics about the line-breaking calculations.) + ++ \yskip\hang|condensedness| is the font variant to be used. We store this ++ information in passive nodes rather than active ones, since it has to ++ stay around till the packaging, when all active nodes are long gone. ++ + \yskip\noindent + There is a global variable called |passive| that points to the most + recently created passive node. Another global variable, |printed_node|, + is used to help print out the paragraph when detailed information about + the line-breaking computation is being displayed. + +! @d passive_node_size=3 {number of words in passive nodes} + @d cur_break==rlink {in passive node, points to position of this breakpoint} + @d prev_break==llink {points to passive node that should precede this one} + @d serial==info {serial number for symbolic identification} ++ @d condensedness(#)==mem[#+2].int + + @<Glob...@>= + @!passive:pointer; {most recent node on passive list} +*************** +*** 16153,16183 **** + pt, fil, fill, and filll appear in |mem[q+2..q+5].sc|; and the shrink difference + appears in |mem[q+6].sc|. The |subtype| field of a delta node is not used. + +! @d delta_node_size=7 {number of words in a delta node} + @d delta_node=2 {|type| field in a delta node} + +! @ As the algorithm runs, it maintains a set of six delta-like registers + for the length of the line following the first active breakpoint to the + current position in the given hlist. When it makes a pass through the +! active list, it also maintains a similar set of six registers for the + length following the active breakpoint of current interest. A third set + holds the length of an empty line (namely, the sum of \.{\\leftskip} and + \.{\\rightskip}); and a fourth set is used to create new delta nodes. + + When we pass a delta node we want to do operations like + $$\hbox{\ignorespaces|for +! k:=1 to 6 do cur_active_width[k]:=cur_active_width[k]+mem[q+k].sc|};$$ and we +! want to do this without the overhead of |for| loops. The |do_all_six| +! macro makes such six-tuples convenient. + + @d do_all_six(#)==#(1);#(2);#(3);#(4);#(5);#(6) + + @<Glo...@>= +! @!active_width:array[1..6] of scaled; + {distance from first active node to~|cur_p|} +! @!cur_active_width:array[1..6] of scaled; {distance from current active node} +! @!background:array[1..6] of scaled; {length of an ``empty'' line} +! @!break_width:array[1..6] of scaled; {length being computed after current break} + + @ Let's state the principles of the delta nodes more precisely and concisely, + so that the following programs will be less obscure. For each legal +--- 16227,16261 ---- + pt, fil, fill, and filll appear in |mem[q+2..q+5].sc|; and the shrink difference + appears in |mem[q+6].sc|. The |subtype| field of a delta node is not used. + +! Delta nodes have four additional fields keeping track of the +! difference in natural width for the font variants. +! +! @d delta_node_size=11 {number of words in a delta node} + @d delta_node=2 {|type| field in a delta node} + +! @ As the algorithm runs, it maintains a set of ten delta-like registers + for the length of the line following the first active breakpoint to the + current position in the given hlist. When it makes a pass through the +! active list, it also maintains a similar set of ten registers for the + length following the active breakpoint of current interest. A third set + holds the length of an empty line (namely, the sum of \.{\\leftskip} and + \.{\\rightskip}); and a fourth set is used to create new delta nodes. + + When we pass a delta node we want to do operations like + $$\hbox{\ignorespaces|for +! k:=1 to 10 do cur_active_width[k]:=cur_active_width[k]+mem[q+k].sc|};$$ and we +! want to do this without the overhead of |for| loops. The |do_all_ten| +! macro makes such ten-tuples convenient. |do_all_six| is also needed. + + @d do_all_six(#)==#(1);#(2);#(3);#(4);#(5);#(6) ++ @d do_all_ten(#)==#(1);#(2);#(3);#(4);#(5);#(6);#(7);#(8);#(9);#(10) + + @<Glo...@>= +! @!active_width:array[1..10] of scaled; + {distance from first active node to~|cur_p|} +! @!cur_active_width:array[1..10] of scaled; {distance from current active node} +! @!background:array[1..10] of scaled; {length of an ``empty'' line} +! @!break_width:array[1..10] of scaled; {length being computed after current break} + + @ Let's state the principles of the delta nodes more precisely and concisely, + so that the following programs will be less obscure. For each legal +*************** +*** 16258,16263 **** +--- 16336,16345 ---- + background[2+stretch_order(q)]:=stretch(q);@/ + background[2+stretch_order(r)]:=@|background[2+stretch_order(r)]+stretch(r);@/ + background[6]:=shrink(q)+shrink(r); ++ background[7]:=0; ++ background[8]:=0; ++ background[9]:=0; ++ background[10]:=0; + + @ A pointer variable |cur_p| runs through the given horizontal list as we look + for breakpoints. This variable is global, since it is used both by |line_break| +*************** +*** 16316,16322 **** + @<Other local variables for |try_break|@>@; + begin @<Make sure that |pi| is in the proper range@>; + no_break_yet:=true; prev_r:=active; old_l:=0; +! do_all_six(copy_to_cur_active); + loop@+ begin continue: r:=link(prev_r); + @<If node |r| is of type |delta_node|, update |cur_active_width|, + set |prev_r| and |prev_prev_r|, then |goto continue|@>; +--- 16398,16404 ---- + @<Other local variables for |try_break|@>@; + begin @<Make sure that |pi| is in the proper range@>; + no_break_yet:=true; prev_r:=active; old_l:=0; +! do_all_ten(copy_to_cur_active); + loop@+ begin continue: r:=link(prev_r); + @<If node |r| is of type |delta_node|, update |cur_active_width|, + set |prev_r| and |prev_prev_r|, then |goto continue|@>; +*************** +*** 16341,16348 **** + @!f:internal_font_number; {used in character width calculation} + @!l:halfword; {line number of current active node} + @!node_r_stays_active:boolean; {should node |r| remain in the active list?} + @!line_width:scaled; {the current line will be justified to this width} +! @!fit_class:very_loose_fit..tight_fit; {possible fitness class of test line} + @!b:halfword; {badness of test line} + @!d:integer; {demerits of test line} + @!artificial_demerits:boolean; {has |d| been forced to zero?} +--- 16423,16435 ---- + @!f:internal_font_number; {used in character width calculation} + @!l:halfword; {line number of current active node} + @!node_r_stays_active:boolean; {should node |r| remain in the active list?} ++ @!do_not_consider:boolean; + @!line_width:scaled; {the current line will be justified to this width} +! @!fit_class:extremely_loose_fit..very_tight_fit; {possible fitness class of +! test line} +! @!condensed_class,prev_cc:very_condensed_font..very_extended_font; +! @!cw:scaled; +! @!j:small_number; + @!b:halfword; {badness of test line} + @!d:integer; {demerits of test line} + @!artificial_demerits:boolean; {has |d| been forced to zero?} +*************** +*** 16362,16368 **** + @<If node |r|...@>= + @^inner loop@> + if type(r)=delta_node then +! begin do_all_six(update_width); + prev_prev_r:=prev_r; prev_r:=r; goto continue; + end + +--- 16449,16455 ---- + @<If node |r|...@>= + @^inner loop@> + if type(r)=delta_node then +! begin do_all_ten(update_width); + prev_prev_r:=prev_r; prev_r:=r; goto continue; + end + +*************** +*** 16381,16401 **** + @d awful_bad==@'7777777777 {more than a billion demerits} + + @<Global...@>= +! @!minimal_demerits:array[very_loose_fit..tight_fit] of integer; {best total +! demerits known for current line class and position, given the fitness} + @!minimum_demerits:integer; {best total demerits known for current line class + and position} +! @!best_place:array[very_loose_fit..tight_fit] of pointer; {how to achieve + |minimal_demerits|} +! @!best_pl_line:array[very_loose_fit..tight_fit] of halfword; {corresponding + line number} + + @ @<Get ready to start...@>= + minimum_demerits:=awful_bad; +! minimal_demerits[tight_fit]:=awful_bad; +! minimal_demerits[decent_fit]:=awful_bad; +! minimal_demerits[loose_fit]:=awful_bad; +! minimal_demerits[very_loose_fit]:=awful_bad; + + @ The first part of the following code is part of \TeX's inner loop, so + we don't want to waste any time. The current active node, namely node |r|, +--- 16468,16490 ---- + @d awful_bad==@'7777777777 {more than a billion demerits} + + @<Global...@>= +! @!minimal_demerits:array[extremely_loose_fit..very_tight_fit, +! very_condensed_font..very_extended_font] of integer; {best total +! demerits known for current line class and position, given the fitness and condensedness} + @!minimum_demerits:integer; {best total demerits known for current line class + and position} +! @!best_place:array[extremely_loose_fit..very_tight_fit, +! very_condensed_font..very_extended_font] of pointer; {how to achieve + |minimal_demerits|} +! @!best_pl_line:array[extremely_loose_fit..very_tight_fit, +! very_condensed_font..very_extended_font] of halfword; {corresponding + line number} + + @ @<Get ready to start...@>= + minimum_demerits:=awful_bad; +! for l:=extremely_loose_fit to very_tight_fit do +! for j:=very_condensed_font to very_extended_font do +! minimal_demerits[l][j]:=awful_bad; + + @ The first part of the following code is part of \TeX's inner loop, so + we don't want to waste any time. The current active node, namely node |r|, +*************** +*** 16429,16439 **** + if abs(adj_demerits)>=awful_bad-minimum_demerits then + minimum_demerits:=awful_bad-1 + else minimum_demerits:=minimum_demerits+abs(adj_demerits); +! for fit_class:=very_loose_fit to tight_fit do +! begin if minimal_demerits[fit_class]<=minimum_demerits then + @<Insert a new active node + from |best_place[fit_class]| to |cur_p|@>; +! minimal_demerits[fit_class]:=awful_bad; + end; + minimum_demerits:=awful_bad; + @<Insert a delta node to prepare for the next active node@>; +--- 16518,16529 ---- + if abs(adj_demerits)>=awful_bad-minimum_demerits then + minimum_demerits:=awful_bad-1 + else minimum_demerits:=minimum_demerits+abs(adj_demerits); +! for fit_class:=extremely_loose_fit to very_tight_fit do +! for condensed_class:=very_condensed_font to very_extended_font do +! begin if minimal_demerits[fit_class][condensed_class]<=minimum_demerits then + @<Insert a new active node + from |best_place[fit_class]| to |cur_p|@>; +! minimal_demerits[fit_class][condensed_class]:=awful_bad; + end; + minimum_demerits:=awful_bad; + @<Insert a delta node to prepare for the next active node@>; +*************** +*** 16461,16467 **** + @d set_break_width_to_background(#)==break_width[#]:=background[#] + + @<Compute the values of |break...@>= +! begin no_break_yet:=false; do_all_six(set_break_width_to_background); + s:=cur_p; + if break_type>unhyphenated then if cur_p<>null then + @<Compute the discretionary |break_width| values@>; +--- 16551,16557 ---- + @d set_break_width_to_background(#)==break_width[#]:=background[#] + + @<Compute the values of |break...@>= +! begin no_break_yet:=false; do_all_ten(set_break_width_to_background); + s:=cur_p; + if break_type>unhyphenated then if cur_p<>null then + @<Compute the discretionary |break_width| values@>; +*************** +*** 16524,16536 **** + @<Subtract the width of node |v|...@>= + if is_char_node(v) then + begin f:=font(v); +! break_width[1]:=break_width[1]-char_width(f)(char_info(f)(character(v))); +! end +! else case type(v) of + ligature_node: begin f:=font(lig_char(v));@/ +! break_width[1]:=@|break_width[1]- +! char_width(f)(char_info(f)(character(lig_char(v)))); +! end; + hlist_node,vlist_node,rule_node,kern_node: + break_width[1]:=break_width[1]-width(v); + othercases confusion("disc1") +--- 16614,16638 ---- + @<Subtract the width of node |v|...@>= + if is_char_node(v) then + begin f:=font(v); +! cw:=char_width(f)(char_info(f)(character(v))); +! break_width[1]:=break_width[1]-cw; +! for j:=0 to 3 do +! break_width[7+j]:=break_width[7+j] +! -(char_width(font_variants[f][j]) +! (char_info(font_variants[f][j]) +! (character(v))) +! -cw); +! end else case type(v) of + ligature_node: begin f:=font(lig_char(v));@/ +! cw:=char_width(f)(char_info(f)(character(lig_char(v)))); +! break_width[1]:=@|break_width[1]-cw; +! for j:=0 to 3 do +! break_width[7+j]:=break_width[7+j] +! -(char_width(font_variants[f][j]) +! (char_info(font_variants[f][j]) +! (character(lig_char(v)))) +! -cw); +! end; + hlist_node,vlist_node,rule_node,kern_node: + break_width[1]:=break_width[1]-width(v); + othercases confusion("disc1") +*************** +*** 16540,16552 **** + @ @<Add the width of node |s| to |b...@>= + if is_char_node(s) then + begin f:=font(s); +! break_width[1]:=@|break_width[1]+char_width(f)(char_info(f)(character(s))); +! end +! else case type(s) of + ligature_node: begin f:=font(lig_char(s)); +! break_width[1]:=break_width[1]+ +! char_width(f)(char_info(f)(character(lig_char(s)))); +! end; + hlist_node,vlist_node,rule_node,kern_node: + break_width[1]:=break_width[1]+width(s); + othercases confusion("disc2") +--- 16642,16666 ---- + @ @<Add the width of node |s| to |b...@>= + if is_char_node(s) then + begin f:=font(s); +! cw:=char_width(f)(char_info(f)(character(s))); +! break_width[1]:=@|break_width[1]+cw; +! for j:=0 to 3 do +! break_width[7+j]:=break_width[7+j] +! +(char_width(font_variants[f][j]) +! (char_info(font_variants[f][j]) +! (character(s))) +! -cw); +! end else case type(s) of + ligature_node: begin f:=font(lig_char(s)); +! cw:=char_width(f)(char_info(f)(character(lig_char(s)))); +! break_width[1]:=break_width[1]+cw; +! for j:=0 to 3 do +! break_width[7+j]:=break_width[7+j] +! +(char_width(font_variants[f][j]) +! (char_info(font_variants[f][j]) +! (character(lig_char(s)))) +! -cw); +! end; + hlist_node,vlist_node,rule_node,kern_node: + break_width[1]:=break_width[1]+width(s); + othercases confusion("disc2") +*************** +*** 16564,16577 **** + + @<Insert a delta node to prepare for breaks at |cur_p|@>= + if type(prev_r)=delta_node then {modify an existing delta node} +! begin do_all_six(convert_to_break_width); + end + else if prev_r=active then {no delta node needed at the beginning} +! begin do_all_six(store_break_width); + end + else begin q:=get_node(delta_node_size); link(q):=r; type(q):=delta_node;@/ + subtype(q):=0; {the |subtype| is not used} +! do_all_six(new_delta_to_break_width); + link(prev_r):=q; prev_prev_r:=prev_r; prev_r:=q; + end + +--- 16678,16691 ---- + + @<Insert a delta node to prepare for breaks at |cur_p|@>= + if type(prev_r)=delta_node then {modify an existing delta node} +! begin do_all_ten(convert_to_break_width); + end + else if prev_r=active then {no delta node needed at the beginning} +! begin do_all_ten(store_break_width); + end + else begin q:=get_node(delta_node_size); link(q):=r; type(q):=delta_node;@/ + subtype(q):=0; {the |subtype| is not used} +! do_all_ten(new_delta_to_break_width); + link(prev_r):=q; prev_prev_r:=prev_r; prev_r:=q; + end + +*************** +*** 16585,16591 **** + if r<>last_active then + begin q:=get_node(delta_node_size); link(q):=r; type(q):=delta_node;@/ + subtype(q):=0; {the |subtype| is not used} +! do_all_six(new_delta_from_break_width); + link(prev_r):=q; prev_prev_r:=prev_r; prev_r:=q; + end + +--- 16699,16705 ---- + if r<>last_active then + begin q:=get_node(delta_node_size); link(q):=r; type(q):=delta_node;@/ + subtype(q):=0; {the |subtype| is not used} +! do_all_ten(new_delta_from_break_width); + link(prev_r):=q; prev_prev_r:=prev_r; prev_r:=q; + end + +*************** +*** 16596,16606 **** + begin q:=get_node(passive_node_size); + link(q):=passive; passive:=q; cur_break(q):=cur_p; + @!stat incr(pass_number); serial(q):=pass_number;@+tats@;@/ +! prev_break(q):=best_place[fit_class];@/ + q:=get_node(active_node_size); break_node(q):=passive; +! line_number(q):=best_pl_line[fit_class]+1; + fitness(q):=fit_class; type(q):=break_type; +! total_demerits(q):=minimal_demerits[fit_class]; + link(q):=r; link(prev_r):=q; prev_r:=q; + @!stat if tracing_paragraphs>0 then + @<Print a symbolic description of the new break node@>; +--- 16710,16721 ---- + begin q:=get_node(passive_node_size); + link(q):=passive; passive:=q; cur_break(q):=cur_p; + @!stat incr(pass_number); serial(q):=pass_number;@+tats@;@/ +! condensedness(q):=condensed_class; +! prev_break(q):=best_place[fit_class][condensed_class];@/ + q:=get_node(active_node_size); break_node(q):=passive; +! line_number(q):=best_pl_line[fit_class][condensed_class]+1; + fitness(q):=fit_class; type(q):=break_type; +! total_demerits(q):=minimal_demerits[fit_class][condensed_class]; + link(q):=r; link(prev_r):=q; prev_r:=q; + @!stat if tracing_paragraphs>0 then + @<Print a symbolic description of the new break node@>; +*************** +*** 16612,16617 **** +--- 16727,16733 ---- + @.\AT!\AT!@> + print(": line "); print_int(line_number(q)-1); + print_char("."); print_int(fit_class); ++ print_char("."); print_int(condensed_class); + if break_type=hyphenated then print_char("-"); + print(" t="); print_int(total_demerits(q)); + print(" -> @@@@"); +*************** +*** 16703,16727 **** + We also deactivate node~|r| when a break at~|cur_p| is forced, since future + breaks must go through a forced break. + + @<Consider the demerits for a line from |r| to |cur_p|...@>= + begin artificial_demerits:=false;@/ + @^inner loop@> +! shortfall:=line_width-cur_active_width[1]; {we're this much too short} +! if shortfall>0 then +! @<Set the value of |b| to the badness for stretching the line, +! and compute the corresponding |fit_class|@> +! else @<Set the value of |b| to the badness for shrinking the line, +! and compute the corresponding |fit_class|@>; +! if (b>inf_bad)or(pi=eject_penalty) then +! @<Prepare to deactivate node~|r|, and |goto deactivate| unless +! there is a reason to consider lines of text from |r| to |cur_p|@> +! else begin prev_r:=r; +! if b>threshold then goto continue; +! node_r_stays_active:=true; +! end; +! @<Record a new feasible break@>; +! if node_r_stays_active then goto continue; {|prev_r| has been set to |r|} +! deactivate: @<Deactivate node |r|@>; + end + + @ When a line must stretch, the available stretchability can be found in the +--- 16819,16859 ---- + We also deactivate node~|r| when a break at~|cur_p| is forced, since future + breaks must go through a forced break. + ++ The program logic in this section is really f***ed up!!! ++ + @<Consider the demerits for a line from |r| to |cur_p|...@>= + begin artificial_demerits:=false;@/ + @^inner loop@> +! node_r_stays_active:=false; +! for condensed_class:=very_condensed_font to very_extended_font do begin +! do_not_consider:=false; +! shortfall:=line_width-cur_active_width[1]; +! case condensed_class of +! very_condensed_font:shortfall:=shortfall-cur_active_width[7]; +! condensed_font: shortfall:=shortfall-cur_active_width[8]; +! extended_font: shortfall:=shortfall-cur_active_width[9]; +! very_extended_font: shortfall:=shortfall-cur_active_width[10]; +! endcases; +! if shortfall>0 then +! @<Set the value of |b| to the badness for stretching the line, +! and compute the corresponding |fit_class|@> +! else +! @<Set the value of |b| to the badness for shrinking the line, +! and compute the corresponding |fit_class|@>; +! if (b>inf_bad)or(pi=eject_penalty) then begin +! if final_pass and (minimum_demerits=awful_bad) and@| +! (link(r)=last_active) and +! (prev_r=active) then +! artificial_demerits:=true {set demerits zero, this break is forced} +! else if b>threshold then do_not_consider:=true; +! end else begin +! node_r_stays_active:=true; +! if b>threshold then do_not_consider:=true; +! end; +! if not do_not_consider then @<Record a new feasible break@> +! end; +! if node_r_stays_active then prev_r:=r +! else @<Deactivate node |r|@>; + end + + @ When a line must stretch, the available stretchability can be found in the +*************** +*** 16738,16789 **** + (cur_active_width[5]<>0) then + begin b:=0; fit_class:=decent_fit; {infinite stretch} + end +! else begin if shortfall>7230584 then if cur_active_width[2]<1663497 then +! begin b:=inf_bad; fit_class:=very_loose_fit; goto done1; +! end; + b:=badness(shortfall,cur_active_width[2]); + if b>12 then +! if b>99 then fit_class:=very_loose_fit + else fit_class:=loose_fit + else fit_class:=decent_fit; +- done1: + end + + @ Shrinkability is never infinite in a paragraph; + we can shrink the line from |r| to |cur_p| by at most |cur_active_width[6]|. + + @<Set the value of |b| to the badness for shrinking...@>= +! begin if -shortfall>cur_active_width[6] then b:=inf_bad+1 + else b:=badness(-shortfall,cur_active_width[6]); +! if b>12 then fit_class:=tight_fit@+else fit_class:=decent_fit; +! end +! +! @ During the final pass, we dare not lose all active nodes, lest we lose +! touch with the line breaks already found. The code shown here makes sure +! that such a catastrophe does not happen, by permitting overfull boxes as +! a last resort. This particular part of \TeX\ was a source of several subtle +! bugs before the correct program logic was finally discovered; readers +! who seek to ``improve'' \TeX\ should therefore think thrice before daring +! to make any changes here. +! @^overfull boxes@> +! +! @<Prepare to deactivate node~|r|, and |goto deactivate| unless...@>= +! begin if final_pass and (minimum_demerits=awful_bad) and@| +! (link(r)=last_active) and +! (prev_r=active) then +! artificial_demerits:=true {set demerits zero, this break is forced} +! else if b>threshold then goto deactivate; +! node_r_stays_active:=false; + end + + @ When we get to this part of the code, the line from |r| to |cur_p| is + feasible, its badness is~|b|, and its fitness classification is |fit_class|. + We don't want to make an active node for this break yet, but we will + compute the total demerits and record them in the |minimal_demerits| array, + if such a break is the current champion among all ways to get to |cur_p| + in a given line-number class and fitness class. + + @<Record a new feasible break@>= + if artificial_demerits then d:=0 + else @<Compute the demerits, |d|, from |r| to |cur_p|@>; + @!stat if tracing_paragraphs>0 then +--- 16870,16906 ---- + (cur_active_width[5]<>0) then + begin b:=0; fit_class:=decent_fit; {infinite stretch} + end +! else begin + b:=badness(shortfall,cur_active_width[2]); + if b>12 then +! if b>99 then +! if b>799 then fit_class:=extremely_loose_fit +! else fit_class:=very_loose_fit + else fit_class:=loose_fit + else fit_class:=decent_fit; + end + + @ Shrinkability is never infinite in a paragraph; + we can shrink the line from |r| to |cur_p| by at most |cur_active_width[6]|. + + @<Set the value of |b| to the badness for shrinking...@>= +! begin +! if xn_over_d(-shortfall,1000,effective_glue_overshrink)>cur_active_width[6] then b:=inf_bad+1 + else b:=badness(-shortfall,cur_active_width[6]); +! if b>100 then fit_class:= very_tight_fit +! else if b>12 then fit_class:=tight_fit@+else fit_class:=decent_fit; + end + + @ When we get to this part of the code, the line from |r| to |cur_p| is + feasible, its badness is~|b|, and its fitness classification is |fit_class|. ++ And its condensedness classification is |condensed_class|. + We don't want to make an active node for this break yet, but we will + compute the total demerits and record them in the |minimal_demerits| array, + if such a break is the current champion among all ways to get to |cur_p| + in a given line-number class and fitness class. + + @<Record a new feasible break@>= ++ begin + if artificial_demerits then d:=0 + else @<Compute the demerits, |d|, from |r| to |cur_p|@>; + @!stat if tracing_paragraphs>0 then +*************** +*** 16791,16801 **** + tats@;@/ + d:=d+total_demerits(r); {this is the minimum total demerits + from the beginning to |cur_p| via |r|} +! if d<=minimal_demerits[fit_class] then +! begin minimal_demerits[fit_class]:=d; +! best_place[fit_class]:=break_node(r); best_pl_line[fit_class]:=l; + if d<minimum_demerits then minimum_demerits:=d; + end + + @ @<Print a symbolic description of this feasible break@>= + begin if printed_node<>cur_p then +--- 16908,16920 ---- + tats@;@/ + d:=d+total_demerits(r); {this is the minimum total demerits + from the beginning to |cur_p| via |r|} +! if d<=minimal_demerits[fit_class][condensed_class] then +! begin minimal_demerits[fit_class][condensed_class]:=d; +! best_place[fit_class][condensed_class]:=break_node(r); +! best_pl_line[fit_class][condensed_class]:=l; + if d<minimum_demerits then minimum_demerits:=d; + end ++ end + + @ @<Print a symbolic description of this feasible break@>= + begin if printed_node<>cur_p then +*************** +*** 16818,16823 **** +--- 16937,16945 ---- + @.*\relax@> + print(" p="); print_int(pi); print(" d="); + if artificial_demerits then print_char("*")@+else print_int(d); ++ print(" "); print_int(fit_class); ++ print("."); print_int(condensed_class); ++ print(" t="); print_int(d+total_demerits(r)); + end + + @ @<Print the list between |printed_node| and |cur_p|...@>= +*************** +*** 16852,16858 **** + if (break_type=hyphenated)and(type(r)=hyphenated) then + if cur_p<>null then d:=d+double_hyphen_demerits + else d:=d+final_hyphen_demerits; +! if abs(fit_class-fitness(r))>1 then d:=d+adj_demerits; + end + + @ When an active node disappears, we must delete an adjacent delta node if the +--- 16974,16991 ---- + if (break_type=hyphenated)and(type(r)=hyphenated) then + if cur_p<>null then d:=d+double_hyphen_demerits + else d:=d+final_hyphen_demerits; +! case abs(fit_class-fitness(r)) of +! 0,1: do_nothing; +! 2: d:=d+adj_demerits; +! othercases d:=d+adj_demerits+extra_adj_demerits; +! endcases; +! if break_node(r)=null then prev_cc:=normal_font +! else prev_cc:=condensedness(break_node(r)); +! case abs(condensed_class-prev_cc) of +! 0,1: do_nothing; +! 2: d:=d+font_demerits; +! othercases d:=d+font_demerits+extra_font_demerits; +! endcases; + end + + @ When an active node disappears, we must delete an adjacent delta node if the +*************** +*** 16866,16887 **** + mem[prev_r+#].sc + + @<Deactivate node |r|@>= + link(prev_r):=link(r); free_node(r,active_node_size); + if prev_r=active then @<Update the active widths, since the first active + node has been deleted@> + else if type(prev_r)=delta_node then + begin r:=link(prev_r); + if r=last_active then +! begin do_all_six(downdate_width); + link(prev_prev_r):=last_active; + free_node(prev_r,delta_node_size); prev_r:=prev_prev_r; + end + else if type(r)=delta_node then +! begin do_all_six(update_width); +! do_all_six(combine_two_deltas); + link(prev_r):=link(r); free_node(r,delta_node_size); + end; + end + + @ The following code uses the fact that |type(last_active)<>delta_node|. If the + active list has just become empty, we do not need to update the +--- 16999,17022 ---- + mem[prev_r+#].sc + + @<Deactivate node |r|@>= ++ begin + link(prev_r):=link(r); free_node(r,active_node_size); + if prev_r=active then @<Update the active widths, since the first active + node has been deleted@> + else if type(prev_r)=delta_node then + begin r:=link(prev_r); + if r=last_active then +! begin do_all_ten(downdate_width); + link(prev_prev_r):=last_active; + free_node(prev_r,delta_node_size); prev_r:=prev_prev_r; + end + else if type(r)=delta_node then +! begin do_all_ten(update_width); +! do_all_ten(combine_two_deltas); + link(prev_r):=link(r); free_node(r,delta_node_size); + end; + end ++ end + + @ The following code uses the fact that |type(last_active)<>delta_node|. If the + active list has just become empty, we do not need to update the +*************** +*** 16893,16900 **** + @<Update the active widths,...@>= + begin r:=link(active); + if type(r)=delta_node then +! begin do_all_six(update_active); +! do_all_six(copy_to_cur_active); + link(active):=link(r); free_node(r,delta_node_size); + end; + end +--- 17028,17035 ---- + @<Update the active widths,...@>= + begin r:=link(active); + if type(r)=delta_node then +! begin do_all_ten(update_active); +! do_all_ten(copy_to_cur_active); + link(active):=link(r); free_node(r,delta_node_size); + end; + end +*************** +*** 16921,16929 **** +--- 17056,17066 ---- + + @<Local variables for line breaking@>= + @!auto_breaking:boolean; {is node |cur_p| outside a formula?} ++ @!cw:scaled; + @!prev_p:pointer; {helps to determine when glue nodes are breakpoints} + @!q,@!r,@!s,@!prev_s:pointer; {miscellaneous nodes of temporary interest} + @!f:internal_font_number; {used when calculating character widths} ++ @!l:small_number; + + @ The `\ignorespaces|loop|\unskip' in the following code is performed at most + thrice per call of |line_break|, since it is actually a pass over the +*************** +*** 16978,16984 **** + type(q):=unhyphenated; fitness(q):=decent_fit; + link(q):=last_active; break_node(q):=null; + line_number(q):=prev_graf+1; total_demerits(q):=0; link(active):=q; +! do_all_six(store_background);@/ + passive:=null; printed_node:=temp_head; pass_number:=0; + font_in_short_display:=null_font + +--- 17115,17121 ---- + type(q):=unhyphenated; fitness(q):=decent_fit; + link(q):=last_active; break_node(q):=null; + line_number(q):=prev_graf+1; total_demerits(q):=0; link(active):=q; +! do_all_ten(store_background);@/ + passive:=null; printed_node:=temp_head; pass_number:=0; + font_in_short_display:=null_font + +*************** +*** 17024,17031 **** + kern_node: if subtype(cur_p)=explicit then kern_break + else act_width:=act_width+width(cur_p); + ligature_node: begin f:=font(lig_char(cur_p)); +! act_width:=act_width+char_width(f)(char_info(f)(character(lig_char(cur_p)))); +! end; + disc_node: @<Try to break after a discretionary fragment, then |goto done5|@>; + math_node: begin auto_breaking:=(subtype(cur_p)=after); kern_break; + end; +--- 17161,17175 ---- + kern_node: if subtype(cur_p)=explicit then kern_break + else act_width:=act_width+width(cur_p); + ligature_node: begin f:=font(lig_char(cur_p)); +! cw:=char_width(f)(char_info(f)(character(lig_char(cur_p)))); +! act_width:=act_width+cw; +! for j:=0 to 3 do +! active_width[7+j]:=active_width[7+j] +! +(char_width(font_variants[f][j]) +! (char_info(font_variants[f][j]) +! (character(lig_char(cur_p)))) +! -cw); +! end; + disc_node: @<Try to break after a discretionary fragment, then |goto done5|@>; + math_node: begin auto_breaking:=(subtype(cur_p)=after); kern_break; + end; +*************** +*** 17047,17053 **** + @<Advance \(c)|cur_p| to the node following the present string...@>= + begin prev_p:=cur_p; + repeat f:=font(cur_p); +! act_width:=act_width+char_width(f)(char_info(f)(character(cur_p))); + cur_p:=link(cur_p); + until not is_char_node(cur_p); + end +--- 17191,17204 ---- + @<Advance \(c)|cur_p| to the node following the present string...@>= + begin prev_p:=cur_p; + repeat f:=font(cur_p); +! cw:=char_width(f)(char_info(f)(character(cur_p))); +! act_width:=act_width+cw; +! for j:=0 to 3 do +! active_width[7+j]:=active_width[7+j] +! +(char_width(font_variants[f][j]) +! (char_info(font_variants[f][j]) +! (character(cur_p))) +! -cw); + cur_p:=link(cur_p); + until not is_char_node(cur_p); + end +*************** +*** 17378,17384 **** + else begin cur_width:=mem[par_shape_ptr+2*cur_line].sc; + cur_indent:=mem[par_shape_ptr+2*cur_line-1].sc; + end; +! adjust_tail:=adjust_head; just_box:=hpack(q,cur_width,exactly); + shift_amount(just_box):=cur_indent + + @ Penalties between the lines of a paragraph come from club and widow lines, +--- 17529,17538 ---- + else begin cur_width:=mem[par_shape_ptr+2*cur_line].sc; + cur_indent:=mem[par_shape_ptr+2*cur_line-1].sc; + end; +! adjust_tail:=adjust_head; +! line_font_variant:=condensedness(cur_p); +! just_box:=hpack(q,cur_width,exactly); +! line_font_variant:=normal_font; + shift_amount(just_box):=cur_indent + + @ Penalties between the lines of a paragraph come from club and widow lines, +*************** +*** 23263,23271 **** + @ Here is where the information for a new font gets loaded. + + @<Assignments@>= +! def_font: new_font(a); +! + @ @<Declare subprocedures for |prefixed_command|@>= + procedure new_font(@!a:small_number); + label common_ending; + var u:pointer; {user's font identifier} +--- 23417,23441 ---- + @ Here is where the information for a new font gets loaded. + + @<Assignments@>= +! def_font: if cur_chr=0 then new_font(a) else +! set_font_variant(a); +! + @ @<Declare subprocedures for |prefixed_command|@>= ++ procedure set_font_variant(@!a:small_number); ++ var ++ s:integer; ++ begin ++ scan_int; s:=cur_val; ++ if (s<0)or(s>3) then begin ++ print_err("Bad font variant number"); ++ help2("A font variant number must be between 0 and 3.")@/ ++ ("I changed this one to zero."); int_error(s); s:=0; ++ end; ++ scan_font_ident; f:=cur_val; ++ scan_optional_equals; scan_font_ident; ++ font_variants[f][s]:=cur_val; ++ end; ++ + procedure new_font(@!a:small_number); + label common_ending; + var u:pointer; {user's font identifier} +*************** +*** 23274,23279 **** +--- 23444,23450 ---- + @!t:str_number; {name for the frozen font identifier} + @!old_setting:0..max_selector; {holds |selector| setting} + @!flushable_string:str_number; {string not yet referenced} ++ @!k:small_number; + begin if job_name=0 then open_log_file; + {avoid confusing \.{texput} with the font name} + @.texput@> +*************** +*** 23292,23297 **** +--- 23463,23469 ---- + font number and |goto common_ending|@>; + f:=read_font_info(u,cur_name,cur_area,s); + common_ending: equiv(u):=f; eqtb[font_id_base+f]:=eqtb[u]; font_id_text(f):=t; ++ for k:=0 to 3 do font_variants[f][k]:=f; + end; + + @ @<Scan the font size specification@>= +*** tex.ch.orig Wed Sep 16 22:54:44 1998 +--- tex.ch Sun Sep 20 10:03:52 1998 +*************** +*** 1200,1211 **** + @z + + @x [17.236] l.4954 - MLTeX: \charsubdefmax and \tracingcharsubdef +! @d int_pars=55 {total number of integer parameters} + @y +! @d char_sub_def_min_code=55 {smallest value in the charsubdef list} +! @d char_sub_def_max_code=56 {largest value in the charsubdef list} +! @d tracing_char_sub_def_code=57 {traces changes to a charsubdef def} +! @d int_pars=58 {total number of integer parameters} + @z + + @x [17.236] l.5016 - MLTeX: \charsubdefmax and \tracingcharsubdef +--- 1200,1211 ---- + @z + + @x [17.236] l.4954 - MLTeX: \charsubdefmax and \tracingcharsubdef +! @d int_pars=59 {total number of integer parameters} + @y +! @d char_sub_def_min_code=59 {smallest value in the charsubdef list} +! @d char_sub_def_max_code=60 {largest value in the charsubdef list} +! @d tracing_char_sub_def_code=61 {traces changes to a charsubdef def} +! @d int_pars=62 {total number of integer parameters} + @z + + @x [17.236] l.5016 - MLTeX: \charsubdefmax and \tracingcharsubdef +*************** +*** 1752,1757 **** +--- 1752,1759 ---- + {right boundary character, |non_char| if there is none} + @!font_false_bchar:array[internal_font_number] of min_quarterword..non_char; + {|font_bchar| if it doesn't exist in the font, otherwise |non_char|} ++ @!font_variants:array[internal_font_number] of four_fonts; ++ {we use four variants per font} + @y + @!font_info: ^fmemory_word; + {the big collection of font data} +*************** +*** 1783,1788 **** +--- 1785,1791 ---- + {right boundary character, |non_char| if there is none} + @!font_false_bchar: ^nine_bits; + {|font_bchar| if it doesn't exist in the font, otherwise |non_char|} ++ @!font_variants: ^four_fonts; + @z + + @x [30.550] l.10723 - texarray +*************** +*** 1845,1850 **** +--- 1848,1854 ---- + font_glue[null_font]:=null; font_params[null_font]:=7; + param_base[null_font]:=-1; + for k:=0 to 6 do font_info[k].sc:=0; ++ for k:=0 to 3 do font_variants[null_font][k]:=null_font; + @y + @z + +*************** +*** 2176,2184 **** + @z + + @x [38.859] l.16855 - Fix a casting/expression evaluation problem. +! if abs(fit_class-fitness(r))>1 then d:=d+adj_demerits; + @y +! if abs(toint(fit_class)-toint(fitness(r)))>1 then d:=d+adj_demerits; + @z + + @x [39.875] l.17170 - Another casting problem. +--- 2180,2188 ---- + @z + + @x [38.859] l.16855 - Fix a casting/expression evaluation problem. +! case abs(fit_class-fitness(r)) of + @y +! case abs(toint(fit_class)-toint(fitness(r))) of + @z + + @x [39.875] l.17170 - Another casting problem. +*************** +*** 3197,3202 **** +--- 3201,3207 ---- + dump_things(exten_base[null_font], font_ptr+1-null_font); + dump_things(param_base[null_font], font_ptr+1-null_font); + dump_things(font_glue[null_font], font_ptr+1-null_font); ++ dump_things(font_variants[null_font], font_ptr+1-null_font); + dump_things(bchar_label[null_font], font_ptr+1-null_font); + dump_things(font_bchar[null_font], font_ptr+1-null_font); + dump_things(font_false_bchar[null_font], font_ptr+1-null_font); +*************** +*** 3264,3269 **** +--- 3269,3275 ---- + xmalloc_array(kern_base, font_max); + xmalloc_array(exten_base, font_max); + xmalloc_array(param_base, font_max); ++ xmalloc_array(font_variants, font_max); + + undump_things(font_check[null_font], font_ptr+1-null_font); + undump_things(font_size[null_font], font_ptr+1-null_font); +*************** +*** 3290,3295 **** +--- 3296,3302 ---- + undump_things(param_base[null_font], font_ptr+1-null_font); + undump_checked_things(min_halfword, lo_mem_max, + font_glue[null_font], font_ptr+1-null_font); ++ undump_things(font_variants[null_font], font_ptr+1-null_font); + undump_checked_things(0, fmem_ptr-1, + bchar_label[null_font], font_ptr+1-null_font); + undump_checked_things(min_quarterword, non_char, +*************** +*** 3705,3710 **** +--- 3712,3718 ---- + xmalloc_array(kern_base, font_max); + xmalloc_array(exten_base, font_max); + xmalloc_array(param_base, font_max); ++ xmalloc_array(font_variants, font_max); + + font_ptr:=null_font; fmem_ptr:=7; + font_name[null_font]:="nullfont"; font_area[null_font]:=""; +*************** +*** 3720,3725 **** +--- 3728,3734 ---- + font_glue[null_font]:=null; font_params[null_font]:=7; + param_base[null_font]:=-1; + for font_k:=0 to 6 do font_info[font_k].sc:=0; ++ for font_k:=0 to 3 do font_variants[null_font][font_k]:=null_font; + end; + tini@/ + |