/* Spool.c V1.0.0 27-Mar-88 ) Frangois Gagnon */ /* Copyright ) 1988 Frangois Gagnon, All Rights Reserved. The author does not make any warranty expressed or implied, or assumes any liability or responsiblity for the use of this software. Permission is hereby granted to copy, reproduce, redistribute or otherwise use this software as long as it is for non-profit. This notice and the above copyright notice must remain intact and appear on all copies. Permission is also granted to correct any problems with this software, but modifications and improvements are reserved by the author. */ #include #include #include #include #include #include #include #include "stdefs.h" #include "Print_Spool.h" ^L /*********************************/ /* Local Constants and Variables */ /*********************************/ /* Define constant used in the program */ #define Flag_Test (Line_Formats | Page_Formats) #define Flag_Line (Line_Density | Line_Formats) #define Flag_Page (Page_Density | Page_Formats) #define Flag_Used (Page_Density | Page_Formats | Opts_Headers) #define Opts_Page(Opts) ((Opts & Flag_Page) >> 3) #define Opts_Used(Opts) ((Opts & Flag_Used) >> 3) local int Line_Size[8] = { 80, 96, 132, 80, 136, 164, 232, 136 }; local int Page_Size[4] = { 51, 68, 66, 88 }; local int Page_Used[8] = { 48, 64, 63, 84, 48, 63, 63, 83 }; local char Line_Code[4] = { '0', '2', '4', '0' }; /* Declarations of status messages */ local char HEAD[] = "\nSpool V1.0 27-Mar-88 ) Frangois Gagnon\n\n"; local char LOGS[] = "Spool: Unable to access log file.\n"; local char EXEC[] = "Spool: Spool is already running.\n"; local char INIT[] = "Spool: Unable to create a port.\n"; local char OPEN[] = "Unable to open %s for input.\n"; local char COPY[] = "Printed %s ... %ld chars ... %ld lines ... %ld pages.\n"; local char BACK[] = "Reset %s after %ld chars ... %ld lines ... %ld pages.\n"; local char STOP[] = "Canceled %s after %ld chars ... %ld lines ... %ld pages.\n"; local char MOVE[] = "Removed %s after %ld chars ... %ld lines ... %ld pages.\n"; /* Definition for Execution */ local FILE *Spool_File; local char *Spool_Logs = "RAM:Spool.log"; local struct Inform *Info_Port; local struct MsgPort *Data_Port; local Info Status = { 1, Wait_State, 0, FALSE, 0, 0, 0, NULL }; local FILE *From_File, *Dest_File = NULL; local short Line_Limit, Line_Count; local int Char_Saved; /* Definition for Manipulation */ local File **Temp_Move, *Temp_File; local File **Temp_Skip, *Temp_Test; local byte Temp_Opts; /* Simple typing optimization */ #define Next_Char() { Char_Saved = fgetc( From_File); ++Status.Char_Print; } ^L /******************************/ /* File Name Pattern Matching */ /******************************/ local int File_Match( Name, Data) /*************************************/ register char *Name, *Data; { auto char *Save_Name[10], *Save_Data[10]; register int Save; if ((*Data == NUL) || (*Name == NUL)) return FALSE; Save = -1; while ((*Data != NUL) || (*Name != NUL)) { if (*Data == '*') { if (*++Data == NUL) return TRUE; if ( ++Save == 10) return FALSE; Save_Name[Save] = Name; Save_Data[Save] = Data; continue; } if ( ((*Data == '?') && (*Name != NUL)) || (toupper(*Data) == toupper(*Name))) { ++Data; ++Name; continue; } if (*Name == NUL) --Save; if ( Save < 0) return FALSE; Name = ++Save_Name[Save]; Data = Save_Data[Save]; } return TRUE; } ^L /******************************/ /* Initialization of Defaults */ /******************************/ #define INTUITIONNAME "intuition.library" public struct IntuitionBase *IntuitionBase; local void Default_Values() /******************************/ { auto struct Preferences PrefBuffer; auto int Temp; extern struct IntuitionBase *OpenLibrary(); extern struct Preferences *GetPrefs(); /* Fetch the information from the system */ IntuitionBase = OpenLibrary( INTUITIONNAME, 0L); if (IntuitionBase == NULL) return; GetPrefs( &PrefBuffer, (long) sizeof( struct Preferences)); CloseLibrary( IntuitionBase); /* Extract the information from the structure */ Temp = (PrefBuffer.PrintSpacing == EIGHT_LPI ? 8 : 6); if (PrefBuffer.PaperLength / Temp == 11) Status.Opts_State |= Page_11; if (PrefBuffer.PaperSize == W_TRACTOR) Status.Opts_State |= Line_13; } /**********************************/ /* Stop Printing The Current File */ /**********************************/ local int Stop_Printing( Spool_Show) /****************************************/ char *Spool_Show; { extern FILE *fopen(); if ((Status.Prog_State != Exec_State) && (Status.Prog_State != File_State) && (Status.Prog_State != Stop_State) ) return FALSE; if (Line_Count != Line_Limit) putc( '\f', Dest_File); fclose( From_File); if (Status.Prog_State == Exec_State) Status.Prog_State = Wait_State; else Status.Prog_State = Susp_State; if ((Spool_File = fopen( Spool_Logs, "a")) == NULL) Spool_File = stderr; fprintf( Spool_File, Spool_Show, Status.File_Print->File_Name, Status.Char_Print, Status.Line_Print, Status.Page_Print); if (Spool_File != stderr) fclose( Spool_File); return TRUE; } ^L /********************************/ /* Execute all pending commands */ /********************************/ local void Exec_Print() /**************************/ { extern struct Inform *GetMsg(); extern File *AllocMem(); extern int strncmp(); while ((Info_Port = GetMsg( Data_Port)) != NULL) { if (Info_Port->Number != PROTOCOL) Info_Port->Number = PROTOCOL; else switch( Info_Port->Action) { case PS_Insert : Temp_Skip = &Status.File_Print; while (*Temp_Skip) Temp_Skip = &(*Temp_Skip)->File_Next; *Temp_Skip = Info_Port->Detail.Insert; Info_Port->Detail.Insert = NULL; break; case PS_Update : for (Temp_Test = Info_Port->Detail.Update; Temp_Test != NULL; Temp_Test = Temp_Test->File_Next) { for (Temp_File = Status.File_Print; Temp_File != NULL; Temp_File = Temp_File->File_Next) { if (strncmp( Temp_Test->File_Name, Temp_File->File_Name, Name_Size) == 0) { if ((Temp_Test->File_Copy == 0) && (Temp_File == Status.File_Print) ) Stop_Printing( STOP); Temp_File->File_Opts = Temp_Test->File_Opts; Temp_File->File_Flag = Temp_Test->File_Flag; Temp_File->File_Copy = Temp_Test->File_Copy; Temp_File->File_Size = Temp_Test->File_Size; Temp_Test->File_Flag |= Flag_Updated; break; } } } break; ^L case PS_Remove : Temp_Move = &Temp_File; Temp_Skip = &Status.File_Print; while ((Temp_Test = *Temp_Skip) != NULL) { if (File_Match( Temp_Test->File_Name, Info_Port->Detail.Remove)) { if (Temp_Skip == &Status.File_Print) Stop_Printing( MOVE); *Temp_Move = Temp_Test; *Temp_Skip = Temp_Test->File_Next; Temp_Move = &Temp_Test->File_Next; } else Temp_Skip = &Temp_Test->File_Next; } *Temp_Move = NULL; Info_Port->Detail.Insert = Temp_File; break; case PS_Report : Info_Port->Detail.Status = Status; Temp_Skip = &Info_Port->Detail.Status.File_Print; for (Temp_File = Status.File_Print; Temp_File != NULL; Temp_File = Temp_File->File_Next) { Temp_Test = AllocMem( (long) sizeof( File), MEMF_PUBLIC); if (Temp_Test == NULL) { Info_Port->Detail.Status.Opts_State |= Flag_Partial; } else { *(*Temp_Skip = Temp_Test) = *Temp_File; Temp_Skip = &Temp_Test->File_Next; } } *Temp_Skip = NULL; break; case PS_Return : Status.Flag_State = !Status.Flag_State; break; case PS_Change : if (Status.File_Print != NULL) { Status.Opts_State &= ~Flag_Test; Status.Opts_State |= Status.File_Print->File_Opts & Flag_Test; } break; case PS_Freeze : switch( Status.Prog_State) { case Wait_State : case Page_State : case Open_State : Status.Prog_State = Susp_State; break; case Exec_State : case File_State : Status.Prog_State = Stop_State; break; } break; ^L case PS_Finish : switch( Status.Prog_State) { case Wait_State : case Page_State : case Open_State : Status.Prog_State = Susp_State; break; case Exec_State : case Stop_State : Status.Prog_State = File_State; break; } break; case PS_Resets : Stop_Printing( BACK); Status.Prog_State = Susp_State; break; case PS_Cancel : if (Stop_Printing( STOP)) --Status.File_Print->File_Copy; Status.Prog_State = Susp_State; break; case PS_Resume : if (Status.Prog_State == Susp_State) Status.Prog_State = Wait_State; if (Status.Prog_State == Stop_State) Status.Prog_State = Exec_State; if (Status.Prog_State == File_State) Status.Prog_State = Exec_State; break; } Info_Port->Packet.mn_Node.ln_Type = NT_REPLYMSG; ReplyMsg( Info_Port); } } ^L /******************************************/ /* Perform according to the current state */ /******************************************/ local int Exec_Spool() /**************************/ { extern FILE *fopen(); switch( Status.Prog_State) { case Wait_State : case Page_State : case Open_State : /* Eliminate Old File Information */ while ((Temp_File = Status.File_Print) != NULL) { if (Temp_File->File_Copy != 0) break; Status.File_Print = Temp_File->File_Next; if (Temp_File->File_Flag & Flag_Deleted) remove( Temp_File->File_Name); FreeMem( Temp_File, (long) sizeof( Temp_File)); } /* Wait if there is nothing to do */ if (Temp_File == NULL) { Status.Prog_State = Wait_State; if (Dest_File != NULL) { fclose( Dest_File); Dest_File = NULL; } if (Status.Flag_State) { Forbid(); if ((Info_Port = GetMsg( Data_Port)) == NULL) { DeletePort( Data_Port); Permit(); return FALSE; } PutMsg( Data_Port, Info_Port); Permit(); } else WaitPort( Data_Port); break; } /* Check the format of the paper */ Temp_Opts = (Status.Opts_State ^ Temp_File->File_Opts); if (Temp_Opts & Flag_Test) { if (Dest_File != NULL) { fclose( Dest_File); Dest_File = NULL; } Status.Prog_State = Page_State; WaitPort( Data_Port); break; } /* Request access to the printer */ if ((Dest_File == NULL) && ((Dest_File = fopen( "PRT:", "w")) == NULL) ) { Status.Prog_State = Open_State; Delay( 5L * TICKS_PER_SECOND); break; } ^L /* Request access to the data file */ From_File = fopen( Status.File_Print->File_Name, "r"); if (From_File == NULL) { Status.File_Print->File_Copy = 0; Status.Prog_State = Wait_State; Spool_File = fopen( Spool_Logs, "a"); if (Spool_File == NULL) Spool_File = stderr; fprintf( Spool_File, OPEN, Status.File_Print->File_Name); if (Spool_File != stderr) fclose( Spool_File); break; } /* Initialize all control variables */ Status.Opts_State = Status.File_Print->File_Opts; Status.Char_Print = Status.Line_Print = Status.Page_Print = 0; Line_Limit = Page_Used[Opts_Used(Status.Opts_State)]; Line_Count = Line_Limit; /* Initialize the printer */ fprintf( Dest_File, "\033c\033#1\033#5\033[%cw\033[1;%ds\033[%cz\033[%dt\033[%c\"z", Line_Code[Status.Opts_State & Line_Density], Line_Size[Status.Opts_State & Flag_Line], (Status.Opts_State & Page_Density ? '0' : '1'), Page_Size[Opts_Page(Status.Opts_State)], (Status.File_Print->File_Flag & Flag_Quality ? '2' : '1')); /* Start printing the specified file */ Status.Prog_State = Exec_State; Char_Saved = fgetc( From_File); ^L case Exec_State : case File_State : /* Print the file one line at a time */ if (Char_Saved == EOF) { Stop_Printing( COPY); --Status.File_Print->File_Copy; break; } /* Deal with form feed characters */ if (Char_Saved == '\f') { if (Line_Count != Line_Limit) { putc( '\f', Dest_File); Line_Count = Line_Limit; } Next_Char(); break; } /* Deal with page counters and headers */ if (Line_Count == Line_Limit) { ++Status.Page_Print; Line_Count = 0; if (Status.Opts_State & Opts_Headers) { fprintf( Dest_File, "%-20.20s %-42.42s Page %3ld\n\n\n", Status.File_Print->File_Date, Status.File_Print->File_Name, Status.Page_Print); Line_Count = 3; } } /* Time to print the line */ ++Status.Line_Print; ++Line_Count; if (Status.Opts_State & Opts_Numbers) fprintf( Dest_File, "%6ld: ", Status.Line_Print); while ((Char_Saved != EOF) && (Char_Saved != '\n') && (Char_Saved != '\f') ) { putc( Char_Saved, Dest_File); Next_Char(); } if (Char_Saved == '\n') Next_Char(); fputs( (Line_Count == Line_Limit ? "\n\f" : "\n"), Dest_File); break; case Susp_State : /* Wait for new comamnds */ if (Dest_File != NULL) { fclose( Dest_File); Dest_File = NULL; } case Stop_State : WaitPort( Data_Port); break; } return TRUE; } ^L /*****************************/ /* This is the Spool program */ /*****************************/ public void main( argc, argv) /*******************************/ int argc; char *argv[]; { extern struct MsgPort *FindPort(), *CreatePort(); extern FILE *fopen(); fprintf( stderr, HEAD); if (FindPort( SPOOLNAME) != NULL) { fprintf( stderr, EXEC); exit( 1); } if (argc > 1) Spool_Logs = argv[1]; if ((Spool_File = fopen( Spool_Logs, "a")) == NULL) { fprintf( stderr, LOGS, Spool_Logs); exit(1); } fprintf( Spool_File, HEAD); fclose( Spool_File); if ((Data_Port = CreatePort( SPOOLNAME, 0L)) == NULL) { fprintf( stderr, INIT); exit( 1); } Default_Values(); do Exec_Print(); while (Exec_Spool()); }