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