diff options
Diffstat (limited to 'dviware/crudetype/version3/hpgf.ch')
-rw-r--r-- | dviware/crudetype/version3/hpgf.ch | 832 |
1 files changed, 832 insertions, 0 deletions
diff --git a/dviware/crudetype/version3/hpgf.ch b/dviware/crudetype/version3/hpgf.ch new file mode 100644 index 0000000000..c1a5734d2c --- /dev/null +++ b/dviware/crudetype/version3/hpgf.ch @@ -0,0 +1,832 @@ +% hpgf.ch -*-mode: change; webfile: crudetype.web version 3.01;-*- +% HPGF.CH Provisional change file for the HP Laserjet... +% NOTE the system change file must normally be inserted above this point. +% SEE HPGF.DOC for users document--which must be rewritten for any new +% system. +% BUGFIX 19-dec-1990 Bug spoilt Landscape mode. +% + +@x Module 41; Lines 822 -- 839 +When this module starts, the \.{DVI} file should be positioned at or before a +BOP. + +@<For each page...@>= + read_BOP; + if (counter[0] >= first_page) then start := true ; + if start and (count_pages > 0 ) + then begin + @<Maybe a formfeed@> + decr(count_pages); + if not quiet then display('[', counter[0]:1 ); {Progress report} + Read_one_page ; + @<Sort the page@> + Send_page ; + if not quiet then display( ']' ); + end + else if ( count_pages > 0) then Skip_page + else time_to_stop := true; +@y +When this module starts, the \.{DVI} file should be positioned at or before a +BOP. + +This is where the printer change file proper begins. This change file goes +with \.{Crudetype} version 2. First, it should be explained that the HP is not +at all a "crude" printer, and the mechanisms of \.{Crudetype} are not really +suitable for it. It is really stretching the program a very long way from its +intended purpose. In particular, some changes have to be spliced into the +middle of the program, instead of going at the end as printer changes ought +to. It seems that the only reasonable way to drive a HP is by downloading all +the required characters. As stated in \.{Crudetype}, the problems of +downloading are extremely difficult and I have not solved them in any +satisfactory manner. The code given below manages downloading in the simplest +and crudest way possible. + +First, I have added flags to print either even or odd pages only. In +principle, this will allow double sided printing. Also, we do not sort the +page as the HP can jump about. + +@<For each page...@>= + read_BOP; + if (counter[0] >= first_page) then start := true ; + if start and (count_pages > 0 ) and ( + ( odd( counter[0]) = odds) or (( not evens) and ( not odds)) ) + then begin + decr(count_pages); + if not quiet then display('[', counter[0]:1 ); {Progress report} + Read_one_page ; + @<Dont sort the page but |reset| it @> + Send_page ; + @<Maybe a formfeed@> + if not quiet then display( ']' ); + end + else if ( count_pages > 0) then Skip_page + else time_to_stop := true; +@z + +% Next, the HP has its own rule-setting commands. +@x Module 57; Lines 1126 -- 1136 + procedure set_rule; + var D_p,D_q: integer; + begin + D_p:=get_integer(dvi) (-4); + D_q:=get_integer(dvi)(-4); + if (D_p<=0)or(D_q<=0) then + {an invisible rule! Dont ask me why \TeX\ wants to do this} + else if (D_p*v_conv <= post_height/2) + then do_rail(D_p, D_q) + else do_post(D_p, D_q); + end; +@y + procedure set_rule; + var D_p,D_q: integer; + rule_h, rule_v, rule_ht, rule_wid: integer ; {all in pixels} + begin + D_p:=get_integer(dvi) (-4); + D_q:=get_integer(dvi)(-4); + if (D_p<=0)or(D_q<=0) then + {an invisible rule! Dont ask me why \TeX\ wants to do this} + else begin @<Find the pixel sizes and reference point@> + @<Send it to the printer@> + end; + end; +@z + +% Dont shunt on a fine printer +@x Module 154; Lines 2678 -- 2679 + if H_shunt > (Set_h - 3) + then H_shunt := (Set_h - 3) ; +@y + do_nothing ; +@z + +@x Module 174; Lines 2958 -- 2959 +@d out_of_sequence == + ( ( Old_v > Set_v) or ( ( Old_v = Set_v) and ( Old_h > Set_h))) +@y +Since we do not sort, we will not separate the characters into runs. + +@d out_of_sequence == false +@z + +% Again, shunting is only appropriate for line printers. +@x Module 186; Lines 3157 -- 3157 + PR_h_next := hpos - H_shunt ; +@y + PR_h_next := hpos ; +@z + +@x Module 207; Lines 3467 -- 3484 +@ So here are their default values. We believe they are all appropriate for +lineprinters on VMS machines. Note that the program makes no attempt to check +these values for consistency. + +@<Set init...@>= + device_ID := 'Lineprinter '; {Pad to 12 chars} + list := false ; + fortran := false ; + b_feed_absolute := false ; + b_feed_by_string := false ; + feed_absolute := false ; + b_feed_scream := true ; + b_space_absolute := false ; + b_space_by_string := false ; + space_absolute := false ; + abs_is_incr := false ; + wl_does_cr := false ; + want_split := true ; +@y +@ The first lot of data describes the HP's overall style of carriage +control. Many of them are completely irrelevant to the HP, but still needed in +order for the program to compile. + +@<Set init...@>= + device_ID := 'Laserjet + '; + list := false ; + fortran := false ; + b_feed_absolute := true ; + b_feed_by_string := false ; + feed_absolute := true ; + b_feed_scream := true ; + b_space_absolute := true ; + b_space_by_string :=false ; + space_absolute := true ; + abs_is_incr := false ; + wl_does_cr := false ; + want_split := true ; + is_header := false ; {each page needs a header} +@z + +@x Module 208; Lines 3518 -- 3527 +@ The general run of \TeX\ characters are narrower than line-printer chars. So +we spread them out to make them fit. + +@<Set init...@>= + l_margin := 1.0 ; {Normal left margin, in inches} + top_margin := 1.0 ; {Top ditto} + h_fudge := 7.227 {number of points per |h_step|} + / 5.25 ; {A typical design width} + v_fudge := 2.0 ; + { Force double-spacing, in hope that suffixes will come out right} +@y +@ The general run of \TeX\ characters are narrower than line-printer chars. +But the HP prints them at their proper widths. + +@<Set init...@>= + l_margin := 1.0 ; {Normal left margin, in inches} + top_margin := 1.0 ; {Top ditto} + h_fudge := 1.0 ; + v_fudge := 1.0 ; +@z + +@x Module 213; Lines 3584 -- 3594 +@ This batch is concerned with distances and resolutions. + +@<Const...@>= + h_resolution = 10 ; {|h_steps| per inch} + v_resolution = 6 ; {|v_steps| per inch} + fixed_width = true ; {printers characters are fixed width} + char_width = 1 ; + {all printer characters are this width, in units of |h_step|. Normally, + |space_dist| will be equal to this, but some printers are not normal!} + gap_width = 1 ; {Intended minimum space between words} + char_ht = 1 ; +@y +@ This batch is concerned with distances and resolutions. + +@<Const...@>= + h_resolution = 300 ; {|h_steps| per inch} + v_resolution = 300 ; {|v_steps| per inch} + fixed_width = false ; + char_width = 30 ; {default char. sizes in |h_steps| -- a guess} + gap_width = 5 ; {Intended minimum space between words} + char_ht = 42 ; +@z + +@x Module 216; Lines 3616 -- 3620 + max_font = 1 ; + only_one_font = true ; + can_dl_font = false ; + min_dl_font = 0 ; + max_dl_font = 0 ; {printers down-loadable fonts} +@y + max_font = 40 ; + only_one_font = false ; + can_dl_font = true ; + min_dl_font = 8 ; + max_dl_font = 40 ; {printers down-loadable fonts. The HP allows up to 32} +@z + +@x Module 234; Lines 4022 -- 4024 +@<Assign char...@>= + @<Define Lineprinter codes@> + @<Set rule characters@> +@y + @<Assign char...@>= do_nothing +@z + +@x Module 235; Lines 4028 -- 4028 +*** Attach printer change file here *** +@y + +@ The remaining changes can all go at the end of the program. Before getting +onto the hardest task (namely, downloading) lets clear up the loose ends that +were left lying about in the body of the program. First, there are a number of +extra command options: + +@<If the |key|...@>= + else if ( key = "O") then odds := true {Print odd-numbered pages only} + else if ( key = "E") then evens := true {Even ditto} + else if ( key = "L") then begin + land := true ; {Print Landscape} + start_stuff.data[ 8] := '1' ; {bugfix, 19-dec-1990, previously 6} + end + +@ @<Glob...@>= + land, odds, evens: boolean ; + +@ @<Set init...@>= + land := false ; + odds := false ; + evens := false ; + +@ Where will the printed file go to? + +@<Set init...@>= + be_string( '.HPL') ; print_ex := buffer ; + +@ @<Dont sort the page but |reset| it @>= + L_reset( run) ; + Add_run ; + L_reset( mid) ; + cur_pge_ptr := son( next( mid) ) ; + +@ Now lets dispose of rule-setting. \TeX\ puts the reference point of a rule +at bottom left, the HP at top left. Sizes must be rounded up. + +@<Find the pixel sizes and reference point@>= + rule_ht := round(v_conv*D_p + 0.5) ; + rule_wid := round(h_conv*D_q + 0.5) ; + D_dis := D_q ; + IM_dis := rule_wid ; + round_IM_h ( 0); + rule_h := IM_h ; + rule_v := IM_v - rule_ht ; + +@ @<Send it to the printer@>= + set_v_abs(rule_v) ; + set_h_abs(rule_h) ; + print(chr(27), '*c', rule_ht:1, 'B') ; + print(chr(27), '*c', rule_wid:1, 'A') ; + print(chr(27), '*c0P') ; + print_ln; + +@ Consider command strings. + +@<Set init...@>= + be_string ( '^[E^[&l0O' ) ; start_stuff := buffer ; + {Reset everything to default state} + be_string ( '^[(&DX' ) ; font_command := buffer ; + be_string ( '^[*p&DY' ) ; v_abs_com := buffer ; + be_string ( '^[*p&DX ' ) ; h_abs_com := buffer ; + stop_stuff := start_stuff ; + page_top := blank ; + pause_after := blank ; + +@ On the HP, we must explicitly start a new page at a set position. Also since +rules get set before any characters, we must then reset the position. + +@<Set up an empty page...@>= + set_v_abs(0) ; + set_h_abs(0) ; + +@ @<Pause reset@>= + set_v_abs(0) ; + set_h_abs(0) ; + +@* Downloading, 1: reading the font file. + +The simplest and crudest way this could possibly be done is: read the raster +file and load the entire font, as soon as the |font_def| command is read from +the \.{DVI} file. On VAX/VMS, this turned out to be unbearably slow. So it is +here changed as follows: When a |font_def| command is read, we read the whole +raster file into an array. Then download each character before trying to print +it. This `lazy downloading' makes the program run much faster, at the price of +a large use of memory. + @^\.{TUG}boat@> + +@<Download a whole font@>= + begin + @<Prepare to read the |raster_file|@> + repeat + @<Get \.{GF} command |GF_com|, and do it@> + until GF_com = 248; + close_binary( raster_file) ; + @<Establish the new font in memory@> + end + +@ First we have to determine the file name. + +@<Prepare to read...@>= + raster_mag := round(300 * font_mag * magnification ) ; + if not hunt_for_size( font_name, raster_mag) + then font_error('cannot load this font') ; + @.Error: cannot load@> + +@ @<Medium...@>= + function open_font( + name: var_string; mag: integer; ask: boolean ): boolean; + begin + splice( raster_name, raster_def, mag) ; + open_font := open_and_ask( + raster_file, raster_indx, name, raster_name, ask) ; + end; + +@ Frequently the {\.DVI} file calls for a font at a magnification that is +almost but not quite one of the standard sizes. So we try a few steps up or +down before giving up. |range| is the maximum percentage that we allow the +magnification to vary. + +@<Forw...@>= + function hunt_for_size ( + name: var_string; mag: integer): boolean; forward ; + +@ @<Medium...@>= function hunt_for_size ; + label exit ; + const range = 5 ; + var try_mag, n , max : integer; hh: boolean; + begin + max := round( raster_mag* range / 100); + n := 0 ; + while ( n <= max) do begin + try_mag := mag + n ; + hh := open_font( name, try_mag, false) ; + if hh then return + else if ( n>0) then n:= -n + else n := 1 - n ; + end; + hh := open_font( name, mag, true) ; + exit: hunt_for_size := hh; + end; + +@ Then read the file; a horrible mess. + +@<Get \.{GF} command...@>= + GF_com := get_byte( raster) ; + if GF_com <= 63 then paint( GF_com) + else if ( GF_com >= 74) and ( GF_com <= 238) then + new_row( GF_com - 74 ) + else + +@ Then we have the usual messy |case| statement: + +@d three_cases(#)== + #,#+1,#+2 : begin GF_par := get_integer( raster)( GF_com - # + 1 ); + four_case_end + +@<Get \.{GF} command...@>= + case GF_com of + three_cases( 64)( paint( GF_par)); + 67, 68: boc; + 69: eoc; + 70: miss_row( 0); + three_cases( 71)( miss_row( GF_par)); + three_cases( 239)( skip( raster)( GF_par)); + 242: skip( raster)( get_integer( raster)( -4)) ; + 243: skip( raster)( 4); + 244:; + 247: preamble; + 248: postamble ; + 245,246,249,250,251,252,253,254,255: + warn( 'illegal GF command, will try to continue'); + end; + @.illegal GF command@> + +@ Now there follow lots of procedures to deal with the commands. + +@<Lowest...@>= + procedure preamble; + var p: byte; + begin + p:=get_byte( raster); + p:=get_byte( raster); + skip( raster)( p) ; {the introductory comment} + with Font_box do begin + L := pixel_R ; + R := pixel_L ; + T := pixel_B ; + B := pixel_T ; + end; + end; + +@# + procedure postamble; + var GF_check: integer ; + begin + skip( raster)( 8); + GF_check := get_integer( raster)( -4) ; + if (D_check<>0)and(GF_check<>0)and(D_check<>GF_check) then + begin warn('check sums do not agree!'); + @.error: check sums...@> + display_ln('DVI check was: ', D_check, ' GF check was: ', GF_check); + display(' '); + end; + end; + +@# + procedure boc; + var q : byte; mm, nn: i_word; + begin + if GF_com = 67 then + begin GF_char := get_integer( raster)( 4) mod 256 ; + skip( raster) ( 4); + Boc_box.L:=get_integer( raster)( -4); + Boc_box.R:=get_integer( raster)( -4); + Boc_box.B:=get_integer( raster)( -4); + Boc_box.T:=get_integer( raster)( -4); + end + else begin GF_char:=get_byte( raster); + q:=get_byte( raster); Boc_box.R:=get_byte( raster); + Boc_box.L:=Boc_box.R-q; + q:=get_byte( raster); Boc_box.T:=get_byte( raster); + Boc_box.B:=Boc_box.T-q; + end; + @<Clear the image@> + end; + +@ Now lets assign names to variables. In order to try to clear up the muddle +of boundaries for character cells, I introduce a concept of a ``box'', not the +same as a \TeX\ box. The fields represent the boundaries that must contain all +the black pixels of any character. + +@<Const...@>= + pixel_L = -300; pixel_R = 700; pixel_B = -300; pixel_T = 700; + +@ @<Types...@>= + @!x_coord=pixel_L..pixel_R; + @!y_coord=pixel_B..pixel_T; + box = packed record + L,R: x_coord; + T,B: y_coord; + end; + dir_entry = packed record + point: integer; + h_offset, v_offset, wid, ht : i_word; + end; + +@ @<Glob...@>= + Boc_box, {Limits of char. cell declared in |BOC| command} + char_box, {actual boundaries of char. cell} + Font_box: box; {The font cell. This is the smallest cell that + contains the reference point and any char. cell in the font} + GF_com, GF_par, GF_char : byte; + glyphs: packed array[1..max_glyph] of byte ; + glyph_ptr: integer; + raster_mag: integer; + directory : array[D_font_ptr, D_char_ptr ] of dir_entry ; + C_width : integer; + +@ @<Set init...@>= + glyph_ptr := 1 ; + for in_i := 0 to max_D_fonts do + for in_j := 0 to max_D_char do + directory[ in_i, in_j].point := sentry ; + {Mark everything as unprintable} + +@ The definition of \.{GF} files refers to two registers, $(G_m,G_n)$, which +hold row and column numbers. We also need to remember |paint_switch|, which +is either |black| or |white|. + +@<Glob...@>= + @!pixels: packed array [y_coord,x_coord] of pixel; + @!G_m: x_coord; + @!G_n: y_coord; {current state values} + @!paint_switch: pixel; + +@ We'll need a big array of pixels to hold the character image. Each pixel +should be represented as a single bit in order to save space. Different +systems may prefer the following definitions, while others may do better using +the |boolean| type and constants. + @^system dependencies@> + +@d white==false +@d black==true +@d swop == paint_switch:=not paint_switch +{could also be |if paint_switch=black then paint_switch:=white +else paint_switch:=black|} + +@<Types...@>= +@!pixel=boolean ; + {could also be |white..black|} + +@ Maybe there's a faster way to do this on your system. Note that the only +part of the |image_array| that we clear is the part that the current character +may use. Thus, the rest of this program may not look outside the area +delimited by |Boc_box| and expect to see anything but junk. +@^system dependencies@> + +@<Clear the image@>= + begin + for nn := Boc_box.B to Boc_box.T do + for mm := Boc_box.L to Boc_box.R do + pixels[nn,mm] := white; + G_n := Boc_box.T ; + G_m := Boc_box.L ; + char_box.L := pixel_R ; + char_box.R := pixel_L ; + char_box.B := pixel_T ; + char_box.T := pixel_B ; + directory[ nf, GF_char].point := 0 ; + {Indicates a blank character} + end + +@ @<Lowest...@>= + procedure paint( p: integer); + var m, k: integer; + begin + if G_m+p> pixel_R then + warn('character extends too far to the right') + @.character extends...@> + else if paint_switch = white then + else begin + m := G_m + p -1 ; + if char_box.T < G_n then char_box.T := G_n ; + if char_box.B > G_n then char_box.B := G_n ; + if char_box.L > G_m then char_box.L := G_m ; + for k:= G_m to m do + pixels[G_n, k] := black ; + if char_box.R < m then char_box.R := m ; + end; + swop; + G_m := G_m +p ; + end; + +@# +procedure new_row( p:integer); + begin + decr(G_n); + G_m:=Boc_box.L + p; + paint_switch:=black; + end; + +@# procedure miss_row( p: integer); + begin + G_n:=G_n - p ; + G_m:= Boc_box.L; + paint_switch:=white; + end; + +@* Downloading, 2: Transfer characters into memory. + +After we have read the character, we must transfer it into memory. First, +stretch the Font box to include the current characters box. + +@<Lowest...@>= + procedure eoc; + var x, y : integer; + cur_byt: byte ; + q: i_word ; + begin + if char_box.R >= char_box.L {If not, the character is unprintable} + then begin + if char_box.L < Font_box.L then Font_box.L := char_box.L ; + if char_box.B < Font_box.B then Font_box.B := char_box.B ; + if char_box.R > Font_box.R then Font_box.R := char_box.R ; + if char_box.T > Font_box.T then Font_box.T := char_box.T ; + @<Transfer the dimensions of the character@> + @<Transfer the |pixels| into |glyphs|@> + end; + end; + +@ In landscape mode, the character must be rotated. The |directory| will +contain the dimensions to be downloaded; these do depend on orientation. +|char_box| describes the logical character which does not depend on +orientation. + +@<Transfer the dimensions...@>= + with directory[nf, GF_char] do begin + point := glyph_ptr; + if land then begin + h_offset := - char_box.T ; + v_offset := char_box.R ; + ht := char_box.R - char_box.L +1 ; + wid := char_box.T - char_box.B +1 ; + end else begin + h_offset := char_box.L ; + {\TeX\ and the HP measure this in opposite directions} + v_offset := char_box.T ; + wid := char_box.R - char_box.L +1 ; + ht := char_box.T - char_box.B +1 ; + end; + end; + +@ Likewise the |glyphs| array will contain the pixels to be downloaded; these +also depend on orientation. Looking at the logical character, |x| is the +horizontal coordinate and |y| the vertical. In portrait mode the pixels must +be sent starting at the top left corner and going left to right along the top +row. In Landscape mode you must start at the top right corner and go down the +right hand column. Each row or column must be padded to |8n| bits. + +@<Transfer the |pixels|...@>= + if land then begin + for x := char_box.R downto char_box.L do begin + cur_byt := 0 ; + q := 0 ; + for y := char_box.T downto char_box.B do begin + if pixels[ y, x] then cur_byt := cur_byt + powers[q] ; + if q < 7 then incr( q) + else begin + glyphs[glyph_ptr] := cur_byt ; incr( glyph_ptr) ; cur_byt := 0; + q := 0 ; + end; + end; + if q > 0 then + begin + glyphs[glyph_ptr] := cur_byt ; incr( glyph_ptr) ; cur_byt := 0; + end; + end; + end else + +@ @<Transfer the |pixels|...@>= + begin + for y := char_box.T downto char_box.B do begin + cur_byt := 0 ; + q := 0 ; + for x := char_box.L to char_box.R do begin + if pixels[ y, x] then cur_byt := cur_byt + powers[q] ; + if q < 7 then incr( q) + else begin + glyphs[glyph_ptr] := cur_byt ; incr( glyph_ptr) ; cur_byt := 0; + q := 0 ; + end; + end; + if q > 0 then + begin + glyphs[glyph_ptr] := cur_byt ; incr( glyph_ptr) ; cur_byt := 0; + end; + end; + end ; + +@ @<Set init...@>= + powers[0] := 128 ; + for in_i := 1 to 7 do powers[in_i] := powers[in_i-1] div 2 ; + +@ @<Glob...@>= powers: array[0..7] of byte ; + +@ @<Const...@>= max_glyph = 1000000 ; + +@ @<Clean...@>= + display_ln + ('Used ', glyph_ptr:1, ' bytes of font memory out of ', max_glyph:1); + +@ Finally, does the printer have enough room for the font? The HP allows 32 +fonts per job and 395 KB memory. I have not checked the restriction of only 16 +fonts per page. + +@<Establish...@>= + incr(PR_dl_font ) ; + if PR_dl_font > max_dl_font then + font_error('tried to load too many fonts') ; + @.Error: tried to load@> + +@ @<Set init...@>= + PR_dl_font := min_dl_font ; + PR_mem_used := 0 ; + PR_max_mem := 395000; + be_string( '^[*c&DD' ) ; font_start := buffer ; + +@ @<Glob...@>= PR_dl_font, PR_max_mem, PR_mem_used: integer ; + font_start: var_string ; + +@ If the error tests succeed, then we come here. Before we can load any +characters, we have to send a command to the printer to declare the new font. +This section assembles the necessary information. |dir_start[ nf]| should be +pointing to the start of the font directory. The main task is that the printer +must be given the size of a character cell; this must be large enough to +contain all the characters. First we specify the font ID. This is a number by +which the printer will refer to the font after loading it. + +@<Establish...@>= + print_command( font_start, PR_dl_font, '^') ; + print(chr(27), ')s26W' ); + {A create font command} + prw(26); + prw(1) ; { 8 bit chars} + prw(0) ; + with Font_box do begin + if L > 0 then L := 0 ; + if B > 0 then B := 0 ; + if R < 0 then R := 0 ; + if T < 0 then T := 0 ; {Stretch the Font box to include the ref. point} + prw( T) ; + prw( R - L + 1) ; {width} + prw( T - B + 1) ; {height} + end; + if land then prw( 257) else prw(1) ; {proportional spaced} + prw(277) ; + for font_i := 1 to 5 do prw(0) ; + {The HP needs these parameters, but they serve no purpose known to me} + +@ Finally, we must establish the map from \TeX\ characters to printers +characters in the new font. + +@<Establish...@>= + incr(top_code) ; {get a new coding scheme} + scheme[ nf] := top_code ; + alphabet(0, 33, top_code, PR_dl_font, 190); + alphabet(33, 95, top_code, PR_dl_font, 33); + for tex_chr := 0 to max_D_char do + codes[ top_code, tex_chr].breadth := down_loaded ; + +@ @<Glob...@>= top_code: integer ; + +@ @<|font_def| vars@>= tex_chr, font_i: integer; + +@ @<Set init...@>= top_code := 1 ; + +@* Downloading, 3: Lazy downloading. + +The idea is to load only those characters in each font that actually will be +printed. It is obviously essential to ensure that each character gets loaded +before being printed, and only once. This is done in the procedure +|set_character|. The \TeX\ character is number |c_num| in font |D_font|, +but the printer character is addressed by |cod|. + +The first job is to update the directory info. for the character, and assemble +its size parameters. + +@<Enter a download...@>= + with directory [ D_font, c_num] do begin + if point < 0 then begin warn( + 'tried to print a non-existent character, number: ' , c_num:1) ; + codes[ cur_scheme, c_num].breadth := bad_char ; + end else begin + C_length := ht * (( wid + 7) div 8) ; {length of data} + C_width := D_width[ D_font, c_num] ; + C_delta := round(C_width * h_conv) ; + codes[ cur_scheme, c_num].breadth := C_delta ; + cod.breadth := C_delta ; + PR_mem_used := PR_mem_used + C_length + 64 ; {approximate} + if PR_mem_used > PR_max_mem then + warn('overflowed printer memory, will try to proceed regardless') ; + @.Error: overflowed printer memory@> + @.Error: tried to print...@> + +@ @<Clean...@>= + display_ln + ('Used ', PR_mem_used:1, ' bytes of printers memory out of ', + PR_max_mem:1) ; + +@ @<Glob...@>= + C_length, C_delta : integer; + char_start, char_head: var_string ; + +@ @<Set init...@>= + be_string( '^[*c&DE' ) ; char_start := buffer ; + be_string( '^[(s&DW' ) ; char_head := buffer ; + +@ Now we must not let the character get downloaded twice, so we put the +correct value into its |breadth|; we must also update the current |cod|. + +@ Now we send the character header. First, tell the printer which character +will be downloaded. \TeX\ fonts usually have 128 characters and HP fonts have +either 96 or 192. The permitted values for HP characters are 33..127 and +160..255 according to the manual but appendix B says 160 and some others are +undefined. So we map \TeX\ characters 0..32 onto 190..222 . + +@<Enter a download...@>= + { N.B. still |with directory [ D_font, c_num]| } + print_command( font_start, cod.IM_font, '^') ; + {Specify printers font identifier} + print_command( char_start, cod.IM_char, '^') ; + print_command( char_head, (C_length + 16), '^') ; + {and the character} + prw(1024); + prw(14*256 + 1); + if land then prw( 256 ) else prw(0); + prw(h_offset) ; + prw(v_offset); + prw(wid) ; + prw(ht) ; + prw(4 * C_delta) ; + +@ And at long last we can send the pixels!! + +@<Enter a download...@>= + for d_i := point to point+C_length-1 do + print(chr(glyphs[ d_i] )) ; + print_ln ; +end; end; + +@ Nearly all the HP's arguments come as signed 16-bit words, to be printed in +two-complement notation. This procedure prints them. + +@<Low...@>= + procedure prw( n: i_word); + var nn: integer ; + begin + if (n>= 0) then nn := n + else nn := n + 65536 ; + print( zchr(nn div 256)); + print( zchr(nn mod 256)); + end ; +@z |