home *** CD-ROM | disk | FTP | other *** search
- /*---------------------------------------------------------*
- | Author: Maurizio Loreti, aka MLO or I3NOO. |
- | Address: University of Padova - Department of Physics |
- | Via F. Marzolo, 8 - 35131 PADOVA - Italy |
- | Phone: (39)(49) 844-313 FAX: (39)(49) 844-245 |
- | E-Mail: LORETI at IPDINFN (BITNET); or VAXFPD::LORETI |
- | (DECnet) - VAXFPD is node 38.257 i.e. 39169; or |
- | LORETI@PADOVA.INFN.IT (INTERNET). |
- | Home: Via G. Donizetti 6 - 35010 CADONEGHE (PD) - Italy |
- *---------------------------------------------------------*/
-
- #include <stdio.h> /* Standard library */
- #include <string.h>
- #include <stdarg.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <exec/types.h> /* Amiga specific */
- #include <intuition/intuition.h>
- #include <graphics/gfxbase.h>
- #include <libraries/dos.h>
- #include <libraries/reqbase.h>
- #include <devices/printer.h>
- #include <proto/exec.h>
- #include <proto/intuition.h>
- #include <proto/graphics.h>
- #include "mlo.h" /* Program specific */
- #include "pf2.h"
- #include "ext.h"
-
- static Boolean CheckBreak(void); /* Local functions */
- static void CheckDefaults(void);
- static void ClearPageBuffer(void);
- static void ClearThisPage(void);
- static void Detab(char *buffer, int length);
- static void DoubleLine(char *left, char *right);
- static void EjectPage(void);
- static void Header(int type);
- static void InterLine(void);
- static void OutLine(void);
- static void ResetPrinter(void);
- static void SendBuffer(char *buffer);
- static void SendToPrinter(char *fmt, ...);
- static void Syntax(void);
-
- /*-----------------------------------------*
- | Routines (sorted in alphabetical order) |
- *-----------------------------------------*/
-
- static Boolean CheckBreak(void)
- {
-
- /**
- | Check for CTRL-C
- **/
-
- if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
- return True;
- }
- return False;
- }
-
- static void CheckDefaults(void)
- {
-
- /**
- | As the name says, this procedure checks for incompatible options
- | selected: e.g. the only Landscape fonts are Courier, so to give
- | the command PF2 -TL ... is an error. I suppose that the internal
- | fonts only are present; otherwise this procedure should be modified.
- | Checks:
- | -> Letter-Gothic: 12 or 24 cpi; portrait only.
- | -> Times: proportional; portrait only.
- | -> Courier: 10 or 20 cpi; plus 16.67 cpi for Courier Roman (not
- | allowed for Courier Italic).
- | -> Landscape/Italic not allowed.
- | -> The number of extra spaces inserted before every line must be
- | not negative.
- **/
-
- switch (Font) {
- case GOTHIC:
- Orientation = PORTRAIT;
- if (Pitch == P10CPI) {
- Pitch = P12CPI;
- } else {
- Pitch = P24CPI;
- }
- break;
- case TIMES:
- Orientation = PORTRAIT;
- Pitch = PROPORTIONAL;
- break;
- case COURIER:
- if (Pitch == P16_67CPI && Style == ITALIC) {
- Pitch = P20CPI;
- }
- break;
- }
-
- if (Orientation == LANDSCAPE) {
- Style = ROMAN;
- }
-
- if (nBlanks < 0) {
- nBlanks = 0;
- } else {
- if (nBlanks) {
- Buffer = inBuffer + nBlanks;
- memset(inBuffer, BLANK, nBlanks);
- }
- }
- }
-
- void Cleanup(
- int code
- ){
-
- /**
- | Releases all system resources (closes opened files
- | and frees heap memory - if any). "code" is the
- | status to be returned to the operating system.
- **/
-
- windowOff();
-
- if (fp != NULL) fclose(fp);
-
- if (pPB != NULL) {
- if (pPB->line[0] != NULL) free(pPB->line[0]);
- free(pPB);
- }
-
- if (PrinterOpened) CloseDevice((struct IORequest *) IOrequest);
- if (IOrequest != NULL) DeleteExtIO((struct IORequest *) IOrequest);
- if (printPort != NULL) DeletePort((struct MsgPort *) printPort);
-
- if (!FromCLI) {
- int i;
- fprintf(stdout, "\nStrike <CR> to continue ... ");
- while ( (i = getchar()) != '\n' && i != EOF) { }
- }
-
- if (ReqBase != NULL) {
- PurgeFiles(&fr);
- CloseLibrary((struct Library *) ReqBase);
- }
- if (GfxBase != NULL) CloseLibrary((struct Library *) GfxBase);
- if (IntuitionBase != NULL) CloseLibrary((struct Library *) IntuitionBase);
-
- exit(code);
- }
-
- static void ClearPageBuffer(void)
- {
-
- /**
- | This routine resets the content of the page buffer
- | used in the 2-pages-on-a-sheet mode to all-blank
- | lines, and the pointer to the next line to be filled
- | to the first line in the buffer.
- **/
-
- memset(pPB->line[0], BLANK, BUFFER_SIZE);
- ThisLine = 0;
- }
-
- static void ClearThisPage(void)
- {
-
- /**
- | Called every end of file: in the normal mode, ejects a page;
- | in the 2-pages mode, switches from the left to the right page
- | (if there is at least a line on this page), and leaving the
- | remainder of the lines on the current page all blank.
- **/
-
- switch (PageMode) {
- case SINGLE_PAGE:
- EjectPage();
- break;
- case LEFT_PAGE:
- if (ThisLine) {
- Header(UP);
- PageMode = RIGHT_PAGE;
- ThisLine = 0;
- }
- break;
- case RIGHT_PAGE:
- if (ThisLine) {
- FlushBuffers();
- PageMode = LEFT_PAGE;
- ClearPageBuffer();
- }
- break;
- }
- }
-
- static void Detab(
- char *buffer,
- int length
- ){
-
- /**
- | Translates TAB stops to blanks: TAB stops are assumed at columns
- | (1 + N * nTabs), with N = 1, 2, ... ; the default value of nTabs
- | is 8, and can be changed using the command switches. In the same
- | time non-printable characters are deleted from the input string:
- | for non-printable I mean characters from 00 to 037 and 0177, assuming
- | that characters over 0177 have special meaning different for every
- | computer and that nothing can be said about them.
- | The buffer can hold "length" characters only.
- **/
-
- char temp[LINE_LENGTH]; /* Internal buffer */
- char *pC1, *pC2; /* Temporary pointers */
- char *pEnd; /* Pointer to the buffer end */
-
- strcpy(temp, buffer);
- pEnd = (buffer + length - 1);
- for (pC1 = temp, pC2 = buffer; *pC1 && pC2 < pEnd; pC1++) {
- if (*pC1 == TAB) {
- do {
- *pC2++ = BLANK;
- } while (((pC2 - buffer) % nTabs) && (pC2 < pEnd));
- } else {
- if (isspace(*pC1) || !iscntrl(*pC1)) {
- *pC2++ = *pC1;
- }
- }
- }
- *pC2 = NIHIL;
- }
-
- void DoOutput(
- char *FileName
- ){
-
- /**
- | Sends to the printer the given file.
- **/
-
- if ((fp = fopen(FileName, "r")) == NULL) {
- printf("Can't open input file %s ...", FileName);
- return;
- }
- printf("Printing file %s ... ", FileName);
-
- while (fgets(Buffer, bufferLength, fp) != NULL) {
- if (CheckBreak()) {
- printf("*** PF2: BREAK ***\n");
- EjectPage();
- ExitProgram();
- }
- Detab(Buffer, bufferLength);
- OutLine();
- }
-
- printf("done.\n");
- fclose(fp);
- fp = NULL;
- ClearThisPage();
- }
-
- static void DoubleLine(
- char *left,
- char *right
- ){
-
- /**
- | Prints a line in the 2-pages mode, the two parameters being
- | pointers to the left-page line and the right-page line; a
- | blank line is printed if the corresponding pointer is NULL.
- **/
-
- if (left == NULL) {
- SendToPrinter("%c%*c%c%*c",
- V_LINE, TOTAL_LENGTH, BLANK, V_LINE, SEP_LENGTH, BLANK);
- } else {
- SendToPrinter("%c%*c%.*s%*c%c%*c",
- V_LINE, SIDE_LENGTH, BLANK, OUTPUT_LENGTH, left,
- SIDE_LENGTH, BLANK, V_LINE, SEP_LENGTH, BLANK);
- }
-
- if (right == NULL) {
- SendToPrinter("%c%*c%c\r",
- V_LINE, TOTAL_LENGTH, BLANK, V_LINE);
- } else {
- SendToPrinter("%c%*c%.*s%*c%c\r",
- V_LINE, SIDE_LENGTH, BLANK, OUTPUT_LENGTH, right,
- SIDE_LENGTH, BLANK, V_LINE);
- }
- }
-
- static void EjectPage(void)
- {
- SendToPrinter("%c", FORM_FEED);
- }
-
- void ExitProgram(void)
- {
- ResetPrinter();
- printf("Good Bye!\n");
- Cleanup(SYS_NORMAL_CODE);
- }
-
- void FlushBuffers(void)
- {
-
- /**
- | In the 2-pages mode, prints the current page as
- | it is (non filled lines will be left blank).
- **/
-
- int i;
-
- switch (PageMode) {
- case LEFT_PAGE:
- if (!ThisLine) return;
- for (i=0; i<ThisLine; i++) {
- DoubleLine(pPB->line[i], NULL);
- InterLine();
- }
- for (i=ThisLine; i<PAGE_LENGTH; i++) {
- DoubleLine(NULL, NULL);
- InterLine();
- }
- Header(DOWN);
- break;
- case RIGHT_PAGE:
- for (i=ThisLine; i<PAGE_LENGTH; i++) {
- DoubleLine(pPB->line[i], NULL);
- InterLine();
- }
- Header(DOWN);
- break;
- }
- }
-
- static void Header(
- int type
- ){
-
- /**
- | Prints the top or the down header in the 2-pages mode:
- | a solid line separated from the text by a blank line.
- **/
-
- memset(Buffer, H_LINE, TOTAL_LENGTH);
-
- if (type == UP) {
- SendToPrinter("%c%.*s%c%*c%c%.*s%c\r",
- NW, TOTAL_LENGTH, Buffer, NE, SEP_LENGTH,
- BLANK, NW, TOTAL_LENGTH, Buffer, NE);
- InterLine();
- }
- DoubleLine(NULL, NULL);
- InterLine();
- if (type == DOWN) {
- SendToPrinter("%c%.*s%c%*c%c%.*s%c\r",
- SW, TOTAL_LENGTH, Buffer, SE, SEP_LENGTH,
- BLANK, SW, TOTAL_LENGTH, Buffer, SE);
- EjectPage();
- }
- }
-
- void InitPrinter(void)
- {
-
- char *PitchID[] = {"10", "12", "16.67", "20", "24"};
- UBYTE status[2] = {0, 0};
- int dummy;
-
- /**
- | Connect properly to printer device
- **/
-
- printPort = (PrintIO *) CreatePort(PORT_NAME, 0);
- IOrequest = (PrintIO *) CreateExtIO((struct MsgPort *) printPort,
- sizeof(PrintIO));
- if (!(PrinterOpened = (OpenDevice("printer.device", 0,
- (struct IORequest *) IOrequest, 0) == 0))) {
- Cleanup(SYS_ABORT_CODE);
- }
-
- /**
- | Check if the printer is there... Actually, if the printer is connected
- | to the serial port, I don't know what to do: in this case I continue,
- | knowing that a System requester will come after a while. If the printer
- | is connected to the parallel port, printer selected (bit 0), paper out
- | (bit 1) and printer offline (bit 2) are checked.
- **/
-
- FOREVER {
- IOrequest->ios.io_Command = PRD_QUERY;
- IOrequest->ios.io_Data = (APTR) status;
- IOrequest->ios.io_Flags = 0;
- if (DoIO((struct IORequest *) IOrequest)) {
- Cleanup(SYS_ABORT_CODE);
- }
- if (IOrequest->ios.io_Actual == 2) break;
- if ((status[0] & 0x7) == 0x4) break;
-
- puts("Please, check if your printer is ready!");
- printf("When done, enter <CR> ... ");
- while (((dummy = getc(stdin)) != NEWLINE) && (dummy != EOF) ) {}
- puts("");
- }
-
- /**
- | Printer initialisation: see the HP DeskJet 500
- | user's manual for explanation...
- **/
-
- SendToPrinter("%c&l%do%dD%c(10U%c(s0u", ESC, Orientation, Lpi, ESC, ESC);
- if (Pitch == PROPORTIONAL) {
- SendToPrinter("1p");
- } else {
- SendToPrinter("0p%sh", PitchID[Pitch]);
- }
- SendToPrinter("%dv%ds0b%dt%dQ", Height, Style, Font, Quality);
- }
-
- static void InterLine(void)
- {
-
- /**
- | Writing at 8 lines per inch and 6 points high characters,
- | the double page border is not continuous. This procedure
- | skips half line, draws the border, then skips another half
- | line down to the correct placement for next printing.
- **/
-
- SendToPrinter("%c=", ESC);
- DoubleLine(NULL, NULL);
- SendToPrinter("%c=", ESC);
- }
-
- static void OutLine(void)
- {
-
- /**
- | Outputs a line to the printer.
- | In the normal mode, the line is sent to the port after storing a
- | carriage return and a line feed after the text, and leaving to the
- | printer to deal with form feeds and long lines.
- | In the 2-pages mode, the line is truncated to a fixed length: if
- | we are in the left page, the line is stored in the internal buffer;
- | otherwise, it is printed together with the corresponding left line.
- **/
-
- int length, n;
- static char *EndOfLine = "\r\n";
-
- length = strlen(inBuffer) - 1;
-
- switch (PageMode) {
- case SINGLE_PAGE:
- memcpy(inBuffer+length, EndOfLine, 3);
- SendBuffer(inBuffer);
- break;
- case LEFT_PAGE:
- if (length > OUTPUT_LENGTH) {
- length = OUTPUT_LENGTH;
- }
- memcpy(pPB->line[ThisLine], Buffer, length);
- if (++ThisLine >= PAGE_LENGTH) {
- Header(UP);
- PageMode = RIGHT_PAGE;
- ThisLine = 0;
- }
- break;
- case RIGHT_PAGE:
- if ((n = OUTPUT_LENGTH - length) > 0) {
- memset(Buffer+length, BLANK, n);
- }
- DoubleLine(pPB->line[ThisLine], Buffer);
- InterLine();
- if (++ThisLine >= PAGE_LENGTH) {
- Header(DOWN);
- PageMode = LEFT_PAGE;
- ClearPageBuffer();
- }
- break;
- }
- }
-
- static void ResetPrinter(void)
- {
-
- /**
- | Resets the printer to the default.
- **/
-
- SendToPrinter("%cE", ESC);
- }
-
- static void SendBuffer(
- char *buffer
- ){
- IOrequest->ios.io_Command = PRD_RAWWRITE;
- IOrequest->ios.io_Data = (APTR) buffer;
- IOrequest->ios.io_Length = strlen(buffer);
- IOrequest->ios.io_Flags = 0;
- if (DoIO((struct IORequest *) IOrequest)) {
- Cleanup(SYS_ABORT_CODE);
- }
- }
-
- static void SendToPrinter(
- char *fmt,
- ...
- ){
- static char slate[LINE_LENGTH];
- va_list vl;
-
- va_start(vl, fmt);
- vsprintf(slate, fmt, vl);
- va_end(vl);
- SendBuffer(slate);
- }
-
- void SetSpecialMode(void)
- {
-
- /**
- | Sets the internal constants for the "two pages on a sheet"
- | special mode.
- **/
-
- int i;
-
- if ((pPB = malloc(sizeof(PageBuffer))) == NULL) {
- fprintf(stderr, "Can't allocate the Page Buffer ...");
- Cleanup(SYS_ABORT_CODE);
- }
- if ((pPB->line[0] = malloc(BUFFER_SIZE)) == NULL) {
- fprintf(stderr, "Can't allocate the Line Buffer ...");
- Cleanup(SYS_ABORT_CODE);
- }
- for (i=1; i<PAGE_LENGTH; i++) {
- pPB->line[i] = pPB->line[0] + (i * OUTPUT_LENGTH);
- }
-
- Orientation = LANDSCAPE;
- Font = COURIER;
- Style = ROMAN;
- Pitch = P16_67CPI;
- Height = 6;
- Lpi = 8;
- nBlanks = 0;
- ClearPageBuffer();
- }
-
- char **Setup(
- int *pArgc,
- char **argv
- ){
-
- /**
- | We look into the command line for switches; the function value is
- | argv when pointing to the first non-switch argument (i.e. the first
- | file name) - if any. If the 2-page mode was requested, the procedure
- | allocates from the heap memory the internal buffer for the left-page
- | lines, and a service buffer filled with the pointers to the first
- | character of every line in the left page; this calling malloc(),
- | to make this program more portable.
- **/
-
- int i;
- char c;
-
- /**
- | Error if called from the Workbench, or if called
- | from the CLI but without any argument.
- **/
-
- if (*pArgc < 2) Syntax();
-
- while (--(*pArgc)) {
- if ((*++argv)[0] == '-') {
-
- /**
- | A switch ...
- **/
-
- for (i=1; (c = (*argv)[i]); i++) {
- switch (c) {
- case 'l': case 'L':
- Orientation = LANDSCAPE;
- break;
- case 'i': case 'I':
- Style = ITALIC;
- break;
- case 'b': case 'B':
- nBlanks = atoi(*argv + ++i);
- goto NextSwitch;
- case 'a': case 'A':
- nTabs = atoi(*argv + ++i);
- goto NextSwitch;
- case 'g': case 'G':
- Font = GOTHIC;
- break;
- case 't': case 'T':
- Font = TIMES;
- break;
- case 's': case 'S':
- Pitch = P16_67CPI;
- break;
- case 'x': case 'X':
- Pitch = P20CPI;
- break;
- case '6':
- Height = 6;
- break;
- case '8':
- Lpi = 8;
- break;
- case 'd': case 'D':
- Quality = DRAFT_Q;
- break;
- case '2':
- PageMode = LEFT_PAGE;
- break;
- default:
- Syntax();
- }
- }
- } else {
-
- /**
- | The first file name; perform some
- | intialisations, then return to the caller.
- **/
-
- if (PageMode != SINGLE_PAGE) {
- SetSpecialMode();
- } else {
- CheckDefaults();
- }
- return argv;
- }
-
- NextSwitch: ;
- }
-
- /**
- | Here if no file name given; initialise
- | the printer, then exit without reset.
- **/
-
- CheckDefaults();
- InitPrinter();
- puts("Printer initialised ... Good bye!");
- Cleanup(SYS_NORMAL_CODE);
- }
-
- static void Syntax(void)
- {
-
- /**
- | A syntax error has been detected in the command
- | line; a short help is output to the screen.
- **/
-
- puts("Usage: PF2 [switches] [file [file [file ... ] ] ]");
- puts("Switches: -l : Landscape (default is Portrait);");
- puts(" -i : Italic (default is Roman);");
- puts(" -bN : insert N Blanks before every output line;");
- puts(" -aN : tAb stops every N characters (default: 8);");
- puts(" -g : Letter-Gothic font (default is Courier);");
- puts(" -t : Times font (default is Courier);");
- puts(" -s : Small pitch (Courier: 16.67 cpi; "
- "Letter-Gothic: 24 cpi);");
- puts(" -x : eXtra-small pitch (20 cpi - for Courier only);");
- puts(" -8 : 8 lines per inch (default: 6 lpi);");
- puts(" -6 : 6 points high font (default: 12 points);");
- puts(" -d : Draft quality (default is Letter quality);");
- puts(" -2 : special mode (2 pages on every sheet of paper).\n");
- puts("The s/x/l switches are ignored when incompatible with selected font.");
- puts("The default pitch is 10 cpi for Courier and 12 cpi for Letter-Gothic");
- puts("(Times is a proportional font); all switches different from -d and");
- puts("-a will be ignored, if -2 is selected. The switches on the command");
- puts("line can be grouped: e.g. -c -8 -s is the same as -c8s; only -bN and");
- puts("-aN, if present, must be specified alone or the last in a group. The");
- puts("printer is reset to its default, at the completion - UNLESS if no");
- puts("file names are given. This program can be interrupted with CTRL-C.\n");
-
- Cleanup(SYS_NORMAL_CODE);
- }
-