/* * 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 #include #include #include #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("", 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 ]\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 */