home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 344_01 / lstprt.c < prev    next >
C/C++ Source or Header  |  1990-04-18  |  32KB  |  992 lines

  1. /*        lstprt (c) 1989, 1990 Bryan R Leipper, Reno NV
  2.  
  3. SYNOPSIS: print files to PCL printer with graphics in landscape two up 80 x 69
  4.  
  5. DESCRIPTION: A utility to list files to a printer. Uses HP LJ II+ graphics to
  6.   shade margin areas where headers, footers, and line numbering information is
  7.   printed. Expands tabs and emulates formfeeds. Carriage return, linefeeds, or
  8.   a combination are all taken as new line commands (file is considered an MSDOS
  9.   text file). Up to 69 lines can be printed on each page half. Lines over 80
  10.   characters are wrapped with an indicator in the margin instead of a line
  11.   number.  An index file may be printed if an I=filename runstring option is
  12.   given.  The file listed as an index is printed after all of the listing files
  13.   are printed. Non printable characters can be printed as underlined byte
  14.   values. Pages to print can be selected for two sided copy or destroyed page
  15.   reprint. Manual feed and copies can be specified.
  16.  
  17. USAGE: lstprt optionlist filemask
  18.  
  19. valid options are:
  20.  
  21. Index=index file    (e.g. "I=files.lst")
  22.     An index file is created listing all files in listing with page
  23.     numbers and size information. This will be printed at the end of
  24.     the listing.
  25.  
  26. Height=height of page (1 to 69 lines)    (e.g. "H=66")
  27.     Normally up to 69 lines are printed on each half page. Long lines,
  28.     lines made long by non printable codes, or formfeeds will shorten
  29.     the number of lines printed. This option provides another means to
  30.     reduce the number of lines printed on a half page.
  31.  
  32. Tabs=tab stop (1 to half line length)    (e.g. "T=4")
  33.     Tabs are expanded. The default is an eight character expansion.
  34.     This option allows setting tab expansion to a value that may be more
  35.     suitable to the files being listed (T=4 is good for program listings).
  36.  
  37. Width=width of line (1 to 80 characters)    (e.g. "W=72")
  38.     Up to 80 characters are printed on a line. This option will cause
  39.     automatic line wrap at less than 80 characters.
  40.  
  41. Codes=None, Decimal, Octal, or Hex    (e.g "C=n")
  42.     Non printable codes can be ignored or can be printed as underlined
  43.     numeric codes in hex, decimal, or octal. Decimal is the default. 
  44.     Setting codes=n will ignore codes and print the file as if they did
  45.     not exist. (note that code 26 or control Z is an end of file and
  46.     codes 8, 9, 10, 12, and 13 are interpreted).
  47.  
  48. Label=label    (e.g. "L=This_list_of_files_is_for_documentation")
  49.     Label=footer_description prints a footer in the margin at the bottom
  50.     left of each page. Since blanks are not allowed within an option,
  51.     a multi-word footer must use periods, underscores, or a similar
  52.     character between words instead of a space.
  53.  
  54. Pages=Odd, Even or All pages printed    (e.g. "P=O")
  55.     This option allows printing on two sides of the paper in two runs.
  56.     First select P=O. Then reset the paper and run with P=E to print
  57.     the back sides (even numbered physical pages). If a page get jammed,
  58.     use the STArt and STOp options to reprint only the destroyed pages.
  59.  
  60. STArt=first page to print
  61. STOp=last page to print (1 to whatever)        (e.g. "STA=3 STO=5")
  62.     Sets the physical (or paper) page number limits printed. This is
  63.     intended to allow reprinting selected pages destroyed by paper
  64.     jams or other accident.
  65.  
  66. COPies=number of copies        (e.g. "COP=2")
  67.     Tells the printer to produce multiple copies of each page printed.
  68.  
  69. Feed=Manual feed    (e.g. "f=m")
  70.     Tells the printer to use manual paper feed.
  71.  
  72. OUtput=filename        (e.g. "OUt=output.prn")
  73.     Sets output to a device or file other than the standard printer.
  74.  
  75. FIles=file mask        (e.g. "f=c:\doc\*.txt")
  76.     Explicitly states the files to be printed. This is not required as
  77.     the last runstring argument that cannot be recognized as an option
  78.     is assumed to be the file mask.
  79.  
  80. Query=Y        (e.g. "q=y")
  81.     If set to Yes, the query option will ask if ok to continue after
  82.     examining the runstring. Use this option if there is any doubt
  83.     about the action of the listing command with options.
  84.  
  85. NEwline=decimal ASCII code    (e.g. "NE=31" for Borland Sprint *.spr files)
  86.     Force a new line whenever this character code is found in the file
  87.     being listed. Allows more reasonable printing of word processing
  88.     files.
  89.  
  90. Mask=numvalue (e.g. "M=0x7F")
  91.     A value that is 'AND'ed with each character printed. This is provided
  92.     to facilitate printing of files such as those in Wordstar format.
  93.  
  94. TMargin=top margin lines (0 to 8) (e.g. "TO=3")
  95.     Sets number of lines for top margin. This is to allow for printer
  96.     variations and also adjusting margins as might be needed for hole
  97.     punching.
  98.  
  99. PRinter=init_string    (e.g. "PR=\27\69")
  100.     Do not use HP LJ II printer control codes. Sets H=62 and W=78.
  101.     init_string is a printer setup string. A backslash digits in the
  102.     init_string is converted to a code of the decimal value of the
  103.     digits. For example, to set an IBM printer to 12 character per
  104.     inch spacing, use the option "PRINTER=\27:". To set to draft
  105.     quality print use "PRINTER=\27\73\1" on IBM printers. This option
  106.     disables all margin data including headers, footers, and line
  107.     numbering. Formfeeds are inserted between pages.
  108.  
  109. unknown options or any argument without an = is considered a file mask.
  110. Only enough option name to uniquely identify it is required (in caps above).
  111. If an option is duplicated, the last one in the runstring is used.
  112.  
  113. RETURNS: exits with a value of zero unless error in redirection or argument
  114.  
  115. CAVEATS: The filemask of files to print is a standard DOS filemask.
  116.     Equal signs in the file mask should be avoided as there may be
  117.     confusion with an option name.
  118.  
  119.     =>Only visible files can be found for listing.
  120.     =>non printables near end of line in listing may cause line overflow.
  121.     =>No blanks allowed in any option definition!
  122.  
  123. FILES:    input:        files derived from runstring file mask.
  124.      output:        PRN unless overridden
  125.                     NUL for pages not being printed
  126.     err and status: standard error
  127.     index:            as defined by I= runstring option.
  128.  
  129. SEE ALSO: PC Magazine laserlst.asm utility June 1989
  130.     4PRINT shareware program.
  131.     BLASER laser printer user's/programmer's guide.
  132.  
  133. REGISTRATION: A registration fee of $10 to
  134.     Bryan R Leipper, 714 Terra Court, Reno, NV 89506
  135.     would be appreciated.
  136.  
  137.     Comments, criticisms, and suggestions are welcome.
  138.     There is no warranty of any sort on this software.
  139.     Users should verify suitability before registering license to use.
  140.  
  141. HISTORY
  142.     version A (initial beta test version) released 12 June 1989.
  143.     version B 4 July 1989
  144.         added start, stop, noprt, query, files, output options
  145.         enhanced to allow flexible option names
  146.     version C - 19 April 1990
  147.         generic Microsoft C 5.1 (no additional support needed)
  148.         added MASK and TOPMARGIN options
  149.  
  150. */
  151. /* =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= */
  152.  
  153. #include <dos.h>
  154. #include <string.h>
  155. #include <stdlib.h>
  156. #include <stdio.h>
  157. #include <stddef.h>
  158. #include <ctype.h>
  159. #include <io.h>
  160. #include <fcntl.h>
  161. #include <time.h>
  162. #include <limits.h>
  163.  
  164. /* =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= */
  165.  
  166. #define MAX_PRT_ROWS 69
  167.  
  168. static int page_len = MAX_PRT_ROWS;
  169. static int tab_stop = 8;        /* tabs expansion defaults to 8 */
  170. static int line_len = 80;        /* lines wrap at 80 characters */
  171. static int codes = 'd';            /* decimal, octal, hex, or none */
  172. static int copies = 1;            /* copies of each page */
  173. static int tray = 'n';            /* feed from normal or manual */
  174. static int odd_even = 'a';        /* print odd, even, or all pages */
  175. static int query = FALSE;        /* check if ok if TRUE */
  176. static int noprt = FALSE;        /* printer control if FALSE */
  177. static int nl_char = 257;        /* optional additional newline character */
  178. static int charmask = 0xFF;        /* character AND mask value */
  179. static int topmargin = 3;        /* lines top margin */
  180. static char prt_init[24] = "\f";    /* substitute printer init string */
  181. static unsigned int first_page = 1;
  182. static unsigned int last_page = UINT_MAX;
  183. static char *owner_line= NULL;
  184. static char copyright[] =
  185.  
  186.     "lstprt version C (c) 1990 Bryan R Leipper, Reno NV";
  187.  
  188. FILE *index;
  189.  
  190. /* =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= */
  191. typedef struct _FILE_ENT {
  192.     char *path;
  193.     char *drive;
  194.     char name[_MAX_FNAME];
  195.     char ext[_MAX_EXT];
  196.     char atrb;        /* R A H S V D or default */
  197.     int mo;        /* date and time values are integer values */
  198.     int da;
  199.     int yr;        /* add 1980 for full value */
  200.     int hr;
  201.     int mn;
  202.     long sz;        /* this structure more complete than this particular */
  203. } FILE_ENT;            /* program needs. (designed for file search utility) */
  204. /* =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= */
  205.  
  206. /* printing functions */
  207.  
  208. int init_prtr(FILE_ENT *f);            /* printer and variable setup */
  209. int reset_prtr(FILE_ENT *f);        /* printer reset */
  210. int new_page(FILE_ENT *f);            /* file listing page control */
  211. int new_line(FILE_ENT *f);            /* line to line control */
  212. int prtr(FILE_ENT *f);                /* file output manager */
  213. int make_index(char *idx_name, int idx_len, FILE_ENT *f);
  214.                                     /* print index file listing */
  215.  
  216. /* support functions */
  217.  
  218. char *scan_str(char *dest, char *src);    /* translate escape sequences */
  219. unsigned long lgetbits(unsigned long mask, int low_bit, int mask_len);
  220.                                     /* pull bit value from long integer */
  221. int file_parse(char *inpstr, char *fdrive, char *fpath, char *fname);
  222.  
  223. /* output file */
  224.  
  225. FILE *ofl;
  226.  
  227. /* =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= */
  228. main(int argc, char *argv[], char *envp[]) {
  229. /*
  230.     list file to printer with HP LJ II+ capabilities
  231. */
  232.     struct find_t fdat;
  233.     FILE_ENT fl;
  234.     char *c, *d, *ep
  235.     ,  fpath[_MAX_DIR]
  236.     ,  *mask
  237.     ,  idx_name[_MAX_PATH]
  238.     ,  fdrive[_MAX_DRIVE];
  239.     int i, status, count;
  240.     long tot_size;
  241.     time_t tm_now;
  242.     static unsigned attributes = _A_NORMAL | _A_RDONLY | _A_ARCH;
  243.                     /*    | _A_HIDDEN | _A_SYSTEM | _A_VOLID | _A_SUBDIR; */
  244.  
  245.     static char opt_list[] = {
  246.         "iINDEX "        /* index file" */
  247.         "tTABS "        /* tab stop (1 to half line length)" */
  248.         "hHEIGHT "        /* height of page (1 to %d lines)",MAX_PRT_ROWS  */
  249.         "wWIDTH "        /* Width of line (1 to 80 characters)" */
  250.         "cCODES "        /* no, decimal, octal, or hex" */
  251.         "lLABEL "        /* label" */
  252.         "pPAGES "        /* odd, even or all pages printed\n" */
  253.         "fFEED "        /* manual feed" */
  254.         "aSTART "        /* first page to print */
  255.         "bSTOP "        /* last page to print */
  256.         "oOUTPUT "        /* output file name override */
  257.         "#COPIES "        /* number of copies" */
  258.         "qQUERY "        /* check if ok to continue */
  259.         "dPRINTER "        /* printer (device) control */
  260.         "sFILES "        /* file mask */
  261.         "nNEWLINE "        /* additional newline character */
  262.         "mMASK "        /* character AND mask */
  263.         "uTMARGIN "        /* top margin lines */
  264.     };    /* first of arg name in upper case must be first in list */
  265.  
  266.     static char *opt_desc[] = {
  267.          "\nvalid options are:"
  268.         , "\n\tIndex=index file"
  269.         , "\n\tHeight=height of page (1 to 69 lines)"
  270.         , "\n\tTabs=tab stop (1 to half line length)"
  271.         , "\n\tWidth=width of line (1 to 80 characters)"
  272.         , "\n\tCodes=None, Decimal, Octal, or Hex"
  273.         , "\n\tLabel=label"
  274.         , "\n\tPages=Odd, Even or All pages printed"
  275.         , "\n\tSTArt=first page to print"
  276.         , "\n\tSTOp=last page to print"
  277.         , "\n\tCOPies=number of copies"
  278.         , "\n\tOUtput=output file name override"
  279.         , "\n\tFeed=Manual feed"
  280.         , "\n\tQuery=Yes, query for ok"
  281.         , "\n\tFIles=file mask"
  282.         , "\n\tNEwline=decimal ASCII code also counted as newline (0 - 255)"
  283.         , "\n\tPRINTER=init_string, no printer control except init string"
  284.         , "\n\tMask=numvalue, character AND mask value"
  285.         , "\n\tTMargin=lines for top margin (0 to 8, defaults to 3)"
  286.         , ""
  287.     };
  288.  
  289.     static char dflt_opt[] = "sFILES ";
  290.  
  291. /* prep runstring parameters */
  292.     memset(fpath, EOS, sizeof(fpath));
  293.     memset(fdrive, EOS, sizeof(fdrive));
  294.     memset(idx_name, EOS, sizeof(idx_name));
  295.     memset(&fl, EOS, sizeof(fl));
  296.     index = NULL;
  297.     mask = NULL;
  298.     ofl = stdprn;
  299.     setmode(fileno(ofl), O_TEXT);
  300.  
  301.     if (argc > 0) {
  302.         for (i = 1; i < argc; ++i) {
  303.             d = strchr(argv[i], '=');        /* set for parameter */
  304.             if (d == NULL) {        /* no arg delim, must be a file */
  305.                 d = argv[i];
  306.                 c = dflt_opt + 1;
  307.             } else {
  308.                 *(d++) = EOS;        /* name and param segregated */
  309.                 strupr(argv[i]);
  310.                 c = argv[i];        /* find arg name in list */
  311.                 c = strstr(opt_list, c);
  312.             }
  313.             if (c == NULL) {
  314.                 d = argv[i];    /* must be a file name */
  315.                 c = dflt_opt;
  316.             } else {
  317.                 c -= 1;
  318.             }
  319.             switch (*c) {
  320.                 case 'h' :            /* height */
  321.                     status = atoi(d);
  322.                     if ((status > 0) && (status < 70)) {
  323.                         page_len = status;
  324. fprintf(stderr, "\npage length set to %d lines", page_len);
  325.                     }
  326.                 break;
  327.                 case 't' :            /* tabs */
  328.                     status = atoi(d);
  329.                     if ((status > 0) && (status < (line_len/2))) {
  330.                         tab_stop = status;
  331. fprintf(stderr, "\ntabs set to %d spaces", tab_stop);
  332.                     }
  333.                 break;
  334.                 case 'w' :        /* width */
  335.                     status = atoi(d);
  336.                     if ((status > 0) && (status < 81)) {
  337.                         line_len = status;
  338. fprintf(stderr, "\nline length set to %d chars", line_len);
  339.                     }
  340.                 break;
  341.                 case 'c' :         /* codes handling */
  342.                     if (toupper(*d) == 'N') {
  343.                         codes = 'n';        /* ignore non printables */
  344. fprintf(stderr,"\nnon printing codes being ignored");
  345.                     } else if (toupper(*d) == 'H') {
  346.                         codes = 'h';        /* print values hexadecimal */
  347. fprintf(stderr,"\nnon printing codes printed as hex values");
  348.                     } else if (toupper(*d) == 'O') {
  349.                         codes = 'o';        /* print values octal */
  350. fprintf(stderr,"\nnon printing codes printed as octal values");
  351.                     }    /* default is print codes decimal */
  352.                 break;
  353.                 case 'l' :        /* left side footer */
  354.                     owner_line = d;
  355. fprintf(stderr,"\nleft footer set to %s",owner_line);
  356.                 break;
  357.                 case 'i' :         /* index file */
  358.                     if ((index = fopen(d,"wt")) == NULL) {
  359. fprintf(stderr,"\ncannot open index file %s", &argv[i][2]);
  360.                     } else {
  361.                         strcpy(idx_name, d);
  362. fprintf(stderr,"\nindex file %s ready" ,idx_name);
  363.                     }
  364.                 break;
  365.                 case 'f' :         /* feed override */
  366.                     if (toupper(*d) == 'M') {
  367.                         tray = 'm';
  368. fprintf(stderr, "\nmanual feed specified");
  369.                     }
  370.                 break;
  371.                 case 'q' :         /* query for ok  */
  372.                     if (toupper(*d) == 'Y') {
  373.                         query = TRUE;
  374.                     }
  375.                 break;
  376.                 case 'n' :        /* optional additional newline character */
  377.                     status = atoi(d);
  378.                     if ((status >= 0) && (status < 256)) {
  379.                         nl_char = status;
  380. fprintf(stderr, "\nadditional newline char is %d", nl_char);
  381.                     }
  382.                 break;
  383.                 case 'u' :        /* top margin lines */
  384.                     status = atoi(d);
  385.                     if ((status >= 0) && (status < 8)) {
  386.                         topmargin = status;
  387. fprintf(stderr, "\n topmargin set to %d lines", topmargin);
  388.                     }
  389.                 break;
  390.                 case 'm' :         /* character AND mask */
  391.                     status = (int)strtol(d, &ep, 0);
  392.                     if (status) {
  393.                         charmask = status;
  394. fprintf(stderr, "\ncharacter AND mask set to %d", charmask);
  395.                     }
  396.                 break;
  397.                 case 'd' :         /* no printer codes  */
  398.                     noprt = TRUE;
  399.                     line_len = 78;
  400.                     page_len = 62;
  401.                     if (strlen(d) < sizeof(prt_init)) {
  402.                         scan_str(prt_init, d);
  403. fprintf(stderr, "\nNo printer control codes (+60 lines x 78 char)");
  404.                     } else
  405. fprintf(stderr, "\nInvalid printer init string. Formeed used instead");
  406.                 break;
  407.                 case 'p' :         /* pages to print */
  408.                     if (toupper(*d) == 'O') {
  409.                         odd_even = 'o';
  410. fprintf(stderr, "\nprint odd pages only");
  411.                     } else if (toupper(*d) == 'E') {
  412.                         odd_even = 'e';
  413. fprintf(stderr, "\nprint even pages only");
  414.                     }
  415.                 break;
  416.                 case '#' :        /* copies */
  417.                     status = atoi(d);
  418.                     if ((status > 1) && (status < 255)) {
  419.                         copies = status;
  420. fprintf(stderr, "\n%d copies specified", copies);
  421.                     }
  422.                 break;
  423.                 case 'a' :        /* first page to print */
  424.                     status = atoi(d);
  425.                     if ((status > 0) && (status < last_page)) {
  426.                         first_page = status;
  427. fprintf(stderr, "\nstart print at page %d", first_page);
  428.                     }
  429.                 break;
  430.                 case 'b' :         /* last page to print */
  431.                     status = atoi(d);
  432.                     if (status > 0) {
  433.                         last_page = status;
  434. fprintf(stderr, "\nstop print at page %d", last_page);
  435.                     }
  436.                 break;
  437.                 case 'o' :        /* output redirection */
  438.                     if (freopen(d,"wt", ofl) == NULL) {
  439.                         fprintf(stderr,"\ncannot open output file %s",d);
  440.                         exit(-1);
  441.                     } else
  442.                         fprintf(stderr,"\noutput file %s",d);
  443.                 break;
  444.                 case 's' :        /* file mask (source) */
  445.                     mask = d;
  446.                     file_parse(d, fdrive, fpath, fl.name);
  447.                 break;
  448.                 default:
  449. fprintf(stderr,"\n unknown option: %s = %s", argv[i], d);
  450.                     query = TRUE;
  451.                 break;
  452.             }        /* argument list parse case */
  453.         }        /* argument examination loop */
  454.     }         /* have runstring arguments */
  455.  
  456.     if (mask == NULL) {
  457.         fprintf(stderr, "\nusage: %s options filemask",argv[0]);
  458.         for (status = 0; *opt_desc[status];
  459.             fprintf(stderr, "%s", opt_desc[status++]));
  460.         fprintf(stderr, "%s", 
  461. "\nunknown options or any argument without an = is considered a file mask."
  462. "\nOnly enough option name to uniquely identify it is required (in caps above)."
  463.         );
  464.         fprintf(stderr,"\n\n%s\n\n",copyright);
  465.         exit(-1);
  466.     } 
  467.  
  468.     if (owner_line == NULL)        /* install default owner line */
  469.         owner_line = mask;
  470.  
  471.     if (query) {
  472.         fprintf(stderr,"\nlist %s",mask);
  473.         fprintf(stderr,"\nOK to continue (Y or N)?");
  474.         i = getchar();
  475.         if (toupper(i) != 'Y') {
  476.             exit(0);
  477.         }    
  478.     }
  479.  
  480. /* initialize */
  481.     fl.path = fpath;
  482.     fl.drive = fdrive;
  483.     init_prtr(&fl);        /* initialize printer */
  484.  
  485.     time(&tm_now);
  486.     fprintf(stderr, "\nprint 2 up listings");
  487.     if (noprt == FALSE)
  488.         fprintf(stderr, " to HPLJ II compatible");
  489.     fprintf(stderr, " %s", ctime(&tm_now));
  490.  
  491.     if (index != NULL) {
  492.         fprintf(index,"\nlisting printed: %s\n", ctime(&tm_now));
  493.         fprintf(index,"\n  file      on page lines (pages) listed\n");
  494.     }
  495.  
  496. /* read directory of files */
  497.     status = _dos_findfirst(mask, attributes, &fdat);
  498.     count = 0;
  499.     tot_size = 0;
  500.     printf("\n");
  501.     while (status == 0) {
  502.         count += 1;
  503.         tot_size += fdat.size;
  504.         fl.sz = fdat.size;
  505.                                         /* segregate name and extent */
  506.         for (c = fdat.name, i=0; (*c != EOS) && (*c != '.'); ++c) 
  507.             fl.name[i++] = *c;
  508.         fl.name[i] = EOS;
  509.         if (*c != EOS) {
  510.             for (++c,i=0; (*c != EOS) && (i < (sizeof(fl.ext)-1)); ++c) 
  511.                 fl.ext[i++] = *c;
  512.         } else
  513.             i = 0;
  514.         fl.ext[i] = EOS;
  515.  
  516.         fl.hr = (int)lgetbits((unsigned long)fdat.wr_time, 11, 5);
  517.         fl.mn = (int)lgetbits((unsigned long)fdat.wr_time, 5, 6);
  518.         fl.mo = (int)lgetbits((unsigned long)fdat.wr_date, 5, 4);
  519.         fl.da = (int)lgetbits((unsigned long)fdat.wr_date, 0, 5);
  520.         fl.yr = (int)lgetbits((unsigned long)fdat.wr_date, 9, 7);
  521.         if ((status = prtr(&fl)) != 0)
  522.             fprintf(stderr,"\n error %d reading file %s%s%s.%s", status
  523.                 , fl.drive, fl.path, fl.name, fl.ext);
  524.         status =_dos_findnext(&fdat);
  525.     }
  526.  
  527. /*    if (status != 18) fprintf(stderr,"\n find exit status = %d\n",status); */
  528.  
  529.     if (index != NULL) {
  530.         fclose(index);
  531.         make_index(idx_name, sizeof(idx_name), &fl);
  532.     }
  533.  
  534. /* reset printer to original conditions and shut down */
  535.     reset_prtr(&fl);
  536.  
  537.     if (count == 0) {
  538.         fprintf(stderr,"\nno files matching %s",mask);
  539.         fprintf(stderr,"\nusage: %s optionlist filemask",argv[0]);
  540.         fprintf(stderr,"\nrun with no arguments for assistance\n");
  541.     } else {
  542.         fprintf(stderr,"\n%d files occupying %ld bytes\n",count, tot_size);
  543.     }
  544.     fprintf(stderr,"\n%s\n",copyright);
  545.  
  546.     exit(0);
  547. }
  548. /* =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= */
  549.  
  550. /* printer management and output routines */
  551.  
  552. int prt_col        /* column being printed (0 < prt_col <= max) */
  553.     , prt_row        /* row being printed (0 < prt_row < max) */
  554.     , prt_page        /* indicates odd or left col and even or right col */
  555.     , file_page        /* file page < prt_page < paper_page */
  556.     , file_line        /* line in file */
  557.     , paper_page;     /* pieces of paper in print run */
  558.  
  559. FILE *evnout, *oddout, *nulout, *ctrl;
  560.  
  561. /* =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= */
  562. int make_index(char *idx_name, int idx_len, FILE_ENT *f) {
  563.     int status, i;
  564.     char *c, *d, fpath[64];
  565.  
  566.     memset(fpath, EOS, sizeof(fpath));
  567.     for (c = idx_name, d=NULL; *c; ++c) {
  568.         if (*c == '\\') { /* convert all backslashes to forward slashes */
  569.             *c = '/';
  570.             d = c;
  571.         } else if (*c == ':') 
  572.             d = c;        /* trap end of path */
  573.     }
  574.     if (d != NULL) {        /* pull path name for file opens */
  575.         strncpy(fpath, idx_name, (d - idx_name) + 1);
  576.         ++d;
  577.     } else 
  578.         d = idx_name;
  579.  
  580.     f->path = fpath;
  581.                                     /* segregate name and extent */
  582.     for (c=d, i=0; (*c != EOS) && (*c != '.'); ++c) 
  583.         f->name[i++] = *c;
  584.     f->name[i] = EOS;
  585.     if (*c != EOS) {
  586.         for (++c,i=0; (*c != EOS) && (i < (sizeof(f->ext)-1)); ++c) 
  587.             f->ext[i++] = *c;
  588.     } else
  589.         i = 0;
  590.     f->ext[i] = EOS;
  591.  
  592.     f->sz = 0;
  593.  
  594. /*
  595.     fprintf(stderr,"\nindex input %s",idx_name); 
  596.     fprintf(stderr,"\nindex path %s",f->path); 
  597.     fprintf(stderr,"\nindex file %s",f->name); 
  598.     fprintf(stderr,"\nindex ext %s",f->ext); 
  599. */
  600.  
  601.     status = strlen(idx_name) + strlen(owner_line) + 5;
  602.     if (status < idx_len) {
  603.         strcat(idx_name," for ");
  604.         strcat(idx_name,owner_line);
  605.         owner_line = idx_name;
  606.     }
  607.  
  608.     prt_page = 0;
  609.     paper_page = 0;
  610.     putc('\f', ofl);
  611.     status = prtr(f);
  612.     return(status);
  613. }
  614. /* =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= */
  615. int init_prtr(FILE_ENT *f) {
  616. /*
  617. set ofl to text mode output and send setup string to printer.
  618.             "\033&s1C"            disable end of line wrap
  619.             "\033&l0L"            disable perf skip mode
  620.             "\033&l",n,"X"        make n copies per page
  621.             "\033&l2H"            feed paper from manual slot
  622.  
  623. */
  624.     char str[32];
  625.     int i, j;
  626.  
  627. /* set file stream pointers for odd and even pages and control */
  628.     ctrl = ofl;
  629.     nulout = fopen("NUL","wt");
  630.     if (odd_even == 'o') {
  631.         evnout = nulout;
  632.         oddout = ofl;
  633.     } else if (odd_even == 'e') {
  634.         evnout = ofl;
  635.         oddout = nulout;
  636.     } else {
  637.         evnout = ofl;
  638.         oddout = ofl;
  639.     }        /* ofl always starts out pointing to output file (not NULL) */
  640.  
  641.     prt_page = 0;
  642.     paper_page = 0;
  643.  
  644.     if (noprt) {
  645.         fprintf(ctrl, "%s", prt_init);
  646.         return(FALSE);
  647.     }
  648.  
  649. /* set printer parameters */
  650.     fprintf(ctrl, "\033E"
  651.             "\033&l1O"            /* landscape */
  652.             "\033(s17H"            /* primary font pitch = 17 cpi */
  653.             "\033&l5.14c"        /* c vmi = 5.14/48 in */
  654.             "%de"                /* e top margin lines */
  655.             "71F"                /* F text length = 71 lines */
  656.             "\033(s-3B"            /* light stroke weight */
  657.             "\033&k7H"            /* hmi in 120th inch (7 =171.4 chr / 10 in) */
  658.             "\r", topmargin);
  659.  
  660.     if (copies > 1)
  661.         fprintf(ctrl, "\033&l%uX", copies);
  662.     
  663.     if (tray == 'm')
  664.         fprintf(ctrl, "\033&l2H");
  665.  
  666.     return(FALSE);
  667. }
  668. /* =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= */
  669. int reset_prtr(FILE_ENT *f) {
  670.  
  671.     if (noprt) {
  672.         fprintf(ctrl, "%s", prt_init);
  673.         return(FALSE);
  674.     }
  675.  
  676.     fprintf(ctrl, "\033E");
  677.     return(FALSE);
  678. }
  679. /* =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= */
  680. int new_page(FILE_ENT *f) {
  681. /*
  682. called only by new line routine that takes care of line header after
  683. this is called. This routine prints shaded areas for headers, footers, and
  684. line header areas, prints page headers and footers as appropriate.
  685. increments file page, prt page, and paper page, resets prt col and prt row.
  686. */
  687.  
  688.     ++file_page;
  689.     prt_col = 1;
  690.     prt_row = 1;
  691.  
  692.     if ((++prt_page % 2) == 0) {        /* prep for right hand side */
  693.         if (noprt) {
  694.             putc('\f', ofl);
  695.             return(FALSE);
  696.         } else
  697.             fprintf(ofl,"\0339\033&a174m88L\r"); /* rhs: ff, lm=88, rm=174 */
  698.     } else {
  699.         if (paper_page != 0)
  700.             putc('\f', ofl);
  701.  
  702.         paper_page += 1;
  703.         if ((paper_page < first_page) || (paper_page > last_page))
  704.             ofl = nulout;
  705.         else if ((paper_page % 2) == 0)
  706.             ofl = evnout;
  707.         else
  708.             ofl = oddout;
  709.  
  710.         if (noprt) 
  711.             return(0);
  712.  
  713.         fprintf(ofl, "\033&a174m1L\r"    /* rm = 174; lm = 1 */
  714.                 "\033*t300R"            /* raster graphics resolution */
  715.                 "\033*r0A"                /* start graphics at left margin */
  716.                 "\r");
  717.  
  718. /* title line box */
  719.         fprintf(ofl,"\033*c15g3132a33B"    /* 15% gray scale, wh in dots */
  720.                 "\033*p0X"                /* set horiz col */
  721.                 "\033*p0Y"                /* set vertical row */
  722.                 "\033*c2P\r");            /* print gray scale pattern */
  723.  
  724. /* ownership line box */
  725.         fprintf(ofl, "\033*p0x2245Y"    /* set vertical row */
  726.                 "\033*c2P\r");            /* print gray scale pattern */
  727.  
  728. /* lhs number box */
  729.         fprintf(ofl,"\033*c106a2250B"    /* size in dots */
  730.                 "\033*p0x0Y"            /* set xy in dots */
  731.                 "\033*c2P\r");            /* print gray scale pattern */
  732.  
  733. /* rhs number box */
  734.         fprintf(ofl,    "\033*p1522x0Y"    /* set xy in dots */
  735.                 "\033*c2P\r");            /* print gray scale pattern */
  736.  
  737.         fprintf(ofl, "\033*rB\r");        /* turn off graphics mode */
  738.  
  739. /* print footer */
  740.         fprintf(ofl,    "\033&a70R\r");        /* set row 70 at left margin */
  741.         fprintf(ofl, "      %-75s page %-5d %78s"
  742.             , owner_line, paper_page, copyright);
  743.  
  744. /* left hand side initialization */
  745.         fprintf(ofl,"\0339\033&a87m1L\r"); /* lhs: ff row 0, lm=1, rm=87 */
  746.     }
  747.  
  748. /* print page header */
  749.     fprintf(ofl,    "\033&a0R\r");        /* set row at left margin */
  750.     fprintf(ofl,
  751. "      %8s.%-3s last modified %02d:%02d %02d/%02d/%02d %6ld bytes %20s %d\n"
  752.         , f->name, f->ext, f->hr , f->mn, f->mo , f->da , 80+f->yr, f->sz
  753.         , " file page", file_page
  754.     );
  755.     return(0);
  756. }
  757. /* =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= */
  758. int new_line(FILE_ENT *f) {
  759.  
  760.     if (++prt_row > page_len) {
  761.         new_page(f);
  762.     } else {
  763.         putc('\n',ofl);
  764.     }
  765.     file_line += 1;
  766.     if (noprt == FALSE)
  767.         fprintf(ofl,"%5d ",file_line);
  768.     prt_col = 1;
  769.     return(0);
  770. }
  771. /* =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= */
  772. int prtr(FILE_ENT *f) {
  773.  
  774.     FILE *ifd;
  775.     int inp_chr, start_page, status;
  776.     long chr_cnt;
  777.     
  778.     char openstr[127];
  779.  
  780.     if (strlen(f->drive) > 0) 
  781.         strcpy(openstr, f->drive);
  782.     else 
  783.         *openstr = EOS;
  784.  
  785.     if (strlen(f->path) > 0) 
  786.         strcat(openstr, f->path);
  787.  
  788.     strcat(openstr, f->name);
  789.     strcat(openstr, ".");
  790.     strcat(openstr, f->ext);
  791.  
  792. /*    fprintf(stderr,"\nopen %s",openstr); */
  793.  
  794.     if ((ifd = fopen(openstr,"rt")) == NULL) {
  795.         fprintf(stderr,"\ncannot open file %s",openstr);
  796.         return(-1);
  797.     }
  798.  
  799.     file_page = 0;
  800.     file_line = 0; 
  801.     chr_cnt = 0;
  802.     prt_row = page_len;
  803.     new_line(f);
  804.     start_page = paper_page;
  805.  
  806.     inp_chr = fgetc(ifd);
  807.     while (inp_chr != EOF) {
  808.         if ((status = ferror(ifd)) != 0) {
  809.             fclose(ifd);
  810.             return(status);
  811.         }
  812.         inp_chr = charmask & inp_chr; 
  813.         if ((prt_col > line_len) && (strchr("\b\n\r\f",inp_chr) == NULL)) {
  814.             if (++prt_row > page_len)     /* line overflow */
  815.                 new_page(f);
  816.             else 
  817.                 putc('\n',ofl);
  818.             if (noprt == FALSE)
  819.                 fprintf(ofl," =>  ");
  820.             prt_col = 1;
  821.         }
  822.         ++chr_cnt;
  823.         switch (inp_chr) {
  824.         case '\t' :        /* tab */
  825.             do { putc(BLANK, ofl);
  826.             } while (((++prt_col % tab_stop) != 1) && (prt_col < line_len));
  827.         break;
  828.         case '\b' :        /* backspace */
  829.             putc(inp_chr, ofl);
  830.             --prt_col;
  831.         break;
  832.         case '\f' :        /* formfeed */
  833.             prt_row = page_len;
  834.             new_line(f);
  835.         break;
  836.         case '\n' :        /* newline */
  837.         case '\r' :        /* carriage return */
  838.             new_line(f);
  839.         break;
  840.         default :
  841.             if (inp_chr == nl_char)            /* optional additional */
  842.                 new_line(f);
  843.             else if (isprint(inp_chr) ) {
  844.                 putc(inp_chr, ofl);
  845.                 ++prt_col;
  846.             } else if (noprt == FALSE) {
  847.                 if (codes == 'h') { /* make sure space left on line ??  */
  848.                     fprintf(ofl, "\033&dD%2X\033&d@ ",inp_chr); 
  849.                     prt_col += 4;
  850.                 } else if (codes == 'd') {
  851.                     fprintf(ofl, "\033&dD%3u\033&d@ ",inp_chr); 
  852.                     prt_col += 5;
  853.                 } else if (codes == 'o') {
  854.                     fprintf(ofl, "\033&dD%3o\033&d@ ",inp_chr); 
  855.                     prt_col += 5;
  856.                 }
  857.             }
  858.         break;
  859.         }
  860.         inp_chr = fgetc(ifd);
  861.     }
  862.     if ((++prt_row < MAX_PRT_ROWS) && (noprt == FALSE)) {
  863.         fprintf(ofl, "\n EOF:   \033&d3D%8s.%3s  %5d lines, %ld characters"
  864.                 , f->name, f->ext, file_line, chr_cnt );
  865.         if (codes == 'n')
  866.             fprintf(ofl, " (codes ignored)");
  867.         else if (codes == 'h')
  868.             fprintf(ofl, " (codes values hexadecimal)");
  869.         else if (codes == 'o')
  870.             fprintf(ofl, " (codes values octal)");
  871.         fprintf(ofl, "\033&d@");
  872.     }
  873.  
  874.     fclose(ifd);
  875.  
  876.     fprintf(stderr, "%8s.%-3s p %4d; %5d lines (%d page halves) \n"
  877.             , f->name, f->ext, start_page, file_line, file_page);
  878.  
  879.     if (index != NULL)
  880.         fprintf(index , "%8s.%-3s %4d; %5d (%d)\n"
  881.                 , f->name, f->ext, start_page, file_line, file_page);
  882.  
  883.     return(0);
  884. }
  885.  
  886. /* =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= */
  887. int file_parse(char *inpstr, char *fdrive, char *fpath, char *fname) {
  888. /*
  889.     inpstr parsed into fpath and fname 
  890.     string sizes assumed to be:
  891.      _MAX_FNAME    9    max. length of file name component 
  892.      _MAX_EXT    5    max. length of extension component 
  893.      _MAX_DIR    130    max. length of path component 
  894.      _MAX_DRIVE    3    max. length of drive component 
  895.     _MAX_PATH    144    max. length of full pathname 
  896.  
  897. */
  898.     char *c, *d, *p;
  899.  
  900.     /* fprintf(stderr,"\n parse %s",inpstr); */
  901.  
  902.     for (c = inpstr, d=p=NULL ; *c; ++c) {
  903.         if (*c == '\\') {
  904.             *c = '/';        /* convert all backslashes to forward slashes */
  905.             d = c;
  906.         } else if (*c == ':') {
  907.             p = c;            /* trap end of path */
  908.         } else if (*c == '/') {
  909.             d = c;
  910.         }
  911.     }
  912.     if (p != NULL) {
  913.         strncpy(fdrive, inpstr, min((p-inpstr)+1, _MAX_DRIVE));
  914.         /* fprintf(stderr,"\n drive: %s",fdrive);  */
  915.         inpstr = p + 1;
  916.     } else {
  917.         fdrive[0] = EOS;
  918.     }
  919.     if (d != NULL) {        /* pull path name for file opens */
  920.         strncpy(fpath, inpstr, min((d-inpstr)+1, _MAX_DIR));
  921.         inpstr = d + 1;
  922.         /* fprintf(stderr,"\n path: %s",fpath);  */
  923.     } else {
  924.         fpath[0] = EOS;
  925.     }
  926.  
  927.     /* fprintf(stderr,"\n name: %s",fname); */
  928.     strcpy(fname, inpstr);
  929.  
  930. }    
  931. /* =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= */
  932. /* scanstr.c (c) 1990 Bryan R Leipper
  933.  
  934. SYNOPSIS: copy string replacing escape sequences
  935. DESCRIPTION:
  936.     copy src to dest replacing escape sequences as found
  937.     escape sequences are indicated by a backslash and followed by strtol
  938.     function input values using an implied base (0x for hex 0[1-7] for
  939.     octal [1-9]* for decimal. If value comes up as zero, then try for
  940.     standard codes. Finally just dump character following backslash as is.
  941. RETURNS: pointer to end of destination string
  942. CAVEATS: make sure dest string long enough for output
  943. FILES: none
  944. NOTES:
  945. SEE ALSO: strtol standard C library function
  946. HISTORY: Feb 1988    original version
  947.     Feb 1990 use strtol implicit base directly
  948. */
  949. /* =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= */
  950. char *scan_str(char *dest, char *src) {
  951. char *endptr;
  952. long esc_code;
  953.  
  954.     while (*src) {
  955.         if (*src == '\\') {
  956.             esc_code = strtol(src, &endptr, 0);
  957.             if (esc_code) {        /* non zero result stashed */
  958.                 *(dest++) = (char)esc_code;
  959.                 src = endptr;
  960.             } else switch (*src) {
  961.                 case '0' : *(dest++) = 0; break;
  962.                 case 'a' : *(dest++) = '\a'; break;
  963.                 case 'b' : *(dest++) = '\b'; break;
  964.                 case 'f' : *(dest++) = '\f'; break;
  965.                 case 'n' : *(dest++) = '\n'; break;
  966.                 case 'r' : *(dest++) = '\r'; break;
  967.                 case 't' : *(dest++) = '\t'; break;
  968.                 case 'v' : *(dest++) = '\v'; break;
  969.                 default     : *(dest++) = *(src++); break;
  970.             }
  971.         } else {
  972.             *(dest++) = *(src++);
  973.         }
  974.     }
  975.     *dest = 0;
  976.     return(dest);
  977. }
  978. /* =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= =-=-= */
  979. unsigned long lgetbits(unsigned long mask, int low_bit, int mask_len) {
  980. /*
  981.     returns value of selected bits in long integer
  982. */
  983.     unsigned long i;
  984.     int j, intlen = sizeof(long int) * 8        /* BITSPERBYTE */ ;
  985.  
  986.     j = intlen - (low_bit + mask_len);
  987.     i = mask << j;
  988.     j += low_bit;
  989.     i >>= j;
  990.     return (i);
  991. }
  992.