source: trunk/third/transcript/src/psnup.c @ 9090

Revision 9090, 15.2 KB checked in by ghudson, 28 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r9089, which included commits to RCS files with non-trunk default branches.
Line 
1#ifndef lint
2#define _NOTICE static char
3_NOTICE N1[] = "Copyright (c) 1990,1991,1992 Adobe Systems Incorporated";
4_NOTICE N2[] = "GOVERNMENT END USERS: See Notice file in TranScript library directory";
5_NOTICE N3[] = "-- probably /usr/lib/ps/Notice";
6_NOTICE RCSID[]="$Header: /afs/dev.mit.edu/source/repository/third/transcript/src/psnup.c,v 1.1.1.1 1996-10-07 20:25:51 ghudson Exp $";
7#endif
8/* psnup.c
9 *
10 *
11 * Copyright (C) 1990,1991,1992 Adobe Systems Incorporated.  All rights
12 *  reserved.
13 * GOVERNMENT END USERS: See Notice File in TranScript library directory
14 * -- probably /usr/lib/ps/Notice
15 *
16 * n x n printing
17 *
18 * $Log: not supported by cvs2svn $
19 * Revision 3.10  1994/02/16  00:31:00  snichols
20 * support for Orientation comment.
21 *
22 * Revision 3.9  1993/12/21  23:00:14  snichols
23 * correct %%Pages comment in output.
24 *
25 * Revision 3.8  1993/04/20  22:16:50  snichols
26 * should close the prolog file when we're done, and should make sure
27 * we only include the prolog once.
28 *
29 * Revision 3.7  1993/01/13  22:59:45  snichols
30 * another uninitialized variable.
31 *
32 * Revision 3.6  1992/12/02  00:52:18  snichols
33 * need to set ndex before using it.
34 *
35 * Revision 3.5  1992/08/21  16:26:32  snichols
36 * Release 4.0
37 *
38 * Revision 3.4  1992/07/14  22:38:39  snichols
39 * Updated copyright.
40 *
41 * Revision 3.3  1992/07/02  23:07:35  snichols
42 * xmax, ymax need to be floats.
43 *
44 * Revision 3.2  1992/06/02  18:26:31  snichols
45 * support for -d option.
46 *
47 * Revision 3.1  1992/05/22  20:59:53  snichols
48 * Now uses defaults if a printer name is supplied but there's no ppd
49 * file.  Also added -w and -h switch, to allow page size to be
50 * any size. (Page size, not paper size).
51 *
52 * Revision 3.0  1991/06/17  16:46:10  snichols
53 * Release3.0
54 *
55 * Revision 1.9  1991/04/19  23:21:55  snichols
56 * typo: should have %%IncludeFeature: *PageSize instead of
57 * %%IncludeFeature: *PaperSize.
58 *
59 * Revision 1.8  1991/03/28  23:47:32  snichols
60 * isolated code for finding PPD files to one routine, in psutil.c.
61 *
62 * Revision 1.7  1991/03/21  18:53:15  snichols
63 * if printername is > 10 characters and can't find ppd, truncate to 10 and
64 * check again.
65 *
66 * Revision 1.6  1991/02/20  16:53:48  snichols
67 * mismatch in declaration: formal was int, actual was char *.
68 *
69 * Revision 1.5  91/02/19  16:42:09  snichols
70 * added support for -n 1; this allows documents formatted for one size
71 * paper to be printed on another size paper.  Cleaned up the paper size
72 * DSC comment handling as well.
73 *
74 * Revision 1.4  91/01/25  16:36:00  snichols
75 * Oops, still had hard wired pathname for prolog.
76 *
77 * Revision 1.3  90/12/12  10:28:11  snichols
78 * new configuration stuff.
79 *
80 * Revision 1.2  90/11/16  14:42:25  snichols
81 * Support for other page sizes.  NxM printing.
82 *
83 * Revision 1.1  90/10/29  14:05:26  snichols
84 * Initial revision
85 *
86 *
87 */
88#include <stdio.h>
89#include <string.h>
90#include <math.h>
91#include <ctype.h>
92#include "transcript.h"
93#include "config.h"
94
95extern char *optarg;
96extern int optind, opterr;
97
98struct paper {
99    float paperwidth;
100    float paperlength;
101    float imagexorig;
102    float imageyorig;
103    float imagewidth;
104    float imagelength;
105};
106
107struct page {
108    float width;
109    float height;
110} pagesize;
111
112float width;
113float length;
114float xorig;
115float yorig;
116
117struct paper paperSizes[5] = {
118    {612, 792, 18, 8, 582, 776},
119    {612, 1008, 15, 8, 582, 992},
120    {595, 842, 13, 10, 564, 822},
121    {516, 729, 21, 10, 479, 705},
122    {0,0,0,0,0,0}
123};
124
125#define LETTER 0
126#define LEGAL 1
127#define A4 2
128#define B5 3
129#define OTHER 4
130
131int paperndx = LETTER;
132char *papersize = "Letter";
133int useDefault = FALSE;
134
135char *printername;
136
137
138/* scale factor */
139float scale;
140
141/* defaults - 4 up (2x2), not rotated */
142int nrows = 2;
143int ncolumns = 2;
144int rotate = FALSE;
145int urotate = FALSE;
146
147int gaudy = FALSE;
148int noscaleup = FALSE;
149
150
151private void Usage()
152{
153    fprintf(stderr,"psnup [-n number[xnumber]] [-S size] [-s size] [-G] [-p outputfilename] filename\n");
154    exit(0);
155}
156
157private int checkpower(i)
158    int i;
159{
160    /* returns powers of 2 above 0 */
161    int result;
162    int rem;
163    int count = 0;
164
165    result = i;
166    while (result != 0) {
167        count++;
168        rem = result % 2;
169        result = result/2;
170        if (result == 1 && (rem == 0) ) return count;
171    }
172    return -1;
173}
174
175private int strtondx(s)
176    char *s;
177{
178    if (!strcmp(s, "Legal"))
179        return LEGAL;
180    if (!strcmp(s, "Letter"))
181        return LETTER;
182    if (!strcmp(s, "A4"))
183        return A4;
184    if (!strcmp(s,"B5"))
185        return B5;
186    /* if no match, return OTHER */
187    return OTHER;
188}
189
190private char *ndxtostr(i)
191    int i;
192{
193    switch (i) {
194        case LETTER:
195            return "Letter";
196            break;
197        case LEGAL:
198            return "Legal";
199            break;
200        case A4:
201            return "A4";
202            break;
203        case B5:
204            return "B5";
205            break;
206    }
207}
208
209static int HandlePPD(printername, size, fp)
210    char *printername;
211    char *size;
212    FILE **fp;
213{
214    int ndex;
215
216    ndex = strtondx(size);
217    if (printername == NULL) {
218        if (ndex == OTHER) {
219            fprintf(stderr,
220                    "psnup: must supply a printer name to use %s size\n",
221                    size);
222            exit(1);
223        }
224        else return FALSE;
225    }
226    else {
227        *fp = GetPPD(printername);
228        if (*fp == NULL) {
229            fprintf(stderr,"psnup: couldn't open PPD file for printer %s,",
230                    printername);
231            fprintf(stderr, " using defaults\n");
232            return FALSE;
233        }
234        return TRUE;
235    }
236}
237           
238       
239
240static void GetDimensions(fp, size, w, h)
241    FILE *fp;
242    char *size;
243    float *w, *h;
244{
245    char *value;
246
247    value = (char *) parseppd(fp, "*PaperDimension", size);
248    if (value)
249        sscanf(value, "%f %f", w, h);
250    else {
251        fprintf(stderr, "Couldn't find dimensions for size %s", size);
252        exit(1);
253    }
254}
255
256/* read page size and imageable area info from ppd file */
257private void GetPageSizeInfo(size, def)
258    char *size;
259    int def;
260{
261    char *value;
262    FILE *fptr;
263    float xmax, ymax;
264    int ndex;
265    int useppd;
266
267    ndex = strtondx(size);
268    useppd = HandlePPD(printername, size, &fptr);
269    if (useppd) {
270        if (def) {
271            /* check default */
272            value = (char *) parseppd(fptr,"*DefaultPageSize", NULL);
273            if (value) {
274                if (!strcmp(size, value))
275                    useDefault = TRUE;
276            }
277            rewind(fptr);
278        }
279        GetDimensions(fptr, size, &paperSizes[ndex].paperwidth,
280                      &paperSizes[ndex].paperlength);
281        rewind(fptr);
282        value = (char *) parseppd(fptr, "*ImageableArea", size);
283        if (value)
284            sscanf(value, "%f %f %f %f",
285              &paperSizes[ndex].imagexorig, &paperSizes[ndex].imageyorig,
286                   &xmax, &ymax);
287        paperSizes[ndex].imagewidth = xmax - paperSizes[ndex].imagexorig;
288        paperSizes[ndex].imagelength = ymax - paperSizes[ndex].imageyorig;
289        close(fptr);
290    }
291}
292
293DoFixedProlog(output)
294    FILE *output;
295{
296    FILE *pfp;
297    char mybuf[BUFSIZ];
298    char prolog[TSPATHSIZE];
299
300    strncpy(prolog,PSLibDir,TSPATHSIZE);
301    strncat(prolog,"psnup.pro",TSPATHSIZE);
302    if ((pfp = fopen(prolog,"r")) == NULL) {
303        fprintf(stderr,"psnup: couldn't open prolog file %s.\n",prolog);
304        exit(1);
305    }
306    while (fgets(mybuf,255,pfp))
307        fputs(mybuf,output);
308    close(pfp);
309}
310
311static float ParseNum(s)
312    char *s;
313{
314   char *p;
315
316   if (p = strchr(s, 'i')) {
317       /* inches, convert to points */
318       *p = '\0';
319       return atof(optarg) * 72.0;
320   }
321   else if (p = strchr(s, 'm')) {
322       /* millimeters, convert to points */
323       *p = '\0';
324       return atof(optarg) * 72.0 / 254.0;
325   }
326   else
327       return atof(optarg);
328}
329
330#define ARGS "P:d:p:n:S:s:w:h:rGf"
331
332main(argc,argv)
333    int argc;
334    char **argv;
335{
336
337    FILE *ifp, *ofp;
338    FILE *tfp;
339    int row = 0;
340    int column = 0;
341    float x,y;
342    float lscale,wscale;
343    int i, c;
344    char *outfile, *infile;
345    char buf[255];
346    int page = 0;
347    int realpage = 0;
348    int power;
349    char *p,*q;
350    int n;
351    int prolog = FALSE;
352    int sizecom = FALSE;
353    char *tmpsize = NULL;
354    int origpages;
355    int newpages;
356
357    if (argc == 1) {
358        Usage();
359        exit(1);
360    }
361    infile = outfile = NULL;
362    pagesize.width = pagesize.height = 0;
363    while ((c = getopt(argc,argv,ARGS)) != EOF) {
364        switch (c) {
365        case 'p':
366            outfile = optarg;
367            break;
368        case 'r':
369            urotate = TRUE;
370            break;
371        case 'n':
372            p = strchr(optarg,'x');
373            if (p) {
374                *p = '\0';
375                p++;
376                ncolumns = atoi(p);
377                nrows = atoi(optarg);
378            }
379            else {
380                n = atoi(optarg);
381                if (n == 1) {
382                    /* special case */
383                    rotate = FALSE;
384                    nrows = ncolumns = 1;
385                }
386                else {
387                    if ((power = checkpower(n)) == -1) {
388                        fprintf(stderr,"psnup: must supply either a power of 2 or rowsxcolumns.\n");
389                        exit(1);
390                    }
391                    if (power % 2) {
392                        rotate = TRUE;
393                        nrows = sqrt((double) n/2);
394                        ncolumns = sqrt((double) n*2);
395                    }
396                    else {
397                        rotate = FALSE;
398                        nrows = ncolumns = sqrt((double) n);
399                    }
400                }
401            }
402            break;
403        case 'w':
404            pagesize.width = ParseNum(optarg);
405            break;
406        case 'h':
407            pagesize.height = ParseNum(optarg);
408            break;
409        case 'S':
410            if (islower(*optarg)) toupper(*optarg);
411            papersize = optarg;
412            paperndx = strtondx(optarg);
413            break;
414        case 's':
415            tmpsize = optarg;
416            break;
417        case 'd':
418        case 'P':
419            printername = optarg;
420            break;
421        case 'G':
422            gaudy = TRUE;
423            break;
424        case 'f':
425            noscaleup = TRUE;
426        default:
427            Usage();
428            break;
429        }
430    }
431    if (urotate) rotate = urotate;
432    GetPageSizeInfo(papersize, TRUE);
433    if (pagesize.width == 0)
434        pagesize.width = paperSizes[paperndx].paperwidth;
435    if (pagesize.height == 0)
436        pagesize.height = paperSizes[paperndx].paperlength;
437    if (tmpsize) {
438        if (HandlePPD(printername, tmpsize, &tfp)) {
439            GetDimensions(tfp, tmpsize, &pagesize.width, &pagesize.height);
440        }
441        else {
442            n = strtondx(tmpsize);
443            pagesize.width = paperSizes[n].paperwidth;
444            pagesize.height = paperSizes[n].paperlength;
445        }
446    }
447    if (optind < argc)
448        infile = argv[optind];
449
450    if (infile) {
451        if ((ifp = fopen(infile,"r")) == NULL) {
452            fprintf(stderr,"Couldn't open %s\n",infile);
453            exit(2);
454        }
455    }
456    else ifp = stdin;
457    if (outfile) {
458        if ((ofp = fopen(outfile,"w")) == NULL) {
459            fprintf(stderr,"Couldn't open %s.\n",outfile);
460            exit(3);
461        }
462    }
463    else ofp = stdout;
464
465    if (rotate) {
466        wscale = (float) ((paperSizes[paperndx].imagelength -
467                           (ncolumns -1)*4.5)/ncolumns)/
468                               pagesize.width;
469        lscale = (float) ((paperSizes[paperndx].imagewidth -
470                           (nrows - 1)*4.5)/nrows)/
471                               pagesize.height;
472        if (wscale < lscale)
473            scale = wscale;
474        else scale = lscale;
475        width = nrows*scale*pagesize.height + (nrows -1)*4.5;
476        length = ncolumns*scale*pagesize.width +
477            (ncolumns -1)*4.5;
478        xorig = (paperSizes[paperndx].paperwidth - width)/2;
479        yorig = (paperSizes[paperndx].paperlength - length)/2;
480    }
481    else {
482        wscale = (float)((paperSizes[paperndx].imagewidth - (ncolumns -1)
483                          *4.5)/ncolumns)/pagesize.width;
484        lscale = (float)((paperSizes[paperndx].imagelength - (nrows -1)
485                          *4.5)/nrows)/pagesize.height; 
486        if (wscale < lscale)
487            scale = wscale;
488        else scale = lscale;
489        length = nrows*scale*pagesize.height + (nrows -1)*4.5;
490        width = ncolumns*scale*pagesize.width + (ncolumns -1)*4.5;
491        yorig = (paperSizes[paperndx].paperlength - length)/2;
492        xorig = (paperSizes[paperndx].paperwidth - width)/2;
493    }
494
495
496    row = nrows - 1;
497    column = 0;
498    if (!fgets(buf,255,ifp)) {
499        fprintf(stderr,"psnup: empty input.\n");
500        exit(1);
501    }
502    if (strncmp(buf,"%!PS-Adobe-",11)) {
503        fprintf(stderr,"psnup: non-conforming input.\n");
504        exit(1);
505    }
506    fputs(buf,ofp);
507    /* redefine showpage */
508    fprintf(ofp,"/PNshowpage /showpage load def\n /showpage { } def\n");
509
510    while (fgets(buf,255,ifp)) {
511        if (!strncmp(buf,"%%EndProlog",11)) {
512            if (!prolog) {
513                prolog = TRUE;
514                DoFixedProlog(ofp);
515            }
516        }
517        if (!strncmp(buf,"%%BeginFeature: *PageSize",25)) {
518            /* if it's not for the size we want, lose it! */
519            p = buf;
520            p += 26;
521            if (strncmp(p, papersize, strlen(papersize))) {
522                while (fgets(buf, 255, ifp)) {
523                    if (!strncmp(buf,"%%EndFeature", 12))
524                        break;
525                }
526                if (!useDefault)
527                    fprintf(ofp, "%%%%IncludeFeature: *PageSize %s\n", papersize);
528                sizecom = TRUE;
529                continue;
530            }
531            sizecom = TRUE;
532        }
533        if (!strncmp(buf,"%%IncludeFeature: *PageSize", 27)) {
534            /* again, if it's not for the size we want, get rid of it */
535            p = buf;
536            p += 28;
537            if (strncmp(p, papersize, strlen(papersize))) {
538                if (!useDefault)
539                    fprintf(ofp, "%%%%IncludeFeature: *PageSize %s\n", papersize);
540                sizecom = TRUE;
541                continue;
542            }
543            sizecom = TRUE;
544        }
545        if (!strncmp(buf, "%%Orientation:", 14)) {
546            /* if it doesn't match us, replace it */
547            p = buf + 15;
548            if (rotate) {
549                if (strncmp(p, "Landscape", 9) != 0) {
550                    fprintf(ofp, "%%%%Orientation: Landscape\n");
551                }
552            }
553            else {
554                if (strncmp(p, "Portrait", 9) != 0) {
555                    fprintf(ofp, "%%%%Orientation: Portrait\n");
556                }
557            }
558        }
559        if (!strncmp(buf, "%%EndSetup", 10) && !sizecom && !useDefault) {
560            /* if we reached here without a size comment and we're not */
561            /* the default page size, output a comment */
562            fprintf(ofp, "%%%%IncludeFeature: *PageSize %s\n", papersize);
563            sizecom = TRUE;
564        }
565        if (!strncmp(buf,"%%Page:",7)) {
566            if (!prolog) {
567                prolog = TRUE;
568                DoFixedProlog(ofp);
569            }
570            if (!sizecom && !useDefault) {
571                /* still might not have seen or output a size comment! */
572                fprintf(ofp, "%%%%IncludeFeature: *PageSize %s\n", papersize);
573                sizecom = TRUE;
574            }
575            /* found a page boundary */
576            page++;
577            if ((page % (nrows*ncolumns)) == 1 || nrows*ncolumns == 1) {
578                realpage++;
579                if (page > 1) {
580                    fprintf(ofp,"PNP restore\n");
581                    fprintf(ofp,"PNEP\n");
582                }
583                fprintf(ofp,"%%%%Page: ? %d\n",realpage);
584                if (rotate)
585                    fprintf(ofp,"%7.4f %10.2f PNLS\n",scale,
586                            -paperSizes[paperndx].paperwidth);
587                else
588                    fprintf(ofp,"%7.4f PNSP\n",scale);
589                row = nrows-1;
590                column = 0;
591            }
592            if (rotate) {
593                if (column == 0)
594                    x = ((float) yorig )/scale;
595                else
596                    x = ((float) yorig + (float)column*length/ncolumns)/scale;
597                if (row == 0)
598                    y = ((float) xorig)/scale;
599                else
600                    y = ((float) xorig + (float)row*width/nrows)/scale;
601            }
602            else {
603                if (column == 0)
604                    x = ((float) xorig )/scale ;
605                else
606                    x = ((float) xorig  + (float)column*width/ncolumns)/scale;
607                if (row == 0)
608                    y = ((float) yorig )/scale ;
609                else
610                    y = ((float) yorig  + (float)row*length/nrows)/scale;
611            }
612            column++;
613            if (column == ncolumns) {
614                column = 0;
615                row--;
616            }
617            if ((page % (nrows*ncolumns)) != 1 && nrows*ncolumns != 1) fprintf(ofp,"PNP restore\n");
618            fprintf(ofp,"/PNP save def\n");
619            fprintf(ofp,"%7.4f %7.4f translate\n",x,y);
620            if (gaudy)
621                fprintf(ofp,"%10.2f %10.2f PNBOX\n",pagesize.width,
622                        pagesize.height);
623        }
624        else if (!strncmp(buf,"%%Trailer",9)) {
625            fprintf(ofp,"PNP restore\n");
626            fprintf(ofp,"PNEP\n");
627            fprintf(ofp,"%s",buf);
628        }
629        else if (!strncmp(buf, "%%Pages:", 8)) {
630            /* if it's not (atend), divide the number of pages by the
631               number of pages per sheet */
632            p = strchr(buf, '(');
633            if (p) {
634                if (!strncmp(p, "(atend)", 7)) {
635                    fprintf(ofp, "%s", buf);
636                }
637            }
638            else {
639                /* read the value */
640                p = strchr(buf, ':');
641                p++;
642                while (*p == ' ') p++;
643                q = strchr(p, '\n');
644                if (q) *q = '\0';
645                origpages = atoi(p);
646                if (origpages % (nrows*ncolumns))
647                    newpages = origpages/(nrows*ncolumns) + 1;
648                else
649                    newpages = origpages/(nrows*ncolumns);
650                fprintf(ofp, "%%Pages: %d\n", newpages);
651            }
652        }
653        else fprintf(ofp,"%s",buf);
654    }
655    close(ofp);
656}
657       
Note: See TracBrowser for help on using the repository browser.