uniform - universal form filer (part 1 of 2)

Istvan Mohos istvan at hhb.UUCP
Thu Mar 1 03:03:17 AEST 1990



However much you may despise scribbling redundant and purposeless
responses into little boxes on pre-printed official forms...

on the rare occasion when this is unavoidable you will grit your
teeth, grab a ball point pen, and put the gestalt behind you.
Still, should you have to face the same form time and time again
(colored perhaps in a nice, mottled pink --- it can happen!)
call UNIFORM to your "emotional rescue".

Complete the form one last time with your computer and printer, and
let UNIFORM remember every move you made: what went into which box,
where the boxes are, linefeeds, and the spacing between fields.
UNIFORM will *learn* your form and will then be able to reprint it
on demand.  Naturally, you can specify arbitrary boxes to contain
string variables, and supply current strings at reprint time.  But
don't throw away your ball point just yet!  You must still sign the
form by hand.

Although UNIFORM is a fullblooded, "curses"-guzzling, Unix native,
it can jolt a Unix mindset, being darn right contrary to ideas of
       device-independent output,
       device indistinguishable from file,
       the printer as a shared resource.

UNIFORM forces the printer back the evolutionary ladder, demoting
it to typewriter status (having clearly and separately controllable
paper and carriage movements).  The printer MUST be in the user's
immediate vicinity for positioning the blank form and for sustained
visual feedback.  The printer MUST be able to print characters on a
line one at a time, and MUST be able to return the carriage to the
left without a corresponding line feed.

The installer of the program is requested to define a handful of
printer escape codes in "myprinter.h" specific to the intended slave
printer.  The present source defines such escape sequences for the
   C ITOH 8510A     dot matrix printer (ImageWriter compatible),
   ROYAL BETA 8000  typewriter (Diablo 630 compatible),
   DECWRITER II     serial printer.
Posted or E-mailed additions to this printcap are accepted with
gratitude, and will be included in an update of UNIFORM.

Installation procedures are given in Install.  System- and printer-
specific compile-time defines (notably REALUNIX for SysV) should be
enabled in Makefile prior to compiling the source.  Use
"troff -man uniform.man" to print the operating instructions.

Part 1 (this posting) is the complete source in a shell archive.
Part 2 is the man pages.

===========================CUT HERE===============================
# This is a shell archive.  Remove anything before this line, then
# unpack it by saving it in a file and typing "sh file".  (Files
# unpacked will be owned by you and have default permissions.)
#
# This archive contains:
# Install Makefile README globals.h myprinter.h adjust.c counters.c etc.c getvar.c highlight.c makeform.c printform.c uniform.c

echo x - Install
cat > "Install" << '//E*O*F Install//'
This file contains instructions for compiling the source of
the program "uniform" under SysV or BSD Unix, and instructions for
defining printer "escape sequences" to control a fully operational
printer existing on the system, from "uniform".

No instructions are given for installing or "setting up" a printer
for normal operation in a Unix system.  In particular, it is assumed
that a "character device" exists under /dev as a device driver for
the port that the printer is connected to, and that this /dev file is
active and writable by the "uniform" process.

/******************************************************************
 * In order to compile the source for your printer and on your system,
 * edit "myprinter.h" and "Makefile".
 * 
 * In "myprinter.h" add a #ifdef section of the form:
 ******************************************************************/
#ifdef FOOBAR
    /* more stuff will be added here, momentarily */
#endif

/******************************************************************
 * where FOOBAR stands for the name of your printer, NOT YET DEFINED
 * in "myprinter.h".
 * Within the "#ifdef FOOBAR" block, define the following strings
 * and character arrays (example initial values are given):
 ******************************************************************/
    char *Prtype = "Reconditioned 1932 FOO operating at near 300 baud";
                   /* strlen must be less than 70 chars */

    /* three lines of instructions on setting up the printer manually;
       len must be less than 77 chars per string;
       leave string NULL if there is nothing to say
    */
    char *Setmesg0 = "Turn printer on with on-off switch hidden inside";
    char *Setmesg1 = "Slap sharply from left if head starts to vibrate";
    char *Setmesg2;

    /* Provide escape code sequence that will initialize the printer
       to operate most closely to UNIFORM's assumptions:
       1) set printer to incremental mode (printing "by byte").
          If the printer does this anyway, skip this.
       2) set width of a single line feed to 1/48 inch
          (eight feeds/singlespaced line).  If the printer can't do
          this, set the smallest linefeed the printer is capable of.
          If the width of the linefeed cannot be set, skip this..
       3) Set the printer to print 12 characters per inch.  (For
          some printers, this will be the same as using the "elite"
          character set).  If the printer prints 12 characters anyway,
          or if 12 characters per inch cannot be set, skip this.
       4) Add trailing carriage return.
       5) Terminate the sequence with a null byte.
       For example:
    */
    char prinit[] = {       27, 84, 48, 51, 27, 69, 13, 0};
/*                    |     |               |       |   |
prints by byte anyway /     |               |       |   |
ESC T03 for 1/48" line feed /               |       |   |
ESC E to select elite character set (12cpi) /       |   |
carriage return (without line feed) at end of init  /   |
null byte Unix string terminator - printer won't see it /
*/

    /* Provide escape code sequence that will reset printer to initial
       conditions:
       1) reset printer to buffered mode.  If not applicable, skip this.
       2) reset printer to line feed width of 1/6" (standard
          single spaced print), or whatever line feed the the printer
          powers up with.
          If the width of the linefeed cannot be set, skip this..
       3) Reset the printer to print 10 characters per inch.  (To
          some printers this means "pica" font.)  Alternately, reset
          the printer to the character spacing evident at powerup.
          If character spacing cannot be set, skip this.
       4) Add trailing CRLF (carriage return and line feed).
       5) Terminate the sequence with a null byte.
       For example:
    */
    char prreset[] = {        27, 84, 50, 52, 27, 78, 13, 10, 0};
/*                       |    |               |       |       |
always prints unbuffered /    |               |       |       |
ESC T24 for 1/6" line feed    /               |       |       |
ESC N to select pica  character set (10cpi)   /       |       |
carriage return followed by line feed at end of reset /       |
null byte Unix string terminator - printer won't see it       /
*/

    /* Provide eight normal 1/48" line feeds in succession, equivalent
       to a 1/6" paper feed (1 single spaced line).  Alternate
       escape sequences may exist for this.  One way is to just give
       eight CRLF commands, each feeding 1/48", adding up to 1/6".
       Interim carriage returns may not be necessary for your printer,
       but the head must return to the left by the end of the sequence.
       For example:
    */
    char tabfeed[] = {13,10,13,10,13,10,13,10,13,10,13,10,13,10,13,10,0};
/*                    CR LF CR LF CR LF CR LF CR LF CR LF CR LF CR LF |
              null byte Unix string terminator - printer won't see it /
*/

    /* Provide the three simple but essential control codes for
       carriage return and line feed.  Note the null byte necessary
       at the end of each array.
    */
    char cr[] = {13, 0};       /* carriage return without line feed */
    char lf[] = {10, 0};       /* line feed without carriage return */
    char crlf[] = {13, 10, 0}; /* carriage return plus linefeed */

    /* Provide optional font switching and other definitions.  That is,
       the arrays must be declared here, but supplying escape sequences
       is optional.  If an escape sequence is not given, the array
       should be defined as a single null byte.  Example:
    */
    char bs[] = {0};         /* backspace; GENERATED IN SOFTWARE */
    char pi[] = {27, 78, 0}; /* pica pitch/font 10 cpi */
    char el[] = {27, 69, 0}; /* elite pitch/font 12 cpi */
    char co[] = {0};         /* compressed pitch; NOT AVAILABLE */
    char bo[] = {0};         /* overstrike (bold); NOT AVAILABLE */
    char kb[] = {0};         /* kill overstrike; NOT AVAILABLE */

    /* In the above set if a capability is 0, the user's control
       keys will expand to zero-length  escape codes, and will not be
       written to the printer, except for bs.  If bs is 0,
       backspace capability will be manufactured in software,
       by returning the carriage to the left (margin),
       and then advancing the carriage to the right, to one less
       column position than the head occupied before the bs command.
    */

