% DviReader.ch change file for DVItype.web % for Java compilation with web2java. % % 07/15/96 (TGM) Java version A. @x l.49 --- WEAVE: print changes only. \pageno=\contentspagenumber \advance\pageno by 1 @y \pageno=\contentspagenumber \advance\pageno by 1 \let\maybe=\iffalse \def\title{DVI$\,$\lowercase{type} changes for Java} @z @x l.89 @d banner=='This is DVItype, Version 3.5' {printed when the program starts} @y @d banner=='This is DVItype, Version 3.5 [Java version B]' {printed when the program starts} @z @x l.114 @d random_reading==true {should we skip around in the file?} @y @d random_reading==false {should we skip around in the file?} @z @x [3] We don't print out symbolic values. @d print(#)==write(#) @d print_ln(#)==write_ln(#) @y @d term_out==log @d print(#)==pri@&nt(term_out,#) @d print_ln(#)==pri@&nt_ln(term_out,#) @d integer == int @d real == double @d chr(#) == cast(char,#) @d loop == @+ while true do@+ {repeat over and over until a |goto| happens} @d eof(#) == #.e@&o@&f @d abs(#) == Math.ab@&s(#) @d round(#) == cast(int,Math.rou@&nd(#)) @d trunc(#) == cast(int,Math.rou@&nd(#-0.4999)) @d break == goto 0 @d reset(#)== @d rewrite(#)== @d hh==Hh @d exit = 10 @d return == goto exit {terminate a procedure call} @z @x Could add command-line options here. @p program DVI_type(@!dvi_file,@!output); @y @p program DviReader(@!printer:DVI) implements Runnable; @z @x type @@/ @y @z @x l.145 @=final_end,done; @y @=done; @z @x [5] Allow more widths, no arbitrary filename length. @!max_fonts=100; {maximum number of distinct fonts per \.{DVI} file} @!max_widths=10000; {maximum number of different characters among all fonts} @y @!max_fonts=500; {maximum number of distinct fonts per \.{DVI} file} @!max_widths=25000; {maximum number of different characters among all fonts} @!max_virtual_level=4; {maximum recursion level in virtual fonts} @z @@x @!name_length=50; {a file name shouldn't be longer than this} @@y @@z @x l.181 @p procedure jump_out; begin goto final_end; end; @y @p procedure jump_out; begin System.exi@&t(1); end; @z @x l.200 @= @!ASCII_code=" ".."~"; {a subrange of the integers} @y @d ASCII_code==0..255 {a subrange of the integers} @z @x l.222 @d last_text_char=127 {ordinal number of the largest element of |text_char|} @= @!text_file=packed file of text_char; @y @d last_text_char=255 {ordinal number of the largest element of |text_char|} @d text_file==dont_make alpha_out; @z @x [10] @!xord: array [text_char] of ASCII_code; @y @!xord: array [0..255] of ASCII_code; @z @x @= @!eight_bits=0..255; {unsigned one-byte quantity} @!byte_file=packed file of eight_bits; {files that contain binary data} @y @d eight_bits==0..255 {unsigned one-byte quantity} @z @x l.864 @!dvi_file:byte_file; {the stuff we are \.{DVI}typing} @!tfm_file:byte_file; {a font metric file} @y @!dvi_file:dont_make byte_file; {the stuff we are \.{DVI}typing} @!tfm_file:dont_make byte_file; {a font metric file} @z @x l.876 @p procedure open_dvi_file; {prepares to read packed bytes in |dvi_file|} begin reset(dvi_file); cur_loc:=0; end; @# procedure open_tfm_file; {prepares to read packed bytes in |tfm_file|} begin reset(tfm_file,cur_name); end; @y @p procedure open_dvi_file; {prepares to read packed bytes in |dvi_file|} begin dvi_file:=dont_make printer.dviStream(0); cur_loc:=0; end; @# procedure open_tfm_file; {prepares to read packed bytes in |tfm_file|} begin reset(tfm_file,cur_name); end; @z @x [line 893] @!cur_name:packed array[1..name_length] of char; {external name, with no lower case letters} @y @!cur_name:String; {external name} @z @x @p procedure read_tfm_word; begin read(tfm_file,b0); read(tfm_file,b1); read(tfm_file,b2); read(tfm_file,b3); end; @y @p procedure read_tfm_word; begin end; @z @@x [line 919] @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 @f shl div_like @f shr div_like @p function get_byte:integer throws IOException; {returns the next byte, unsigned} begin try begin get_byte:=dvi_file.readUnsignedByte; incr(cur_loc); end; catch(ex:EOFException) begin print_ln('Unexpected EOF in byte ', cur_loc); get_byte:=0; eof(dvi_file):=true; end; end; @# function signed_byte:integer throws IOException; {returns the next byte, signed} begin try begin signed_byte:=dvi_file.readByte; incr(cur_loc); get_byte:=0; end; catch(ex:EOFException) begin print_ln('Unexpected EOF in byte ', cur_loc); get_byte:=0; eof(dvi_file):=true; end; end; @# function get_two_bytes:integer throws IOException; {returns the next two bytes, unsigned} begin try begin get_two_bytes:=dvi_file.readUnsignedShort; cur_loc:=cur_loc+2; end; catch(ex:EOFException) begin print_ln('Unexpected EOF in byte ', cur_loc); get_byte:=0; eof(dvi_file):=true; end; end; @# function signed_pair:integer throws IOException; {returns the next two bytes, signed} begin try begin signed_pair:=dvi_file.readShort; cur_loc:=cur_loc+2; end; catch(ex:EOFException) begin print_ln('Unexpected EOF in byte ', cur_loc); get_byte:=0; eof(dvi_file):=true; end; end; @# function get_three_bytes:integer throws IOException; {returns the next three bytes, unsigned} var n: integer; begin try begin n:=dvi_file.readUnsignedShort; get_three_bytes:=(n shl 8) + dvi_file.readUnsignedByte; cur_loc:=cur_loc+3; end; catch(ex:EOFException) begin print_ln('Unexpected EOF in byte ', cur_loc); get_byte:=0; eof(dvi_file):=true; end; end; @# function signed_trio:integer throws IOException; {returns the next three bytes, signed} var n: integer; begin try begin n:=dvi_file.readShort; get_three_bytes:=(n shl 8) + dvi_file.readUnsignedByte; cur_loc:=cur_loc+3; end; catch(ex:EOFException) begin print_ln('Unexpected EOF in byte ', cur_loc); get_byte:=0; eof(dvi_file):=true; end; end; @# function signed_quad:integer throws IOException; {returns the next four bytes, signed} begin try begin signed_quad:=dvi_file.readInt; cur_loc:=cur_loc+4; end; catch(ex:EOFException) begin print_ln('Unexpected EOF in byte ', cur_loc); get_byte:=0; eof(dvi_file):=true; end; end; @@z @x [28] dvi_length and move_to_byte. @p function dvi_length:integer; begin set_pos(dvi_file,-1); dvi_length:=cur_pos(dvi_file); end; @# procedure move_to_byte(n:integer); begin set_pos(dvi_file,n); cur_loc:=n; end; @y @p function dvi_length:integer; var len:integer; begin dvi_length:=0; { try begin dvi_length:=cast(int,dvi_file.length); end; catch(ex:IOException) begin print_ln('IO error in dvi_length()'); end; } end; @# procedure move_to_byte(n:integer); begin { try begin dvi_file.seek(cast(long,n)); cur_loc:=n; eof(dvi_file):=false; end; catch(ex:IOException) begin print_ln('IO error in move_to_byte()'); end; } end; @z @x Omit TFM material [line 994] @* Reading the font information. \.{DVI} file format does not include information about character widths, since that would tend to make the files a lot longer. But a program that reads a \.{DVI} file is supposed to know the widths of the characters that appear in \\{set\_char} commands. Therefore \.{DVItype} looks at the font metric (\.{TFM}) files for the fonts that are involved. @.TFM {\rm files}@> The character-width data appears also in other files (e.g., in \.{GF} files that specify bit patterns for digitized characters); thus, it is usually possible for \.{DVI} reading programs to get by with accessing only one file per font. \.{DVItype} has a comparatively easy task in this regard, since it needs only a few words of information from each font; other \.{DVI}-to-printer programs may have to go to some pains to deal with complications that arise when a large number of large font files all need to be accessed simultaneously. @ For purposes of this program, we need to know only two things about a given character |c| in a given font |f|: (1)~Is |c| a legal character in~|f|? (2)~If so, what is the width of |c|? We also need to know the symbolic name of each font, so it can be printed out, and we need to know the approximate size of inter-word spaces in each font. The answers to these questions appear implicitly in the following data structures. The current number of known fonts is |nf|. Each known font has an internal number |f|, where |0<=finvalid_width|. Finally, |char_width(f)(c)=width[width_base[f]+c]|, and |width_ptr| is the first unused position of the |width| array. @d char_width_end(#)==#] @d char_width(#)==width[width_base[#]+char_width_end @d invalid_width==@'17777777777 @d invalid_font==max_fonts @= @!font_num:array [0..max_fonts] of integer; {external font numbers} @!font_name:array [0..max_fonts] of 1..name_size; {starting positions of external font names} @!names:array [1..name_size] of ASCII_code; {characters of names} @!font_check_sum:array [0..max_fonts] of integer; {check sums} @!font_scaled_size:array [0..max_fonts] of integer; {scale factors} @!font_design_size:array [0..max_fonts] of integer; {design sizes} @!font_space:array [0..max_fonts] of integer; {boundary between ``small'' and ``large'' spaces} @!font_bc:array [0..max_fonts] of integer; {beginning characters in fonts} @!font_ec:array [0..max_fonts] of integer; {ending characters in fonts} @!width_base:array [0..max_fonts] of integer; {index into |width| table} @!width:array [0..max_widths] of integer; {character widths, in \.{DVI} units} @!nf:0..max_fonts; {the number of known fonts} @!width_ptr:0..max_widths; {the number of known character widths} @ @= nf:=0; width_ptr:=0; font_name[0]:=1;@/ font_space[invalid_font]:=0; {for |out_space| and |out_vmove|} font_bc[invalid_font]:=1; font_ec[invalid_font]:=0; @ It is, of course, a simple matter to print the name of a given font. @p procedure print_font(@!f:integer); {|f| is an internal font number} var k:0..name_size; {index into |names|} begin if f=invalid_font then print('UNDEFINED!') @.UNDEFINED@> else begin for k:=font_name[f] to font_name[f+1]-1 do print(xchr[names[k]]); end; end; @ An auxiliary array |in_width| is used to hold the widths as they are input. The global variables |tfm_check_sum| and |tfm_design_size| are set to the check sum and design size that appear in the current \.{TFM} file. @= @!in_width:array[0..255] of integer; {\.{TFM} width data in \.{DVI} units} @!tfm_check_sum:integer; {check sum found in |tfm_file|} @!tfm_design_size:integer; {design size found in |tfm_file|, in \.{DVI} units} @!tfm_conv:real; {\.{DVI} units per absolute \.{TFM} unit} @ Here is a procedure that absorbs the necessary information from a \.{TFM} file, assuming that the file has just been successfully reset so that we are ready to read its first byte. (A complete description of \.{TFM} file format appears in the documentation of \.{TFtoPL} and will not be repeated here.) The procedure does not check the \.{TFM} file for validity, nor does it give explicit information about what is wrong with a \.{TFM} file that proves to be invalid; \.{DVI}-reading programs need not do this, since \.{TFM} files are almost always valid, and since the \.{TFtoPL} utility program has been specifically designed to diagnose \.{TFM} errors. The procedure simply returns |false| if it detects anything amiss in the \.{TFM} data. There is a parameter, |z|, which represents the scaling factor being used to compute the font dimensions; it must be in the range $0; @; @; @; width_ptr:=wp; in_TFM:=true; goto 9999; 9997: print_ln('---not loaded, TFM file is bad'); @.TFM file is bad@> 9998: in_TFM:=false; 9999: end; @ @= read_tfm_word; lh:=b2*256+b3; read_tfm_word; font_bc[nf]:=b0*256+b1; font_ec[nf]:=b2*256+b3; if font_ec[nf]max_widths then begin print_ln('---not loaded, DVItype needs larger width table'); @.DVItype needs larger...@> goto 9998; end; wp:=width_ptr+font_ec[nf]-font_bc[nf]+1; read_tfm_word; nw:=b0*256+b1; if (nw=0)or(nw>256) then goto 9997; for k:=1 to 3+lh do begin if eof(tfm_file) then goto 9997; read_tfm_word; if k=4 then if b0<128 then tfm_check_sum:=((b0*256+b1)*256+b2)*256+b3 else tfm_check_sum:=(((b0-256)*256+b1)*256+b2)*256+b3 else if k=5 then if b0<128 then tfm_design_size:=round(tfm_conv*(((b0*256+b1)*256+b2)*256+b3)) else goto 9997; end; @ @= if wp>0 then for k:=width_ptr to wp-1 do begin read_tfm_word; if b0>nw then goto 9997; width[k]:=b0; end; @ The most important part of |in_TFM| is the width computation, which involves multiplying the relative widths in the \.{TFM} file by the scaling factor in the \.{DVI} file. This fixed-point multiplication must be done with precisely the same accuracy by all \.{DVI}-reading programs, in order to validate the assumptions made by \.{DVI}-writing programs like \TeX82. Let us therefore summarize what needs to be done. Each width in a \.{TFM} file appears as a four-byte quantity called a |fix_word|. A |fix_word| whose respective bytes are $(a,b,c,d)$ represents the number $$x=\left\{\vcenter{\halign{$#$,\hfil\qquad&if $#$\hfil\cr b\cdot2^{-4}+c\cdot2^{-12}+d\cdot2^{-20}&a=0;\cr -16+b\cdot2^{-4}+c\cdot2^{-12}+d\cdot2^{-20}&a=255.\cr}}\right.$$ (No other choices of $a$ are allowed, since the magnitude of a \.{TFM} dimension must be less than 16.) We want to multiply this quantity by the integer~|z|, which is known to be less than $2^{27}$. If $|z|<2^{23}$, the individual multiplications $b\cdot z$, $c\cdot z$, $d\cdot z$ cannot overflow; otherwise we will divide |z| by 2, 4, 8, or 16, to obtain a multiplier less than $2^{23}$, and we can compensate for this later. If |z| has thereby been replaced by $|z|^\prime=|z|/2^e$, let $\beta=2^{4-e}$; we shall compute $$\lfloor(b+c\cdot2^{-8}+d\cdot2^{-16})\,z^\prime/\beta\rfloor$$ if $a=0$, or the same quantity minus $\alpha=2^{4+e}z^\prime$ if $a=255$. This calculation must be done exactly, for the reasons stated above; the following program does the job in a system-independent way, assuming that arithmetic is exact on numbers less than $2^{31}$ in magnitude. @= @; for k:=0 to nw-1 do begin read_tfm_word; in_width[k]:=(((((b3*z)div@'400)+(b2*z))div@'400)+(b1*z))div beta; if b0>0 then if b0<255 then goto 9997 else in_width[k]:=in_width[k]-alpha; end @ @= begin alpha:=16; while z>=@'40000000 do begin z:=z div 2; alpha:=alpha+alpha; end; beta:=256 div alpha; alpha:=alpha*z; end @ A \.{DVI}-reading program usually works with font files instead of \.{TFM} files, so \.{DVItype} is atypical in that respect. Font files should, however, contain exactly the same character width data that is found in the corresponding \.{TFM}s; check sums are used to help ensure this. In addition, font files usually also contain the widths of characters in pixels, since the device-independent character widths of \.{TFM} files are generally not perfect multiples of pixels. The |pixel_width| array contains this information; when |width[k]| is the device-independent width of some character in \.{DVI} units, |pixel_width[k]| is the corresponding width of that character in an actual font. The macro |char_pixel_width| is set up to be analogous to |char_width|. @d char_pixel_width(#)==pixel_width[width_base[#]+char_width_end @= @!pixel_width:array[0..max_widths] of integer; {actual character widths, in pixels} @!conv:real; {converts \.{DVI} units to pixels} @!true_conv:real; {converts unmagnified \.{DVI} units to pixels} @!numerator,@!denominator:integer; {stated conversion ratio} @!mag:integer; {magnification factor times 1000} @ The following code computes pixel widths by simply rounding the \.{TFM} widths to the nearest integer number of pixels, based on the conversion factor |conv| that converts \.{DVI} units to pixels. However, such a simple formula will not be valid for all fonts, and it will often give results that are off by $\pm1$ when a low-resolution font has been carefully hand-fitted. For example, a font designer often wants to make the letter `m' a pixel wider or narrower in order to make the font appear more consistent. \.{DVI}-to-printer programs should therefore input the correct pixel width information from font files whenever there is a chance that it may differ. A warning message may also be desirable in the case that at least one character is found whose pixel width differs from |conv*width| by more than a full pixel. @^system dependencies@> @d pixel_round(#)==round(conv*(#)) @= if in_width[0]<>0 then goto 9997; {the first width should be zero} width_base[nf]:=width_ptr-font_bc[nf]; if wp>0 then for k:=width_ptr to wp-1 do if width[k]=0 then begin width[k]:=invalid_width; pixel_width[k]:=0; end else begin width[k]:=in_width[width[k]]; pixel_width[k]:=pixel_round(width[k]); end @y @* Reading the font information. @d invalid_font==max_fonts @= @!font_num:array [0..max_fonts] of integer; {external font numbers} @!font_name:array [0..max_fonts] of 1..name_size; {starting positions of external font names} @!names:array [1..name_size] of ASCII_code; {characters of names} @!font_space:array [0..max_fonts] of integer; {boundary between ``small'' and ``large'' spaces} @!nf:0..max_fonts; {the number of known fonts} @!conv:real; {converts \.{DVI} units to pixels} @!true_conv:real; {converts unmagnified \.{DVI} units to pixels} @!numerator,@!denominator:integer; {stated conversion ratio} @!mag:integer; {magnification factor times 1000} @z @@x begin @; @; @; @; width_ptr:=wp; in_TFM:=true; goto 9999; 9997: print_ln('---not loaded, TFM file is bad'); @.TFM file is bad@> 9998: in_TFM:=false; 9999: end; @@y begin 9999: loop begin 9998: loop begin 9997: loop begin @; @; @; @; width_ptr:=wp; in_TFM:=true; goto 9999; {9997:}break end; print_ln('---not loaded, TFM file is bad'); @.TFM file is bad@> {9998:}break end; in_TFM:=false; {9999:}break end; end; @@z @x [line 1282] @!out_mode:errors_only..the_works; {controls the amount of output} @!max_pages:integer; {at most this many |bop..eop| pages will be printed} @!resolution:real; {pixels per inch} @!new_mag:integer; {if positive, overrides the postamble's magnification} @y @!out_mode:public errors_only..the_works; {controls the amount of output} @!max_pages:public integer; {at most this many |bop..eop| pages will be printed} @!resolution:public real; {pixels per inch} @!new_mag:public integer; {if positive, overrides the postamble's magnification} @z @x [line 1302] out_mode:=the_works; max_pages:=1000000; start_vals:=0; start_there[0]:=false; @y out_mode:=errors_only; max_pages:=1000000; start_vals:=0; start_there[0]:=false; resolution:=600.0; @z @x [45, line 1316] @ 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 @ We send diagnostic output to |log|. @= @!log:public dont_make PrintStream; @z @x [47] No input_ln. @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= @!buf_ptr:0..terminal_line_length; {the number of characters read} @y @ No dialog. @z @x [49] No dialog. @ Here is a routine that scans a (possibly signed) integer and computes the decimal value. If no decimal integer starts at |buf_ptr|, the value 0 is returned. The integer should be less than $2^{31}$ in absolute value. @p function get_integer:integer; var x:integer; {accumulates the value} @!negative:boolean; {should the value be negated?} begin if buffer[buf_ptr]="-" then begin negative:=true; incr(buf_ptr); end else negative:=false; x:=0; while (buffer[buf_ptr]>="0")and(buffer[buf_ptr]<="9") do begin x:=10*x+buffer[buf_ptr]-"0"; incr(buf_ptr); end; if negative then get_integer:=-x @+ else get_integer:=x; end; @y @ No dialog. @z @x [50-55] No dialog. @ The selected options are put into global variables by the |dialog| procedure, which is called just as \.{DVItype} begins. @^system dependencies@> @p procedure dialog; label 1,2,3,4,5; var k:integer; {loop variable} begin rewrite(term_out); {prepare the terminal for output} write_ln(term_out,banner); @; @; @; @; @; @; end; @ @= 1: write(term_out,'Output level (default=4, ? for help): '); out_mode:=the_works; input_ln; if buffer[0]<>" " then if (buffer[0]>="0")and(buffer[0]<="4") then out_mode:=buffer[0]-"0" else begin write(term_out,'Type 4 for complete listing,'); write(term_out,' 0 for errors only,'); write_ln(term_out,' 1 or 2 or 3 for something in between.'); goto 1; end @ @= 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 @ @= 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 @ @= 4: write(term_out,'Assumed device resolution'); write(term_out,' in pixels per inch (default=300/1): '); resolution:=300.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 @ @= 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 @ No dialog (50). @ No dialog (51). @ No dialog (52). @ No dialog (53). @ No dialog (54). @ No dialog (55). @z @@x [56] Fix printing of floating point number. print_ln(' Resolution = ',resolution:12:8,' pixels per inch'); if new_mag>0 then print_ln(' New magnification factor = ',new_mag/1000:8:3) @@y print (' Resolution = '); print_real (resolution, 12, 8); print_ln (' pixels per inch'); if new_mag > 0 then begin print (' New magnification factor = '); print_real (new_mag / 1000.0, 8, 3); print_ln('') end @@z @x [line 1512] @p procedure define_font(@!e:integer); {|e| is an external font number} var f:0..max_fonts; @y @p @t\4@>@@; procedure define_font(@!e:integer) throws IOException; {|e| is an external font number} var f:0..max_fonts; name_buf: StringBuffer; @z @x [line 1539] @ @= begin if font_check_sum[f]<>c then print_ln('---check sum doesn''t match previous definition!'); @.check sum doesn't match@> if font_scaled_size[f]<>q then print_ln('---scaled size doesn''t match previous definition!'); @.scaled size doesn't match@> if font_design_size[f]<>d then print_ln('---design size doesn''t match previous definition!'); @.design size doesn't match@> j:=font_name[f]; k:=font_name[nf]; if font_name[f+1]-j<>font_name[nf+1]-k then mismatch:=true else begin mismatch:=false; while jnames[k] then mismatch:=true; incr(j); incr(k); end; end; if mismatch then print_ln('---font name doesn''t match previous definition!'); @.font name doesn't match@> end @y @ @d font_err(#)==begin print(cur_name); font_named:=true; print_ln(#) end @= @z @x [line 1561] @ @= c:=signed_quad; font_check_sum[nf]:=c;@/ q:=signed_quad; font_scaled_size[nf]:=q;@/ d:=signed_quad; font_design_size[nf]:=d;@/ if (q<=0) or (d<=0) then m:=1000 else m:=round((1000.0*conv*q)/(true_conv*d)); p:=get_byte; n:=get_byte; if font_name[nf]+n+p>name_size then abort('DVItype capacity exceeded (name size=',name_size:1,')!'); @.DVItype capacity exceeded...@> font_name[nf+1]:=font_name[nf]+n+p; if showing then print(': ') {when |showing| is true, the font number has already been printed} else print('Font ',e:1,': '); if n+p=0 then print('null font name!') @.null font name@> else for k:=font_name[nf] to font_name[nf+1]-1 do names[k]:=get_byte; print_font(nf); if not showing then if m<>1000 then print(' scaled ',m:1) @.scaled@> @y @ @= c:=signed_quad; q:=signed_quad; d:=signed_quad; font_named:=false; p:=get_byte; n:=get_byte; name_buf:=new StringBuffer; if n+p=0 then font_err('null font name!') @.null font name@> else for j:=1 to n+p do begin k:=get_byte; name_buf.append(xchr[k]); end; cur_name:=name_buf.toString; if showing then begin print_ln(': ', cur_name); font_named:=true end; @z @x [line 1582] @ @= begin @; open_tfm_file; if eof(tfm_file) then print('---not loaded, TFM file can''t be opened!') @.TFM file can\'t be opened@> else begin if (q<=0)or(q>=@'1000000000) then print('---not loaded, bad scale (',q:1,')!') @.bad scale@> else if (d<=0)or(d>=@'1000000000) then print('---not loaded, bad design size (',d:1,')!') @.bad design size@> else if in_TFM(q) then @; end; if out_mode=errors_only then print_ln(' '); end @y @ @= begin printer.defineFont(nf,c,q,d,'',cur_name,null); font_space[nf]:=q div 6; {this is a 3-unit ``thin space''} incr(nf); {now the new font is officially present} end @z @x [line 1599] @ @= begin font_space[nf]:=q div 6; {this is a 3-unit ``thin space''} if (c<>0)and(tfm_check_sum<>0)and(c<>tfm_check_sum) then begin print_ln('---beware: check sums do not agree!'); @.beware: check sums do not agree@> @.check sums do not agree@> print_ln(' (',c:1,' vs. ',tfm_check_sum:1,')'); print(' '); end; if abs(tfm_design_size-d)>2 then begin print_ln('---beware: design sizes do not agree!'); @.beware: design sizes do not agree@> @.design sizes do not agree@> print_ln(' (',d:1,' vs. ',tfm_design_size:1,')'); print(' '); end; print('---loaded at size ',q:1,' DVI units'); d:=round((100.0*conv*q)/(true_conv*d)); if d<>100 then begin print_ln(' '); print(' (this font is magnified ',d:1,'%)'); end; @.this font is magnified@> incr(nf); {now the new font is officially present} end @y @z @@x [59] We use r for something else. @!r:0..name_length; {index into |cur_name|} @@y @!r:0..name_size; {current filename length} @@z @@x [61] else m:=round((1000.0*conv*q)/(true_conv*d)); @@y else m:=round((1000.0*conv*q)/(true_conv*d)); @@z @@x [64] Don't set default_directory_name. @d default_directory_name=='TeXfonts:' {change this to the correct name} @d default_directory_name_length=9 {change this to the correct length} @= @!default_directory:packed array[1..default_directory_name_length] of char; @@y Under Unix, users have a path searched for fonts, there's no single default directory. @@z @x [64] @d default_directory_name=='TeXfonts:' {change this to the correct name} @d default_directory_name_length=9 {change this to the correct length} @= @!default_directory:packed array[1..default_directory_name_length] of char; @y @d default_directory_name=='' {change this to the correct name} @d default_directory_name_length=0 {change this to the correct length} @= @!default_directory:String; @!def_dir:String; @z @@x [65] @ @= default_directory:=default_directory_name; @@y @ @= def_dir:=default_directory_name; for i:=1 to default_directory_name_length do default_directory[i]:=def_dir.charAt(i-1); @@z @x [line 1646] @= for k:=1 to name_length do cur_name[k]:=' '; if p=0 then begin for k:=1 to default_directory_name_length do cur_name[k]:=default_directory[k]; r:=default_directory_name_length; end else r:=0; for k:=font_name[nf] to font_name[nf+1]-1 do begin incr(r); if r+4>name_length then abort('DVItype capacity exceeded (max font name length=', name_length:1,')!'); @.DVItype capacity exceeded...@> if (names[k]>="a")and(names[k]<="z") then cur_name[r]:=xchr[names[k]-@'40] else cur_name[r]:=xchr[names[k]]; end; cur_name[r+1]:='.'; cur_name[r+2]:='T'; cur_name[r+3]:='F'; cur_name[r+4]:='M' @y @= @z @@x [66] Don't append `.tfm' here, and keep lowercase. @ The string |cur_name| is supposed to be set to the external name of the \.{TFM} file for the current font. This usually means that we need to prepend the name of the default directory, and to append the suffix `\.{.TFM}'. Furthermore, we change lower case letters to upper case, since |cur_name| is a \PASCAL\ string. @^system dependencies@> @= for k:=1 to name_length do cur_name[k]:=' '; if p=0 then begin for k:=1 to default_directory_name_length do cur_name[k]:=default_directory[k]; r:=default_directory_name_length; end else r:=0; for k:=font_name[nf] to font_name[nf+1]-1 do begin incr(r); if r+4>name_length then abort('DVItype capacity exceeded (max font name length=', name_length:1,')!'); @.DVItype capacity exceeded...@> if (names[k]>="a")and(names[k]<="z") then cur_name[r]:=xchr[names[k]-@'40] else cur_name[r]:=xchr[names[k]]; end; cur_name[r+1]:='.'; cur_name[r+2]:='T'; cur_name[r+3]:='F'; cur_name[r+4]:='M' @@y @ The string |cur_name| is supposed to be set to the external name of the \.{TFM} file for the current font. We do not impose a maximum limit here. It's too bad there is a limit on the total length of all filenames, but it doesn't seem worth reprogramming all that. @^system dependencies@> @d name_start == font_name[nf] @d name_end == font_name[nf+1] @= r := name_end - name_start; cur_name := xmalloc (r + 1); {|strncpy| might be faster, but it's probably a good idea to keep the |xchr| translation.} for k := name_start to name_end do begin cur_name[k - name_start] := xchr[names[k]]; end; cur_name[r] := 0; {Append null byte for C.} @@z @@x if (names[k]>="a")and(names[k]<="z") then cur_name[r]:=xchr[names[k]-@'40] else cur_name[r]:=xchr[names[k]]; end; cur_name[r+1]:='.'; cur_name[r+2]:='T'; cur_name[r+3]:='F'; cur_name[r+4]:='M' @@y cur_name[r]:=xchr[names[k]]; end; cur_name[r+1]:='.'; cur_name[r+2]:='t'; cur_name[r+3]:='f'; cur_name[r+4]:='m'; name_len:=r+4; @@z @x [line 1575] @p function first_par(o:eight_bits):integer; @y @p function first_par(o:eight_bits):integer throws IOException; @z @x [line 1758] begin case o of @y begin first_par:=0; case o of @z @x @ Here is another subroutine that we need: It computes the number of pixels in the height or width of a rule. Characters and rules will line up properly if the sizes are computed precisely as specified here. (Since |conv| is computed with some floating-point roundoff error, in a machine-dependent way, format designers who are tailoring something for a particular resolution should not plan their measurements to come out to an exact integer number of pixels; they should compute things so that the rule dimensions are a little less than an integer number of pixels, e.g., 4.99 instead of 5.00.) @p function rule_pixels(x:integer):integer; {computes $\lceil|conv|\cdot x\rceil$} var n:integer; begin n:=trunc(conv*x); if n; 9998: print_ln('!'); do_page:=false; 9999: end; @y @!next_step: integer; begin q:=0; s:=0; h:=0; v:=0; w:=0; x:=0; y:=0; z:=0; hh:=0; vv:=0; {initialize the state variables} do_page:=false; try begin 127: while true do @; end; {try clause} catch(ex: Dvi_Exception) begin print_ln('!'); do_page:=false; end; exit: end; @z @x [80, line 1846] (major,minor) optionally show opcode @d show(#)==begin flush_text; showing:=true; print(a:1,': ',#); end @d major(#)==if out_mode>errors_only then show(#) @d minor(#)==if out_mode>terse then begin showing:=true; print(a:1,': ',#); @y @d show(#)==begin flush_text; showing:=true; end @d major(#)==if out_mode>errors_only then show(#) @d minor(#)==if out_mode>terse then begin showing:=true; @z @x [line 1859] @; fin_set: @; fin_rule: @; move_right: @; show_state: @; done: if showing then print_ln(' '); end @y next_step:=0; @; case next_step of fin_set: begin @; end; fin_rule: begin @; end; othercases; endcases; case next_step of move_right: begin @; end; show_state: begin @; end; othercases; endcases; if showing then print_ln(' '); end @z @x [line 1877] four_cases(set1): begin major('set',o-set1+1:1,' ',p:1); goto fin_set; end; four_cases(put1): begin major('put',o-put1+1:1,' ',p:1); goto fin_set; end; set_rule: begin major('setrule'); goto fin_rule; end; put_rule: begin major('putrule'); goto fin_rule; end; @y four_cases(set1): begin q:=printer.setChar(p); next_step:=fin_set; if virtual_font then begin_virtual_char(p); end; four_cases(put1): begin printer.putChar(p); next_step:=fin_set; end; set_rule: begin q:=signed_quad; printer.setRule(p,q); next_step:=fin_rule; end; put_rule: begin q:=signed_quad; printer.putRule(p,q); next_step:=fin_rule; end; @z @x [line 1887] othercases if special_cases(o,p,a) then goto done@+else goto 9998 @y othercases if special_cases(o,p,a) then goto done else throw new Dvi_Exception('! '); @z @x [line 1891] function special_cases(@!o:eight_bits;@!p,@!a:integer):boolean; @y function special_cases(@!o:eight_bits;@!p,@!a:integer):boolean throws IOException; @z @x [line 1899] begin pure:=true; case o of @t\4@>@@; @t\4@>@@; four_cases(xxx1): @; pre: begin error('preamble command within a page!'); goto 9998; end; @.preamble command within a page@> post,post_post: begin error('postamble command within a page!'); goto 9998; @.postamble command within a page@> end; othercases begin error('undefined command ',o:1,'!'); goto done; @.undefined command@> end endcases; move_down: @; change_font: @; 9998: pure:=false; done: special_cases:=pure; @y @!next_step: integer; begin pure:=true; next_step:=0; try begin case o of @t\4@>@@; @t\4@>@@; four_cases(xxx1): @; pre: begin error('preamble command within a page!'); throw new Dvi_Exception('! '); end; @.preamble command within a page@> post,post_post: begin error('postamble command within a page!'); throw new Dvi_Exception('! '); @.postamble command within a page@> end; othercases begin error('undefined command ',o:1,'!'); goto done; @.undefined command@> end endcases; end; {try clause} catch(ex: Dvi_Exception) begin print_ln(ex.getMessage); pure:=false; next_step:=0; end; case next_step of move_down: begin @; end; change_font: begin @; end; othercases; endcases; special_cases:=pure; @z @x [line 1924] bop: begin error('bop occurred before eop!'); goto 9998; @y bop: begin error('bop occurred before eop!'); throw new Dvi_Exception('! '); @z @x [line 1931] do_page:=true; print_ln(' '); goto 9999; @y printer.e@&o@&p; if virtual_level > 0 then begin end_virtual_char; goto done; end else begin do_page:=true; return; end; @z @x [line 1941] stack_size:1,')'); goto 9998; @y stack_size:1,')'); throw new Dvi_Exception('! '); @z @x [line 1946] hhstack[s]:=hh; vvstack[s]:=vv; incr(s); ss:=s-1; goto show_state; @y incr(s); ss:=s-1; next_step:=show_state; @z @x [line 1950] else begin decr(s); hh:=hhstack[s]; vv:=vvstack[s]; @y else begin decr(s); @z @x [line 1954] ss:=s; goto show_state; @y ss:=s; printer.moveTo(h,v); next_step:=show_state; @z @x [line 1965] @d out_space(#)==if (p>=font_space[cur_font])or(p<=-4*font_space[cur_font]) then begin out_text(" "); hh:=pixel_round(h+p); end else hh:=hh+pixel_round(p); minor(#,' ',p:1); q:=p; goto move_right @y @d out_space(#)==if (p>=font_space[cur_font])or(p<=-4*font_space[cur_font]) then out_text(" "); q:=p; next_step:=move_right @z @x [line 1971] @= four_cases(right1):begin out_space('right',o-right1+1:1); end; w0,four_cases(w1):begin w:=p; out_space('w',o-w0:1); end; x0,four_cases(x1):begin x:=p; out_space('x',o-x0:1); end; @y @= four_cases(right1):begin out_space('right',o-right1+1:1); printer.moveRight(p); next_step:=move_right; end; w0,four_cases(w1):begin w:=p; out_space('w',o-w0:1); printer.moveRight(p); next_step:=move_right; end; x0,four_cases(x1):begin x:=p; out_space('x',o-x0:1); printer.moveRight(p); next_step:=move_right; end; @z @x [line 1984] @d out_vmove(#)==if abs(p)>=5*font_space[cur_font] then vv:=pixel_round(v+p) else vv:=vv+pixel_round(p); major(#,' ',p:1); goto move_down @y @d out_vmove(#)==next_step:=move_down @z @x [line 1988] @= four_cases(down1):begin out_vmove('down',o-down1+1:1); end; y0,four_cases(y1):begin y:=p; out_vmove('y',o-y0:1); end; z0,four_cases(z1):begin z:=p; out_vmove('z',o-z0:1); end; @y @= four_cases(down1):begin printer.moveDown(p); next_step:=move_down; end; y0,four_cases(y1):begin y:=p; printer.moveDown(p); next_step:=move_down; end; z0,four_cases(z1):begin z:=p; printer.moveDown(p); next_step:=move_down; end; @z @x [line 1997] sixty_four_cases(fnt_num_0): begin major('fntnum',p:1); goto change_font; end; four_cases(fnt1): begin major('fnt',o-fnt1+1:1,' ',p:1); goto change_font; end; four_cases(fnt_def1): begin major('fntdef',o-fnt_def1+1:1,' ',p:1); define_font(p); goto done; end; @y sixty_four_cases(fnt_num_0): begin next_step:=change_font; end; four_cases(fnt1): begin next_step:=change_font; end; four_cases(fnt_def1): begin define_font(p); goto done; end; @z @x [line 2011] for k:=1 to p do begin q:=get_byte; if (q<" ")or(q>"~") then bad_char:=true; if showing then print(xchr[q]); end; if showing then print(''''); if bad_char then error('non-ASCII character in xxx command!'); @y str_buf.setLength( 0 ); for k:=1 to p do begin q:=get_byte; if (q<" ")or(q>"~") then bad_char:=true else str_buf.append(xchr[q]); if showing then print(xchr[q]); end; if showing then print(''''); if bad_char then error('non-ASCII character in xxx command!'); printer.special( str_buf.toString ); @z @x [line 2022] @ @= begin if (o>" ")and(o<="~") then begin out_text(p); minor('setchar',p:1); end else major('setchar',p:1); goto fin_set; end @y @ @= begin out_text(p); q:=printer.setChar(p); next_step:=fin_set; if virtual_font then begin_virtual_char(p); end @z @x [line 2030] @ @= if p<0 then p:=255-((-1-p) mod 256) else if p>=256 then p:=p mod 256; {width computation for oriental fonts} @^oriental characters@>@^Chinese characters@>@^Japanese characters@> if (pfont_ec[cur_font]) then q:=invalid_width else q:=char_width(cur_font)(p); if q=invalid_width then begin error('character ',p:1,' invalid in font '); @.character $c$ invalid...@> print_font(cur_font); if cur_font<>invalid_font then print('!'); {the invalid font has `\.!' in its name} end; if o>=put1 then goto done; if q=invalid_width then q:=0 else hh:=hh+char_pixel_width(cur_font)(p); goto move_right @y @ @= if p<0 then p:=255-((-1-p) mod 256) else if p>=256 then p:=p mod 256; {width computation for oriental fonts} @^oriental characters@>@^Chinese characters@>@^Japanese characters@> if o>=put1 then goto done; next_step:=move_right @z @x [line 2048] @ @= q:=signed_quad; if showing then begin print(' height ',p:1,', width ',q:1); if out_mode>mnemonics_only then if (p<=0)or(q<=0) then print(' (invisible)') else print(' (',rule_pixels(p):1,'x',rule_pixels(q):1,' pixels)'); end; if o=put_rule then goto done; if showing then if out_mode>mnemonics_only then print_ln(' '); hh:=hh+rule_pixels(q); goto move_right @y @ @= if showing then begin print(' height ',p:1,', width ',q:1); if out_mode>mnemonics_only then if (p<=0)or(q<=0) then print(' (invisible)') else print(' (',rule_pixels(p):1,'x',rule_pixels(q):1,' pixels)'); end; if o=put_rule then goto done; if showing then if out_mode>mnemonics_only then print_ln(' '); next_step:=move_right @z @x [line 2076] q:1,' to ',infinity-h:1); @y q:1,' to ',(infinity-h):1); @z @x [line 2081] q:1, ' to ',(-h)-infinity:1); @y q:1, ' to ',((-h)-infinity):1); @z @x [line 2084] 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 @z @x [line 2108] p:1,' to ',infinity-v:1); @y p:1,' to ',(infinity-v):1); @z @x [line 2113] p:1, ' to ',(-v)-infinity:1); @y p:1, ' to ',((-v)-infinity):1); @z @x [line 2116] vvv:=pixel_round(v+p); if abs(vvv-vv)>max_drift then if vvv>vv then vv:=vvv-max_drift else vv:=vvv+max_drift; @y @z @x [line 2145] @ @= font_num[nf]:=p; cur_font:=0; while font_num[cur_font]<>p do incr(cur_font); if cur_font=nf then begin cur_font:=invalid_font; error('invalid font selection: font ',p:1,' was never defined!'); end; if showing then if out_mode>mnemonics_only then begin print(' current font is '); print_font(cur_font); end; goto done @y @ @= if virtual_level > 0 then begin virtual_font:=printer.setFont(p); cur_font:=p; end else begin font_num[nf]:=p; cur_font:=0; while font_num[cur_font]<>p do incr(cur_font); if cur_font=nf then begin cur_font:=invalid_font; error('invalid font selection: font ',p:1,' was never defined!'); end; virtual_font:=printer.setFont(cur_font); end; goto done @z @x [line 2166] procedure skip_pages(@!bop_seen:boolean); label 9999; {end of this subroutine} @y procedure skip_pages(@!bop_seen:boolean) throws IOException; label exit; {end of this subroutine} @z @x [line 2175] if in_postamble then goto 9999; if not started then if start_match then begin started:=true; goto 9999; @y if in_postamble then return; if not started then if start_match then begin started:=true; return; @z @x l.2183 9999:end; @y exit:end; @z @x [line 2193] print_ln(' '); @y if font_named then print_ln(' '); @z @x [line 2199] bad_dvi('illegal command at byte ',cur_loc-1:1); @y bad_dvi('illegal command at byte ',(cur_loc-1):1); @z @x [line 2221] procedure scan_bop; @y procedure scan_bop throws IOException; @z @x [line 2231] else begin if k<>bop then bad_dvi('byte ',cur_loc-1:1,' is not bop'); @y else begin if k<>bop then bad_dvi('byte ',(cur_loc-1):1,' is not bop'); @z @x [line 2234] for k:=0 to 9 do count[k]:=signed_quad; @y for k:=0 to 9 do count[k]:=signed_quad; printer.b@&o@&p(count); @z @x [line 2236] then print_ln('backpointer in byte ',cur_loc-4:1, @y then print_ln('backpointer in byte ',(cur_loc-4):1, @z @x [line 2260] if (q<0)or(q>m-33) then bad_dvi('post pointer ',q:1,' at byte ',m-3:1); @y if (q<0)or(q>m-33) then bad_dvi('post pointer ',q:1,' at byte ',(m-3):1); @z @x [line 2317] @p procedure read_postamble; @y @p procedure read_postamble throws IOException; @z @x [line 2321] print_ln('Postamble starts at byte ',post_loc:1,'.'); @y if out_mode>errors_only then print_ln('Postamble starts at byte ',post_loc:1,'.'); @z @x [line 2333] print('maxv=',max_v:1,', maxh=',max_h:1);@/ max_s:=get_two_bytes; total_pages:=get_two_bytes;@/ print_ln(', maxstackdepth=',max_s:1,', totalpages=',total_pages:1); @y max_s:=get_two_bytes; total_pages:=get_two_bytes;@/ printer.postamble(max_v,max_h,max_s,total_pages); @z @x [line 2372] print_ln('bad postamble pointer in byte ',cur_loc-4:1,'!'); @y print_ln('bad postamble pointer in byte ',(cur_loc-4):1,'!'); @z @x [line 2375] if m<>id_byte then print_ln('identification in byte ',cur_loc-1:1, @y if m<>id_byte then print_ln('identification in byte ',(cur_loc-1):1, @z @x [line 2379] while (m=223)and not eof(dvi_file) do m:=get_byte; if not eof(dvi_file) then bad_dvi('signature in byte ',cur_loc-1:1, @.signature...should be...@> ' should be 223') else if cur_loc cur_loc-k:1,')'); @y @z @@x [line 2380] if not eof(dvi_file) then bad_dvi('signature in byte ',cur_loc-1:1, @@y if not eof(dvi_file) then bad_dvi('signature in byte ',(cur_loc-1):1, @@z @@x [line 2386] cur_loc-k:1,')'); @@y (cur_loc-k):1,')'); @@z @x [line 2391] begin p:=first_par(k); define_font(p); print_ln(' '); k:=nop; @y begin p:=first_par(k); define_font(p); if font_named then print_ln(' '); k:=nop; @z @x [line 2395] print_ln('byte ',cur_loc-1:1,' is not postpost!') @y print_ln('byte ',(cur_loc-1):1,' is not postpost!') @z @x [106, line 2402] DVItype(): No dialog; remove unused label. @p begin initialize; {get all variables initialized} dialog; {set up all the options} @; @y @p procedure run; begin try begin @; @z @x [line 2415] print_ln('backpointer in byte ',cur_loc-4:1, @y print_ln('backpointer in byte ',(cur_loc-4):1, @z @x [line 2420] final_end:end. @y end; catch(ex: EOFException) begin print_ln('Unexpected EOF in DVI file: ', ex.getMessage); end; catch(ex: IOException) begin print_ln('IO error in DVI file: ', ex.getMessage); end; end; @# begin this.printer:=dont_make printer; if log=null then log:=dont_make System.err; initialize; {get all variables initialized} end. @z @x [line 2442] print(''''); while p>0 do begin decr(p); print(xchr[get_byte]); end; print_ln(''''); @y str_buf.append(''''); while p>0 do begin decr(p); str_buf.append(xchr[get_byte]); end; str_buf.append(''''); printer.preamble( numerator, denominator, mag, str_buf.toString ); @z @x [line 2461] tfm_conv:=(25400000.0/numerator)*(denominator/473628672)/16.0; @y @z @@x [109, line 2468] Fix another floating point print. print_ln('magnification=',mag:1,'; ',conv:16:8,' pixels per DVI unit') @@y print ('magnification=', mag:1, '; '); print_real (conv, 16, 8); print_ln (' pixels per DVI unit') @@z @x [line 2478] begin while max_pages>0 do @y done: begin while max_pages>0 do @z @x [line 2480] print_ln(' '); print(cur_loc-45:1,': beginning of page '); @y if out_mode>errors_only then begin print_ln(' '); print(cur_loc-45:1,': beginning of page '); end; @z @x [line 2481] for k:=0 to start_vals do begin print(count[k]:1); if k @y @ Global filenames. @= @!printer:dont_make DVI; @!dvi_name:String; @!index:integer; @!show_opcodes: boolean; @!file_store:Hashtable; @!entry:String; @!dir:String; @!list_line:integer; @!name_len:integer; @!str_buf:StringBuffer; @!font_named:boolean; @ @= show_opcodes:=true; str_buf := new StringBuffer; @* Virtual fonts. The |DVI| device returns |true| to the `message' |setFont| if the font is virtual, and |false| if it is real. We set the global variable |virtual_font| accordingly. Thus a character (encountered through |setchar| or |putchar|) is real or virtual according to the value of this variable. On encountering a virtual character we call the routine |begin_virtual_char|. This saves the current |h|, |v|, etc, through an imitation |push|, and also saves the current stream and other variables on a `virtual stack' indexed by the |virtual_level|. The end of a virtual character is signalled by |eop|. Thus if |eop| is encountered while $|virtual_level| > 0$ we call the routine |end_virtual_char| which restores the values from the previous level. Meanwhile the device must also keep a virtual font stack recording the font in use at each level. @= @!virtual_font: boolean; @!virtual_level: 0..max_virtual_level; @!dvi_stream: array[0..max_virtual_level] of byte_file; @!location: array[0..max_virtual_level] of integer; @!vf_char: VfChar; @!h_offset,@!v_offset: integer; @ @= h_offset:=0; v_offset:=0; @ @= procedure begin_virtual_char(p:integer); begin dvi_stream[virtual_level]:=dont_make dvi_file; location[virtual_level]:=cur_loc; incr(virtual_level); hstack[s]:=h; vstack[s]:=v; wstack[s]:=w; xstack[s]:=x; ystack[s]:=y; zstack[s]:=z; incr(s); dvi_file:=dont_make printer.dviStream( p ); cur_loc:=0; h_offset:=h_offset+h; v_offset:=v_offset+v; h:=0; v:=0; virtual_font:=printer.setFont(0); end; procedure end_virtual_char; begin decr(virtual_level); virtual_font:=true; dvi_file:=dont_make dvi_stream[virtual_level]; cur_loc:=location[virtual_level]; decr(s); h:=hstack[s]; v:=vstack[s]; w:=wstack[s]; x:=xstack[s]; y:=ystack[s]; z:=zstack[s]; end; @z