home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 19 Printer / 19-Printer.zip / mpage.zip / mp_text.c < prev    next >
Text File  |  1997-09-25  |  10KB  |  363 lines

  1. # include <stdio.h>
  2. # include <sys/types.h>
  3.  
  4. # ifndef lint
  5. static char *rcs_id =
  6.   "@(#) $Header: mp_text.c,v 2.8 89/06/23 13:14:00 mark Exp $";
  7. # endif
  8.  
  9. # include "mp_head.h"
  10.  
  11. /*
  12.  * mpage:    a program to reduce pages of print so that several pages
  13.  *           of output appear on one printed sheet.
  14.  *
  15.  * Written by:
  16.  *   ...!uunet!\                       Mark Hahn, Sr Systems Engineer
  17.  *              >pyrdc!mark            Pyramid Technology Corporation
  18.  * ...!pyramid!/                       Vienna, Va    (703)848-2050
  19.  *
  20.  *
  21.  * Copyright (c) 1988 Mark P. Hahn, Herndon, Virginia
  22.  *  
  23.  *     Permission is granted to anyone to make or distribute verbatim
  24.  *     copies of this document as received, in any medium, provided
  25.  *     that this copyright notice notice is preserved, and that the
  26.  *     distributor grants the recipient permission for further
  27.  *     redistribution as permitted by this notice.
  28.  *
  29.  */
  30.  
  31. /* $Log:    mp_text.c,v $
  32.  * Revision 2.8  89/06/23  13:14:00  mark
  33.  * Fixed range checking for control characters so that tilde was
  34.  * included as a printable character.
  35.  * 
  36.  * Revision 2.7  89/06/21  08:58:56  mark
  37.  * moved the bottom of the clipping region for text below zero so that
  38.  * decenders on the last line can be seen.  Currently the font, font size
  39.  * and this extra space are hard coded.  Something more reasonable should
  40.  * be done.  Probably involves more command line options.  (Sorry, "Something
  41.  * more reasonable" should be "something more flexible")
  42.  * 
  43.  * Revision 2.6  89/05/25  10:20:11  mark
  44.  * changed the format of debugging prints in the PS code.
  45.  * 
  46.  * Revision 2.5  89/05/25  09:01:51  mark
  47.  * rearranged the rcs header keywords for better readability.
  48.  * 
  49.  * Revision 2.4  89/05/24  17:36:56  mark
  50.  * fixed the $Log:    mp_text.c,v $
  51.  * Revision 2.8  89/06/23  13:14:00  mark
  52.  * Fixed range checking for control characters so that tilde was
  53.  * included as a printable character.
  54.  * 
  55.  * Revision 2.7  89/06/21  08:58:56  mark
  56.  * moved the bottom of the clipping region for text below zero so that
  57.  * decenders on the last line can be seen.  Currently the font, font size
  58.  * and this extra space are hard coded.  Something more reasonable should
  59.  * be done.  Probably involves more command line options.  (Sorry, "Something
  60.  * more reasonable" should be "something more flexible")
  61.  * 
  62.  * Revision 2.6  89/05/25  10:20:11  mark
  63.  * changed the format of debugging prints in the PS code.
  64.  * 
  65.  * Revision 2.5  89/05/25  09:01:51  mark
  66.  * rearranged the rcs header keywords for better readability.
  67.  *  rcs keyword.
  68.  *  */
  69.  
  70. /*
  71.  * keeps track of the current location on the sheet.  it is kept global
  72.  * to while file printing process because of form feeds in particular.
  73.  * form feeds change the vertical page location (line number) but not
  74.  * the horizontal location (character column)
  75.  */
  76. struct pageloc {
  77.     int pl_line;
  78.     int pl_col;
  79.     int pl_new_line;
  80.     int pl_new_col;
  81. };
  82. static struct pageloc loc;
  83.  
  84. /*
  85.  * do_text_doc processes an input stream fd, reducing output to fit on
  86.  * a printed page as decribed by asheet, and prints this on outfd.
  87.  */
  88. do_text_doc(fd, asheet, outfd)
  89.  FILE *fd;
  90.  struct sheet *asheet;
  91.  FILE *outfd;
  92. {
  93.     do_text_prolog(outfd);
  94.  
  95.     /*
  96.      * initalize the postion on the first printed page
  97.      */
  98.     loc.pl_line = 1;
  99.     loc.pl_col = 0;
  100.     /*
  101.      * while we have input, print a page
  102.      */
  103.     while (do_text_sheet(fd, asheet, outfd) != FILE_EOF)
  104.       ;
  105. }
  106.  
  107. /*
  108.  * ps_text_prolog prints mpage startup information for plain text documents
  109.  */
  110. do_text_prolog(outfd)
  111.  FILE *outfd;
  112. {
  113.     time_t curr_time;
  114.     char *time_str;
  115.  
  116.     fprintf(outfd, "/Courier findfont %d scalefont setfont\n", fsize -1);
  117.     fprintf(outfd, "(a) stringwidth pop /mp_a_x exch def\n");
  118.     fprintf(outfd, "(\\t'a' length ) print mp_a_x ==  ");
  119.     fprintf(outfd, "flush\n");
  120.     fprintf(outfd, "%%%%EndProlog\n");
  121. }
  122.  
  123. /*
  124.  * do_text_sheet creates one printed sheet consisting of several reduced pages
  125.  */
  126. do_text_sheet(fd, asheet, outfd)
  127.  FILE *fd;
  128.  struct sheet *asheet;
  129.  FILE *outfd;
  130. {
  131.     char **outline;
  132.     struct pagepoints *points;
  133.     int rtn_val;
  134.  
  135.     /*
  136.      * keep track of the pages printed
  137.      */
  138.     ps_pagenum += 1;
  139.     fprintf(outfd, "%%%%Page: %d %d\n", ps_pagenum, ps_pagenum);
  140. # ifdef DEBUG
  141.     if (Debug_flag & DB_PSMPAGE) {
  142.         fprintf(outfd, "(Page: %d\\n) print flush\n", ps_pagenum);
  143.     }
  144. # endif DEBUG
  145.     fprintf(outfd, "save\n"); /* for better memory usage */
  146.     /*
  147.      * print the page outline, which draws lines and such
  148.      */
  149.     mp_outline(outfd, asheet);
  150.     /*
  151.      * run through the list of base points for putting reduced pages
  152.      * on the printed page
  153.      */
  154.     points = asheet->sh_pagepoints;
  155.     while (points->pp_origin_x != 0) {
  156.         /*
  157.          * print one reduced page by moveing to the proper point,
  158.          * turning to the proper aspect, scaling to the proper
  159.          * size, and setting up a clip path to prevent overwritting;
  160.          * the print a reduced page of output
  161.          */
  162.         fprintf(outfd, "gsave\n");
  163. # ifdef DEBUG
  164.         if (Debug_flag & DB_PSMPAGE) {
  165.             fprintf(outfd, "(    %d %d translate %d rotate\\n)",
  166.                 points->pp_origin_x(), points->pp_origin_y(),
  167.                 asheet->sh_rotate);
  168.             fprintf(outfd, " print flush\n");
  169.         }
  170. # endif DEBUG
  171.         fprintf(outfd, "%d %d translate %d rotate\n",
  172.                points->pp_origin_x(), points->pp_origin_y(),
  173.                asheet->sh_rotate);
  174.         fprintf(outfd, "%d %d mp_a_x mul div %d %d div scale\n",
  175.                (*asheet->sh_width)(), asheet->sh_cwidth, 
  176.                (*asheet->sh_height)(), asheet->sh_plength * fsize);
  177.         /*
  178.          * output the clip path (the bottom of the cliping region
  179.          * is 1/2 the font size below "0" so that you can see decenders
  180.          * on the last line of each page
  181.          */
  182.         fprintf(outfd, "0 -4 moveto 0 %d lineto %d mp_a_x mul ",
  183.             asheet->sh_plength * fsize, asheet->sh_cwidth);
  184.         fprintf(outfd, "%d lineto %d mp_a_x mul -4 lineto\n",
  185.             asheet->sh_plength * fsize, asheet->sh_cwidth);
  186.         fprintf(outfd, "closepath clip\n");
  187.         /*
  188.          * place one reduced page on the printed page
  189.          */
  190.         rtn_val = text_onepage(fd, asheet, outfd);
  191.         /*
  192.          * clean up this page and move to the next
  193.          */
  194.         fprintf(outfd, "grestore\n");
  195.         points++;
  196.     }
  197.     /*
  198.      * release PS vm used, and eject the sheet
  199.      */
  200.     fprintf(outfd, "restore\n");
  201.     fprintf(outfd, "showpage\n");
  202.     /*
  203.      * let the upper level know about the status of possible EOF
  204.      */
  205.     return rtn_val;
  206. }
  207.  
  208. /*
  209.  * onepage places on page of reduced output on the printed page
  210.  * all scaling, translation, and rotation has already been done before
  211.  */
  212.  
  213. text_onepage(file, asheet, outfd)
  214.  FILE *file;
  215.  struct sheet *asheet;
  216.  FILE *outfd;
  217. {
  218.     char *text;
  219.     char linenum;
  220.     int pos;
  221.     char *mp_get_text();
  222.  
  223.     /*
  224.      * as we move from one page to the next, restart printing text at
  225.      * the head of the page. horziontal location is not reset because
  226.      * form feeds leave the column the same from page to page.
  227.      */
  228.     Debug(DB_ONEPAGE, "%% reseting line to top of page\n", 0);
  229.     loc.pl_line = 1;
  230.     /*
  231.      * keep getting lines of input, until we have filled a page
  232.      */
  233.     while (loc.pl_line <= asheet->sh_plength) {
  234.         text = mp_get_text(file, &loc);
  235.         Debug(DB_ONEPAGE, "%% text = %d\n", text);
  236.         if (text == 0) {
  237.             return FILE_EOF;
  238.         }
  239.         Debug(DB_ONEPAGE, "%% text = (%s)\n", text);
  240.         Debug(DB_ONEPAGE, "%% loc.pl_line = %d\n", loc.pl_line);
  241.         Debug(DB_ONEPAGE, "%% loc.pl_col = %d\n", loc.pl_col);
  242.         Debug(DB_ONEPAGE, "%% loc.pl_new_line = %d\n",loc.pl_new_line);
  243.         Debug(DB_ONEPAGE, "%% loc.pl_new_col = %d\n", loc.pl_new_col);
  244.         if (text[0] != 0) {
  245.             /* fprintf(outfd, "(%s\\n) print flush\n", text); */
  246.             fprintf(outfd, "%d mp_a_x mul %d moveto (%s) show\n",
  247.                 loc.pl_col,
  248.                 (asheet->sh_plength - loc.pl_line) * fsize,
  249.                 text);
  250.         }
  251.         if (loc.pl_new_line == -1) {
  252.             loc.pl_col = loc.pl_new_col;
  253.             return FILE_MORE;
  254.         }
  255.         loc.pl_line = loc.pl_new_line;
  256.         loc.pl_col = loc.pl_new_col;
  257.     }
  258.     return FILE_MORE;
  259. }
  260.  
  261.  
  262. static char text[LINESIZE];
  263.  
  264. char *mp_get_text(infile, locp)
  265.  FILE *infile;
  266.  struct pageloc *locp;
  267. {
  268.     int gathering;
  269.     int tabcnt;
  270.     int ichr;
  271.     char *textp;
  272.  
  273.     textp = text;
  274.     locp->pl_new_line = locp->pl_line;
  275.     locp->pl_new_col = locp->pl_col;
  276.  
  277.     gathering = 1;
  278.     while (gathering) {
  279.         ichr = fgetc(infile);
  280.         Debug(DB_GETLINE, "%%called fgetc ichr = %d", ichr);
  281.         Debug(DB_GETLINE, "(%d)\n", EOF);
  282.         /*
  283.          * this prevents nulls in the input from confusing the
  284.          * program logic with truncated strings
  285.          */
  286.         if (ichr == 0) {
  287.             ichr = 1;
  288.         }
  289.         switch (ichr) {
  290.         case EOF:
  291.             gathering = 0;
  292.             return 0;
  293.             break;
  294.         case '\n':
  295.             locp->pl_new_line += 1;
  296.             locp->pl_new_col = 0;
  297.             gathering = 0;
  298.             break;
  299.         case '\r':
  300.             locp->pl_col = 0;
  301.             gathering = 0;
  302.             break;
  303.         case '\b':
  304.             locp->pl_new_col -= 1;
  305.             if (locp->pl_new_col < 0) {
  306.                 locp->pl_new_col = 0;
  307.             }
  308.             gathering = 0;
  309.             break;
  310.         case '\f':
  311.             locp->pl_new_line = -1;
  312.             gathering = 0;
  313.             break;
  314.         case '\t':
  315.             tabcnt = 8 - (locp->pl_new_col % 8);
  316.             locp->pl_new_col += tabcnt;
  317.             gathering = 0;
  318.             break;
  319. /**/
  320. /*        case ' ':
  321. /*            locp->pl_new_col += 1;
  322. /*            gathering = 0;
  323. /*            break;
  324. /**/
  325.         case '(':
  326.         case ')':
  327.         case '\\':
  328.             *textp++ = '\\';
  329.             *textp++ = ichr;
  330.             locp->pl_new_col += 1;
  331.             break;
  332.         default:
  333.             if (ichr >= ' ' && ichr <= '~') {
  334.                 *textp++ = ichr;
  335.                 locp->pl_new_col += 1;
  336.             } else {
  337.                 *textp++ = '\\';
  338.                 *textp++ = '2';
  339.                 *textp++ = '7';
  340.                 *textp++ = '7';
  341.                 locp->pl_new_col += 1;
  342.             }
  343.             break;
  344.         }
  345.     }
  346.     *textp = 0;
  347.     /*
  348.      * remove any spaces at the front of the text string by
  349.      * "converting" it to a position change
  350.      */
  351.     textp = text;
  352.     while (*textp && *textp == ' ') {
  353.         /*
  354.          * this affects the starting position of this text string
  355.          * (not the next)
  356.          */
  357.         locp->pl_col += 1;
  358.         textp++;
  359.     }
  360.     return textp;
  361. }
  362.  
  363.