/******************************************************************
 * Edit "Makefile" next:
 * 
 * define REALUNIX under CFLAGS if running on SysV
 * define printer type you just wrote a printcap for (FOOBAR)
 * define baud rate if printer is a serial printer
 * do not define baud rate if printer is a parallel printer
 * define name of the /dev character device (tty) of the printer port
 *     unless the name is /dev/lp
 * set "LIBS=-lcurses" for SysV systems, or
 * set "LIBS=-lcurses -ltermcap" for BSD systems
 ******************************************************************/

# SysV example if PRINTERPORT is "/dev/lp"
CFLAGS=-O -DREALUNIX -DFOOBAR -D'BAUD=300'
LIBS=-lcurses

# BSD example
CFLAGS=-O -DFOOBAR -D'BAUD=300' -D'PRINTERPORT="/dev/ttya"'
LIBS=-lcurses -ltermcap

/*** MAKE ***/
//E*O*F Install//

echo x - Makefile
cat > "Makefile" << '//E*O*F Makefile//'
#
CC=/bin/cc

# PC6300+ SysV, Royal 8000 typewriter (parallel, Diablo 630 compatible)
#CFLAGS=-O -DREALUNIX -DPLUS6300 -DROYAL
#LIBS=-lcurses

# generic SysV, CItoh 8310A (parallel, ImageWriter compatible)
#CFLAGS=-O -DREALUNIX -DCITOH
#LIBS=-lcurses

# generic BSD, 300 baud Decwriter II (serial)
CFLAGS=-O -DDECWRITER -D'BAUD=300' -D'PRINTERPORT="/dev/ttya"'
LIBS=-lcurses -ltermcap

#.SILENT:

FILES= adjust.o makeform.o printform.o counters.o \
	getvar.o highlight.o etc.o

uniform: uniform.o ${FILES}
	$(CC) -o $@ uniform.o ${FILES} ${LIBS}

uniform.o: globals.h myprinter.h
${FILES}:  globals.h
//E*O*F Makefile//

echo x - README
cat > "README" << '//E*O*F README//'
uniform - universal form filer
robot control sequence prototyping

However much you may despise scribbling redundant and purposeless
responses into little boxes on pre-printed official forms...

on the rare occasion when this is unavoidable you will grit your
teeth, grab a ball point pen, and put the gestalt behind you.
Still, should you have to face the same form time and time again
(colored perhaps in a nice, mottled pink --- it can happen!)
call UNIFORM to your "emotional rescue".

Complete the form one last time with your computer and printer, and
let UNIFORM remember every move you made: what went into which box,
where the boxes are, linefeeds, and the spacing between fields.
UNIFORM will *learn* your form and will then be able to reprint it
on demand.  Naturally, you can specify arbitrary boxes to contain
string variables, and supply current strings at reprint time.  But
don't throw away your ball point just yet!  You must still sign the
form by hand.

Although UNIFORM is a fullblooded, "curses"-guzzling, Unix native,
it can jolt a Unix mindset, being darn right contrary to ideas of
       device-independent output,
       device indistinguishable from file,
       the printer as a shared resource.

UNIFORM forces the printer back the evolutionary ladder, demoting
it to typewriter status (having clearly and separately controllable
paper and carriage movements).  The printer MUST be in the user's
immediate vicinity for positioning the blank form and for sustained
visual feedback.  The printer MUST be able to print characters on a
line one at a time, and MUST be able to return the carriage to the
left without a corresponding line feed.

The installer of the program is requested to define a handful of
printer escape codes in "myprinter.h" specific to the intended slave
printer.  The present source defines such escape sequences for the
   C ITOH 8510A     dot matrix printer (ImageWriter compatible),
   ROYAL BETA 8000  typewriter (Diablo 630 compatible),
   DECWRITER II     serial printer.
Posted or E-mailed additions to this printcap are accepted with
gratitude, and will be included in an update of UNIFORM.

Installation procedures are given in Install.  System- and printer-
specific compile-time defines (notably REALUNIX for SysV) should be
enabled in Makefile prior to compiling the source.  Use
"troff -man uniform.man" to print the operating instructions.
//E*O*F README//

echo x - globals.h
cat > "globals.h" << '//E*O*F globals.h//'
/* globals.h */

#include <curses.h>
#include <signal.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>

#ifndef X_OK
#    ifdef REALUNIX
#        define F_OK 0
#        define X_OK 1
#        define W_OK 2
#        define R_OK 4
#        include <fcntl.h>
#    else
#        include <sys/file.h>
#    endif
#endif

#define BAILOUT   sprintf (Mesg, "bad write at %d of %s",\
					 __LINE__, __FILE__), goaway()

#define BADCHARP(p)  ((p) == (char *)NULL || *(p) == '\0')
#define NULCHARP(p)  ((p) == (char *)NULL)

#define ABORT     1         /* ASCII value of ^A character */
#define COMMENT   1         /* ASCII value of ^A character */
#define LITTLINE  12        /* ASCII value of ^L character */
#define FEED      6         /* ASCII ^F as alternate RETURN in getvar */
#define DELETE    127       /* ASCII value of DEL character */
#define SPACE     32        /* ASCII value of the space character */
#define TOKBUFSIZ 256       /* length limit of input token string */
#define COUNTERS  0         /* y screen position of counter displays */
#define TOPLINE   5         /* y of first line of echoed user text */
#define BOTLINE   (LINES-5) /* y of last line of echoed user text */

int  goaway();
int  fstat();
int  stat();
char *malloc();
char *gets();

#ifdef MAIN

char Record[BUFSIZ*2]; /* buffer for new data, prior to saving to file */
char Mesg[256];      /* scratch buffer for interface to user */
char File[256];      /* recording the session */
char Onefeed[128];   /* CRLF escape sequence plus margin */
char Eightfeed[128]; /* eightfeed escape sequence plus margin */
char *Recp;          /* to base of malloc buffer for data from file */
char *Ep;            /* to end of &Recp (cutting off sentinel newline) */
int  Partial;        /* 1 == continue work on incomplete file */
int  Margin;         /* blanks to align print head with left edge of box */
int  Descr;          /* file descriptor to open /dev/$PRINTER */
int  Curx, Cury;     /* screen cursor position */
int  Lcnt;           /* microfeed increments; singlespaced line=6mf */
int  Ccnt;           /* print character position */
int  Back;           /* how many characters can be back spaced */
int  Onefeedsiz;     /* length of onefeed string */
int  Eightfeedsiz;   /* length of eightfeed string */

#else

extern char *Prtype;
extern char *Setmesg0;
extern char *Setmesg1;
extern char *Setmesg2;
extern char prinit[];
extern char prreset[];
extern char cr[];
extern char lf[];
extern char crlf[];
extern char tabfeed[];
extern char bs[];
extern char pi[];
extern char el[];
extern char co[];
extern char bo[];
extern char kb[];

