/* Line printer formatter Written by Leor Zolman May 28, 1980 ------------------------------------------------------------------- Modifications by John Hastwell-Batten 16th January 1983 1) Includes line-printer configuration commands. These are specific to Epson MX100 (& MX80) but could serve as an example for other printers. 2) Reads date from QT systems calendar/clock board. 3) WILDEXP and DIO added. PRINTER CONFIGURATION COMMANDS: A command-line or interactive entry prefixed with a hyphen (-) is treated as a set of printer configuration commands. Each command is a single letter which may be followed by a number (must be non- zero to be effective). The commands implemented are: Bn Set automatic skip-over-perforations (n lines), B Cancel perforation skip, Cn Select character set n F Skip to new page on first file Hn Enable page heading H Suppress page heading In Indent each data line n columns Ln Set form length to n inches Nn Turn on line numbering N Suppress line numbers Examples: -b6fn1 specifies perforation skip of 6 lines, starts listing with a page throw and turns on line numbering. -i15h1 indents each line in the body of the listing by 15 columns and prints a heading on each page. Defaults: A call on the printer configuration procedure is done by this program before any parameters are scanned. The configuration is set to NH1I15C0, i.e. line-numbering off, page headings on, 15-column indenting and character set 0 (USA) is selected. The defaults are easily modified by altering the parameter to the configuration procedure. --------------------------------------------------------------------- First prints all files named on the command line, and then asks for names of more files to print until a null line is typed. Control-Q aborts current printing and goes to next file. Paper should be positioned ready to print on the first page. Tabs are expanded into spaces. (NO! Tab stops are set on the MX100 and tabs in the text are NOT expanded. John H-B.) */ #include "bdscio.h" #include "dio.h" #define FF 0x0C /* formfeed character, or zero if not supported */ #define PGLEN 66 /* lines per lineprinter page */ char colno, linesleft; char indenting, headings, numbering; unsigned linenumber, charcount; #include main(argc,argv) char **argv; { int i, pgno, fd; char date[30], linebuf[135]; /* date and line buffers */ char fnbuf[30], *fname; /* filename buffer & ptr */ char numbuf[8]; /* place to build line number */ char ibuf[BUFSIZ]; /* buffered input buffer */ char *gets(); wildexp(&argc,&argv); dioinit(&argc,argv); pgno = colno = 0; linesleft = PGLEN; clock(date); printf("Today's date is %s\n",date); setmem(numbuf,8,0); lpoption("NHI12C0"); while (1) { if (argc-1) { fname = *++argv; argc--; } else { printf("\nEnter file to print, or CR if done: "); if (!*(fname = gets(fnbuf))) break; } if (*fname == '-') { lpoption(++fname); continue; } else if ((fd = fopen(fname,ibuf)) == ERROR) { printf("\n<<< Can't open %s >>>\n",fname); continue; } else { l_to_u(fname); linenumber = charcount = 0; printf("\n+++ Printing %s +++\n",fname); } for (pgno = 1; ; pgno++) { putchar((pgno % 10) ? '-' : '+'); if (headings) { sprintf(linebuf, "\016%-20s%5s%-3d%36s\023\n\n", fname,"Page ",pgno,date); linepr(linebuf); } loop: if (!fgets(linebuf,ibuf)) { Printf("\n+++ End of %s +++\n",fname); printf("\t%d lines, %d characters\n",linenumber,charcount); break; } if (kbhit() && getchar() == 0x11) { printf("\n+++ Skipping to next file +++\n"); break; } if (indenting) putlpr('\t'); linenumber++; if (numbering) { sprintf(numbuf,"%5d:\t",linenumber); if (linepr(numbuf)) continue; } if (linepr(linebuf)) continue; if (linesleft > 6) goto loop; formfeed(); } formfeed(); /* if (pgno % 2) formfeed(); */ fabort(fd); } dioflush(); } /* Print a line of text out on the list device, and return true if a formfeed was encountered in the text. */ linepr(string) char *string; { char c, ffflag; ffflag = 0; while (c = *string++) { charcount++; switch (c) { case FF: ffflag = 1; break; case '\n': putlpr('\r'); putlpr('\n'); colno = 0; linesleft--; break; /* case '\t': do { putlpr(' '); colno++; } while (colno % 8); break; */ default: putlpr(c); colno++; } } if (ffflag) formfeed(); return ffflag; } putlpr(c) char c; { bios(5,c); } formfeed() { if (FF) putlpr(FF); else while (linesleft--) putlpr('\n'); linesleft = PGLEN; } /* LPOPTION: This routine interprets a string as a series of commands to set up an Epson MX100 for subsequent printing. The commands implemented are: Bn Set automatic skip-over-perforations, Cn Select character set n F Skip to new page on first file Hn Enable page heading H Suppress page heading I Indent each data line n columns Ln Set form length to n inches Nn Turn on line numbering N Suppress line numbers */ lpoption(opts) char *opts; { char c, v, stops; while (c=*opts++) { switch (toupper(c)) { case 'B': v = atoi(*opts); while (isdigit(*opts++)); --opts; putlpr('\033'); putlpr('N'); putlpr(v); printf("- End-of-page skip set to %d lines\n",v); break; case 'C': putlpr('\033'); putlpr('R'); if (isdigit(*opts)) putlpr(v=*opts++ & 7); printf("- Character set %d selected\n",v); break; case 'F': v = formfeed(); printf("- Advancing to new page\n"); break; case 'H': if (headings = atoi(opts)) printf("- Page headings enabled\n"); else printf("- Page headings suppressed\n"); while (isdigit(*opts++)); --opts; break; case 'I': indenting = atoi(opts); while (isdigit(*opts++)); --opts; putlpr('\033'); putlpr('D'); stops = 12; printf("- Indenting set to %d columns\n",indenting); for (v=(indenting ? (indenting+1) : 9); stops--; v=v+8) putlpr(v); putlpr(0); break; case 'L': if (!(v=atoi(opts))) v = 11; while (isdigit(*opts++)); --opts; putlpr('\033'); putlpr('C'); putlpr('\0'); putlpr(v); printf("- Page length set to %d inches\n",v); break; case 'N': if (numbering = atoi(opts)) printf("- Line numbering enabled\n"); else Printf("- Line numbering suppressed\n"); while (isdigit(*opts++)); --opts; break; default: printf("- Invalid format specifier: %c\n",*opts); } } } l_to_u(string) char *string; { while (toupper(*string++)) ; } clock(date) char *date; { struct _time tick ; struct _date tock ; char *days[7], *months[12] ; char *suffix[3]; int dd; suffix[0] = "th"; suffix[1] = "st"; suffix[2] = "nd"; suffix[3] = "rd"; months[0] = "January"; months[1] = "February"; months[2] = "March"; months[3] = "April"; months[4] = "May"; months[5] = "June"; months[6] = "July"; months[7] = "August"; months[8] = "September"; months[9] = "October"; months[10] = "November"; months[11] = "December"; days[0] = "Sun"; days[1] = "Mon"; days[2] = "Tues"; days[3] = "Wednes"; days[4] = "Thurs"; days[5] = "Fri"; days[6] = "Satur"; getdate(&tock) ; if ((tock.day / 10 == 1) | (tock.day % 10 > 4)) dd = 0; else dd = tock.day % 10; sprintf(date,"%sday %2d%s %s 19%02d\0", days[tock . weekday], tock.day, suffix[dd], months[tock.month], tock.year) ; } getdate(now) struct _date *now; { char i, time[7] ; outp(CLDATA, CLHOLD) ; for (i = 0; i < 7; i++) time[i] = getclock(i + 6) ; outp(CLDATA, CLREL) ; now -> day = time[1] + 10 * (time[2] & CLOMASK) ; now -> month = time[3] + 10 * time[4] - 1 ; now -> year = time[5] + 10 * time[6] ; now -> weekday = *time ; } char getclock(reg) char *reg; { char x ; outp(CLADDR, reg + CLOFF) ; x = inp(CLADDR) & CLMASK ; return x ; }  .