/*
* mpage.c
*/
/*
* mpage: a program to reduce pages of print so that several pages
* of output appear on one printed page.
*
* Copyright (c) 1994-2004 Marcel J.E. Mol, The Netherlands
* 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 is preserved, and that the
* distributor grants the recipient permission for further
* redistribution as permitted by this notice.
*
*/
#include "mpage.h"
#include <string.h>
#include <time.h>
#include <fcntl.h>
#include <locale.h>
#include "encoding.h"
/*
* Function Declarations
*/
static void ps_title();
char *current_locale;
int
main(argc, argv)
int argc;
char **argv;
{
FILE *outfd;
int currarg;
struct sheet *thelist;
struct sheet *thesheet;
char outcommand[LINESIZE]; /* the command which is the output filter */
current_locale = setlocale(LC_ALL,"");
#ifdef __EMX__
/*
* wildcard expansion from emx package (used by OS/2)
*/
_wildcard (&argc, &argv);
#endif
/*
* Check page size for /etc/papersize
*/
check_papersize();
/*
* examine the environment for PRINTER (or LPDEST) and MPAGE
* environment variables
*/
if ((currarg = do_env()) < 0) {
usage(currarg);
exit(1);
}
if ((currarg = do_args(argc, argv, 0)) < 0) {
usage(currarg);
exit(1);
}
/*
* if a print queue was specified then create a print command using
* the queue, else use standard output.
*/
if (doprint) {
if (printque != NULL)
(void) sprintf(outcommand, "%s %s%s",
printprog, printarg, printque);
else
(void) strcpy(outcommand, printprog);
if ((outfd = popen(outcommand, "w")) == NULL) {
fprintf(stderr, "%s: cannot create pipe for '%s'\n",
MPAGE, outcommand);
perror(MPAGE);
}
}
else
outfd = stdout;
/*
* pick the array of sheet lists based upon the specified option
*/
if (sheetorder == UPDOWN)
sheetlist = up_down;
else
sheetlist = left_right;
/*
* from the array of sheet lists pick the proper sheet list for
* the given sheetaspect, then select the proper sheet format
* for the given number of redueced pages per output page
*/
thelist = sheetlist[sheetaspect];
thesheet = &(thelist[sheetindex]);
/* GPN. */
if (Coli == 1)
thesheet = &(coli[0]);
if (Coli == 2)
thesheet = &(coli[1]);
if (Coli == 3)
thesheet = &(coli[2]);
orientation = (sheetindex + sheetaspect) & 0x01;
/*
* if either lines or columns were specified as options, over
* the default sheets idea of the number of line or columns
* per reduced page
*/
if (opt_lines > 0)
thesheet->sh_plength = opt_lines;
if (opt_width > 0)
thesheet->sh_cwidth = opt_width;
/*
* Prepare the textbox parameters when needed
*/
if (opt_textbox) {
textbox.over = textmargin_left;
textbox.lift = textmargin_bottom;
textbox.wide = thesheet->sh_cwidth - (textmargin_left+textmargin_right);
textbox.high = thesheet->sh_plength - (textmargin_top+textmargin_bottom);
}
/*
* if there are arguments left over after processing options, then
* these are names of files to process, else process the standard
* input
*/
if (currarg < argc) {
ps_title(argv[currarg], outfd);
for ( ; currarg < argc; currarg++)
do_file(argv[currarg], thesheet, outfd);
}
else {
ps_title("<stdin>", outfd);
do_stdin(thesheet, outfd);
}
/*
* in case files are merged on sheets, make sure the last page
* is printed...
*/
if (points->pp_origin_x != 0 && !opt_file) {
if (had_ps)
fprintf(outfd, "showsheet\n");
else {
fprintf(outfd, "restore\n");
fprintf(outfd, "showpage\n");
}
}
/*
* having processed all input, print out a PS trailer
* (timing stuff stolen from old adobe troff stuff)
*/
fprintf(outfd, "%%%%Trailer\n");
if (opt_verbose) {
fprintf(outfd, "statusdict begin jobname print flush");
fprintf(outfd, " (: Job finished:\\n) print\n");
fprintf(outfd, "(\\tmpage time (s) = ) print flush usertime ");
fprintf(outfd, "mp_stm sub 1000 div ==\n(\\tmpage pages = ) print");
fprintf(outfd, " flush pagecount mp_pgc sub ==\nend flush\n");
/* fprintf(outfd, "showpage\n"); */
}
fprintf(outfd, "%%%%Pages: %d\n", ps_outpages);
if (opt_verbose) {
fprintf(stderr, "[%s: %d pages, ", MPAGE, ps_outpages);
if (doprint) {
if (printque != NULL)
fprintf(stderr, "print queue %s]\n", printque);
else
fprintf(stderr, "on default printer queue]\n");
}
else
fprintf(stderr, "on <stdout>]\n");
}
/*
* proper clean up to make sure the pipe is flushed
*/
if (doprint)
(void) pclose(outfd);
return 0;
} /* main */
/*
* ps_title prints a post script header suitable for PS processors
*/
static void
ps_title(name, outfd)
char *name;
FILE *outfd;
{
time_t curr_time;
char *time_str;
FILE * charfp;
char buf[LINESIZE];
fprintf(outfd, "%%!PS-Adobe-2.0\n");
fprintf(outfd, "%%%%DocumentFonts: %s Times-Bold\n", fontname);
fprintf(outfd, "%%%%Title: %s (%s)\n", name, MPAGE);
fprintf(outfd, "%%%%Creator: %s %s\n", MPAGE, VERSION);
(void) time(&curr_time);
time_str = ctime(&curr_time);
fprintf(outfd, "%%%%CreationDate: %s", time_str);
fprintf(outfd, "%%%%Orientation: %s\n", orientation ? "Landscape" : "Portrait");
fprintf(outfd, "%%%%DocumentMedia: %s %d %d\n", media, ps_width, ps_height);
fprintf(outfd, "%%%%BoundingBox: %d %d %d %d\n",
sheetmargin_left, sheetmargin_bottom,
ps_width - sheetmargin_right,
ps_height - sheetmargin_top);
fprintf(outfd, "%%%%Pages: (atend)\n");
fprintf(outfd, "%%%%EndComments\n\n");
fprintf(outfd, "%%%%BeginProlog\n\n");
fprintf(outfd, "/mp_stm usertime def\n");
fprintf(outfd, "/mp_pgc statusdict begin pagecount end def\n");
fprintf(outfd, "statusdict begin /jobname (%s) def end\n", name);
if (opt_duplex) {
fprintf(outfd, "statusdict /setduplexmode known");
fprintf(outfd, " { statusdict begin true setduplexmode end } if\n");
if (opt_tumble) {
fprintf(outfd, "statusdict /settumble known ");
fprintf(outfd, "{ statusdict begin true settumble end } if\n");
}
}
else {
/*
* CAN WE DO THIS FOR PRINTERS THAT DO NOT NDERSTAND DUPLEX PRINTING???
* It also seems to break for example the lp -o duplex command.
* So better switch this part of.
*/
#if 0
fprintf(outfd, "statusdict /setduplexmode known");
fprintf(outfd, " { statusdict begin false setduplexmode end } if\n");
#endif
}
if (opt_encoding) {
fprintf(outfd,
"/reencsmalldict 12 dict def "
"/ReEncodeSmall { reencsmalldict begin\n"
"/newcodesandnames exch def "
"/newfontname exch def "
"/basefontname exch def\n"
"/basefontdict basefontname findfont def "
"/newfont basefontdict maxlength dict def\n"
"basefontdict "
"{ exch dup /FID ne "
"{ dup /Encoding eq "
"{ exch dup length array copy newfont 3 1 roll put } "
"{ exch newfont 3 1 roll put }\n"
"ifelse }\n"
" { pop pop }\n"
" ifelse } "
"forall\n"
"newfont /FontName newfontname put\n"
"newcodesandnames aload pop "
"newcodesandnames length 2 idiv\n"
"{ newfont /Encoding get 3 1 roll put } "
"repeat\n"
"newfontname newfont definefont pop "
"end } def\n");
fprintf(outfd, "/charvec [\n");
if (charvec_file != NULL) {
if ((charfp = fopen(charvec_file, "r")) == NULL) {
perror(charvec_file);
exit(1);
}
while (fgets(buf, LINESIZE, charfp) != NULL) {
if (*buf != '%' && *buf != '\n') {
if (first_encoding == -1) {
first_encoding = atoi(buf);
last_encoding = atoi(strchr(buf, ' '));
# ifdef DEBUG
fprintf(stderr, "first=%d, last=%d\n",
first_encoding, last_encoding);
#endif
}
else
fprintf(outfd, "%s", buf);
}
}
}
else { /* use internal default encoding */
int i;
first_encoding = encoding_table_first;
last_encoding = encoding_table_last;
for (i = 0; i <= last_encoding - first_encoding; i++)
fprintf(outfd, "%s\n", encoding_table[i]);
}
fprintf(outfd, "] def\n");
fprintf(outfd, "/%s /OurCharSet charvec ReEncodeSmall\n", fontname);
}
else {
first_encoding = ' ';
last_encoding = '~';
}
fprintf(outfd, "/textfont /%s findfont %d scalefont def\n",
opt_encoding ? "OurCharSet" : fontname, fsize - 1);
fprintf(outfd, "/textfontbold /%s-Bold findfont %d scalefont def\n",
opt_encoding ? "OurCharSet" : fontname, fsize - 1);
fprintf(outfd, "/fnamefont /Times-Bold findfont %d scalefont def\n", HSIZE);
fprintf(outfd, "/headerfont /Times-Bold findfont %d scalefont def\n",
HSIZE - 2);
fprintf(outfd, "textfont setfont\n");
fprintf(outfd, "(a) stringwidth pop /mp_a_x exch def\n");
if (current_locale){
if (!strncmp (current_locale, "ja_JP", 5)){
#ifdef KANJI
#ifdef GOTHIC
fprintf(outfd, "/kanj /GothicBBB-Medium-H findfont %d scalefont def\n", fsize - 1);
fprintf(outfd, "/han /GothicBBB-Medium.Hankaku findfont %d scalefont def\n", fsize - 1);
#else
fprintf(outfd, "/kanj /Ryumin-Light-H findfont %d scalefont def\n", fsize - 1);
fprintf(outfd, "/han /Ryumin-Light.Hankaku findfont %d scalefont def\n", fsize - 1);
#endif
#endif
#ifdef GOTHIC
fprintf(outfd, "/unijis /GothicBBB-Medium-UniJIS-UTF8-H findfont %d scalefont def\n", fsize - 1);
#else
fprintf(outfd, "/unijis /Ryumin-Light-UniJIS-UTF8-H findfont %d scalefont def\n", fsize - 1);
#endif
}
else if (!strncmp (current_locale, "ko_KR", 5))
fprintf(outfd, "/uniks /Baekmuk-Batang-UniKS-UTF8-H findfont %d scalefont def\n", fsize - 1);
else if (!strncmp (current_locale, "zh_CN", 5))
fprintf(outfd, "/unigb /BousungEG-Light-GB-UniGB-UTF8-H findfont %d scalefont def\n", fsize - 1);
else if (!strncmp (current_locale, "zh_TW", 5))
fprintf(outfd, "/unicns /ShanHeiSun-Light-UniCNS-UTF8-H findfont %d scalefont def\n", fsize - 1);
}
# ifdef DEBUG
if (Debug_flag & DB_PSMPAGE)
fprintf(outfd, "(\\t'a' length ) print mp_a_x ==\nflush\n");
# endif
fprintf(outfd, "%%%%EndProlog\n");
if (opt_duplex) {
fprintf(outfd, "%%%%BeginSetup\n");
if (opt_tumble) {
fprintf(outfd, "%%%%BeginFeature: *Duplex DuplexTumble\n");
fprintf(outfd, "<< /Duplex true /Tumble true >> setpagedevice\n");
fprintf(outfd, "%%%%EndFeature\n");
}
else {
fprintf(outfd, "%%%%BeginFeature: *Duplex DuplexNoTumble\n");
fprintf(outfd, "<< /Duplex true /Tumble false >> setpagedevice\n");
fprintf(outfd, "%%%%EndFeature\n");
}
fprintf(outfd, "%%%%EndSetup\n");
}
return;
} /* ps_title */
|