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