home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume9
/
mpage
/
part01
/
mp_text.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-12-26
|
10KB
|
363 lines
# include <stdio.h>
# include <sys/types.h>
# ifndef lint
static char *rcs_id =
"@(#) $Header: mp_text.c,v 2.8 89/06/23 13:14:00 mark Exp $";
# endif
# include "mp_head.h"
/*
* mpage: a program to reduce pages of print so that several pages
* of output appear on one printed sheet.
*
* Written by:
* ...!uunet!\ Mark Hahn, Sr Systems Engineer
* >pyrdc!mark Pyramid Technology Corporation
* ...!pyramid!/ Vienna, Va (703)848-2050
*
*
* Copyright (c) 1988 Mark P. Hahn, Herndon, Virginia
*
* Permission is granted to anyone to make or distribute verbatim
* copies of this document as received, in any medium, provided
* that this copyright notice notice is preserved, and that the
* distributor grants the recipient permission for further
* redistribution as permitted by this notice.
*
*/
/* $Log: mp_text.c,v $
* Revision 2.8 89/06/23 13:14:00 mark
* Fixed range checking for control characters so that tilde was
* included as a printable character.
*
* Revision 2.7 89/06/21 08:58:56 mark
* moved the bottom of the clipping region for text below zero so that
* decenders on the last line can be seen. Currently the font, font size
* and this extra space are hard coded. Something more reasonable should
* be done. Probably involves more command line options. (Sorry, "Something
* more reasonable" should be "something more flexible")
*
* Revision 2.6 89/05/25 10:20:11 mark
* changed the format of debugging prints in the PS code.
*
* Revision 2.5 89/05/25 09:01:51 mark
* rearranged the rcs header keywords for better readability.
*
* Revision 2.4 89/05/24 17:36:56 mark
* fixed the $Log: mp_text.c,v $
* Revision 2.8 89/06/23 13:14:00 mark
* Fixed range checking for control characters so that tilde was
* included as a printable character.
*
* Revision 2.7 89/06/21 08:58:56 mark
* moved the bottom of the clipping region for text below zero so that
* decenders on the last line can be seen. Currently the font, font size
* and this extra space are hard coded. Something more reasonable should
* be done. Probably involves more command line options. (Sorry, "Something
* more reasonable" should be "something more flexible")
*
* Revision 2.6 89/05/25 10:20:11 mark
* changed the format of debugging prints in the PS code.
*
* Revision 2.5 89/05/25 09:01:51 mark
* rearranged the rcs header keywords for better readability.
* rcs keyword.
* */
/*
* keeps track of the current location on the sheet. it is kept global
* to while file printing process because of form feeds in particular.
* form feeds change the vertical page location (line number) but not
* the horizontal location (character column)
*/
struct pageloc {
int pl_line;
int pl_col;
int pl_new_line;
int pl_new_col;
};
static struct pageloc loc;
/*
* do_text_doc processes an input stream fd, reducing output to fit on
* a printed page as decribed by asheet, and prints this on outfd.
*/
do_text_doc(fd, asheet, outfd)
FILE *fd;
struct sheet *asheet;
FILE *outfd;
{
do_text_prolog(outfd);
/*
* initalize the postion on the first printed page
*/
loc.pl_line = 1;
loc.pl_col = 0;
/*
* while we have input, print a page
*/
while (do_text_sheet(fd, asheet, outfd) != FILE_EOF)
;
}
/*
* ps_text_prolog prints mpage startup information for plain text documents
*/
do_text_prolog(outfd)
FILE *outfd;
{
time_t curr_time;
char *time_str;
fprintf(outfd, "/Courier findfont %d scalefont setfont\n", fsize -1);
fprintf(outfd, "(a) stringwidth pop /mp_a_x exch def\n");
fprintf(outfd, "(\\t'a' length ) print mp_a_x == ");
fprintf(outfd, "flush\n");
fprintf(outfd, "%%%%EndProlog\n");
}
/*
* do_text_sheet creates one printed sheet consisting of several reduced pages
*/
do_text_sheet(fd, asheet, outfd)
FILE *fd;
struct sheet *asheet;
FILE *outfd;
{
char **outline;
struct pagepoints *points;
int rtn_val;
/*
* keep track of the pages printed
*/
ps_pagenum += 1;
fprintf(outfd, "%%%%Page: %d %d\n", ps_pagenum, ps_pagenum);
# ifdef DEBUG
if (Debug_flag & DB_PSMPAGE) {
fprintf(outfd, "(Page: %d\\n) print flush\n", ps_pagenum);
}
# endif DEBUG
fprintf(outfd, "save\n"); /* for better memory usage */
/*
* print the page outline, which draws lines and such
*/
mp_outline(outfd, asheet);
/*
* run through the list of base points for putting reduced pages
* on the printed page
*/
points = asheet->sh_pagepoints;
while (points->pp_origin_x != 0) {
/*
* print one reduced page by moveing to the proper point,
* turning to the proper aspect, scaling to the proper
* size, and setting up a clip path to prevent overwritting;
* the print a reduced page of output
*/
fprintf(outfd, "gsave\n");
# ifdef DEBUG
if (Debug_flag & DB_PSMPAGE) {
fprintf(outfd, "( %d %d translate %d rotate\\n)",
points->pp_origin_x(), points->pp_origin_y(),
asheet->sh_rotate);
fprintf(outfd, " print flush\n");
}
# endif DEBUG
fprintf(outfd, "%d %d translate %d rotate\n",
points->pp_origin_x(), points->pp_origin_y(),
asheet->sh_rotate);
fprintf(outfd, "%d %d mp_a_x mul div %d %d div scale\n",
(*asheet->sh_width)(), asheet->sh_cwidth,
(*asheet->sh_height)(), asheet->sh_plength * fsize);
/*
* output the clip path (the bottom of the cliping region
* is 1/2 the font size below "0" so that you can see decenders
* on the last line of each page
*/
fprintf(outfd, "0 -4 moveto 0 %d lineto %d mp_a_x mul ",
asheet->sh_plength * fsize, asheet->sh_cwidth);
fprintf(outfd, "%d lineto %d mp_a_x mul -4 lineto\n",
asheet->sh_plength * fsize, asheet->sh_cwidth);
fprintf(outfd, "closepath clip\n");
/*
* place one reduced page on the printed page
*/
rtn_val = text_onepage(fd, asheet, outfd);
/*
* clean up this page and move to the next
*/
fprintf(outfd, "grestore\n");
points++;
}
/*
* release PS vm used, and eject the sheet
*/
fprintf(outfd, "restore\n");
fprintf(outfd, "showpage\n");
/*
* let the upper level know about the status of possible EOF
*/
return rtn_val;
}
/*
* onepage places on page of reduced output on the printed page
* all scaling, translation, and rotation has already been done before
*/
text_onepage(file, asheet, outfd)
FILE *file;
struct sheet *asheet;
FILE *outfd;
{
char *text;
char linenum;
int pos;
char *mp_get_text();
/*
* as we move from one page to the next, restart printing text at
* the head of the page. horziontal location is not reset because
* form feeds leave the column the same from page to page.
*/
Debug(DB_ONEPAGE, "%% reseting line to top of page\n", 0);
loc.pl_line = 1;
/*
* keep getting lines of input, until we have filled a page
*/
while (loc.pl_line <= asheet->sh_plength) {
text = mp_get_text(file, &loc);
Debug(DB_ONEPAGE, "%% text = %d\n", text);
if (text == 0) {
return FILE_EOF;
}
Debug(DB_ONEPAGE, "%% text = (%s)\n", text);
Debug(DB_ONEPAGE, "%% loc.pl_line = %d\n", loc.pl_line);
Debug(DB_ONEPAGE, "%% loc.pl_col = %d\n", loc.pl_col);
Debug(DB_ONEPAGE, "%% loc.pl_new_line = %d\n",loc.pl_new_line);
Debug(DB_ONEPAGE, "%% loc.pl_new_col = %d\n", loc.pl_new_col);
if (text[0] != 0) {
/* fprintf(outfd, "(%s\\n) print flush\n", text); */
fprintf(outfd, "%d mp_a_x mul %d moveto (%s) show\n",
loc.pl_col,
(asheet->sh_plength - loc.pl_line) * fsize,
text);
}
if (loc.pl_new_line == -1) {
loc.pl_col = loc.pl_new_col;
return FILE_MORE;
}
loc.pl_line = loc.pl_new_line;
loc.pl_col = loc.pl_new_col;
}
return FILE_MORE;
}
static char text[LINESIZE];
char *mp_get_text(infile, locp)
FILE *infile;
struct pageloc *locp;
{
int gathering;
int tabcnt;
int ichr;
char *textp;
textp = text;
locp->pl_new_line = locp->pl_line;
locp->pl_new_col = locp->pl_col;
gathering = 1;
while (gathering) {
ichr = fgetc(infile);
Debug(DB_GETLINE, "%%called fgetc ichr = %d", ichr);
Debug(DB_GETLINE, "(%d)\n", EOF);
/*
* this prevents nulls in the input from confusing the
* program logic with truncated strings
*/
if (ichr == 0) {
ichr = 1;
}
switch (ichr) {
case EOF:
gathering = 0;
return 0;
break;
case '\n':
locp->pl_new_line += 1;
locp->pl_new_col = 0;
gathering = 0;
break;
case '\r':
locp->pl_col = 0;
gathering = 0;
break;
case '\b':
locp->pl_new_col -= 1;
if (locp->pl_new_col < 0) {
locp->pl_new_col = 0;
}
gathering = 0;
break;
case '\f':
locp->pl_new_line = -1;
gathering = 0;
break;
case '\t':
tabcnt = 8 - (locp->pl_new_col % 8);
locp->pl_new_col += tabcnt;
gathering = 0;
break;
/**/
/* case ' ':
/* locp->pl_new_col += 1;
/* gathering = 0;
/* break;
/**/
case '(':
case ')':
case '\\':
*textp++ = '\\';
*textp++ = ichr;
locp->pl_new_col += 1;
break;
default:
if (ichr >= ' ' && ichr <= '~') {
*textp++ = ichr;
locp->pl_new_col += 1;
} else {
*textp++ = '\\';
*textp++ = '2';
*textp++ = '7';
*textp++ = '7';
locp->pl_new_col += 1;
}
break;
}
}
*textp = 0;
/*
* remove any spaces at the front of the text string by
* "converting" it to a position change
*/
textp = text;
while (*textp && *textp == ' ') {
/*
* this affects the starting position of this text string
* (not the next)
*/
locp->pl_col += 1;
textp++;
}
return textp;
}