1% omdir.ch: Primitives to deal with multiple-direction text 2% 3% This file is part of the Omega projet, which 4% is based on the web2c distribution of TeX. 5% 6% Copyright (c) 1994--2000 John Plaice and Yannis Haralambous 7% 8% This library is free software; you can redistribute it and/or 9% modify it under the terms of the GNU Library General Public 10% License as published by the Free Software Foundation; either 11% version 2 of the License, or (at your option) any later version. 12% 13% This library is distributed in the hope that it will be useful, 14% but WITHOUT ANY WARRANTY; without even the implied warranty of 15% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16% Library General Public License for more details. 17% 18% You should have received a copy of the GNU Library General Public 19% License along with this library; if not, write to the Free Software 20% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21% 22%------------------------- 23@x [10] m.135 24@d hlist_node=0 {|type| of hlist nodes} 25@d box_node_size=7 {number of words to allocate for a box node} 26@d width_offset=1 {position of |width| field in a box node} 27@d depth_offset=2 {position of |depth| field in a box node} 28@d height_offset=3 {position of |height| field in a box node} 29@d width(#) == mem[#+width_offset].sc {width of the box, in sp} 30@d depth(#) == mem[#+depth_offset].sc {depth of the box, in sp} 31@d height(#) == mem[#+height_offset].sc {height of the box, in sp} 32@d shift_amount(#) == mem[#+4].sc {repositioning distance, in sp} 33@d list_offset=5 {position of |list_ptr| field in a box node} 34@d list_ptr(#) == link(#+list_offset) {beginning of the list inside the box} 35@d glue_order(#) == subtype(#+list_offset) {applicable order of infinity} 36@d glue_sign(#) == type(#+list_offset) {stretching or shrinking} 37@d normal=0 {the most common case when several cases are named} 38@d stretching = 1 {glue setting applies to the stretch components} 39@d shrinking = 2 {glue setting applies to the shrink components} 40@d glue_offset = 6 {position of |glue_set| in a box node} 41@d glue_set(#) == mem[#+glue_offset].gr 42 {a word of type |glue_ratio| for glue setting} 43@y 44@d hlist_node=0 {|type| of hlist nodes} 45@d box_node_size=8 {number of words to allocate for a box node} 46@d width_offset=1 {position of |width| field in a box node} 47@d depth_offset=2 {position of |depth| field in a box node} 48@d height_offset=3 {position of |height| field in a box node} 49@d width(#) == mem[#+width_offset].sc {width of the box, in sp} 50@d depth(#) == mem[#+depth_offset].sc {depth of the box, in sp} 51@d height(#) == mem[#+height_offset].sc {height of the box, in sp} 52@d shift_amount(#) == mem[#+4].sc {repositioning distance, in sp} 53@d list_offset=5 {position of |list_ptr| field in a box node} 54@d list_ptr(#) == link(#+list_offset) {beginning of the list inside the box} 55@d glue_order(#) == subtype(#+list_offset) {applicable order of infinity} 56@d glue_sign(#) == type(#+list_offset) {stretching or shrinking} 57@d normal=0 {the most common case when several cases are named} 58@d stretching = 1 {glue setting applies to the stretch components} 59@d shrinking = 2 {glue setting applies to the shrink components} 60@d glue_offset = 6 {position of |glue_set| in a box node} 61@d glue_set(#) == mem[#+glue_offset].gr 62 {a word of type |glue_ratio| for glue setting} 63@d dir_offset = 7 {position of |box_dir| in a box node} 64@d box_dir(#) == mem[#+dir_offset].int 65@z 66%------------------------- 67@x [10] m.136 68@p function new_null_box:pointer; {creates a new box node} 69var p:pointer; {the new node} 70begin p:=get_node(box_node_size); type(p):=hlist_node; 71subtype(p):=min_quarterword; 72width(p):=0; depth(p):=0; height(p):=0; shift_amount(p):=0; list_ptr(p):=null; 73glue_sign(p):=normal; glue_order(p):=normal; set_glue_ratio_zero(glue_set(p)); 74new_null_box:=p; 75@y 76@p function new_null_box:pointer; {creates a new box node} 77var p:pointer; {the new node} 78begin p:=get_node(box_node_size); type(p):=hlist_node; 79subtype(p):=min_quarterword; 80width(p):=0; depth(p):=0; height(p):=0; shift_amount(p):=0; list_ptr(p):=null; 81glue_sign(p):=normal; glue_order(p):=normal; set_glue_ratio_zero(glue_set(p)); 82box_dir(p):=text_direction; 83new_null_box:=p; 84@z 85%------------------------- 86@x [10] m.138 87@d rule_node=2 {|type| of rule nodes} 88@d rule_node_size=4 {number of words to allocate for a rule node} 89@d null_flag==-@'10000000000 {$-2^{30}$, signifies a missing item} 90@d is_running(#) == (#=null_flag) {tests for a running dimension} 91@y 92@d rule_node=2 {|type| of rule nodes} 93@d rule_node_size=5 {number of words to allocate for a rule node} 94@d null_flag==-@'10000000000 {$-2^{30}$, signifies a missing item} 95@d is_running(#) == (#=null_flag) {tests for a running dimension} 96@d rule_dir(#)==info(#+4) 97@z 98%------------------------- 99@x [10] m.139 100@p function new_rule:pointer; 101var p:pointer; {the new node} 102begin p:=get_node(rule_node_size); type(p):=rule_node; 103subtype(p):=0; {the |subtype| is not used} 104width(p):=null_flag; depth(p):=null_flag; height(p):=null_flag; 105new_rule:=p; 106end; 107@y 108@p function new_rule:pointer; 109var p:pointer; {the new node} 110begin p:=get_node(rule_node_size); type(p):=rule_node; 111subtype(p):=0; {the |subtype| is not used} 112width(p):=null_flag; depth(p):=null_flag; height(p):=null_flag; 113rule_dir(p):=-1; 114new_rule:=p; 115end; 116@z 117%------------------------- 118@x [10] m.176 119procedure print_rule_dimen(@!d:scaled); {prints dimension in rule node} 120begin if is_running(d) then print_char("*") else print_scaled(d); 121@.*\relax@> 122end; 123@y 124procedure print_rule_dimen(@!d:scaled); {prints dimension in rule node} 125begin if is_running(d) then print_char("*") else print_scaled(d); 126@.*\relax@> 127end; 128@# 129procedure print_dir(d:integer); 130begin 131print(dir_names[dir_primary[d]]); 132print(dir_names[dir_secondary[d]]); 133print(dir_names[dir_tertiary[d]]); 134end; 135@z 136%------------------------- 137@x [12] m.184 138@ @<Display box |p|@>= 139begin if type(p)=hlist_node then print_esc("h") 140else if type(p)=vlist_node then print_esc("v") 141else print_esc("unset"); 142print("box("); print_scaled(height(p)); print_char("+"); 143print_scaled(depth(p)); print(")x"); print_scaled(width(p)); 144if type(p)=unset_node then 145 @<Display special fields of the unset node |p|@> 146else begin @<Display the value of |glue_set(p)|@>; 147 if shift_amount(p)<>0 then 148 begin print(", shifted "); print_scaled(shift_amount(p)); 149 end; 150 end; 151node_list_display(list_ptr(p)); {recursive call} 152end 153@y 154@ @<Display box |p|@>= 155begin if type(p)=hlist_node then print_esc("h") 156else if type(p)=vlist_node then print_esc("v") 157else print_esc("unset"); 158print("box("); print_scaled(height(p)); print_char("+"); 159print_scaled(depth(p)); print(")x"); print_scaled(width(p)); 160if type(p)=unset_node then 161 @<Display special fields of the unset node |p|@> 162else begin @<Display the value of |glue_set(p)|@>; 163 if shift_amount(p)<>0 then 164 begin print(", shifted "); print_scaled(shift_amount(p)); 165 end; 166 print(", direction "); print_dir(box_dir(p)); 167 end; 168node_list_display(list_ptr(p)); {recursive call} 169end 170@z 171%------------------------- 172@x [10] m.206 173hlist_node,vlist_node,unset_node: begin r:=get_node(box_node_size); 174 mem[r+6]:=mem[p+6]; mem[r+5]:=mem[p+5]; {copy the last two words} 175@y 176hlist_node,vlist_node,unset_node: begin r:=get_node(box_node_size); 177 mem[r+7]:=mem[p+7]; mem[r+6]:=mem[p+6]; mem[r+5]:=mem[p+5]; 178 {copy the last three words} 179@z 180%------------------------- 181@x [15] m.209 182@d max_internal=register 183 {the largest code that can follow \.{\\the}} 184@y 185@d assign_dir=register+1 {(\.{\\pagedir}, \.{\\textdir})} 186@d max_internal=assign_dir 187 {the largest code that can follow \.{\\the}} 188@z 189%------------------------- 190@x [16] m.212 191 @!aux_field: memory_word; 192@y 193 @!aux_field: memory_word; 194 @!dirs_field: halfword; 195 @!math_field: integer; 196@z 197%------------------------- 198@x [16] m.212 199@d mode_line==cur_list.ml_field {source file line number at beginning of list} 200@y 201@d mode_line==cur_list.ml_field {source file line number at beginning of list} 202@d dir_save==cur_list.dirs_field {dir stack when a paragraph is interrupted} 203@d dir_math_save==cur_list.math_field 204 {should begin/end dir nodes be placed around mathematics?} 205@z 206%------------------------- 207@x [16] m.215 208prev_graf:=0; shown_mode:=0; 209@y 210prev_graf:=0; shown_mode:=0; 211dir_save:=null; dir_math_save:=false; 212@z 213%------------------------- 214@x [16] m.216 l.4351 215@ @p @<LOCAL: Declare |make_local_par_node|@>; 216@y 217@ @p @<LOCAL: Declare |make_local_par_node|@>; 218 219@ @p @<DIR: Declare |new_dir|@>; 220@z 221%------------------------- 222@x [16] m.216 223incr(nest_ptr); head:=get_avail; tail:=head; prev_graf:=0; mode_line:=line; 224@y 225incr(nest_ptr); head:=get_avail; tail:=head; prev_graf:=0; mode_line:=line; 226dir_save:=null; dir_math_save:=false; 227@z 228%------------------------- 229@x [16] m.217 230free_avail(head); decr(nest_ptr); cur_list:=nest[nest_ptr]; 231@y 232free_avail(head); decr(nest_ptr); cur_list:=nest[nest_ptr]; 233@z 234%------------------------- 235@x [17] m.236 236@d int_pars=58 {total number of integer parameters} 237@d count_base=int_base+int_pars {|number_regs| user \.{\\count} registers} 238@y 239@d no_local_dirs_code=58 240@d level_local_dir_code=59 241@d int_pars=61 {total number of integer parameters} 242@d dir_base=int_base+int_pars 243@d page_direction_code=0 244@d body_direction_code=1 245@d par_direction_code=2 246@d text_direction_code=3 247@d math_direction_code=4 248@d dir_pars=5 249@d count_base=dir_base+dir_pars {|number_regs| user \.{\\count} registers} 250@z 251%------------------------- 252@x [17] m.238 253@d no_local_whatsits==int_par(no_local_whatsits_code) 254@y 255@d no_local_whatsits==int_par(no_local_whatsits_code) 256@d no_local_dirs==int_par(no_local_dirs_code) 257@d level_local_dir==int_par(level_local_dir_code) 258@d dir_par(#)==new_eqtb_int(dir_base+#) {a direction parameter} 259@d page_direction==dir_par(page_direction_code) 260@d body_direction==dir_par(body_direction_code) 261@d par_direction==dir_par(par_direction_code) 262@d text_direction==dir_par(text_direction_code) 263@d math_direction==dir_par(math_direction_code) 264@z 265%------------------------- 266@x [17] m.240 267set_new_eqtb_int(int_base+end_line_char_code,carriage_return); 268@y 269set_new_eqtb_int(int_base+end_line_char_code,carriage_return); 270set_new_eqtb_int(int_base+level_local_dir_code,level_one); 271@z 272%------------------------- 273@x [17] m.247 274@d dimen_pars=21 {total number of dimension parameters} 275@y 276@d page_width_code=21 277@d page_height_code=22 278@d page_right_offset_code=23 279@d page_bottom_offset_code=24 280@d dimen_pars=25 {total number of dimension parameters} 281@z 282%------------------------- 283@x [17] m.247 284@d emergency_stretch==dimen_par(emergency_stretch_code) 285@y 286@d emergency_stretch==dimen_par(emergency_stretch_code) 287@d page_width==dimen_par(page_width_code) 288@d page_height==dimen_par(page_height_code) 289@d page_right_offset==dimen_par(page_right_offset_code) 290@d page_bottom_offset==dimen_par(page_bottom_offset_code) 291@z 292%------------------------- 293@x [26] m.410 294@d int_val=0 {integer values} 295@d dimen_val=1 {dimension values} 296@d glue_val=2 {glue specifications} 297@d mu_val=3 {math glue specifications} 298@d ident_val=4 {font identifier} 299@d tok_val=5 {token lists} 300 301@<Glob...@>= 302@!cur_val:integer; {value returned by numeric scanners} 303@!cur_val_level:int_val..tok_val; {the ``level'' of this value} 304@y 305@d int_val=0 {integer values} 306@d dimen_val=1 {dimension values} 307@d glue_val=2 {glue specifications} 308@d mu_val=3 {math glue specifications} 309@d dir_val=4 {directions} 310@d ident_val=5 {font identifier} 311@d tok_val=6 {token lists} 312 313@<Glob...@>= 314@!cur_val:integer; {value returned by numeric scanners} 315@!cur_val1:integer; {delcodes are now 51 digits} 316@!cur_val_level:int_val..dir_val; {the ``level'' of this value} 317@z 318%------------------------- 319@x [26] m.413 320assign_int: scanned_result(new_eqtb_int(m))(int_val); 321@y 322assign_int: scanned_result(new_eqtb_int(m))(int_val); 323assign_dir: scanned_result(new_eqtb_int(m))(dir_val); 324@z 325%------------------------- 326@x [26] m.437 327@ @<Declare procedures that scan restricted classes of integers@>= 328procedure scan_eight_bit_int; 329@y 330@ 331@d dir_T=0 332@d dir_L=1 333@d dir_B=2 334@d dir_R=3 335@d dir_eq_end(#)==(#) 336@d dir_eq(#)==(#)=dir_eq_end 337@d dir_ne_end(#)==(#) 338@d dir_ne(#)==(#)<>dir_ne_end 339@d dir_opposite_end(#)==((#) mod 4) 340@d dir_opposite(#)==(((#)+2) mod 4)=dir_opposite_end 341@d dir_parallel_end(#)==((#) mod 2) 342@d dir_parallel(#)==((#) mod 2)=dir_parallel_end 343@d dir_orthogonal_end(#)==(# mod 2) 344@d dir_orthogonal(#)==((#) mod 2)<>dir_orthogonal_end 345@d dir_next_end(#)==((#) mod 4) 346@d dir_next(#)==(((#)+3) mod 4)=dir_next_end 347@d dir_prev_end(#)==((#) mod 4) 348@d dir_prev(#)==(((#)+1) mod 4)=dir_prev_end 349 350{box directions} 351@d dir_TL_=0 352@d dir_TR_=1 353@d dir_LT_=2 354@d dir_LB_=3 355@d dir_BL_=4 356@d dir_BR_=5 357@d dir_RT_=6 358@d dir_RB_=7 359 360{font directions} 361@d dir__LT= 0 362@d dir__LL= 1 363@d dir__LB= 2 364@d dir__LR= 3 365@d dir__RT= 4 366@d dir__RL= 5 367@d dir__RB= 6 368@d dir__RR= 7 369@d dir__TT= 8 370@d dir__TL= 9 371@d dir__TB=10 372@d dir__TR=11 373@d dir__BT=12 374@d dir__BL=13 375@d dir__BB=14 376@d dir__BR=15 377 378@d is_mirrored(#)==dir_opposite(dir_primary[#])(dir_tertiary[#]) 379@d is_rotated(#)==dir_parallel(dir_secondary[#])(dir_tertiary[#]) 380@d font_direction(#)==(# mod 16) 381@d box_direction(#)==(# div 4) 382 383@d scan_single_dir(#)==begin 384if scan_keyword("T") then #:=dir_T 385else if scan_keyword("L") then #:=dir_L 386else if scan_keyword("B") then #:=dir_B 387else if scan_keyword("R") then #:=dir_R 388else begin 389 print_err("Bad direction"); cur_val:=0; 390 goto exit; 391 end 392end 393 394@<Declare procedures that scan restricted classes of integers@>= 395procedure scan_dir; 396var d1,d2,d3: integer; 397begin 398get_x_token; 399if cur_cmd=assign_dir then begin 400 cur_val:=new_eqtb_int(cur_chr); 401 goto exit; 402 end 403else back_input; 404scan_single_dir(d1); 405scan_single_dir(d2); 406if dir_parallel(d1)(d2) then begin 407 print_err("Bad direction"); cur_val:=0; 408 goto exit; 409 end; 410scan_single_dir(d3); 411cur_val:=d1*8+dir_rearrange[d2]*4+d3; 412exit: 413end; 414 415@ @<Declare procedures that scan restricted classes of integers@>= 416procedure scan_eight_bit_int; 417@z 418%------------------------- 419@x [27] m.463 420@p function scan_rule_spec:pointer; 421label reswitch; 422var q:pointer; {the rule node being created} 423begin q:=new_rule; {|width|, |depth|, and |height| all equal |null_flag| now} 424if cur_cmd=vrule then width(q):=default_rule 425else begin height(q):=default_rule; depth(q):=0; 426 end; 427@y 428@p function scan_rule_spec:pointer; 429label reswitch; 430var q:pointer; {the rule node being created} 431begin q:=new_rule; {|width|, |depth|, and |height| all equal |null_flag| now} 432if cur_cmd=vrule then begin 433 width(q):=default_rule; 434 rule_dir(q):=body_direction; 435 end 436else begin 437 height(q):=default_rule; depth(q):=0; 438 rule_dir(q):=text_direction; 439end; 440@z 441%------------------------- 442@x [27] m.465 443 int_val:print_int(cur_val); 444@y 445 int_val:print_int(cur_val); 446 dir_val:print_dir(cur_val); 447@z 448%------------------------- 449@x [30] m.550 450@d offset_false_bchar=offset_bchar+1 451@d offset_ivalues_start=offset_false_bchar+1 452@y 453@d offset_false_bchar=offset_bchar+1 454@d offset_natural_dir=offset_false_bchar+1 455@d offset_ivalues_start=offset_natural_dir+1 456@z 457%------------------------- 458@x [30] m.550 459@d font_false_bchar(#)==font_info(#)(offset_false_bchar).int 460@y 461@d font_false_bchar(#)==font_info(#)(offset_false_bchar).int 462@d font_natural_dir(#)==font_info(#)(offset_natural_dir).int 463@z 464%------------------------- 465@x [30] m.560 466@p function read_font_info(@!u:pointer;@!nom,@!aire:str_number; 467 @!s:scaled;offset:quarterword):internal_font_number; {input a \.{TFM} file} 468@y 469@p function read_font_info(@!u:pointer;@!nom,@!aire:str_number; 470 @!s:scaled;offset:quarterword;natural_dir:integer):internal_font_number; 471 {input a \.{TFM} file} 472@z 473%------------------------- 474@x [30] m.560 475font_offset(f):=offset; 476@y 477font_offset(f):=offset; 478font_natural_dir(f):=natural_dir; 479@z 480%------------------------- 481@x [31] m.586 482@d set_rule=132 {typeset a rule and move right} 483@y 484@d set_rule=132 {typeset a rule and move right} 485@d put1==133 {typeset a character without moving} 486@z 487%------------------------- 488@x [31] m.586 489@d right1=143 {move right} 490@y 491@d right1==143 {move right} 492@d right4==146 {move right, 4 bytes} 493@z 494%------------------------- 495@x [31] m.586 496@d down1=157 {move down} 497@y 498@d down1=157 {move down} 499@d down4=160 {move down, 4 bytes} 500@z 501%------------------------- 502@x [32] m.607 503@p procedure movement(@!w:scaled;@!o:eight_bits); 504label exit,found,not_found,2,1; 505var mstate:small_number; {have we seen a |y| or |z|?} 506@!p,@!q:pointer; {current and top nodes on the stack} 507@!k:integer; {index into |dvi_buf|, modulo |dvi_buf_size|} 508begin q:=get_node(movement_node_size); {new node for the top of the stack} 509width(q):=w; location(q):=dvi_offset+dvi_ptr; 510if o=down1 then 511 begin link(q):=down_ptr; down_ptr:=q; 512 end 513else begin link(q):=right_ptr; right_ptr:=q; 514 end; 515@<Look at the other stack entries until deciding what sort of \.{DVI} command 516 to generate; |goto found| if node |p| is a ``hit''@>; 517@<Generate a |down| or |right| command for |w| and |return|@>; 518found: @<Generate a |y0| or |z0| command in order to reuse a previous 519 appearance of~|w|@>; 520exit:end; 521@y 522@d dvi_set(#)==oval:=#-font_offset(f); ocmd:=set1; out_cmd 523@d dvi_put(#)==oval:=#-font_offset(f); ocmd:=put1; out_cmd 524@d dvi_set_rule_end(#)==dvi_four(#) 525@d dvi_set_rule(#)==dvi_out(set_rule); dvi_four(#); dvi_set_rule_end 526@d dvi_put_rule_end(#)==dvi_four(#) 527@d dvi_put_rule(#)==dvi_out(put_rule); dvi_four(#); dvi_put_rule_end 528@d dvi_right(#)==dvi_out(right4); dvi_four(#); 529@d dvi_left(#)==dvi_out(right4); dvi_four(-#); 530@d dvi_down(#)==dvi_out(down4); dvi_four(#); 531@d dvi_up(#)==dvi_out(down4); dvi_four(-#); 532 533@p procedure movement(@!w:scaled;@!o:eight_bits); 534label exit,found,not_found,2,1; 535var mstate:small_number; {have we seen a |y| or |z|?} 536@!p,@!q:pointer; {current and top nodes on the stack} 537@!k:integer; {index into |dvi_buf|, modulo |dvi_buf_size|} 538begin 539case box_direction(dvi_direction) of 540 dir_TL_: begin 541 end; 542 dir_TR_: begin 543 if o=right1 then negate(w); 544 end; 545 dir_LT_: begin 546 if o=right1 then o:=down1 547 else o:=right1; 548 end; 549 dir_LB_: begin 550 if o=right1 then begin 551 o:=down1; negate(w); 552 end 553 else o:=right1; 554 end; 555 dir_BL_: begin 556 if o=down1 then negate(w); 557 end; 558 dir_BR_: begin 559 negate(w); 560 end; 561 dir_RT_: begin 562 if o=right1 then o:=down1 563 else begin o:=right1; negate(w); 564 end; 565 end; 566 dir_RB_: begin 567 if o=right1 then o:=down1 else o:=right1; 568 negate(w); 569 end; 570 end; 571if false then begin 572q:=get_node(movement_node_size); {new node for the top of the stack} 573width(q):=w; location(q):=dvi_offset+dvi_ptr; 574if o=down1 then 575 begin link(q):=down_ptr; down_ptr:=q; 576 end 577else begin link(q):=right_ptr; right_ptr:=q; 578 end; 579@<Look at the other stack entries until deciding what sort of \.{DVI} command 580 to generate; |goto found| if node |p| is a ``hit''@>; 581end; 582@<Generate a |down| or |right| command for |w| and |return|@>; 583found: @<Generate a |y0| or |z0| command in order to reuse a previous 584 appearance of~|w|@>; 585exit:end; 586@z 587%------------------------- 588@x [32] m.610 589info(q):=yz_OK; 590@y 591@z 592%------------------------- 593@x [32] m.617 594dvi_h:=0; dvi_v:=0; cur_h:=h_offset; dvi_f:=null_font; 595@y 596dvi_h:=0; dvi_v:=0; cur_h:=0; cur_v:=0; dvi_f:=null_font; 597@z 598%------------------------- 599@x [32] m.619 600procedure hlist_out; {output an |hlist_node| box} 601label reswitch, move_past, fin_rule, next_p; 602var base_line: scaled; {the baseline coordinate for this box} 603@y 604procedure hlist_out; {output an |hlist_node| box} 605label reswitch, move_past, fin_rule, next_p; 606var base_line: scaled; {the baseline coordinate for this box} 607c_wd,c_ht,c_dp: scaled; 608 {the real width, height and depth of the character} 609c_htdp: quarterword; {height-depth entry in |char_info|} 610c_info: four_quarters; {|char_info| entry} 611edge_v: scaled; 612edge_h: scaled; 613effective_horizontal: scaled; 614basepoint_horizontal: scaled; 615basepoint_vertical: scaled; 616saving_h: scaled; 617saving_v: scaled; 618save_direction: integer; 619dir_tmp,dir_ptr:pointer; 620dvi_dir_h,dvi_dir_ptr,dvi_temp_ptr:integer; 621@z 622%------------------------- 623@x [32] m.619 624incr(cur_s); 625if cur_s>0 then dvi_out(push); 626if cur_s>max_push then max_push:=cur_s; 627save_loc:=dvi_offset+dvi_ptr; base_line:=cur_v; left_edge:=cur_h; 628while p<>null do @<Output node |p| for |hlist_out| and move to the next node, 629 maintaining the condition |cur_v=base_line|@>; 630prune_movements(save_loc); 631if cur_s>0 then dvi_pop(save_loc); 632decr(cur_s); 633@y 634save_direction:=dvi_direction; 635dvi_direction:=box_dir(this_box); 636@<DIR: Initialize |dir_ptr| for |ship_out|@>; 637saving_h:=dvi_h; saving_v:=dvi_v; 638incr(cur_s); 639if cur_s>0 then dvi_out(push); 640if cur_s>max_push then max_push:=cur_s; 641save_loc:=dvi_offset+dvi_ptr; base_line:=cur_v; left_edge:=cur_h; 642while p<>null do @<Output node |p| for |hlist_out| and move to the next node, 643 maintaining the condition |cur_v=base_line|@>; 644cur_h:=saving_h; cur_v:=saving_v; 645synch_h; synch_v; 646prune_movements(save_loc); 647if cur_s>0 then dvi_pop(save_loc); 648decr(cur_s); 649dvi_direction:=save_direction; 650@<DIR: Reset |dir_ptr|@>; 651@z 652%------------------------- 653@x [32] m.620 654 oval:=c-font_offset(f); ocmd:=set1; out_cmd;@/ 655 cur_h:=cur_h+char_width(f)(char_info(f)(c)); 656@y 657 c_info:=char_info(f)(c); 658 c_htdp:=height_depth(c_info); 659 if is_rotated(dvi_direction) then begin 660 c_ht:=char_width(f)(c_info) div 2; 661 c_wd:=char_height(f)(c_htdp)+char_depth(f)(c_htdp); 662 end 663 else begin 664 c_ht:=char_height(f)(c_htdp); 665 c_dp:=char_depth(f)(c_htdp); 666 c_wd:=char_width(f)(c_info); 667 end; 668 cur_h:=cur_h+c_wd; 669 if (font_natural_dir(f)<>-1) then 670 case font_direction(dvi_direction) of 671 dir__LT,dir__LB: begin 672 dvi_set(c); 673 end; 674 dir__RT,dir__RB: begin 675 dvi_put(c); 676 dvi_left(c_wd); 677 end; 678 dir__TL,dir__TR: begin 679 dvi_put(c); 680 dvi_down(c_wd); 681 end; 682 dir__BL,dir__BR: begin 683 dvi_put(c); 684 dvi_up(c_wd); 685 end; 686 dir__LL,dir__LR: begin 687 dvi_put(c); 688 dvi_right(c_wd); 689 end; 690 dir__RL,dir__RR: begin 691 dvi_put(c); 692 dvi_left(c_wd); 693 end; 694 dir__TT,dir__TB: begin 695 dvi_put(c); 696 dvi_down(c_wd); 697 end; 698 dir__BT,dir__BB: begin 699 dvi_put(c); 700 dvi_up(c_wd); 701 end; 702 end 703 else 704 case font_direction(dvi_direction) of 705 dir__LT: begin 706 dvi_set(c); 707 end; 708 dir__LB: begin 709 dvi_down(c_ht); 710 dvi_set(c); 711 dvi_up(c_ht); 712 end; 713 dir__RT: begin 714 dvi_left(c_wd); 715 dvi_put(c); 716 end; 717 dir__RB: begin 718 dvi_left(c_wd); 719 dvi_down(c_ht); 720 dvi_put(c); 721 dvi_up(c_ht); 722 end; 723 dir__TL: begin 724 dvi_down(c_wd); 725 dvi_left(c_ht); 726 dvi_put(c); 727 dvi_right(c_ht); 728 end; 729 dir__TR: begin 730 dvi_down(c_wd); 731 dvi_left(c_dp); 732 dvi_put(c); 733 dvi_right(c_dp); 734 end; 735 dir__BL: begin 736 dvi_left(c_ht); 737 dvi_put(c); 738 dvi_right(c_ht); 739 dvi_up(c_wd); 740 end; 741 dir__BR: begin 742 dvi_left(c_dp); 743 dvi_put(c); 744 dvi_right(c_dp); 745 dvi_up(c_wd); 746 end; 747 dir__LL,dir__LR: begin 748 dvi_down(c_ht); 749 dvi_put(c); 750 dvi_up(c_ht); 751 dvi_right(c_wd); 752 end; 753 dir__RL,dir__RR: begin 754 dvi_left(c_wd); 755 dvi_down(c_ht); 756 dvi_put(c); 757 dvi_up(c_ht); 758 end; 759 dir__TT,dir__TB: begin 760 dvi_down(c_wd); 761 dvi_left(c_ht); 762 dvi_put(c); 763 dvi_right(c_ht); 764 end; 765 dir__BT,dir__BB: begin 766 dvi_left(c_ht); 767 dvi_put(c); 768 dvi_right(c_ht); 769 dvi_up(c_wd); 770 end; 771 end; 772@z 773%------------------------- 774@x [32] m.622 775rule_node: begin rule_ht:=height(p); rule_dp:=depth(p); rule_wd:=width(p); 776 goto fin_rule; 777 end; 778@y 779rule_node: begin 780 if not (dir_orthogonal(dir_primary[rule_dir(p)])(dir_primary[dvi_direction])) 781 then begin 782 rule_ht:=height(p); rule_dp:=depth(p); rule_wd:=width(p); 783 end 784 else begin 785 rule_ht:=width(p) div 2; 786 rule_dp:=width(p) div 2; 787 rule_wd:=height(p)+depth(p); 788 end; 789 goto fin_rule; 790 end; 791@z 792%------------------------- 793@x [32] m.623 794if list_ptr(p)=null then cur_h:=cur_h+width(p) 795else begin save_h:=dvi_h; save_v:=dvi_v; 796 cur_v:=base_line+shift_amount(p); {shift the box down} 797 temp_ptr:=p; edge:=cur_h; 798 if type(p)=vlist_node then vlist_out@+else hlist_out; 799 dvi_h:=save_h; dvi_v:=save_v; 800 cur_h:=edge+width(p); cur_v:=base_line; 801 end 802@y 803begin 804if not (dir_orthogonal(dir_primary[box_dir(p)])(dir_primary[dvi_direction])) 805 then begin 806 effective_horizontal:=width(p); 807 basepoint_vertical:=0; 808 if dir_opposite(dir_secondary[box_dir(p)])(dir_secondary[dvi_direction]) then 809 basepoint_horizontal:=width(p) 810 else 811 basepoint_horizontal:=0; 812 end 813else begin 814 effective_horizontal:=height(p)+depth(p); 815 if not (is_mirrored(box_dir(p))) then 816 if dir_eq(dir_primary[box_dir(p)])(dir_secondary[dvi_direction]) then 817 basepoint_horizontal:=height(p) 818 else 819 basepoint_horizontal:=depth(p) 820 else 821 if dir_eq(dir_primary[box_dir(p)])(dir_secondary[dvi_direction]) then 822 basepoint_horizontal:=depth(p) 823 else 824 basepoint_horizontal:=height(p); 825 if dir_eq(dir_secondary[box_dir(p)])(dir_primary[dvi_direction]) then 826 basepoint_vertical:= -(width(p) div 2) 827 else 828 basepoint_vertical:= (width(p) div 2); 829 end; 830if not (is_mirrored(dvi_direction)) then 831 basepoint_vertical := basepoint_vertical + shift_amount(p) 832 {shift the box `down'} 833else 834 basepoint_vertical := basepoint_vertical - shift_amount(p); 835 {shift the box `up'} 836if list_ptr(p)=null then cur_h:=cur_h + effective_horizontal 837else begin 838 temp_ptr:=p; edge:=cur_h; cur_h:=cur_h + basepoint_horizontal; 839 edge_v:=cur_v; cur_v:=base_line + basepoint_vertical; 840 synch_h; synch_v; save_h:=dvi_h; save_v:=dvi_v; 841 if type(p)=vlist_node then vlist_out@+else hlist_out; 842 dvi_h:=save_h; dvi_v:=save_v; 843 cur_h:=edge+effective_horizontal; cur_v:=base_line; 844 end 845end 846@z 847%------------------------- 848@x [32] m.624 849 dvi_out(set_rule); dvi_four(rule_ht); dvi_four(rule_wd); 850@y 851 case font_direction(dvi_direction) of 852 dir__LT: begin 853 dvi_set_rule(rule_ht)(rule_wd); 854 end; 855 dir__LB: begin 856 dvi_down(rule_ht); 857 dvi_set_rule(rule_ht)(rule_wd); 858 dvi_up(rule_ht); 859 end; 860 dir__RT: begin 861 dvi_left(rule_wd); 862 dvi_put_rule(rule_ht)(rule_wd); 863 end; 864 dir__RB: begin 865 dvi_left(rule_wd); 866 dvi_down(rule_ht); 867 dvi_put_rule(rule_ht)(rule_wd); 868 dvi_up(rule_ht); 869 end; 870 dir__TL: begin 871 dvi_down(rule_wd); 872 dvi_left(rule_ht); 873 dvi_set_rule(rule_wd)(rule_ht); 874 end; 875 dir__TR: begin 876 dvi_down(rule_wd); 877 dvi_put_rule(rule_wd)(rule_ht); 878 end; 879 dir__BL: begin 880 dvi_left(rule_ht); 881 dvi_set_rule(rule_wd)(rule_ht); 882 dvi_up(rule_wd); 883 end; 884 dir__BR: begin 885 dvi_put_rule(rule_wd)(rule_ht); 886 dvi_up(rule_wd); 887 end; 888 end; 889@z 890%------------------------- 891@x [32] m.626 892leader_wd:=width(leader_box); 893@y 894if not (dir_orthogonal(dir_primary[box_dir(leader_box)])(dir_primary[dvi_direction])) 895 then leader_wd:=width(leader_box) 896else 897 leader_wd:=height(leader_box)+depth(leader_box); 898@z 899------------------------- 900@x [32] m.628 901@<Output a leader box at |cur_h|, ...@>= 902begin cur_v:=base_line+shift_amount(leader_box); synch_v; save_v:=dvi_v;@/ 903synch_h; save_h:=dvi_h; temp_ptr:=leader_box; 904outer_doing_leaders:=doing_leaders; doing_leaders:=true; 905if type(leader_box)=vlist_node then vlist_out@+else hlist_out; 906doing_leaders:=outer_doing_leaders; 907dvi_v:=save_v; dvi_h:=save_h; cur_v:=base_line; 908cur_h:=save_h+leader_wd+lx; 909end 910@y 911@<Output a leader box at |cur_h|, ...@>= 912begin 913if not (dir_orthogonal(dir_primary[box_dir(leader_box)])(dir_primary[dvi_direction])) 914 then begin 915 basepoint_vertical:=0; 916 if dir_opposite(dir_secondary[box_dir(leader_box)])(dir_secondary[dvi_direction]) then 917 basepoint_horizontal:=width(leader_box) 918 else 919 basepoint_horizontal:=0; 920 end 921else begin 922 if not (is_mirrored(box_dir(leader_box))) then 923 if dir_eq(dir_primary[box_dir(leader_box)])(dir_secondary[dvi_direction]) then 924 basepoint_horizontal:=height(leader_box) 925 else 926 basepoint_horizontal:=depth(leader_box) 927 else 928 if dir_eq(dir_primary[box_dir(leader_box)])(dir_secondary[dvi_direction]) then 929 basepoint_horizontal:=depth(leader_box) 930 else 931 basepoint_horizontal:=height(leader_box); 932 if dir_eq(dir_secondary[box_dir(leader_box)])(dir_primary[dvi_direction]) then 933 basepoint_vertical:= -(width(leader_box) div 2) 934 else 935 basepoint_vertical:= (width(leader_box) div 2); 936 end; 937if not (is_mirrored(dvi_direction)) then 938 basepoint_vertical := basepoint_vertical + shift_amount(leader_box) 939 {shift the box `down'} 940else 941 basepoint_vertical := basepoint_vertical - shift_amount(leader_box); 942 {shift the box `up'} 943temp_ptr:=leader_box; 944edge_h:=cur_h; cur_h:=cur_h + basepoint_horizontal; 945edge_v:=cur_v; cur_v:=base_line + basepoint_vertical; 946synch_h; synch_v; save_h:=dvi_h; save_v:=dvi_v; 947outer_doing_leaders:=doing_leaders; doing_leaders:=true; 948if type(leader_box)=vlist_node then vlist_out@+else hlist_out; 949doing_leaders:=outer_doing_leaders; 950dvi_h:=save_h; dvi_v:=save_v; 951cur_h:=edge_h+leader_wd+lx; cur_v:=base_line; 952end 953@z 954%------------------------- 955@x [32] m.629 956@!glue_temp:real; {glue value before rounding} 957@!cur_glue:real; {glue seen so far} 958@!cur_g:scaled; {rounded equivalent of |cur_glue| times the glue ratio} 959begin cur_g:=0; cur_glue:=float_constant(0); 960this_box:=temp_ptr; g_order:=glue_order(this_box); 961g_sign:=glue_sign(this_box); p:=list_ptr(this_box); 962incr(cur_s); 963if cur_s>0 then dvi_out(push); 964if cur_s>max_push then max_push:=cur_s; 965save_loc:=dvi_offset+dvi_ptr; left_edge:=cur_h; cur_v:=cur_v-height(this_box); 966top_edge:=cur_v; 967while p<>null do @<Output node |p| for |vlist_out| and move to the next node, 968 maintaining the condition |cur_h=left_edge|@>; 969prune_movements(save_loc); 970if cur_s>0 then dvi_pop(save_loc); 971decr(cur_s); 972@y 973@!glue_temp:real; {glue value before rounding} 974@!cur_glue:real; {glue seen so far} 975@!cur_g:scaled; {rounded equivalent of |cur_glue| times the glue ratio} 976@!save_direction: integer; 977@!effective_vertical: scaled; 978@!basepoint_horizontal: scaled; 979@!basepoint_vertical: scaled; 980@!edge_v: scaled; 981@!saving_v: scaled; 982@!saving_h: scaled; 983begin cur_g:=0; cur_glue:=float_constant(0); 984this_box:=temp_ptr; g_order:=glue_order(this_box); 985g_sign:=glue_sign(this_box); p:=list_ptr(this_box); 986saving_v:=dvi_v; saving_h:=dvi_h; 987save_direction:=dvi_direction; 988dvi_direction:=box_dir(this_box); 989incr(cur_s); 990if cur_s>0 then dvi_out(push); 991if cur_s>max_push then max_push:=cur_s; 992save_loc:=dvi_offset+dvi_ptr; left_edge:=cur_h; cur_v:=cur_v-height(this_box); 993top_edge:=cur_v; 994while p<>null do @<Output node |p| for |vlist_out| and move to the next node, 995 maintaining the condition |cur_h=left_edge|@>; 996cur_v:=saving_v; cur_h:=saving_h; 997synch_v; synch_h; 998prune_movements(save_loc); 999if cur_s>0 then dvi_pop(save_loc); 1000decr(cur_s); 1001dvi_direction:=save_direction; 1002@z 1003%------------------------- 1004@x [32] m.631 1005rule_node: begin rule_ht:=height(p); rule_dp:=depth(p); rule_wd:=width(p); 1006 goto fin_rule; 1007 end; 1008@y 1009rule_node: begin 1010 if not (dir_orthogonal(dir_primary[rule_dir(p)])(dir_primary[dvi_direction])) 1011 then begin 1012 rule_ht:=height(p); rule_dp:=depth(p); rule_wd:=width(p); 1013 end 1014 else begin 1015 rule_ht:=width(p) div 2; 1016 rule_dp:=width(p) div 2; 1017 rule_wd:=height(p)+depth(p); 1018 end; 1019 goto fin_rule; 1020 end; 1021@z 1022%------------------------- 1023@x [32] m.632 1024@<Output a box in a vlist@>= 1025if list_ptr(p)=null then cur_v:=cur_v+height(p)+depth(p) 1026else begin cur_v:=cur_v+height(p); synch_v; 1027 save_h:=dvi_h; save_v:=dvi_v; 1028 cur_h:=left_edge+shift_amount(p); {shift the box right} 1029 temp_ptr:=p; 1030 if type(p)=vlist_node then vlist_out@+else hlist_out; 1031 dvi_h:=save_h; dvi_v:=save_v; 1032 cur_v:=save_v+depth(p); cur_h:=left_edge; 1033 end 1034@y 1035@<Output a box in a vlist@>= 1036begin 1037if not (dir_orthogonal(dir_primary[box_dir(p)])(dir_primary[dvi_direction])) 1038 then begin 1039 effective_vertical:=height(p)+depth(p); 1040 if (type(p)=hlist_node) and (is_mirrored(box_dir(p))) then 1041 basepoint_vertical:=depth(p) 1042 else 1043 basepoint_vertical:=height(p); 1044 if dir_opposite(dir_secondary[box_dir(p)])(dir_secondary[dvi_direction]) then 1045 basepoint_horizontal:=width(p) 1046 else 1047 basepoint_horizontal:=0; 1048 end 1049else begin 1050 effective_vertical:=width(p); 1051 if not (is_mirrored(box_dir(p))) then 1052 if dir_eq(dir_primary[box_dir(p)])(dir_secondary[dvi_direction]) then 1053 basepoint_horizontal:=height(p) 1054 else 1055 basepoint_horizontal:=depth(p) 1056 else 1057 if dir_eq(dir_primary[box_dir(p)])(dir_secondary[dvi_direction]) then 1058 basepoint_horizontal:=depth(p) 1059 else 1060 basepoint_horizontal:=height(p); 1061 if dir_eq(dir_secondary[box_dir(p)])(dir_primary[dvi_direction]) then 1062 basepoint_vertical:=0 1063 else 1064 basepoint_vertical:=width(p); 1065 end; 1066basepoint_horizontal := basepoint_horizontal + shift_amount(p); 1067 {shift the box `right'} 1068if list_ptr(p)=null then begin 1069 cur_v:=cur_v+effective_vertical; 1070 end 1071else begin 1072 synch_h; synch_v; edge_v:=cur_v; 1073 cur_h:=left_edge + basepoint_horizontal; 1074 cur_v:=cur_v + basepoint_vertical; 1075 synch_h; synch_v; save_h:=dvi_h; save_v:=dvi_v; 1076 temp_ptr:=p; 1077 if type(p)=vlist_node then vlist_out@+else hlist_out; 1078 dvi_h:=save_h; dvi_v:=save_v; 1079 cur_h:=left_edge; cur_v:=edge_v + effective_vertical; 1080 end 1081end 1082@z 1083%------------------------- 1084@x [32] m.633 1085 dvi_out(put_rule); dvi_four(rule_ht); dvi_four(rule_wd); 1086@y 1087 case font_direction(dvi_direction) of 1088 dir__LT: begin 1089 dvi_put_rule(rule_ht)(rule_wd); 1090 end; 1091 dir__LB: begin 1092 dvi_down(rule_ht); 1093 dvi_put_rule(rule_ht)(rule_wd); 1094 dvi_up(rule_ht); 1095 end; 1096 dir__RT: begin 1097 dvi_left(rule_wd); 1098 dvi_set_rule(rule_ht)(rule_wd); 1099 end; 1100 dir__RB: begin 1101 dvi_down(rule_ht); 1102 dvi_left(rule_wd); 1103 dvi_set_rule(rule_ht)(rule_wd); 1104 dvi_up(rule_ht); 1105 end; 1106 dir__TL: begin 1107 dvi_down(rule_wd); 1108 dvi_left(rule_ht); 1109 dvi_set_rule(rule_wd)(rule_ht); 1110 dvi_up(rule_wd); 1111 end; 1112 dir__TR: begin 1113 dvi_down(rule_wd); 1114 dvi_put_rule(rule_wd)(rule_ht); 1115 dvi_up(rule_wd); 1116 end; 1117 dir__BL: begin 1118 dvi_left(rule_ht); 1119 dvi_set_rule(rule_wd)(rule_ht); 1120 end; 1121 dir__BR: begin 1122 dvi_put_rule(rule_wd)(rule_ht); 1123 end; 1124 end; 1125@z 1126%------------------------- 1127@x [32] m.635 1128leader_ht:=height(leader_box)+depth(leader_box); 1129@y 1130if not (dir_orthogonal(dir_primary[box_dir(leader_box)])(dir_primary[dvi_direction])) 1131 then leader_ht:=height(leader_box)+depth(leader_box) 1132else 1133 leader_ht:=width(leader_box); 1134@z 1135%------------------------- 1136@x [32] m.637 1137@<Output a leader box at |cur_v|, ...@>= 1138begin cur_h:=left_edge+shift_amount(leader_box); synch_h; save_h:=dvi_h;@/ 1139cur_v:=cur_v+height(leader_box); synch_v; save_v:=dvi_v; 1140temp_ptr:=leader_box; 1141outer_doing_leaders:=doing_leaders; doing_leaders:=true; 1142if type(leader_box)=vlist_node then vlist_out@+else hlist_out; 1143doing_leaders:=outer_doing_leaders; 1144dvi_v:=save_v; dvi_h:=save_h; cur_h:=left_edge; 1145cur_v:=save_v-height(leader_box)+leader_ht+lx; 1146end 1147@y 1148@<Output a leader box at |cur_v|, ...@>= 1149begin 1150if not (dir_orthogonal(dir_primary[box_dir(leader_box)])(dir_primary[dvi_direction])) 1151 then begin 1152 effective_vertical:=height(leader_box)+depth(leader_box); 1153 if (type(leader_box)=hlist_node) and (is_mirrored(box_dir(leader_box))) then 1154 basepoint_vertical:=depth(leader_box) 1155 else 1156 basepoint_vertical:=height(leader_box); 1157 if dir_opposite(dir_secondary[box_dir(leader_box)])(dir_secondary[dvi_direction]) then 1158 basepoint_horizontal:=width(leader_box) 1159 else 1160 basepoint_horizontal:=0; 1161 end 1162else begin 1163 effective_vertical:=width(leader_box); 1164 if not (is_mirrored(box_dir(leader_box))) then 1165 if dir_eq(dir_primary[box_dir(leader_box)])(dir_secondary[dvi_direction]) then 1166 basepoint_horizontal:=height(leader_box) 1167 else 1168 basepoint_horizontal:=depth(leader_box) 1169 else 1170 if dir_eq(dir_primary[box_dir(leader_box)])(dir_secondary[dvi_direction]) then 1171 basepoint_horizontal:=depth(leader_box) 1172 else 1173 basepoint_horizontal:=height(leader_box); 1174 if dir_eq(dir_secondary[box_dir(leader_box)])(dir_primary[dvi_direction]) then 1175 basepoint_vertical:= width(leader_box) 1176 else 1177 basepoint_vertical:= 0; 1178 end; 1179basepoint_horizontal := basepoint_horizontal + shift_amount(leader_box); 1180 {shift the box `right'} 1181temp_ptr:=leader_box; 1182cur_h:=left_edge + basepoint_horizontal; 1183edge_v:=cur_v ; 1184cur_v:=cur_v + basepoint_vertical; 1185synch_h; synch_v; save_h:=dvi_h; save_v:=dvi_v; 1186outer_doing_leaders:=doing_leaders; doing_leaders:=true; 1187if type(leader_box)=vlist_node then vlist_out@+else hlist_out; 1188doing_leaders:=outer_doing_leaders; 1189dvi_h:=save_h; dvi_v:=save_v; 1190cur_h:=left_edge; cur_v:=edge_v+leader_ht+lx; 1191end 1192@z 1193%------------------------- 1194@x [32] m.640 1195cur_v:=height(p)+v_offset; temp_ptr:=p; 1196if type(p)=vlist_node then vlist_out@+else hlist_out; 1197@y 1198dvi_direction:=page_direction; 1199case box_direction(dvi_direction) of 1200dir_TL_,dir_LT_: begin 1201 end; 1202dir_TR_,dir_RT_: begin 1203 dvi_right(page_right_offset); 1204 end; 1205dir_RB_,dir_BR_: begin 1206 dvi_right(page_right_offset); 1207 dvi_down(page_bottom_offset); 1208 end; 1209dir_BL_,dir_LB_: begin 1210 dvi_down(page_bottom_offset); 1211 end; 1212end; 1213cur_h:=h_offset; 1214cur_v:=height(p)+v_offset; 1215case box_direction(dvi_direction) of 1216dir_TL_: begin 1217 dvi_down(cur_v); 1218 dvi_right(cur_h); 1219 end; 1220dir_TR_: begin 1221 dvi_down(cur_v); 1222 dvi_right(-cur_h); 1223 end; 1224dir_LT_: begin 1225 dvi_right(cur_v); 1226 dvi_down(cur_h); 1227 end; 1228dir_LB_: begin 1229 dvi_right(cur_v); 1230 dvi_down(-cur_h); 1231 end; 1232dir_BL_: begin 1233 dvi_down(-cur_v); 1234 dvi_right(cur_h); 1235 end; 1236dir_BR_: begin 1237 dvi_down(-cur_v); 1238 dvi_right(-cur_h); 1239 end; 1240dir_RT_: begin 1241 dvi_right(-cur_v); 1242 dvi_down(cur_h); 1243 end; 1244dir_RB_: begin 1245 dvi_right(-cur_v); 1246 dvi_down(-cur_h); 1247 end; 1248end; 1249dvi_h:=cur_h; 1250dvi_v:=cur_v; 1251temp_ptr:=p; 1252if type(p)=vlist_node then vlist_out@+else hlist_out; 1253@z 1254%------------------------- 1255@x [33] m.644 1256@d exactly=0 {a box dimension is pre-specified} 1257@d additional=1 {a box dimension is increased from the natural one} 1258@d natural==0,additional {shorthand for parameters to |hpack| and |vpack|} 1259@y 1260@d exactly=0 {a box dimension is pre-specified} 1261@d additional=1 {a box dimension is increased from the natural one} 1262@d natural==0,additional {shorthand for parameters to |hpack| and |vpack|} 1263 1264@<Glob...@>= 1265pack_direction:integer; 1266spec_direction:integer; 1267 1268@z 1269%------------------------- 1270@x [33] m.645 1271@p procedure scan_spec(@!c:group_code;@!three_codes:boolean); 1272 {scans a box specification and left brace} 1273label found; 1274var @!s:integer; {temporarily saved value} 1275@!spec_code:exactly..additional; 1276begin if three_codes then s:=saved(0); 1277if scan_keyword("to") then spec_code:=exactly 1278@.to@> 1279else if scan_keyword("spread") then spec_code:=additional 1280@.spread@> 1281else begin spec_code:=additional; cur_val:=0; 1282 goto found; 1283 end; 1284scan_normal_dimen; 1285found: if three_codes then 1286 begin saved(0):=s; incr(save_ptr); 1287 end; 1288saved(0):=spec_code; saved(1):=cur_val; save_ptr:=save_ptr+2; 1289new_save_level(c); scan_left_brace; 1290end; 1291@y 1292@p procedure scan_spec(@!c:group_code;@!three_codes:boolean); 1293 {scans a box specification and left brace} 1294label found; 1295var @!s:integer; {temporarily saved value} 1296@!spec_code:exactly..additional; 1297begin if three_codes then s:=saved(0); 1298if (c<>align_group) and (c<>vcenter_group) then begin 1299 if scan_keyword("dir") then begin 1300 scan_dir; spec_direction:=cur_val; 1301 end; 1302 end; 1303if scan_keyword("to") then spec_code:=exactly 1304@.to@> 1305else if scan_keyword("spread") then spec_code:=additional 1306@.spread@> 1307else begin spec_code:=additional; cur_val:=0; 1308 goto found; 1309 end; 1310scan_normal_dimen; 1311found: if three_codes then 1312 begin saved(0):=s; incr(save_ptr); 1313 end; 1314saved(0):=spec_code; saved(1):=cur_val; 1315if (c<>align_group) and (c<>vcenter_group) then begin 1316 saved(2):=spec_direction; 1317 @<DIR: Adjust |text_dir_ptr| for |scan_spec|@>; 1318 save_ptr:=save_ptr+4; 1319 new_save_level(c); scan_left_brace; 1320 eq_word_define(dir_base+body_direction_code,spec_direction); 1321 eq_word_define(dir_base+par_direction_code,spec_direction); 1322 eq_word_define(dir_base+text_direction_code,spec_direction); 1323 eq_word_define(int_base+level_local_dir_code,cur_level); 1324 end 1325else begin 1326 save_ptr:=save_ptr+2; 1327 new_save_level(c); scan_left_brace; 1328 end; 1329spec_direction:=-1; 1330end; 1331@z 1332%------------------------- 1333@x [33] m.649 1334@p function hpack(@!p:pointer;@!w:scaled;@!m:small_number):pointer; 1335label reswitch, common_ending, exit; 1336var r:pointer; {the box node that will be returned} 1337@!q:pointer; {trails behind |p|} 1338@!h,@!d,@!x:scaled; {height, depth, and natural width} 1339@!s:scaled; {shift amount} 1340@!g:pointer; {points to a glue specification} 1341@!o:glue_ord; {order of infinity} 1342@!f:internal_font_number; {the font in a |char_node|} 1343@!i:four_quarters; {font information about a |char_node|} 1344@!hd:eight_bits; {height and depth indices for a character} 1345begin last_badness:=0; r:=get_node(box_node_size); type(r):=hlist_node; 1346@y 1347@p function hpack(@!p:pointer;@!w:scaled;@!m:small_number):pointer; 1348label reswitch, common_ending, exit; 1349var r:pointer; {the box node that will be returned} 1350@!q:pointer; {trails behind |p|} 1351@!h,@!d,@!x:scaled; {height, depth, and natural width} 1352@!s:scaled; {shift amount} 1353@!g:pointer; {points to a glue specification} 1354@!o:glue_ord; {order of infinity} 1355@!f:internal_font_number; {the font in a |char_node|} 1356@!i:four_quarters; {font information about a |char_node|} 1357@!hd:eight_bits; {height and depth indices for a character} 1358@!dir_tmp,@!dir_ptr:pointer; {for managing the direction stack} 1359@!hpack_dir:integer; {the current direction} 1360begin last_badness:=0; r:=get_node(box_node_size); type(r):=hlist_node; 1361if pack_direction=-1 then 1362 box_dir(r):=text_direction 1363else begin 1364 box_dir(r):=pack_direction; pack_direction:=-1; 1365 end; 1366hpack_dir:=box_dir(r); 1367@<DIR: Initialize |dir_ptr| for |hpack|@>; 1368@z 1369%------------------------- 1370@x [33] m.649 1371exit: hpack:=r; 1372@y 1373exit: 1374@<DIR: Reset |dir_ptr|@>; 1375hpack:=r; 1376@z 1377%------------------------- 1378@x [33] m.653 1379@<Incorporate box dimensions into the dimensions of the hbox...@>= 1380begin x:=x+width(p); 1381if type(p)>=rule_node then s:=0 @+else s:=shift_amount(p); 1382if height(p)-s>h then h:=height(p)-s; 1383if depth(p)+s>d then d:=depth(p)+s; 1384end 1385@y 1386@<Incorporate box dimensions into the dimensions of the hbox...@>= 1387begin 1388if (type(p)=hlist_node) or (type(p)=vlist_node) then begin 1389 if dir_orthogonal(dir_primary[box_dir(p)])(dir_primary[hpack_dir]) then begin 1390 x:=x+height(p)+depth(p); 1391 s:=shift_amount(p); 1392 if (width(p) div 2)-s>h then h:=(width(p) div 2)-s; 1393 if (width(p) div 2)+s>d then d:=(width(p) div 2)+s; 1394 end 1395 else if (type(p)=hlist_node) and (is_mirrored(hpack_dir)) then begin 1396 x:=x+width(p); 1397 s:=shift_amount(p); 1398 if depth(p)-s>h then h:=depth(p)-s; 1399 if height(p)+s>d then d:=height(p)+s; 1400 end 1401 else begin 1402 x:=x+width(p); 1403 s:=shift_amount(p); 1404 if height(p)-s>h then h:=height(p)-s; 1405 if depth(p)+s>d then d:=depth(p)+s; 1406 end 1407 end 1408else begin 1409 x:=x+width(p); 1410 if type(p)>=rule_node then s:=0 @+else s:=shift_amount(p); 1411 if height(p)-s>h then h:=height(p)-s; 1412 if depth(p)+s>d then d:=depth(p)+s; 1413 end; 1414end 1415@z 1416%------------------------- 1417@x [33] m.654 1418@<Incorporate character dimensions into the dimensions of the hbox...@>= 1419begin f:=font(p); i:=char_info(f)(character(p)); hd:=height_depth(i); 1420x:=x+char_width(f)(i);@/ 1421s:=char_height(f)(hd);@+if s>h then h:=s; 1422s:=char_depth(f)(hd);@+if s>d then d:=s; 1423p:=link(p); 1424end 1425@y 1426@<Incorporate character dimensions into the dimensions of the hbox...@>= 1427begin f:=font(p); i:=char_info(f)(character(p)); hd:=height_depth(i); 1428if is_rotated(hpack_dir) then begin 1429 x:=x+char_height(f)(hd)+char_depth(f)(hd);@/ 1430 s:=char_width(f)(i) div 2;@+if s>h then h:=s; 1431 s:=char_width(f)(i) div 2;@+if s>d then d:=s; 1432 end 1433else if dir_opposite(dir_tertiary[hpack_dir])(dir_tertiary[box_dir(r)]) 1434 then begin 1435 x:=x+char_width(f)(i);@/ 1436 s:=char_depth(f)(hd);@+if s>h then h:=s; 1437 s:=char_height(f)(hd);@+if s>d then d:=s; 1438 end 1439else begin 1440 x:=x+char_width(f)(i);@/ 1441 s:=char_height(f)(hd);@+if s>h then h:=s; 1442 s:=char_depth(f)(hd);@+if s>d then d:=s; 1443 end; 1444p:=link(p); 1445end 1446@z 1447%------------------------- 1448@x [33] m.666 1449@ @<Report an overfull hbox and |goto common_ending|, if...@>= 1450if (-x-total_shrink[normal]>hfuzz)or(hbadness<100) then 1451 begin if (overfull_rule>0)and(-x-total_shrink[normal]>hfuzz) then 1452 begin while link(q)<>null do q:=link(q); 1453 link(q):=new_rule; 1454 width(link(q)):=overfull_rule; 1455 end; 1456@y 1457@ @<Report an overfull hbox and |goto common_ending|, if...@>= 1458if (-x-total_shrink[normal]>hfuzz)or(hbadness<100) then 1459 begin if (overfull_rule>0)and(-x-total_shrink[normal]>hfuzz) then 1460 begin while link(q)<>null do q:=link(q); 1461 link(q):=new_rule; rule_dir(link(q)):=box_dir(r); 1462 width(link(q)):=overfull_rule; 1463 end; 1464@z 1465%------------------------- 1466@x [33] m.668 1467@p function vpackage(@!p:pointer;@!h:scaled;@!m:small_number;@!l:scaled): 1468 pointer; 1469label common_ending, exit; 1470var r:pointer; {the box node that will be returned} 1471@!w,@!d,@!x:scaled; {width, depth, and natural height} 1472@!s:scaled; {shift amount} 1473@!g:pointer; {points to a glue specification} 1474@!o:glue_ord; {order of infinity} 1475begin last_badness:=0; r:=get_node(box_node_size); type(r):=vlist_node; 1476@y 1477@p function vpackage(@!p:pointer;@!h:scaled;@!m:small_number;@!l:scaled): 1478 pointer; 1479label common_ending, exit; 1480var r:pointer; {the box node that will be returned} 1481@!w,@!d,@!x:scaled; {width, depth, and natural height} 1482@!s:scaled; {shift amount} 1483@!g:pointer; {points to a glue specification} 1484@!o:glue_ord; {order of infinity} 1485begin last_badness:=0; r:=get_node(box_node_size); type(r):=vlist_node; 1486if pack_direction=-1 then 1487 box_dir(r):=body_direction 1488else begin 1489 box_dir(r):=pack_direction; pack_direction:=-1; 1490 end; 1491@z 1492%------------------------- 1493@x [33] m.670 1494@ @<Incorporate box dimensions into the dimensions of the vbox...@>= 1495begin x:=x+d+height(p); d:=depth(p); 1496if type(p)>=rule_node then s:=0 @+else s:=shift_amount(p); 1497if width(p)+s>w then w:=width(p)+s; 1498end 1499@y 1500@ @<Incorporate box dimensions into the dimensions of the vbox...@>= 1501begin 1502if (type(p)=hlist_node) or (type(p)=vlist_node) then begin 1503 if dir_orthogonal(dir_primary[box_dir(p)])(dir_primary[box_dir(r)]) then begin 1504 x:=x+d+(width(p) div 2); d:=width(p) div 2; 1505 s:=shift_amount(p); 1506 if depth(p)+height(p)+s>w then w:=depth(p)+height(p)+s; 1507 end 1508 else if (type(p)=hlist_node) and (is_mirrored(box_dir(p))) then begin 1509 x:=x+d+depth(p); d:=height(p); 1510 s:=shift_amount(p); 1511 if width(p)+s>w then w:=width(p)+s; 1512 end 1513 else begin 1514 x:=x+d+height(p); d:=depth(p); 1515 s:=shift_amount(p); 1516 if width(p)+s>w then w:=width(p)+s; 1517 end 1518 end 1519else 1520 begin x:=x+d+height(p); d:=depth(p); 1521 if type(p)>=rule_node then s:=0 @+else s:=shift_amount(p); 1522 if width(p)+s>w then w:=width(p)+s; 1523 end; 1524end 1525@z 1526%------------------------- 1527@x [33] m.679 1528 begin d:=width(baseline_skip)-prev_depth-height(b); 1529 if d<line_skip_limit then p:=new_param_glue(line_skip_code) 1530 else begin p:=new_skip_param(baseline_skip_code); 1531 width(temp_ptr):=d; {|temp_ptr=glue_ptr(p)|} 1532 end; 1533 link(tail):=p; tail:=p; 1534 end; 1535link(tail):=b; tail:=b; prev_depth:=depth(b); 1536@y 1537 begin 1538 if (type(b)=hlist_node) and (is_mirrored(box_dir(b))) then 1539 d:=width(baseline_skip)-prev_depth-depth(b) 1540 else 1541 d:=width(baseline_skip)-prev_depth-height(b); 1542 if d<line_skip_limit then p:=new_param_glue(line_skip_code) 1543 else begin p:=new_skip_param(baseline_skip_code); 1544 width(temp_ptr):=d; {|temp_ptr=glue_ptr(p)|} 1545 end; 1546 link(tail):=p; tail:=p; 1547 end; 1548link(tail):=b; tail:=b; 1549if (type(b)=hlist_node) and (is_mirrored(box_dir(b))) then 1550 prev_depth:=height(b) 1551else 1552 prev_depth:=depth(b); 1553@z 1554%------------------------- 1555@x [35] m.704 1556@p function fraction_rule(@!t:scaled):pointer; 1557 {construct the bar for a fraction} 1558var p:pointer; {the new node} 1559begin p:=new_rule; height(p):=t; depth(p):=0; fraction_rule:=p; 1560end; 1561@y 1562@p function fraction_rule(@!t:scaled):pointer; 1563 {construct the bar for a fraction} 1564var p:pointer; {the new node} 1565begin p:=new_rule; rule_dir(p):=math_direction; 1566height(p):=t; depth(p):=0; fraction_rule:=p; 1567end; 1568@z 1569%------------------------- 1570@x [35] m.705 1571@p function overbar(@!b:pointer;@!k,@!t:scaled):pointer; 1572var p,@!q:pointer; {nodes being constructed} 1573begin p:=new_kern(k); link(p):=b; q:=fraction_rule(t); link(q):=p; 1574p:=new_kern(t); link(p):=q; overbar:=vpack(p,natural); 1575end; 1576@y 1577@p function overbar(@!b:pointer;@!k,@!t:scaled):pointer; 1578var p,@!q:pointer; {nodes being constructed} 1579begin p:=new_kern(k); link(p):=b; q:=fraction_rule(t); link(q):=p; 1580p:=new_kern(t); link(p):=q; 1581pack_direction:=math_direction; overbar:=vpack(p,natural); 1582end; 1583@z 1584%------------------------- 1585@x [36] m.735 1586procedure make_under(@!q:pointer); 1587var p,@!x,@!y: pointer; {temporary registers for box construction} 1588@!delta:scaled; {overall height plus depth} 1589begin x:=clean_box(nucleus(q),cur_style); 1590p:=new_kern(3*default_rule_thickness); link(x):=p; 1591link(p):=fraction_rule(default_rule_thickness); 1592y:=vpack(x,natural); 1593delta:=height(y)+depth(y)+default_rule_thickness; 1594height(y):=height(x); depth(y):=delta-height(y); 1595info(nucleus(q)):=y; math_type(nucleus(q)):=sub_box; 1596end; 1597@y 1598procedure make_under(@!q:pointer); 1599var p,@!x,@!y: pointer; {temporary registers for box construction} 1600@!delta:scaled; {overall height plus depth} 1601begin x:=clean_box(nucleus(q),cur_style); 1602p:=new_kern(3*default_rule_thickness); link(x):=p; 1603link(p):=fraction_rule(default_rule_thickness); 1604pack_direction:=math_direction; y:=vpack(x,natural); 1605delta:=height(y)+depth(y)+default_rule_thickness; 1606height(y):=height(x); depth(y):=delta-height(y); 1607info(nucleus(q)):=y; math_type(nucleus(q)):=sub_box; 1608end; 1609@z 1610%------------------------- 1611@x [36] m.738 1612 y:=vpack(y,natural); width(y):=width(x); 1613@y 1614 pack_direction:=math_direction; 1615 y:=vpack(y,natural); width(y):=width(x); 1616@z 1617%------------------------- 1618@x [36] m.759 1619x:=vpack(x,natural); shift_amount(x):=shift_down; 1620@y 1621pack_direction:=math_direction; 1622x:=vpack(x,natural); shift_amount(x):=shift_down; 1623@z 1624%------------------------- 1625@x [38] m.814 1626@!internal_right_box_width:integer; {running \.{\\localrightbox} width} 1627@!temp_no_whatsits:integer; {used when closing group} 1628 1629@ @<Set init...@>= 1630@y 1631@!internal_right_box_width:integer; {running \.{\\localrightbox} width} 1632@!paragraph_dir:integer; {main direction of paragraph} 1633@!line_break_dir:integer; {current direction within paragraph} 1634@!break_c_htdp:quarterword; {height-depth entry in |char_info|} 1635@!temp_no_whatsits:integer; {used when closing group} 1636@!temp_no_dirs:integer; {used when closing group} 1637@!temporary_dir:integer; 1638@!dir_ptr,@!dir_tmp,@!dir_rover:pointer; 1639 1640@ @<Set init...@>= 1641temp_no_whatsits:=0; temp_no_dirs:=0; temporary_dir:=0; 1642dir_ptr:=null; dir_tmp:=null; dir_rover:=null; 1643@z 1644%------------------------- 1645@x [39] m.816 1646link(tail):=new_param_glue(par_fill_skip_code); 1647@y 1648final_par_glue:=new_param_glue(par_fill_skip_code); 1649link(tail):=final_par_glue; 1650@z 1651%------------------------- 1652@x [38] m.816 1653init_cur_lang:=prev_graf mod @'200000; 1654init_l_hyf:=prev_graf div @'20000000; 1655init_r_hyf:=(prev_graf div @'200000) mod @'100; 1656@y 1657init_cur_lang:=prev_graf mod @'200000; 1658init_l_hyf:=prev_graf div @'20000000; 1659init_r_hyf:=(prev_graf div @'200000) mod @'100; 1660paragraph_dir:=local_par_dir(link(head)); 1661line_break_dir:=paragraph_dir; 1662@<DIR: Initialize |dir_ptr| for |line_break|@>; 1663@z 1664%------------------------- 1665@x [39] m.821 1666@!pass_number:halfword; {the number of passive nodes allocated on this pass} 1667@y 1668@!pass_number:halfword; {the number of passive nodes allocated on this pass} 1669@!final_par_glue:pointer; 1670@z 1671%------------------------- 1672@x [38] m.841 1673@<Subtract the width of node |v|...@>= 1674if is_char_node(v) then 1675 begin f:=font(v); 1676 break_width[1]:=break_width[1]-char_width(f)(char_info(f)(character(v))); 1677 end 1678else case type(v) of 1679 ligature_node: begin f:=font(lig_char(v));@/ 1680 break_width[1]:=@|break_width[1]- 1681 char_width(f)(char_info(f)(character(lig_char(v)))); 1682 end; 1683 hlist_node,vlist_node,rule_node,kern_node: 1684 break_width[1]:=break_width[1]-width(v); 1685@y 1686@<Subtract the width of node |v|...@>= 1687if is_char_node(v) then 1688 begin f:=font(v); 1689 if is_rotated(line_break_dir) then begin 1690 break_c_htdp:=height_depth(char_info(f)(character(v))); 1691 break_width[1]:=break_width[1]-char_height(f)(break_c_htdp) 1692 -char_depth(f)(break_c_htdp); 1693 end 1694 else 1695 break_width[1]:=break_width[1]-char_width(f)(char_info(f)(character(v))); 1696 end 1697else case type(v) of 1698 ligature_node: begin f:=font(lig_char(v));@/ 1699 if is_rotated(line_break_dir) then begin 1700 break_c_htdp:=height_depth(char_info(f)(character(lig_char(v)))); 1701 break_width[1]:=break_width[1]-char_height(f)(break_c_htdp) 1702 -char_depth(f)(break_c_htdp); 1703 end 1704 else 1705 break_width[1]:=@|break_width[1]- 1706 char_width(f)(char_info(f)(character(lig_char(v)))); 1707 end; 1708 hlist_node,vlist_node: 1709 if not (dir_orthogonal(dir_primary[box_dir(v)])(dir_primary[line_break_dir])) 1710 then break_width[1]:=break_width[1]-width(v) 1711 else 1712 break_width[1]:=break_width[1]-(depth(v)+height(v)); 1713 rule_node,kern_node: 1714 break_width[1]:=break_width[1]-width(v); 1715@z 1716%------------------------- 1717@x [38] m.842 1718@ @<Add the width of node |s| to |b...@>= 1719if is_char_node(s) then 1720 begin f:=font(s); 1721 break_width[1]:=@|break_width[1]+char_width(f)(char_info(f)(character(s))); 1722 end 1723else case type(s) of 1724 ligature_node: begin f:=font(lig_char(s)); 1725 break_width[1]:=break_width[1]+ 1726 char_width(f)(char_info(f)(character(lig_char(s)))); 1727 end; 1728 hlist_node,vlist_node,rule_node,kern_node: 1729 break_width[1]:=break_width[1]+width(s); 1730@y 1731@ @<Add the width of node |s| to |b...@>= 1732if is_char_node(s) then 1733 begin f:=font(s); 1734 if is_rotated(line_break_dir) then begin 1735 break_c_htdp:=height_depth(char_info(f)(character(s))); 1736 break_width[1]:=break_width[1]+char_height(f)(break_c_htdp) 1737 +char_depth(f)(break_c_htdp); 1738 end 1739 else 1740 break_width[1]:=@|break_width[1]+char_width(f)(char_info(f)(character(s))); 1741 end 1742else case type(s) of 1743 ligature_node: begin f:=font(lig_char(s)); 1744 if is_rotated(line_break_dir) then begin 1745 break_c_htdp:=height_depth(char_info(f)(character(lig_char(s)))); 1746 break_width[1]:=break_width[1]+char_height(f)(break_c_htdp) 1747 +char_depth(f)(break_c_htdp); 1748 end 1749 else 1750 break_width[1]:=break_width[1]+ 1751 char_width(f)(char_info(f)(character(lig_char(s)))); 1752 end; 1753 hlist_node,vlist_node: 1754 if not (dir_orthogonal(dir_primary[box_dir(s)])(dir_primary[line_break_dir])) 1755 then break_width[1]:=break_width[1]+width(s) 1756 else 1757 break_width[1]:=break_width[1]+(depth(s)+height(s)); 1758 rule_node,kern_node: 1759 break_width[1]:=break_width[1]+width(s); 1760@z 1761%------------------------- 1762@x [38] m.844 1763passive_right_box_width(q):=internal_right_box_width; 1764@y 1765passive_right_box_width(q):=internal_right_box_width; 1766@z 1767%------------------------- 1768@x [38] m.866 1769hlist_node,vlist_node,rule_node: act_width:=act_width+width(cur_p); 1770@y 1771hlist_node,vlist_node: 1772if not (dir_orthogonal(dir_primary[box_dir(cur_p)])(dir_primary[line_break_dir])) 1773then act_width:=act_width+width(cur_p) 1774else act_width:=act_width+(depth(cur_p)+height(cur_p)); 1775rule_node: act_width:=act_width+width(cur_p); 1776@z 1777%------------------------- 1778@x [38] m.866 1779 act_width:=act_width+char_width(f)(char_info(f)(character(lig_char(cur_p)))); 1780@y 1781 if is_rotated(line_break_dir) then begin 1782 break_c_htdp:=height_depth(char_info(f)(character(lig_char(cur_p)))); 1783 act_width:=act_width+char_height(f)(break_c_htdp) 1784 +char_depth(f)(break_c_htdp); 1785 end 1786 else 1787 act_width:=act_width+char_width(f)(char_info(f)(character(lig_char(cur_p)))); 1788@z 1789%------------------------- 1790@x [38] m.867 1791act_width:=act_width+char_width(f)(char_info(f)(character(cur_p))); 1792@y 1793if is_rotated(line_break_dir) then begin 1794 break_c_htdp:=height_depth(char_info(f)(character(cur_p))); 1795 act_width:=act_width+char_height(f)(break_c_htdp) 1796 +char_depth(f)(break_c_htdp); 1797 end 1798else 1799 act_width:=act_width+char_width(f)(char_info(f)(character(cur_p))); 1800@z 1801%------------------------- 1802@x [38] m.870 1803@ @<Add the width of node |s| to |disc_width|@>= 1804if is_char_node(s) then 1805 begin f:=font(s); 1806 disc_width:=disc_width+char_width(f)(char_info(f)(character(s))); 1807 end 1808else case type(s) of 1809 ligature_node: begin f:=font(lig_char(s)); 1810 disc_width:=disc_width+ 1811 char_width(f)(char_info(f)(character(lig_char(s)))); 1812 end; 1813 hlist_node,vlist_node,rule_node,kern_node: 1814 disc_width:=disc_width+width(s); 1815@y 1816@ @<Add the width of node |s| to |disc_width|@>= 1817if is_char_node(s) then 1818 begin f:=font(s); 1819 if is_rotated(line_break_dir) then begin 1820 break_c_htdp:=height_depth(char_info(f)(character(s))); 1821 disc_width:=disc_width+char_height(f)(break_c_htdp) 1822 +char_depth(f)(break_c_htdp); 1823 end 1824 else 1825 disc_width:=disc_width+char_width(f)(char_info(f)(character(s))); 1826 end 1827else case type(s) of 1828 ligature_node: begin f:=font(lig_char(s)); 1829 if is_rotated(line_break_dir) then begin 1830 break_c_htdp:=height_depth(char_info(f)(character(lig_char(s)))); 1831 disc_width:=disc_width+char_height(f)(break_c_htdp) 1832 +char_depth(f)(break_c_htdp); 1833 end 1834 else 1835 disc_width:=disc_width+ 1836 char_width(f)(char_info(f)(character(lig_char(s)))); 1837 end; 1838 hlist_node,vlist_node: 1839 if not (dir_orthogonal(dir_primary[box_dir(s)])(dir_primary[line_break_dir])) 1840 then disc_width:=disc_width+width(s) 1841 else disc_width:=disc_width+(depth(s)+height(s)); 1842 rule_node,kern_node: 1843 disc_width:=disc_width+width(s); 1844@z 1845%------------------------- 1846@x [38] m.871 1847@ @<Add the width of node |s| to |act_width|@>= 1848if is_char_node(s) then 1849 begin f:=font(s); 1850 act_width:=act_width+char_width(f)(char_info(f)(character(s))); 1851 end 1852else case type(s) of 1853 ligature_node: begin f:=font(lig_char(s)); 1854 act_width:=act_width+ 1855 char_width(f)(char_info(f)(character(lig_char(s)))); 1856 end; 1857 hlist_node,vlist_node,rule_node,kern_node: 1858 act_width:=act_width+width(s); 1859@y 1860@ @<Add the width of node |s| to |act_width|@>= 1861if is_char_node(s) then 1862 begin f:=font(s); 1863 if is_rotated(line_break_dir) then begin 1864 break_c_htdp:=height_depth(char_info(f)(character(s))); 1865 act_width:=act_width+char_height(f)(break_c_htdp) 1866 +char_depth(f)(break_c_htdp); 1867 end 1868 else 1869 act_width:=act_width+char_width(f)(char_info(f)(character(s))); 1870 end 1871else case type(s) of 1872 ligature_node: begin f:=font(lig_char(s)); 1873 if is_rotated(line_break_dir) then begin 1874 break_c_htdp:=height_depth(char_info(f)(character(lig_char(s)))); 1875 act_width:=act_width+char_height(f)(break_c_htdp) 1876 +char_depth(f)(break_c_htdp); 1877 end 1878 else 1879 act_width:=act_width+ 1880 char_width(f)(char_info(f)(character(lig_char(s)))); 1881 end; 1882 hlist_node,vlist_node: 1883 if not (dir_orthogonal(dir_primary[box_dir(s)])(dir_primary[line_break_dir])) 1884 then act_width:=act_width+width(s) 1885 else act_width:=act_width+(depth(s)+height(s)); 1886 rule_node,kern_node: 1887 act_width:=act_width+width(s); 1888@z 1889%------------------------- 1890@x [39] m.877 1891@ The total number of lines that will be set by |post_line_break| 1892is |best_line-prev_graf-1|. The last breakpoint is specified by 1893|break_node(best_bet)|, and this passive node points to the other breakpoints 1894via the |prev_break| links. The finishing-up phase starts by linking the 1895relevant passive nodes in forward order, changing |prev_break| to 1896|next_break|. (The |next_break| fields actually reside in the same memory 1897space as the |prev_break| fields did, but we give them a new name because 1898of their new significance.) Then the lines are justified, one by one. 1899 1900@d next_break==prev_break {new name for |prev_break| after links are reversed} 1901 1902@<Declare subprocedures for |line_break|@>= 1903procedure post_line_break(@!final_widow_penalty:integer); 1904label done,done1; 1905var q,@!r,@!s:pointer; {temporary registers for list manipulation} 1906@!disc_break:boolean; {was the current break at a discretionary node?} 1907@!post_disc_break:boolean; {and did it have a nonempty post-break part?} 1908@!cur_width:scaled; {width of line number |cur_line|} 1909@!cur_indent:scaled; {left margin of line number |cur_line|} 1910@!t:quarterword; {used for replacement counts in discretionary nodes} 1911@!pen:integer; {use when calculating penalties between lines} 1912@!cur_line: halfword; {the current line number being justified} 1913begin @<Reverse the links of the relevant passive nodes, setting |cur_p| to the 1914 first breakpoint@>; 1915cur_line:=prev_graf+1; 1916repeat @<Justify the line ending at breakpoint |cur_p|, and append it to the 1917 current vertical list, together with associated penalties and other 1918 insertions@>; 1919incr(cur_line); cur_p:=next_break(cur_p); 1920if cur_p<>null then if not post_disc_break then 1921 @<Prune unwanted nodes at the beginning of the next line@>; 1922until cur_p=null; 1923if (cur_line<>best_line)or(link(temp_head)<>null) then 1924 confusion("line breaking"); 1925@:this can't happen line breaking}{\quad line breaking@> 1926prev_graf:=best_line-1; 1927end; 1928@y 1929@ The total number of lines that will be set by |post_line_break| 1930is |best_line-prev_graf-1|. The last breakpoint is specified by 1931|break_node(best_bet)|, and this passive node points to the other breakpoints 1932via the |prev_break| links. The finishing-up phase starts by linking the 1933relevant passive nodes in forward order, changing |prev_break| to 1934|next_break|. (The |next_break| fields actually reside in the same memory 1935space as the |prev_break| fields did, but we give them a new name because 1936of their new significance.) Then the lines are justified, one by one. 1937 1938The |post_line_break| must also keep an dir stack, so that it can 1939output end direction instructions at the ends of lines 1940and begin direction instructions at the beginnings of lines. 1941 1942@d next_break==prev_break {new name for |prev_break| after links are reversed} 1943 1944@<Declare subprocedures for |line_break|@>= 1945procedure post_line_break(@!final_widow_penalty:integer); 1946label done,done1; 1947var q,@!r,@!s:pointer; {temporary registers for list manipulation} 1948@!disc_break:boolean; {was the current break at a discretionary node?} 1949@!post_disc_break:boolean; {and did it have a nonempty post-break part?} 1950@!cur_width:scaled; {width of line number |cur_line|} 1951@!cur_indent:scaled; {left margin of line number |cur_line|} 1952@!t:quarterword; {used for replacement counts in discretionary nodes} 1953@!pen:integer; {use when calculating penalties between lines} 1954@!cur_line: halfword; {the current line number being justified} 1955begin dir_ptr:=dir_save; 1956@<Reverse the links of the relevant passive nodes, setting |cur_p| to the 1957 first breakpoint@>; 1958cur_line:=prev_graf+1; 1959repeat @<Justify the line ending at breakpoint |cur_p|, and append it to the 1960 current vertical list, together with associated penalties and other 1961 insertions@>; 1962incr(cur_line); cur_p:=next_break(cur_p); 1963if cur_p<>null then if not post_disc_break then 1964 @<Prune unwanted nodes at the beginning of the next line@>; 1965until cur_p=null; 1966if (cur_line<>best_line)or(link(temp_head)<>null) then 1967 confusion("line breaking"); 1968@:this can't happen line breaking}{\quad line breaking@> 1969prev_graf:=best_line-1; dir_save:=dir_ptr; 1970end; 1971@z 1972%------------------------- 1973@x [39] m.880 1974@<Justify the line ending at breakpoint |cur_p|, and append it...@>= 1975@<Modify the end of the line to reflect the nature of the break and to include 1976 \.{\\rightskip}; also set the proper value of |disc_break|@>; 1977@<Put the \(l)\.{\\leftskip} glue at the left and detach this line@>; 1978@y 1979@<Justify the line ending at breakpoint |cur_p|, and append it...@>= 1980@<DIR: Insert dir nodes at the beginning of the current line@>; 1981@<DIR: Adjust the dir stack based on dir nodes in this line@>; 1982@<Modify the end of the line to reflect the nature of the break and to include 1983 \.{\\rightskip}; also set the proper value of |disc_break|@>; 1984@<Put the \(l)\.{\\leftskip} glue at the left and detach this line@>; 1985@z 1986%------------------------- 1987@x [39] m.881 1988 if passive_right_box(cur_p)<>null then begin 1989 r:=temp_head; 1990 while link(r)<>q do r:=link(r); 1991 s:=copy_node_list(passive_right_box(cur_p)); 1992 link(r):=s; 1993 link(s):=q; 1994 end; 1995 delete_glue_ref(glue_ptr(q)); 1996 glue_ptr(q):=right_skip; 1997 subtype(q):=right_skip_code+1; add_glue_ref(right_skip); 1998 goto done; 1999 end 2000 else begin if type(q)=disc_node then 2001 @<Change discretionary to compulsory and set 2002 |disc_break:=true|@> 2003 else if (type(q)=math_node)or(type(q)=kern_node) then width(q):=0; 2004 end 2005else begin q:=temp_head; 2006 while link(q)<>null do q:=link(q); 2007 end; 2008@y 2009 if passive_right_box(cur_p)<>null then begin 2010 r:=temp_head; 2011 while link(r)<>q do r:=link(r); 2012 @<DIR: Insert dir nodes at the end of the current line@>; 2013 s:=copy_node_list(passive_right_box(cur_p)); 2014 link(r):=s; 2015 link(s):=q; 2016 end 2017 else begin 2018 r:=temp_head; 2019 while link(r)<>q do r:=link(r); 2020 @<DIR: Insert dir nodes at the end of the current line@>; 2021 end; 2022 delete_glue_ref(glue_ptr(q)); 2023 glue_ptr(q):=right_skip; 2024 subtype(q):=right_skip_code+1; add_glue_ref(right_skip); 2025 goto done; 2026 end 2027 else begin if type(q)=disc_node then 2028 @<Change discretionary to compulsory and set 2029 |disc_break:=true|@> 2030 else if (type(q)=math_node)or(type(q)=kern_node) then width(q):=0; 2031 end 2032else begin q:=temp_head; 2033 while link(q)<>null do q:=link(q); 2034 end; 2035r:=q; 2036@<DIR: Insert dir nodes at the end of the current line@>; 2037@z 2038%------------------------- 2039@x [39] m.888 2040append_to_vlist(just_box); 2041if adjust_head<>adjust_tail then 2042 begin link(tail):=link(adjust_head); tail:=adjust_tail; 2043 end; 2044adjust_tail:=null 2045@y 2046append_to_vlist(just_box); 2047if adjust_head<>adjust_tail then 2048 begin link(tail):=link(adjust_head); tail:=adjust_tail; 2049 end; 2050adjust_tail:=null 2051@z 2052%------------------------- 2053@x [39] m.888 2054adjust_tail:=adjust_head; just_box:=hpack(q,cur_width,exactly); 2055@y 2056adjust_tail:=adjust_head; 2057pack_direction:=paragraph_dir; 2058just_box:=hpack(q,cur_width,exactly); 2059@z 2060%------------------------- 2061@x [44] m.977 2062@p function vsplit(@!n:eight_bits; @!h:scaled):pointer; 2063 {extracts a page of height |h| from box |n|} 2064label exit,done; 2065var v:pointer; {the box to be split} 2066p:pointer; {runs through the vlist} 2067q:pointer; {points to where the break occurs} 2068begin v:=box(n); 2069if split_first_mark<>null then 2070 begin delete_token_ref(split_first_mark); split_first_mark:=null; 2071 delete_token_ref(split_bot_mark); split_bot_mark:=null; 2072 end; 2073@<Dispense with trivial cases of void or bad boxes@>; 2074q:=vert_break(list_ptr(v),h,split_max_depth); 2075@<Look at all the marks in nodes before the break, and set the final 2076 link to |null| at the break@>; 2077q:=prune_page_top(q); p:=list_ptr(v); free_node(v,box_node_size); 2078@y 2079@p function vsplit(@!n:eight_bits; @!h:scaled):pointer; 2080 {extracts a page of height |h| from box |n|} 2081label exit,done; 2082var v:pointer; {the box to be split} 2083vdir:integer; {the direction of the box to be split} 2084p:pointer; {runs through the vlist} 2085q:pointer; {points to where the break occurs} 2086begin v:=box(n); vdir:=box_dir(v); 2087if split_first_mark<>null then 2088 begin delete_token_ref(split_first_mark); split_first_mark:=null; 2089 delete_token_ref(split_bot_mark); split_bot_mark:=null; 2090 end; 2091@<Dispense with trivial cases of void or bad boxes@>; 2092q:=vert_break(list_ptr(v),h,split_max_depth); 2093@<Look at all the marks in nodes before the break, and set the final 2094 link to |null| at the break@>; 2095q:=prune_page_top(q); p:=list_ptr(v); free_node(v,box_node_size); 2096pack_direction:=vdir; 2097@z 2098%------------------------- 2099@x [45] m.1001 2100if width(temp_ptr)>height(p) then width(temp_ptr):=width(temp_ptr)-height(p) 2101else width(temp_ptr):=0; 2102@y 2103if (type(p)=hlist_node) and (is_mirrored(body_direction)) then begin 2104 if width(temp_ptr)>depth(p) then width(temp_ptr):=width(temp_ptr)-depth(p) 2105 else width(temp_ptr):=0; 2106 end 2107else begin 2108 if width(temp_ptr)>height(p) then width(temp_ptr):=width(temp_ptr)-height(p) 2109 else width(temp_ptr):=0; 2110 end; 2111@z 2112%------------------------- 2113@x [45] m.1002 2114begin page_total:=page_total+page_depth+height(p); 2115page_depth:=depth(p); 2116@y 2117begin 2118if (type(p)=hlist_node) and (is_mirrored(body_direction)) then begin 2119 page_total:=page_total+page_depth+depth(p); 2120 page_depth:=height(p); 2121 end 2122else begin 2123 page_total:=page_total+page_depth+height(p); 2124 page_depth:=depth(p); 2125 end; 2126@z 2127%------------------------- 2128@x [45] m.1017 2129set_equiv(box_base+255, 2130 vpackage(link(page_head),best_size,exactly,page_max_depth)); 2131@y 2132pack_direction:=body_direction; 2133set_equiv(box_base+255, 2134 vpackage(link(page_head),best_size,exactly,page_max_depth)); 2135@z 2136%------------------------- 2137@x [45] m.1021 2138temp_ptr:=list_ptr(box(n)); 2139free_node(box(n),box_node_size); 2140@y 2141temp_ptr:=list_ptr(box(n)); 2142free_node(box(n),box_node_size); 2143pack_direction:=body_direction; 2144@z 2145%------------------------- 2146@x [47] m.1063 2147non_math(left_brace): begin 2148 new_save_level(simple_group); 2149 eq_word_define(int_base+no_local_whatsits_code,0); 2150 end; 2151any_mode(begin_group): begin 2152 new_save_level(semi_simple_group); 2153 eq_word_define(int_base+no_local_whatsits_code,0); 2154 end; 2155any_mode(end_group): 2156 if cur_group=semi_simple_group then begin 2157 temp_no_whatsits:=no_local_whatsits; 2158 unsave; 2159 if temp_no_whatsits<>0 then 2160 if abs(mode)=hmode then @<LOCAL: Add local paragraph node@>; 2161 end 2162 else off_save; 2163@y 2164non_math(left_brace): begin 2165 new_save_level(simple_group); 2166 eq_word_define(int_base+no_local_whatsits_code,0); 2167 eq_word_define(int_base+no_local_dirs_code,0); 2168 end; 2169any_mode(begin_group): begin 2170 new_save_level(semi_simple_group); 2171 eq_word_define(int_base+no_local_whatsits_code,0); 2172 eq_word_define(int_base+no_local_dirs_code,0); 2173 end; 2174any_mode(end_group): 2175 if cur_group=semi_simple_group then begin 2176 temp_no_whatsits:=no_local_whatsits; 2177 temp_no_dirs:=no_local_dirs; 2178 temporary_dir:=text_direction; 2179 if dir_level(text_dir_ptr)=cur_level then 2180 @<DIR: Remove from |text_dir_ptr|@>; 2181 unsave; 2182 if abs(mode)=hmode then begin 2183 if temp_no_dirs<>0 then begin 2184 @<DIR: Add local dir node@>; 2185 dir_dir(tail):=temporary_dir-64; 2186 end; 2187 if temp_no_whatsits<>0 then 2188 @<LOCAL: Add local paragraph node@>; 2189 end 2190 end 2191 else off_save; 2192@z 2193%------------------------- 2194@x [47] m.1068 2195simple_group: begin 2196 temp_no_whatsits:=no_local_whatsits; 2197 unsave; 2198 if temp_no_whatsits<>0 then 2199 if abs(mode)=hmode then @<LOCAL: Add local paragraph node@>; 2200 end; 2201@y 2202simple_group: begin 2203 temp_no_whatsits:=no_local_whatsits; 2204 temp_no_dirs:=no_local_dirs; 2205 temporary_dir:=text_direction; 2206 if dir_level(text_dir_ptr)=cur_level then 2207 @<DIR: Remove from |text_dir_ptr|@>; 2208 unsave; 2209 if abs(mode)=hmode then begin 2210 if temp_no_dirs<>0 then begin 2211 @<DIR: Add local dir node@>; 2212 dir_dir(tail):=temporary_dir-64; 2213 end; 2214 if temp_no_whatsits<>0 then 2215 @<LOCAL: Add local paragraph node@>; 2216 end 2217 end; 2218@z 2219%------------------------- 2220@x [47] m.1083 2221begin k:=cur_chr-vtop_code; saved(0):=box_context; 2222if k=hmode then 2223 if (box_context<box_flag)and(abs(mode)=vmode) then 2224 scan_spec(adjusted_hbox_group,true) 2225 else scan_spec(hbox_group,true) 2226else begin if k=vmode then scan_spec(vbox_group,true) 2227 else begin scan_spec(vtop_group,true); k:=vmode; 2228 end; 2229 normal_paragraph; 2230 end; 2231push_nest; mode:=-k; 2232@y 2233begin k:=cur_chr-vtop_code; saved(0):=box_context; 2234case abs(mode) of 2235vmode: spec_direction:=body_direction; 2236hmode: spec_direction:=text_direction; 2237mmode: spec_direction:=math_direction; 2238end; 2239if k=hmode then 2240 if (box_context<box_flag)and(abs(mode)=vmode) then 2241 scan_spec(adjusted_hbox_group,true) 2242 else scan_spec(hbox_group,true) 2243else begin if k=vmode then scan_spec(vbox_group,true) 2244 else begin scan_spec(vtop_group,true); k:=vmode; 2245 end; 2246 normal_paragraph; 2247 end; 2248push_nest; mode:=-k; 2249@z 2250%------------------------- 2251@x [47] m.1086 2252procedure package(@!c:small_number); 2253var h:scaled; {height of box} 2254@!p:pointer; {first node in a box} 2255@!d:scaled; {max depth} 2256begin d:=box_max_depth; unsave; save_ptr:=save_ptr-3; 2257if mode=-hmode then cur_box:=hpack(link(head),saved(2),saved(1)) 2258else begin cur_box:=vpackage(link(head),saved(2),saved(1),d); 2259 if c=vtop_code then @<Readjust the height and depth of |cur_box|, 2260 for \.{\\vtop}@>; 2261 end; 2262pop_nest; box_end(saved(0)); 2263end; 2264@y 2265procedure package(@!c:small_number); 2266var h:scaled; {height of box} 2267@!p:pointer; {first node in a box} 2268@!d:scaled; {max depth} 2269begin d:=box_max_depth; unsave; save_ptr:=save_ptr-5; 2270pack_direction:=saved(3); 2271if mode=-hmode then cur_box:=hpack(link(head),saved(2),saved(1)) 2272else begin cur_box:=vpackage(link(head),saved(2),saved(1),d); 2273 if c=vtop_code then @<Readjust the height and depth of |cur_box|, 2274 for \.{\\vtop}@>; 2275 end; 2276if saved(4)<>null then 2277 @<DIR: Adjust back |text_dir_ptr| for |scan_spec|@>; 2278pop_nest; box_end(saved(0)); 2279end; 2280@z 2281%------------------------- 2282@x [47] m.1091 2283procedure new_graf(@!indented:boolean); 2284begin prev_graf:=0; 2285if (mode=vmode)or(head<>tail) then 2286 tail_append(new_param_glue(par_skip_code)); 2287push_nest; mode:=hmode; space_factor:=1000; set_cur_lang; clang:=cur_lang; 2288prev_graf:=(norm_min(left_hyphen_min)*@'100+norm_min(right_hyphen_min)) 2289 *@'200000+cur_lang; 2290@<LOCAL: Add local paragraph node@>; 2291if indented then begin 2292 tail:=new_null_box; link(link(head)):=tail; width(tail):=par_indent;@+ 2293 end; 2294@y 2295procedure new_graf(@!indented:boolean); 2296var p,q,dir_graf_tmp:pointer; 2297begin prev_graf:=0; 2298if (mode=vmode)or(head<>tail) then 2299 tail_append(new_param_glue(par_skip_code)); 2300push_nest; mode:=hmode; space_factor:=1000; set_cur_lang; clang:=cur_lang; 2301prev_graf:=(norm_min(left_hyphen_min)*@'100+norm_min(right_hyphen_min)) 2302 *@'200000+cur_lang; 2303@<LOCAL: Add local paragraph node@>; 2304if indented then begin 2305 p:=new_null_box; box_dir(p):=par_direction; 2306 width(p):=par_indent;@+ 2307 tail_append(p); 2308 end; 2309q:=tail; 2310dir_rover:=text_dir_ptr; 2311while dir_rover<>null do 2312 begin 2313 if (link(dir_rover)<>null) or (dir_dir(dir_rover)<>par_direction) then 2314 begin 2315 dir_graf_tmp:=new_dir(dir_dir(dir_rover)); 2316 link(dir_graf_tmp):=link(q); link(q):=dir_graf_tmp; 2317 end; 2318 dir_rover:=link(dir_rover); 2319 end; 2320q:=head; 2321while link(q)<>null do q:=link(q); 2322tail:=q; 2323@z 2324%------------------------- 2325@x [47] m.1096 2326procedure end_graf; 2327begin if mode=hmode then 2328 begin if (head=tail) or (link(head)=tail) then pop_nest 2329 {null paragraphs are ignored, all contain a |local_paragraph| node} 2330 else line_break(widow_penalty); 2331 normal_paragraph; 2332 error_count:=0; 2333 end; 2334end; 2335@y 2336procedure end_graf; 2337begin if mode=hmode then 2338 begin if (head=tail) or (link(head)=tail) then pop_nest 2339 {null paragraphs are ignored, all contain a |local_paragraph| node} 2340 else line_break(widow_penalty); 2341 if dir_save<>null then 2342 begin flush_node_list(dir_save); dir_save:=null; 2343 end; 2344 normal_paragraph; 2345 error_count:=0; 2346 end; 2347end; 2348@z 2349%------------------------- 2350@x [48] m.1136 2351procedure push_math(@!c:group_code); 2352begin push_nest; mode:=-mmode; incompleat_noad:=null; new_save_level(c); 2353end; 2354@y 2355procedure push_math(@!c:group_code); 2356begin 2357if math_direction<>text_direction then dir_math_save:=true; 2358push_nest; mode:=-mmode; incompleat_noad:=null; 2359@<DIR: |new_save_level| math@>; 2360end; 2361@z 2362%------------------------- 2363@x [48] m.1174 2364begin unsave; p:=fin_mlist(null); 2365@y 2366begin @<DIR: |unsave| math@>; p:=fin_mlist(null); 2367@z 2368%------------------------- 2369@x [48] m.1186 2370math_group: begin unsave; decr(save_ptr);@/ 2371@y 2372math_group: begin @<DIR: |unsave| math@>; decr(save_ptr);@/ 2373@z 2374%------------------------- 2375@x [48] m.1191 2376 else begin p:=fin_mlist(p); unsave; {end of |math_left_group|} 2377@y 2378 else begin p:=fin_mlist(p); 2379 @<DIR: |unsave| math@>; {end of |math_left_group|} 2380@z 2381%------------------------- 2382@x [48] m.1194 2383procedure after_math; 2384var l:boolean; {`\.{\\leqno}' instead of `\.{\\eqno}'} 2385@!danger:boolean; {not enough symbol fonts are present} 2386@!m:integer; {|mmode| or |-mmode|} 2387@!p:pointer; {the formula} 2388@!a:pointer; {box containing equation number} 2389@<Local variables for finishing a displayed formula@>@; 2390begin danger:=false; 2391@<Check that the necessary fonts for math symbols are present; 2392 if not, flush the current math lists and set |danger:=true|@>; 2393m:=mode; l:=false; p:=fin_mlist(null); {this pops the nest} 2394if mode=-m then {end of equation number} 2395 begin @<Check that another \.\$ follows@>; 2396 cur_mlist:=p; cur_style:=text_style; mlist_penalties:=false; 2397 mlist_to_hlist; a:=hpack(link(temp_head),natural); 2398 unsave; decr(save_ptr); {now |cur_group=math_shift_group|} 2399 if saved(0)=1 then l:=true; 2400@y 2401procedure after_math; 2402var l:boolean; {`\.{\\leqno}' instead of `\.{\\eqno}'} 2403@!danger:boolean; {not enough symbol fonts are present} 2404@!m:integer; {|mmode| or |-mmode|} 2405@!p:pointer; {the formula} 2406@!a:pointer; {box containing equation number} 2407@<Local variables for finishing a displayed formula@>@; 2408begin danger:=false; 2409@<Check that the necessary fonts for math symbols are present; 2410 if not, flush the current math lists and set |danger:=true|@>; 2411m:=mode; l:=false; p:=fin_mlist(null); {this pops the nest} 2412if mode=-m then {end of equation number} 2413 begin @<Check that another \.\$ follows@>; 2414 cur_mlist:=p; cur_style:=text_style; mlist_penalties:=false; 2415 mlist_to_hlist; a:=hpack(link(temp_head),natural); 2416 @<DIR: |unsave| math@>; 2417 decr(save_ptr); {now |cur_group=math_shift_group|} 2418 if saved(0)=1 then l:=true; 2419@z 2420%------------------------- 2421@x [48] m.1196 2422@<Finish math in text@>= 2423begin tail_append(new_math(math_surround,before)); 2424cur_mlist:=p; cur_style:=text_style; mlist_penalties:=(mode>0); mlist_to_hlist; 2425link(tail):=link(temp_head); 2426while link(tail)<>null do tail:=link(tail); 2427tail_append(new_math(math_surround,after)); 2428space_factor:=1000; unsave; 2429end 2430@y 2431@<Finish math in text@> = 2432begin tail_append(new_math(math_surround,before)); 2433if dir_math_save then 2434 @<Append a begin direction to the tail of the current list@>; 2435cur_mlist:=p; cur_style:=text_style; mlist_penalties:=(mode>0); mlist_to_hlist; 2436link(tail):=link(temp_head); 2437while link(tail)<>null do tail:=link(tail); 2438if dir_math_save then 2439 @<Append an end direction to the tail of the current list@>; 2440dir_math_save:=false; 2441tail_append(new_math(math_surround,after)); 2442space_factor:=1000; 2443@<DIR: |unsave| math@>; 2444end 2445@z 2446%------------------------- 2447@x [48] m.1200 2448procedure resume_after_display; 2449begin if cur_group<>math_shift_group then confusion("display"); 2450@:this can't happen display}{\quad display@> 2451unsave; prev_graf:=prev_graf+3; 2452@y 2453procedure resume_after_display; 2454begin if cur_group<>math_shift_group then confusion("display"); 2455@:this can't happen display}{\quad display@> 2456@<DIR: |unsave| math@>; 2457prev_graf:=prev_graf+3; 2458@z 2459%------------------------- 2460@x [49] m.1210 2461any_mode(assign_int), 2462@y 2463any_mode(assign_int), 2464any_mode(assign_dir), 2465@z 2466%------------------------- 2467@x [49] m.1228 2468assign_dimen: begin p:=cur_chr; scan_optional_equals; 2469 scan_normal_dimen; word_define(p,cur_val); 2470 end; 2471@y 2472assign_dir: begin 2473 @<DIR: Assign direction codes@> 2474 end; 2475assign_dimen: begin p:=cur_chr; scan_optional_equals; 2476 scan_normal_dimen; word_define(p,cur_val); 2477 end; 2478@z 2479%------------------------- 2480@x [49] m.1257 2481@!flushable_string:str_number; {string not yet referenced} 2482@y 2483@!natural_dir:integer;{the natural direction of the font} 2484@!flushable_string:str_number; {string not yet referenced} 2485@z 2486%------------------------- 2487@x [49] m.1257 2488if scan_keyword("offset") then begin 2489 scan_int; 2490 offset:=cur_val; 2491 if (cur_val<0) then begin 2492 print_err("Illegal offset has been changed to 0"); 2493 help1("The offset must be bigger than 0."); int_error(cur_val); 2494 offset:=0; 2495 end 2496 end 2497else offset:=0; 2498name_in_progress:=false; 2499@<If this font has already been loaded, set |f| to the internal 2500 font number and |goto common_ending|@>; 2501f:=read_font_info(u,cur_name,cur_area,s,offset); 2502@y 2503if scan_keyword("offset") then begin 2504 scan_int; 2505 offset:=cur_val; 2506 if (cur_val<0) then begin 2507 print_err("Illegal offset has been changed to 0"); 2508 help1("The offset must be bigger than 0."); int_error(cur_val); 2509 offset:=0; 2510 end 2511 end 2512else offset:=0; 2513if scan_keyword("naturaldir") then begin 2514 scan_dir; 2515 natural_dir:=cur_val; 2516 end 2517else natural_dir:=-1; 2518name_in_progress:=false; 2519@<If this font has already been loaded, set |f| to the internal 2520 font number and |goto common_ending|@>; 2521f:=read_font_info(u,cur_name,cur_area,s,offset,natural_dir); 2522@z 2523%------------------------- 2524@x [51] m.1337 2525if (loc<limit)and(cat_code(buffer[loc])<>escape) then start_input; 2526 {\.{\\input} assumed} 2527@y 2528if (loc<limit)and(cat_code(buffer[loc])<>escape) then start_input; 2529 {\.{\\input} assumed} 2530@<DIR: Initialize |text_dir_ptr|@>; 2531@z 2532%------------------------- 2533@x [53] m.1341 2534@d language_node=4 {|subtype| in whatsits that change the current language} 2535@y 2536@d language_node=4 {|subtype| in whatsits that change the current language} 2537@d dir_node_size=4 {number of words in change direction node} 2538@d dir_dir(#)==info(#+1) {keep the direction to be taken} 2539@d dir_level(#)==link(#+1) {the save level at which the direction was defined} 2540@d dir_dvi_ptr(#)==info(#+2) {for reflecting dvi output} 2541@d dir_dvi_h(#)==info(#+3) {for reflecting dvi output} 2542@z 2543%------------------------- 2544@x [53] m.1342 2545@!write_open:array[0..17] of boolean; 2546@y 2547@!write_open:array[0..17] of boolean; 2548@!neg_wd:scaled; 2549@!pos_wd:scaled; 2550@!neg_ht:scaled; 2551@!dvi_direction:integer; 2552@!dir_primary:array[0..31] of 0..31; 2553@!dir_secondary:array[0..31] of 0..31; 2554@!dir_tertiary:array[0..31] of 0..31; 2555@!dir_rearrange:array[0..3] of 0..31; 2556@!dir_names:array[0..3] of str_number; 2557@!text_dir_ptr:pointer; 2558@!text_dir_tmp:pointer; 2559@z 2560%------------------------- 2561@x [53] m.1343 2562for k:=0 to 17 do write_open[k]:=false; 2563@y 2564for k:=0 to 17 do write_open[k]:=false; 2565set_new_eqtb_int(dir_base+page_direction_code,0); 2566set_new_eqtb_int(dir_base+body_direction_code,0); 2567set_new_eqtb_int(dir_base+par_direction_code,0); 2568set_new_eqtb_int(dir_base+text_direction_code,0); 2569set_new_eqtb_int(dir_base+math_direction_code,0); 2570pack_direction:=-1; 2571set_new_eqtb_sc(dimen_base+page_height_code,55380984); {29.7cm} 2572set_new_eqtb_sc(dimen_base+page_width_code,39158276); {21cm} 2573set_new_eqtb_sc(dimen_base+page_bottom_offset_code,page_height-9472573); 2574 {-2 inches} 2575set_new_eqtb_sc(dimen_base+page_right_offset_code,page_width-9472573); 2576 {-2 inches} 2577for k:= 0 to 7 do begin 2578 dir_primary [k ]:=dir_T; 2579 dir_primary [k+ 8]:=dir_L; 2580 dir_primary [k+16]:=dir_B; 2581 dir_primary [k+24]:=dir_R; 2582 end; 2583for k:= 0 to 3 do begin 2584 dir_secondary[k ]:=dir_L; 2585 dir_secondary[k+ 4]:=dir_R; 2586 dir_secondary[k+ 8]:=dir_T; 2587 dir_secondary[k+12]:=dir_B; 2588 2589 dir_secondary[k+16]:=dir_L; 2590 dir_secondary[k+20]:=dir_R; 2591 dir_secondary[k+24]:=dir_T; 2592 dir_secondary[k+28]:=dir_B; 2593 end; 2594for k:=0 to 7 do begin 2595 dir_tertiary[k*4 ]:=dir_T; 2596 dir_tertiary[k*4+1]:=dir_L; 2597 dir_tertiary[k*4+2]:=dir_B; 2598 dir_tertiary[k*4+3]:=dir_R; 2599 end; 2600dir_rearrange[0]:=0; 2601dir_rearrange[1]:=0; 2602dir_rearrange[2]:=1; 2603dir_rearrange[3]:=1; 2604dir_names[0]:="T"; 2605dir_names[1]:="L"; 2606dir_names[2]:="B"; 2607dir_names[3]:="R"; 2608@z 2609%------------------------- 2610@x [53] m.1344 2611@d local_par_node=6 {|subtype| in whatsits for local paragraph node} 2612@y 2613@d local_par_node=6 {|subtype| in whatsits for local paragraph node} 2614@d dir_node=7 {|subtype| in whatsits for change direction node} 2615@z 2616%------------------------- 2617@x [53] m.1344 2618primitive("localinterlinepenalty",assign_int,local_inter_line_penalty_code);@/ 2619primitive("localbrokenpenalty",assign_int,local_broken_penalty_code);@/ 2620@y 2621primitive("localinterlinepenalty",assign_int,local_inter_line_penalty_code);@/ 2622primitive("localbrokenpenalty",assign_int,local_broken_penalty_code);@/ 2623primitive("pagedir",assign_dir,dir_base+page_direction_code);@/ 2624primitive("bodydir",assign_dir,dir_base+body_direction_code);@/ 2625primitive("pardir",assign_dir,dir_base+par_direction_code);@/ 2626primitive("textdir",assign_dir,dir_base+text_direction_code);@/ 2627primitive("mathdir",assign_dir,dir_base+math_direction_code);@/ 2628primitive("pageheight",assign_dimen,dimen_base+page_height_code);@/ 2629primitive("pagewidth",assign_dimen,dimen_base+page_width_code);@/ 2630{ 2631|primitive("pagerightoffset",assign_dimen,dimen_base+page_right_offset_code);| 2632|primitive("pagebottomoffset",assign_dimen,dimen_base+page_bottom_offset_code);| 2633} 2634@z 2635%------------------------- 2636@x [53] m.1346 2637 set_language_code:print_esc("setlanguage"); 2638 othercases print("[unknown extension!]") 2639 endcases; 2640@y 2641 set_language_code:print_esc("setlanguage"); 2642 othercases print("[unknown extension!]") 2643 endcases; 2644@z 2645%------------------------- 2646@x [53] m.1348 2647set_language_code:@<Implement \.{\\setlanguage}@>; 2648@y 2649set_language_code:@<Implement \.{\\setlanguage}@>; 2650@z 2651%------------------------- 2652@x [53] m.1356 2653language_node:begin print_esc("setlanguage"); 2654 print_int(what_lang(p)); print(" (hyphenmin "); 2655 print_int(what_lhm(p)); print_char(","); 2656 print_int(what_rhm(p)); print_char(")"); 2657 end; 2658@y 2659language_node:begin print_esc("setlanguage"); 2660 print_int(what_lang(p)); print(" (hyphenmin "); 2661 print_int(what_lhm(p)); print_char(","); 2662 print_int(what_rhm(p)); print_char(")"); 2663 end; 2664dir_node: 2665 if dir_dir(p)<0 then begin 2666 print_esc("enddir"); print(" "); print_dir(dir_dir(p)+64); 2667 end 2668 else begin 2669 print_esc("begindir"); print(" "); print_dir(dir_dir(p)); 2670 end; 2671@z 2672%------------------------- 2673@x [53] m.1357 2674close_node,language_node: begin r:=get_node(small_node_size); 2675 words:=small_node_size; 2676 end; 2677@y 2678close_node,language_node: begin r:=get_node(small_node_size); 2679 words:=small_node_size; 2680 end; 2681dir_node: begin r:=get_node(dir_node_size); 2682 words:=dir_node_size; 2683 end; 2684@z 2685%------------------------- 2686@x [53] m.1358 2687close_node,language_node: free_node(p,small_node_size); 2688@y 2689close_node,language_node: free_node(p,small_node_size); 2690dir_node: free_node(p,dir_node_size); 2691@z 2692%------------------------- 2693@x [53] m.1360 2694@ @<Incorporate a whatsit node into an hbox@>=do_nothing 2695@y 2696@ @<Incorporate a whatsit node into an hbox@>= 2697begin 2698if subtype(p)=dir_node then 2699 begin 2700 @<DIR: Adjust the dir stack for the |hpack| routine@>; 2701 end; 2702end 2703@z 2704%------------------------- 2705@x [53] m.1362 2706@<Advance \(p)past a whatsit node in the \(l)|line_break| loop@>=@+ 2707adv_past(cur_p) else @<LOCAL: Advance past a |local_paragraph| node@> 2708@y 2709@<Advance \(p)past a whatsit node in the \(l)|line_break| loop@>=@+ 2710adv_past(cur_p) else @<LOCAL: Advance past a |local_paragraph| node@> 2711else @<DIR: Adjust the dir stack for the |line_break| routine@> 2712@z 2713%------------------------- 2714@x [53] m.1366 2715@ @<Output the whatsit node |p| in an hlist@>= 2716out_what(p) 2717@y 2718@ @<Output the whatsit node |p| in an hlist@>= 2719if subtype(p)<>dir_node then out_what(p) 2720else @<Output a reflection instruction if the direction has changed@> 2721@z 2722%------------------------- 2723@x 2724@d local_par_size==7 2725@y 2726@d local_par_dir(#)==mem[#+7].int 2727@d local_par_size==8 2728@z 2729%------------------------- 2730@x 2731make_local_par_node:=p; 2732@y 2733local_par_dir(p):=par_direction; 2734make_local_par_node:=p; 2735@z 2736%------------------------- 2737@x 2738@ @<LOCAL: local paragraph node@>= 2739((type(q)=whatsit_node) and (subtype(q)=local_par_node)) 2740 2741@y 2742@ @<LOCAL: local paragraph node@>= 2743((type(q)=whatsit_node) and (subtype(q)=local_par_node)) 2744 2745@ @<DIR: Assign direction codes@>= 2746case cur_chr of 2747dir_base+page_direction_code: begin 2748 if its_all_over then begin 2749 scan_dir; 2750 eq_word_define(dir_base+page_direction_code,cur_val); 2751 end; 2752 end; 2753dir_base+body_direction_code: begin 2754 if its_all_over then begin 2755 scan_dir; 2756 eq_word_define(dir_base+body_direction_code,cur_val); 2757 end; 2758 end; 2759dir_base+par_direction_code: begin 2760 scan_dir; 2761 eq_word_define(dir_base+par_direction_code,cur_val); 2762 end; 2763dir_base+text_direction_code: begin scan_dir; 2764 if (no_local_dirs>0) and (abs(mode)=hmode) then begin 2765 @<DIR: Add local dir node@>; 2766 dir_dir(tail):=dir_dir(tail)-64; 2767 end; 2768 if dir_level(text_dir_ptr)=cur_level then 2769 @<DIR: Remove from |text_dir_ptr|@>; 2770 eq_word_define(dir_base+text_direction_code,cur_val); 2771 @<DIR: Add to |text_dir_ptr|@>; 2772 if abs(mode)=hmode then 2773 begin 2774 @<DIR: Add local dir node@>; 2775 dir_level(tail):=cur_level; 2776 end; 2777 eq_word_define(int_base+no_local_dirs_code,no_local_dirs+1); 2778 eq_word_define(int_base+level_local_dir_code,cur_level); 2779 end; 2780dir_base+math_direction_code: begin scan_dir; 2781 eq_word_define(dir_base+math_direction_code,cur_val); 2782 end; 2783end; 2784 2785@ 2786@d push_dir(#)== 2787begin dir_tmp:=new_dir(#); 2788link(dir_tmp):=dir_ptr; dir_ptr:=dir_tmp; 2789dir_ptr:=dir_tmp; 2790end 2791 2792@d push_dir_node(#)== 2793begin dir_tmp:=get_node(dir_node_size); 2794type(dir_tmp):=whatsit_node; subtype(dir_tmp):=dir_node; 2795dir_dir(dir_tmp):=dir_dir(#); 2796dir_level(dir_tmp):=dir_level(#); 2797dir_dvi_h(dir_tmp):=dir_dvi_h(#); 2798dir_dvi_ptr(dir_tmp):=dir_dvi_ptr(#); 2799link(dir_tmp):=dir_ptr; dir_ptr:=dir_tmp; 2800end 2801 2802@d pop_dir_node== 2803begin dir_tmp:=dir_ptr; 2804dir_ptr:=link(dir_tmp); 2805free_node(dir_tmp,dir_node_size); 2806end 2807 2808@ @<DIR: Declare |new_dir|@>= 2809function new_dir(s:small_number): pointer; 2810var p:pointer; {the new node} 2811begin p:=get_node(dir_node_size); type(p):=whatsit_node; 2812subtype(p):=dir_node; dir_dir(p):=s; 2813dir_dvi_h(p):=0; dir_dvi_ptr(p):=-1; 2814dir_level(p):=cur_level; new_dir:=p; 2815end 2816 2817@ @<Append a begin direction to the tail of the current list@>= 2818tail_append(new_dir(math_direction)) 2819 2820@ @<Append an end direction to the tail of the current list@>= 2821tail_append(new_dir(math_direction-64)) 2822 2823@ @<DIR: Add local dir node@>= 2824tail_append(new_dir(text_direction)) 2825 2826@ @<DIR: Adjust the dir stack for the |line_break| routine@>= 2827if subtype(cur_p)=dir_node then 2828begin 2829if dir_dir(cur_p)>=0 then begin 2830 line_break_dir:=dir_dir(cur_p); 2831 push_dir_node(cur_p); 2832 end 2833else begin 2834 pop_dir_node; 2835 line_break_dir:=dir_dir(dir_ptr); 2836 end 2837end 2838 2839@ @<DIR: Adjust the dir stack for the |hpack| routine@>= 2840begin 2841if dir_dir(p)>=0 then begin 2842 hpack_dir:=dir_dir(p); 2843 push_dir_node(p); 2844 end 2845else begin 2846 pop_dir_node; 2847 hpack_dir:=dir_dir(dir_ptr); 2848 end 2849end 2850 2851@ @<DIR: Insert dir nodes at the beginning of the current line@>= 2852begin 2853dir_rover:=dir_ptr; 2854while dir_rover<>null do 2855 begin 2856 dir_tmp:=new_dir(dir_dir(dir_rover)); link(dir_tmp):=link(temp_head); 2857 link(temp_head):=dir_tmp; dir_rover:=link(dir_rover); 2858 end 2859end 2860 2861@ @<DIR: Adjust the dir stack based on dir nodes in this line@>= 2862begin flush_node_list(dir_ptr); dir_ptr:=null; 2863q:=link(temp_head); 2864while q<>cur_break(cur_p) do 2865 begin if not is_char_node(q) then 2866 if type(q)=whatsit_node then 2867 if subtype(q)=dir_node then begin 2868 if dir_dir(q)>=0 then begin 2869 push_dir_node(q) 2870 end 2871 else if dir_ptr<>null then 2872 if dir_dir(dir_ptr)=(dir_dir(q)+64) then begin 2873 pop_dir_node; 2874 end; 2875 end; 2876 q:=link(q); 2877 end 2878end 2879 2880@ @<DIR: Insert dir nodes at the end of the current line@>= 2881if dir_ptr<>null then 2882 begin 2883 if link(r)=q then begin 2884 dir_rover:=dir_ptr; 2885 while dir_rover<>null do 2886 begin 2887 dir_tmp:=new_dir(dir_dir(dir_rover)-64); 2888 link(dir_tmp):=q; 2889 link(r):=dir_tmp; 2890 r:=dir_tmp; 2891 dir_rover:=link(dir_rover); 2892 end; 2893 end 2894 else if r=final_par_glue then begin 2895 s:=temp_head; 2896 while link(s)<>r do 2897 s:=link(s); 2898 dir_rover:=dir_ptr; 2899 while dir_rover<>null do 2900 begin 2901 dir_tmp:=new_dir(dir_dir(dir_rover)-64); 2902 link(dir_tmp):=q; 2903 link(s):=dir_tmp; 2904 s:=dir_tmp; 2905 dir_rover:=link(dir_rover); 2906 end; 2907 end 2908 else begin 2909 dir_rover:=dir_ptr; 2910 s:=link(q); 2911 while dir_rover<>null do 2912 begin 2913 dir_tmp:=new_dir(dir_dir(dir_rover)-64); 2914 link(dir_tmp):=s; 2915 link(q):=dir_tmp; 2916 q:=dir_tmp; 2917 dir_rover:=link(dir_rover); 2918 end; 2919 r:=q; 2920 end 2921 end 2922 2923@ @<DIR: Reset |dir_ptr|@>= 2924begin 2925 while dir_ptr<>null do 2926 pop_dir_node 2927end 2928 2929@ @<DIR: |unsave| math@>= 2930begin 2931unsave; 2932decr(save_ptr); 2933flush_node_list(text_dir_ptr); 2934text_dir_ptr:=saved(0); 2935end 2936 2937@ @<DIR: |new_save_level| math@>= 2938begin 2939saved(0):=text_dir_ptr; 2940text_dir_ptr:=new_dir(math_direction); 2941incr(save_ptr); 2942new_save_level(c); 2943eq_word_define(dir_base+body_direction_code,math_direction); 2944eq_word_define(dir_base+par_direction_code,math_direction); 2945eq_word_define(dir_base+text_direction_code,math_direction); 2946eq_word_define(int_base+level_local_dir_code,cur_level); 2947end 2948 2949@ @<DIR: Adjust |text_dir_ptr| for |scan_spec|@>= 2950begin 2951if spec_direction<>-1 then begin 2952 saved(3):=text_dir_ptr; 2953 text_dir_ptr:=new_dir(spec_direction); 2954 end 2955else saved(3):=null; 2956end 2957 2958@ @<DIR: Adjust back |text_dir_ptr| for |scan_spec|@>= 2959begin 2960flush_node_list(text_dir_ptr); 2961text_dir_ptr:=saved(4); 2962end 2963 2964@ @<DIR: Add to |text_dir_ptr|@>= 2965begin 2966text_dir_tmp:=new_dir(text_direction); 2967link(text_dir_tmp):=text_dir_ptr; 2968text_dir_ptr:=text_dir_tmp; 2969end 2970 2971@ @<DIR: Remove from |text_dir_ptr|@>= 2972begin 2973text_dir_tmp:=link(text_dir_ptr); 2974free_node(text_dir_ptr,dir_node_size); 2975text_dir_ptr:=text_dir_tmp; 2976end 2977 2978@ @<DIR: Initialize |text_dir_ptr|@>= 2979begin 2980text_dir_ptr:=new_dir(0); 2981end 2982 2983@ @<DIR: Initialize |dir_ptr| for |ship_out|@>= 2984begin dir_ptr:=null; push_dir(dvi_direction); 2985dir_dvi_ptr(dir_ptr):=dvi_ptr; 2986end 2987 2988@ @<DIR: Initialize |dir_ptr| for |hpack|@>= 2989begin dir_ptr:=null; push_dir(hpack_dir) end 2990 2991@ @<DIR: Initialize |dir_ptr| for |line_break|@>= 2992begin dir_ptr:=null; push_dir(paragraph_dir); end 2993 2994@ @<Output a reflection instruction if the direction has changed@>= 2995begin 2996if dir_dir(p)>=0 then 2997 begin synch_h; synch_v; 2998 push_dir_node(p); 2999 if dir_opposite(dir_secondary[dir_dir(dir_ptr)])(dir_secondary[dvi_direction]) 3000 then begin 3001 if (dir_secondary[dvi_direction]=0) or 3002 (dir_secondary[dvi_direction]=2) then 3003 dvi_out(down4) 3004 else 3005 dvi_out(right4); 3006 dir_dvi_ptr(dir_ptr):=dvi_ptr; 3007 dir_dvi_h(dir_ptr):=dvi_h; 3008 dvi_four(0); 3009 cur_h:=0; dvi_h:=0; 3010 end 3011 else begin 3012 dir_dvi_ptr(dir_ptr):=dvi_ptr; 3013 dir_dvi_h(dir_ptr):=dvi_h; 3014 end; 3015 dvi_direction:=dir_dir(dir_ptr); 3016 end 3017else begin 3018 dvi_dir_h:=dir_dvi_h(dir_ptr); 3019 dvi_dir_ptr:=dir_dvi_ptr(dir_ptr); 3020 pop_dir_node; 3021 synch_h; synch_v; 3022 dvi_direction:=dir_dir(dir_ptr); 3023 if dir_opposite(dir_secondary[dir_dir(p)+64])(dir_secondary[dvi_direction]) 3024 then begin 3025 dvi_temp_ptr:=dvi_ptr; 3026 dvi_ptr:=dvi_dir_ptr; 3027 if (dir_secondary[dvi_direction]=0) or 3028 (dir_secondary[dvi_direction]=1) then 3029 dvi_four(dvi_h) 3030 else 3031 dvi_four(-dvi_h); 3032 dvi_ptr:=dvi_temp_ptr; 3033 if (dir_secondary[dvi_direction]=0) or 3034 (dir_secondary[dvi_direction]=2) then 3035 dvi_out(down4) 3036 else 3037 dvi_out(right4); 3038 if (dir_secondary[dvi_direction]=0) or 3039 (dir_secondary[dvi_direction]=1) then 3040 dvi_four(dvi_h) 3041 else 3042 dvi_four(-dvi_h); 3043 end; 3044 cur_h:=dvi_dir_h+dvi_h; dvi_h:=cur_h; 3045 end 3046end 3047@z 3048