extern char Record[];
extern char Mesg[];
extern char File[];
extern char Onefeed[];
extern char Eightfeed[];
extern char *Recp;
extern char *Ep;
extern int  Partial;
extern int  Margin;
extern int  Descr;
extern int  Curx, Cury;
extern int  Lcnt;
extern int  Ccnt;
extern int  Back;
extern int  Onefeedsiz;
extern int  Eightfeedsiz;

#endif
//E*O*F globals.h//

echo x - myprinter.h
cat > "myprinter.h" << '//E*O*F myprinter.h//'
/* myprinter.h */

#ifndef PRINTERPORT
#define PRINTERPORT "/dev/lp"
#endif


/****************************************************************/
#ifdef CITOH
	char *Prtype = "C Itoh Model 8510A";
	char *Setmesg0 =
"Printer head seeks to left or right boundaries of an imaginary window;";
	char *Setmesg1 =
"do not use head as an indication for horizontal print position in line.";
	char *Setmesg2;

	/* PRINIT: set printer to incremental mode ("by byte" print),
	   set single line feed width to 1/48" (eight feeds/singlespaced line),
	   set elite font, add trailing carriage return, no line feed */
	char prinit[] = {27, 91, 27, 84, 48, 51, 27, 69, 13, 0};

	/* PRRESET: reset printer to initial conditions: buffered mode,
	   line feed width 1/6" (== singlespaced),
	   reset to pica font, add trailing crlf */
	char prreset[] = {27, 93, 27, 84, 50, 52, 27, 78, 13, 10, 0};

	/* TABFEED: eight normal line feeds in succession == 1 singlespaced line */
	char tabfeed[] = {13,10,13,10,13,10,13,10,13,10,13,10,13,10,13,10,0};

	char cr[] = {13, 0};        /* carriage return without line feed */
	char lf[] = {10, 0};        /* line feed without cr */
	char crlf[] = {13, 10, 0};  /* carriage_return+linefeed: normal feed */

	/* optional capabilities */
	char bs[] = {8, 0};         /* backspace */
	char pi[] = {27, 78, 0};    /* pica pitch/font */
	char el[] = {27, 69, 0};    /* elite pitch/font */
	char co[] = {27, 81, 0};    /* compressed pitch/font */
	char bo[] = {27, 33, 0};    /* bold print: overstrike */
	char kb[] = {27, 34, 0};    /* kill overstrike */
#endif


/****************************************************************/
#ifdef ROYAL
	char *Prtype = "Royal Beta 8000 Electric Typewriter";
	char *Setmesg0 =
"Advance to right margin, hit MAR REL; advance to right edge, hit MAR RIGHT.";
	char *Setmesg1 =
"After setting margin, get printer on-line by simultaneously pressing CODE o";
	char *Setmesg2;

	/* PRINIT:
	   set single line feed width to 1/48" (eight feeds/singlespaced line),
	   set elite pitch, add trailing carriage return, no line feed */
	char prinit[] = {27, 30, 2, 27, 31, 11, 13, 0};

	/* PRRESET: reset to singlespaced, pica pitch, add trailing crlf */
	char prreset[] = {27, 30, 9, 27, 31, 13, 13, 10, 0};

	/* TABFEED: eight normal line feeds in succession == 1 singlespaced line */
	char tabfeed[] = {13,10,13,10,13,10,13,10,13,10,13,10,13,10,13,10,0};

	char cr[] = {13, 0};         /* carriage return without line feed */
	char lf[] = {10, 0};         /* line feed without cr */
	char crlf[] = {13, 10, 0};   /* carriage_return+linefeed: normal feed */

	/* optional capabilities */
	char bs[] = {8, 0};          /* backspace */
	char pi[] = {27, 31, 13, 0}; /* pica pitch */
	char el[] = {27, 31, 11, 0}; /* elite pitch */
	char co[] = {27, 31, 9, 0};  /* compressed pitch */
	char bo[] = {27, 79, 0};     /* bold print: automatically cleared on CR */
	char kb[] = {27, 38, 0};     /* kill overstrike */
#endif


/****************************************************************/
#ifdef DECWRITER
/* a practically useless printer, serving as the lowest common denominator */
	char *Prtype = "Digital DECWRITER II at 300 baud";
	char *Setmesg0 =
"Minimum linefeed width for printer is 1/6\" --- use ^L instead of RETURN";
	char *Setmesg1;
	char *Setmesg2;

	char prinit[] = {0};
	char prreset[] = {13, 10, 0};

	/* TABFEED: eight normal line feeds in succession */
	char tabfeed[] = {13,10,13,10,13,10,13,10,13,10,13,10,13,10,13,10,0};

	char cr[] = {13, 0};        /* carriage return without line feed */
	char lf[] = {10, 0};        /* line feed without cr */
	char crlf[] = {13, 10, 0};  /* carriage_return+linefeed: normal feed */

	/* optional capabilities */
	char bs[] = {8, 0}; /* backspace */
	char pi[] = {0};    /* pica pitch/font */
	char el[] = {0};    /* elite pitch/font */
	char co[] = {0};    /* compressed pitch/font */
	char bo[] = {0};    /* bold print: overstrike */
	char kb[] = {0};    /* kill overstrike */
#endif
//E*O*F myprinter.h//

echo x - adjust.c
cat > "adjust.c" << '//E*O*F adjust.c//'
/* adjust.c */
#include "globals.h"

char *
adjust (new)
int new;
{
	char *getvar(), *readrem();
	char tokbuf[TOKBUFSIZ];
	char *rp;
	char *bp;
	int scrflag = new;
	int cnt;
	int first;
	int ry;
	int cy;
	int remy = 4;            /* comments, if applicable */
	char c;

mvaddstr(0, 0, "Using: "), addstr (Prtype);
	if (Setmesg0 != NULL)
		mvaddstr (1, 0, Setmesg0);
	if (Setmesg1 != NULL)
		mvaddstr (2, 0, Setmesg1);
	if (Setmesg2 != NULL)
		mvaddstr (3, 0, Setmesg2);

	if (new) {
		showhow();
		rp = Record;
	}
	else { /* file was read at Recp in main(); may begin with comments */
		rp = Recp;
		if (*rp != COMMENT)
			showhow();
		else {
			for (cnt = 4; cnt < 18; cnt++) {
				rp = readrem (rp, tokbuf, COLS);
				if (*tokbuf)
					mvaddstr (cnt, 0, tokbuf);
			}
		}
	}

ry = 18;
mvaddstr(ry++, 0, "Type ");
standout(), addstr ("spaces"), standend();
addstr (" from the computer, until the next print position coincides with");

mvaddstr(ry++, 0, "the spot where the bracket should go; then hit ");
standout(), addstr ("RETURN"), standend();
addstr (" to print the bracket.");

mvaddstr(ry++, 0,
"Repeat the procedure if the bracket is in the wrong place.  After alignment");

mvaddstr(ry++, 0, "hit ");
standout(), addstr ("ESC"), standend();
addstr (" to continue.  Hit ");
standout(), addstr ("^A"), standend();
addstr (" to abort: process may hang if printer is \"OFF\"");

	refresh();
	move (Cury = ry, Curx = 0);
	refresh();

	sprintf (tokbuf, "]%s", cr);
	for (first = cnt = 1; c = getchar();) {
		if (first && c != ABORT) {
			first = 0;
			if (write (Descr, prinit, strlen (prinit)) < 0)
				BAILOUT;
		}
		switch (c) {
			case SPACE:
				addch ('.');
				if (! (++Curx % COLS))
					++Cury;
				refresh();
				if (write (Descr, " ", 1) != 1)
					BAILOUT;
				++cnt;
				break;

			case 27:
				move (0, 0);
				clrtobot();
				refresh();

				strcpy (Onefeed, crlf);
				bp = Onefeed + strlen (Onefeed);
				for (cnt = Margin; --cnt >= 0; *bp++ = SPACE);
				*bp = 0;
				Onefeedsiz = strlen (Onefeed);

				strcpy (Eightfeed, tabfeed);
				bp = Eightfeed + strlen (Eightfeed);
				for (cnt = Margin; --cnt >= 0; *bp++ = SPACE);
				*bp = 0;
				Eightfeedsiz = strlen (Eightfeed);

				return (rp);

			case ABORT: /* abort, do not return to main */
				if (!first && write (Descr, prreset, strlen (prreset)) < 0)
					BAILOUT;
				goaway();

			case '\n':
			case '\r':
				addch (']');
				move (Cury=ry, Curx=0);
				refresh();
				if (write (Descr, tokbuf,  strlen (tokbuf)) < 0)
					BAILOUT;
				Margin = cnt;
				cnt = 1;
				break;

			/* Instead of turning platen knob for vertical adjust,
			   ^L advances paper by microfeed, leaves head in place.
			*/
			case LITTLINE:
				if (write (Descr, lf,  strlen (lf)) < 0)
					BAILOUT;
				break;

			case DELETE: /* just an inconvenient value above 31 */
				break;

			/* For any printing characters, start automatic comment
			   routine if new file is written, otherwise do nothing
			*/
			default:
				if (c > 32) {
					if (new && remy < 18) {
						getyx (stdscr, Cury, Curx);
						if (scrflag) {
	                        scrflag = 0;
							for (cy = remy+14; --cy >= remy;)
								move (cy, 0), clrtoeol();
	                    }
						move (Cury, Curx);
						refresh();
						sprintf (rp, "%c%s\n", COMMENT,
							getvar (remy++, 0, COLS-1, c));
						rp += strlen (rp);
					}
				}
				break;
		}
	}
}

