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

Received: From KL.SRI.COM by CRVAX.SRI.COM with TCP; Fri,  1 SEP 89 10:47:30 PDT
Received: from ecsgate.uncecs.edu by KL.SRI.COM with TCP; Fri, 1 Sep 89 10:43:08 PDT
Received: by ecsgate.uncecs.edu (5.59/UNCECS/8-30-88)
	id AA24237; Fri, 1 Sep 89 13:13:12 EDT
Message-Id: <8909011713.AA24237@ecsgate.uncecs.edu>
Date: Fri, 1 Sep 89 13:07 EDT
From: "Bill Bailey, 'The VAXman'" <BAILEYB@ATSUVAX1.BITNET>
Subject: Apple LaserWriter Symbiont (6 of 12)
To: INFO-VAX@KL.SRI.COM
X-Vms-To: INFOVAX

-+-+-+-+-+-+-+-+ START OF PART 6 -+-+-+-+-+-+-+-+
X`009stat = sys$qiow(0, chan, IO$_SENSEMODE, 0, 0, 0,
X`009`009mode, 12, 0, 0, 0, 0);
X`009if (!(stat & 1)) return stat;
X`009
X`009mode`0911`093 &= `126(TT$M_NOTYPEAHD);`009`009/* clear notypeahead */
X`009stat = sys$qiow(0, chan, IO$_SETMODE, 0, 0, 0,`009
X`009`009mode, 12, 0, 0, 0, 0);
X
X`009return stat;
X`125
X
X
X/**`009startstream - start the stream.
X*/
Xstartstream()
X`123
X`009int`009stat;
X`009static int svector`0912`093 = `1231,0`125;`009`009/* status vector */
X
X`009struct dsc$descriptor_s device = `1230, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0`
V125;
X`009struct dsc$descriptor_s temp = `1230, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0`12
V5;
X`009
X`009getitemdescrip(SMBMSG$K_DEVICE_NAME, &device, TRUE);
X`009
X/*  Copy the library file specification, if it exists */
X`009
X`009if (getitemdescrip(SMBMSG$K_LIBRARY_SPECIFICATION, &temp, FALSE))
X`009`009str$copy_dx(&library_spec, &temp);
X
X`009svector`0911`093 = sys$alloc(&device, 0, 0, 0, 0);
X`009if (svector`0911`093 == SS$_NORMAL)`032
X`009`009svector`0911`093 = sys$assign(&device, &laserchan, 0, 0);
X`009if (svector`0911`093 != SS$_NORMAL) `123
X`009`009stat = smb$send_to_jobctl(&0, &SMBMSG$K_START_STREAM,
X`009`009`0090, 0, 0, svector);
X`009`009checkstat(stat, "startstream: send to jobctl");
X`009`009return;
X`009`125
X
X`009set_typeahead(laserchan);`009`009/* set terminal typeahead */
X`009
X`009stat = smb$send_to_jobctl(&0, &SMBMSG$K_START_STREAM,
X`009`0090, 0, 0, 0);`009`009`009/* ok */
X`009checkstat(stat, "startstream: send to jobctl");
X`125
X
X
X/**`009stopstream - stop the stream.
X*/
Xstopstream()
X`123
X`009int stat;
X
X`009stat = sys$dassgn(laserchan);
X`009checkstat(stat, "stopstream: dassgn");
X`009laserchan = 0;
X
X`009stat = smb$send_to_jobctl(&0, &SMBMSG$K_STOP_STREAM, 0, 0, 0, 0);
X`009checkstat(stat, "stopstream: send to jobctl");
X`009
X`009exit(SS$_NORMAL);
X`125
X
X
X/**`009syncprinter - get synchronized with printer.
X*/
Xsyncprinter()
X`123
Xstatic char getstart`091`093 = `123
X"\004\
Xversion (23.0) eq `123 statusdict /Patch1Installed known not `123 \
X(%%`091 patch needed `093%%\n) print `125 if `125 if \
Xstatusdict begin (%%`091 start page #=) print \
Xpagecount pstack pop flush end \r\n\004"`125;
X
X`009int stat;
X`009int daytim`0912`093;`009`009`009`009/* quadword time interval */
X`009int timeoutcount;
X`009static $DESCRIPTOR(timetowait, "0 ::10");`009/* +10 sec */
X`009static $DESCRIPTOR(patch, "PATCH");
X`009int expireindex;
X`009static int expiretime`091`093 = `1231,1*60/10,5*60/10,10*60/10,60*60/10`
V125; /* notify intervals */
X#define NEXPIRES (sizeof(expiretime)/sizeof(int))
X`009startpage = 0;
X
X`009status_idle = FALSE;
X`009
X`009timeoutcount = 0;
X`009expireindex = 0;
X`009do `123
X`009`009lib$wait(&1.0);`009`009`009/* wait 1 second */
X`009`009WRITELASER(&0x14,1)`009`009/* `094T */
X
X`009`009stat = sys$bintim(&timetowait, daytim);
X`009`009checkstat(stat, "bintim");
X`009`009stat = sys$schdwk(0, 0, daytim, 0);`009/* wake up later */
X`009`009checkstat(stat, "schdwk");
X
X`009`009stat = sys$hiber();
X`009`009if (status_idle) break;`009`009/* if sync occured */
X
X/*  Abort whatever is happening */
X
X`009`009WRITELASER(&0X03,1)`009`009/* control-c */
X`009`009lib$wait(&1.0);`009`009`009/* wait 1 second */
X`009`009WRITELASER(&0X04,1)`009`009/* end of job */
X`009`009lib$wait(&1.0);`009`009`009/* wait 1 second */
X`009`009
X/*  Notify the operator on 1 minute intervals. */
X`009`009
X`009`009if (++timeoutcount == expiretime`091expireindex`093) `123
X`009`009`009strcpy(msg.text, "LaserWriter offline");
X`009`009`009oprmsg_dsc.dsc$w_length = 8 + strlen(msg.text);
X`009`009`009sys$sndopr(&oprmsg_dsc, 0);
X`009`009`009timeoutcount = 0;`009`009/* reset counter */
X`009`009`009if (expireindex < (NEXPIRES-1)) expireindex++;
X`009`009`125
X`009`009
X`009`125 while (TRUE);
X`009
X`009stat = sys$canwak(0,0);`009/* cancel wakeup requests */`009
X`009
X`009timeoutcount = 0;
X`009expireindex = 0;
X`009do `123
X`009`009WRITELASER(getstart,strlen(getstart))
X
X`009`009stat = sys$bintim(&timetowait, daytim);
X`009`009checkstat(stat, "bintim");
X`009`009stat = sys$schdwk(0, 0, daytim, 0);`009/* wake up later */
X`009`009checkstat(stat, "schdwk");
X
X`009`009stat = sys$hiber();
X`009`009if (startpage) break;`009`009/* if sync occured */
X
X/*  Notify the operator on 1 minute intervals. */
X`009`009
X`009`009if (++timeoutcount == expiretime`091expireindex`093) `123
X`009`009`009strcpy(msg.text, "LaserWriter offline");
X`009`009`009oprmsg_dsc.dsc$w_length = 8 + strlen(msg.text);
X`009`009`009sys$sndopr(&oprmsg_dsc, 0);
X`009`009`009timeoutcount = 0;`009`009/* reset counter */
X`009`009`009if (expireindex < (NEXPIRES-1)) expireindex++;
X`009`009`125
X`009`009
X`009`125 while (TRUE);
X`009
X`009stat = sys$canwak(0,0);`009/* cancel wakeup requests */
X`009
X/*  This looks like a good place to send the patch module */
X
X`009if (patchneeded) `123`009`009`009/* if patch needed */
X`009`009patchneeded = FALSE;
X`009`009writemodule(patch);`009`009/* write the patch module */
X`009`009WRITELASER(&4, 1)
X`009`125
X`125
X`009
X
X/**`009trailer - issue job trailer.
X*/
Xtrailer(which)
Xint which;`009`009`009`009`009/* 0 if flag, 1 if trailer */
X`123
X`009int ctl, stat, stop;
X`009short msglen;
X`009char buf`0911024`093;`009`009`009`009/* scratch buffer */
X`009char time`09124`093;
X`009char user`09120`093, job`091255`093, file`091255`093, message`091257`093
V;
X`009char *cp;
X`009static char z = 0;
X`009static $DESCRIPTOR(key, "TRAILER");
X`009struct dsc$descriptor_s temp = `1230, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0`12
V5;
X`009struct dsc$descriptor_s date=`12323, DSC$K_DTYPE_T, DSC$K_CLASS_S, time`
V125;
X`009struct dsc$descriptor_s msgd =
X`009`009`123sizeof(message)-1, DSC$K_DTYPE_T, DSC$K_CLASS_S, message`125;
X`009static struct dsc$descriptor_s zero =
X`009`009`009`009`1231, DSC$K_DTYPE_T, DSC$K_CLASS_S, &z`125;
X
X/*  Check to see if we need a trailer. */
X
X`009getitemdescrip(SMBMSG$K_SEPARATION_CONTROL, &temp, TRUE);
X`009ctl = * (long*) temp.dsc$a_pointer;
X
X`009/*  save page count if first file of job */
X`009if (ctl & SMBMSG$M_FIRST_FILE_OF_JOB) jobstart = startpage;
X`009
X`009if (which == 0) `123`009`009`009/* if flag page */
X`009`009if ((ctl & (SMBMSG$M_FILE_FLAG `124 SMBMSG$M_JOB_FLAG))  == 0) /* if
V no flags */
X`009`009`009return;
X
X`009`009if ((ctl & SMBMSG$M_FILE_FLAG) == 0) /* if job only */
X`009`009`009if ((ctl & SMBMSG$M_FIRST_FILE_OF_JOB) == 0) /* if not first fil
Ve */
X`009`009`009`009return;
X`009`125
X`009else `123`009`009`009`009`009/* trailer page */
X`009`009if (((ctl & (SMBMSG$M_JOB_TRAILER `124 SMBMSG$M_FILE_TRAILER))== 0)
V &&
X`009`009`009((stop_task `124 stop_reason) == 0)) return;
X
X`009`009if ((stop_task `124 stop_reason) == 0) /* if no error */
X`009`009`009if ((ctl & SMBMSG$M_FILE_TRAILER) == 0) /* if job only */
X`009`009`009`009if ((ctl & SMBMSG$M_LAST_FILE_OF_JOB) == 0) /* if not last f
Vile */
X`009`009`009`009`009return;
X`009`125
X`009
X/*  send the trailer module from the library */
X
X`009WRITELASER(&4,1)`009`009`009/* leading EOF */
X`009if(!writemodule(key)) return;
X
X`009getitemdescrip(SMBMSG$K_USER_NAME, &temp, TRUE);
X`009strncpy(user, temp.dsc$a_pointer, temp.dsc$w_length);
X`009user`091temp.dsc$w_length`093 = 0;
X
X`009getitemdescrip(SMBMSG$K_JOB_NAME, &temp, TRUE);
X`009strncpy(job, temp.dsc$a_pointer, temp.dsc$w_length);
X`009job`091temp.dsc$w_length`093 = 0;
X
X`009getitemdescrip(SMBMSG$K_FILE_SPECIFICATION, &temp, TRUE);
X`009strncpy(file, temp.dsc$a_pointer, temp.dsc$w_length);
X`009file`091temp.dsc$w_length`093 = 0;
X
X`009lib$date_time(&date);
X`009time`09123`093 = 0;
X
X`009sprintf(buf,
X`009 "setuppage (%s) h-job (%s) h-user (%s) h-file (%s) h-time  ",
X`009  job, user, file, time);
X`009WRITELASER(buf,strlen(buf))
X`009
X/*  only print page count on last trailer page */
X`009
X`009if ((which == 1) && (ctl & SMBMSG$M_LAST_FILE_OF_JOB)) `123 /* if last o
Vne */
X`009`009sprintf(buf, "(%d) h-pages ", jobstart);
X`009`009WRITELASER(buf,strlen(buf))
X`009`125
X`009
X`009
X`009if ((which == 1) && (stop_task `124 stop_reason)) `123
X`009`009if (stop_task) stop = stop_task; else stop = stop_reason;
X`009`009msglen = 0;`009`009`009/* in case of error */
X`009`009stat = sys$getmsg(stop, &msglen, &msgd, 15, 0);
X`009`009checkstat(stat,"$getmsg");
X`009`009message`091msglen`093 = 0;
X`009`009sprintf(buf, "(%s) h-error ", message);
X`009`009WRITELASER(buf,strlen(buf))
X`009`125
X`009
X`009if (userlog > 0) `123`009`009`009/* if log file */
X`009`009str$append(&savelog, &zero);
X`009`009for (cp=savelog.dsc$a_pointer; *cp; cp+=strlen(cp)+1) `123
X`009`009`009sprintf(buf, "(%s) h-logline\n", cp);
X`009`009`009WRITELASER(buf,strlen(buf))
X`009`009`125
X`009`125
X`009
X`009sprintf(buf, " showpage \004");
X`009WRITELASER(buf,strlen(buf))
X`125
X
X
X/**`009writemodule - write module from library.
X*
X*`009return:`009TRUE if module written, else FALSE.
X*/
Xwritemodule(key)
Xstruct dsc$descriptor_s key;
X`123
X`009int stat, len;
X`009int library_index;
X`009long txtrfa`0912`093;
X`009char inbuf`091255`093;
X`009struct dsc$descriptor_s inbufdes = `123sizeof(inbuf), DSC$K_DTYPE_T, DSC
V$K_CLASS_S, inbuf`125;
X`009struct dsc$descriptor_s outbufdes;
X
X`009if (library_spec.dsc$a_pointer == 0) return FALSE;
X`009
X`009stat = lbr$ini_control(&library_index, &LBR$C_READ, &LBR$C_TYP_TXT, 0);
X`009checkstat(stat, "ini_control");
X
X`009stat = lbr$open(&library_index, &library_spec, 0, 0, 0, 0, 0);
X`009checkstat(stat, "open");
X
X`009stat = lbr$lookup_key(&library_index, &key, txtrfa);
X`009if ((stat & 1) != 1) `123`009`009`009/* if bad key */
X`009`009stat = lbr$close(&library_index);
X`009`009checkstat(stat, "close library");
X`009`009return FALSE;
X`009`125
X
X`009do `123
X`009`009stat = lbr$get_record(&library_index, &inbufdes, &outbufdes);
X`009`009if (stat == RMS$_EOF) break;
X`009`009
X`009`009len = outbufdes.dsc$w_length;
X`009`009inbuf`091len++`093 = '\r';
X`009`009inbuf`091len++`093 = '\n';
X
X`009`009WRITELASER(inbuf,len)
X`009`009
X`009`125 while (1);
X
X`009stat = lbr$close(&library_index);
X`009checkstat(stat, "close");
X`125
X
X
X/**`009writeuserlog - write line to user log file.
X*/
Xwriteuserlog()
X`123
X`009int stat;
X`009static struct dsc$descriptor_s temp =
X`009`009`009`009`1230, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0`125;
X
X`009if (userlog == -1) return;`009`009/* if no log file */
X`009
X`009sys$setast(0);
X`009
X`009userlog++;`009`009`009`009/* bump flag */
X
X`009log_rab.rab$l_rbf = laser_buf;
X`009log_rab.rab$w_rsz = strlen(laser_buf);
X
X`009stat = sys$put(&log_rab, 0, 0);
X`009
X`009if (userlog <= 5) `123`009`009`009/* save first 5 lines */
X`009`009temp.dsc$w_length = strlen(laser_buf) + 1;`009/* incl 0 */
X`009`009temp.dsc$a_pointer = laser_buf;
X`009`009str$append(&savelog, &temp);
X`009`125
X`009
X`009sys$setast(1);
X
X`009checkstat(stat, "write log");
X`125
$ CALL UNPACK [.LASER_DIST]LASER.C;1 710060858
$ create/nolog 'f'
X1 LaserWriter
X2 Forms
XThe following forms are defined for use with the LaserWriter. Parameters
Xare passed as follows on the print command:
X
X                   /param=(parameter=value,...)
X
XForm`009`009Parameters
X
XHEADERS`009`009Print file with filename and page number headers.
X`009`009ncopies:   Number of copies. (default: 1)
X`009`009fsize:`009   Font size in points. (default: 10)
X`009`009wide:`009   If true set landscape mode. (default: false)
X`009`009title:`009   If false suppress the page headers. (default: true)
X`009`009ncolumns:  Number of columns. (default: 1)
X`009`009linelimit: Max number of lines per page. (default 66)`009
X
X`009`009(Under VMS >= 4.4, HEADERS is the default for spooled files)
X
XLETTER`009`009Same as HEADERS except default title to false.
X
XLANDSCAPE`009Same as LETTER except default wide to true, fsize to 8.
X
X2UP`009`009Same as LANDSCAPE except default ncolumns to 2.
X
XPAINT`009`009Print a MacPaint image.
X`009`009ncopies:   Number of copies. (default: 1)
X`009`009scale:`009   Scale factor. (default: 4, recommended: 1-4)`009
X
XBITIMAGE`009Print an uncompressed image.
X`009`009ncopies:  Number of copies. (default: 1)
X`009`009scale:`009  Scale factor. (default: 1)
X`009`009xsize:    Number of pixels in a row. (default: 512)
X`009`009ysize:`009  Number of pixel columns. (default: 512)
X`009`009pxlwid:`009  Number of bits in a pixel, default 1, values: 1,2,4,8
X
XZETA`009`009Print a zeta plot file.
X`009`009ncopies:  Number of copies. (default: 1)
X`009`009scale:`009  Scale factor. (default: 1)
X`009`009zFont:    false - selects Helvetica font for internal character
X`009`009`009  true -  (default) uses Zeta characters
X`009`009penscale: Scaling factor for pen point (default: 1)
X`009`009usepens:  false - (default) ignore alternate pen select
X2 Spooling
XSpooled file names have the following syntax:
X
X                     _FormName._ParameterList
X
Xwhere ParameterList is a list of parameters separated by "_". Keywords
Xare separated from their values with "-". Example:
X
X             $ copy thing.mpt alw:_paint._scale-4_ncopies-5
X
X2 Examples
X
X1. $ PRINT/QUEUE=ALW/FORM=HEADERS/PARAM=(NCOPIES=4,FSIZE=14)  STUFF.TXT
X     Prints 4 copies of STUFF.TXT with a font size of 14.
X
X2. $ PRINT/QUEUE=ALW/FORM=POST/NOTE="/debug true def" USER.PS
X     "Prints" (executes) a user's PostScript file.  The first line sent
X     to the printer will be "/debug true def".
X
X3. $ FORTRAN /LIST=ALW:_LANDSCAPE TEST.FOR
X     Compile a program, spooling the output to the LaserWriter.
X
X4. $ PRINT/QUEUE=ALW/FORM=POST USER.PS -
X           /NOTE="statusdict begin /manualfeed true def end"
X     Set up to feed the printer manually, by sending the PostScript
X     command that enables the manual feed option.
$ CALL UNPACK [.LASER_DIST]LASER.HLP;1 460532163
$ create/nolog 'f'
Xlaser,laser_err,sys$share:vaxcrtl.exe/share
$ CALL UNPACK [.LASER_DIST]LASER.OPT;1 606016596
$ create/nolog 'f'
X`009.Title`009`009LASER error messages
X`009.Facility`009LASER,1/prefix=LASER$_
X        .Ident`009`009'LASER Version 1.0'
X
X`009.Severity`009FATAL
X`009MAXITEMS`009<Too many items in item list.>
X`009ITEMNOTFOUND`009<Item not in item list.>
X`009STREAMNOTSTART`009<Stream was not started.>
X`009TOOMANYTABS`009<Too many tabs in input record.>
X`009FLUSHED`009`009<Job flushed.>
+-+-+-+-+-+-+-+-  END  OF PART 6 +-+-+-+-+-+-+-+-

