home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d174 / print1.2.lha / Print1.2 / Print.c < prev    next >
C/C++ Source or Header  |  1989-02-04  |  22KB  |  1,070 lines

  1. /**
  2. *
  3. * print
  4. *
  5. * CLI PRINT command
  6. * Version 1.2
  7. *
  8. * (c) 1988 by John F. Zacharias, All rights reserved
  9. *
  10. * Permission granted for use by non-profit, non-commercial user
  11. * provided above copyright notice and these restrictions are
  12. * included with any copy.  Any for profit use or use by a commericial
  13. * enterprise is strictly forbidden unless proper arrangements are
  14. * made with the author.
  15. *
  16. * This program is intended to run only under CLI.  The CLI command line
  17. * syntax is:
  18. *
  19. * print {-i} file-name {...file-name} {rp=n} {OPT H | N | S}
  20. *
  21. * parameters:
  22. *
  23. *       -i         perform printer initialization (sets printer to Preferences
  24. *           specifications).
  25. *
  26. *    file-name  the name of the file or directory to print.
  27. *
  28. *    rp=       start printing at page number n.  This allows you to skip
  29. *           over a portion of a printout they may have previously
  30. *           been printed.  The "rp=" applies ONLY to the filename that
  31. *           precedes it.
  32. *
  33. *    OPT H       Printout is in hexadecimal.
  34. *
  35. *    OPT N       Sequence number each line of the printout.
  36. *
  37. *    OPT S       Show all control characters and printer ESC sequences.
  38. *
  39. * NOTE: multiple OPT operands can be given - any one option operand will
  40. *       apply to all files that preceed that option operand.  As an example:
  41. *
  42. *       print file-1 opt h file-2 opt n file 3
  43. *
  44. *       will print file-1 in hex, file-2 with sequence numbers, and file-3
  45. *       without sequence numbers.
  46. *
  47. * MODIFIED FOR WORKBENCH 1.3
  48. *
  49. * NOTICE: This program can not be used as a 'resident' command.  It is not
  50. *         re-entrant.
  51. *
  52. * THIS FILE IS WRITTEN FOR LATTICE V. 4.01
  53. *
  54. **/
  55.  
  56. #include <time.h>
  57. #include <stdio.h>
  58. #include <intuition/intuition.h>
  59. #include <dos.h>
  60. #include <ctype.h>
  61.  
  62. #define    MAXFILES  25             /* change if different # files wanted */
  63. #define TOP_MARGIN 4                 /* number lines at top of page */
  64. #define DIRLNSZ 76             /* size of full directory line */
  65. #define DIRHD_LINES 14               /* body = page size minus this (files) */
  66. #define FILHD_LINES 12               /* body = page size minus this (dir) */
  67. #define EJECT -1             /* Eject code returned by GET_LINE() */
  68. #define PARLINE -2             /* Partial line code rtrnd by GET_LINE() */
  69.  
  70.  
  71. struct Dir_Entry {
  72.     struct Dir_Entry *de_left;
  73.     struct Dir_Entry *de_right;
  74.     struct Dir_Entry *de_root;
  75.     long de_Type;
  76.     long de_Protect;
  77.     long de_Size;
  78.     long de_Blocks;
  79.     struct DateStamp de_Date;
  80.     char de_Name[32];
  81.     };                 /* structure used to define each 
  82.                         directory entry */
  83.  
  84. extern long IntuitionBase;           /* global intuition base variable */
  85. extern char *_ProgramName;           /* Program Name */
  86. extern int (*_ONBREAK)();         /* ONBREAK routine */
  87.  
  88. struct Preferences Prefs;            /* for looking at preferences */
  89. struct InfoData DiskInfo;            /* for looking at disk volume info */
  90. struct FileInfoBlock Fib;            /* for looking at File Information Block */
  91. struct DateStamp FileDate;         /* for looking at file date/time */    
  92. struct DateStamp SysDate;         /* for looking at system date/time */
  93.  
  94. static struct IntuiText Text1 = {-1,-1,
  95.             0,
  96.             16,14,
  97.             NULL,
  98.             "** Abort Current Print-Out? **",
  99.             NULL};
  100.  
  101. static struct IntuiText Text2 = {-1,-1,
  102.             0,
  103.             16,14,
  104.             NULL,
  105.             "** Go on to next File? **",
  106.             NULL};
  107.  
  108. static struct IntuiText NameText = {-1,-1,
  109.             0,
  110.             6,4,
  111.             NULL,
  112.             NULL,
  113.             NULL};
  114.  
  115. static struct IntuiText NoText = {-1,-1,
  116.             0,
  117.             8,4,
  118.             NULL,
  119.             "NO",
  120.             NULL};
  121.  
  122. static struct IntuiText YesText = {-1,-1,
  123.             0,
  124.             8,4,
  125.             NULL,
  126.             "YES",
  127.             NULL};
  128.  
  129.  
  130. /* Global Variables - accessed by more than one function */
  131.  
  132. long FileProtect, FileSize, FileBlocks;
  133.  
  134. FILE *Prt;
  135. FILE *Inp;
  136.  
  137. unsigned int SeqNo;
  138. int lmargn, lnsz, pgsz, lncnt, Abort_Print, nfiles;
  139. int nmbrfiles = 0;
  140. int page_no = 0;
  141. int init_prtr = 0;
  142. char heading_buf[132];
  143.  
  144. char FullPath[160];
  145. char FileComments[80];
  146. char FileName[MAXFILES][160];
  147. char Option[MAXFILES];
  148.  
  149. #define HEX       'h'
  150. #define LINENOS   'n'
  151. #define SHOW      's'
  152.  
  153. int StartPage[MAXFILES];
  154. int ResetPage[MAXFILES];
  155. int PrintType[MAXFILES];
  156.  
  157. #define HAVE_FILE   -1
  158. #define HAVE_DIR    1
  159.  
  160.  
  161. void main(argc, argv)      
  162.  
  163. int argc;
  164. char *argv[];
  165.  
  166. {
  167.     int PRTBRK();
  168.  
  169.     printf("PRINT v 1.2\n");
  170.     printf("Copyright (c) 1988 by John F. Zacharias, All Rights Reserved\n");
  171.  
  172.     IntuitionBase = OpenLibrary("intuition.library",0);
  173.     if (IntuitionBase == NULL) {
  174.         printf("Can't open Intuition Library\n");
  175.         exit(1);
  176.         }
  177.  
  178.     GetPrefs(&Prefs,sizeof(Prefs));
  179.     
  180.     lmargn = Prefs.PrintLeftMargin;
  181.     lnsz = Prefs.PrintRightMargin-Prefs.PrintLeftMargin+1;
  182.     pgsz = Prefs.PaperLength;
  183.  
  184.     getargs(argc,argv);
  185. /*    showargs();             /* TEMPORARY for testing */
  186.  
  187.     if ((Prt = fopen("PRT:","w")) == NULL) {
  188.         printf(">> Printer can't be opened <<\n");
  189.         exit(1);
  190.         }
  191.  
  192.     if (init_prtr) fputs("\x1b#1",Prt);
  193.  
  194.     _ONBREAK = PRTBRK;    /* Set up break processing routine */
  195.  
  196.     for(nfiles=1; nfiles <= nmbrfiles; nfiles++){
  197.         Abort_Print = 0;
  198.         if (PrintType[nfiles] == HAVE_FILE) print_files(nfiles);
  199.         if (PrintType[nfiles] == HAVE_DIR) print_directory(nfiles);
  200.         }
  201.  
  202.     fclose(Prt);
  203.     rbrk();
  204.     exit(0);
  205. }
  206. getargs(argc,argv)
  207.  
  208. int argc;
  209. char *argv[];
  210.  
  211. {
  212.     int ftype;
  213.     int argn = 0;
  214.     int n = 1;
  215.     char opt;
  216.  
  217.     if (argc < 2)
  218.         printf("ERROR: no arguements given\n");
  219.  
  220.     while(argc-- > 1) {    
  221.         argn++;
  222.         if (stricmp(argv[argn],"-i") == 0) {
  223.             init_prtr = 1;
  224.             continue;
  225.             }
  226.         if (strnicmp(argv[argn],"rp=",3) == 0) {
  227.             if (nmbrfiles == 0) {
  228.                 printf("ERROR: Starting page must follow filename\n");
  229.                 exit(1);
  230.                 }
  231.             if (sscanf(argv[argn],"rp=%d",
  232.                 &StartPage[nmbrfiles]) != 1) {
  233.                 printf("ERROR: Incorrect starting page number\n");
  234.                 exit(1);
  235.                 }
  236.             continue;
  237.             }
  238.         if (stricmp(argv[argn],"opt") == 0) {
  239.             if (--argc < 1) {
  240.                 printf("ERROR: No option given\n");
  241.                 exit(1);
  242.                 }
  243.             if (strlen(argv[++argn]) > 1) {
  244.                 printf("ERROR: Option '%c' invalid combination\n",
  245.                     argv[argn]);
  246.                 exit(1);
  247.                 }
  248.             strlwr(argv[argn]);
  249.             opt = *argv[argn];
  250.             if (((opt == HEX) || (opt == LINENOS) || (opt == SHOW))
  251.                     == 0) {
  252.                 printf("ERROR: '%c' is an invalid option\n",
  253.                     opt);
  254.                 exit(1);
  255.                 }
  256.             for(;n <= nmbrfiles; n++)
  257.                 Option[n] = opt;
  258.             continue;
  259.             }
  260.  
  261.          ftype = getfa(argv[argn]);
  262.  
  263.         if (ftype != NULL) {
  264.             nmbrfiles++;
  265.             strcpy(FileName[nmbrfiles],argv[argn]);
  266.             PrintType[nmbrfiles] = ftype;
  267.             StartPage[nmbrfiles] = 0;
  268.             }
  269.         else printf("%s does not exist\n",argv[argn]);
  270.         }
  271.     return(0);
  272. }
  273.  
  274.  
  275. print_files(fileno)
  276.  
  277. int fileno;
  278.  
  279. {
  280.     int lnend, newline, textsz, mode;
  281.  
  282. /*
  283. *    mode = 0 (text display), 1 (hex display)
  284. *    newline = 0 (continuation line), 1 (start of line)
  285. *    lnend = 0 (end of file)
  286. *        + (size of line if line feed encountered)
  287. *        -1 (EJECT encountered - TEXT only!)
  288. *        -2 (line size reached, no line feed - TEXT only!)
  289. *
  290. */
  291.  
  292.     char inbuf[182], date[50];
  293.  
  294.     page_no = 1;
  295.     set_header(heading_buf,fileno);
  296.     lncnt = pgsz - FILHD_LINES;
  297.     if (page_no >= StartPage[fileno]) {
  298.         skip_lines(TOP_MARGIN);
  299.         fprintf(Prt,heading_buf,page_no);
  300.         ConvertDate(&FileDate,date,1);
  301.         fprintf(Prt,"\nThe file was last updated on %s\n",date);
  302.         fprintf(Prt,"The file size is %d bytes (%d blocks)\n",FileSize,FileBlocks);
  303.         fprintf(Prt,"File protection status: ");
  304.         Set_Protect(FileProtect);
  305.         fputs(" allowed\n",Prt);
  306.         fprintf(Prt,"File comments are: %s\n",FileComments);
  307.         DateStamp(&SysDate);
  308.         ConvertDate(&SysDate,date,1);
  309.         fprintf(Prt,"\nThis file is being printed on %s\n",date);
  310.         line_across();
  311.         skip_lines(2);
  312.         }
  313.  
  314.     lncnt = lncnt - 8;
  315.  
  316.     if ((Inp = fopen(FileName[fileno],"r")) == NULL) {
  317.         printf("Cannot open file %s\n",FileName[fileno]);
  318.         fprintf(Prt,"CANNOT OPEN FILE TO PRINT\n\f");
  319.         return(0);
  320.         }
  321.  
  322.     mode = 0;
  323.     newline = 1;        /* indicate start of new line */
  324.     SeqNo = 0;
  325.     textsz = lnsz;
  326.  
  327.     if (Option[fileno] == LINENOS) textsz = lnsz-7;
  328.  
  329.     if (Option[fileno] == HEX) {
  330.         textsz = 16;
  331.         mode = 1;
  332.         }
  333.  
  334.     while ((lnend = get_line(inbuf,textsz,mode,Option[fileno]))) {
  335.         if (Abort_Print) {
  336.             fprintf(Prt,"\n>>> PRINTOUT ABORTED WITH CONTROL C <<<\n");
  337.             break;
  338.             }
  339.         if ((lnend == EJECT) && (*inbuf == 0)) {
  340.             newline = 1;
  341.             lncnt = 0;
  342.             continue;
  343.             }
  344.         if (newline || (lncnt < -3)) {
  345.             if (lncnt <= 0) {
  346.                 if (page_no >= StartPage[fileno])
  347.                     putc('\f',Prt);
  348.                 if (++page_no >= StartPage[fileno]) {
  349.                     skip_lines(TOP_MARGIN);
  350.                     fprintf(Prt,heading_buf,page_no);
  351.                     line_across();
  352.                     skip_lines(2);
  353.                     }
  354.                 lncnt = pgsz - FILHD_LINES;
  355.                 }
  356.             }
  357.         if (mode) newline = lnend-1;
  358.         print_line(inbuf,newline,fileno);
  359.         lncnt--;
  360.         newline = 1;    /* indicate start of line for next line */ 
  361.         if (lnend == PARLINE) newline = 0;    /* next not start */
  362.         if (lnend == EJECT) lncnt = 0;
  363.         }
  364.  
  365.     putc('\f',Prt);
  366.     fclose(Inp);
  367.     return(0);
  368. }
  369.  
  370. Set_Protect(fp)
  371.  
  372. long fp;
  373.  
  374. {
  375.     if (fp & 128) putc('-',Prt);
  376.          else putc('-',Prt);
  377.     if (fp & 64) putc('s',Prt);
  378.          else putc('-',Prt);
  379.     if (fp & 32) putc('p',Prt);
  380.          else putc('-',Prt);
  381.     if (fp & 16) putc('a',Prt);
  382.          else putc('-',Prt);
  383.     if (fp & 8) putc('-',Prt);
  384.          else putc('r',Prt);
  385.     if (fp & 4) putc('-',Prt);
  386.          else putc('w',Prt);
  387.     if (fp & 2) putc('-',Prt);
  388.          else putc('e',Prt);
  389.     if (fp & 1) putc('-',Prt);
  390.          else putc('d',Prt);
  391.     return(0);
  392. }
  393.  
  394. set_header(buf,fileno)
  395.  
  396. char *buf;
  397. int fileno;
  398.  
  399. {
  400.     char l,*p;
  401.  
  402.     get_path(fileno);
  403.     p = stpcpy(buf,"FILE: ");
  404.     if (PrintType[fileno] == HAVE_DIR) {
  405.         p = stpcpy(buf,"DIRECTORY: ");
  406.         }
  407.     l = strlen(FullPath);
  408.     p = p + stccpy(p,FullPath,lnsz-15) - 1;
  409.     while(p < buf+lnsz-8)
  410.         *p++=' ';
  411.     stpcpy(p,"Page %3d\n");
  412.     return(0);
  413. }
  414.  
  415. get_path(fileno)
  416.  
  417. int fileno;
  418.  
  419. {
  420.     long file_lock,new_lock;
  421.     char *p;
  422.  
  423.     file_lock = Lock(FileName[fileno],ACCESS_READ);
  424.  
  425.     if (file_lock == NULL) {
  426.         printf("Can't get File Lock for %s\n",FileName[fileno]);
  427.         exit(1);
  428.         }
  429.  
  430.     if (Info(file_lock,&DiskInfo) == NULL) {
  431.         printf("Cannot get volume information for %s\n",
  432.             FileName[fileno]);
  433.         exit(1);
  434.         }
  435.  
  436.     if (Examine(file_lock,&Fib) == NULL) {
  437.         printf("Cannot get FIB for %s\n",FileName[fileno]);
  438.         exit(1);
  439.         }
  440.  
  441.     strcpy(FullPath,Fib.fib_FileName);
  442.     FileProtect = Fib.fib_Protection;
  443.     FileSize = Fib.fib_Size;
  444.     FileBlocks = Fib.fib_NumBlocks;
  445.  
  446.     FileDate.ds_Days = Fib.fib_Date.ds_Days;
  447.     FileDate.ds_Minute = Fib.fib_Date.ds_Minute;
  448.     FileDate.ds_Tick = Fib.fib_Date.ds_Tick;
  449.  
  450.     strcpy(FileComments,Fib.fib_Comment);
  451.  
  452.     while(new_lock = ParentDir(file_lock)) {
  453.  
  454.         if (Examine(new_lock,&Fib) == NULL) {
  455.             printf("Cannot get parent FIB for %s\n",FullPath);
  456.             return(0);
  457.             }
  458.  
  459.         strins(FullPath,"/");
  460.         strins(FullPath,Fib.fib_FileName);
  461.  
  462.         UnLock(file_lock);
  463.         file_lock = new_lock;
  464.         }
  465.  
  466.     p = strchr(FullPath,'/');
  467.     if (p) {
  468.         *p = ':';
  469.         return(0);
  470.         }
  471.  
  472.     strcat(FullPath,":");
  473.     return(0);
  474. }
  475.  
  476. ConvertDate(Date,datebuf,mode)
  477.  
  478. struct DateStamp *Date;
  479. int mode;
  480. char *datebuf;
  481.  
  482. {
  483.  
  484.     long t;
  485.     int i, weekday, day, month, year, dmode;
  486.     int tmode = 6;
  487.  
  488.     static int month_day[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
  489.  
  490.     char date_table[3];
  491.     char time_table[4];
  492.     char *p;
  493.  
  494.     static char *day_week[] = {
  495.         "Sunday, ",
  496.         "Monday, ",
  497.         "Tuesday, ",
  498.         "Wednesday, ",
  499.         "Thursday, ",
  500.         "Friday, ",
  501.         "Saturday, "
  502.     };
  503.  
  504.     i = 2;
  505.     t = Date->ds_Days;
  506.     year = 0;
  507.     month_day[2] = 29;
  508.     weekday = t % 7;
  509.  
  510.     while(1) {
  511.         while (i<4) {
  512.             if (t<365) {
  513.                 month_day[2] = 28;
  514.                 break;
  515.                 }
  516.             t = t - 365;
  517.             year++;
  518.             i++;
  519.             if (year == 2100) i = 0;
  520.             }
  521.  
  522.         if (t<366) break;
  523.         t = t - 366;
  524.         year++;
  525.         i = 1;
  526.         }
  527.      
  528.     i = 0;
  529.     month = 0;
  530.  
  531.     while (t >= 0) {
  532.         day = t + 1;
  533.         t = t - month_day[++month];
  534.         }
  535.  
  536.     date_table[0] = year;
  537.     date_table[1] = month;
  538.     date_table[2] = day;
  539.     
  540.     time_table[0] = Date->ds_Minute / 60;
  541.     time_table[1] = Date->ds_Minute % 60;
  542.     time_table[2] = Date->ds_Tick / TICKS_PER_SECOND;
  543.     time_table[3] = 0;
  544.  
  545.     p = datebuf;
  546. /*    dmode = 2;
  547.     if (mode) dmode = 5;    * this was required for stpdate */
  548.     dmode = mode;
  549.     if (mode) p = stpcpy(p,day_week[weekday]);
  550.     p = astpdate(p,dmode,date_table);    /* replaces stpdate */
  551.     if (mode) p = stpcpy(p," at ");
  552.     else p = stpcpy(p," ");
  553.     stptime(p,tmode,time_table);
  554.     return(0);
  555. }
  556.  
  557. skip_lines(nolines)
  558.  
  559. int nolines;
  560.  
  561. {
  562.     while (nolines--) putc('\n',Prt);
  563.     return(0);
  564. }
  565.  
  566. print_line(inbuf,lnstrt,fn)
  567.  
  568. int fn, lnstrt;
  569. char *inbuf;
  570.  
  571. {
  572.  
  573.     if (Option[fn] == LINENOS) {
  574.         if (lnstrt) {
  575.             SeqNo++;
  576.             if (page_no >= StartPage[fn])
  577.                 fprintf(Prt,"%5d: %s\n",SeqNo,inbuf);
  578.             return(1);
  579.             }
  580.         else {
  581.              if (page_no >= StartPage[fn])
  582.                 fprintf(Prt,"       %s\n",inbuf);
  583.             return(1);
  584.             }
  585.         }
  586.     if (page_no < StartPage[fn]) return(1);
  587.  
  588.     if (Option[fn] == HEX) {
  589.         print_hexline(inbuf,lnstrt);
  590.         return(1);
  591.         }
  592.  
  593.     fprintf(Prt,"%s\n",inbuf);
  594.     return(1);
  595. }
  596.     
  597. line_across()
  598.  
  599. {
  600.     int i;
  601.  
  602.     i = 10;
  603.     while (i--) fputc(' ',Prt);
  604.     i = lnsz - 20;
  605.     while (i--) fputc('-',Prt);
  606.     i = 10;
  607.     while (i--) fputc(' ',Prt);
  608.     fputc('\n',Prt);
  609.     return(0);
  610. }
  611. get_line(buf,sz,mode,opt)
  612.  
  613. char *buf;
  614. int sz, mode;
  615. char opt;
  616.  
  617. /*    Mode is 0 for text display and 1 for hex display.
  618. *
  619. *    Normally, this routine returns the size of the text placed in
  620. *    the buffer.  On text displays this occurs only when a line
  621. *    feed ($0A) is encountered.
  622. *
  623. *    If the "end of file" occurs a zero is returned.
  624. *
  625. *    The following applies to text displays only:
  626. *
  627. *    This routine returns EJECT (-1) if a line form ($0C) appears
  628. *    in the text even if the buffer has data in it.
  629. *
  630. *    This routine returns PARLINE (-2) if the line size passed as
  631. *    "sz" is reached before a line feed is encountered.
  632. *
  633. *    Binary zeros in text are ignored.
  634. *
  635. *    If a carriage return ($0D) is encountered it is ignored if a
  636. *    line feed is in the same sequence, otherwise the carriage
  637. *    return is treated as a line feed.
  638. *
  639. *    All other control sequences (ASCII 0 through 31) are displayed
  640. *    with a ^ followed with a capitol character representing the
  641. *    ASCII position.
  642. *
  643. */
  644.    
  645. {
  646.     int l = 0;
  647.     int cr = 0;
  648.     int c;
  649.  
  650.     while (l < sz) {
  651.         if ((c = fgetc(Inp)) == EOF) {
  652.             *buf = 0;
  653.             if (l == 0) return(0);
  654.             ungetc(c,Inp);
  655.             return(l+1);
  656.             }
  657.         if (mode == 0) {
  658.             if (c > 127) c = c-128;
  659.             if (c == '\n') {
  660.                 *buf = 0;
  661.                 return(l+1);
  662.                 }
  663.             if (opt == SHOW) {
  664.                 if (c < 32) {
  665.                     if (l > sz-3) break;
  666.                     *buf++ = '^';
  667.                     l++;
  668.                     c = c + 64;
  669.                     }
  670.                 }
  671.             if (c == '\f') {
  672.                 *buf = 0;
  673.                 if ((c = fgetc(Inp)) != '\n')
  674.                     ungetc(c,Inp);
  675.                 return(EJECT);
  676.                 }
  677.             if (c == 13) {
  678.                 cr = 1;
  679.                 continue;
  680.                 }
  681.             if (cr && l) {
  682.                 *buf = 0;
  683.                 ungetc(c,Inp);
  684.                 return(l+1);
  685.                 }
  686.             cr = 0;
  687.             if (c == 8) {
  688.                 if (l == 0) continue;
  689.                 l--;
  690.                 *buf-- = 0;
  691.                 continue;
  692.                 }
  693.             if (c == 27) {
  694.                 if (byp_esc() == 0) {
  695.                     *buf = 0;
  696.                     if (l == 0) return(0);
  697.                     ungetc(c,Inp);
  698.                     return(l+1);
  699.                     }
  700.                 }
  701.             if (c == '\t') {
  702.                 while (++l %8) *buf++ = ' ';
  703.                 *buf++ = ' ';
  704.                 continue;
  705.                 }
  706.             if (c < 32) continue;
  707.             }
  708.         l++;
  709.         *buf++ = c;
  710.         }
  711.     if (mode == 1) return(l+1);
  712.     *buf = 0;
  713.     if ((c = fgetc(Inp)) == '\n') return(l+1);
  714.     ungetc(c,Inp);
  715.     return(PARLINE);
  716. }
  717.  
  718. print_hexline(inbuf,ln)
  719.  
  720. int ln;
  721. unsigned char *inbuf;
  722.  
  723. {
  724.     unsigned int hexbuf[8], i;
  725.     unsigned char c;
  726.  
  727.     for(i = 0; i < ln; i+=2) 
  728.         hexbuf[i/2] = (*(inbuf+i))*256 + (*(inbuf+i+1));
  729.  
  730.     fprintf(Prt,"  %06X:  ",SeqNo);
  731.     for (i=0; i < ln/2; i++)
  732.         fprintf(Prt,"%04X ",hexbuf[i]);
  733.  
  734.     if (ln%2)
  735.         fprintf(Prt,"%02X   ",hexbuf[ln/2]/256);
  736.  
  737.     for (i = (ln/2)+(ln%2); i < 8; i++)
  738.         fprintf(Prt,"     ");
  739.  
  740.     fprintf(Prt, "  ");
  741.     for (i=0; i < ln; i++) {
  742.         c = *inbuf++;
  743.         c = toascii(c);            /* removes 2-7 high zone */
  744.         if (c == '\x7f') c = '.';
  745.         if (c == '\n') c = '>';
  746.         if (c < 32) c = '.';
  747.         fputc(c,Prt);
  748.         }
  749.     fputc('\n',Prt);
  750.     SeqNo = SeqNo + ln;
  751.     return(0);
  752. }
  753.  
  754. print_directory(fn)
  755.  
  756. int fn;
  757.  
  758. {
  759.     struct Dir_Entry *root, *get_dir_base();
  760.     int dir_no = 0;
  761.     int percent, free, fbytes;
  762.     char date[50], vol_name[30];
  763.  
  764.     root = NULL;
  765.     root = get_dir_base(FileName[fn],root);
  766.  
  767.     page_no = 1;
  768.     set_header(heading_buf,fn);
  769.     lncnt = pgsz - DIRHD_LINES;
  770.     if (page_no >= StartPage[fn]) {
  771.         skip_lines(TOP_MARGIN);
  772.         fprintf(Prt,heading_buf,page_no);
  773.         ConvertDate(&FileDate,date,1);
  774.         fprintf(Prt,"\nThis directory was last updated on %s\n",date);
  775.         stptok(FullPath,vol_name,sizeof(vol_name),":");
  776.         fprintf(Prt,"The Volume containing the directory is: %s\n", vol_name);
  777.           fprintf(Prt,"The Volume contains %d blocks of %d bytes each.\n",
  778.             DiskInfo.id_NumBlocks, DiskInfo.id_BytesPerBlock);
  779.         percent = 100 * DiskInfo.id_NumBlocksUsed / DiskInfo.id_NumBlocks;
  780.         fprintf(Prt,"The number of blocks currently is use are %d (%d%%).\n",
  781.             DiskInfo.id_NumBlocksUsed, percent);
  782.         free = DiskInfo.id_NumBlocks - DiskInfo.id_NumBlocksUsed;
  783.         fbytes = free * DiskInfo.id_BytesPerBlock;
  784.         fprintf(Prt,"The number of blocks available are %d (%d bytes).\n",
  785.             free, fbytes);
  786.         fprintf(Prt,"The number of soft errors are %d.\n\n",
  787.             DiskInfo.id_NumSoftErrors);
  788.         DateStamp(&SysDate);
  789.         ConvertDate(&SysDate,date,1);
  790.         fprintf(Prt,"\nThis directory is being printed on %s\n",date);
  791.         print_dir_head_1();
  792.         }
  793.     lncnt = lncnt - 11;
  794.  
  795.     print_dir_line(root,dir_no,fn);
  796.  
  797.     putc('\f',Prt);
  798.  
  799.     return(0);
  800. }
  801.  
  802. struct Dir_Entry *get_dir_base(name,root)
  803.  
  804. char *name;
  805. struct Dir_Entry *root;
  806.  
  807. {
  808.     struct Dir_Entry *get_file_info();
  809.     struct FileInfoBlock *Dib;
  810.  
  811.     long dir_lock, old_lock;
  812.  
  813.     Dib = (struct FileInfoBlock *)malloc(sizeof(struct FileInfoBlock));
  814.     if (!Dib) {
  815.         printf("ERROR: Out of Memory allocating directory FIB\n");
  816.         exit(1);
  817.         }
  818.  
  819.     dir_lock = Lock(name,ACCESS_READ);
  820.  
  821.     if (dir_lock == NULL) {
  822.         printf("Can't get file lock for directory %s\n",name);
  823.         exit(1);
  824.         }
  825.  
  826.     old_lock = CurrentDir(dir_lock);
  827.  
  828.     if (Examine(dir_lock,Dib) == NULL) {
  829.         printf("Can't get FIB for directory %s\n",name);
  830.         exit(1);
  831.         }
  832.  
  833.     while(ExNext (dir_lock,Dib)) { 
  834.         root = get_file_info(root,Dib);
  835.         if (Abort_Print) break;
  836.         }
  837.  
  838.     UnLock(dir_lock);
  839.     CurrentDir(old_lock);
  840.     return(root);
  841. }
  842.  
  843. struct Dir_Entry *get_file_info(p,fb)
  844.  
  845. struct Dir_Entry *p;
  846. struct FileInfoBlock *fb;
  847.  
  848. {
  849.     struct Dir_Entry *get_dir_base();
  850.  
  851.     if (p == NULL) {
  852.         p = (struct Dir_Entry *)malloc(sizeof(struct Dir_Entry));
  853.         if (!p) {
  854.             printf("ERROR: Out of Memory allocating Directories\n");
  855.             exit(1);
  856.             }
  857.         p->de_Type = fb->fib_DirEntryType;
  858.         p->de_Protect = fb->fib_Protection;
  859.         p->de_Size = fb->fib_Size;
  860.         p->de_Blocks = fb->fib_NumBlocks;
  861.         p->de_Date.ds_Days = fb->fib_Date.ds_Days;
  862.         p->de_Date.ds_Minute = fb->fib_Date.ds_Minute;
  863.         p->de_Date.ds_Tick = fb->fib_Date.ds_Tick;
  864.         stccpy(p->de_Name,fb->fib_FileName,30);
  865.         p->de_left = p->de_right = p->de_root = NULL;
  866.  
  867.           if (p->de_Type > 0) 
  868.             p->de_root = get_dir_base(p->de_Name,p->de_root);
  869.  
  870.         return(p);
  871.         }
  872.  
  873.     if (p->de_Type == fb->fib_DirEntryType) {
  874.         if (stricmp (fb->fib_FileName, p->de_Name) < 0)
  875.             p->de_left = get_file_info(p->de_left,fb);
  876.         else
  877.             p->de_right = get_file_info(p->de_right,fb);
  878.         return(p);
  879.         }
  880.  
  881.     if (fb->fib_DirEntryType < 0)
  882.         p->de_left = get_file_info(p->de_left,fb);
  883.     else
  884.         p->de_right = get_file_info(p->de_right,fb);
  885.     return(p);
  886. }
  887.  
  888. print_dir_line(p,n,fileno)
  889.  
  890. struct Dir_Entry *p;
  891. int n;
  892. int fileno;
  893.  
  894. {
  895.     int n1;
  896.     char date[30];
  897.  
  898.     if (Abort_Print) {
  899.         fprintf(Prt,"\n>>> PRINTOUT ABORTED WITH CONTROL C <<<\n");
  900.         return(1);
  901.         }
  902.  
  903.     if (p != NULL) {
  904.         if (print_dir_line(p->de_left, n, fileno)) return(1);
  905.         if (lncnt <= 0) {
  906.             if (page_no >= StartPage[fileno]) putc('\f',Prt);
  907.             if (++page_no >= StartPage[fileno]) {
  908.                 skip_lines(TOP_MARGIN);
  909.                 fprintf(Prt,heading_buf,page_no);
  910.                 print_dir_head_1();
  911.                 }
  912.             lncnt = pgsz - 14;
  913.             }
  914.         else
  915.             {
  916.             if (p->de_Type > 0) {
  917.                 if (page_no >= StartPage[fileno]) line_across();
  918.                 lncnt--;
  919.                 }
  920.             }
  921.         if (page_no >= StartPage[fileno]) {
  922.             fprintf(Prt,"%2d> ", n);
  923.             if (p->de_Type > 0) 
  924.                 fprintf(Prt,"<DIR>");
  925.             else
  926.                 fprintf(Prt,"     ");
  927.             fprintf(Prt,"%30.30s %6d %4d ", p->de_Name, p->de_Size,
  928.                 p->de_Blocks);
  929.             Set_Protect(p->de_Protect);
  930.             ConvertDate(&p->de_Date,date,0);
  931.             }
  932.         if (lnsz < DIRLNSZ+1) {
  933.             if (page_no >= StartPage[fileno]) 
  934.                 fprintf(Prt,"\n    Last Updated On ");
  935.             lncnt--;
  936.             }
  937.         if (page_no >= StartPage[fileno]) fprintf(Prt," %s\n",date);
  938.         lncnt--;
  939.         if (p->de_Type > 0) {
  940.             if (page_no >= StartPage[fileno]) skip_lines(1);
  941.             lncnt--;
  942.             n1 = n + 1;
  943.             if (print_dir_line(p->de_root, n1, fileno)) return(1);
  944.             }
  945.  
  946.         if (print_dir_line(p->de_right, n, fileno)) return(1);
  947.         }
  948.     return(0);
  949. }
  950.  
  951. print_dir_head_1()
  952.  
  953. {
  954.     line_across();
  955.     skip_lines(2);
  956.     fprintf(Prt,"Lvl %35.35s  Bytes Blks","NAME");
  957.     if (lnsz > DIRLNSZ) fprintf(Prt,"      Last Updated On");
  958.     skip_lines(2);
  959.     return(0);
  960. }
  961.  
  962. /*    the following routine is used to replace the Lattice "stpdate"
  963. *    routine because of the incompatibility of base years (Amiga uses
  964. *    1978 while Lattice uses 1980).  Since "print" only uses two of
  965. *    the stpdate modes, these are the only two that are programmed.
  966. */
  967.  
  968. astpdate(p,m,dt)
  969.  
  970. char *p, *dt;
  971. int m;
  972.  
  973. {
  974.     int l, dy, yr, mo;
  975.     static char *month[] = {
  976.         "",
  977.         "January",
  978.         "February",
  979.         "March",
  980.         "April",
  981.         "May",
  982.         "June",
  983.         "July",
  984.         "August",
  985.         "September",
  986.         "October",
  987.         "November",
  988.         "December",
  989.     };
  990.  
  991.     mo = dt[1];
  992.     yr = dt[0];
  993.     dy = dt[2];
  994.  
  995.     if (m) {
  996.         p = stpcpy(p,month[mo]);
  997.         yr = yr+1978;
  998.         l = sprintf(p," %d, %4.4d",dy,yr);
  999.         return (p+l);
  1000.         }
  1001.     else {
  1002.         yr = yr+78;
  1003.         l = sprintf(p,"%2.2d/%02.2d/%02.2d",mo,dy,yr);
  1004.         return (p+l);
  1005.         }
  1006.  
  1007. }
  1008.  
  1009. PRTBRK()
  1010.  
  1011. {
  1012.     NameText.IText = _ProgramName;
  1013.     NameText.NextText = &Text1;
  1014.     if (AutoRequest (NULL, &NameText, &NoText, &YesText, 0, 0, 296, 60)
  1015.         == TRUE) return(0);
  1016.     Abort_Print = 1;
  1017.     if (nfiles >= nmbrfiles) return(0);
  1018.  
  1019.     NameText.NextText = &Text2;
  1020.     if (AutoRequest (NULL, &NameText, &NoText, &YesText, 0, 0, 254, 60)
  1021.         == TRUE) nfiles = nmbrfiles+1;
  1022.     return(0);
  1023. }
  1024.  
  1025. byp_esc()
  1026.  
  1027. {
  1028.     int c;
  1029.  
  1030.     if ((c = fgetc(Inp)) == EOF) return(0);
  1031.     if ((c == '#') || (c == '(')) {
  1032.         if (fgetc(Inp) == EOF) return(0);
  1033.         return(1);
  1034.         }
  1035.     if (c != '[') return(1);
  1036.     while ((c = fgetc(Inp)) != EOF) {
  1037.         if (isalpha(c)) return(1);
  1038.         }
  1039.     return(0);
  1040. }
  1041.  
  1042. /*
  1043. *    The following routine is for testing purposes only.
  1044. *
  1045. *    It is used to display the arguments as they are parsed by
  1046. *    by the 'getargs()' routine. 
  1047. *
  1048. */
  1049.  
  1050. showargs()
  1051.  
  1052. {
  1053.     int nfiles;
  1054.  
  1055.     printf("Initialize Printer = %d\n",init_prtr);
  1056.     for(nfiles=1; nfiles <= nmbrfiles; nfiles++) {
  1057.         printf("\nFile number %d:\n",nfiles);    
  1058.         printf("   FILE NAME: %s\n",FileName[nfiles]);
  1059.         printf("   PRINT OPTION: %c\n",Option[nfiles]);
  1060.         printf("   STARTING PAGE: %d\n",StartPage[nfiles]);
  1061.         printf("   RESET PAGE: %d\n",ResetPage[nfiles]);
  1062.         printf("   PRINT TYPE: ");
  1063.         if (PrintType[nfiles] == HAVE_FILE)
  1064.             printf("HAVE_FILE\n");
  1065.         if (PrintType[nfiles] == HAVE_DIR)
  1066.             printf("HAVE_DIR\n");
  1067.         }
  1068.     return(1);
  1069. }
  1070.