*** UNDER DEVELOPMENT *** DVItype change file for LN03 output This change file has been produced by adding stuff to the Vax/VMS change file, originally due to David R. Fuchs. Author: Flavio Rose (c) 1983 by Digital Equipment Corporation Modified for DVItype version 2.6 by John Sauter, August 3, 1984. Version 0.8, quick fix to correct bug in rule merging. Version 0.9, another quick fix to match a Topp bug fix Version 0.91, issue an {X} command when position is changed because of max_drift @x \centerline{(Version 2.6, June 1984)} @y \centerline{(Version 2.6, June 1984)} \centerline{(Including LN03 Changes at Version 0.92)} @z @x \pageno=\contentspagenumber \advance\pageno by 1 @y \pageno=\contentspagenumber \advance\pageno by 1 \let\maybe=\iftrue \def\title{DVI$\,$\lowercase{type} changes for LN03} @z @x The |banner| string defined here should be changed whenever \.{DVItype} gets modified. @d banner=='This is DVItype, Version 2.6' {printed when the program starts} @y The present version of \.{DVItype} is quite special, because in addition to its normal output, it produces two extra files, with extensions \.{LNG} and \.{LNH}. These files can be converted by a second post-processor to commands for the Digital Equipment Corporation LN03 laser printer which will cause it to print the \.{DVI} file, provided the latter is not too complex. @^LNG file@> @^LNH file@> @^LN03 laser printer@> The \.{LNG} output file contains a font loading command, followed by a command which tells the postprocessor to read the \.{LNH} file. The \.{LNH} file contains postprocessor commands that are converted to the actual printing commands, including font selection. Two different files are used, because the information necessary to generate the font loading command is not available until we have finished reading the \.{DVI} file (given that we do not perform |random_reading|), yet the LN03 understandably wants to see the font loading command before it sees any printing commands. The |banner| string defined here should be changed whenever \.{DVItype} gets modified. @d banner=='This is DVItype, Version 2.6, with LN03 Version 0.92' @z @x @d random_reading==true {should we skip around in the file?} @d othercases == others: {default for cases not listed explicitly} @y @d random_reading==false {should we skip around in the file?} @d othercases == otherwise {Vax/VMS default for cases not listed explicitly} @z @x @d print(#)==write(#) @d print_ln(#)==write_ln(#) @y In fact, we do this under Vax/VMS. We also use double-precision for all real values. @d print(#)==write(type_file,#) @d print_ln(#)==write_ln(type_file,#) @d real==double @z @x @p program DVI_type(@!dvi_file,@!output); @y @p program DVI_type(@!dvi_file,@!tfm_file,@!type_file,@!input,@!output, @!lng_file,@!lnh_file); @z @x procedure initialize; {this procedure gets things started properly} var i:integer; {loop index for initializations} begin print_ln(banner);@/ @y @@/ procedure initialize; {this procedure gets things started properly} var i:integer; {loop index for initializations} begin @@/ print_ln(banner);@/ @z @x @!byte_file=packed file of eight_bits; {files that contain binary data} @y {later we'll define files that contain binary data} @z @x @!dvi_file:byte_file; {the stuff we are \.{DVI}typing} @!tfm_file:byte_file; {a font metric file} @y @!dvi_file:packed file of byte_block; {the stuff we are \.{DVI}typing} @!tfm_file:packed file of byte_block; {a font metric file} @!dvi_count:integer; {number of bytes read from current block of |dvi_file|} @!tfm_count:integer; {number of bytes read from current block of |tfm_file|} @z @x begin reset(dvi_file); @y begin reset(dvi_file); dvi_count:=0; @z @x begin reset(tfm_file,cur_name); @y begin close(tfm_file,@=error@>:=@=continue@>); {stupid Vax/VMS run-times} open(tfm_file,cur_name,@=readonly@>,@=error@>:=@=continue@>); reset(tfm_file,@=error@>:=@=continue@>); tfm_count:=0; @z @x @p procedure read_tfm_word; begin read(tfm_file,b0); read(tfm_file,b1); read(tfm_file,b2); read(tfm_file,b3); @y @d read_tfm_file(#)==begin if tfm_count=VAX_block_length then begin get(tfm_file,@=error:=continue@>); tfm_count:=0; end; #:=tfm_file^[tfm_count]; incr(tfm_count); end @p procedure read_tfm_word; begin read_tfm_file(b0); read_tfm_file(b1); read_tfm_file(b2); read_tfm_file(b3); @z @x @p function get_byte:integer; {returns the next byte, unsigned} var b:eight_bits; begin if eof(dvi_file) then get_byte:=0 else begin read(dvi_file,b); incr(cur_loc); get_byte:=b; end; end; @# function signed_byte:integer; {returns the next byte, signed} var b:eight_bits; begin read(dvi_file,b); incr(cur_loc); if b<128 then signed_byte:=b @+ else signed_byte:=b-256; end; @# function get_two_bytes:integer; {returns the next two bytes, unsigned} var a,@!b:eight_bits; begin read(dvi_file,a); read(dvi_file,b); cur_loc:=cur_loc+2; get_two_bytes:=a*256+b; end; @# function signed_pair:integer; {returns the next two bytes, signed} var a,@!b:eight_bits; begin read(dvi_file,a); read(dvi_file,b); cur_loc:=cur_loc+2; if a<128 then signed_pair:=a*256+b else signed_pair:=(a-256)*256+b; end; @# function get_three_bytes:integer; {returns the next three bytes, unsigned} var a,@!b,@!c:eight_bits; begin read(dvi_file,a); read(dvi_file,b); read(dvi_file,c); cur_loc:=cur_loc+3; get_three_bytes:=(a*256+b)*256+c; end; @# function signed_trio:integer; {returns the next three bytes, signed} var a,@!b,@!c:eight_bits; begin read(dvi_file,a); read(dvi_file,b); read(dvi_file,c); cur_loc:=cur_loc+3; if a<128 then signed_trio:=(a*256+b)*256+c else signed_trio:=((a-256)*256+b)*256+c; end; @# function signed_quad:integer; {returns the next four bytes, signed} var a,@!b,@!c,@!d:eight_bits; begin read(dvi_file,a); read(dvi_file,b); read(dvi_file,c); read(dvi_file,d); cur_loc:=cur_loc+4; if a<128 then signed_quad:=((a*256+b)*256+c)*256+d else signed_quad:=(((a-256)*256+b)*256+c)*256+d; end; @y @d read_dvi_file(#)==begin if dvi_count=VAX_block_length then begin get(dvi_file,@=error:=continue@>); dvi_count:=0; end; #:=dvi_file^[dvi_count]; incr(dvi_count); end @p function get_byte:integer; {returns the next byte, unsigned} var b:eight_bits; begin if eof(dvi_file) then get_byte:=0 else begin read_dvi_file(b); incr(cur_loc); get_byte:=b; end; end; @# function signed_byte:integer; {returns the next byte, signed} var b:eight_bits; begin read_dvi_file(b); incr(cur_loc); if b<128 then signed_byte:=b @+ else signed_byte:=b-256; end; @# function get_two_bytes:integer; {returns the next two bytes, unsigned} var a,@!b:eight_bits; begin read_dvi_file(a); read_dvi_file(b); cur_loc:=cur_loc+2; get_two_bytes:=a*256+b; end; @# function signed_pair:integer; {returns the next two bytes, signed} var a,@!b:eight_bits; begin read_dvi_file(a); read_dvi_file(b); cur_loc:=cur_loc+2; if a<128 then signed_pair:=a*256+b else signed_pair:=(a-256)*256+b; end; @# function get_three_bytes:integer; {returns the next three bytes, unsigned} var a,@!b,@!c:eight_bits; begin read_dvi_file(a); read_dvi_file(b); read_dvi_file(c); cur_loc:=cur_loc+3; get_three_bytes:=(a*256+b)*256+c; end; @# function signed_trio:integer; {returns the next three bytes, signed} var a,@!b,@!c:eight_bits; begin read_dvi_file(a); read_dvi_file(b); read_dvi_file(c); cur_loc:=cur_loc+3; if a<128 then signed_trio:=(a*256+b)*256+c else signed_trio:=((a-256)*256+b)*256+c; end; @# function signed_quad:integer; {returns the next four bytes, signed} var a,@!b,@!c,@!d:eight_bits; begin read_dvi_file(a); read_dvi_file(b); read_dvi_file(c); read_dvi_file(d); cur_loc:=cur_loc+4; if a<128 then signed_quad:=((a*256+b)*256+c)*256+d else signed_quad:=(((a-256)*256+b)*256+c)*256+d; end; @z @x begin set_pos(dvi_file,-1); dvi_length:=cur_pos(dvi_file); @y begin write_ln('Sorry, can''t do DVI_LENGTH.'); dvi_length:=0; @z @x begin set_pos(dvi_file,n); cur_loc:=n; @y begin write_ln('Sorry, can''t do MOVE_TO_BYTE.'); cur_loc:=0; @z @x @!width:array [0..max_widths] of integer; {character widths, in \.{DVI} units} @y @!width:array [0..max_widths] of integer; {character widths, in \.{DVI} units} @!chused: array [0..max_fonts,0..255] of boolean; {is character used?} @z @x if font_ec[nf] @y This version of \.{DVItype} derives the option values from the command line, where they are specified in a VMS-like syntax, e.g., \.{/s=10} to indicate starting page 10, \.{/n=200} to indicate a maximum of 200 output pages, and \.{/t=3} to indicate verbose typeout (|out_mode=the_works|). The default options that hold if the command line does not override them are \.{/s=*}, \.{/n=1000000} and \.{/t=0}. The use of a command line is of course not standard \PASCAL. The actual input of the line (into the array |command_line|) is done in the system-dependent section at the end of this \.{WEB} file. @^system dependencies@> @z @x @ The |input_ln| routine waits for the user to type a line at his or her terminal; then it puts ASCII-code equivalents for the characters on that line into the |buffer| array. The |term_in| file is used for terminal input, and |term_out| for terminal output. @^system dependencies@> @= @!buffer:array[0..terminal_line_length] of ASCII_code; @!term_in:text_file; {the terminal, considered as an input file} @!term_out:text_file; {the terminal, considered as an output file} @y @ The |term_out| file is used for terminal output. @^system dependencies@> @d term_out==output {the terminal, considered as an output file} @= @!buffer:array[0..terminal_line_length] of ASCII_code; @z @x @d update_terminal == break(term_out) {empty the terminal output buffer} @y On Vax/VMS, this is actually not necessary in this context, since the system gives us the effect of |update_terminal| automatically before every |read|. In this particular version of \.{DVItype}, since we don't even do terminal input, there is even less need of |update_terminal|. @d update_terminal == {the terminal output buffer is emptied by |read|} @z @x @ During the dialog, \.{DVItype} will treat the first blank space in a line as the end of that line. Therefore |input_ln| makes sure that there is always at least one blank space in |buffer|. @^system dependencies@> @p procedure input_ln; {inputs a line from the terminal} var k:0..terminal_line_length; begin update_terminal; reset(term_in); if eoln(term_in) then read_ln(term_in); k:=0; while (k' ') and (k' ') do incr(cmd_j); goto 1001 end; while (cmd_j<=cmd_len) and (command_line[cmd_j]<>' ') do incr(cmd_j) end; 1001: buffer[k]:=" "; end; @z @x label 1,2,3,4,5; @y @z @x 1: write(term_out,'Output level (default=3, ? for help): '); out_mode:=the_works; input_ln; if buffer[0]<>" " then if (buffer[0]>="0")and(buffer[0]<="3") then out_mode:=buffer[0]-"0" else begin write(term_out,'Type 3 for complete listing,'); write(term_out,' 0 for errors only,'); write_ln(term_out,' 1 or 2 for something in between.'); goto 1; end @y out_mode:=errors_only; cmd_j:=cmd_i; cmd_k:=1; while (cmd_j<=cmd_len) do begin input_option; if buffer[0]<>" " then if (buffer[0]>="0")and(buffer[0]<="3") then out_mode:=buffer[0]-"0" end @z @x 2: write(term_out,'Starting page (default=*): '); start_vals:=0; start_there[0]:=false; input_ln; buf_ptr:=0; k:=0; if buffer[0]<>" " then repeat if buffer[buf_ptr]="*" then begin start_there[k]:=false; incr(buf_ptr); end else begin start_there[k]:=true; start_count[k]:=get_integer; end; if (k<9)and(buffer[buf_ptr]=".") then begin incr(k); incr(buf_ptr); end else if buffer[buf_ptr]=" " then start_vals:=k else begin write(term_out,'Type, e.g., 1.*.-5 to specify the '); write_ln(term_out,'first page with \count0=1, \count2=-5.'); goto 2; end; until start_vals=k @y start_vals:=0; start_there[0]:=false; cmd_j:=cmd_i; cmd_k:=2; while (cmd_j<=cmd_len) do begin input_option; if (buffer[0]<>" ") then begin buf_ptr:= 0; k:=0; if buffer[0]<>" " then repeat if buffer[buf_ptr]="*" then begin start_there[k]:=false; incr(buf_ptr); end else begin start_there[k]:=true; start_count[k]:=get_integer; end; if (k<9)and(buffer[buf_ptr]=".") then begin incr(k); incr(buf_ptr); end else start_vals:=k { anything ill-formed we just stop } until start_vals=k end end @z @x 3: write(term_out,'Maximum number of pages (default=1000000): '); max_pages:=1000000; input_ln; buf_ptr:=0; if buffer[0]<>" " then begin max_pages:=get_integer; if max_pages<=0 then begin write_ln(term_out,'Please type a positive number.'); goto 3; end; end @y max_pages:=1000000; cmd_j:=cmd_i; cmd_k:=3; while (cmd_j<=cmd_len) do begin input_option; if (buffer[0]<>" ") then begin buf_ptr := 0; max_pages:=get_integer; if max_pages<=0 then max_pages:=1000000; end end @z @x 4: write(term_out,'Assumed device resolution'); write(term_out,' in pixels per inch (default=240/1): '); resolution:=240.0; input_ln; buf_ptr:=0; if buffer[0]<>" " then begin k:=get_integer; if (k>0)and(buffer[buf_ptr]="/")and (buffer[buf_ptr+1]>"0")and(buffer[buf_ptr+1]<="9") then begin incr(buf_ptr); resolution:=k/get_integer; end else begin write(term_out,'Type a ratio of positive integers;'); write_ln(term_out,' (1 pixel per mm would be 254/10).'); goto 4; end; end @y resolution:=300.0; { this is the LN03's resolution } @z @x 5: write(term_out,'New magnification (default=0 to keep the old one): '); new_mag:=0; input_ln; buf_ptr:=0; if buffer[0]<>" " then if (buffer[0]>="0")and(buffer[0]<="9") then new_mag:=get_integer else begin write(term_out,'Type a positive integer to override '); write_ln(term_out,'the magnification in the DVI file.'); goto 5; end @y new_mag:=0; { no provision for magnified LN03 output yet } @z @x if eof(tfm_file) then @y if status(tfm_file)<>0 then @z @x @d default_directory_name=='TeXfonts:' {change this to the correct name} @d default_directory_name_length=9 {change this to the correct length} @y @d default_directory_name=='TEX$FONTS:' {change this to the correct name} @d default_directory_name_length=10 {change this to the correct length} @z @x characters currently in the buffer. @y characters currently in the buffer. Something quite similar is done for output to the \.{LNH} file. @z @x @!text_buf:array[1..line_length] of ASCII_code; {saved characters} @y @!text_buf:array[1..line_length] of ASCII_code; {saved characters} @!lnh_ptr:0..511; {how much stuff written to lnh file this line} @z @x @ @= text_ptr:=0; @y @ @d lnh_char(#) == begin write(lnh_file,#); lnh_ptr := lnh_ptr+1; if lnh_ptr >= 132 then begin write_ln(lnh_file); lnh_ptr := 0 end end @d lnh_cs(#) == begin write(lnh_file,#); lnh_ptr := lnh_ptr+7; { conservatively } if lnh_ptr >= 132 then begin write_ln(lnh_file); lnh_ptr := 0 end end @= text_ptr:=0; lnh_ptr:=0; @z @x @ Strictly speaking, the |do_page| procedure is really a function with @y @ Rule Accumulation. We accumulate all rules generated on a page. At the end of the page, the rules are combined to form larger rules when possible, then output. @ Start by defining the maximum rule segments to be processed per page. @= @!max_rules=1000; {maximum number of rules per page} @!max_lap_rules=3; {maximum under/over lap of rules} @ A special record describes the rule rectangles encountered. @= @!rules = record {rule record} @!horiz,@; {Horizontal Coordinate} @!width,@; {Width in Horizontal Direction} @!vert,@; {Vertical Coordinate} @!height:integer; {Height in Vertical Direction} @!covered:boolean; {Indicates if combined} end; @ An array of |rules| is defined along with an index. @= @!page_rules:array[1..max_rules] of rules; {rules generated on this page} @!rules_on_page: 0..max_rules; {count of rules found on this page} @ Initialize |rules_on_page| to show no rules yet. @= @!rules_on_page := 0; {set no rules found yet} @ All rules are collected and placed into |page_rules|. Later, the rules will be merged. @= begin incr(rules_on_page); with page_rules[rules_on_page] do begin horiz := hh; vert := vv; height := rule_pixels(p); width := rule_pixels(q); covered := false; end; end; @ Rules can now be combined and output in the \.{LNH} file. To accomplish this the rules are scanned in vertical and then in horizontal order. During the scan adjacent rules are combined and marked as used. At completion, rules that aren't marked as |covered| are output. @= if rules_on_page > 0 then begin reduce_rules; for rules_on_page := rules_on_page downto 1 do with page_rules[rules_on_page] do if not covered then lnh_cs('{RULEA',horiz:1,' ',vert-height:1,' ', horiz+width:1,' ',vert:1,'}'); rules_on_page := 0 end; @ |reduce_rules| implements the rule reduction algorithm. Maps are generated for traversing all rules both horizontally and vertically. Rules can overlap or underlap by up to |max_lap_rules| in |height| or |width|. @p procedure reduce_rules; var horiz_map: array[1..max_rules] of 0..max_rules; verti_map: array[1..max_rules] of 0..max_rules; hi,hj,vi,vj: 0..max_rules; ht,vt:integer; begin for hi := 1 to rules_on_page do horiz_map[hi] := hi; for vi := 1 to rules_on_page do verti_map[vi] := vi; @@; @@; @@; @@; if showing then begin @@; end end; @ Build map for horizontal combination by sorting the rules into increasing vertical order and within the same vertical line into increasing horizontal order. This allows for rule combination by looking for |width| overlap. @= for hi := 1 to rules_on_page-1 do for hj := (hi+1) to rules_on_page do if (page_rules[horiz_map[hi]].vert > page_rules[horiz_map[hj]].vert) or ((page_rules[horiz_map[hi]].vert = page_rules[horiz_map[hj]].vert) and (page_rules[horiz_map[hi]].horiz > page_rules[horiz_map[hj]].horiz)) then begin ht:=horiz_map[hi]; horiz_map[hi]:=horiz_map[hj]; horiz_map[hj]:=ht end; @ Build map for vertical combination by sorting the rules into increasing horizontal order and within the same horizontal line into increasing vertical order. This allows for rule combination by looking for |height| overlap. @= for vi := 1 to rules_on_page-1 do for vj := (vi+1) to rules_on_page do if (page_rules[verti_map[vi]].horiz > page_rules[verti_map[vj]].horiz) or ((page_rules[verti_map[vi]].horiz = page_rules[verti_map[vj]].horiz) and (page_rules[verti_map[vi]].vert > page_rules[verti_map[vj]].vert)) then begin vt:=verti_map[vi]; verti_map[vi]:=verti_map[vj]; verti_map[vj]:=vt end; @ Traverse mapped rules looking for adjoining vertical rules. We actually look for |height| overlap within |max_lap_rules|. Rules that have been combined with other rules are set |covered := true|. @= for vi:=1 to rules_on_page-1 do with page_rules[verti_map[vi]] do if not covered then for vj:= vi+1 to rules_on_page do if not page_rules[verti_map[vj]].covered then begin vt := vert - (page_rules[verti_map[vj]].vert - page_rules[verti_map[vj]].height); if ((horiz = page_rules[verti_map[vj]].horiz) and (width = page_rules[verti_map[vj]].width) and (abs(vt) <= max_lap_rules)) then begin vert := page_rules[verti_map[vj]].vert; height := height + page_rules[verti_map[vj]].height - vt; page_rules[verti_map[vj]].covered := true; end; end; @ Traverse mapped rules looking for adjoining horizontal rules. We actually look for |width| overlap within |max_lap_rules|. Rules that have been combined with other rules are set |covered := true|. @= for hi:=1 to rules_on_page-1 do with page_rules[horiz_map[hi]] do if not covered then for hj:= hi+1 to rules_on_page do if not page_rules[horiz_map[hj]].covered then begin ht := (horiz+width) - page_rules[horiz_map[hj]].horiz; if ((vert = page_rules[horiz_map[hj]].vert) and (height = page_rules[horiz_map[hj]].height) and (abs(ht) <= max_lap_rules)) then begin width := width + page_rules[horiz_map[hj]].width - ht; page_rules[horiz_map[hj]].covered := true; end; end; @ Dump the Rules after processing. @= for vt := 1 to rules_on_page do with page_rules[vt] do print_ln('Rule ',vt:1,':horiz=',horiz:1,',vert=',vert:1, ',height=',height:1,',width=',width:1, ',covered=',covered,'.'); for vt := 1 to rules_on_page do print_ln('Vertical slot ',vt:1,' is Rule ',verti_map[vt]:1,';', 'Horizontal slot ',vt:1,' is Rule ',horiz_map[vt]:1,'.'); @ Strictly speaking, the |do_page| procedure is really a function with @z @x four_cases(put1): begin major('put',o-put1+1:1,' ',p:1); goto fin_set; end; @y four_cases(put1): begin major('put',o-put1+1:1,' ',p:1); if (p<32) or (p>=127) then lnh_cs('{CHAR',p:1,'}') else if p=123 then lnh_cs('{LB}') else lnh_char(xchr[p]); chused[cur_font,p]:=true; lnh_cs('{X',hh:1,'}'); goto fin_set; end; @z @x do_page:=true; print_ln(' '); goto 9999; end; @y @@; do_page:=true; print_ln(' '); write_ln(lnh_file,'{NEWPAGE}'); lnh_ptr:=0; goto 9999; end; @z @x else begin decr(s); hh:=hhstack[s]; vv:=vvstack[s]; @y else begin decr(s); if (vv <> vvstack[s]) then begin write_ln(lnh_file); lnh_ptr := 0; lnh_cs('{VPA',vvstack[s]:1,'}') end; if ((hh <> hhstack[s]) or (vv <> vvstack[s])) then lnh_cs('{X',hhstack[s]:1,'}'); hh:=hhstack[s]; vv:=vvstack[s]; @z @x minor(#,' ',p:1); q:=p; goto move_right @y minor(#,' ',p:1); lnh_cs('{X',hh:1,'}'); q:=p; goto move_right @z @x major(#,' ',p:1); goto move_down @y write_ln(lnh_file); lnh_ptr := 0; lnh_cs('{VPA',vv:1,'}'); lnh_cs('{X',hh:1,'}'); major(#,' ',p:1); goto move_down @z @x if o>=put1 then goto done; @y if (p<32) or (p>=127) then lnh_cs('{CHAR',p:1,'}') else if p=123 then lnh_cs('{LB}') else lnh_char(xchr[p]); chused[cur_font,p]:=true; if o>=put1 then goto done; @z @x if o=put_rule then goto done; @y if (p>0)and(q>0) then @@; if o=put_rule then goto done; if rule_pixels(q)<>0 then lnh_cs('{X',hh+rule_pixels(q):1,'}'); @z @x hhh:=pixel_round(h+q); if abs(hhh-hh)>max_drift then if hhh>hh then hh:=hhh-max_drift else hh:=hhh+max_drift; @y hhh:=pixel_round(h+q); if abs(hhh-hh)>max_drift then begin if hhh>hh then hh:=hhh-max_drift else hh:=hhh+max_drift; lnh_cs('{X',hh:1,'}') end; @z @x while font_num[cur_font]<>p do incr(cur_font); @y while font_num[cur_font]<>p do incr(cur_font); lnh_cs('{FO',cur_font:1,'}'); @z @x final_end:end. @y @; close(type_file,@=disposition:=save@>,@=error:=continue@>); close(lng_file,@=disposition:=save@>,@=error:=continue@>); close(lnh_file,@=disposition:=save@>,@=error:=continue@>); final_end:end. @z @x This section should be replaced, if necessary, by changes to the program that are necessary to make \.{DVItype} work at a particular installation. It is usually best to design your change file so that all changes to previous sections preserve the section numbering; then everybody's version will be consistent with the printed program. More extensive changes, which introduce new sections, can be inserted here; then only the index itself will get a new section number. @y Here are the remaining changes to the program that are necessary to make \.{DVItype} work on Vax/VMS. @== @!VAX_block_length=512; @ @== @!byte_block=packed array [0..VAX_block_length-1] of 0..255; @ On Vax/VMS we need the following special definitions, types, variables and procedures to be able to get the file name from the command line, or to prompt for them. @d VAX_volatile==@=volatile@> @d VAX_immed==@=%immed @> @d VAX_external==@=external@> @d VAX_stdescr==@=%stdescr @> @d VAX_lib_get_foreign==@= lib$get_foreign@> @d VAX_length==@=length @> @ @= @!sixteen_bits= 0..65535; @ @== @!type_file: text; @!lng_file: text; @!lnh_file: text; @!command_line:packed array[1..300] of char; @!cmd_len:sixteen_bits; @!cmd_i,cmd_j,cmd_k:integer; @!file_name,@!def_file_name:varying [300] of char; @!ask,@!got_file_name: boolean; @ @= open(output,'SYS$OUTPUT',@=error:=continue@>); {FIX ME! JUNK FOR RUN-TIME BUG} cmd_i:=0; VAX_lib_get_foreign(command_line,,cmd_len,cmd_i); cmd_i:=1; while (cmd_i<=cmd_len) and (command_line[cmd_i]=' ') do incr(cmd_i); got_file_name:=cmd_i<=cmd_len; cmd_j:=cmd_i; while (cmd_i<=cmd_len) and (command_line[cmd_i]<>' ') do incr(cmd_i); if got_file_name then def_file_name:=substr(command_line,cmd_j,cmd_i-cmd_j) else begin write_ln('Usage: dvi2lng '); goto final_end end; if got_file_name then begin file_name:=def_file_name+'.DVI'; open(dvi_file,file_name,@=readonly@>,@=error:=continue@>); ask:=status(dvi_file)<>0; if ask then begin write_ln('Couldn''t open ',file_name); goto final_end end end else ask:=true; if got_file_name then begin cmd_j:=1; for cmd_k:=1 to def_file_name.VAX_length do if (def_file_name[cmd_k]=']') or (def_file_name[cmd_k]=':') or (def_file_name[cmd_k]='>') then cmd_j:=cmd_k+1; if cmd_j<=def_file_name.VAX_length then def_file_name:=substr(def_file_name,cmd_j, def_file_name.VAX_length-cmd_j+1); file_name:=def_file_name+'.TYP'; open(type_file,file_name,@=new,32767,disposition:=delete@>, @=error:=continue@>); ask:=status(type_file)>0; if ask then begin write_ln('Couldn''t open ',file_name); goto final_end end end else ask:=true; rewrite(type_file); file_name := def_file_name+'.LNG'; open(lng_file,file_name,@=new,2047,disposition:=delete@>, @=error:=continue@>); ask:=status(lng_file)>0; if ask then begin write_ln('Couldn''t open ',file_name); goto final_end end; rewrite(lng_file); file_name := def_file_name+'.LNH'; open(lnh_file,file_name,@=new,511,disposition:=delete@>, @=error:=continue@>); ask:=status(lnh_file)>0; if ask then begin write_ln('Couldn''t open ',file_name); goto final_end end; rewrite(lnh_file); @ Here is the library procedure that gets the user's command line. @= [VAX_external] function VAX_lib_get_foreign( VAX_stdescr cmdlin:[VAX_volatile] packed array [$l1..$u1:integer] of char := VAX_immed 0; VAX_stdescr prompt:[VAX_volatile] packed array [$l2..$u2:integer] of char := VAX_immed 0; var len : [VAX_volatile] sixteen_bits := VAX_immed 0; var flag : [VAX_volatile] integer := VAX_immed 0) :integer; extern; @ This code writes the font info into the LNG file. @= for m := 0 to nf-1 do begin write(lng_file,'{CU ',m:1,' '); for k := 0 to font_ec[m] do begin if chused[m,k] then write(lng_file,'1') else write(lng_file,'0') end; write_ln(lng_file,'}') end; write(lng_file,'{WLN'); for m := 0 to nf-1 do begin write(lng_file,' '); for n := font_name[m] to font_name[m+1]-1 do write(lng_file, xchr[names[n]]); k := trunc((100.0*conv*font_scaled_size[m])/(true_conv* font_design_size[m])+0.5); if k<>100 then begin if k> 100 then write(lng_file,'.',k:1) else if k >= 10 then write(lng_file,'.0',k:1) else if k > 0 then write(lng_file,'.00',k:1) end; write(lng_file,' ',m:1) end; write(lng_file,'}'); write_ln(lng_file); write(lng_file,'{INCLUDE ',def_file_name,'.LNH}') @z