File: psspec.c

package info (click to toggle)
psutils 1.17.dfsg-2
  • links: PTS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 796 kB
  • ctags: 605
  • sloc: ansic: 6,567; sh: 756; perl: 705; makefile: 639; lisp: 74
file content (266 lines) | stat: -rw-r--r-- 8,176 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
/* psspec.c
 * Copyright (C) Angus J. C. Duggan 1991-1995
 * See file LICENSE for details.
 *
 * page spec routines for page rearrangement
 */

#include "psutil.h"
#include "psspec.h"
#include "pserror.h"
#include "patchlev.h"

#include <string.h>

double width = -1;
double height = -1;

/* create a new page spec */
PageSpec *newspec(void)
{
   PageSpec *temp = (PageSpec *)malloc(sizeof(PageSpec));
   if (temp == NULL)
      message(FATAL, "out of memory\n");
   temp->reversed = temp->pageno = temp->flags = temp->rotate = 0;
   temp->hflip = 0;
   temp->vflip = 0;
   temp->scale = 1;
   temp->xoff = temp->yoff = 0;
   temp->next = NULL;
   return (temp);
}

/* dimension parsing routines */
int parseint(char **sp, void (*errorfn)(void))
{
   char *s = *sp;
   int num = atoi(s);

   while (isdigit(*s))
      s++;
   if (*sp == s) (*errorfn)() ;
   *sp = s;
   return (num);
}

double parsedouble(char **sp, void (*errorfn)(void))
{
   char *s = *sp;
   double num = atof(s);

   while (isdigit(*s) || *s == '-' || *s == '.')
      s++;
   if (*sp == s) (*errorfn)() ;
   *sp = s;
   return (num);
}

double parsedimen(char **sp, void (*errorfn)(void))
{
   double num = parsedouble(sp, errorfn);
   char *s = *sp;

   if (strncmp(s, "pt", 2) == 0) {
      s += 2;
   } else if (strncmp(s, "in", 2) == 0) {
      num *= 72;
      s += 2;
   } else if (strncmp(s, "cm", 2) == 0) {
      num *= 28.346456692913385211;
      s += 2;
   } else if (strncmp(s, "mm", 2) == 0) {
      num *= 2.8346456692913385211;
      s += 2;
   } else if (*s == 'w') {
      if (width < 0)
	 message(FATAL, "width not initialised\n");
      num *= width;
      s++;
   } else if (*s == 'h') {
      if (height < 0)
	 message(FATAL, "height not initialised\n");
      num *= height;
      s++;
   }
   *sp = s;
   return (num);
}

double singledimen(char *str, void (*errorfn)(void), void (*usagefn)(void))
{
   double num = parsedimen(&str, errorfn);
   if (*str) (*usagefn)();
   return (num);
}

static char *prologue[] = { /* PStoPS procset */
#ifndef SHOWPAGE_LOAD
   /* Wrap these up with our own versions.  We have to  */
   "userdict begin",
   "[/showpage/erasepage/copypage]{dup where{pop dup load",
   " type/operatortype eq{ /PStoPSenablepage cvx 1 index"
   " load 1 array astore cvx {} bind /ifelse cvx 4 array"
   " astore cvx def}{pop}ifelse}{pop}ifelse}forall"
   " /PStoPSenablepage true def",
#else
   "userdict begin",
   "[/showpage/copypage/erasepage]{dup 10 string cvs dup",
   " length 6 add string dup 0 (PStoPS) putinterval dup",
   " 6 4 -1 roll putinterval 2 copy cvn dup where",
   " {pop pop pop}{exch load def}ifelse cvx cvn 1 array cvx",
   " dup 0 4 -1 roll put def}forall",
#endif
   "[/letter/legal/executivepage/a4/a4small/b5/com10envelope",	/* nullify */
   " /monarchenvelope/c5envelope/dlenvelope/lettersmall/note",	/* paper */
   " /folio/quarto/a5]{dup where{dup wcheck{exch{}put}",	/* operators */
   " {pop{}def}ifelse}{pop}ifelse}forall",
   "/setpagedevice {pop}bind 1 index where{dup wcheck{3 1 roll put}",
   " {pop def}ifelse}{def}ifelse",
   "/PStoPSmatrix matrix currentmatrix def",
   "/PStoPSxform matrix def/PStoPSclip{clippath}def",
   "/defaultmatrix{PStoPSmatrix exch PStoPSxform exch concatmatrix}bind def",
   "/initmatrix{matrix defaultmatrix setmatrix}bind def",
   "/initclip[{matrix currentmatrix PStoPSmatrix setmatrix",
   " [{currentpoint}stopped{$error/newerror false put{newpath}}",
   " {/newpath cvx 3 1 roll/moveto cvx 4 array astore cvx}ifelse]",
   " {[/newpath cvx{/moveto cvx}{/lineto cvx}",
   " {/curveto cvx}{/closepath cvx}pathforall]cvx exch pop}",
   " stopped{$error/errorname get/invalidaccess eq{cleartomark",
   " $error/newerror false put cvx exec}{stop}ifelse}if}bind aload pop",
   " /initclip dup load dup type dup/operatortype eq{pop exch pop}",
   " {dup/arraytype eq exch/packedarraytype eq or",
   "  {dup xcheck{exch pop aload pop}{pop cvx}ifelse}",
   "  {pop cvx}ifelse}ifelse",
   " {newpath PStoPSclip clip newpath exec setmatrix} bind aload pop]cvx def",
   "/initgraphics{initmatrix newpath initclip 1 setlinewidth",
   " 0 setlinecap 0 setlinejoin []0 setdash 0 setgray",
   " 10 setmiterlimit}bind def",
   "end",
   NULL
   };

