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

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

-+-+-+-+-+-+-+-+ START OF PART 4 -+-+-+-+-+-+-+-+
X`009char obuf`09140`093;
X
X`009if (ccb == 0) `123
X`009`009return;
X`009`125
X
X`009if ((ccb & 0x80) == 0) `123`009`009/* output (n) LF, 1 CR */
X`009`009if ((ccb & 0x7f) == 1) `123`009/* 1 LF, output short form */
X`009`009`009WRITELASER("XLF XCR\r\n", 9);
X`009`009`125
X`009`009else `123
X`009`009`009sprintf(obuf, "%d`123XLF`125repeat XCR\r\n",(ccb & 0x7f));
X`009`009`009WRITELASER(obuf, strlen(obuf));
X`009`009`125
X`009`125
X`009else `123
X`009`009if ((ccb & 0xe0) != 0xe0) `123`009/* output single character */
X`009`009`009ic = ccb & 0x7f;
X`009`009`009expand_line(&ic, obuf, 1);
X`009`009`125
X`009`125
X`125
X
X
X/**`009expand_hex - expand buffer into hex bytes.
X*/
Xexpand_hex(ibuf, obuf, rsz)
Xunsigned char *ibuf;`009`009`009/* pointer to input buffer */
Xchar *obuf;`009`009`009`009/* pointer to output buffer */
Xint rsz;`009`009`009`009/* buffer size */
X`123
X`009int i, c, stat;
X`009static char hex`091`093 = "0123456789ABCDEF";
X`009
X`009for (i = 0; i < rsz; i++) `123
X`009`009obuf`091i*2`093 = hex`091(ibuf`091i`093 & 0xF0) >> 4`093;
X`009`009obuf`091i*2+1`093 = hex`091ibuf`091i`093 & 0xF`093;
X`009`125
X`009WRITELASER(obuf,rsz*2)
X`125
X
X`009
X/**`009expand_line - expand input buffer and output result to printer.
X*
X*`009The ()pop sequences are an obscure hack to fix an obscure bug
X*`009with XON/XOFF.  It just works.
X*/
Xexpand_line(ibuf, obuf, rsz)
Xchar *ibuf;`009`009`009`009`009/* input buffer */
Xchar *obuf;
Xint rsz;`009`009`009`009`009/* buffer size */
X`123
X`009int i, d, col, stat;
X`009static int popcount = 0;`009`009/* XON kludge counter */
X`009
X`009d = 0;`009`009`009`009`009/* preset destination index */
X`009col = 0;`009`009`009`009/* preset column */
X
X`009for (i = 0; i < rsz; i++) `123
X`009`009if (ibuf`091i`093 == 9 ) `009`009`123`009/* if tab */
X`009`009`009if (string && (d == 0)) obuf`091d++`093 = '(';/* if first */
X`009`009`009do `123
X`009`009`009`009obuf`091d++`093 = ' ';`009/* fill spaces */
X`009`009`009`009col++;
X`009`009`009`125 while (col & 7);
X`009`009`125
X`009`009else if ((ibuf`091i`093 == 8) && (col > 0)) `123`009/* if backspace
V */
X`009`009`009obuf`091d++`093 = 8;`009/* insert backspace */
X`009`009`009col--;
X`009`009`125
X`009`009else if (string && (ibuf`091i`093 == '(')) `123`009/* ( */
X`009`009`009if (string && (d == 0)) obuf`091d++`093 = '(';/* if first */
X`009`009`009obuf`091d++`093 = '\\';
X`009`009`009obuf`091d++`093 = '(';
X`009`009`009col++;
X`009`009`125
X`009`009else if (string && (ibuf`091i`093 == ')')) `123`009/* ) */
X`009`009`009if (string && (d == 0)) obuf`091d++`093 = '(';/* if first */
X`009`009`009obuf`091d++`093 = '\\';
X`009`009`009obuf`091d++`093 = ')';
X`009`009`009col++;
X`009`009`125
X`009`009else if (string && (ibuf`091i`093 == '\\')) `123`009/* \ */
X`009`009`009if (string && (d == 0)) obuf`091d++`093 = '(';/* if first */
X`009`009`009obuf`091d++`093 = '\\';
X`009`009`009obuf`091d++`093 = '\\';
X`009`009`009col++;
X`009`009`125
X`009`009else if (string && (ibuf`091i`093 == 0x0d)) `123 /* CR */
X`009`009`009if (d) `123`009`009/* if string to terminate */
X`009`009`009`009WRITELASER(obuf,d)
X`009`009`009`009if (++popcount == 20) `123
X`009`009`009`009`009popcount = 0;
X`009`009`009`009`009WRITELASER(")XSTR()pop\r\n",12)
X`009`009`009`009`125
X`009`009`009`009else `123
X`009`009`009`009`009WRITELASER(")XSTR\r\n",7)
X`009`009`009`009`125
X`009`009`009`009d = 0;
X`009`009`009`125
X`009`009`009WRITELASER("XCR\r\n",5)
X`009`009`125
X `009`009else if (string && (ibuf`091i`093 == 0x0a)) `123 /* LF */
X`009`009`009if (d) `123`009`009/* if string to terminate */
X`009`009`009`009WRITELASER(obuf,d)
X`009`009`009`009if (++popcount == 20) `123
X`009`009`009`009`009popcount = 0;
X`009`009`009`009`009WRITELASER(")XSTR()pop\r\n",12)
X`009`009`009`009`125
X`009`009`009`009else `123
X`009`009`009`009`009WRITELASER(")XSTR\r\n",7)
X`009`009`009`009`125
X`009`009`009`009d = 0;
X`009`009`009`125
X`009`009`009WRITELASER("XLF\r\n",5)
X`009`009`125
X `009`009else if (string && (ibuf`091i`093 == 0x0c)) `123 /* FF */
X`009`009`009if (d) `123`009`009/* if string to terminate */
X`009`009`009`009WRITELASER(obuf,d)
X`009`009`009`009if (++popcount == 20) `123
X`009`009`009`009`009popcount = 0;
X`009`009`009`009`009WRITELASER(")XSTR()pop\r\n",12)
X`009`009`009`009`125
X`009`009`009`009else `123
X`009`009`009`009`009WRITELASER(")XSTR\r\n",7)
X`009`009`009`009`125
X`009`009`009`009d = 0;
X`009`009`009`125
X`009`009`009WRITELASER("XFF\r\n",5)
X`009`009`125
X`009`009else `123
X`009`009`009if (string && (d == 0)) obuf`091d++`093 = '(';/* if first */
X`009`009`009obuf`091d++`093 = ibuf`091i`093;`009/* move char */
X`009`009`009col++;
X`009`009`125
X`009`125
X`009if (string && d) `123
X`009`009obuf`091d++`093 = ')';
X`009`009obuf`091d++`093 = 'X';
X`009`009obuf`091d++`093 = 'S';
X`009`009obuf`091d++`093 = 'T';
X`009`009obuf`091d++`093 = 'R';
X`009`009obuf`091d++`093 = '\r';
X`009`009obuf`091d++`093 = '\n';
X`009`125
X`009WRITELASER(obuf,d)
X`125
X
X
X/**`009getitems - get item list from job controller.
X*/
Xgetitems()
X`123
X`009int stat;
X`009int`009context;`009`009`009/* read_message_item context */
X`009int`009item_code;`009`009`009/* item code */
X`009unsigned short item_size;`009`009/* item size */
X`009struct dsc$descriptor_d item_buffer =
X`009`009`009`009`1230, DSC$K_DTYPE_T, DSC$K_CLASS_D, 0`125;
X
X`009context = 0;`009`009`009`009/* init context */
X
X/*  Save each item in a list */
X`009
X`009do `123
X`009`009item_buffer.dsc$a_pointer = 0;`009/* force d string allocation */
X
X`009`009stat = smb$read_message_item(&buffer_des, &context,
X`009`009&item_code, &item_buffer, &item_size);
X
X`009`009item`091ii`093.item_code = item_code;
X`009`009item`091ii`093.item_size = item_size;
X`009`009item`091ii`093.buffer = item_buffer.dsc$a_pointer;
X`009`009if (++ii > MAXITEMS) exit(LASER$_MAXITEMS);
X`009`125 while (stat == SS$_NORMAL);
X`125
X
X
X/**`009getitemdescrip - return item descriptor.
X*
X*`009return:`009TRUE if item found
X*`009`009FALSE if (item not found) && NOT FATAL
X*`009`009exit if (item not found) && FATAL
X*/
Xgetitemdescrip(code, descrip, fatal)
Xint code;`009`009`009`009`009/* item code to search for */
Xstruct dsc$descriptor_s *descrip;`009`009/* pointer to descriptor */
Xint fatal;`009`009`009`009`009/* error severity */
X`123
X`009int`009i;
X
X`009for (i = 0; i < ii; i++) `123
X`009`009if (item`091i`093.item_code == code) `123`009/* if found */
X`009`009`009descrip->dsc$w_length = item`091i`093.item_size;
X`009`009`009descrip->dsc$a_pointer = item`091i`093.buffer;
X`009`009`009return TRUE;
X`009`009`125
X`009`125
X`009if (fatal) exit(LASER$_ITEMNOTFOUND);`009/* item not in list */
X`009else return FALSE;
X`125
X
X
X/**`009getcopies - send copy count to laserwriter.
X*
X*`009Leave this here for now, but unfortunately, if you specify
X*`009/copies=n to the print command, the job contoller sends
X*`009the file that many times.  Not what we want.
X*/
Xgetcopies()
X`123
X`009int stat, n;
X`009struct dsc$descriptor_s temp = `1230, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0`12
V5;
X`009char defcopy`09180`093;
X
X`009if (!getitemdescrip(SMBMSG$K_FILE_COPIES, &temp, FALSE))
X`009`009if (!getitemdescrip(SMBMSG$K_JOB_COPIES, &temp, FALSE))
X`009`009`009return;`009`009`009/* if no copies */
X
X`009n = * (long*) temp.dsc$a_pointer;
X`009if (n == 1) return;`009`009`009/* if only 1 copy */
X`009sprintf(defcopy, "/#copies %d def\r\n", n);
X
X`009WRITELASER(defcopy,strlen(defcopy))
X`125
X
X
X/**`009getnote - get /note=<Text> to laserwriter.
X*/
Xgetnote()
X`123
X`009int stat;
X`009struct dsc$descriptor_s temp = `1230, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0`12
V5;
X`009
X`009if (!getitemdescrip(SMBMSG$K_NOTE, &temp, FALSE)) return; /* none */
X`009
X`009WRITELASER(temp.dsc$a_pointer,temp.dsc$w_length)
X`009WRITELASER(&0x0A0D,2)`009`009`009/* cr-lf */
X`125
X
X
X/**`009getparams - get user parameters.
X*/
Xgetparams()
X`123
X`009int stat;
X`009int i, j;
X`009int first=TRUE;
X`009struct dsc$descriptor_s temp = `1230, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0`12
V5;
X`009char param`091255`093, str`091255+15`093, *eq;
X`009static $DESCRIPTOR(parser,"PARSER");
X
X`009for (i = 0; i < 8; i++) `123`009`009/* loop for 8  parameters */
X`009`009if (!getitemdescrip(SMBMSG$K_PARAMETER_1+i, &temp, FALSE))
X`009`009`009continue;`009`009/* if no parameter */
X
X`009`009if (temp.dsc$w_length == 0) continue;`009/* if null string */
X
X`009`009if (first) `123`009`009`009`009/* if first one */
X`009`009`009first = FALSE;
X`009`009`009WRITELASER("/params `091\r\n",11)
X`009`009`125
X
X`009`009strncpy(param, temp.dsc$a_pointer, temp.dsc$w_length);
X`009`009param`091temp.dsc$w_length`093 = 0;
X`009`009
X`009`009for (j= 0; j < strlen(param); j++)`009/* lowercase string */
X`009`009`009if (isupper(param`091j`093)) param`091j`093 `094= 0x20;
X`009`009
X/*  if there is an = separator (or - for spooled files), use it */
X`009`009
X`009`009if ((eq = strchr(param, '=')) `124`124 (eq = strchr(param, '-'))
X`009`009`009`124`124 (eq = strchr(param, ':'))) `123
X`009`009`009*eq++ = 0;`009`009`009/* bust string in 2 */
X`009`009`009sprintf(str, "(%s) %s\r\n", param, eq);
X`009`009`125
X`009`009else sprintf(str, "(param%d) %s\r\n", i+1, param);
X
X`009`009WRITELASER(str,strlen(str))
X`009`125
X`009
X`009if (!first) `123`009`009`009`009/* if some params found */
X`009`009WRITELASER("`093 def\r\n",7)
X`009`009writemodule(parser);`009`009/* write the parser module */
X`009`125
X`125
X
X
X/**`009getsetup - get setup module to laserwriter.
X*
X*`009return:`009TRUE if no problems with setup module.
X*`009        FALSE if setup module nonexistant
X*/
Xgetsetup()
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`009struct dsc$descriptor_s key = `1230, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0`125
V;
X`009struct dsc$descriptor_s temp = `1230, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0`12
V5;
X`009`009
X`009ascii = TRUE;`009`009`009`009/* assume main file is ascii */
X`009hex = FALSE;
X`009string = FALSE;
X
X/*  Try for a file setup module first, then a form setup module.  For now,
X    we only support one setup module, the first found. We should support
X    lists of setup modules, and all found. */
X`009
X`009if (!getitemdescrip(SMBMSG$K_FILE_SETUP_MODULES, &key, FALSE))
X`009`009if (!getitemdescrip(SMBMSG$K_FORM_SETUP_MODULES, &key, FALSE))
X`009`009`009return TRUE;`009`009/* if no setup */
X
X`009if (key.dsc$w_length == 0) return TRUE;`009/* if no setup */
X`009
X/*  Get out if no library. Error because the user specified a setup. */
X
X`009if (library_spec.dsc$a_pointer == 0) `123
X`009`009stop_reason = LASER$_SETUPNOTFOUND;
X`009`009return FALSE;
X`009`125
X
X/*  Check to see if the setup module ends in _HEX or _STR */
X
X`009if (key.dsc$w_length >= 4)`123
X`009   if (strncmp(&key.dsc$a_pointer`091key.dsc$w_length-4`093,"_HEX", 4) =
V= 0)`123
X`009`009ascii = FALSE;
X`009`009hex = TRUE;
X`009   `125
X`009  `032
X`009   if (strncmp(&key.dsc$a_pointer`091key.dsc$w_length-4`093,"_STR", 4) =
V= 0)`123
X`009`009ascii = FALSE;
X`009`009string = TRUE;
X`009   `125
X        `125       `032
X       `032
X/*  if this is the setup module HEADERS, assume it needs to have the file
X    name defined. */
X
X    `009if (strncmp(key.dsc$a_pointer, "HEADERS", 7) == 0) `123
X`009`009getitemdescrip(SMBMSG$K_FILE_SPECIFICATION, &temp, TRUE);
X`009`009strcpy(inbuf, "/filename (");
X`009`009strncat(inbuf, temp.dsc$a_pointer, temp.dsc$w_length);
X`009`009strcat(inbuf, ") def\r\n");
X`009`009WRITELASER(inbuf,strlen(inbuf))
X
X/*  Also send the form name if it exists */
X
X`009`009if (getitemdescrip(SMBMSG$K_FORM_NAME, &temp, FALSE)) `123
X`009`009`009strcpy(inbuf, "/formname (");
X`009`009`009strncat(inbuf, temp.dsc$a_pointer, temp.dsc$w_length);
X`009`009`009strcat(inbuf, ") def \r\n");
X`009`009`009WRITELASER(inbuf,strlen(inbuf))
X`009`009`125
X`009`125
X`009
X/*  Send the setup module */
X
X`009if (!writemodule(key)) `123
X`009`009stop_reason = LASER$_SETUPNOTFOUND;
X`009`009return FALSE;
X`009`125
X`009
X`009return TRUE;
X`125
X
X
X/**`009inititems - initialize item list.
X*/
Xinititems()
X`123
X`009int`009i;
X
X`009for (i = 0; i < MAXITEMS; i++) item`091i`093.buffer = 0;
X`125
X
X
X/**`009initsymb - initialize printer symbiont.
X*/
Xinitsymb()
X`123
X`009int stat;
X
X`009stat = smb$initialize(&SMBMSG$K_STRUCTURE_LEVEL, jobctl_ast, 0);
X`009checkstat(stat, "initsymb");
X`125
X
X
X/**`009jobctl_ast - ast routine called by the job controller.
X*/
Xvoid jobctl_ast()
X`123`009
X`009int`009stat;
X`009int`009request;`009`009`009/* jobctl request */
X`009struct dsc$descriptor_s temp = `1230, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0`12
V5;
X
X`009stat = smb$read_message(&0, &buffer_des, &request);
X`009if (stat != SS$_NORMAL) exit(stat);
X
X/*  Process the request */
X
X`009switch (request) `123
X`009`009
X`009`009case SMBMSG$K_START_STREAM:
X`009`009getitems();
X`009`009startstream();
X`009`009break;
X
X`009`009case SMBMSG$K_START_TASK:
X`009`009getitems();
X`009`009start_task = TRUE;
X`009`009stop_task = 0;
X`009`009stop_reason = 0;
X`009`009break;
X
X`009`009case SMBMSG$K_RESUME_TASK:
X`009`009getitems();
X`009`009break;
X
X`009`009case SMBMSG$K_RESET_STREAM:
X`009`009resetstream();
X`009`009break;
X
X`009`009case SMBMSG$K_STOP_STREAM:
X`009`009stopstream();
X`009`009break;
X
X`009`009case SMBMSG$K_PAUSE_TASK:
X`009`009break;
X
X`009`009case SMBMSG$K_STOP_TASK:
X`009`009getitems();
X`009`009getitemdescrip(SMBMSG$K_STOP_CONDITION, &temp, TRUE);
X`009`009stop_task = * (long*) temp.dsc$a_pointer;
X`009`009break;
X`009`125
X`009sys$wake(0,0);
X`125
X
X
X/**`009laser_read_ast - laser read ast completion routine.
X*/
Xvoid laser_read_ast(param)
Xint param;
X`123
X`009int iosb_stat;
X
X`009iosb_stat = laser_iosb`0910`093;
X`009if (iosb_stat == 0) return;`009`009/* if incomplete io (?) */
X`009if ((iosb_stat == SS$_ABORT) `124`124
X`009`009(iosb_stat == SS$_CANCEL) `124`124
X`009`009(iosb_stat == SS$_DATAOVERUN)) return;
X`009if (iosb_stat != SS$_NORMAL) exit(iosb_stat);`009/* if error */
X
X`009if (laser_iosb`0911`093) `123`009`009`009/* if bytes in buffer */
+-+-+-+-+-+-+-+-  END  OF PART 4 +-+-+-+-+-+-+-+-