showhow ()
{
	int ry = 4;

mvaddstr(ry++, 0,
"Insert the form into the printer,  positioning the top part of the paper on");
mvaddstr(ry++, 0,
"the printer platen (under the print head, ready for printing).  The goal of");
mvaddstr(ry++, 0,
"the following alignment procedure is to print a square bracket (shown below");
mvaddstr(ry++, 0,
"in inverse) just to the left of the top corner of the top box on the paper.");

mvaddstr(ry++,20, " _____________________________________");
mvaddstr(ry++,20, "| upper edge of paper");
mvaddstr(ry++,20, "|      _______________________________");
mvaddstr(ry,  20, "|    *| top left box            |");
standout(), mvaddstr(ry++,25,"]"), standend();
mvaddstr(ry++,20, "|     |_________________________|_____");
mvaddstr(ry++,20, "|     |                   |");
mvaddstr(ry++,20, "|     |___________________|___________");
mvaddstr(ry++,20, "|     |");

mvaddstr(ry++, 0,
"Turn the printer platen knob to get the print head in line with the topmost");

mvaddstr(ry++, 0, "box of the form, or by typing ");
standout(), addstr ("^L"), standend();
addstr (" (CONTROL-L) characters  from the computer.");
}

char *
readrem (ptr, target, maxc)
char *ptr, *target;
int maxc;
{
	char *rp = target;

	if (ptr == Ep || *ptr != COMMENT) {
		*rp = 0;
		return (ptr);
	}

	while (++ptr !=Ep && *ptr != '\n' && maxc--)
		*rp++ = *ptr;
	*rp = 0;

	if (!maxc) /* comment line too long */
		while (++ptr !=Ep && *ptr != '\n');

	if (ptr != Ep)
		++ptr; /* pass the newline */

	return (ptr);
}
//E*O*F adjust.c//

echo x - counters.c
cat > "counters.c" << '//E*O*F counters.c//'
/* counters.c */
#include "globals.h"

/* horizontal beginning column of counter displays */
#define  LINEX      14
#define  MICROX     27
#define  COLUMNX    36
#define  SCREENXX   45
#define  SCREENYX   54
#define  BACKX      63

/* Display running count of Lcnt, Ccnt, Curx, Cury, Back in top line,
   move cursor back to current screen coordinates Cury, Curx
*/
counters()
{
	char microbuf[8];
	char colbuf[8];
	char ybuf[8];
	char xbuf[8];
	char bbuf[8];
	char *fourspace = "    ";

	sprintf (microbuf, "%d", Lcnt/8);
	mvaddstr (COUNTERS, LINEX, fourspace);
	mvaddstr (COUNTERS, LINEX, microbuf);

	sprintf (microbuf, "%d", Lcnt);
	mvaddstr (COUNTERS, MICROX, fourspace);
	mvaddstr (COUNTERS, MICROX, microbuf);

	sprintf (colbuf, "%d", Ccnt);
	mvaddstr (COUNTERS, COLUMNX, fourspace);
	mvaddstr (COUNTERS, COLUMNX, colbuf);

	sprintf (xbuf, "%d", Curx);
	mvaddstr (COUNTERS, SCREENXX, fourspace);
	mvaddstr (COUNTERS, SCREENXX, xbuf);

	sprintf (ybuf, "%d", Cury);
	mvaddstr (COUNTERS, SCREENYX, fourspace);
	mvaddstr (COUNTERS, SCREENYX, ybuf);

	sprintf (bbuf, "%d", Back);
	mvaddstr (COUNTERS, BACKX, fourspace);
	mvaddstr (COUNTERS, BACKX, bbuf);

	move (Cury, Curx);
}
//E*O*F counters.c//

echo x - etc.c
cat > "etc.c" << '//E*O*F etc.c//'
/* etc.c */
#include "globals.h"

iread (fname, mallocp)
char *fname;
char **mallocp;
{
	struct stat sbuf;
	int checkval, fd;
	int count;

	if (BADCHARP (fname) || (fd = open (fname, 0)) == -1)
		return (-1);
	if ((checkval = fstat (fd, &sbuf)) == -1)
		return (-1);
	if ((count = (int)sbuf.st_size) == 0)
		return (-1);
	if (NULCHARP (*mallocp = malloc ((unsigned int) count+1)))
		return (-1);
	if ((checkval = read (fd, *mallocp, count)) != count)
		return (-1);
	close (fd);
	*(*mallocp + count) = 0;
	return (checkval);
}

input (ptr, message)
char *ptr, *message;
{
	char *pp;

	fprintf (stderr, message);
	gets (ptr);
	for (pp = ptr; *pp++;);
	return (--pp - ptr);
}

iwrite (fname, start, end, append)
char *fname;
char *start;
char *end;
int  append;
{
	struct stat sbuf;
	int checkval, descr;
	int perm = 0644;
	long offset;
	long lseek();

	if (BADCHARP (fname))
		return (-1);
	if ((checkval = stat(fname, &sbuf)) != -1)
		perm = (int)sbuf.st_mode;

	if (NULCHARP (start)) {
		if ((descr = open(fname, O_RDWR | O_CREAT, perm)) == -1)
			return(-1); /* no access */
		if (checkval != -1) {
			close(descr);
			return(1); /* it was there, it's OK, didn't touch it */
		}
		unlink(fname);
		return(0); /* wasn't there, not there now, looks OK */
	}

	if (append) {
		if ((descr = open (fname, O_WRONLY, perm)) == -1)
			return (-1);

		/* File has a sentinel newline at end so it can be edited regardless
		   of where the learning process ended it; must loose this newline
		   to continue with new data.
		*/
		offset = (long) sbuf.st_size;
		if (lseek (descr, offset-1, 0) == -1)
			return (-1);
	}
	else if ((descr = open (fname, O_WRONLY | O_CREAT | O_TRUNC, perm)) == -1)
		return (-1);

	if ((checkval = write(descr, start, end-start)) != end-start)
		return (-1);
	close (descr);
	return (checkval);
}

