Old mpage.c
  1 /*
  2  * mpage.c
  3  */
  4 
  5 /*
  6  * mpage:    a program to reduce pages of print so that several pages
  7  *           of output appear on one printed page.
  8  *
  9  * Copyright (c) 1994-2004 Marcel J.E. Mol, The Netherlands
 10  * Copyright (c) 1988 Mark P. Hahn, Herndon, Virginia
 11  *  
 12  *     Permission is granted to anyone to make or distribute verbatim
 13  *     copies of this document as received, in any medium, provided
 14  *     that this copyright notice is preserved, and that the
 15  *     distributor grants the recipient permission for further
 16  *     redistribution as permitted by this notice.
 17  *
 18  */
 19 
 20 #include "mpage.h"
 21 #include <string.h>
 22 #include <time.h>
 23 #include <fcntl.h>
 24 #include <locale.h>
 25 
 26 
 27 #include "encoding.h"
 28 
 29 /*
 30  * Function Declarations
 31  */
 32 static void ps_title();
 33 
 34 char *current_locale;
 35 
 36 int
 37 main(argc, argv)
 38 int argc;
 39 char **argv;
 40 {
 41     FILE *outfd;
 42     int currarg;
 43     struct sheet *thelist;
 44     struct sheet *thesheet;
 45     char outcommand[LINESIZE]; /* the command which is the output filter */
 46 
 47     current_locale = setlocale(LC_ALL,"");
 48 
 49    
 50 #ifdef __EMX__
 51     /*
 52      * wildcard expansion from emx package (used by OS/2)
 53      */
 54     _wildcard (&argc, &argv);
 55 #endif
 56 
 57     /*
 58      * examine the environment for PRINTER (or LPDEST) and MPAGE
 59      * environment variables
 60      */
 61     if ((currarg = do_env()) < 0) {
 62         usage(currarg);
 63         exit(1);
 64     }
 65         
 66     if ((currarg = do_args(argc, argv, 0)) < 0) {
 67         usage(currarg);
 68         exit(1);
 69     }
 70 
 71     /*
 72      * if a print queue was specified then create a print command using
 73      * the queue, else use standard output.
 74      */
 75     if (doprint) {
 76         if (printque != NULL)
 77             (void) sprintf(outcommand, "%s %s%s",
 78                            printprog, printarg, printque);
 79         else
 80             (void) strcpy(outcommand, printprog);
 81         if ((outfd = popen(outcommand, "w")) == NULL) {
 82             fprintf(stderr, "%s: cannot create pipe for '%s'\n",
 83                             MPAGE, outcommand);
 84             perror(MPAGE);
 85         }
 86     }
 87     else
 88         outfd = stdout;
 89 
 90     /*
 91      * pick the array of sheet lists based upon the specified option
 92      */
 93     if (sheetorder == UPDOWN)
 94         sheetlist = up_down;
 95     else
 96         sheetlist = left_right;
 97 
 98     /*
 99      * from the array of sheet lists pick the proper sheet list for
100      * the given sheetaspect, then select the proper sheet format
101      * for the given number of redueced pages per output page
102      */
103     thelist = sheetlist[sheetaspect];
104     thesheet = &(thelist[sheetindex]);
105 
106     /* GPN. */
107     if (Coli == 1)
108         thesheet = &(coli[0]);
109     if (Coli == 2)
110         thesheet = &(coli[1]);
111     if (Coli == 3)
112         thesheet = &(coli[2]);
113 
114     orientation = (sheetindex + sheetaspect) & 0x01;
115 
116     /*
117      * if either lines or columns were specified as options, over
118      * the default sheets idea of the number of line or columns
119      * per reduced page
120      */
121     if (opt_lines > 0)
122         thesheet->sh_plength = opt_lines;
123     if (opt_width > 0)
124         thesheet->sh_cwidth = opt_width;
125 
126     /*
127      * Prepare the textbox parameters when needed
128      */
129     if (opt_textbox) {
130         textbox.over = textmargin_left;
131         textbox.lift = textmargin_bottom;
132         textbox.wide = thesheet->sh_cwidth  - (textmargin_left+textmargin_right);
133         textbox.high = thesheet->sh_plength - (textmargin_top+textmargin_bottom);
134     }
135 
136     /*
137      * if there are arguments left over after processing options, then
138      * these are names of files to process, else process the standard
139      * input
140      */
141     if (currarg < argc) {
142         ps_title(argv[currarg], outfd);
143         for ( ; currarg < argc; currarg++)
144             do_file(argv[currarg], thesheet, outfd);
145     }
146     else {
147         ps_title("<stdin>", outfd);
148         do_stdin(thesheet, outfd);
149     }
150 
151     /*
152      * in case files are merged on sheets, make sure the last page
153      * is printed...
154      */
155     if (points->pp_origin_x != 0 && !opt_file) {
156         if (had_ps)
157             fprintf(outfd, "showsheet\n");
158         else {
159             fprintf(outfd, "restore\n");
160             fprintf(outfd, "showpage\n");
161         }
162     }
163 
164     /*
165      * having processed all input, print out a PS trailer
166      * (timing stuff stolen from old adobe troff stuff)
167      */
168     fprintf(outfd, "%%%%Trailer\n");
169     if (opt_verbose) {
170         fprintf(outfd, "statusdict begin jobname print flush");
171         fprintf(outfd, " (: Job finished:\\n) print\n");
172         fprintf(outfd, "(\\tmpage time (s) = ) print flush usertime ");
173         fprintf(outfd, "mp_stm sub 1000 div ==\n(\\tmpage pages = ) print");
174         fprintf(outfd, " flush pagecount mp_pgc sub ==\nend flush\n");
175         /* fprintf(outfd, "showpage\n"); */
176     }
177     fprintf(outfd, "%%%%Pages: %d\n", ps_outpages);
178     if (opt_verbose) {
179         fprintf(stderr, "[%s: %d pages, ", MPAGE, ps_outpages);
180         if (doprint) {
181             if (printque != NULL)
182                 fprintf(stderr, "print queue %s]\n", printque);
183             else
184                 fprintf(stderr, "on default printer queue]\n");
185         }
186         else
187             fprintf(stderr, "on <stdout>]\n");
188     }
189     /*
190      * proper clean up to make sure the pipe is flushed
191      */
192     if (doprint)
193         (void) pclose(outfd);
194 
195     return 0;
196 
197 } /* main */
198 
199 
200 
201 /*
202  * ps_title prints a post script header suitable for PS processors
203  */
204 static void
205 ps_title(name, outfd)
206  char *name;
207  FILE *outfd;
208 {
209     time_t curr_time;
210     char *time_str;
211     FILE * charfp;
212     char buf[LINESIZE];
213 
214     fprintf(outfd, "%%!PS-Adobe-2.0\n");
215     fprintf(outfd, "%%%%DocumentFonts: %s Times-Bold\n", fontname);
216     fprintf(outfd, "%%%%Title: %s (%s)\n", name, MPAGE);
217     fprintf(outfd, "%%%%Creator: %s %s\n", MPAGE, VERSION);
218     (void) time(&curr_time);
219     time_str = ctime(&curr_time);
220     fprintf(outfd, "%%%%CreationDate: %s", time_str);
221     fprintf(outfd, "%%%%Orientation: %s\n", orientation ? "Landscape" : "Portrait");
222     fprintf(outfd, "%%%%DocumentMedia: %s %d %d\n", media, ps_width, ps_height);
223     fprintf(outfd, "%%%%BoundingBox: %d %d %d %d\n",
224                    sheetmargin_left, sheetmargin_bottom,
225                    ps_width - sheetmargin_right,
226                    ps_height - sheetmargin_top);
227     fprintf(outfd, "%%%%Pages: (atend)\n");
228     fprintf(outfd, "%%%%EndComments\n\n");
229     fprintf(outfd, "%%%%BeginProlog\n\n");
230     fprintf(outfd, "/mp_stm usertime def\n");
231     fprintf(outfd, "/mp_pgc statusdict begin pagecount end def\n");
232     fprintf(outfd, "statusdict begin /jobname (%s) def end\n", name);
233     if (opt_duplex) {
234        fprintf(outfd, "statusdict /setduplexmode known");
235        fprintf(outfd, " { statusdict begin true setduplexmode end } if\n");
236        if (opt_tumble) {
237            fprintf(outfd, "statusdict /settumble known ");
238            fprintf(outfd, "{ statusdict begin true settumble end } if\n"); 
239        }
240     }
241     else {
242        /*
243         * CAN WE DO THIS FOR PRINTERS THAT DO NOT NDERSTAND DUPLEX PRINTING??? 
244         * It also seems to break for example the lp -o duplex command.
245         * So better switch this part of.
246         */
247 #if 0
248        fprintf(outfd, "statusdict /setduplexmode known");
249        fprintf(outfd, " { statusdict begin false setduplexmode end } if\n");
250 #endif
251     }
252 
253     if (opt_encoding) {
254         fprintf(outfd,
255                 "/reencsmalldict 12 dict def "
256                 "/ReEncodeSmall { reencsmalldict begin\n"
257                 "/newcodesandnames exch def "
258                 "/newfontname exch def "
259                 "/basefontname exch def\n"
260                 "/basefontdict basefontname findfont def "
261                 "/newfont basefontdict maxlength dict def\n"
262                 "basefontdict "
263                 "{ exch dup /FID ne "
264                   "{ dup /Encoding eq "
265                     "{ exch dup length array copy newfont 3 1 roll put } "
266                     "{ exch newfont 3 1 roll put }\n"
267                     "ifelse }\n"
268                 "  { pop pop }\n"
269                 "  ifelse } "
270                 "forall\n"
271                 "newfont /FontName newfontname put\n"
272                 "newcodesandnames aload pop "
273                 "newcodesandnames length 2 idiv\n"
274                 "{ newfont /Encoding get 3 1 roll put } "
275                 "repeat\n"
276                 "newfontname newfont definefont pop "
277                 "end } def\n");
278 
279         fprintf(outfd, "/charvec [\n");
280 
281         if (charvec_file != NULL) {
282             if ((charfp = fopen(charvec_file, "r")) == NULL) {
283                 perror(charvec_file);
284                 exit(1);
285             }
286             while (fgets(buf, LINESIZE, charfp) != NULL) {
287                 if (*buf != '%' && *buf != '\n') {
288                     if (first_encoding == -1) {
289                         first_encoding = atoi(buf);
290                         last_encoding = atoi(strchr(buf, ' '));
291 # ifdef DEBUG
292                         fprintf(stderr, "first=%d, last=%d\n",
293                                         first_encoding, last_encoding);
294 #endif
295                     }
296                     else
297                         fprintf(outfd, "%s", buf);
298                 }
299             }
300         }
301         else { /* use internal default encoding */
302             int i;
303 
304             first_encoding = encoding_table_first;
305             last_encoding  = encoding_table_last;
306             for (i = 0; i <= last_encoding - first_encoding; i++)
307                 fprintf(outfd, "%s\n", encoding_table[i]);
308         }
309         fprintf(outfd, "] def\n");
310         fprintf(outfd, "/%s /OurCharSet charvec ReEncodeSmall\n", fontname);
311     }
312     else {
313         first_encoding = ' ';
314         last_encoding = '~';
315     }
316 
317     fprintf(outfd, "/textfont /%s findfont %d scalefont def\n",
318                    opt_encoding ? "OurCharSet" : fontname, fsize - 1);
319     fprintf(outfd, "/textfontbold /%s-Bold findfont %d scalefont def\n",
320                    opt_encoding ? "OurCharSet" : fontname, fsize - 1);
321     fprintf(outfd, "/fnamefont /Times-Bold findfont %d scalefont def\n", HSIZE);
322     fprintf(outfd, "/headerfont /Times-Bold findfont %d scalefont def\n",
323                    HSIZE - 2);
324     fprintf(outfd, "textfont setfont\n");
325     fprintf(outfd, "(a) stringwidth pop /mp_a_x exch def\n");
326 
327     if (current_locale){
328       if (!strncmp (current_locale, "ja_JP", 5)){
329 #ifdef KANJI
330 #ifdef GOTHIC
331         fprintf(outfd, "/kanj /GothicBBB-Medium-H findfont %d scalefont def\n", fsize - 1);
332         fprintf(outfd, "/han /GothicBBB-Medium.Hankaku findfont %d scalefont def\n", fsize - 1);
333 #else
334         fprintf(outfd, "/kanj /Ryumin-Light-H findfont %d scalefont def\n", fsize - 1);
335         fprintf(outfd, "/han /Ryumin-Light.Hankaku findfont %d scalefont def\n", fsize - 1);
336 #endif
337 #endif
338 #ifdef GOTHIC
339         fprintf(outfd, "/unijis /GothicBBB-Medium-UniJIS-UTF8-H findfont %d scalefont def\n", fsize - 1);
340 #else
341         fprintf(outfd, "/unijis /Ryumin-Light-UniJIS-UTF8-H findfont %d scalefont def\n", fsize - 1);
342 #endif
343       }
344       else if (!strncmp (current_locale, "ko_KR", 5))
345         fprintf(outfd, "/uniks /Baekmuk-Batang-UniKS-UTF8-H findfont %d scalefont def\n", fsize - 1);
346       else if (!strncmp (current_locale, "zh_CN", 5))
347         fprintf(outfd, "/unigb /BousungEG-Light-GB-UniGB-UTF8-H findfont %d scalefont def\n", fsize - 1);
348       else if (!strncmp (current_locale, "zh_TW", 5))
349         fprintf(outfd, "/unicns /ShanHeiSun-Light-UniCNS-UTF8-H findfont %d scalefont def\n", fsize - 1);
350     }
351 
352 # ifdef DEBUG
353     if (Debug_flag & DB_PSMPAGE)
354         fprintf(outfd, "(\\t'a' length ) print mp_a_x ==\nflush\n");
355 # endif
356     fprintf(outfd, "%%%%EndProlog\n");
357 
358     if (opt_duplex) {
359         fprintf(outfd, "%%%%BeginSetup\n");
360         if (opt_tumble) {
361             fprintf(outfd, "%%%%BeginFeature: *Duplex DuplexTumble\n");
362             fprintf(outfd, "<< /Duplex true /Tumble true >> setpagedevice\n");
363             fprintf(outfd, "%%%%EndFeature\n");
364         }
365         else {
366             fprintf(outfd, "%%%%BeginFeature: *Duplex DuplexNoTumble\n");
367             fprintf(outfd, "<< /Duplex true /Tumble false >> setpagedevice\n");
368             fprintf(outfd, "%%%%EndFeature\n");
369         }
370         fprintf(outfd, "%%%%EndSetup\n");
371     }
372 
373     return;
374 
375 } /* ps_title */
376