home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d154 / printspool.lha / PrintSpool / Spool.c < prev    next >
C/C++ Source or Header  |  1987-06-15  |  14KB  |  466 lines

  1.  
  2. /* Spool.c    V1.0.0    27-Mar-88    ) Frangois Gagnon */
  3.  
  4.  
  5. /*
  6.    Copyright ) 1988  Frangois Gagnon,  All Rights Reserved.
  7.  
  8.    The author does not make any warranty expressed or implied,
  9.    or assumes any liability or responsiblity for the use of
  10.    this software.
  11.  
  12.    Permission is hereby granted to copy, reproduce, redistribute
  13.    or otherwise use this software as long as it is for non-profit.
  14.    This notice and the above copyright notice must remain intact
  15.    and appear on all copies.
  16.  
  17.    Permission is also granted to correct any problems with this
  18.    software, but modifications and improvements are reserved by
  19.    the author.
  20. */
  21.  
  22. #include <stdio.h>
  23. #include <ctype.h>
  24.  
  25. #include <exec/memory.h>
  26. #include <exec/ports.h>
  27. #include <exec/nodes.h>
  28. #include <libraries/dos.h>
  29. #include <intuition/preferences.h>
  30.  
  31. #include "stdefs.h"
  32. #include "Print_Spool.h"
  33. ^L
  34. /*********************************/
  35. /* Local Constants and Variables */
  36. /*********************************/
  37.  
  38. /* Define constant used in the program */
  39. #define Flag_Test    (Line_Formats | Page_Formats)
  40. #define Flag_Line    (Line_Density | Line_Formats)
  41. #define Flag_Page    (Page_Density | Page_Formats)
  42. #define Flag_Used    (Page_Density | Page_Formats | Opts_Headers)
  43. #define Opts_Page(Opts) ((Opts & Flag_Page) >> 3)
  44. #define Opts_Used(Opts) ((Opts & Flag_Used) >> 3)
  45.  
  46. local    int    Line_Size[8] = { 80, 96, 132, 80, 136, 164, 232, 136 };
  47. local    int    Page_Size[4] = { 51, 68, 66, 88 };
  48. local    int    Page_Used[8] = { 48, 64, 63, 84, 48, 63, 63, 83 };
  49. local    char    Line_Code[4] = { '0', '2', '4', '0' };
  50.  
  51. /* Declarations of status messages */
  52. local    char    HEAD[] = "\nSpool  V1.0  27-Mar-88  ) Frangois Gagnon\n\n";
  53. local    char    LOGS[] = "Spool: Unable to access log file.\n";
  54. local    char    EXEC[] = "Spool: Spool is already running.\n";
  55. local    char    INIT[] = "Spool: Unable to create a port.\n";
  56.  
  57. local    char    OPEN[] = "Unable to open %s for input.\n";
  58. local    char    COPY[] = "Printed %s ... %ld chars ... %ld lines ... %ld pages.\n";
  59. local    char    BACK[] = "Reset %s after %ld chars ... %ld lines ... %ld pages.\n";
  60. local    char    STOP[] = "Canceled %s after %ld chars ... %ld lines ... %ld pages.\n";
  61. local    char    MOVE[] = "Removed %s after %ld chars ... %ld lines ... %ld pages.\n";
  62.  
  63. /* Definition for Execution */
  64. local    FILE    *Spool_File;
  65. local    char    *Spool_Logs = "RAM:Spool.log";
  66.  
  67. local    struct    Inform  *Info_Port;
  68. local    struct    MsgPort *Data_Port;
  69.  
  70. local    Info    Status = { 1, Wait_State, 0, FALSE, 0, 0, 0, NULL };
  71.  
  72. local    FILE    *From_File, *Dest_File = NULL;
  73. local    short    Line_Limit, Line_Count;
  74. local    int    Char_Saved;
  75.  
  76. /* Definition for Manipulation */
  77. local    File    **Temp_Move, *Temp_File;
  78. local    File    **Temp_Skip, *Temp_Test;
  79. local    byte      Temp_Opts;
  80.  
  81. /* Simple typing optimization */
  82. #define    Next_Char() { Char_Saved = fgetc( From_File); ++Status.Char_Print; }
  83. ^L
  84. /******************************/
  85. /* File Name Pattern Matching */
  86. /******************************/
  87.  
  88. local     int    File_Match( Name, Data)
  89. /*************************************/
  90. register char    *Name, *Data;
  91.  
  92. { auto       char *Save_Name[10],
  93.         *Save_Data[10];
  94.   register int     Save;
  95.  
  96.   if ((*Data == NUL) || (*Name == NUL)) return FALSE;
  97.   Save = -1;
  98.  
  99.   while ((*Data != NUL) || (*Name != NUL))
  100.   { if (*Data == '*')
  101.     { if (*++Data == NUL) return TRUE;
  102.       if ( ++Save ==  10) return FALSE;
  103.       Save_Name[Save] = Name;
  104.       Save_Data[Save] = Data;
  105.       continue;
  106.     }
  107.     if (   ((*Data == '?') && (*Name != NUL))
  108.     || (toupper(*Data) == toupper(*Name)))
  109.     { ++Data; ++Name; continue; }
  110.  
  111.     if (*Name == NUL) --Save;
  112.     if ( Save <    0) return FALSE;
  113.     Name = ++Save_Name[Save];
  114.     Data =   Save_Data[Save];
  115.   }
  116.   return TRUE;
  117. }
  118. ^L
  119. /******************************/
  120. /* Initialization of Defaults */
  121. /******************************/
  122.  
  123. #define INTUITIONNAME        "intuition.library"
  124. public    struct IntuitionBase    *IntuitionBase;
  125.  
  126. local    void    Default_Values()
  127. /******************************/
  128.  
  129. { auto     struct Preferences    PrefBuffer;
  130.   auto     int            Temp;
  131.   extern struct IntuitionBase  *OpenLibrary();
  132.   extern struct Preferences    *GetPrefs();
  133.  
  134.   /* Fetch the information from the system */
  135.   IntuitionBase = OpenLibrary( INTUITIONNAME, 0L);
  136.   if (IntuitionBase == NULL) return;
  137.   GetPrefs( &PrefBuffer, (long) sizeof( struct Preferences));
  138.   CloseLibrary( IntuitionBase);
  139.  
  140.   /* Extract the information from the structure */
  141.   Temp = (PrefBuffer.PrintSpacing == EIGHT_LPI ? 8 : 6);
  142.   if (PrefBuffer.PaperLength / Temp == 11) Status.Opts_State |= Page_11;
  143.   if (PrefBuffer.PaperSize == W_TRACTOR)   Status.Opts_State |= Line_13;
  144. }
  145.  
  146.  
  147. /**********************************/
  148. /* Stop Printing The Current File */
  149. /**********************************/
  150.  
  151. local    int    Stop_Printing( Spool_Show)
  152. /****************************************/
  153. char    *Spool_Show;
  154.  
  155. { extern FILE    *fopen();
  156.   if ((Status.Prog_State != Exec_State) &&
  157.       (Status.Prog_State != File_State) &&
  158.       (Status.Prog_State != Stop_State) ) return FALSE;
  159.  
  160.   if (Line_Count != Line_Limit) putc( '\f', Dest_File);
  161.   fclose( From_File);
  162.   if (Status.Prog_State == Exec_State)    Status.Prog_State = Wait_State;
  163.   else                    Status.Prog_State = Susp_State;
  164.  
  165.   if ((Spool_File = fopen( Spool_Logs, "a")) == NULL) Spool_File = stderr;
  166.   fprintf( Spool_File,             Spool_Show,
  167.        Status.File_Print->File_Name, Status.Char_Print,
  168.        Status.Line_Print,         Status.Page_Print);
  169.   if (Spool_File != stderr) fclose( Spool_File);
  170.   return TRUE;
  171. }
  172. ^L
  173. /********************************/
  174. /* Execute all pending commands */
  175. /********************************/
  176.  
  177. local    void    Exec_Print()
  178. /**************************/
  179.  
  180. { extern struct    Inform    *GetMsg();
  181.   extern File        *AllocMem();
  182.   extern int         strncmp();
  183.  
  184.   while ((Info_Port = GetMsg( Data_Port)) != NULL)
  185.   { if (Info_Port->Number != PROTOCOL)
  186.       Info_Port->Number = PROTOCOL;
  187.     else switch( Info_Port->Action)
  188.     {
  189.       case PS_Insert :
  190.     Temp_Skip = &Status.File_Print;
  191.     while (*Temp_Skip) Temp_Skip = &(*Temp_Skip)->File_Next;
  192.     *Temp_Skip = Info_Port->Detail.Insert;
  193.     Info_Port->Detail.Insert = NULL;
  194.     break;
  195.  
  196.       case PS_Update :
  197.     for  (Temp_Test  = Info_Port->Detail.Update;
  198.           Temp_Test != NULL;
  199.           Temp_Test  = Temp_Test->File_Next)
  200.     {
  201.       for  (Temp_File  = Status.File_Print;
  202.         Temp_File != NULL;
  203.         Temp_File  = Temp_File->File_Next)
  204.       {
  205.         if (strncmp( Temp_Test->File_Name,
  206.              Temp_File->File_Name, Name_Size) == 0)
  207.         { if ((Temp_Test->File_Copy == 0)      &&
  208.           (Temp_File == Status.File_Print) ) Stop_Printing( STOP);
  209.           Temp_File->File_Opts  = Temp_Test->File_Opts;
  210.           Temp_File->File_Flag  = Temp_Test->File_Flag;
  211.           Temp_File->File_Copy  = Temp_Test->File_Copy;
  212.           Temp_File->File_Size  = Temp_Test->File_Size;
  213.           Temp_Test->File_Flag |= Flag_Updated;
  214.           break;
  215.     } } }
  216.     break;
  217. ^L
  218.       case PS_Remove :
  219.     Temp_Move = &Temp_File;
  220.     Temp_Skip = &Status.File_Print;
  221.     while ((Temp_Test = *Temp_Skip) != NULL)
  222.     { if (File_Match( Temp_Test->File_Name,
  223.               Info_Port->Detail.Remove))
  224.       { if (Temp_Skip == &Status.File_Print) Stop_Printing( MOVE);
  225.         *Temp_Move = Temp_Test;
  226.         *Temp_Skip = Temp_Test->File_Next;
  227.         Temp_Move  = &Temp_Test->File_Next;
  228.       }
  229.       else Temp_Skip = &Temp_Test->File_Next;
  230.     }
  231.     *Temp_Move = NULL;
  232.     Info_Port->Detail.Insert = Temp_File;
  233.     break;
  234.  
  235.       case PS_Report :
  236.     Info_Port->Detail.Status = Status;
  237.     Temp_Skip = &Info_Port->Detail.Status.File_Print;
  238.     for (Temp_File  = Status.File_Print;
  239.          Temp_File != NULL;
  240.          Temp_File  = Temp_File->File_Next)
  241.     {
  242.       Temp_Test = AllocMem( (long) sizeof( File), MEMF_PUBLIC);
  243.       if (Temp_Test == NULL)
  244.       { Info_Port->Detail.Status.Opts_State |= Flag_Partial; }
  245.       else
  246.       { *(*Temp_Skip = Temp_Test) = *Temp_File;
  247.         Temp_Skip = &Temp_Test->File_Next;
  248.     } }
  249.     *Temp_Skip = NULL;
  250.     break;
  251.  
  252.       case PS_Return :
  253.     Status.Flag_State = !Status.Flag_State;
  254.     break;
  255.  
  256.       case PS_Change :
  257.     if (Status.File_Print != NULL)
  258.     { Status.Opts_State &= ~Flag_Test;
  259.       Status.Opts_State |= Status.File_Print->File_Opts & Flag_Test;
  260.     }
  261.     break;
  262.  
  263.       case PS_Freeze :
  264.     switch( Status.Prog_State)
  265.     { case Wait_State : case Page_State : case Open_State :
  266.         Status.Prog_State = Susp_State; break;
  267.       case Exec_State : case File_State :
  268.         Status.Prog_State = Stop_State; break;
  269.     }
  270.     break;
  271. ^L
  272.       case PS_Finish :
  273.       switch( Status.Prog_State)
  274.       { case Wait_State : case Page_State : case Open_State :
  275.           Status.Prog_State = Susp_State; break;
  276.         case Exec_State : case Stop_State :
  277.           Status.Prog_State = File_State; break;
  278.       }
  279.       break;
  280.       
  281.       case PS_Resets :
  282.     Stop_Printing( BACK);
  283.     Status.Prog_State = Susp_State;
  284.     break;
  285.  
  286.       case PS_Cancel :
  287.     if (Stop_Printing( STOP)) --Status.File_Print->File_Copy;
  288.     Status.Prog_State = Susp_State;
  289.     break;
  290.  
  291.       case PS_Resume :
  292.     if (Status.Prog_State == Susp_State) Status.Prog_State = Wait_State;
  293.     if (Status.Prog_State == Stop_State) Status.Prog_State = Exec_State;
  294.     if (Status.Prog_State == File_State) Status.Prog_State = Exec_State;
  295.     break;
  296.     }
  297.     Info_Port->Packet.mn_Node.ln_Type = NT_REPLYMSG;
  298.     ReplyMsg( Info_Port);
  299. } }
  300. ^L
  301. /******************************************/
  302. /* Perform according to the current state */
  303. /******************************************/
  304.  
  305. local    int    Exec_Spool()
  306. /**************************/
  307.  
  308. { extern FILE *fopen();
  309.  
  310.   switch( Status.Prog_State)
  311.   {
  312.     case Wait_State : case Page_State : case Open_State :
  313.  
  314.       /* Eliminate Old File Information */
  315.       while ((Temp_File = Status.File_Print) != NULL)
  316.       { if (Temp_File->File_Copy != 0) break;
  317.     Status.File_Print = Temp_File->File_Next;
  318.     if (Temp_File->File_Flag & Flag_Deleted)
  319.       remove( Temp_File->File_Name);
  320.     FreeMem( Temp_File, (long) sizeof( Temp_File));
  321.       }
  322.  
  323.       /* Wait if there is nothing to do */
  324.       if (Temp_File == NULL)
  325.       { Status.Prog_State = Wait_State;
  326.     if (Dest_File != NULL) { fclose( Dest_File); Dest_File = NULL; }
  327.     if (Status.Flag_State)
  328.     { Forbid();
  329.       if ((Info_Port = GetMsg( Data_Port)) == NULL)
  330.       { DeletePort( Data_Port); Permit(); return FALSE; }
  331.       PutMsg( Data_Port, Info_Port);
  332.       Permit();
  333.     }
  334.     else WaitPort( Data_Port);
  335.     break;
  336.       }
  337.  
  338.       /* Check the format of the paper */
  339.       Temp_Opts = (Status.Opts_State ^ Temp_File->File_Opts);
  340.       if (Temp_Opts & Flag_Test)
  341.       { if (Dest_File != NULL) { fclose( Dest_File); Dest_File = NULL; }
  342.     Status.Prog_State = Page_State;
  343.     WaitPort( Data_Port);
  344.     break;
  345.       }
  346.  
  347.       /* Request access to the printer */
  348.       if ((Dest_File                 == NULL) &&
  349.       ((Dest_File = fopen( "PRT:", "w")) == NULL) )
  350.       { Status.Prog_State = Open_State;
  351.     Delay( 5L * TICKS_PER_SECOND);
  352.     break;
  353.       }
  354. ^L
  355.       /* Request access to the data file */
  356.       From_File = fopen( Status.File_Print->File_Name, "r");
  357.       if (From_File == NULL)
  358.       { Status.File_Print->File_Copy = 0;
  359.     Status.Prog_State = Wait_State;
  360.  
  361.     Spool_File = fopen( Spool_Logs, "a");
  362.     if (Spool_File == NULL) Spool_File = stderr;
  363.     fprintf( Spool_File, OPEN, Status.File_Print->File_Name);
  364.     if (Spool_File != stderr) fclose( Spool_File);
  365.     break;
  366.       }
  367.  
  368.       /* Initialize all control variables */
  369.       Status.Opts_State = Status.File_Print->File_Opts;
  370.       Status.Char_Print = Status.Line_Print = Status.Page_Print = 0;
  371.  
  372.       Line_Limit = Page_Used[Opts_Used(Status.Opts_State)];
  373.       Line_Count = Line_Limit;
  374.  
  375.       /* Initialize the printer */
  376.       fprintf( Dest_File,
  377.     "\033c\033#1\033#5\033[%cw\033[1;%ds\033[%cz\033[%dt\033[%c\"z",
  378.     Line_Code[Status.Opts_State & Line_Density],
  379.     Line_Size[Status.Opts_State & Flag_Line],
  380.     (Status.Opts_State & Page_Density ? '0' : '1'),
  381.     Page_Size[Opts_Page(Status.Opts_State)],
  382.     (Status.File_Print->File_Flag & Flag_Quality ? '2' : '1'));
  383.     
  384.       /* Start printing the specified file */
  385.       Status.Prog_State = Exec_State;
  386.       Char_Saved    = fgetc( From_File);
  387. ^L
  388.     case Exec_State : case File_State :
  389.       /* Print the file one line at a time */
  390.       if (Char_Saved == EOF)
  391.       { Stop_Printing( COPY);
  392.     --Status.File_Print->File_Copy;
  393.     break;
  394.       }
  395.  
  396.       /* Deal with form feed characters */
  397.       if (Char_Saved == '\f')
  398.       { if (Line_Count != Line_Limit)
  399.     { putc( '\f', Dest_File); Line_Count = Line_Limit; }
  400.     Next_Char();
  401.     break;
  402.       }
  403.  
  404.       /* Deal with page counters and headers */
  405.       if (Line_Count == Line_Limit)
  406.       { ++Status.Page_Print; Line_Count = 0;
  407.     if (Status.Opts_State & Opts_Headers)
  408.     { fprintf( Dest_File, "%-20.20s    %-42.42s    Page %3ld\n\n\n",
  409.            Status.File_Print->File_Date,
  410.            Status.File_Print->File_Name,
  411.            Status.Page_Print);
  412.       Line_Count = 3;
  413.       } }
  414.  
  415.       /* Time to print the line */
  416.       ++Status.Line_Print; ++Line_Count;
  417.       if (Status.Opts_State & Opts_Numbers)
  418.     fprintf( Dest_File, "%6ld: ", Status.Line_Print);
  419.       while ((Char_Saved !=  EOF) &&
  420.          (Char_Saved != '\n') &&
  421.          (Char_Saved != '\f') )
  422.       { putc( Char_Saved, Dest_File); Next_Char(); }
  423.       if (Char_Saved == '\n') Next_Char();
  424.       fputs( (Line_Count == Line_Limit ? "\n\f" : "\n"), Dest_File);
  425.       break;
  426.  
  427.     case Susp_State :
  428.       /* Wait for new comamnds */
  429.       if (Dest_File != NULL) { fclose( Dest_File); Dest_File = NULL; }
  430.     case Stop_State :
  431.       WaitPort( Data_Port);
  432.       break;
  433.   }
  434.   return TRUE;
  435. }
  436. ^L
  437. /*****************************/
  438. /* This is the Spool program */
  439. /*****************************/
  440.  
  441. public    void    main( argc, argv)
  442. /*******************************/
  443. int     argc;
  444. char    *argv[];
  445.  
  446. { extern struct MsgPort *FindPort(), *CreatePort();
  447.   extern FILE        *fopen();
  448.  
  449.   fprintf( stderr, HEAD);
  450.   if (FindPort( SPOOLNAME) != NULL)
  451.   { fprintf( stderr, EXEC); exit( 1); }
  452.  
  453.   if (argc > 1) Spool_Logs = argv[1];
  454.   if ((Spool_File = fopen( Spool_Logs, "a")) == NULL)
  455.   { fprintf( stderr, LOGS, Spool_Logs); exit(1); }
  456.   fprintf( Spool_File, HEAD);
  457.   fclose( Spool_File);
  458.  
  459.   if ((Data_Port = CreatePort( SPOOLNAME, 0L)) == NULL)
  460.   { fprintf( stderr, INIT); exit( 1); }
  461.   Default_Values();
  462.  
  463.   do Exec_Print();
  464.   while (Exec_Spool());
  465. }
  466.