goaway()    /* restore terminal in case of interrupt */
{
	mvcur (0, COLS-1, LINES-1, 0);
	endwin();
	printf ("%s\n", Mesg);
	exit (0);
}
//E*O*F etc.c//

echo x - getvar.c
cat > "getvar.c" << '//E*O*F getvar.c//'
/* getvar.c */
#include "globals.h"

char *
getvar (vary, varx, varlen, comment)
int vary, varx, varlen, comment;
{
	static char varbuf[TOKBUFSIZ];
	char varcnt[8];
	char c;
	char *p;
	int  ri;
	int  ly, lx;

	getyx (stdscr, Cury, Curx);
	move (vary,   0), clrtoeol();
	if (!comment) {
		move (vary+1, 0), clrtoeol();
		move (vary+2, 0), clrtoeol();
	}
	move (ly = vary, lx = 0);

	p = varbuf;
	if (comment) {
		addch (comment);
		++lx, --varlen;
		*p++ = comment;
	}
	refresh();

	for (ri = varlen; c = getchar(); ri--) {
		if (c == DELETE)
			c = '\b';

		if (!comment && c == LITTLINE) {
			++ri; /* no strlen penalty */
			if (write (Descr, Onefeed, Onefeedsiz) != Onefeedsiz)
					BAILOUT;
		}
		else if (!comment && c == FEED) {
			++ri;
			if (write (Descr, Eightfeed, Eightfeedsiz) != Eightfeedsiz)
						BAILOUT;
		}
		/* quit printing, do not go back to main */
		else if (!comment && c == ABORT) {
			if (write (Descr, prreset, strlen (prreset)) < 0)
				BAILOUT;
			goaway();
		}
		else if (c == '\n' || c == '\r' || (!ri && c != '\b')) {
			if (!comment)
				while (ri--)
					*p++ = SPACE;
			*p = 0;
			move (Cury, Curx);
			refresh();
			return (varbuf);
		}
		else if (c > 31) {
			*p++ = c;
			addch (c);
			if (! (++lx % COLS))
				lx = 0, ++ly;
			if (!comment) {
				sprintf (varcnt, "%d", ri-1);
				mvaddstr (vary-3, varx, "   ");
				mvaddstr (vary-3, varx, varcnt);
			}
			move (ly, lx);
			refresh();
		}
		else if (c == '\b' && p > varbuf) {
			--p, ri += 2; /* 1 byte for original character, 1 byte for \b */
			if (lx)
				--lx;
			else
				lx = COLS-1, --ly;
			if (!comment) {
				sprintf (varcnt, "%d", ri-1);
				mvaddstr (vary-3, varx, "   ");
				mvaddstr (vary-3, varx, varcnt);
			}
			move (ly, lx);
			clrtoeol();
			refresh();
		}
		else
			++ri;
	}
}
//E*O*F getvar.c//

echo x - highlight.c
cat > "highlight.c" << '//E*O*F highlight.c//'
/* highlight.c */
#include "globals.h"

/* horizontal beginning column and Y locations of display of active keys */
#define  LFX        0
#define  LFY        (BOTLINE+2)
#define  RETX       12
#define  RETY       (BOTLINE+2)
#define  UNX        29
#define  UNY        (BOTLINE+2)
#define  TABX       41
#define  TABY       (BOTLINE+2)
#define  BSX        52
#define  BSY        (BOTLINE+2)
#define  SPX        65
#define  SPY        (BOTLINE+2)

#define  COX        0
#define  COY        (BOTLINE+3)
#define  PIX        12
#define  PIY        (BOTLINE+3)
#define  ELX        20
#define  ELY        (BOTLINE+3)
#define  KBX        29
#define  KBY        (BOTLINE+3)
#define  BOX        41
#define  BOY        (BOTLINE+3)
#define  REX        52
#define  REY        (BOTLINE+3)
#define  VARX       65
#define  VARY       (BOTLINE+3)

/* Any call first turns off the highlighting of the previous display,
   then highlights the display of an active control key.
   Cursor is moved back to the current screen coordinates Cury, Curx.
*/
highlight (spec)
int spec;
{
	static int prev;

	switch (prev) {
		default:
			break;
		case LITTLINE: /* ^L */
			mvaddstr (LFY, LFX, "^L");
			break;
		case '\n':
		case '\r':
			mvaddstr (RETY, RETX, "RETURN");
			break;
		case 21: /* ^U */
			mvaddstr (UNY, UNX, "^U");
			break;
		case '\t':
			mvaddstr (TABY, TABX, "TAB");
			break;
		case '\b':
			mvaddstr (BSY, BSX, "^H");
			break;
		case SPACE:
			mvaddstr (SPY, SPX, "SPACE");
			break;
		case 3: /* ^C */
			mvaddstr (COY, COX, "^C");
			break;
		case 16: /* ^P */
			mvaddstr (PIY, PIX, "^P");
			break;
		case 5: /* ^E */
			mvaddstr (ELY, ELX, "^E");
			break;
		case 11: /* ^K */
			mvaddstr (KBY, KBX, "^K");
			break;
		case 2: /* ^B */
			mvaddstr (BOY, BOX, "^B");
			break;
		case 18: /* ^R */
			mvaddstr (REY, REX, "^R");
			break;
		case 22: /* ^V */
			mvaddstr (VARY, VARX, "^V");
			break;
	}

	switch (spec) {
		default:
			break;
		case LITTLINE: /* ^L */
			standout();
			mvaddstr (LFY, LFX, "^L");
			standend();
			break;
		case '\n':
		case '\r':
			standout();
			mvaddstr (RETY, RETX, "RETURN");
			standend();
			break;
		case 21: /* ^U */
			standout();
			mvaddstr (UNY, UNX, "^U");
			standend();
			break;
		case '\t':
			standout();
			mvaddstr (TABY, TABX, "TAB");
			standend();
			break;
		case '\b':
			standout();
			mvaddstr (BSY, BSX, "^H");
			standend();
			break;
		case SPACE:
			standout();
			mvaddstr (SPY, SPX, "SPACE");
			standend();
			break;
		case 3: /* ^C */
			standout();
			mvaddstr (COY, COX, "^C");
			standend();
			break;
		case 16: /* ^P */
			standout();
			mvaddstr (PIY, PIX, "^P");
			standend();
			break;
		case 5: /* ^E */
			standout();
			mvaddstr (ELY, ELX, "^E");
			standend();
			break;
		case 11: /* ^K */
			standout();
			mvaddstr (KBY, KBX, "^K");
			standend();
			break;
		case 2: /* ^B */
			standout();
			mvaddstr (BOY, BOX, "^B");
			standend();
			break;
		case 18: /* ^R */
			standout();
			mvaddstr (REY, REX, "^R");
			standend();
			break;
		case 22: /* ^V */
			standout();
			mvaddstr (VARY, VARX, "^V");
			standend();
			break;
	}
	prev = spec;
	move (Cury, Curx);
}
//E*O*F highlight.c//

echo x - makeform.c
cat > "makeform.c" << '//E*O*F makeform.c//'
/* makeform.c */
#include "globals.h"

