Constitutional Crisis: Fix typos and formatting errors
[ccbib.git] / psutils / psspec.c
blob88d46f07a436c29274d2c6d9a6c7e2745495a26d
1 /* psspec.c
2 * Copyright (C) Angus J. C. Duggan 1991-1995
3 * See file LICENSE for details.
5 * page spec routines for page rearrangement
6 */
8 #include "psutil.h"
9 #include "psspec.h"
10 #include "pserror.h"
11 #include "patchlev.h"
13 #include <string.h>
15 double width = -1;
16 double height = -1;
18 /* create a new page spec */
19 PageSpec *newspec(void)
21 PageSpec *temp = (PageSpec *)malloc(sizeof(PageSpec));
22 if (temp == NULL)
23 message(FATAL, "out of memory\n");
24 temp->reversed = temp->pageno = temp->flags = temp->rotate = 0;
25 temp->scale = 1;
26 temp->xoff = temp->yoff = 0;
27 temp->next = NULL;
28 return (temp);
31 /* dimension parsing routines */
32 int parseint(char **sp, void (*errorfn)(void))
34 char *s = *sp;
35 int num = atoi(s);
37 while (isdigit(*s))
38 s++;
39 if (*sp == s) (*errorfn)() ;
40 *sp = s;
41 return (num);
44 double parsedouble(char **sp, void (*errorfn)(void))
46 char *s = *sp;
47 double num = atof(s);
49 while (isdigit(*s) || *s == '-' || *s == '.')
50 s++;
51 if (*sp == s) (*errorfn)() ;
52 *sp = s;
53 return (num);
56 double parsedimen(char **sp, void (*errorfn)(void))
58 double num = parsedouble(sp, errorfn);
59 char *s = *sp;
61 if (strncmp(s, "pt", 2) == 0) {
62 s += 2;
63 } else if (strncmp(s, "in", 2) == 0) {
64 num *= 72;
65 s += 2;
66 } else if (strncmp(s, "cm", 2) == 0) {
67 num *= 28.346456692913385211;
68 s += 2;
69 } else if (strncmp(s, "mm", 2) == 0) {
70 num *= 2.8346456692913385211;
71 s += 2;
72 } else if (*s == 'w') {
73 if (width < 0)
74 message(FATAL, "width not initialised\n");
75 num *= width;
76 s++;
77 } else if (*s == 'h') {
78 if (height < 0)
79 message(FATAL, "height not initialised\n");
80 num *= height;
81 s++;
83 *sp = s;
84 return (num);
87 double singledimen(char *str, void (*errorfn)(void), void (*usagefn)(void))
89 double num = parsedimen(&str, errorfn);
90 if (*str) (*usagefn)();
91 return (num);
94 static char *prologue[] = { /* PStoPS procset */
95 #ifndef SHOWPAGE_LOAD
96 "userdict begin",
97 "[/showpage/erasepage/copypage]{dup where{pop dup load", /* prevent */
98 " type/operatortype eq{1 array cvx dup 0 3 index cvx put", /* binding */
99 " bind def}{pop}ifelse}{pop}ifelse}forall", /* in prolog */
100 #else
101 "userdict begin",
102 "[/showpage/copypage/erasepage]{dup 10 string cvs dup",
103 " length 6 add string dup 0 (PStoPS) putinterval dup",
104 " 6 4 -1 roll putinterval 2 copy cvn dup where",
105 " {pop pop pop}{exch load def}ifelse cvx cvn 1 array cvx",
106 " dup 0 4 -1 roll put def}forall",
107 #endif
108 "[/letter/legal/executivepage/a4/a4small/b5/com10envelope", /* nullify */
109 " /monarchenvelope/c5envelope/dlenvelope/lettersmall/note", /* paper */
110 " /folio/quarto/a5]{dup where{dup wcheck{exch{}put}", /* operators */
111 " {pop{}def}ifelse}{pop}ifelse}forall",
112 "/setpagedevice {pop}bind 1 index where{dup wcheck{3 1 roll put}",
113 " {pop def}ifelse}{def}ifelse",
114 "/PStoPSmatrix matrix currentmatrix def",
115 "/PStoPSxform matrix def/PStoPSclip{clippath}def",
116 "/defaultmatrix{PStoPSmatrix exch PStoPSxform exch concatmatrix}bind def",
117 "/initmatrix{matrix defaultmatrix setmatrix}bind def",
118 "/initclip[{matrix currentmatrix PStoPSmatrix setmatrix",
119 " [{currentpoint}stopped{$error/newerror false put{newpath}}",
120 " {/newpath cvx 3 1 roll/moveto cvx 4 array astore cvx}ifelse]",
121 " {[/newpath cvx{/moveto cvx}{/lineto cvx}",
122 " {/curveto cvx}{/closepath cvx}pathforall]cvx exch pop}",
123 " stopped{$error/errorname get/invalidaccess eq{cleartomark",
124 " $error/newerror false put cvx exec}{stop}ifelse}if}bind aload pop",
125 " /initclip dup load dup type dup/operatortype eq{pop exch pop}",
126 " {dup/arraytype eq exch/packedarraytype eq or",
127 " {dup xcheck{exch pop aload pop}{pop cvx}ifelse}",
128 " {pop cvx}ifelse}ifelse",
129 " {newpath PStoPSclip clip newpath exec setmatrix} bind aload pop]cvx def",
130 "/initgraphics{initmatrix newpath initclip 1 setlinewidth",
131 " 0 setlinecap 0 setlinejoin []0 setdash 0 setgray",
132 " 10 setmiterlimit}bind def",
133 "end",
134 NULL
137 void pstops(int modulo, int pps, int nobind, PageSpec *specs, double draw)
139 int thispg, maxpage;
140 int pageindex = 0;
141 char **pro;
143 scanpages();
145 maxpage = ((pages+modulo-1)/modulo)*modulo;
147 /* rearrange pages: doesn't cope properly with loaded definitions */
148 writeheader((maxpage/modulo)*pps);
149 #ifndef SHOWPAGE_LOAD
150 writestring("%%BeginProcSet: PStoPS");
151 #else
152 writestring("%%BeginProcSet: PStoPS-spload");
153 #endif
154 if (nobind)
155 writestring("-nobind");
156 writestring(" 1 15\n");
157 for (pro = prologue; *pro; pro++) {
158 writestring(*pro);
159 writestring("\n");
161 if (nobind) /* desperation measures */
162 writestring("/bind{}def\n");
163 writestring("%%EndProcSet\n");
164 /* save transformation from original to current matrix */
165 if (writepartprolog()) {
166 writestring("userdict/PStoPSxform PStoPSmatrix matrix currentmatrix\n");
167 writestring(" matrix invertmatrix matrix concatmatrix\n");
168 writestring(" matrix invertmatrix put\n");
170 writesetup();
171 for (thispg = 0; thispg < maxpage; thispg += modulo) {
172 int add_last = 0;
173 PageSpec *ps;
174 for (ps = specs; ps != NULL; ps = ps->next) {
175 int actualpg;
176 int add_next = ((ps->flags & ADD_NEXT) != 0);
177 if (ps->reversed)
178 actualpg = maxpage-thispg-modulo+ps->pageno;
179 else
180 actualpg = thispg+ps->pageno;
181 if (actualpg < pages)
182 seekpage(actualpg);
183 if (!add_last) { /* page label contains original pages */
184 PageSpec *np = ps;
185 char *eob = pagelabel;
186 char sep = '(';
187 do {
188 *eob++ = sep;
189 if (np->reversed)
190 sprintf(eob, "%d", maxpage-thispg-modulo+np->pageno);
191 else
192 sprintf(eob, "%d", thispg+np->pageno);
193 eob = eob + strlen(eob);
194 sep = ',';
195 } while ((np->flags & ADD_NEXT) && (np = np->next));
196 strcpy(eob, ")");
197 writepageheader(pagelabel, ++pageindex);
199 writestring("userdict/PStoPSsaved save put\n");
200 if (ps->flags & GSAVE) {
201 char buffer[BUFSIZ];
202 writestring("PStoPSmatrix setmatrix\n");
203 if (ps->flags & OFFSET) {
204 sprintf(buffer, "%f %f translate\n", ps->xoff, ps->yoff);
205 writestring(buffer);
207 if (ps->flags & ROTATE) {
208 sprintf(buffer, "%d rotate\n", ps->rotate);
209 writestring(buffer);
211 if (ps->flags & SCALE) {
212 sprintf(buffer, "%f dup scale\n", ps->scale);
213 writestring(buffer);
215 writestring("userdict/PStoPSmatrix matrix currentmatrix put\n");
216 if (width > 0 && height > 0) {
217 char buffer[BUFSIZ];
218 writestring("userdict/PStoPSclip{0 0 moveto\n");
219 sprintf(buffer, " %f 0 rlineto 0 %f rlineto -%f 0 rlineto\n",
220 width, height, width);
221 writestring(buffer);
222 writestring(" closepath}put initclip\n");
223 if (draw > 0) {
224 sprintf(buffer, "gsave clippath 0 setgray %f setlinewidth stroke grestore\n", draw);
225 writestring(buffer);
229 if (add_next) {
230 #ifndef SHOWPAGE_LOAD
231 writestring("/showpage{}def/copypage{}def/erasepage{}def\n");
232 #else
233 writestring("/PStoPSshowpage{}store/PStoPScopypage{}store/PStoPSerasepage{}store\n");
234 #endif
236 if (actualpg < pages) {
237 writepagesetup();
238 writestring("PStoPSxform concat\n");
239 writepagebody(actualpg);
240 } else {
241 writestring("PStoPSxform concat\n");
242 writestring("showpage\n");
244 writestring("PStoPSsaved restore\n");
245 add_last = add_next;
248 writetrailer();