home *** CD-ROM | disk | FTP | other *** search
- Subject: v06i014: TeX DVI driver for LaserJet+ (texdvi2lj), Part2/3
- Newsgroups: mod.sources
- Approved: rs@mirror.UUCP
-
- Submitted by: Tor Lillqvist <talcott!seismo!mcvax!santra!tml>
- Mod.sources: Volume 6, Issue 14
- Archive-name: texdvi2lj/Part2
-
- [ I have split this submission into three pieces named LJ.1.3,
- LJ.2.3, and LJ.2.3. Unpack each piece and do
- "cat LJ.[123].3 >dvi2lj.web"
- This is not great, but is the best way I could think of to
- distribute a large single-file source; if you have a better
- way, please let me know.
- * * * * * *
- OOPS! This article went out earlier with a wrong subject
- line. I sent out a cancel, but in case it didn't get out,
- here's the "official" posting.
- * * * * * *
- --r$]
-
- Here is a DVI (TeX output) driver for the HP LaserJet+. This version
- is for the Pascal/1000 compiler on HP1000 machines running RTE-A (and
- my TeX implementation), but it should be fairly easy to convert to
- other TeX implementations, compilers and operating systems.
-
- DVIplus is based on the DVItype program. It downloads only those
- characters actually used. Pages are printed in reverse.
-
- # This is a shell archive. Remove anything before this line,
- # then unpack it by saving it in a file and typing "sh file".
- # Contents: LJ.2.3
-
- echo x - LJ.2.3
- sed 's/^XX//' > "LJ.2.3" <<'@//E*O*F LJ.2.3//'
- XX@* Reading the font information.
- XXThe current number of known fonts is |nf|. Each known font has
- XXan internal number |f|, where |0<=f<nf|; the external number of this font,
- XXi.e., its font identification number in the \.{DVI} file, is
- XX|font_num[f]|, and the external name of this font is the string that
- XXoccupies positions |font_name[f]| through |font_name[f+1]-1| of the array
- XX|names|. The latter array consists of |ASCII_code| characters, and
- XX|font_name[nf]| is its first unoccupied position. A horizontal motion
- XXin the range |-4*font_space[f]<h<font_space[f]|
- XXwill be treated as a `kern'.
- XXA given character |c| is valid in font |f| if and only if
- XX|char_width(f)(c)<>invalid_width|.
- XXFinally, |char_width(f)(c)=width[width_base[f]+c]|, and |width_ptr| is the
- XXfirst unused position of the |width| array.
- XX
- XX@d char_width(#)==width[width_base[#]+char_end_width
- XX@d invalid_width==@'17777777777
- XX
- XX@<Glob...@>=
- XX@!font_num:array [0..max_fonts] of integer; {external font numbers}
- XX@!font_name:array [0..max_fonts] of 0..name_size; {starting positions
- XX of external font names}
- XX@!names:array [0..name_size] of ASCII_code; {characters of names}
- XX@!font_check_sum:array [0..max_fonts] of integer; {check sums}
- XX@!font_scaled_size:array [0..max_fonts] of integer; {scale factors}
- XX@!font_design_size:array [0..max_fonts] of integer; {design sizes}
- XX@!font_mag:array [0..max_fonts] of integer;
- XX@!font_space:array [0..max_fonts] of integer; {boundary between ``small''
- XX and ``large'' spaces}
- XX@!font_used_on:array[0..max_fonts] of integer; {on which page last used}
- XX@!width_base:array [0..max_fonts] of integer; {index into |width| table}
- XX@=$Ema_Var On$@>
- XX@!width:array [0..max_widths] of integer; {character widths, in \.{DVI} units}
- XX@=$Ema_Var Off$@>
- XX@!nf:0..max_fonts; {the number of known fonts}
- XX@!width_ptr:0..max_widths; {the number of known character widths}
- XX
- XX@ @<Set init...@>=
- XXnf:=0; width_ptr:=0; font_name[0]:=0; font_space[0]:=0;
- XXfont_used_on[0]:=0;
- XX
- XX@ It is, of course, a simple matter to print the name of a given font.
- XX
- XX@p procedure print_font(@!f:integer); {|f| is an internal font number}
- XXvar k:0..name_size; {index into |names|}
- XXbegin if f=nf then print('UNDEFINED!')
- XX@.UNDEFINED@>
- XXelse begin for k:=font_name[f] to font_name[f+1]-1 do
- XX print(xchr[names[k]]);
- XX end;
- XXend;
- XX
- XX@ The global variabls |pxl_check_sum|,
- XX|pxl_design_size| are set from the \.{PXL} file.
- XX
- XX@<Glob...@>=
- XX@!pxl_check_sum:integer; {check sum found in |pxl_file|}
- XX@!pxl_dptr:array [0..max_fonts] of integer; {directory pointers}
- XX@!pxl_design_size:integer;
- XX
- XX@ Here is a procedure that absorbs the necessary information from a
- XX\.{PXL} file, assuming that the file has just been successfully opened.
- XX(A complete description of
- XX\.{PXL} file format appears elsewhere and will
- XXnot be repeated here.) The procedure does not check the \.{PXL} file
- XXfor validity, nor does it give explicit information about what is
- XXwrong with a \.{PXL} file that proves to be invalid; \.{DVI}-reading
- XXprograms need not do this, since \.{PXL} files are almost always valid.
- XXThe procedure simply returns |false| if it
- XXdetects anything amiss in the \.{PXL} data.
- XX
- XXThere is a parameter, |z|, which represents the scaling factor being
- XXused to compute the font dimensions; it must be in the range $0<z<2^{27}$.
- XX
- XX@d read_pxl(#)==begin #:=pxl_file[nf]^.i; get(pxl_file[nf]); end
- XX
- XX@p procedure in_PXL(@!z:integer); {input \.{PXL} data}
- XXvar i,j,k,n:short; {indices etc.}
- XX@!wp:0..max_widths; {new value of |width_ptr| after successful input}
- XX@!raster_address:integer;
- XX@!alpha,@!beta:integer; {quantities used in the scaling computation}
- XXbegin
- XX if width_ptr+128>max_widths then begin
- XX print_nl;
- XX abort('Need larger width table');
- XX end;
- XX width_base[nf]:=width_ptr;
- XX wp:=width_ptr;
- XX @<Check the header ID@>;
- XX @<Read the trailer@>;
- XX @<Read the font directory@>;
- XX width_ptr:=wp;
- XXend;
- XX
- XX@ @<Check the header ID@>=
- XXbegin
- XX seek_pxl(nf)(0);
- XX get(pxl_file[nf]);
- XX if pxl_file[nf]^.i <> pxl_id then
- XX bad_pxl('bad header id');
- XXend
- XX
- XX@ @<Read the trailer@>=
- XXbegin
- XX seek(pxl_file[nf],s_pxl_file+1);
- XX get(pxl_file[nf]);
- XX if pxl_file[nf]^.i <> pxl_id then
- XX bad_pxl('bad trailer id');
- XX seek(pxl_file[nf],s_pxl_file-3);
- XX get(pxl_file[nf]);
- XX read_pxl(pxl_check_sum);
- XX read_pxl(font_mag[nf]);
- XX read_pxl(pxl_design_size);
- XX read_pxl(pxl_dptr[nf]);
- XXend;
- XX
- XX@ One important part of |in_PXL| is the width computation, which
- XXinvolves multiplying the relative widths in the \.{PXL} file by the
- XXscaling factor in the \.{DVI} file. This fixed-point multiplication
- XXmust be done with precisely the same accuracy by all \.{DVI}-reading programs,
- XXin order to validate the assumptions made by \.{DVI}-writing programs
- XXlike \TeX82.
- XX
- XXLet us therefore summarize what needs to be done. Each width in a \.{PXL}
- XXfile appears as a four-byte quantity called a |fix_word|. A |fix_word|
- XXwhose respective bytes are $(a,b,c,d)$ represents the number
- XX$$x=\left\{\vcenter{\halign{$#$,\hfil\qquad&if $#$\hfil\cr
- XXb\cdot2^{-4}+c\cdot2^{-12}+d\cdot2^{-20}&a=0;\cr
- XX-16+b\cdot2^{-4}+c\cdot2^{-12}+d\cdot2^{-20}&a=255.\cr}}\right.$$
- XX(No other choices of $a$ are allowed, since the magnitude of a \.{TFM}
- XXdimension must be less than 16.) We want to multiply this quantity by the
- XXinteger~|z|, which is known to be less than $2^{27}$. Let $\alpha=16z$.
- XXIf $|z|<2^{23}$, the individual multiplications $b\cdot z$, $c\cdot z$,
- XX$d\cdot z$ cannot overflow; otherwise we will divide |z| by 2, 4, 8, or
- XX16, to obtain a multiplier less than $2^{23}$, and we can compensate for
- XXthis later. If |z| has thereby been replaced by $|z|^\prime=|z|/2^e$, let
- XX$\beta=2^{4-e}$; we shall compute
- XX$$\lfloor(b+c\cdot2^{-8}+d\cdot2^{-16})\,z^\prime/\beta\rfloor$$ if $a=0$,
- XXor the same quantity minus $\alpha$ if $a=255$. This calculation must be
- XXdone exactly, for the reasons stated above; the following program does the
- XXjob in a system-independent way, assuming that arithmetic is exact on
- XXnumbers less than $2^{31}$ in magnitude.
- XX
- XXThe following code computes pixel widths by simply rounding the \.{PXL}
- XXwidths to the nearest integer number of pixels, based on the conversion factor
- XX|conv| that converts \.{DVI} units to pixels. However, such a simple
- XXformula will not be valid for all fonts, and it will often give results that
- XXare off by $\pm1$ when a low-resolution font has been carefully
- XXhand-fitted. For example, a font designer often wants to make the letter `m'
- XXa pixel wider or narrower in order to make the font appear more consistent.
- XX\.{DVI}-to-printer programs should therefore input the correct pixel width
- XXinformation from font files whenever there is a chance that it may differ.
- XXA warning message may also be desirable in the case that at least one character
- XXis found whose pixel width differs from |conv*width| by more than a full pixel.
- XX
- XXThose characters that are too large to be downloadable, are marked as such,
- XXand will be transferred using raster graphics. We must be especially careful
- XXin the y dimension, as the character must fit into the 255*255 box when
- XXthe reference point is placed on the baseline. The baseline was set to
- XX$255-$|baseline| pixel rows down from the top.
- XX@^system dependencies@>
- XX
- XX@d pixel_round(#)==round(conv*(#))
- XX
- XX@<Read the font dir...@>=
- XX@<Replace |z| by $|z|^\prime$ and compute $\alpha,\beta$@>;
- XXfor k:=0 to 127 do begin
- XX seek(pxl_file[nf],pxl_dptr[nf]+k*4+2);
- XX get(pxl_file[nf]);
- XX {is the charater too large ?}
- XX if (pxl_file[nf]^.i0 >= 128) or (pxl_file[nf]^.i1 >= 128) then
- XX status[wp]:=too_large
- XX else
- XX status[wp]:=not_loaded;
- XX get(pxl_file[nf]);
- XX get(pxl_file[nf]);
- XX if pxl_file[nf]^.i=0 then begin
- XX width[wp]:=invalid_width;
- XX pixel_width[wp]:=0 end
- XX else begin
- XX get(pxl_file[nf]);
- XX read_pxl_word(nf);
- XX width[wp]:=(((((b3*z)div@'400)+(b2*z))div@'400)+(b1*z))div beta;
- XX if b0>0 then if b0<255 then bad_pxl('strange width for char ', k:1)
- XX else width[wp]:=width[wp]-alpha;
- XX pixel_width[wp]:=pixel_round(width[wp]);
- XX end;
- XX incr(wp);
- XXend
- XX
- XX@ @<Replace |z|...@>=
- XXbegin alpha:=16*z; beta:=16;
- XXwhile z>=@'40000000 do
- XX begin z:=z div 2; beta:=beta div 2;
- XX end;
- XXend
- XX
- XX@* Downloading information to the printer.
- XXThe procedure |update_pos| is used to update the printer cursor position.
- XXThis is the only place where the cursor is explicitely positioned.
- XX
- XX@p procedure update_pos;
- XXlabel done;
- XXbegin if (lj_h<>hh)or(lj_v<>vv) then begin
- XX write_lj(@=#27'*p'@>);
- XX if (lj_h<>hh) then begin
- XX if abs(lj_h-hh) > hh div 10 then
- XX write_lj_f(hh:1)
- XX else if (lj_h<hh) then
- XX write_lj_f('+', hh-lj_h:1)
- XX else
- XX write_lj_f('-', lj_h-hh:1);
- XX if (lj_v<>vv) then
- XX write_lj_f('x')
- XX else begin
- XX write_lj_f('X');
- XX goto done;
- XX end
- XX end;
- XX if abs(lj_v-vv) > vv div 10 then
- XX write_lj_f(vv:1)
- XX else if (lj_v<vv) then
- XX write_lj_f('+', vv-lj_v:1)
- XX else
- XX write_lj_f('-', lj_v-vv:1);
- XX write_lj_f('Y');
- XXend;
- XXdone:
- XXlj_h:=hh; lj_v:=vv;
- XXend;
- XX
- XX@ This procedure downloads a single character from a \.{PXL} file.
- XX@^system dependencies@>
- XX
- XX@p procedure download_char(p:integer);
- XXvar i,j:short;
- XX@!pixel_wd,@!pixel_ht:integer;
- XX@!offsets,char_wd,char_ht,delta_x:i2c;
- XX@!raster_address:integer;
- XX
- XXbegin
- XX seek(pxl_file[cur_font],pxl_dptr[cur_font]+p*4+2);
- XX get(pxl_file[cur_font]);
- XX pixel_wd:=pxl_file[cur_font]^.i0;
- XX pixel_ht:=pxl_file[cur_font]^.i1;
- XX get(pxl_file[cur_font]);
- XX offsets:=pxl_file[cur_font]^;
- XX get(pxl_file[cur_font]);
- XX raster_address:=pxl_file[cur_font]^.i;
- XX @<Download character header@>;
- XX seek(pxl_file[cur_font],raster_address+2);
- XX for j:=1 to pixel_ht do begin
- XX for i:=1 to (pixel_wd-1) div 8 + 1 do begin
- XX if (i-1) mod 4 = 0 then
- XX get(pxl_file[cur_font]);
- XX write_lj(pxl_file[cur_font]^.c[(i-1) mod 4]);
- XX end;
- XX end
- XXend;
- XX
- XX@ Download a character header.
- XX
- XX@d data_bytes==(pixel_ht*(((pixel_wd-1) div 8)+1))
- XX
- XX@<Download character header@>=
- XXbegin
- XX if pixel_ht - offsets.i1 > baseline then begin
- XX char_status(cur_font)(p):=pixel_ht-offsets.i1;
- XX offsets.i1:=pixel_ht; end
- XX else
- XX char_status(cur_font)(p):=loaded_ok;
- XX offsets.i0:=-offsets.i0;
- XX char_wd.i0:=pixel_wd;
- XX char_ht.i0:=pixel_ht;
- XX delta_x.i0:=char_pixel_width(cur_font)(p)*4;
- XX write_lj(@=#27'*c'@>,font_num[cur_font]:1,'d',
- XX ord(vis_chr(p)):1,@='E'#27'(s'@>,
- XX data_bytes+16:1,'W'+
- XX @=#4#0#14#1#0#0@>,
- XX offsets.c[0], offsets.c[1],
- XX offsets.c[2], offsets.c[3],
- XX char_wd.c[0], char_wd.c[1],
- XX char_ht.c[0], char_ht.c[1],
- XX delta_x.c[0], delta_x.c[1]);
- XXend
- XX
- XX@ This procedure transfers a character in raster form.
- XXThis is used for characters which are too large to be stored in
- XXthe font memory of the printer.
- XX@^system dependencies@>
- XX
- XX@p procedure raster_char(p:integer);
- XXvar
- XXi,j,n:short;
- XX@!pixel_ht,@!pixel_wd,@!x_offset,@!y_offset:short;
- XX@!raster_address:integer;
- XX
- XXbegin
- XX seek(pxl_file[cur_font],pxl_dptr[cur_font]+p*4+2);
- XX get(pxl_file[cur_font]);
- XX pixel_wd:=pxl_file[cur_font]^.i0;
- XX pixel_ht:=pxl_file[cur_font]^.i1;
- XX get(pxl_file[cur_font]);
- XX x_offset:=pxl_file[cur_font]^.i0;
- XX y_offset:=pxl_file[cur_font]^.i1;
- XX get(pxl_file[cur_font]);
- XX raster_address:=pxl_file[cur_font]^.i;
- XX hh:=hh-x_offset; vv:=vv-y_offset;
- XX update_pos;
- XX write_lj(@=#27'*r1A'@>);
- XX seek(pxl_file[cur_font],raster_address+2);
- XX for j:=1 to pixel_ht do begin
- XX write_lj(#27'*b',(pixel_wd-1) div 8 + 1:1, 'W');
- XX for i:=1 to (pixel_wd-1) div 8 + 1 do begin
- XX if (i-1) mod 4 = 0 then
- XX get(pxl_file[cur_font]);
- XX write_lj(pxl_file[cur_font]^.c[(i-1) mod 4]);
- XX end;
- XX end;
- XX lj_v:=lj_v+pixel_ht;
- XX hh:=hh+char_pixel_width(cur_font)(p); vv:=vv+y_offset;
- XX write_lj(@=#27'*rB'@>);
- XXend;
- XX
- XX@* Optional modes of output.
- XXThe starting page is specified by giving a sequence of 1 to 10 numbers or
- XXasterisks separated by dots. For example, the specification `\.{1.*.-5}'
- XXcan be used to refer to a page output by \TeX\ when $\.{\\count0}=1$
- XXand $\.{\\count2}=-5$. (Recall that |bop| commands in a \.{DVI} file
- XXare followed by ten `count' values.) An asterisk matches any number,
- XXso the `\.*' in `\.{1.*.-5}' means that \.{\\count1} is ignored when
- XXspecifying the first page. If several pages match the given specification,
- XX\.{DVIplus} will begin with the earliest such page in the file. The
- XXdefault specification `\.*' (which matches all pages) therefore denotes
- XXthe page at the beginning of the file.
- XX
- XXAnother option is the page offset. That is the point on the physical
- XXprinter page where the point (0,0) in the DVI file is mapped.
- XX
- XXNormally \.{DVIplus} uses default values for the options.
- XXIt can be started in such a way that it engages
- XXthe user in a brief dialog so that the
- XXoptions will be specified.
- XX@^system dependencies@>
- XX
- XX@<Glob...@>=
- XX@!max_pages:integer; {at most this many |bop..eop| pages will be printed}
- XX@!resolution:real; {pixels per inch}
- XX@!new_mag:integer; {if positive, overrides the postamble's magnification}
- XX@!copies:integer;
- XX@!h_offset,@!v_offset:integer; {offset where to put (0,0) on physical page}
- XX
- XX@ The starting page specification is recorded in two global arrays called
- XX|start_count| and |start_there|. For example, `\.{1.*.-5}' is represented
- XXby |start_there[0]=true|, |start_count[0]=1|, |start_there[1]=false|,
- XX|start_there[2]=true|, |start_count[2]=-5|.
- XXWe also set |start_vals=2|, to indicate that count 2 was the last one
- XXmentioned. The other values of |start_count| and |start_there| are not
- XXimportant, in this example.
- XX
- XX@<Glob...@>=
- XX@!start_count:array[0..9] of integer; {count values to select starting page}
- XX@!start_there:array[0..9] of boolean; {is the |start_count| value relevant?}
- XX@!start_vals:0..9; {the last count considered significant}
- XX@!count:array[0..9] of integer; {the count values on the current page}
- XX
- XX@ @<Set init...@>=
- XXmax_pages:=100; start_vals:=0; start_there[0]:=false; copies:=1;
- XXresolution:=300.0; new_mag:=0;
- XXh_offset:=210; v_offset:=100;
- XX
- XX@ Here is a simple subroutine that tests if the current page might be the
- XXstarting page.
- XX
- XX@p function start_match:boolean; {does |count| match the starting spec?}
- XXvar k:0..9; {loop index}
- XX@!match:boolean; {does everything match so far?}
- XXbegin match:=true;
- XXfor k:=0 to start_vals do
- XX if start_there[k]and(start_count[k]<>count[k]) then match:=false;
- XXstart_match:=match;
- XXend;
- XX
- XX@ The |input_ln| routine waits for the user to type a line at his or her
- XXterminal; then it puts ASCII-code equivalents for the characters on that line
- XXinto the |buffer| array. The |term_in| file is used for terminal input,
- XXand |term_out| for terminal output.
- XX@^system dependencies@>
- XX
- XX@<Glob...@>=
- XX@!buffer:array[0..terminal_line_length] of ASCII_code;
- XX@!term_in:text_file; {the terminal, considered as an input file}
- XX@!term_out:text_file; {the terminal, considered as an output file}
- XX@!arg_index:short; {which command line argument is being processed}
- XX@!interactive:boolean;
- XX
- XX@ Since the terminal is being used for both input and output, some systems
- XXneed a special routine to make sure that the user can see a prompt message
- XXbefore waiting for input based on that message. (Otherwise the message
- XXmay just be sitting in a hidden buffer somewhere, and the user will have
- XXno idea what the program is waiting for.) We shall call a system-dependent
- XXsubroutine |update_terminal| in order to avoid this problem.
- XX@^system dependencies@>
- XX
- XX@d update_terminal == prompt(term_out) {empty the terminal output buffer}
- XX
- XX@ During the dialog, \.{DVIplus} will treat the first blank space in a
- XXline as the end of that line. Therefore |input_ln| makes sure that there
- XXis always at least one blank space in |buffer|.
- XX@^system dependencies@>
- XX
- XX@p procedure input_ln; {inputs a line from the terminal}
- XXvar k:0..terminal_line_length;
- XXbegin update_terminal;
- XXk:=0;
- XXif eoln(term_in) then read_ln(term_in)
- XXelse begin while (k<terminal_line_length)and not eoln(term_in) do
- XX begin buffer[k]:=xord[term_in^]; incr(k); get(term_in);
- XX end;
- XX read_ln(term_in);
- XXend;
- XXbuffer[k]:=" ";
- XXend;
- XX
- XX@ The global variable |buf_ptr| is used while scanning each line of input;
- XXit points to the first unread character in |buffer|.
- XX
- XX@<Glob...@>=
- XX@!buf_ptr:0..terminal_line_length; {the number of characters read}
- XX
- XX@ Here is a routine that scans a (possibly signed) integer and computes
- XXthe decimal value. If no decimal integer starts at |buf_ptr|, the
- XXvalue 0 is returned. The integer should be less than $2^{31}$ in
- XXabsolute value.
-
- XX@p function get_integer:integer;
- XXvar x:integer; {accumulates the value}
- XX@!negative:boolean; {should the value be negated?}
- XXbegin if buffer[buf_ptr]="-" then
- XX begin negative:=true; incr(buf_ptr);
- XX end
- XXelse negative:=false;
- XXx:=0;
- XXwhile (buffer[buf_ptr]>="0")and(buffer[buf_ptr]<="9") do
- XX begin x:=10*x+buffer[buf_ptr]-"0"; incr(buf_ptr);
- XX end;
- XXif negative then get_integer:=-x @+ else get_integer:=x;
- XXend;
- XX
- XX@ The selected options are put into global variables by the |dialog|
- XXprocedure, which is called just as \.{DVIplus} begins.
- XX@^system dependencies@>
- XX
- XX@p procedure dialog;
- XXlabel 2,3,6,7,8,9,99;
- XXvar i,j,k:short;
- XXbegin rewrite(term_out, '1', 'NOCCTL'); {prepare the terminal for output}
- XXreset(term_in, '1'); {and for input}
- XXprint_ln(banner);
- XX@<Get flags, check if interactive@>;
- XX@<Determine the desired |start_count| values@>;
- XX@<Determine the desired |max_pages|@>;
- XX@<Determine the number of copies@>;
- XX@<Determine the page offset@>;
- XX@<Print all the selected options@>;
- XXend;
- XX
- XX@ @<Get flags, check if interactive@>=
- XXarg_index:=1; interactive:=false;
- XXrepeat
- XX i:=parameters(arg_index,cur_name,name_length);
- XX if cur_name[1]='-' then begin
- XX incr(arg_index);
- XX if i=1 then
- XX interactive:=true
- XX else case cur_name[2] of
- XX 'i','I':interactive:=true;
- XX othercases begin end;
- XX endcases;
- XX end;
- XXuntil cur_name[1]<>'-';
- XXif not interactive then goto 99;
- XX
- XX@ @<Determine the desired |start...@>=
- XX2: print('Starting page (default=*): ');
- XXinput_ln; buf_ptr:=0; k:=0;
- XXif buffer[0]<>" " then
- XX repeat if buffer[buf_ptr]="*" then
- XX begin start_there[k]:=false; incr(buf_ptr);
- XX end
- XX else begin start_there[k]:=true; start_count[k]:=get_integer;
- XX end;
- XX if (k<9)and(buffer[buf_ptr]=".") then
- XX begin incr(k); incr(buf_ptr);
- XX end
- XX else if buffer[buf_ptr]=" " then start_vals:=k
- XX else begin print('Type, e.g., 1.*.-5 to specify the ');
- XX print_ln('first page with \count0=1, \count2=-5.');
- XX goto 2;
- XX end;
- XX until start_vals=k
- XX
- XX@ @<Determine the desired |max_pages|@>=
- XX3: print('Maximum number of pages (default=100): ');
- XXinput_ln; buf_ptr:=0;
- XXif buffer[0]<>" " then
- XX begin max_pages:=get_integer;
- XX if max_pages<=0 then
- XX begin print_ln('Please type a positive number.');
- XX goto 3;
- XX end;
- XX end
- XX
- XX@ @<Determine the number of copies@>=
- XX6: print('Number of copies (default=1): ');
- XXinput_ln; buf_ptr:=0;
- XXif buffer[0]<>" " then
- XX if (buffer[0]>="0")and(buffer[0]<="9") then copies:=get_integer
- XX else begin print('Type a positive integer to specify ');
- XX print_ln('the number of copies.');
- XX goto 6;
- XX end
- XX
- XX@ @<Determine the page offset@>=
- XX7: print('Page offset in dots (default=210,100): ');
- XXinput_ln; buf_ptr:=0;
- XXif buffer[0]=" " then goto 9;
- XXif ((buffer[0]>="0")and(buffer[0]<="9")) or (buffer[0]="-") then
- XX h_offset:=get_integer
- XXelse goto 8;
- XXif (buffer[buf_ptr]=",") then incr(buf_ptr);
- XXif (buffer[buf_ptr]=" ") then incr(buf_ptr);
- XXif ((buffer[buf_ptr]>="0")and(buffer[buf_ptr]<="9")) or
- XX (buffer[buf_ptr]="-") then begin
- XX v_offset:=get_integer;
- XX goto 9; end
- XXelse goto 8;
- XX8:print('Specify a dot coordinate pair where the (0,0) ');
- XX print_ln('point will be placed.');
- XX goto 7;
- XX9:
- XX
- XX@ After the dialog is over, we print the options so that the user
- XXcan see what \.{DVIplus} thought was specified.
- XX
- XX@<Print all the selected options@>=
- XX99:print_ln('Options selected:');
- XX@.Options selected@>
- XXprint(' Starting page = ');
- XXfor k:=0 to start_vals do
- XX begin if start_there[k] then print(start_count[k]:1)
- XX else print('*');
- XX if k<start_vals then print('.')
- XX else print_nl;
- XX end;
- XXprint_ln(' Maximum number of pages = ',max_pages:1);
- XXprint_ln(' Page offset = (', h_offset:1, ',', v_offset:1, ')');
- XX
- XX@* Defining fonts.
- XX\.{DVIplus} reads the postamble first and loads
- XXall of the fonts defined there; then it processes the pages.
- XX
- XX@ Approximate the desired magnification to an available one.
- XXThe ``magig numbers'' that the desired magnification
- XXis compared to are calculated as
- XX$1500*1.2^m$, where $m = 1/4,3/4,1.5,2.5,3.5,4.5$
- XX
- XX@p function approx_mag(f:integer;d_mag:integer):integer;
- XX
- XXbegin
- XX if d_mag < 1569 then
- XX approx_mag := 1500
- XX else if d_mag < 1720 then
- XX approx_mag := 1643
- XX else if d_mag < 1971 then
- XX approx_mag := 1800
- XX else if d_mag < 2366 then
- XX approx_mag := 2160
- XX else if d_mag < 2839 then
- XX approx_mag := 2592
- XX else if d_mag < 3407 then
- XX approx_mag := 3110
- XX else if d_mag < 4089 then
- XX approx_mag := 3732
- XX else
- XX approx_mag:= 4479;
- XXend;
- XX
- XX@ The following subroutine does the necessary things when a \\{fnt\_def}
- XXcommand is being processed.
- XX
- XX@p procedure define_font(@!e:integer); {|e| is an external font number}
- XXvar f:0..max_fonts;
- XX@!p:integer; {length of the area/directory spec}
- XX@!n:integer; {length of the font name proper}
- XX@!c,@!q,@!d:integer; {check sum, scaled size, and design size}
- XX@!m:integer; {|mag| corrected for 300 pixels/inch}
- XX@!r:0..name_length; {index into |cur_name|}
- XX@!j,@!k:0..name_size; {indices into |names|}
- XX@!mismatch:boolean; {do names disagree?}
- XXbegin if nf=max_fonts then abort('DVIplus capacity exceeded (max fonts=',
- XX max_fonts:1,')!');
- XX@.DVIplus capacity exceeded...@>
- XXfont_num[nf]:=e; f:=0;
- XXwhile font_num[f]<>e do incr(f);
- XX@<Read the font parameters into position for font |nf|, and
- XX print the font name@>;
- XX if f<nf then print_ln('---this font was already defined!');
- XX@.this font was already defined@>
- XX @<Load the new font, unless there are problems@>
- XXend;
- XX
- XX@ @<Read the font parameters into position for font |nf|...@>=
- XXc:=signed_quad; font_check_sum[nf]:=c;@/
- XXq:=signed_quad; font_scaled_size[nf]:=q;@/
- XXd:=signed_quad; font_design_size[nf]:=d;@/
- XXp:=get_byte; n:=get_byte;
- XXif font_name[nf]+n+p>name_size then
- XX abort('DVIplus capacity exceeded (name size=',name_size:1,')');
- XX@.DVIplus capacity exceeded...@>
- XXfont_name[nf+1]:=font_name[nf]+n+p;
- XXif n+p=0 then abort('Null font name')
- XX@.Null font name@>
- XXelse for k:=font_name[nf] to font_name[nf+1]-1 do names[k]:=get_byte;
- XXfont_used_on[nf+1]:=0;
- XXincr(nf);
- XXif f=nf-1 then begin
- XX print('Font ', e:1, ': '); print_font(nf-1);
- XX update_terminal;
- XXend;
- XXdecr(nf)
- XX
- XX@ @<Load the new font, unless there are problems@>=
- XXbegin
- XX@<Compute |desired_mag|@>;
- XX@<Move font name into the |cur_name| string@>;
- XXif not open_pxl_file(nf) then begin
- XX print_nl;
- XX abort('Cannot open PXL file ', cur_name); end
- XX@.Cannot open PXL file@>
- XXelse begin if (q<=0)or(q>=@'1000000000) then begin
- XX print_nl;
- XX abort('PXL file not loaded, bad scale (',q:1,')!'); end
- XX@.bad scale@>
- XX else if (d<=0)or(d>=@'1000000000) then begin
- XX print_nl;
- XX abort('PXL file not loaded, bad design size (',d:1,')!'); end
- XX@.bad design size@>
- XX else begin
- XX in_PXL(q);
- XX @<Finish loading the new font info@>;
- XX end
- XXend
- XXend
- XX
- XX@ @<Compute |desired_mag|@>=
- XXdesired_mag:=round((mag * q * (300.0/200.0))/d+0.5);
- XX
- XX@ @<Finish loading...@>=
- XXbegin font_space[nf]:=q div 6; {this is a 3-unit ``thin space''}
- XXif (c<>0)and(pxl_check_sum<>0)and(c<>pxl_check_sum) then
- XX begin print(' ---beware: check sums do not agree!');
- XX@.beware: check sums do not agree@>
- XX@.check sums do not agree@>
- XX print(' (',c:1,' vs. ',pxl_check_sum:1,')');
- XX end;
- XXd:=round((100.0*conv*q)/(true_conv*d));
- XXif d<>100 then
- XX print(' (magnified ',d:1,'%)');
- XX@.this font is magnified@>
- XXincr(nf); {now the new font is officially present}
- XXfont_space[nf]:=0; {for |out_space| and |out_vmove|}
- XXend
- XX
- XX@ If |p=0|, i.e., if no font directory has been specified, \.{DVIplus}
- XXuses the default font directory, which is a
- XXsystem-dependent place where the standard fonts are kept.
- XX
- XXIn RTE--A, the \.{PXL} files are kept in directories called
- XX\.{/TeX/Fonts/MagXXXX}, where \.{XXXX} is the magnification.
- XXThe string variable |default_prefix| contains the prefix of these names.
- XX@^system dependencies@>
- XX
- XX@d default_prefix_name=='/TeX/Fonts/Mag'
- XX@d default_prefix_length=14 {change this to the correct length}
- XX
- XX@<Glob...@>=
- XX@!default_prefix:packed array[1..default_prefix_length] of char;
- XX
- XX@ @<Set init...@>=
- XXdefault_prefix:=default_prefix_name;
- XX
- XX@ The string |cur_name| is set to the external name of the
- XX\.{PXL} file for the current font and magnification.
- XX@^system dependencies@>
- XX
- XX@<Move font name into the |cur_name| string@>=
- XXfor k:=1 to name_length do cur_name[k]:=' ';
- XXif p=0 then
- XX begin for k:=1 to default_prefix_length do
- XX cur_name[k]:=default_prefix[k];
- XX r:=default_prefix_length;
- XX incr(r);
- XX best_mag:=approx_mag(font_name[nf],desired_mag);
- XX m:=best_mag;
- XX cur_name[r]:=xchr[ m div 1000 + xord['0']];
- XX incr(r);
- XX cur_name[r]:=xchr[ (m div 100) mod 10 + xord['0']];
- XX incr(r);
- XX cur_name[r]:=xchr[ (m div 10) mod 10 + xord['0']];
- XX incr(r);
- XX cur_name[r]:=xchr[ m mod 10 + xord['0']];
- XX incr(r);
- XX cur_name[r]:='/'; end
- XXelse
- XX r:=0;
- XX
- XXfor k:=font_name[nf] to font_name[nf+1]-1 do
- XX begin incr(r);
- XX if r+4>name_length then
- XX abort('DVIplus capacity exceeded (max font name length=',
- XX name_length:1,')!');
- XX@.DVIplus capacity exceeded...@>
- XX cur_name[r]:=xchr[names[k]];
- XX end;
- XXcur_name[r+1]:='.'; cur_name[r+2]:='P'; cur_name[r+3]:='X'; cur_name[r+4]:='L'
- XX
- @//E*O*F LJ.2.3//
- chmod u=rw,g=rw,o=rw LJ.2.3
-
- exit 0
-