makeform (inside, abrupt)
char *inside;
int abrupt;
{
	char tokbuf[TOKBUFSIZ]; /* for getting constant or variable */
	char bsbuf[TOKBUFSIZ];  /* simulated backspace if no bs capability */
	char cret[128];      /* carriage return without linefeed, plus margin */
	char *bp;            /* buffer pointer into tokbuf */
	char *rp;            /* buffer pointer into Record */
	char *undop;         /* to leftmost history byte affected by undo */
	char *leasttok;      /* leftmost tokbuf byte to which bs applies */
	char *limp;          /* limit at rightmost available tokbuf position */
	char *bsp;           /* mark the print start byte in bsbuf */
	char c;              /* for holding getchar() */
	int  ri;
	int  toksiz;         /* length of finished constant or variable */
	int  cretsiz;        /* length of cret string */
	int  bssiz;          /* length of backspace string */
	int  leastimm;       /* least immediate line col to which bs applies */
	int  emptyline;      /* flag that no printing character got into line */
	int  variable;       /* flag that variable definition is under way */

	/* set up carriage return without line feed, + bytes of left margin */
	strcpy (cret, cr);
	bp = cret + strlen (cret);
	for (ri = Margin; --ri >= 0; *bp++ = SPACE);
	*bp = 0;
	cretsiz = strlen (cret);

	/* initialize bsbuf with spaces */
	if ((bssiz = strlen (bs)) == 0) {
		for (bsp = bsbuf, ri = TOKBUFSIZ; --ri; *bsp++ = SPACE);
		*bsp = 0;
	}

	if (Margin) {
		bp = tokbuf;
		for (ri = Margin; --ri >= 0; *bp++ = SPACE);
		*bp = 0;
		if (!abrupt)
			if (write (Descr, tokbuf, strlen (tokbuf)) < 0)
				BAILOUT;
	}
	Lcnt = Ccnt = Back = leastimm = 0;
	clear();

	mvaddstr (COUNTERS, 0,
"quit:ESC line:    littline:    Pcol:    scrX:    scrY:    back:    abort: ^A");

	mvaddstr (BOTLINE+2, 0,
"^L:littline RETURN:normaline ^U:undoline TAB:8space ^H:backspace SPACE:space");

	mvaddstr (BOTLINE+3, 0, "^C:");
	if (strlen (co))
		addstr ("compress ^P:");
	else
		addstr ("         ^P:");
	if (strlen (pi))
		addstr ("pica ^E:");
	else
		addstr ("     ^E:");
	if (strlen (el))
		addstr ("elite ^K:");
	else
		addstr ("      ^K:");
	if (strlen (kb))
		addstr ("killbold ^B:");
	else
		addstr ("         ^B:");
	if (strlen (bo))
		addstr ("boldfnt ^R:redisplay ^V:variable");
	else
		addstr ("        ^R:redisplay ^V:variable");

	Cury=TOPLINE, Curx=0;
	counters();
	refresh();
	rp = undop = inside;
	limp = tokbuf + TOKBUFSIZ -10; /* allow tab expansion past limp */


/*************************
   MAIN INTERACTIVE LOOP 
 *************************/
	for (emptyline = 1, variable = 0; c = getchar();) {


		/******************************
		   COLLECT TOKEN/VARIABLE LOOP 
		 ******************************/
		if (c == DELETE)
			c = '\b';
		/* collect string if any printing character was typed */
		if (c > 32) {
			highlight (0);
varentry:
			emptyline = 0;
			bp = leasttok = tokbuf;
			*bp++ = c; /* printing char or ^V */
			if (!variable)
				addch (c), Ccnt++, Back++;

			/* advance leasttok to first byte of current value of variable */
			if (variable) {
				++leasttok; /* past the ^V */
				varname (&leasttok);
				bp = leasttok;
			}
			else if (! (++Curx % COLS))
				++Cury, Curx = 0; /* Cury will not exceed BOTLINE */
			counters();
			refresh();

			for (; c = getchar(); counters(), refresh()) {
				if (c == DELETE)
					c = '\b';
				if (Ccnt > 247 && c != '\b' && c != ABORT)
					c = 21; /* automatic ^Undo on line overflow */

				/* RETURN (newline) or tokbuf limit terminates string */
				if (c == '\n' || c == '\r' || bp >= limp) {
					if (variable)
						 *bp++ = 22; /* terminating ^V */
					*bp = 0; /* do not put newline in buffer */
					Back = 0;
					break;
				}

				/* convert each tab unilaterally to eight spaces */
				else if (c == '\t') {
					Ccnt += 8;
					Back += 8;
					highlight (c);
					for (ri = 8; --ri >= 0; addch (SPACE)) {
						*bp++ = SPACE;
						if (! (++Curx % COLS))
							++Cury, Curx = 0; /* won't exceed BOTLINE */
					}
				}

				/* ^U (undo) clears history to beginning of print line */
				else if (c == 21) {
					highlight (c);
					*tokbuf = 0;
					variable = 0;
					move (COUNTERS+2, 0), clrtoeol();
					move (COUNTERS+3, 0), clrtoeol();
					emptyline = 1;
					rp = undop;
					/* length of entire string also includes present toksiz */
						Cury -= Ccnt/COLS;   /* 0, 1, 2, or 3 */
					move (Cury, Curx=0); /* no clrtoeol */
					Ccnt = Back = leastimm = 0;
					counters();
					refresh();
					if (write (Descr, cret, cretsiz) != cretsiz)
						BAILOUT;
					break;
				}

				/* abort, do not write file, do not go back to main */
				else if (c == ABORT) {
					if (write (Descr, prreset, strlen (prreset)) < 0)
						BAILOUT;
					goaway();
				}

				/* clear bytes maximally to beginning of string */
				else if (c == '\b') {
					highlight (c);
					*bp = 0;
					if (bp > leasttok) {
						--bp, --Ccnt, --Back;
						if (Curx)
							--Curx;
						else {
							move (Cury, Curx);
							clrtoeol();
							/* will not underrun TOPLINE */
							Curx = COLS-1, --Cury;
						}
						move (Cury, Curx);
						clrtoeol();
					}
				}

				/* all printing characters */
				else if (c > 31) {
					++Ccnt, ++Back;
					highlight (c);
					*bp++ = c;
					addch (c);
					if (! (++Curx % COLS))
						++Cury, Curx = 0; /* won't overrun BOTLINE */
				}
			}

			/* write out finished non-null string */
			if (variable) {
				variable = 0;
				move (COUNTERS+2, 0), clrtoeol();
				move (COUNTERS+3, 0), clrtoeol();
				move (Cury, Curx);
				toksiz = strlen (leasttok) -1; /* no trailing ^V to printer */

				/* variable stays in stream even if value is empty */
				leastimm = 0;
				strcpy (rp, tokbuf);
				rp += strlen (tokbuf);
				counters();
				refresh();
			}
			else {
				toksiz = strlen (tokbuf);
				if (toksiz) {
					leastimm = 0;
					strcpy (rp, tokbuf);
					rp += strlen (tokbuf);
					counters();
					refresh();
				}
			}
			if (toksiz)
				if (write (Descr, leasttok, toksiz) != toksiz)
					BAILOUT;
		}

		/***************************
		   IMMEDIATE RESPONSE LOOP 
		 ***************************/
		else {
			if (Ccnt > 247 && c != '\b' && c != ABORT)
				c = 21; /* automatic ^Undo for line overflow */

			highlight (c);
			refresh();
			switch (c) {
				/* garbage; do nothing */
				default:
					break;

				case SPACE:
					++Ccnt, ++Back, ++leastimm;
					if (++Curx % 5)
						addch ('.');
					else
						addch ('|');
					if (! (Curx % COLS))
						++Cury, Curx = 0; /* won't overrun BOTLINE */
					*rp++ = SPACE;
					counters();
					refresh();
					if (write (Descr, " ", 1) != 1)
						BAILOUT;
					break;

				case '\t':
					Ccnt += 8;
					Back += 8;
					leastimm += 8;
					for (ri = 8; --ri >= 0; *rp++ = SPACE) {
						if (++Curx % 5)
							addch ('.');
						else
							addch ('|');
						if (! (Curx % COLS))
							++Cury, Curx = 0; /* won't overrun BOTLINE */
					}
					counters();
					refresh();
					if (write (Descr, "        ", 8) != 8)
						BAILOUT;
					break;

				/* ctrl-L small line feed */
				case LITTLINE:
					Lcnt++, Curx = 0; /* even if there were no tokens */

					/* proceed to the next line on the screen only if
					   present line contains tokens
					*/
					if (!emptyline) {
						emptyline = 1;
						if (++Cury > (BOTLINE-3))
							newscreen();
					}
					else
						rp = undop;
					*rp++ = '\n';
					undop = rp;
					Ccnt = Back = leastimm = 0;

					/* ....|.. or possible screen garbage from previous undo */
					move (Cury, Curx), clrtoeol();
					counters();
					refresh();
					if (write (Descr, Onefeed, Onefeedsiz) != Onefeedsiz)
						BAILOUT;
					break;

				case '\n':
				case '\r':
					Lcnt += 8, Curx = 0;

					/* proceed to the next line on the screen only if
					   present line contains tokens
					*/
					if (!emptyline) {
						emptyline = 1;
						if (++Cury > (BOTLINE-3))
							newscreen();
					}
					else
						rp = undop; /* don't print spaces, just linefeed */
					for (ri = 8; --ri >= 0; *rp++ = '\n');
					undop = rp;
					Ccnt = Back = leastimm = 0;

					/* ....|.. or possible screen garbage from previous undo */
					move (Cury, Curx), clrtoeol();
					counters();
					refresh();
					if (write (Descr, Eightfeed, Eightfeedsiz) != Eightfeedsiz)
						BAILOUT;
					break;

				/* ^Undo clears history to beginning of print line, returns head
				   to left margin, leaves already printed characters on paper
				*/
				case 21:
					emptyline = 1;
					rp = undop;
					Cury -= Ccnt/COLS;   /* 0, 1, 2, or 3 */
					move (Cury, Curx=0); /* learn from mistake; no clrtoeol */
					Ccnt = Back = leastimm = 0;
					counters();
					refresh();
					if (write (Descr, cret, cretsiz) != cretsiz)
						BAILOUT;
					break;

				/* ^H or BACKSPACE or DELETE clears bytes, maximally to
				   beginning of line or to end of previous variable or
				   constant, whichever is nearest.
				*/
				case '\b':
					highlight (c);
					if (leastimm) {
						--leastimm, --Ccnt, --Back;
						if (Curx)
							--Curx;
						else {
							move (Cury, Curx);
							clrtoeol();
							Curx = COLS-1, --Cury;
						}
						move (Cury, Curx);
						clrtoeol();
						while (*--rp < 32);
						counters();
						if (bssiz) {
							if (write (Descr, bs, bssiz) != bssiz)
								BAILOUT;
						}
						else {
							if (write (Descr, cret, cretsiz) != cretsiz)
								BAILOUT;
							bsp = bsbuf + TOKBUFSIZ -1 -Ccnt;
							ri = strlen (bsp);
							if (write (Descr, bsp, ri) != ri)
								BAILOUT;
						}
					}
					refresh();
					break;

				/*************************************************
				   change printer attributes, no update of screen
				 *************************************************/

				/* ctrl-P to select pica font */
				case 16:
					emptyline = 0;
					*rp++ = 16;
					if (write (Descr, pi, strlen (pi)) < 0)
						BAILOUT;
					break;

				/* ctrl-E to select elite font */
				case 5:
					emptyline = 0;
					*rp++ = 5;
					if (write (Descr, el, strlen (el)) < 0)
						BAILOUT;
					break;

				/* ctrl-C to select compressed font */
				case 3:
					emptyline = 0;
					*rp++ = 3;
					if (write (Descr, co, strlen (co)) < 0)
						BAILOUT;
					break;

				/* ctrl-B to select overstrike (bold) */
				case 2:
					emptyline = 0;
					*rp++ = 2;
					if (write (Descr, bo, strlen (bo)) < 0)
						BAILOUT;
					break;

				/* ctrl-K to kill overstrike (kill bold) */
				case 11:
					emptyline = 0;
					*rp++ = 11;
					if (write (Descr, kb, strlen (kb)) < 0)
						BAILOUT;
					break;

				/* ctrl-R to redisplay screen */
				case 18:
					clearok (curscr, 1);
					refresh();
					break;

				/* ctrl-V to begin variable definition */
				case 22:
					variable = 1;
					goto varentry;

				case ABORT: /* do not write file, do not go back to main */
					if (write (Descr, prreset, strlen (prreset)) < 0)
						BAILOUT;
					goaway();

				case 27: /* quit, return to main */
					*rp++ = '\n'; /* so that saved file can be edited */
					if (iwrite (File, Record, rp, Partial) < 0)
						sprintf (Mesg, "can't write Record to %s", File);
					return;
			}
		}
	}
}

