home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / TEXT / INFO / INTER30C.ZIP / INTPRINT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-10  |  28.3 KB  |  1,039 lines

  1. /************************************************************************/
  2. /* INTPRINT.C by Ralf Brown.  Donated to the Public Domain.        */
  3. /* Please do not remove my name from any copies or derivatives.        */
  4. /************************************************************************/
  5. /* Program History:                            */
  6. /*   v1.00  4/23/89  initial public release                */
  7. /*             with 4/30/89 list                    */
  8. /*   v1.10  5/21/89  added -I and -f                    */
  9. /*   v1.11  1/6/90   fixed #endif's for compilers which don't handle    */
  10. /*             labels                        */
  11. /*   v1.20  6/8/90   added -r                        */
  12. /*   v1.30  7/14/90  added -b, tables now stay aligned on odd indents    */
  13. /*   v1.40  10/6/90  added -B based on changes by Naoto Kimura, -w    */
  14. /*   v1.40a 5/6/91   HP LaserJet II support by Russ Herman        */
  15. /*   v1.41  7/9/91   HP PCL support by P.J.Farley III            */
  16. /*   v2.00  9/1/91   modular printer definitions            */
  17. /*             printing multipart interrupt list            */
  18. /*   v2.01  2/9/92   fixed summary entry for non-numeric AX= and AH=    */
  19. /*             smarter page breaks                */
  20. /*   v2.02  2/18/92  bugfix & isxdigit suggested by Aaron West        */
  21. /*   v2.10  3/14/92  updated to handle extra flags in headings        */
  22. /************************************************************************/
  23. /* Recompiling:                                */
  24. /*   Turbo C / Borland C++                        */
  25. /*    tcc -mt -lt -Z -p intprint                    */
  26. /************************************************************************/
  27.  
  28. #include <stdio.h>
  29. #include <string.h>
  30. #include <ctype.h>
  31.  
  32. #define VERSION "2.10"
  33.  
  34. #define MAXLINE 81   /* at most 80 chars per line (plus newline) */
  35. #define MAXPAGE 200  /* at most 200 lines per page */
  36.  
  37. #ifndef FALSE
  38. #define FALSE 0
  39. #endif
  40. #ifndef TRUE
  41. #define TRUE !FALSE
  42. #endif
  43.  
  44. #ifdef __TURBOC__
  45. #  define PROTOTYPES
  46. #  include <stdlib.h>
  47. int _Cdecl isatty(int handle) ;
  48. void _setenvp(void) {} /* don't need the environment, so don't include it */
  49. /*int isspace(char c) { return (c == ' ' || c == '\t') ; }*/
  50. #else
  51. /*#define PROTOTYPES  /* uncomment if compiler supports ANSI-style prototypes */
  52. #define NEED_STRNICMP /* comment out if library contains strnicmp() */
  53. #define NEED_ISXDIGIT /* comment out if library contains isxdigit() */
  54. #define _Cdecl
  55.  
  56. char *itoa(num,buf,radix)   /* not everybody has the same itoa() as TurboC */
  57. int num ;            /* minimal implementation */
  58. char *buf ;
  59. int radix ;
  60. {
  61.    int count = 0 ;
  62.    int i ; 
  63.    char tmp ;
  64.  
  65.    do {
  66.       buf[count++] = '0' + num % radix ;
  67.       num = num / radix ;
  68.    } while (num) ;
  69.    buf[count] = '\0' ;
  70.    if (count > 1)
  71.       for (i = 0 ; i < count / 2 ; i++)
  72.      {
  73.      tmp = buf[i] ;
  74.      buf[i] = buf[count-i-1] ;
  75.      buf[count-i-1] = tmp ;
  76.      }
  77.    return buf ;
  78. }
  79. #endif /* __TURBOC__ */
  80.  
  81. /***********************************************/
  82.  
  83. typedef struct _cstr         /* a counted string */
  84.    {
  85.    int len ;             /* the string's length */
  86.    char *str ;             /* the actual contents of the string */
  87.    } cstr ;
  88.  
  89. #define CSTR(s) { sizeof(s)-1, (s) }  /* for defining a counted string literal */
  90. #define cstrlen(s) ((s)->len)     /* how long is the counted string? */
  91. #define cstrchar(s,i) ((s)->str[i])  /* retrieve a character from a counted string */
  92.  
  93. typedef struct _printer_def
  94.    {
  95.    char *name ;            /* for selecting the appropriate printer */
  96.    cstr init1, init2 ;        /* initialization strings */
  97.    cstr marginl, marginc, marginr ; /* margins: duplex even, non-duplex, duplex odd */
  98.    cstr duplex_on ;        /* turn on duplex mode */
  99.    cstr term1, term2 ;        /* cleanup strings */
  100.    cstr bold_on, bold_off ;    /* boldface on/off */
  101.    int indent ;            /* how many extra spaces to indent */
  102.    int lines_per_page ;        /* how many lines to print on each page */
  103.    int page_length ;        /* how many lines on each page */
  104.    int page_width ;        /* how many printable columns per line? */
  105. #ifdef PROTOTYPES
  106.    void (*put_line)(FILE *,int) ;/* function to call to print out divider line */
  107. #else
  108.    void (*put_line)() ;        /* function to call to print out divider line */
  109. #endif /* PROTOTYPES */
  110.    int *flag ;            /* flag to set when using this printer definition */
  111.    } PRINTER_DEF ;
  112.  
  113. /***********************************************/
  114.  
  115. #ifdef PROTOTYPES
  116. void usage(void) ;
  117. void fatal(char *msg) ;
  118. void get_line(char *buf,int size) ;
  119. void indent_line(FILE *fp) ;
  120. void put_line(FILE *fp, int len) ;
  121. void HPPCL_put_line(FILE *fp, int len) ;
  122. void fputcstr(cstr *s, FILE *fp) ;
  123. int divider_line(char *line) ;
  124. int section_start(char *line) ;
  125. void output_line(char *line,FILE *fp) ;
  126. void fill_buffer(int lines, int lines_per_page) ;
  127. int find_page_break(int lines) ;
  128. void summarize(FILE *summary, int line, int pages_printed) ;
  129. void start_format(char *line) ;
  130. void print_line(char *line) ;
  131. void print_buffer(int first, int last, int lines_per_page, int total_lines, int use_FF) ;
  132. void select_printer(char *name) ;
  133. void display_printers(void) ;
  134. int _Cdecl main(int argc, char **argv) ;
  135. #else
  136. void put_line() ;
  137. void HPPCL_put_line() ;
  138. #endif /* PROTOTYPES */
  139.  
  140. /***********************************************/
  141.  
  142. FILE *infile, *outfile ;
  143. char *input_file ;
  144.  
  145. char buffer[MAXPAGE][MAXLINE] ;
  146. char num[6] ;
  147. char summary_line[2*MAXLINE] ;
  148.  
  149. int pages_printed = 0 ;
  150. int page_width = 0 ;        /* page width in characters, 0 = use prtdef */
  151. int indent = 0 ;        /* number of blanks to add at start of each line */
  152. int widow_length = 10 ;        /* number of lines to scan for good place to break */
  153. int page_numbers = FALSE ;    /* add page numbers to bottom of page? */
  154. int multi_file = FALSE ;    /* printing multipart interrupt list? */
  155. int out_of_files = FALSE ;    /* hit end of last file for multipart printing? */
  156. int do_summary = FALSE ;    /* create a one-line-per-call summary? */
  157. int do_formats = FALSE ;    /* create a separate file with data structures? */
  158. int IBM_chars = FALSE ;        /* printer can handle IBM graphics characters */
  159. int boldface = FALSE ;        /* boldface titles and Return:/Notes: ? */
  160. int printer_bold = FALSE ;    /* boldface using printer control sequences? */
  161. int echo_format = FALSE ;
  162. int duplex = FALSE ;
  163. int HPPCL_mode = FALSE ;
  164. FILE *summary ;
  165. FILE *formats ;
  166. PRINTER_DEF *printer = NULL ;
  167.  
  168. int first_page = 0 ;
  169. int last_page = 9999 ;
  170.  
  171. /***********************************************/
  172.  
  173. PRINTER_DEF printers[] =
  174.    {
  175.      { "default",
  176.        CSTR(""), CSTR(""),
  177.        CSTR(""), CSTR(""), CSTR(""),
  178.        CSTR(""),
  179.        CSTR(""), CSTR(""),
  180.        CSTR(""), CSTR(""),
  181.        -1,
  182.        60,
  183.        0,
  184.        79,
  185.        put_line,
  186.        NULL,
  187.      },
  188.      { "Epson FX80",
  189.        CSTR("\033M"), CSTR(""),
  190.        CSTR("\033l\004"), CSTR("\033l\007"), CSTR("\033l\014"),
  191.        CSTR(""),
  192.        CSTR("\033P"), CSTR("\033l\000"),
  193.        CSTR("\033E"), CSTR("\033F"),
  194.        0,
  195.        60,
  196.        0,
  197.        87,    /* 96 - left margin - 1 right margin */
  198.        put_line,
  199.        NULL,
  200.      },
  201.      { "HP PCL",
  202.        CSTR("\033(8U"), CSTR(""),
  203.        CSTR("\033&a4c4L"), CSTR("\033&a8c8L"), CSTR("\033&a12c12L"),
  204.        CSTR("\033&l1S"),
  205.        CSTR("\033E"), CSTR(""),
  206.        CSTR("\033(s3B"), CSTR("\033(s0B"),
  207.        0,
  208.        69,
  209.        0,
  210.        87,    /* 96 - left margin - 1 right margin */
  211.        HPPCL_put_line,
  212.        &HPPCL_mode,
  213.      },
  214. #define HPPCL_FONT_ON_A "\033(s0p12h10v0s0b"
  215. /* HP PCL4/5 Font select: Roman-8;Upright12Pitch10PointMediumWeight */
  216. #define HPPCL_FONT_ON_B "T\033&l6.8571C"
  217. /* HP PCL4/5 Font select: End typeface select;VMI=7LPI: (48/7)-48th's inches*/
  218. #define HPPCL_IBM_LN_A    "\033&f0S\033*p-15Y\033*c"
  219. /* HP PCL4/5 IBM Line:    Push Pos;Up 15/720";Hor.Rule ???/300ths" long */
  220. #define HPPCL_IBM_LN_B    "a3b0P\033&f1S"
  221. /* HP PCL4/5 IBM Line:     3/300ths" high,Print rule;Pop Position */
  222.      { "LaserJet II",
  223.        CSTR("\033(10U"),CSTR(""),
  224.        CSTR("\033&a4c4L"), CSTR("\033&a8c8L"), CSTR("\033&a12c12L"),
  225.        CSTR(""),
  226.        CSTR("\033E"),CSTR(""),
  227.        CSTR("\033(S3B"),CSTR("\033(S0B"),
  228.        0,
  229.        54,
  230.        60,
  231.        79,
  232.        put_line,
  233.        &IBM_chars,
  234.      },
  235.    } ;
  236. #define NUM_PRINTERS (sizeof(printers)/sizeof(printers[0]))
  237.  
  238. /***********************************************/
  239.  
  240. #ifdef NEED_STRNICMP
  241. #ifdef PROTOTYPES
  242. int strnicmp(char *s1,char *s2,int len)
  243. #else
  244. int strnicmp(s1,s2,len)
  245. char *s1,*s2 ;
  246. unsigned int len ;
  247. #endif PROTOTYPES
  248. {
  249.    char c1, c2 ;
  250.  
  251.    while (*s1 && *s2 && len > 0)
  252.       {
  253.       len-- ;
  254.       c1 = (islower(*s1) ? toupper(*s1) : *s1) ;
  255.       c2 = (islower(*s2) ? toupper(*s2) : *s2) ;
  256.       if (c1 != c2 || len == 0)     /* mismatch or substrings exhausted? */
  257.      return (c1 - c2) ;
  258.       s1++ ;
  259.       s2++ ;
  260.       }
  261.    return 0 ;  /* strings match exactly on first 'len' characters */
  262. }
  263. #endif /* NEED_STRNICMP */
  264.  
  265. #ifdef NEED_ISXDIGIT
  266. #ifdef PROTOTYPES
  267. int isxdigit(int c)
  268. #else
  269. int isxdigit(c)
  270. int c ;
  271. #endif /* PROTOTYPES */
  272. {
  273.    return isdigit(c) || (strchr("ABCDEFabcdef",c) != NULL) ;
  274. }
  275. #endif /* NEED_ISXDIGIT */
  276.  
  277. /***********************************************/
  278.  
  279. void usage()
  280. {
  281.    fputs("INTPRINT v", stderr) ;
  282.    fputs(VERSION, stderr) ;
  283.    fputs(" by Ralf Brown.  Donated to the Public Domain.\n\n",stderr) ;
  284.    fputs("Usage: intprint [options] intlist [>|>>]output\n",stderr) ;
  285.    fputs("Options:\n",stderr) ;
  286.    fputs("\t-Pname\tassume printer 'name' (-P? lists supported printers)\n",stderr) ;
  287.    fputs("\t-lN\tprint N lines per page (default depends on printer)\n",stderr) ;
  288.    fputs("\t-LN\tassume N lines on a page, use linefeeds if > #lines printed\n",stderr) ;
  289.    fputs("\t-m\tlist is in multiple parts starting with the named file\n",stderr) ;
  290.    fputs("\t-d\t(duplex) print even/odd pages with different indents\n",stderr) ;
  291.    fputs("\t-p\tadd page numbers\n",stderr) ;
  292. /*   fputs("\t-h\tadd page headers\n",stderr) ; */
  293.    fputs("\t-nN\tassume N pages have been printed from previous parts\n",stderr) ;
  294.    fputs("\t-rN:M\tprint only pages N through M\n",stderr) ;
  295.    fputs("\t-wN\tscan N lines from bottom of page for good place to break\n",stderr) ;
  296.    fputs("\t-e\tassume 'elite' mode (96 chars per line) for default printer\n",stderr) ;
  297.    fputs("\t-iN\tindent output N spaces (overridden by some printers)\n",stderr) ;
  298.    fputs("\t-b\tboldface title lines and Return:/Note:\n",stderr) ;
  299.    fputs("\t-B\tboldface using printer control codes instead of overprinting\n",stderr) ;
  300.    fputs("\t-tN\tselect typeface N for the chosen printer\n",stderr) ;
  301.    fputs("\t-I\tprinter supports IBM graphics characters\n",stderr) ;
  302.    fputs("\t-sfile\twrite a one-line-per-function summary to 'file'\n",stderr) ;
  303.    fputs("\t-ffile\twrite all data structures to 'file'\n",stderr) ;
  304.    exit(1) ;
  305. }
  306.  
  307. /***********************************************/
  308.  
  309. void fatal(msg)
  310. char *msg ;
  311. {
  312.    fputs(msg,stderr) ;
  313.    fputs("\n",stderr) ;
  314.    exit(1) ;
  315. }
  316.  
  317. /***********************************************/
  318.  
  319. void indent_line(fp)
  320. FILE *fp ;
  321. {
  322.    int ind = indent ;
  323.  
  324.    while (ind >= 8)
  325.       {
  326.       fputc('\t',fp) ;
  327.       ind -= 8 ;
  328.       }
  329.    while (ind-- > 0)
  330.       fputc(' ', fp) ;
  331. }
  332.  
  333. /***********************************************/
  334.  
  335. void put_line(fp,len)
  336. FILE *fp ;
  337. int len ;
  338. {
  339.    int i ;
  340.  
  341.    if (IBM_chars)
  342.       for (i = 0 ; i < len ; i++)
  343.      fputc(196,fp) ;  /* single horizontal line */
  344.    else
  345.       for (i = 0 ; i < len ; i++)
  346.      fputc('-',fp) ;
  347. }
  348.  
  349. /***********************************************/
  350.  
  351. void HPPCL_put_line(fp,len)
  352. FILE *fp ;
  353. int len ;
  354. {
  355.    fputs(HPPCL_IBM_LN_A,fp) ;
  356.    itoa((len * 25), num, 10) ;
  357.    fputs(num,fp) ;
  358.    fputs(HPPCL_IBM_LN_B,fp) ;
  359. }
  360.  
  361. /***********************************************/
  362.  
  363. void fputcstr(s,fp)        /* output the counted string to the given file */
  364. FILE *fp ;
  365. cstr *s ;
  366. {
  367.    int i ;
  368.  
  369.    for (i = 0 ; i < cstrlen(s) ; i++)
  370.       fputc(cstrchar(s,i),fp) ;
  371. }
  372.  
  373. /***********************************************/
  374.  
  375. int divider_line(line)
  376. char *line ;
  377. {
  378.    return strncmp(line,"--------",8) == 0 ;
  379. }
  380.  
  381. /***********************************************/
  382.  
  383. int section_start(line)
  384. char *line ;
  385. {
  386.    if (strncmp(line,"Return:",7) == 0 ||
  387.        strncmp(line,"Note:",5) == 0 ||
  388.        strncmp(line,"Notes:",6) == 0 ||
  389.        strncmp(line,"SeeAlso:",8) == 0 ||
  390.        strncmp(line,"BUG:",4) == 0)
  391.       return 1 ;
  392.    return 0 ;
  393. }
  394.  
  395. /***********************************************/
  396.  
  397. void output_line(line,fp)
  398. char *line ;
  399. FILE *fp ;
  400. {
  401.    int pos = 0 ;
  402.    char bold[10] ;
  403.  
  404.    if (boldface)
  405.       {
  406.       if (strncmp(line,"INT ",4) == 0 || strncmp(line,"Format of ",10) == 0 ||
  407.       strncmp(line,"Values ",7) == 0)
  408.      {
  409.      indent_line(fp) ;
  410.      if (printer_bold)
  411.         {
  412.         fputcstr(&printer->bold_on,fp) ;
  413.         fputs(line,fp) ;
  414.         fputcstr(&printer->bold_off,fp) ;
  415.         line = NULL ;
  416.         }
  417.      else
  418.         {
  419.         fputs(line,fp) ;
  420.         fputc('\r',fp) ;
  421.         }
  422.      }
  423.       else if (section_start(line))
  424.      {
  425.      strncpy(bold,line,sizeof bold) ;
  426.      *strchr(bold,':') = '\0' ;
  427.      indent_line(fp) ;
  428.      if (printer_bold)
  429.         {
  430.         fputcstr(&printer->bold_on,fp) ;
  431.         fputs(bold,fp) ;
  432.         fputcstr(&printer->bold_off,fp) ;
  433.         pos = strlen(bold) ;     /* we're no longer at the left edge of the */
  434.         line += pos ;         /* line, so figure out where we are */
  435.         }
  436.      else
  437.         {
  438.         fputs(bold,fp) ;
  439.         fputc('\r',fp) ;
  440.         }
  441.      }
  442.       }
  443.    if (line && *line)
  444.       {
  445.       if (pos == 0)        /* are we currently at the left edge of the line? */
  446.      indent_line(fp) ;  /* if yes, indent the desired amount */
  447.       if (indent % 8)
  448.      {
  449.      while (*line)
  450.         {
  451.         if (*line == '\t')
  452.            do {
  453.           fputc(' ',fp) ;
  454.           } while (++pos % 8) ;
  455.         else
  456.            {
  457.            fputc(*line,fp) ;
  458.            pos++ ;
  459.            }
  460.         line++ ;
  461.         }
  462.      }
  463.       else
  464.      fputs(line,fp) ;
  465.       }
  466.    fputc('\n',fp) ;
  467. }
  468.  
  469. /***********************************************/
  470.  
  471. void get_line(buf,size)
  472. char *buf ;
  473. int size ;
  474. {
  475.    int last ;
  476.  
  477.    buf[0] = '\0' ;
  478.    if (out_of_files)
  479.       return ;
  480.    fgets(buf,size,infile) ;
  481.    if ((feof(infile) || buf[0] == '\0'))
  482.       if (multi_file)
  483.      {
  484.      FILE *tempfile ;
  485.  
  486.      last = strlen(input_file) - 1 ;
  487.      input_file[last]++ ;
  488.      if ((tempfile = fopen(input_file,"r")) != NULL)
  489.         {
  490.         fclose(infile) ;
  491.         infile = tempfile ;
  492.         fgets(buf,size,infile) ;
  493.         }
  494.      else
  495.         {
  496.         out_of_files = TRUE ;
  497.         return ;
  498.         }
  499.      }
  500.       else
  501.      out_of_files = TRUE ;
  502.    last = strlen(buf) - 1 ;
  503.    if (last < 0)
  504.       last = 0 ;
  505.    if (buf[last] == '\n')
  506.       buf[last] = '\0' ;  /* strip the newline */
  507. }
  508.  
  509. /***********************************************/
  510.  
  511. void fill_buffer(lines,lines_per_page)
  512. int lines, lines_per_page ;
  513. {
  514.    int i ;
  515.  
  516.    if (lines)
  517.       for (i = lines ; i < lines_per_page ; i++)
  518.      strcpy(buffer[i-lines], buffer[i]) ;
  519.    else
  520.       lines = lines_per_page ;
  521.    for (i = lines_per_page - lines ; i < lines_per_page ; i++)
  522.       get_line(buffer[i], sizeof(buffer[i])) ;
  523. }
  524.  
  525. /***********************************************/
  526.  
  527. int find_page_break(lines)
  528. int lines ;
  529. {
  530.    int i ;
  531.  
  532.    for (i = 0 ; i < widow_length ; i++)
  533.       {
  534.       if (strcmp(buffer[lines-i-1],"\n") == 0 ||
  535.       strlen(buffer[lines-i-1]) == 0 ||
  536.       divider_line(buffer[lines-i-1]) ||
  537.       section_start(buffer[lines-i]))
  538.      return lines - i ;
  539.       }
  540.    return lines ;
  541. }
  542.  
  543. /***********************************************/
  544.  
  545. void summarize(summary, line, pages_printed)
  546. FILE *summary ;
  547. int line, pages_printed ;
  548. {
  549.    char *s ;
  550.    int i ;
  551.    int max_descrip ;
  552.    int len ;
  553.  
  554.    s = buffer[line] ;
  555.    if (strncmp(s, "INT ", 4) == 0)   /* start of an entry? */
  556.       {
  557.       summary_line[3] = summary_line[0] = ' ' ;
  558.       summary_line[1] = s[4] ;     /* output interrupt number */
  559.       summary_line[2] = s[5] ;
  560.       summary_line[4] = '\0' ;
  561.       len = 4 ;
  562.       s = buffer[line+1] ;
  563.       while (*s && isspace(*s))
  564.      s++ ;
  565.       if (*s == 'A')
  566.      {
  567.      if (s[1] == 'X')
  568.         i = 4 ;
  569.      else
  570.         i = (s[1] == 'H') ? 2 : 0 ;
  571.      }
  572.       else
  573.      i = 0 ;
  574.       if (i)
  575.      {
  576.      while (*s && *s != '=')
  577.         s++ ;
  578.      s++ ;    /* skip the equal sign */
  579.      while (*s && isspace(*s))
  580.         s++ ;
  581.      if (isxdigit(*s) && isxdigit(s[1]))
  582.         {
  583.         summary_line[len++] = *s++ ;
  584.         summary_line[len++] = *s++ ;
  585.         summary_line[len++] = ' ' ;
  586.         if (i == 4)
  587.            {
  588.            summary_line[len++] = *s++ ;
  589.            summary_line[len++] = *s ;
  590.            }
  591.         else
  592.            {
  593.            summary_line[len++] = '-' ;
  594.            summary_line[len++] = '-' ;
  595.            }
  596.         summary_line[len++] = ' ' ;
  597.         }
  598.      else
  599.         {
  600.         /* wasn't legal digit, so no numbers */
  601.         strcpy(summary_line+len,"-- -- ") ;
  602.         len += 6 ;
  603.         }
  604.      }
  605.       else
  606.      {
  607.      strcpy(summary_line+len,"-- -- ") ;
  608.      len += 6 ;
  609.      }
  610.       if (page_numbers)
  611.      {
  612.      itoa(pages_printed,num,10) ;
  613.      for (i = strlen(num) ; i < 3 ; i++)
  614.         summary_line[len++] = ' ' ;
  615.      strcpy(summary_line+len,num) ;
  616.      len += strlen(num) ;
  617.      summary_line[len++] = ' ' ;
  618.      }
  619.       s = buffer[line] + 7 ;    /* find function description */
  620.       if (*s && *s != '-')    /* does the heading contain flags? */
  621.      {
  622.      while (*s && !isspace(*s))
  623.         summary_line[len++] = *s++ ;
  624.      summary_line[len++] = '>' ;
  625.      summary_line[len++] = ' ' ;
  626.      while (*s && *s != '-')
  627.         s++ ;
  628.      }
  629.       while (*s && !isspace(*s))
  630.      s++ ;
  631.       while (*s && isspace(*s))
  632.      s++ ;
  633.       max_descrip = (page_width > sizeof(summary_line)-1) ? 
  634.                    sizeof(summary_line)-1 : page_width ;
  635.       while (len < max_descrip && *s)
  636.      summary_line[len++] = *s++ ;
  637.       summary_line[len] = '\0' ;
  638.       if (do_summary)
  639.      output_line(summary_line,summary) ;
  640.       }
  641. }
  642.  
  643. /***********************************************/
  644.  
  645. void start_format(line)
  646. char *line ;
  647. {
  648.    indent_line(formats) ;
  649.    (*printer->put_line)(formats,79) ;
  650.    fputc('\n',formats) ;
  651.    indent_line(formats) ;
  652.    fputs(summary_line,formats) ;
  653.    fputc('\n',formats) ;
  654.    indent_line(formats) ;
  655.    fputc('\t',formats) ;
  656.    fputs(line+10,formats) ;
  657.    fputc('\n',formats) ;
  658.    echo_format = TRUE ;
  659. }
  660.  
  661. /***********************************************/
  662.  
  663. void print_line(line)
  664. char *line ;
  665. {
  666.    if (*line)
  667.       {
  668.       if (divider_line(line))
  669.      {
  670.      indent_line(outfile) ;
  671.      (*printer->put_line)(outfile,79) ;
  672.      fputc('\n', outfile) ;
  673.      echo_format = FALSE ;
  674.      }
  675.       else
  676.      {
  677.      output_line(line, outfile) ;
  678.      if (echo_format)
  679.         output_line(line,formats) ;
  680.      }
  681.       }
  682.    else
  683.       {
  684.       fputc('\n', outfile) ;
  685.       echo_format = FALSE ;
  686.       }
  687. }
  688.  
  689. /***********************************************/
  690.  
  691. void print_buffer(first,last,lines_per_page,total_lines,use_FF)
  692. int first, last, lines_per_page, total_lines ;
  693. int use_FF ;
  694. {
  695.    int i, ind ;
  696.  
  697.    pages_printed++ ;
  698.    for (i = first ; i < last ; i++)
  699.       {
  700.       if (pages_printed >= first_page && pages_printed <= last_page)
  701.      print_line(buffer[i]) ;
  702.       if (do_summary || do_formats)  /* need summary lines if doing formats */
  703.      summarize(summary,i,pages_printed) ;
  704.       if (do_formats && strncmp(buffer[i],"Format of ",10) == 0)
  705.      start_format(buffer[i]) ;
  706.       }
  707.    if (pages_printed >= first_page && pages_printed <= last_page)
  708.       {
  709.       if (page_numbers)
  710.      {
  711.      for (i = last - first ; i < lines_per_page - 1 ; i++)
  712.         fputc('\n', outfile) ;
  713.      indent_line(outfile) ;
  714.      for (ind = 0 ; ind < 38 ; ind++) /* normal indent + 38 spaces */
  715.         fputc(' ', outfile) ;
  716.      fputs("- ", outfile) ;
  717.      itoa(pages_printed, num, 10) ;
  718.      fputs(num, outfile) ;
  719.      fputs(" -\n", outfile) ;
  720.      }
  721.       if (use_FF)
  722.      fputc('\f', outfile) ;
  723.       else
  724.      for (i = page_numbers?lines_per_page:(last-first) ; i<total_lines ; i++)
  725.         fputc('\n', outfile) ;
  726.       if (duplex)
  727.      {
  728.      if ((pages_printed % 2) == 1)    /* next page even or odd? */
  729.         fputcstr(&printer->marginl, outfile) ;    /* even page */
  730.      else
  731.         fputcstr(&printer->marginr, outfile) ;    /* odd page */
  732.      }
  733.       }
  734. }
  735.  
  736. /***********************************************/
  737.  
  738. void display_printers()
  739. {
  740.    int i ;
  741.    
  742.    fputs("Valid printer names are:\n",stderr) ;
  743.    for (i = 0 ; i < NUM_PRINTERS ; i++)
  744.       {
  745.       fputc('\t',stderr) ;
  746.       fputs(printers[i].name,stderr) ;
  747.       fputc('\n',stderr) ;
  748.       }
  749.    fputs("When entering the printer name, use either a dash or an underscore\n",stderr) ;
  750.    fputs("in place of blanks.  Case is ignored, and the name may be abbreviated\n",stderr) ;
  751.    fputs("to the shortest unique prefix.\n",stderr) ;
  752.    exit(1) ;
  753. }
  754.  
  755. /***********************************************/
  756.  
  757. void select_printer(name)
  758. char *name ;
  759. {
  760.    int i, len, prt = -1 ;
  761.    
  762.    len = strlen(name) ;
  763.    for (i = 0 ; i < len ; i++)        /* convert dashes and underscores to blanks */
  764.       if (name[i] == '-' || name[i] == '_')
  765.      name[i] = ' ' ;
  766.    for (i = 0 ; i < NUM_PRINTERS ; i++)
  767.       if (strnicmp(name,printers[i].name,strlen(name)) == 0)
  768.      if (prt == -1)
  769.         prt = i ;
  770.      else
  771.         fatal("Ambiguous printer name!  Use -P? to list printers.") ;
  772.    if (prt == -1)
  773.       fatal("Unknown printer name!  Use -P? to list printers.") ;
  774.    else
  775.       printer = &printers[prt] ;
  776. }
  777.  
  778. /***********************************************/
  779.  
  780. int _Cdecl main(argc,argv)
  781. int argc ;
  782. char *argv[] ;
  783. {
  784.    int lines_per_page = -1 ;
  785.    int total_lines = -1 ;
  786.    int use_FF = TRUE ;
  787.    int last_line ;
  788.    int body_lines ;
  789.    char *typeface = NULL ;
  790.    char *summary_file = NULL ;
  791.    char *formats_file = NULL ;
  792.    char *last_page_num ;
  793.    
  794.    if (argc == 1 && isatty(0))
  795.       usage() ;      /* give help if invoked with no args and keybd input */
  796.    while (argc >= 2 && argv[1][0] == '-')
  797.       {
  798.       switch (argv[1][1])
  799.      {
  800.      case 'e':
  801.         indent = 8 ;
  802.         page_width = 87 ;  /* 96 - indent - 1 right margin */
  803.         break ;
  804.      case 'P':
  805.         if (argv[1][2] == '?')
  806.            display_printers() ;
  807.         else
  808.            select_printer(argv[1]+2) ;
  809.         break ;
  810.      case 'I':
  811.         IBM_chars = TRUE ;
  812.         break ;
  813.      case 'p':
  814.         page_numbers = TRUE ;
  815.         break ;
  816.      case 'h':   /* page headers */
  817.         /* nothing yet */
  818.         break ;
  819.      case 'B':
  820.         printer_bold = TRUE ;
  821.         /* fall through to -b */
  822.      case 'b':
  823.         boldface = TRUE ;
  824.         break ;
  825.      case 'd':
  826.         duplex = TRUE ;
  827.         break ;
  828.      case 'm':
  829.         multi_file = TRUE ;
  830.         break ;
  831.      case 'n':
  832.         pages_printed = atoi(argv[1]+2) ;
  833.         break ;
  834.      case 'r':
  835.         first_page = atoi(argv[1]+2) ;
  836.         last_page_num = strchr(argv[1]+2, ':') ;
  837.         last_page = last_page_num ? atoi(last_page_num+1) : 0 ;
  838.         if (last_page == 0)
  839.            last_page = 9999 ;
  840.         break ;
  841.      case 'i':
  842.         indent = atoi(argv[1]+2) ;
  843.         break ;
  844.      case 's':
  845.         summary_file = argv[1]+2 ;
  846.         break ;
  847.      case 'f':
  848.         formats_file = argv[1]+2 ;
  849.         break ;
  850.      case 'w':
  851.         widow_length = atoi(argv[1]+2) ;
  852.         break ;
  853.      case 'l':
  854.         lines_per_page = atoi(argv[1]+2) ;
  855.         break ;
  856.      case 'L':
  857.         total_lines = atoi(argv[1]+2) ;
  858.         break ;
  859.      case 't':
  860.         typeface = argv[1]+2 ;
  861.         break ;
  862.      default:
  863.         usage() ;
  864.      }
  865.       argv++ ;
  866.       argc-- ;
  867.       }
  868.    if (printer == NULL)
  869.       select_printer("default") ;
  870.    /* apply any necessary overrides to parameters */
  871.    if (printer->indent != -1)
  872.       indent = printer->indent ;
  873.    if (lines_per_page <= 0)
  874.       lines_per_page = printer->lines_per_page ;
  875.    if (total_lines <= 0)
  876.       total_lines = printer->page_length ;
  877.    if (page_width <= 0)
  878.       page_width = printer->page_width ;
  879.    if (printer->flag)
  880.       *(printer->flag) = TRUE ;
  881.    if (cstrlen(&printer->bold_on) == 0)     /* control sequences for bold? */
  882.       printer_bold = FALSE ;        /* if not, don't try to use them */
  883.  
  884.    /* open the summary file, if any */
  885.    if (summary_file && *summary_file)
  886.       if ((summary = fopen(summary_file, pages_printed ? "a":"w")) != NULL)
  887.      do_summary = TRUE ;
  888.       else
  889.      fputs("unable to open summary file\n", stderr) ;
  890.    /* open the data formats file, if any */
  891.    if (formats_file && *formats_file)
  892.       if ((formats = fopen(formats_file, pages_printed ? "a":"w")) != NULL)
  893.      do_formats = TRUE ;
  894.       else
  895.      fputs("unable to open formats file\n", stderr) ;
  896.    if (total_lines <= lines_per_page)
  897.       {
  898.       total_lines = lines_per_page ;
  899.       use_FF = TRUE ;
  900.       }
  901.    else
  902.       use_FF = FALSE ;
  903.    if (argc == 2 || argc == 3)
  904.       {
  905.       input_file = argv[1] ;
  906.       infile = fopen(input_file,"r") ;
  907.       if (infile == NULL)
  908.      fatal("unable to open input file") ;
  909.       if (argc == 3)
  910.      {
  911.      outfile = fopen(argv[2],(pages_printed?"a":"w")) ;
  912.      if (outfile == NULL)
  913.         fatal("unable to open output file") ;
  914.      }
  915.       else
  916.      outfile = stdout ;
  917.       }
  918.    else
  919.       usage() ;
  920.    if (lines_per_page < 20 || lines_per_page > MAXPAGE)
  921.       {
  922.       fputs("Surely you jest!  At least 20 and at most 200 lines per page.\n\n", stderr) ;
  923.       usage() ;
  924.       }
  925.    if (widow_length < 3 || widow_length > lines_per_page / 2)
  926.       {
  927.       fputs("Widow lines (-w) must be set to at least 3 and at most one-half of the\n",stderr) ;
  928.       fputs("page length.  Using default of 10 lines.\n",stderr) ;
  929.       widow_length = 10 ;
  930.       }
  931. #ifdef __TURBOC__
  932.    setvbuf(infile,NULL,_IOFBF,10240) ;    /* use larger disk buffers */
  933.    setvbuf(outfile,NULL,_IOFBF,10240) ; /* for better performance */
  934.    if (do_summary)
  935.       setvbuf(summary,NULL,_IOFBF,4096) ;
  936.    if (do_formats)
  937.       setvbuf(formats,NULL,_IOFBF,4096) ;
  938. #endif /* __TURBOC__ */
  939.    /* set up the printer */
  940.    fputcstr(&printer->init1,outfile) ;
  941.    fputcstr(&printer->init2,outfile) ;
  942.    if (HPPCL_mode)
  943.       {
  944.       fputs(HPPCL_FONT_ON_A,outfile) ;
  945.       if (typeface)
  946.      fputs(typeface,outfile) ;
  947.       else
  948.      fputs("8",outfile) ;
  949.       fputs(HPPCL_FONT_ON_B,outfile) ;
  950.       }
  951.    if (duplex)
  952.       {
  953.       fputcstr(&printer->duplex_on,outfile) ;
  954.       if ((pages_printed % 2) == 1)    /* next page odd or even? */
  955.      fputcstr(&printer->marginl,outfile) ;    /* even */
  956.       else
  957.      fputcstr(&printer->marginr,outfile) ;    /* odd */
  958.       }
  959.    else
  960.       fputcstr(&printer->marginc,outfile) ;    /* non-duplex, so center */
  961.    /* start the summary file */
  962.    if (do_summary && pages_printed == 0)
  963.       {          /* create header, but only on first part */
  964.       /* set up the printer */
  965.       fputcstr(&printer->init1,summary) ;
  966.       fputcstr(&printer->init2,summary) ;
  967.       fputcstr(&printer->marginc,summary) ;
  968.       indent_line(summary) ;
  969.       fputs("\t\t\t\tInterrupt Summary\n",summary) ;
  970.       indent_line(summary) ;
  971.       fputs("\t\t\t\t", summary) ;
  972.       (*printer->put_line)(summary,17) ;
  973.       fputs("\n\n",summary) ;
  974.       indent_line(summary) ;
  975.       fputs("INT AH AL", summary) ;
  976.       if (page_numbers)
  977.      fputs(" Page", summary) ;
  978.       fputs("\t\t\tDescription\n", summary) ;
  979.       indent_line(summary) ;
  980.       (*printer->put_line)(summary,page_width) ;
  981.       fputc('\n', summary) ;
  982.       }
  983.    /* start the data formats file */
  984.    if (do_formats && pages_printed == 0)
  985.       {          /* create header, but only on first part */
  986.       /* set up the printer */
  987.       fputcstr(&printer->init1,formats) ;
  988.       fputcstr(&printer->init2,formats) ;
  989.       fputcstr(&printer->marginc,formats) ;
  990.       indent_line(formats) ;
  991.       fputs("\t\t\tData Structure Formats\n", formats) ;
  992.       indent_line(formats) ;
  993.       fputs("\t\t\t", formats) ;
  994.       (*printer->put_line)(formats,22) ;
  995.       fputs("\n\n", formats) ;
  996.       indent_line(formats) ;
  997.       fputs("INT AH AL", formats) ;
  998.       if (page_numbers)
  999.      fputs(" Page", formats) ;
  1000.       fputs("\t\tData Structure\n", formats) ;
  1001.       }
  1002.    if (page_numbers)
  1003.       body_lines = lines_per_page - 2 ;
  1004.    else
  1005.       body_lines = lines_per_page ;
  1006.    last_line = 0 ;
  1007.    while (!feof(infile) && !out_of_files)
  1008.       {
  1009.       fill_buffer(last_line,body_lines) ;
  1010.       last_line = find_page_break(body_lines) ;
  1011.       print_buffer(0,last_line,lines_per_page,total_lines,use_FF) ;
  1012.       }
  1013.    if (last_line < body_lines)
  1014.       print_buffer(last_line,body_lines,lines_per_page,total_lines,use_FF) ;
  1015.    /* reset the printer */
  1016.    fputcstr(&printer->term1,outfile) ;
  1017.    fputcstr(&printer->term2,outfile) ;
  1018.    fflush(outfile) ;
  1019.    itoa(pages_printed, num, 10) ;
  1020.    fputs(num, stderr) ;
  1021.    fputs(" pages\n", stderr) ;
  1022.    if (do_summary)
  1023.       {
  1024.       /* reset the printer */
  1025.       fputcstr(&printer->term1,summary) ;
  1026.       fputcstr(&printer->term2,summary) ;
  1027.       fclose(summary) ;
  1028.       }
  1029.    if (do_formats)
  1030.       {
  1031.       /* reset the printer */
  1032.       fputcstr(&printer->term1,formats) ;
  1033.       fputcstr(&printer->term2,formats) ;
  1034.       fclose(formats) ;
  1035.       }
  1036.    fclose(infile) ;
  1037.    return 0 ;
  1038. }
  1039.