void pstops(int modulo, int pps, int nobind, PageSpec *specs, double draw) {

  scanpages(NULL);
  pstops_write(modulo, pps, nobind, specs, draw, NULL);
}

void pstops_write(int modulo, int pps, int nobind, PageSpec *specs, double draw, off_t *ignorelist)
{
   int thispg, maxpage;
   int pageindex = 0;
   char **pro;

   maxpage = ((pages+modulo-1)/modulo)*modulo;

   /* rearrange pages: doesn't cope properly with loaded definitions */
   writeheadermedia((maxpage/modulo)*pps, ignorelist, width, height);
#ifndef SHOWPAGE_LOAD
   writestring("%%BeginProcSet: PStoPS");
#else
   writestring("%%BeginProcSet: PStoPS-spload");
#endif
   if (nobind)
      writestring("-nobind");
   writestring(" 1 15\n");
   for (pro = prologue; *pro; pro++) {
      writestring(*pro);
      writestring("\n");
   }
   if (nobind) /* desperation measures */
      writestring("/bind{}def\n");
   writestring("%%EndProcSet\n");
   /* save transformation from original to current matrix */
   if (writepartprolog()) {
      writestring("userdict/PStoPSxform PStoPSmatrix matrix currentmatrix\n");
      writestring(" matrix invertmatrix matrix concatmatrix\n");
      writestring(" matrix invertmatrix put\n");
   }
   writesetup();
   for (thispg = 0; thispg < maxpage; thispg += modulo) {
      int add_last = 0;
      PageSpec *ps;
      for (ps = specs; ps != NULL; ps = ps->next) {
	 int actualpg;
	 int add_next = ((ps->flags & ADD_NEXT) != 0);
	 if (ps->reversed)
	    actualpg = maxpage-thispg-modulo+ps->pageno;
	 else
	    actualpg = thispg+ps->pageno;
	 if (actualpg < pages)
	    seekpage(actualpg);
	 if (!add_last) {	/* page label contains original pages */
	    PageSpec *np = ps;
	    char *eob = pagelabel;
	    char sep = '(';
	    do {
	       *eob++ = sep;
	       if (np->reversed)
		  sprintf(eob, "%d", maxpage-thispg-modulo+np->pageno);
	       else
		  sprintf(eob, "%d", thispg+np->pageno);
	       eob = eob + strlen(eob);
	       sep = ',';
	    } while ((np->flags & ADD_NEXT) && (np = np->next));
	    strcpy(eob, ")");
	    writepageheader(pagelabel, ++pageindex);
	 }
	 writestring("userdict/PStoPSsaved save put\n");
	 if (ps->flags & GSAVE) {
	    char buffer[BUFSIZ];
	    writestring("PStoPSmatrix setmatrix\n");
	    if (ps->flags & OFFSET) {
	       sprintf(buffer, "%f %f translate\n", ps->xoff, ps->yoff);
	       writestring(buffer);
	    }
	    if (ps->flags & ROTATE) {
	       sprintf(buffer, "%d rotate\n", ps->rotate);
	       writestring(buffer);
	    }
	    if ((ps->flags & HFLIP) && (ps->hflip%2)) {
	       sprintf(buffer, "[ -1 0 0 1 %f 0 ] concat\n", width*ps->scale);
	       writestring(buffer);
	    }
	    if ((ps->flags & VFLIP) && (ps->vflip%2)) {
	       sprintf(buffer, "[ 1 0 0 -1 0 %f ] concat\n", height*ps->scale);
	       writestring(buffer);
	    }
	    if (ps->flags & SCALE) {
	       sprintf(buffer, "%f dup scale\n", ps->scale);
	       writestring(buffer);
	    }
	    writestring("userdict/PStoPSmatrix matrix currentmatrix put\n");
	    if (width > 0 && height > 0) {
	       char buffer[BUFSIZ];
	       writestring("userdict/PStoPSclip{0 0 moveto\n");
	       sprintf(buffer, " %f 0 rlineto 0 %f rlineto -%f 0 rlineto\n",
		       width, height, width);
	       writestring(buffer);
	       writestring(" closepath}put initclip\n");
	       if (draw > 0) {
		  sprintf(buffer, "gsave clippath 0 setgray %f setlinewidth stroke grestore\n", draw);
		  writestring(buffer);
	       }
	    }
	 }
	 if (add_next) {
#ifndef SHOWPAGE_LOAD
	    writestring("/PStoPSenablepage false def\n");
#else
	    writestring("/PStoPSshowpage{}store/PStoPScopypage{}store/PStoPSerasepage{}store\n");
#endif
	 }
	 if (actualpg < pages) {
	    writepagesetup();
	    writestring("PStoPSxform concat\n");
	    writepagebody(actualpg);
	 } else {
	    writestring("PStoPSxform concat\n");
	    writestring("showpage\n");
	 }
	 writestring("PStoPSsaved restore\n");
	 add_last = add_next;
      }
   }
   writetrailer();
}