From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX"  1-SEP-1989 13:47
To:	MRGATE::"ARISIA::EVERHART"
Subj:	Apple LaserWriter Symbiont (2 of 12)

Received: From KL.SRI.COM by CRVAX.SRI.COM with TCP; Fri,  1 SEP 89 07:17:52 PDT
Received: from ecsgate.uncecs.edu by KL.SRI.COM with TCP; Fri, 1 Sep 89 07:00:53 PDT
Received: by ecsgate.uncecs.edu (5.59/UNCECS/8-30-88)
	id AA22582; Fri, 1 Sep 89 10:00:58 EDT
Message-Id: <8909011400.AA22582@ecsgate.uncecs.edu>
Date: Fri, 1 Sep 89 09:59 EDT
From: "Bill Bailey, 'The VAXman'" <BAILEYB@ATSUVAX1.BITNET>
Subject: Apple LaserWriter Symbiont (2 of 12)
To: INFO-VAX@KL.SRI.COM
X-Vms-To: INFOVAX

-+-+-+-+-+-+-+-+ START OF PART 2 -+-+-+-+-+-+-+-+
X`009 `091/linelimit 66 (.linelimit .nlines .param6)`093`009% lines per page
X         `091/hdr () (.hdr .header. param7)`093`009`009% page header
X`009`093 def
X`125 if
X`032
Xcurrentdict /table known not `123
X`009/table `091
X`009 `091/#copies 1 (.nc .ncopies .param1)`093`009`009% number of copies
X`009 `091/fsizetmp 0 (.fsize .fs .param2)`093`009`009% font size
X`009 `091/wide false (.wide .w .param3)`093`009`009% landscape mode
X`009 `091/title true (.title .param4)`093 `009`009% title
X`009 `091/ncolumns 1 (.ncolumns .param5)`093`009`009% number of columns
X`009 `091/linelimit 66 (.linelimit .nlines .param6)`093`009% lines per page
X         `091/hdr () (.hdr .header. param7)`093`009`009% page header
X`009`093 def
X`125 if
X`032
Xtable `123`009`009`009`009`009`009% apply defaults
X`009/ta exch def`009`009`009`009% save array
X`009ta 0 get`009`009`009`009% key
X`009ta 1 get`009`009`009`009% default value
X`009def`009`009`009`009`009% define default value
X`125 forall
X`032
Xcurrentdict /parser known `123parser`125 if`009`009% if user inputs
X`032
X% if the user specified a string for /hdr then use it, also imply title true
Xhdr length 0 ne `123/filename hdr def /title true def`125 if
X
Xcurrentdict /filename known not `123/filename () def`125 if
Xfilename (_DUA0:`091`093) anchorsearch `123pop /filename exch def`125 `123po
Vp`125 ifelse %cleanup
X`032
X/inp currentfile def`009`009`009`009% define files
X`032
Xwide `123
X`009/leftmargin .5 inch def
X`009/topmargin 7.96 inch def
X`009/bottommargin .3 inch def
X`009/rightmargin .25 inch def
X`009currentdict /fsize known not `123/fsize 8 point def`125 if % default
X`009fsizetmp 0 ne `123/fsize fsizetmp def`125 if
X`009/pagewidth 11 inch def
X`009/squish -0.3 def
X`009/titlemargin 3 point def
X`125 `123`009
X`009/leftmargin 1. inch def
X`009/topmargin 10.39 inch def`009`009% top of page
X`009/rightmargin .25 inch def
X`009/bottommargin .5 inch def
X`009currentdict /fsize known not `123/fsize 10 point def`125 if % default
X`009fsizetmp 0 ne `123/fsize fsizetmp def`125 if
X`009/pagewidth 8.5 inch def
X`009/squish -0.3 def
X`009/titlemargin .185 inch def
X`125 ifelse
X/lineh fsize point def`009`009`009% line height
X/linecount 0 def
X/column 0 def
X/columnwidth pagewidth leftmargin sub rightmargin sub ncolumns div def
X/ibuf 200 string def`009`009`009% input buffer
X/page 1 def`009`009`009`009% page number
X/xpos leftmargin def
X/xmargin leftmargin def
X/ypos topmargin lineh sub def
X`032
X%  The following section of code makes a new font with a backspace
X%  character defined.  The width of the backspace character is
X%  the negative of the width of an underscore character.
X`032
X/Courier findfont`009`009`009`009% select the font
Xlineh scalefont setfont`009`009`009`009% find width of an underscore
X    (_) stringwidth pop 100 mul /uwid exch def
X`032
X/Courier findfont`009`009`009`009% copy the font
Xdup length 1 add dict /newdict exch def`009%  leaving room for a Metrics ent
Vry
X`123
X`009exch dup  /FID ne `123`009`009`009% if not /FID
X`009`009dup /Encoding eq `123`009`009% if /Encoding copy the entry
X`009`009`009exch dup length array copy`032
X`009`009`009newdict 3 1 roll put
X`009`009`125 `123
X`009`009`009exch newdict 3 1 roll put % else just use the object
X`009`009`125 ifelse
X`009`125 `123
X`009pop pop`009`009`009`009`009% dump /FID
X`009`125 ifelse
X`125 forall
X`032
X1 dict begin`009`009`009`009`009% create Metrics dictionary
X`009/backspace uwid neg def`009`009`009% define backspace width
X`009newdict /Metrics currentdict put
Xend
X`032
Xnewdict begin`009`009`009`009`009% set encoding for backspace
X`009Encoding 8 /backspace put
Xend
X`032
X/xfont newdict definefont pop`009`009`009% define the new font
X`032
X/xfont findfont fsize scalefont setfont`009% select the new font
X`032
Xlandscape
X/saveobj save def
$ CALL UNPACK [.LASER_DIST]HEADERS_STR.PS;1 366135
$ create/nolog 'f'
X%%%`009image - puts a raster image file on the laserwriter.
X%
X%`00902/26/87 R. Watson Derived from paint_hex.ps
X%
X
X%%`009deCompress <string>.
X%
X%`009returns a bitimage string on the stack
X%
X/deCompress
X`123
X`009/count readbyte def`009`009`009% get count
X`009count 16#80 and 0 eq `123`009`009`009% if bit stream
X`009`009/count count 1 add def
X`009`009outstring 0 count getinterval   % get right size string
X`009`009inp exch readhexstring`009`009% get bytes
X`009`009pop`009`009`009`009% toss readhexstring status
X`009`125
X`009`123`009`009`009`009`009% else repeated string
X`009`009/byte readbyte def`009`009% get byte to repeat
X`009`00916#100 count sub 1 add /count exch def% get abs val of count
X`009`0090`009`009`009`009% preset index
X`009`009count `123
X`009`009`009dup outstring exch byte put
X`009`009`0091 add`009`009`009% advance index
X`009`009`125 repeat
X`009`009pop`009`009`009`009% index
X`009`009outstring 0 count getinterval`009% return string
X`009`125 ifelse
X`125 def
X
X
X%%`009getByte
X%
X%`009returns /byte = next input byte
X%`009`009      = 0 if no more bytes on input stream
X%
X/getByte
X`123
X`009inp instring readhexstring `123`009`009% if got one
X`009`0090 get /byte exch def`009`009% store in byte
X`009`125
X`009`123`009`009`009`009`009% else 0
X`009`009pop /byte 0 def
X`009`125 ifelse
X`125 def
X
X
X%%`009decodeheader - decodes the info in the header record.
X%
X/decodeheader
X`123
X`009/bytesinhead 512 def`009`009`009% default 512 bytes
X`009`123`009`009`009`009`009% 512 bytes default
X`009    getlong 10 10string cvrs cvlit `009% key to lit
X`009    dup where
X`009`009`123 pop load exec `125`009`009% if defined func
X`009`009`123 pop getlong pop `125 ifelse`009% if no func (key, fix file)
X`009    /bytesinhead bytesinhead 8 sub def`009% debit header length
X`009    bytesinhead 8 lt `123`009`009`009% if end of header
X`009`009bytesinhead `123`009`009`009% flush remaining bytes
X`009`009`009readbyte pop
X`009`009`125 repeat
X`009`009exit`009`009`009`009% exit loop
X`009    `125 if
X`009`125 loop
X`125 def
X
X/0 `123getlong pop`125 def`009`009`009`009% 0 - nop
X/1 `123/xsize getlong def`125 def`009`009`009% 1 - x size
X/2 `123/ysize getlong def`125 def`009`009`009% 2 - y size
X/3 `123/pxlwid getlong def`125 def`009`009`009% 3 - pixel width
X/4 `123/scale getlong def`125 def`009`009`009% 4 - scale factor
X/5 `123/invert getlong def`125 def`009`009`009% 5 - invert if nonzero
X/8 `123getlong 512 sub `009`009`009`009% 8 - header length
X    bytesinhead add /bytesinhead exch def`125 def  % apply correction factor
X/9 `123/compressed getlong def`125 def`009`009% 9 - true if compressed
X
X%%`009getlong <int>
X%
X%`009converts 4 hex bytes from currentfile to an integer
X%`009longwords from the vax are transmitted low order byte first.
X%
X/getlong
X`123
X`009/acc 0 def`009`009`009`009% preset accumulator
X`0090 1 3 `123
X`009`009readbyte exch 8 mul bitshift acc or /acc exch def
X`009`125 for
X`009acc
X`125 def
X
X
X%%`009readbyte <int>
X%
X%`009reads a hex byte from currentfile and returns it on the stack
X%`009executes "readbyteeof" if EOF encountered
X%
X/readbyte
X`123
X`009currentfile 1string readhexstring `123`125`123pop readbyteeof`125 ifelse
V 0 get
X`125 def
X
X
X
X%%`009main program
X%
X/main
X`123
X`009decodeheader`009`009`009`009% apply user user header
X`009currentdict /parser known `123parser`125 if`009% if user inputs
X
X`009invert 0 ne `123
X`009`009`1231.0 exch sub`125 settransfer`009% invert image
X`009`125 if
X
X`009/sTime usertime def`009`009`009% save start time
X     vmstatus 10 20 string cvrs dbg exch writestring dbg ( ) writestring
X              10 20 string cvrs dbg exch writestring dbg ( ) writestring
X              10 20 string cvrs dbg exch writestring dbg ( \n) writestring
X      flush
X`009/iscale 1 scale div def`009`009`009% compute scale factor
X`009
X`009compressed 1 eq `123`009`009`009% if encoded
X`009`009xsize ysize pxlwid `091iscale 0.0 0.0 iscale 0.0 0.0`093
X`009`009`009`009`009`009`009`123 deCompress `125 image
X`009`125 `123
X`009`009xsize ysize pxlwid `091iscale 0.0 0.0  iscale 0.0 0.0`093
X`009`009    `123 currentfile tmp readhexstring not `123pop <00>`125 if `125
V image
X`009`125 ifelse
X
X`009usertime sTime sub 1000 div 10 20 string cvrs
X`009 dbg exch writestring dbg ( seconds )
X`009 writestring
X
X    vmstatus 10 20 string cvrs dbg exch writestring dbg ( ) writestring
X            10 20 string cvrs dbg exch writestring dbg ( ) writestring
X              10 20 string cvrs dbg exch writestring dbg ( \n) writestring
X      flush
X
X`009showpage
X`009currentfile flushfile`009`009% avoid laser_log's
X`125 def
X
X
X%%`009executable initialization
X%
X/inp (%stdin) (r) file def`009`009`009% define files
X/dbg (%stdout) (w) file def`009
X/1string 1 string def`009`009`009`009% scratch 1 byte string
X/10string 10 string def`009`009`009`009% scratch 10 byte string
X/identity matrix def`009`009`009`009% make an identity matrix
X/outstring 128 string def`009`009`009% storage for output string
X/instring 1 string def`009`009`009`009% input buffer
X/tmp 8 string def`009`009`009`009% for uncompressed images
X
X/table `091
X `091/#copies 1 (.nc .ncopies .param1)`093`009`009% number of copies
X `091/scale 1.0 (.sf .scale .param2)`093`009`009% scale factor
X `091/xsize 512 (.xsize .param3)`093`009`009`009% x size
X `091/ysize 512 (.ysize .param4)`093`009`009`009% y size
X `091/pxlwid 1 (.pxlwid .param5)`093`009`009`009% pixel width
X `091/invert 0 (.invert .param6)`093`009`009`009% invert image if 1
X `091/compressed 1 (.compressed .param7)`093`009`009% default to compressed
X`093 def
X
Xtable `123`009`009`009`009`009`009% apply defaults
X`009/ta exch def`009`009`009`009% save array
X`009ta 0 get`009`009`009`009% key
X`009ta 1 get`009`009`009`009% default value
X`009def`009`009`009`009`009% define default value
X`125 forall
X
X1 72 mul 10 72 mul moveto currentpoint translate
Xcurrentpoint transform`009`009`009% see where we are in device coords
Xidentity setmatrix`009`009`009% turn off transformation - switch to
X`009`009`009`009`009%  device coordinate system
Xtranslate`009`009`009`009% move origin to transformed currpt
X
X/doit `123
X`009`123main`125 stopped `123 (error stack:\n) = pstack flush quit`125 if
X`125 def
X%doit
Xmain
$ CALL UNPACK [.LASER_DIST]IMAGE_HEX.PS;1 1701784921
$ create/nolog 'f'
X
X/***`009LASER - A Single-Threaded Asynchronous Symbiont to drive
X*`009`009an Apple LaserWriter.
X*
X*`009Copyright (C) 1987, The University of Texas at Austin
X*
X*`009Please send modifications, suggestions, bugs, etc to:
X*
X*`009Rick Watson
X*`009The University of Texas at Austin
X*`009Computation Center
X*`009Austin, TX 78712
X*`009512/471-3241
X*
X*`009arpa:`009watson@utadnx.cc.utexas.edu
X*`009bitnet:`009watson@utadnx  (ccaw001@utadnx for non-mail)
X*`009span:`009utspan::ccaw001`009(utspan is 25.128)
X*`009uucp:`009...seismo!ut-ngp!rick
X*
X*`009Look for new versions in the anonymous ftp directory on`032
X*`009utadnx.cc.utexas.edu (128.82.1.26).
X*
X*`009Revised:
X*`009Steve Roseman
X*`009Lehigh University Computing Center
X*`009lusgr@vax1.cc.lehigh.edu
X*
X*`009This user-writter symbiont is tailored specifically to the Apple
X*`009LaserWriter and similar PostScript printers.  It has the following
X*`009features:
X*
X*`0091. Page counting is done by reading the page count from the
X*`009   laserwriter at the beginning and the end of each file.
X*`009   This mechanism also "synchronizes" the user job with the
X*`009   laserwriter.  If the laserwriter does not respond to the
X*`009   first request for a page count, the symbiont notifies the
X*`009   operator, and continues to poll the laserwriter.  This is
X*`009   usefull if the laserwriter is being shared with MAC users.
X*
X*`0092. Parameters may be passed to postscript modules in the setup
X*`009   library via 2 mechanisms.  The text from a $PRINT /NOTE=<text>
X*`009   command will be sent first.
X*
X*`009   The /PARAMETER switch may also be used.  Each entry can be
X*`009   one of two formats. An entry without the "=" character in
X* `009   it is sent as (param<n>) <parameter>.  An entry with the`032
X*`009   "=" character in is is sent as (<left side>) <right side>.
X*`009   The parameters are defined in an array called /param.
X*`009   Example:  /PARAMETER=(1,SIZE=5,"str=(a+b)") generates:
X*`009   /param `091(param1) 1 (size) 5 (str) (a+b)`093 def
X*`009   All alphabetics are forced to lower case.  Using the /PARAMETER
X*`009   switch forces sending PARSER from LASER.TLB as part of the
X*`009   PostScript program sent to the printer.  Look at`032
X*`009   other files in LASER.TLB for examples of using the PARSER
X*`009   module.
X*
X*`0093. If the name of a setup module ends with "_HEX" the file to`032
X*`009   be printed is "hexified" to the laser printer.  This is useful
X*`009   for sending bitimage files to the laserwriter.
X*
X*`0094. A log of responses from the laserwriter is created.  This is`032
X*`009   usefull for debugging postscript programs.  The file is created
X*`009   as <printfilespec>.LASER_LOG.  In the case of spooled output,
X*`009   the log file is written to LASER$LOG:<printfilespec>.LASER_LOG.
X*`009   These files are automatically deleted if empty.
X*
X*`0095. Printer error messages from the laserwriter are sent to operators
X*`009   enabled to receive PRINT messages from OPCOM.
X*
X*`0096. A "%%`091 Flushing:" response from the printer will abort the
X*`009   current file.
X*
X*`0097. Spooled files:  Spooled files normally default to FORMS=HEADERS
X*`009   if the recommended queue initialize procedure is followed.
X*`009   By specifying special filenames, the user can override the
X*`009   forms used, and pass parameters to the setup module.
X*`009   The syntax is:  "_<formname>._<parameter list>"
X*`009   where <formname> is the name of a form to use and
X*`009   <parameter list> is of the form: <parameter>-<value>`091_...`093.
X*`009   (Note the use of "-" instead of "=" for a separator.)
X*`009   For example:  $ copy zeta.plt alw:_zeta._ncopies-5_scale-2
X*`009   (The kludge of the century, huh?)
X*
X*`009Outputs (in the following order) to the laserwriter:
X*
X*`0091. "/note <notestring> def\r\n".
X*`0092. /param definition and library module PARSER if /parameter switch`032
X*`009   present
X*`0093. If the setup module is "HEADERS", the string "/filename <filename>
X*`009   def" and "/formname <name of form> def"
X*`0093. The first file or forms setup module if specified.
+-+-+-+-+-+-+-+-  END  OF PART 2 +-+-+-+-+-+-+-+-