varname (ptr)
char **ptr;
{
	char *p;
	int  ri;
	int  lx, ly;
	char namebuf[3];
	char c;

	p = *ptr;
	mvaddstr (COUNTERS+2, 0, "VARIABLE NAME (MAX. 45 CHARS): ");
	getyx (stdscr, ly, lx);
	refresh();
	for (ri = 45; c = getchar(); ri--) {
		if (c == DELETE)
			c = '\b';
		if (c == '\n' || c == '\r' || (!ri && c != '\b')) {
			*p++ = 22; /* the second ^V */
			*p = 0;
			*ptr += strlen (*ptr);
			mvaddstr (COUNTERS+3, 0,
"Give current value, padding at the end with SPACE/TAB to the maximum length:");
			move (Cury, Curx);
			refresh();
			return;
		}
		else if (c > 31) {
			*p++ = c;
			addch (c);
			++lx;
			sprintf (namebuf, "%d", ri-1);
			mvaddstr (COUNTERS+2, 20, "  ");
			mvaddstr (COUNTERS+2, 20, namebuf);
			move (ly, lx);
			refresh();
		}
		else if (c == '\b' && p > *ptr) {
			--p, ri += 2; /* 1 byte for original character, 1 byte for \b */
			move (ly, --lx);
			clrtoeol();
			sprintf (namebuf, "%d", ri-1);
			mvaddstr (COUNTERS+2, 20, "  ");
			mvaddstr (COUNTERS+2, 20, namebuf);
			move (ly, lx);
			refresh();
		}
		else
			++ri;
	}
}

newscreen()
{
	int ri;

	for (ri = TOPLINE; ri <= BOTLINE; ri++)
		move (ri, 0), clrtoeol();
	Cury = TOPLINE, Curx = 0;
}
//E*O*F makeform.c//

echo x - printform.c
cat > "printform.c" << '//E*O*F printform.c//'
/* printform.c */
#include "globals.h"

