1 /*
2 * glob.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 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 *
26 */
27
28 #include "mpage.h"
29
30 /*
31 * to turn on debugging, define the preprocessor macro DEBUG and set
32 * the variable Debug_flag to the sum of the sections to debug.
33 */
34 # ifdef DEBUG
35 int Debug_flag = DB_PSMPAGE;
36 # endif
37
38
39 /*
40 * some basic PS parameters
41 */
42 int ps_width; /* number of points in the X direction see set_page() */
43 int ps_height; /* number of points in the Y direction */
44 char *media; /* name of output media */
45
46 struct page_desc paper[] = {
47 { "Letter", 612, 792 }, /* 8.5 x 11 in */
48 { "LetterSmall", 612, 792 },
49 { "Tabloid", 792, 1224 },
50 { "Ledger", 1224, 792 }, /* 8.5 x 14 in */
51 { "Legal", 612, 1008 },
52 { "Statement", 396, 612 },
53 { "Executive", 540, 720 },
54 { "A0", 2384, 3368 }, /* 840 x 1188 mm */
55 { "A1", 1684, 2384 }, /* 594 x 840 mm */
56 { "A2", 1192, 1684 }, /* 420 x 594 mm */
57 /* { "A3", 842, 1190 }, */
58 { "A3", 842, 1192 }, /* 297 x 420 mm */
59 /* ISO 216 conforming says 595x841 ... */
60 /* { "A4", 595, 842 }, */
61 { "A4", 596, 842 }, /* 210 x 297 mm */
62 { "A4Small", 595, 842 },
63 { "A5", 420, 595 },
64 { "B4", 729, 1032 },
65 { "B5", 516, 729 },
66 { "Folio", 612, 936 },
67 { "Quarto", 610, 780 },
68 { "10x14", 720, 1008 },
69 { (char *) NULL, 0, 0 }
70 };
71
72 /*
73 * the structures describe where to put the reduced pages of output on the
74 * printed page.
75 */
76 /* empty page */
77 struct pagepoints points_empty[] = {
78 { 0, 0, 0 }
79 };
80 /* base point for one page, normal aspect */
81 struct pagepoints one_normal[] = {
82 { xbase1, ybase1, 0 },
83 { 0, 0, 0 }
84 };
85 /* base points for two pages, normal aspect */
86 struct pagepoints two_normal[] = {
87 { xbase1, ytop4, 0 }, { xbase1 , ytop2, 0 },
88 { 0, 0, 0 }
89 };
90
91 /* GPN outside 2 pages */
92 struct pagepoints two_normal_co[] = {
93 {xbase1, ytop2, 0}, {0, 0, SKIP_PS},
94 {0, 0, SKIP_PS}, {xbase1, ytop4, 0},
95 {0, 0, 0}
96
97 };
98 /* GPN. inside 2 pages */
99 struct pagepoints two_normal_ci[] = {
100 {0, 0, SKIP_PS}, {xbase1, ytop4, 0},
101 {xbase1, ytop2, 0}, {0, 0, SKIP_PS},
102 {0, 0, 0}
103 };
104
105 /* GPN. all 4 pages */
106 struct pagepoints four_normal_dm[] = {
107 {xbase1, ytop2, STORE_PS}, {xbase1, ytop4, 0},
108 {xbase1, ytop2, 0}, {0, 0, 0}, {xbase1, ytop4, FLUSH_PS},
109 {0, 0, 0}
110 };
111
112 /* base points for four pages, normal aspect, running reduced pages
113 * read from left to right */
114 struct pagepoints lr_four_normal[] = {
115 { xbase1, ybase3, 0 }, { xbase2, ybase3, 0 },
116 { xbase1, ybase1, 0 }, { xbase2, ybase1, 0 },
117 { 0, 0, 0 }
118 };
119 /* base points for four pages, normal aspect, running reduced pages
120 * read from top to bottom (up/down) */
121 struct pagepoints ud_four_normal[] = {
122 { xbase1, ybase3, 0 }, { xbase1, ybase1, 0 },
123 { xbase2, ybase3, 0 }, { xbase2, ybase1, 0 },
124 { 0, 0, 0 }
125 };
126 /* base points for four pages, normal aspect, running reduced pages
127 * read from left to right, adjusting for the fact that we have a landscape
128 * input */
129 struct pagepoints land_lr_four_normal[] =
130 {
131 { xbase1, ybase1, 0 }, { xbase1, ybase3, 0 },
132 { xbase2, ybase1, 0 }, { xbase2, ybase3, 0 },
133 { 0, 0, 0}
134 };
135 /* base points for four pages, normal aspect, running reduced pages
136 * read from top to bottom (up/down), adjusting for the fact that we have a
137 * landscape input */
138 struct pagepoints land_ud_four_normal[] =
139 {
140 { xbase1, ybase1, 0 }, { xbase2, ybase1, 0 },
141 { xbase1, ybase3, 0 }, { xbase2, ybase3, 0 },
142 { 0, 0, 0}
143 };
144 /* base points for eight pages, normal aspect, running reduced pages
145 * read from left to right */
146 struct pagepoints lr_eight_normal[] = {
147 { xbase2, ytop4, 0 }, { xbase2, ytop3, 0 },
148 { xbase2, ytop2, 0 }, { xbase2, ytop1, 0 },
149 { xbase1, ytop4, 0 }, { xbase1, ytop3, 0 },
150 { xbase1, ytop2, 0 }, { xbase1, ytop1, 0 },
151 { 0, 0, 0 }
152 };
153 /* base points for eight pages, normal aspect, running reduced pages
154 * read from top to bottom (up/down) */
155 struct pagepoints ud_eight_normal[] = {
156 { xbase2, ytop4, 0 }, { xbase1, ytop4, 0 },
157 { xbase2, ytop3, 0 }, { xbase1, ytop3, 0 },
158 { xbase2, ytop2, 0 }, { xbase1, ytop2, 0 },
159 { xbase2, ytop1, 0 }, { xbase1, ytop1, 0 },
160 { 0, 0, 0 }
161 };
162 /* base points for eight pages, normal aspect, running reduced pages
163 * read from left to right, adjusting for the fact that we have a landscape
164 * input */
165 struct pagepoints land_lr_eight_normal[] =
166 {
167 { xbase1, ytop4, 0 }, { xbase2, ytop4, 0 },
168 { xbase1, ytop3, 0 }, { xbase2, ytop3, 0 },
169 { xbase1, ytop2, 0 }, { xbase2, ytop2, 0 },
170 { xbase1, ytop1, 0 }, { xbase2, ytop1, 0 },
171 { 0, 0, 0 }
172 };
173 /* base points for eight pages, normal aspect, running reduced pages
174 * read from top to bottom (up/down), adjusting for the fact that we have a
175 * landscape input */
176 struct pagepoints land_ud_eight_normal[] =
177 {
178 { xbase1, ytop4, 0 }, { xbase1, ytop3, 0 },
179 { xbase1, ytop2, 0 }, { xbase1, ytop1, 0 },
180 { xbase2, ytop4, 0 }, { xbase2, ytop3, 0 },
181 { xbase2, ytop2, 0 }, { xbase2, ytop1, 0 },
182 { 0, 0, 0}
183 };
184 /* base point for one page, in landscape */
185 struct pagepoints one_landscape[] = {
186 { xbase1, ytop4, 0 },
187 { 0, 0, 0 }
188 };
189 /* base points for two pages, in landscape */
190 struct pagepoints two_landscape[] = {
191 { xbase1, ybase3, 0 }, { xbase1, ybase1, 0 },
192 { 0, 0, 0 }
193 };
194 /* base points for four pages, in landscape, running reduced pages
195 * read from left to right */
196 struct pagepoints lr_four_landscape[] = {
197 { xbase2, ytop4, 0 }, { xbase2, ytop2, 0 },
198 { xbase1, ytop4, 0 }, { xbase1, ytop2, 0 },
199 { 0, 0, 0 }
200 };
201 /* base points for four pages, in landscape, running reduced pages
202 * read from top to bottom (up/down) */
203 struct pagepoints ud_four_landscape[] = {
204 { xbase2, ytop4, 0 }, { xbase1, ytop4, 0 },
205 { xbase2, ytop2, 0 }, { xbase1, ytop2, 0 },
206 { 0, 0, 0 }
207 };
208 /* base points for eight pages, in landscape, running reduced pages
209 * read from left to right */
210 struct pagepoints lr_eight_landscape[] = {
211 { xbase1, ybase4, 0 }, { xbase2, ybase4, 0 },
212 { xbase1, ybase3, 0 }, { xbase2, ybase3, 0 },
213 { xbase1, ybase2, 0 }, { xbase2, ybase2, 0 },
214 { xbase1, ybase1, 0 }, { xbase2, ybase1, 0 },
215 { 0, 0, 0 }
216 };
217 /* base points for eight pages, in landscape, running reduced pages
218 * read from top to bottom (up/down) */
219 struct pagepoints ud_eight_landscape[] = {
220 { xbase1, ybase4, 0 }, { xbase1, ybase3, 0 },
221 { xbase1, ybase2, 0 }, { xbase1, ybase1, 0 },
222 { xbase2, ybase4, 0 }, { xbase2, ybase3, 0 },
223 { xbase2, ybase2, 0 }, { xbase2, ybase1, 0 },
224 { 0, 0, 0 }
225 };
226
227 /* list of sheets (printed page formats) for
228 * left to right reading, in normal aspect */
229 struct sheet lr_normal[] = {
230 /* 0 */ { 80, 66, xwid1, yht1, 0, outline_1, one_normal },
231 /* 1 */ { 80, 66, yht2, xwid1, -90, outline_2, two_normal },
232 /* 2 */ { 80, 66, xwid2, yht2, 0, outline_4, lr_four_normal },
233 /* 3 */ { 80, 66, yht4, xwid2, -90, outline_8, lr_eight_normal },
234 };
235
236 /* list of sheets (printed page formats) for landscape input
237 * left to right reading, in normal aspect */
238 struct sheet land_lr_normal[] = {
239 /* 0 */ { 80, 66, xwid1, yht1, 0, outline_1, one_normal },
240 /* 1 */ { 80, 66, yht2, xwid1, -90, outline_2, two_normal },
241 /* 2 */ { 80, 66, xwid2, yht2, 0, outline_4, land_lr_four_normal },
242 /* 3 */ { 80, 66, yht4, xwid2, -90, outline_8, land_lr_eight_normal },
243 };
244
245 /* list of sheets (printed page formats) for
246 * top to bottom reading, in normal aspect */
247 struct sheet ud_normal[] = {
248 /* 0 */ { 80, 66, xwid1, yht1, 0, outline_1, one_normal },
249 /* 1 */ { 80, 66, yht2, xwid1, -90, outline_2, two_normal },
250 /* 2 */ { 80, 66, xwid2, yht2, 0, outline_4, ud_four_normal },
251 /* 3 */ { 80, 66, yht4, xwid2, -90, outline_8, ud_eight_normal },
252 };
253
254 /* list of sheets (printed page formats) for
255 * left to right reading, in landscape */
256 struct sheet lr_landscape[] = {
257 /* 0 */ { 132, 52, yht1, xwid1, -90, outline_1, one_landscape },
258 /* 1 */ { 132, 52, xwid1, yht2, 0, outline_2, two_landscape },
259 /* 2 */ { 132, 52, yht2, xwid2, -90, outline_4, lr_four_landscape },
260 /* 3 */ { 132, 52, xwid2, yht4, 0, outline_8, lr_eight_landscape },
261 };
262
263 /* list of sheets (printed page formats) for
264 * top to bottom reading, in landscape */
265 struct sheet ud_landscape[] = {
266 /* 0 */ { 132, 52, yht1, xwid1, -90, outline_1, one_landscape },
267 /* 1 */ { 132, 52, xwid1, yht2, 0, outline_2, two_landscape },
268 /* 2 */ { 132, 52, yht2, xwid2, -90, outline_4, ud_four_landscape },
269 /* 3 */ { 132, 52, xwid2, yht4, 0, outline_8, ud_eight_landscape },
270 };
271
272 /* list of sheets (printed page formats) for landscape input
273 * top to bottom reading, in landscape */
274 struct sheet land_ud_normal[] = {
275 /* 0 */ { 80, 66, xwid1, yht1, 0, outline_1, one_normal },
276 /* 1 */ { 80, 66, yht2, xwid1, -90, outline_2, two_normal },
277 /* 2 */ { 80, 66, xwid2, yht2, 0, outline_4, land_ud_four_normal },
278 /* 3 */ { 80, 66, yht4, xwid2, -90, outline_8, land_ud_eight_normal },
279 };
280
281 /* GPN. sheet */
282 struct sheet coli [] = {
283 /* 1 */ { 80, 66, yht2, xwid1, -90, outline_2, two_normal_co },
284 /* 2 */ { 80, 66, yht2, xwid1, -90, outline_2, two_normal_ci },
285 /* 3 */ { 80, 66, yht2, xwid1, -90, outline_2, four_normal_dm },
286 };
287
288 /* array of sheet lists for left to right reading printed pages */
289 struct sheet *left_right[] = {
290 lr_normal,
291 lr_landscape,
292 land_lr_normal
293 };
294
295 /* arrays for top to bottom reading printed pages */
296 struct sheet *up_down[] = {
297 ud_normal,
298 ud_landscape,
299 land_ud_normal
300 };
301
302 /*
303 * Variables for holding the chosen options, The defaults are set here.
304 * the sheetlist pointer is set to point to the array for either up/down
305 * or left/right reading. This array is index by sheetorder, and then
306 * sheetindex. sheetindex encodes the number of reduced pages per printed
307 * page and indexes into the sheet list (0 = 1 page, 1 = two pages, 2 =
308 * four pages, 3 = eight pages).
309 */
310 struct sheet **sheetlist;/* array of sheet lists (up/down or left/right) */
311 int sheetaspect = PORTRAIT; /* either normal or landscape */
312 int sheetorder = UPDOWN; /* up/down or left/right flag */
313 int sheetindex = 2; /* index to page descriptor array */
314 int sheetmargin_left = DEFAULTSMARGIN; /* non-printable border on sheet */
315 int sheetmargin_right = DEFAULTSMARGIN; /* non-printable border on sheet */
316 int sheetmargin_top = DEFAULTSMARGIN; /* non-printable border on sheet */
317 int sheetmargin_bottom= DEFAULTSMARGIN; /* non-printable border on sheet */
318 int pagemargin_left = DEFAULTPMARGIN; /* border for pages */
319 int pagemargin_right = DEFAULTPMARGIN; /* border for pages */
320 int pagemargin_top = DEFAULTPMARGIN; /* border for pages */
321 int pagemargin_bottom = DEFAULTPMARGIN; /* border for pages */
322 int textmargin_left = DEFAULTTMARGIN; /* border for textbox */
323 int textmargin_right = DEFAULTTMARGIN; /* border for textbox */
324 int textmargin_top = DEFAULTTMARGIN; /* border for textbox */
325 int textmargin_bottom = DEFAULTTMARGIN; /* border for textbox */
326 int sheetheader_left = 0; /* space for physical sheetheader */
327 int sheetheader_right = 0; /* space for physical sheetheader */
328 int sheetheader_top = 0; /* space for physical sheetheader */
329 int sheetheader_bottom= 0; /* space for physical sheetheader */
330 struct pagepoints *points = points_empty;
331 int orientation; /* final orientation of text */
332 int fsize = TSIZE; /* font scale size */
333 int opt_indent = 0; /* starting column for ascii printing */
334 int opt_tabstop = DEFAULTTABSTOP; /* width of a tab */
335 int opt_lines = 0; /* lines to fit on reduced page */
336 int opt_killtrail = 1; /* Quit reading input on %%TRailer */
337 int opt_width = 0; /* columns to fit on reduced page */
338 char * opt_page = PAGE_DEF; /* default paper size */
339 /* boolean's: set default to 0 or 1 */
340 int opt_pr = 0; /* if true use pr(1) to format output */
341 int opt_mp_header = 0; /* let mpage create headers */
342 int opt_sheetheader = 0; /* let mpage create sheetheaders */
343 int opt_fold = 0; /* fold lines longer than page width */
344 int opt_outline = 1; /* don't normally outline the pages */
345 int opt_verbose = 0; /* print a count of pages produced */
346 int opt_square = 1; /* print pages with natural aspect ratio */
347 int opt_reverse = 0; /* by default print sheets in forward order */
348 int opt_jarg = 0; /* number of -j opt sets */
349 int opt_first[MAXJARG]; /* start with first sheet per -j */
350 int opt_last[MAXJARG]; /* print as many as supplied per -j */
351 int opt_alt[MAXJARG]; /* by default print all sheets, odd+even per -j*/
352 int opt_file = 1; /* should each file appera on a new sheet */
353 int opt_duplex = DEFAULT_DUPLEX; /* duplex mode flag */
354 int opt_tumble = 0; /* tumble overy second pages */
355 int opt_textbox = 0; /* don't normally draw box around text */
356 int opt_input = IN_AUTO; /* select input file format */
357 int opt_encoding = DEFAULT_ENCODING; /* use default encoding or not */
358 struct pagebox textbox = {0, 0, 80, 66, 0};
359
360 char * opt_header = NULL; /* the header for pr's -h option */
361 char * printque = NULL; /* the printer queuename */
362 char * prprog = PRPROG; /* the pr filter program */
363 char * printprog = PRINTPROG; /* the print program */
364 char * printarg = QUEARG; /* define print queue to printprog */
365 int doprint = 0; /* send it to the printer */
366 char * charvec_file; /* file to read character definitions from */
367 char * libdir = LIBDIR; /* pointer to get library files from */
368 char * fontname = "Courier"; /* Font to use */
369 char * dateformat = "%c"; /* Date/time format for date in headers */
370 char * sheethead = ""; /* Leave empty to get default sheetheader:
371 current filename + physical pagenumber */
372
373 /*
374 * various global information
375 */
376 char MPAGE[] = "mpage"; /* program name */
377 int ps_pagenum = 0; /* current sheet count (printed or not) */
378 int ps_outpages= 0; /* sheets printed */
379 int had_ps = 0; /* did we process ps files */
380
381 int first_encoding = -1; /* first encoding in character set */
382 int last_encoding; /* last encoding in character set */
383
384 /* GPN. for coli */
385 int Coli = 0; /* value of 0 = don't mess, 1 = 4, 1 (outside pages)*/
386 int use_utf8 = 0; /* is input UTF-8 or not. */
387 int check_utf8 = 1; /* do we want to check for UTF-8 or not. */
388
389
390
usage(int errcode)391 void usage(int errcode)
392 {
393 fprintf(stderr, "\
394 mpage - print multiple pages on postscript, version %s\n\n\
395 mpage [-1248aceEfHlkoOrRStTvuVxX] [-b papersize] [-Btextboxmargin]\n\
396 [-C [encodingfile]] [-da|p] [-D dateformat] [-F fontname]\n\
397 [-h header] [-I indent] [-j pagespec] [-J startpageno] [-L lines]\n\
398 [-msheetmargin] [-Mpagemargin] [-p[prprog]] [-P[printer]]\n\
399 [-s tabstop] [-W width] [-X [header]] [-z printcmd] [-Z quearg]\n\
400 [file...]]\n",
401 VERSION
402 );
403
404 fprintf(stderr, "\n\
405 -1, -2, -4, -8 Pages per sheet (4) -D strftime format for date specs\n\
406 -da Force ascii input format -dp Force postscript input format\n\
407 -a Toggle across/updown layout (u) -l Toggle portrait/landscape (p)\n\
408 -f Toggle folding long lines (off) -o Toggle printing outlines (on)\n\
409 -r Reverse printing, last->first sheet -v Toggle verbose output, (on)\n\
410 -F Text font to be used (%s) -C Character encoding filename\n\
411 -E Print every second and third page -O Print every first and fourth page\n\
412 -s Define tabstop width (%d) -k kill on %%TRailer is PS file\n\
413 -V Show mpage version.\n -u switch of utf-8 check\n\
414 -b papersize (%s), use l or ? to get a list of sizes\n\
415 -R Switch to across mode, with first page at lower left corner\n\
416 -H Create page header for each page for text files\n\
417 -X Print physical page header (filename + physical pagenumber)\n\
418 -c Toggle concat pages of different files on same sheet (off)\n\
419 -S Don't square pages for PS input (default uniform X/Y shrink)\n\
420 -B Specify textbox margin/thickness (no space): [<num>[lrtb]*]*\n\
421 -m Specify sheetmargin (no space): [<num>[lrtb]*]*\n\
422 -M Specify pagemargins (no space): [<num>[lrtb]*]*\n\
423 -p Pipe through prprog (no space), pr(1) is default.\n\
424 Mpage assumes the specified pr understands -l, -w and -h options.\n\
425 -P Specify printer queue (no space). -P only uses default queue.\n\
426 -z Specify print command (%s).\n\
427 -Z Specify print command print queue option (%s).\n\
428 -j Print specified sheets: first[-last][%%interval]\n\
429 -j 1-10 does first 10 sheets, -j 1%%2 prints odd ones, -j 2%%2 even ones.\n\
430 -J Set the start of the sheet page count\n\
431 -t Toggle printing both sides of the paper (Duplex mode, %s)\n\
432 -T Toggle tumble of every second pages when printing in duplex mode (off)\n",
433 fontname, opt_tabstop, PAGE_DEF, printprog, printarg,
434 opt_duplex ? "on" : "off"
435 );
436 fprintf(stderr, "\n(c) 1993-2005 Marcel Mol, marcel@mesa.nl (MESA Consulting)\n");
437
438 return;
439
440 } /* usage */
441