int
printform (inside)
char *inside;
{
	char *getvar();
	char tokbuf[TOKBUFSIZ];
	char margbuf[256];
	char varcnt[8];
	int  ri;
	int  crlfsiz;      /* string length of crlf */
	int  varlen;       /* max length of current string variable */
	char *bp;          /* buffer pointer into tokbuf */
	char *rp;          /* buffer pointer into &Recp */
	char *vrp1;        /* place holder pointer in &Recp */
	char *vrp2;        /* place holder pointer in &Recp */

	/* set up linefeed and margin strings */
	crlfsiz = strlen (crlf);
	for (bp = margbuf, ri = Margin; --ri >= 0; *bp++ = SPACE);
	*bp = 0;

	clear();
	for (bp = tokbuf, rp = inside; rp < Ep; rp++) {

		if (*rp > 31) { /* make a string of all normal characters in tokbuf */
			*bp++ = *rp;
			continue;
		}
		switch (*rp) {
			/* weed out garbage */
			default:
				break;

			/* Begin variable; accummulate current value in tokbuf.
			   Variable format in saved file:
...other...^Vvarname^Vpast value padded to max field width^V...other...
			   To process:
			   rp is moved past the first ^V,
			   [variable name] is printed in prompt for user input
			   rp is moved past the second ^V,
			   max width of field is computed as the third ^V - rp,
			   rp is moved to third ^V for post-increment in for-loop,
			   user input of current value is padded to field width,
			   processed variable is added to tokbuf, bp moved past it.
			*/
			case 22:
				vrp1 = ++rp;
				while (*rp++ != 22);
				*(rp-1) = 0;         /* the second ^V */
				vrp2 = rp;           /* beginning of past value */
				while (*rp++ != 22);
				--rp;                /* back to the last ^V */
				varlen = rp - vrp2;
				move (TOPLINE-3, 0), clrtoeol();
				mvaddstr (TOPLINE-3, 0, "CURRENT VALUE (MAX.     CHARS) ");
				addstr (vrp1);
				sprintf (varcnt, "%d", varlen);
				mvaddstr (TOPLINE-3, 20, "   ");
				mvaddstr (TOPLINE-3, 20, varcnt);
				strcpy (bp, getvar (TOPLINE, 20, varlen, 0));
				bp += varlen;
				break;

			/* at line feed, print out accummulated token */
			case '\n':
			case '\r':
				if (bp == tokbuf) { /* multiple line feeds */
					if (write (Descr, crlf, crlfsiz) != crlfsiz)
						BAILOUT;
				}
				else {
					/* print margin if non-null */
					if (Margin && (write (Descr, margbuf, Margin) != Margin))
						BAILOUT;
					strcpy (bp, crlf);
					bp += crlfsiz;
					if (write (Descr, tokbuf, bp - tokbuf) < 0)
						BAILOUT;
					bp = tokbuf;
				}
				break;

			/* ctrl-A begins comment; skip rest of line */
			case COMMENT:
				while (++rp !=Ep && *rp != '\n');
				break;

			/* ctrl-P to select pica font */
			case 16:
				strcpy (bp, pi);
				bp += strlen (pi);;
				break;

			/* ctrl-E to select elite font */
			case 5:
				strcpy (bp, el);
				bp += strlen (el);;
				break;

			/* ctrl-C to select compressed font */
			case 3:
				strcpy (bp, co);
				bp += strlen (co);;
				break;

			/* ctrl-B to select overstrike (bold) */
			case 2:
				strcpy (bp, bo);
				bp += strlen (bo);;
				break;

			/* ctrl-K to kill overstrike (bold) */
			case 11:
				strcpy (bp, kb);
				bp += strlen (kb);;
				break;
		}
	}

	/* print accumulated token if last printer-bound byte was not a newline */
	if (bp != tokbuf) {
		if (Margin && (write (Descr, margbuf, Margin) != Margin))
			BAILOUT;
		if (write (Descr, tokbuf, bp - tokbuf) < 0)
			BAILOUT;
	}
	return (*(Ep-1) != '\n');
}
//E*O*F printform.c//

echo x - uniform.c
cat > "uniform.c" << '//E*O*F uniform.c//'
/* uniform.c --- universal form filer */
/**********************************************************************
* Overlay printed blank forms with computerized information
* uniform         --- fill out sample form, record ("learn") commands
* uniform file    --- fill out blank form from data stored in file
* uniform \&file  --- fill from incomplete file, "learn" rest of form
* Author: Istvan Mohos
* Version 1, March 1990
**********************************************************************/

#include "myprinter.h"
#define MAIN
#include "globals.h"

main (argc, argv)
int argc;
char *argv[];
{
	int new = argc == 1; /* create new form if no filename */
	int no_crlf_end;     /* TRUE if session ended without crlf (in line) */
	int cnt;
	char *file;
	char *remark;        /* point in buffer where parsing should resume */
	char *adjust();

	if ((Descr = open (PRINTERPORT, O_WRONLY)) == -1)
		fprintf (stderr, "can't write to printer\n"), exit (1);
#ifdef BAUD
	sprintf (Mesg, "stty %d > %s", BAUD, PRINTERPORT);
	system (Mesg);
#endif

	if (new) {
		input (File, "Record session under: ");
		if (iwrite (File, (char *)NULL, (char *)NULL, 0) == -1)
			fprintf (stderr, "can't write to %s\n", File), exit (1);
	}
	else {
		file = argv[1];
		if (*file == '&') {
			++file;
			Partial = 1;
			if (access (file, W_OK) == -1)
				fprintf (stderr, "can't append to %s\n", file), exit (1);
		}
		sprintf (File, file);
		if (access (File, R_OK) == -1)
			fprintf (stderr, "can't read %s\n", File), exit (1);
	}

	strcpy (Mesg, "User interrupt... exiting");
	initscr(), raw(), noecho();
	if (COLS < 76 || LINES < 23)
		strcpy (Mesg, "Insufficient screen size... sorry"), goaway();

	if (!new) {
		if ((cnt = iread (File, &Recp)) < 0)
			sprintf (Mesg, "can't read %s", File), goaway();
		Ep = Recp + cnt -1; /* loose sentinel newline at end */
	}

	/* If brand new project, saved data may begin with comments specified
	   by user during adjust().  In this case, "remark" will be moved to
	   just past the comments accummulated in "Record".
	   Else the file is read at "Recp", leading comments are displayed
	   during adjust(), and "remark" will be moved past the displayed
	   comments in "Recp", for printform() to continue from.
	*/
	remark = adjust (new);
	if (new)
		makeform (remark, 0);
	else {
		no_crlf_end = printform (remark);
		if (Partial)
			makeform (Record, no_crlf_end);
	}

	/* Reset printer; abnormal exits made own arrangements */
	if (write (Descr, prreset, strlen (prreset)) < 0)
		BAILOUT;
	Mesg[0] = 0;
	goaway();
}
//E*O*F uniform.c//

echo Possible errors detected by \'wc\' [hopefully none]:
temp=/tmp/shar$$
trap "rm -f $temp; exit" 0 1 2 3 15
cat > $temp <<\!!!
     151    1085    7276 Install
      25      67     601 Makefile
      48     374    2403 README
      99     453    2972 globals.h
     104     625    3986 myprinter.h
     209     735    4910 adjust.c
      49     147    1180 counters.c
      93     311    1958 etc.c
      91     294    1793 getvar.c
     159     422    3154 highlight.c
     508    1859   12358 makeform.c
     131     535    3400 printform.c
      83     384    2541 uniform.c
    1750    7291   48532 total
!!!
wc  Install Makefile README globals.h myprinter.h adjust.c counters.c etc.c getvar.c highlight.c makeform.c printform.c uniform.c | sed 's=[^ ]*/==' | diff -b $temp -
exit 0
-- 
        Istvan Mohos
        ...uunet!pyrdc!pyrnj!hhb!istvan
        RACAL-REDAC/HHB 1000 Wyckoff Ave. Mahwah NJ 07430 201-848-8000
======================================================================



More information about the Alt.sources mailing list