Blame


1 5f1cf8e6 2004-05-16 devnull #include "misc.h"
2 5f1cf8e6 2004-05-16 devnull #include "slug.h"
3 5f1cf8e6 2004-05-16 devnull #include <math.h>
4 5f1cf8e6 2004-05-16 devnull
5 5f1cf8e6 2004-05-16 devnull static char *bufptr(int);
6 5f1cf8e6 2004-05-16 devnull
7 5f1cf8e6 2004-05-16 devnull void slug::coalesce()
8 5f1cf8e6 2004-05-16 devnull {
9 5f1cf8e6 2004-05-16 devnull (this+1)->dp = dp; // pretty grimy, but meant to ensure
10 5f1cf8e6 2004-05-16 devnull // that all output goes out.
11 5f1cf8e6 2004-05-16 devnull // maybe it has to skip over PT's;
12 5f1cf8e6 2004-05-16 devnull // some stuff is getting pushed inside PT..END
13 5f1cf8e6 2004-05-16 devnull }
14 5f1cf8e6 2004-05-16 devnull
15 5f1cf8e6 2004-05-16 devnull void slug::neutralize()
16 5f1cf8e6 2004-05-16 devnull {
17 5f1cf8e6 2004-05-16 devnull switch (type) {
18 5f1cf8e6 2004-05-16 devnull case PAGE:
19 5f1cf8e6 2004-05-16 devnull case UF:
20 5f1cf8e6 2004-05-16 devnull case BF:
21 5f1cf8e6 2004-05-16 devnull case PARM:
22 5f1cf8e6 2004-05-16 devnull type = NEUTRAL;
23 5f1cf8e6 2004-05-16 devnull coalesce();
24 5f1cf8e6 2004-05-16 devnull break;
25 5f1cf8e6 2004-05-16 devnull default:
26 5f1cf8e6 2004-05-16 devnull ERROR "neutralized %d (%s) with %s\n",
27 5f1cf8e6 2004-05-16 devnull type, typename(), headstr() WARNING;
28 5f1cf8e6 2004-05-16 devnull break;
29 5f1cf8e6 2004-05-16 devnull }
30 5f1cf8e6 2004-05-16 devnull }
31 5f1cf8e6 2004-05-16 devnull
32 5f1cf8e6 2004-05-16 devnull void slug::dump() // print contents of a slug
33 5f1cf8e6 2004-05-16 devnull {
34 5f1cf8e6 2004-05-16 devnull printf("# %d %-4.4s parm %d dv %d base %d s%d f%d H%d\n#\t\t%s\n",
35 5f1cf8e6 2004-05-16 devnull serialno(), typename(), parm, dv, base,
36 5f1cf8e6 2004-05-16 devnull size, font, hpos, headstr());
37 5f1cf8e6 2004-05-16 devnull }
38 5f1cf8e6 2004-05-16 devnull
39 5f1cf8e6 2004-05-16 devnull char *slug::headstr()
40 5f1cf8e6 2004-05-16 devnull {
41 5f1cf8e6 2004-05-16 devnull const int HEADLEN = 65;
42 5f1cf8e6 2004-05-16 devnull static char buf[2*HEADLEN];
43 5f1cf8e6 2004-05-16 devnull int j = 0;
44 5f1cf8e6 2004-05-16 devnull char *s = bufptr(dp);
45 5f1cf8e6 2004-05-16 devnull int n = (this+1)->dp - dp;
46 5f1cf8e6 2004-05-16 devnull if (n >= HEADLEN)
47 5f1cf8e6 2004-05-16 devnull n = HEADLEN;
48 5f1cf8e6 2004-05-16 devnull for (int i = 0; i < n; i++)
49 5f1cf8e6 2004-05-16 devnull switch (s[i]) {
50 5f1cf8e6 2004-05-16 devnull case '\n':
51 5f1cf8e6 2004-05-16 devnull case '\t':
52 5f1cf8e6 2004-05-16 devnull case '\0':
53 5f1cf8e6 2004-05-16 devnull case ' ':
54 5f1cf8e6 2004-05-16 devnull break;
55 5f1cf8e6 2004-05-16 devnull default:
56 5f1cf8e6 2004-05-16 devnull buf[j++] = s[i];
57 5f1cf8e6 2004-05-16 devnull break;
58 5f1cf8e6 2004-05-16 devnull }
59 5f1cf8e6 2004-05-16 devnull buf[j] = 0;
60 5f1cf8e6 2004-05-16 devnull return buf;
61 5f1cf8e6 2004-05-16 devnull }
62 5f1cf8e6 2004-05-16 devnull
63 5f1cf8e6 2004-05-16 devnull static char *strindex(char s[], char t[]) // index of earliest t[] in s[]
64 5f1cf8e6 2004-05-16 devnull {
65 5f1cf8e6 2004-05-16 devnull for (int i = 0; s[i] != '\0'; i++) {
66 5f1cf8e6 2004-05-16 devnull int j, k;
67 5f1cf8e6 2004-05-16 devnull for (j = i, k = 0; t[k]!='\0' && s[j] == t[k]; j++, k++)
68 5f1cf8e6 2004-05-16 devnull ;
69 5f1cf8e6 2004-05-16 devnull if (k > 0 && t[k] == '\0')
70 5f1cf8e6 2004-05-16 devnull return s+i;
71 5f1cf8e6 2004-05-16 devnull }
72 5f1cf8e6 2004-05-16 devnull return 0;
73 5f1cf8e6 2004-05-16 devnull }
74 5f1cf8e6 2004-05-16 devnull
75 5f1cf8e6 2004-05-16 devnull void slug::slugout(int col)
76 5f1cf8e6 2004-05-16 devnull {
77 5f1cf8e6 2004-05-16 devnull static int numout = 0;
78 5f1cf8e6 2004-05-16 devnull if (seen++)
79 5f1cf8e6 2004-05-16 devnull ERROR "%s slug #%d seen %d times [%s]\n",
80 5f1cf8e6 2004-05-16 devnull typename(), serialno(), seen, headstr() WARNING;
81 5f1cf8e6 2004-05-16 devnull if (type == TM) {
82 5f1cf8e6 2004-05-16 devnull char *p;
83 5f1cf8e6 2004-05-16 devnull if ((p = strindex(bufptr(dp), "x X TM ")) != 0)
84 5f1cf8e6 2004-05-16 devnull p += strlen("x X TM "); // skip junk
85 5f1cf8e6 2004-05-16 devnull else
86 5f1cf8e6 2004-05-16 devnull ERROR "strange TM [%s]\n", headstr() FATAL;
87 5f1cf8e6 2004-05-16 devnull fprintf(stderr, "%d\t", userpn); // page # as prefix
88 5f1cf8e6 2004-05-16 devnull for ( ; p < bufptr((this+1)->dp); p++)
89 5f1cf8e6 2004-05-16 devnull putc(*p, stderr);
90 5f1cf8e6 2004-05-16 devnull } else if (type == COORD) {
91 5f1cf8e6 2004-05-16 devnull for (char *p = bufptr(dp); p < bufptr((this+1)->dp) && *p != '\n'; p++)
92 5f1cf8e6 2004-05-16 devnull putc(*p, stdout);
93 5f1cf8e6 2004-05-16 devnull printf(" # P %d X %d", userpn, hpos + col*offset);
94 5f1cf8e6 2004-05-16 devnull return;
95 5f1cf8e6 2004-05-16 devnull } else if (type == VBOX) {
96 5f1cf8e6 2004-05-16 devnull if (numout++ > 0) // BUG??? might miss something
97 5f1cf8e6 2004-05-16 devnull printf("s%d\nf%d\n", size, font);
98 5f1cf8e6 2004-05-16 devnull printf("H%d\n", hpos + col*offset);
99 5f1cf8e6 2004-05-16 devnull }
100 5f1cf8e6 2004-05-16 devnull fwrite(bufptr(dp), sizeof(char), (this+1)->dp - dp, stdout);
101 5f1cf8e6 2004-05-16 devnull }
102 5f1cf8e6 2004-05-16 devnull
103 5f1cf8e6 2004-05-16 devnull char *slug::typename()
104 5f1cf8e6 2004-05-16 devnull {
105 5f1cf8e6 2004-05-16 devnull static char buf[50];
106 5f1cf8e6 2004-05-16 devnull char *p = buf; // return value
107 5f1cf8e6 2004-05-16 devnull switch(type) {
108 5f1cf8e6 2004-05-16 devnull case EOF: p = "EOF"; break;
109 5f1cf8e6 2004-05-16 devnull case VBOX: p = "VBOX"; break;
110 5f1cf8e6 2004-05-16 devnull case SP: p = "SP"; break;
111 5f1cf8e6 2004-05-16 devnull case BS: p = "BS"; break;
112 5f1cf8e6 2004-05-16 devnull case US: p = "US"; break;
113 5f1cf8e6 2004-05-16 devnull case BF: p = "BF"; break;
114 5f1cf8e6 2004-05-16 devnull case UF: p = "UF"; break;
115 5f1cf8e6 2004-05-16 devnull case PT: p = "PT"; break;
116 5f1cf8e6 2004-05-16 devnull case BT: p = "BT"; break;
117 5f1cf8e6 2004-05-16 devnull case END: p = "END"; break;
118 5f1cf8e6 2004-05-16 devnull case NEUTRAL: p = "NEUT"; break;
119 5f1cf8e6 2004-05-16 devnull case PAGE: p = "PAGE"; break;
120 5f1cf8e6 2004-05-16 devnull case TM: p = "TM"; break;
121 5f1cf8e6 2004-05-16 devnull case COORD: p = "COORD"; break;
122 5f1cf8e6 2004-05-16 devnull case NE: p = "NE"; break;
123 5f1cf8e6 2004-05-16 devnull case CMD: p = "CMD"; break;
124 5f1cf8e6 2004-05-16 devnull case PARM: p = "PARM"; break;
125 5f1cf8e6 2004-05-16 devnull default: sprintf(buf, "weird type %d", type);
126 5f1cf8e6 2004-05-16 devnull }
127 5f1cf8e6 2004-05-16 devnull return p;
128 5f1cf8e6 2004-05-16 devnull }
129 5f1cf8e6 2004-05-16 devnull
130 5f1cf8e6 2004-05-16 devnull // ================================================================================
131 5f1cf8e6 2004-05-16 devnull
132 5f1cf8e6 2004-05-16 devnull // troff output-specific functions
133 5f1cf8e6 2004-05-16 devnull
134 5f1cf8e6 2004-05-16 devnull // ================================================================================
135 5f1cf8e6 2004-05-16 devnull
136 5f1cf8e6 2004-05-16 devnull const int DELTABUF = 500000; // grow the input buffer in chunks
137 5f1cf8e6 2004-05-16 devnull
138 5f1cf8e6 2004-05-16 devnull static char *inbuf = 0; // raw text input collects here
139 5f1cf8e6 2004-05-16 devnull static int ninbuf = 0; // byte count for inbuf
140 5f1cf8e6 2004-05-16 devnull static char *inbp = 0; // next free slot in inbuf
141 5f1cf8e6 2004-05-16 devnull int linenum = 0; // input line number
142 5f1cf8e6 2004-05-16 devnull
143 5f1cf8e6 2004-05-16 devnull static inline void addc(int c) { *inbp++ = c; }
144 5f1cf8e6 2004-05-16 devnull
145 5f1cf8e6 2004-05-16 devnull static void adds(char *s)
146 5f1cf8e6 2004-05-16 devnull {
147 5f1cf8e6 2004-05-16 devnull for (char *p = s; *p; p++)
148 5f1cf8e6 2004-05-16 devnull addc(*p);
149 05f5d46b 2006-02-17 devnull }
150 05f5d46b 2006-02-17 devnull
151 05f5d46b 2006-02-17 devnull static int fullrune(char *c, int n)
152 05f5d46b 2006-02-17 devnull {
153 05f5d46b 2006-02-17 devnull if(n <= 0)
154 05f5d46b 2006-02-17 devnull return 0;
155 05f5d46b 2006-02-17 devnull if(n>=1 && (unsigned char)c[0] < 0x80)
156 05f5d46b 2006-02-17 devnull return 1;
157 05f5d46b 2006-02-17 devnull if(n>=2 && (unsigned char)c[0] < 0xE0)
158 05f5d46b 2006-02-17 devnull return 1;
159 05f5d46b 2006-02-17 devnull if(n>=3)
160 05f5d46b 2006-02-17 devnull return 1;
161 05f5d46b 2006-02-17 devnull return 0;
162 5f1cf8e6 2004-05-16 devnull }
163 5f1cf8e6 2004-05-16 devnull
164 5f1cf8e6 2004-05-16 devnull static char *getutf(FILE *fp) // get 1 utf-encoded char (might be multiple bytes)
165 5f1cf8e6 2004-05-16 devnull {
166 5f1cf8e6 2004-05-16 devnull static char buf[100];
167 5f1cf8e6 2004-05-16 devnull char *p = buf;
168 5f1cf8e6 2004-05-16 devnull
169 5f1cf8e6 2004-05-16 devnull for (*p = 0; (*p++ = getc(fp)) != EOF; ) {
170 5f1cf8e6 2004-05-16 devnull *p = 0;
171 54357361 2006-02-14 devnull if (fullrune(buf, p-buf)) // found a valid character
172 5f1cf8e6 2004-05-16 devnull break;
173 5f1cf8e6 2004-05-16 devnull }
174 5f1cf8e6 2004-05-16 devnull return buf;
175 5f1cf8e6 2004-05-16 devnull }
176 5f1cf8e6 2004-05-16 devnull
177 5f1cf8e6 2004-05-16 devnull static char *bufptr(int n) { return inbuf + n; } // scope of inbuf is too local
178 5f1cf8e6 2004-05-16 devnull
179 5f1cf8e6 2004-05-16 devnull static inline int wherebuf() { return inbp - inbuf; }
180 5f1cf8e6 2004-05-16 devnull
181 5f1cf8e6 2004-05-16 devnull static char *getstr(char *p, char *temp)
182 5f1cf8e6 2004-05-16 devnull { // copy next non-blank string from p to temp, update p
183 5f1cf8e6 2004-05-16 devnull while (*p == ' ' || *p == '\t' || *p == '\n')
184 5f1cf8e6 2004-05-16 devnull p++;
185 5f1cf8e6 2004-05-16 devnull if (*p == '\0') {
186 5f1cf8e6 2004-05-16 devnull temp[0] = 0;
187 5f1cf8e6 2004-05-16 devnull return(NULL);
188 5f1cf8e6 2004-05-16 devnull }
189 5f1cf8e6 2004-05-16 devnull while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
190 5f1cf8e6 2004-05-16 devnull *temp++ = *p++;
191 5f1cf8e6 2004-05-16 devnull *temp = '\0';
192 5f1cf8e6 2004-05-16 devnull return(p);
193 5f1cf8e6 2004-05-16 devnull }
194 5f1cf8e6 2004-05-16 devnull
195 5f1cf8e6 2004-05-16 devnull /***************************************************************************
196 5f1cf8e6 2004-05-16 devnull bounding box of a circular arc Eric Grosse 24 May 84
197 5f1cf8e6 2004-05-16 devnull
198 5f1cf8e6 2004-05-16 devnull Conceptually, this routine generates a list consisting of the start,
199 5f1cf8e6 2004-05-16 devnull end, and whichever north, east, south, and west points lie on the arc.
200 5f1cf8e6 2004-05-16 devnull The bounding box is then the range of this list.
201 5f1cf8e6 2004-05-16 devnull list = {start,end}
202 5f1cf8e6 2004-05-16 devnull j = quadrant(start)
203 5f1cf8e6 2004-05-16 devnull k = quadrant(end)
204 5f1cf8e6 2004-05-16 devnull if( j==k && long way 'round ) append north,west,south,east
205 5f1cf8e6 2004-05-16 devnull else
206 5f1cf8e6 2004-05-16 devnull while( j != k )
207 5f1cf8e6 2004-05-16 devnull append center+radius*[j-th of north,west,south,east unit vectors]
208 5f1cf8e6 2004-05-16 devnull j += 1 (mod 4)
209 5f1cf8e6 2004-05-16 devnull return( bounding box of list )
210 5f1cf8e6 2004-05-16 devnull The following code implements this, with simple optimizations.
211 5f1cf8e6 2004-05-16 devnull ***********************************************************************/
212 5f1cf8e6 2004-05-16 devnull
213 5f1cf8e6 2004-05-16 devnull static int quadrant(double x, double y)
214 5f1cf8e6 2004-05-16 devnull {
215 5f1cf8e6 2004-05-16 devnull if ( x>=0.0 && y> 0.0) return(1);
216 5f1cf8e6 2004-05-16 devnull else if( x< 0.0 && y>=0.0) return(2);
217 5f1cf8e6 2004-05-16 devnull else if( x<=0.0 && y< 0.0) return(3);
218 5f1cf8e6 2004-05-16 devnull else if( x> 0.0 && y<=0.0) return(4);
219 5f1cf8e6 2004-05-16 devnull else return 0; /* shut up lint */
220 5f1cf8e6 2004-05-16 devnull }
221 5f1cf8e6 2004-05-16 devnull
222 5f1cf8e6 2004-05-16 devnull static double xmin, ymin, xmax, ymax; // used by getDy
223 5f1cf8e6 2004-05-16 devnull
224 5f1cf8e6 2004-05-16 devnull static void arc_extreme(double x0, double y0, double x1, double y1, double xc, double yc)
225 5f1cf8e6 2004-05-16 devnull /* start, end, center */
226 5f1cf8e6 2004-05-16 devnull { /* assumes center isn't too far out */
227 5f1cf8e6 2004-05-16 devnull double r;
228 5f1cf8e6 2004-05-16 devnull int j, k;
229 5f1cf8e6 2004-05-16 devnull printf("#start %g,%g, end %g,%g, ctr %g,%g\n", x0,y0, x1,y1, xc,yc);
230 5f1cf8e6 2004-05-16 devnull y0 = -y0; y1 = -y1; yc = -yc; // troff's up is eric's down
231 5f1cf8e6 2004-05-16 devnull x0 -= xc; y0 -= yc; /* move to center */
232 5f1cf8e6 2004-05-16 devnull x1 -= xc; y1 -= yc;
233 5f1cf8e6 2004-05-16 devnull xmin = (x0<x1)?x0:x1; ymin = (y0<y1)?y0:y1;
234 5f1cf8e6 2004-05-16 devnull xmax = (x0>x1)?x0:x1; ymax = (y0>y1)?y0:y1;
235 5f1cf8e6 2004-05-16 devnull r = sqrt(x0*x0 + y0*y0);
236 5f1cf8e6 2004-05-16 devnull if (r > 0.0) {
237 5f1cf8e6 2004-05-16 devnull j = quadrant(x0,y0);
238 5f1cf8e6 2004-05-16 devnull k = quadrant(x1,y1);
239 5f1cf8e6 2004-05-16 devnull if (j == k && y1*x0 < x1*y0) {
240 5f1cf8e6 2004-05-16 devnull /* viewed as complex numbers, if Im(z1/z0)<0, arc is big */
241 5f1cf8e6 2004-05-16 devnull if( xmin > -r) xmin = -r; if( ymin > -r) ymin = -r;
242 5f1cf8e6 2004-05-16 devnull if( xmax < r) xmax = r; if( ymax < r) ymax = r;
243 5f1cf8e6 2004-05-16 devnull } else {
244 5f1cf8e6 2004-05-16 devnull while (j != k) {
245 5f1cf8e6 2004-05-16 devnull switch (j) {
246 5f1cf8e6 2004-05-16 devnull case 1: if( ymax < r) ymax = r; break; /* north */
247 5f1cf8e6 2004-05-16 devnull case 2: if( xmin > -r) xmin = -r; break; /* west */
248 5f1cf8e6 2004-05-16 devnull case 3: if( ymin > -r) ymin = -r; break; /* south */
249 5f1cf8e6 2004-05-16 devnull case 4: if( xmax < r) xmax = r; break; /* east */
250 5f1cf8e6 2004-05-16 devnull }
251 5f1cf8e6 2004-05-16 devnull j = j%4 + 1;
252 5f1cf8e6 2004-05-16 devnull }
253 5f1cf8e6 2004-05-16 devnull }
254 5f1cf8e6 2004-05-16 devnull }
255 5f1cf8e6 2004-05-16 devnull xmin += xc; ymin += yc; ymin = -ymin;
256 5f1cf8e6 2004-05-16 devnull xmax += xc; ymax += yc; ymax = -ymax;
257 5f1cf8e6 2004-05-16 devnull }
258 5f1cf8e6 2004-05-16 devnull
259 5f1cf8e6 2004-05-16 devnull
260 5f1cf8e6 2004-05-16 devnull static int getDy(char *p, int *dx, int *maxv)
261 5f1cf8e6 2004-05-16 devnull // figure out where we are after a D'...'
262 5f1cf8e6 2004-05-16 devnull {
263 5f1cf8e6 2004-05-16 devnull int x, y, x1, y1; // for input values
264 5f1cf8e6 2004-05-16 devnull char temp[50];
265 5f1cf8e6 2004-05-16 devnull p++; // get to command letter
266 5f1cf8e6 2004-05-16 devnull switch (*p++) {
267 5f1cf8e6 2004-05-16 devnull case 'l': // line
268 5f1cf8e6 2004-05-16 devnull sscanf(p, "%d %d", dx, &y);
269 5f1cf8e6 2004-05-16 devnull return *maxv = y;
270 5f1cf8e6 2004-05-16 devnull case 'a': // arc
271 5f1cf8e6 2004-05-16 devnull sscanf(p, "%d %d %d %d", &x, &y, &x1, &y1);
272 5f1cf8e6 2004-05-16 devnull *dx = x1 - x;
273 5f1cf8e6 2004-05-16 devnull arc_extreme(0, 0, x+x1, y+y1, x, y); // sets [xy][max|min]
274 5f1cf8e6 2004-05-16 devnull printf("#arc bounds x %g, %g; y %g, %g\n",
275 5f1cf8e6 2004-05-16 devnull xmin, xmax, ymin, ymax);
276 5f1cf8e6 2004-05-16 devnull *maxv = (int) (ymin+0.5);
277 5f1cf8e6 2004-05-16 devnull return y + y1;
278 5f1cf8e6 2004-05-16 devnull case '~': // spline
279 5f1cf8e6 2004-05-16 devnull for (*dx = *maxv = y = 0; (p=getstr(p, temp)) != NULL; ) {
280 5f1cf8e6 2004-05-16 devnull // above getstr() gets x value
281 5f1cf8e6 2004-05-16 devnull *dx += atoi(temp);
282 5f1cf8e6 2004-05-16 devnull p = getstr(p, temp); // this one gets y value
283 5f1cf8e6 2004-05-16 devnull y += atoi(temp);
284 5f1cf8e6 2004-05-16 devnull *maxv = max(*maxv, y); // ok???
285 5f1cf8e6 2004-05-16 devnull if (*p == '\n' || *p == 0) // input is a single line;
286 5f1cf8e6 2004-05-16 devnull break; // don't walk off end if realloc
287 5f1cf8e6 2004-05-16 devnull }
288 5f1cf8e6 2004-05-16 devnull return y;
289 5f1cf8e6 2004-05-16 devnull case 'c': // circle, ellipse
290 5f1cf8e6 2004-05-16 devnull sscanf(p, "%d", dx);
291 5f1cf8e6 2004-05-16 devnull *maxv = *dx/2; // high water mark is ht/2
292 5f1cf8e6 2004-05-16 devnull return 0;
293 5f1cf8e6 2004-05-16 devnull case 'e':
294 5f1cf8e6 2004-05-16 devnull sscanf(p, "%d %d", dx, &y);
295 5f1cf8e6 2004-05-16 devnull *maxv = y/2; // high water mark is ht/2
296 5f1cf8e6 2004-05-16 devnull return 0;
297 5f1cf8e6 2004-05-16 devnull default: // weird stuff
298 5f1cf8e6 2004-05-16 devnull return 0;
299 5f1cf8e6 2004-05-16 devnull }
300 5f1cf8e6 2004-05-16 devnull }
301 5f1cf8e6 2004-05-16 devnull
302 5f1cf8e6 2004-05-16 devnull static int serialnum = 0;
303 5f1cf8e6 2004-05-16 devnull
304 5f1cf8e6 2004-05-16 devnull slug eofslug()
305 5f1cf8e6 2004-05-16 devnull {
306 5f1cf8e6 2004-05-16 devnull slug ret;
307 5f1cf8e6 2004-05-16 devnull ret.serialnum = serialnum;
308 5f1cf8e6 2004-05-16 devnull ret.type = EOF;
309 5f1cf8e6 2004-05-16 devnull ret.dp = wherebuf();
310 5f1cf8e6 2004-05-16 devnull return ret;
311 5f1cf8e6 2004-05-16 devnull }
312 5f1cf8e6 2004-05-16 devnull
313 5f1cf8e6 2004-05-16 devnull slug getslug(FILE *fp)
314 5f1cf8e6 2004-05-16 devnull {
315 5f1cf8e6 2004-05-16 devnull if (inbuf == NULL) {
316 5f1cf8e6 2004-05-16 devnull if ((inbuf = (char *) malloc(ninbuf = DELTABUF)) == NULL)
317 5f1cf8e6 2004-05-16 devnull ERROR "no room for %d character input buffer\n", ninbuf FATAL;
318 5f1cf8e6 2004-05-16 devnull inbp = inbuf;
319 5f1cf8e6 2004-05-16 devnull }
320 5f1cf8e6 2004-05-16 devnull if (wherebuf() > ninbuf-5000) {
321 5f1cf8e6 2004-05-16 devnull // this is still flaky -- lines can be very long
322 5f1cf8e6 2004-05-16 devnull int where = wherebuf(); // where we were
323 5f1cf8e6 2004-05-16 devnull if ((inbuf = (char *) realloc(inbuf, ninbuf += DELTABUF)) == NULL)
324 5f1cf8e6 2004-05-16 devnull ERROR "no room for %d character input buffer\n", ninbuf FATAL;
325 5f1cf8e6 2004-05-16 devnull ERROR "grew input buffer to %d characters\n", ninbuf WARNING;
326 5f1cf8e6 2004-05-16 devnull inbp = inbuf + where; // same offset in new array
327 5f1cf8e6 2004-05-16 devnull }
328 5f1cf8e6 2004-05-16 devnull static int baseV = 0; // first V command of preceding slug
329 5f1cf8e6 2004-05-16 devnull static int curV = 0, curH = 0;
330 5f1cf8e6 2004-05-16 devnull static int font = 0, size = 0;
331 5f1cf8e6 2004-05-16 devnull static int baseadj = 0;
332 5f1cf8e6 2004-05-16 devnull static int ncol = 1, offset = 0; // multi-column stuff
333 5f1cf8e6 2004-05-16 devnull char str[1000], str2[1000], buf[3000], *p;
334 5f1cf8e6 2004-05-16 devnull int firstV = 0, firstH = 0;
335 5f1cf8e6 2004-05-16 devnull int maxV = curV;
336 5f1cf8e6 2004-05-16 devnull int ocurV = curV, mxv = 0, dx = 0;
337 5f1cf8e6 2004-05-16 devnull int sawD = 0; // > 0 if have seen D...
338 5f1cf8e6 2004-05-16 devnull slug ret;
339 5f1cf8e6 2004-05-16 devnull ret.serialnum = serialnum++;
340 5f1cf8e6 2004-05-16 devnull ret.type = VBOX; // use the same as last by default
341 5f1cf8e6 2004-05-16 devnull ret.dv = curV - baseV;
342 5f1cf8e6 2004-05-16 devnull ret.hpos = curH;
343 5f1cf8e6 2004-05-16 devnull ret.base = ret.parm = ret.parm2 = ret.seen = 0;
344 5f1cf8e6 2004-05-16 devnull ret.font = font;
345 5f1cf8e6 2004-05-16 devnull ret.size = size;
346 5f1cf8e6 2004-05-16 devnull ret.dp = wherebuf();
347 5f1cf8e6 2004-05-16 devnull ret.ncol = ncol;
348 5f1cf8e6 2004-05-16 devnull ret.offset = offset;
349 5f1cf8e6 2004-05-16 devnull ret.linenum = linenum; // might be low
350 5f1cf8e6 2004-05-16 devnull
351 5f1cf8e6 2004-05-16 devnull for (;;) {
352 5f1cf8e6 2004-05-16 devnull int c, m, n; // for input values
353 5f1cf8e6 2004-05-16 devnull int sign; // hoisted from case 'h' below
354 5f1cf8e6 2004-05-16 devnull switch (c = getc(fp)) {
355 5f1cf8e6 2004-05-16 devnull case EOF:
356 5f1cf8e6 2004-05-16 devnull ret.type = EOF;
357 5f1cf8e6 2004-05-16 devnull ret.dv = 0;
358 5f1cf8e6 2004-05-16 devnull if (baseadj)
359 5f1cf8e6 2004-05-16 devnull printf("# adjusted %d bases\n", baseadj);
360 5f1cf8e6 2004-05-16 devnull printf("# %d characters, %d lines\n", wherebuf(), linenum);
361 5f1cf8e6 2004-05-16 devnull return ret;
362 5f1cf8e6 2004-05-16 devnull case 'V':
363 5f1cf8e6 2004-05-16 devnull fscanf(fp, "%d", &n);
364 5f1cf8e6 2004-05-16 devnull if (firstV++ == 0) {
365 5f1cf8e6 2004-05-16 devnull ret.dv = n - baseV;
366 5f1cf8e6 2004-05-16 devnull baseV = n;
367 5f1cf8e6 2004-05-16 devnull } else {
368 5f1cf8e6 2004-05-16 devnull sprintf(buf, "v%d", n - curV);
369 5f1cf8e6 2004-05-16 devnull adds(buf);
370 5f1cf8e6 2004-05-16 devnull }
371 5f1cf8e6 2004-05-16 devnull curV = n;
372 5f1cf8e6 2004-05-16 devnull maxV = max(maxV, curV);
373 5f1cf8e6 2004-05-16 devnull break;
374 5f1cf8e6 2004-05-16 devnull case 'H': // absolute H motion
375 5f1cf8e6 2004-05-16 devnull fscanf(fp, "%d", &n);
376 5f1cf8e6 2004-05-16 devnull if (firstH++ == 0) {
377 5f1cf8e6 2004-05-16 devnull ret.hpos = n;
378 5f1cf8e6 2004-05-16 devnull } else {
379 5f1cf8e6 2004-05-16 devnull sprintf(buf, "h%d", n - curH);
380 5f1cf8e6 2004-05-16 devnull adds(buf);
381 5f1cf8e6 2004-05-16 devnull }
382 5f1cf8e6 2004-05-16 devnull curH = n;
383 5f1cf8e6 2004-05-16 devnull break;
384 5f1cf8e6 2004-05-16 devnull case 'h': // relative H motion
385 5f1cf8e6 2004-05-16 devnull addc(c);
386 5f1cf8e6 2004-05-16 devnull sign = 1;
387 5f1cf8e6 2004-05-16 devnull if ((c = getc(fp)) == '-') {
388 5f1cf8e6 2004-05-16 devnull addc(c);
389 5f1cf8e6 2004-05-16 devnull sign = -1;
390 5f1cf8e6 2004-05-16 devnull c = getc(fp);
391 5f1cf8e6 2004-05-16 devnull }
392 5f1cf8e6 2004-05-16 devnull for (n = 0; isdigit(c); c = getc(fp)) {
393 5f1cf8e6 2004-05-16 devnull addc(c);
394 5f1cf8e6 2004-05-16 devnull n = 10 * n + c - '0';
395 5f1cf8e6 2004-05-16 devnull }
396 5f1cf8e6 2004-05-16 devnull curH += n * sign;
397 5f1cf8e6 2004-05-16 devnull ungetc(c, fp);
398 5f1cf8e6 2004-05-16 devnull break;
399 5f1cf8e6 2004-05-16 devnull case 'x': // device control: x ...
400 5f1cf8e6 2004-05-16 devnull addc(c);
401 5f1cf8e6 2004-05-16 devnull fgets(buf, (int) sizeof(buf), fp);
402 5f1cf8e6 2004-05-16 devnull linenum++;
403 5f1cf8e6 2004-05-16 devnull adds(buf);
404 5f1cf8e6 2004-05-16 devnull if (buf[0] == ' ' && buf[1] == 'X') { // x X ...
405 5f1cf8e6 2004-05-16 devnull if (2 != sscanf(buf+2, "%s %d", str, &n))
406 5f1cf8e6 2004-05-16 devnull n = 0;
407 5f1cf8e6 2004-05-16 devnull if (eq(str, "SP")) { // X SP n
408 5f1cf8e6 2004-05-16 devnull ret.type = SP; // paddable SPace
409 5f1cf8e6 2004-05-16 devnull ret.dv = n; // of height n
410 5f1cf8e6 2004-05-16 devnull } else if (eq(str, "BS")) {
411 5f1cf8e6 2004-05-16 devnull ret.type = BS; // Breakable Stream
412 5f1cf8e6 2004-05-16 devnull ret.parm = n; // >=n VBOXES on a page
413 5f1cf8e6 2004-05-16 devnull } else if (eq(str, "BF")) {
414 5f1cf8e6 2004-05-16 devnull ret.type = BF; // Breakable Float
415 5f1cf8e6 2004-05-16 devnull ret.parm = ret.parm2 = n;
416 5f1cf8e6 2004-05-16 devnull // n = pref center (as UF)
417 5f1cf8e6 2004-05-16 devnull } else if (eq(str, "US")) {
418 5f1cf8e6 2004-05-16 devnull ret.type = US; // Unbreakable Stream
419 5f1cf8e6 2004-05-16 devnull ret.parm = n;
420 5f1cf8e6 2004-05-16 devnull } else if (eq(str, "UF")) {
421 5f1cf8e6 2004-05-16 devnull ret.type = UF; // Unbreakable Float
422 5f1cf8e6 2004-05-16 devnull ret.parm = ret.parm2 = n;
423 5f1cf8e6 2004-05-16 devnull // n = preferred center
424 5f1cf8e6 2004-05-16 devnull // to select several,
425 5f1cf8e6 2004-05-16 devnull // use several UF lines
426 5f1cf8e6 2004-05-16 devnull } else if (eq(str, "PT")) {
427 5f1cf8e6 2004-05-16 devnull ret.type = PT; // Page Title
428 5f1cf8e6 2004-05-16 devnull ret.parm = n;
429 5f1cf8e6 2004-05-16 devnull } else if (eq(str, "BT")) {
430 5f1cf8e6 2004-05-16 devnull ret.type = BT; // Bottom Title
431 5f1cf8e6 2004-05-16 devnull ret.parm = n;
432 5f1cf8e6 2004-05-16 devnull } else if (eq(str, "END")) {
433 5f1cf8e6 2004-05-16 devnull ret.type = END;
434 5f1cf8e6 2004-05-16 devnull ret.parm = n;
435 5f1cf8e6 2004-05-16 devnull } else if (eq(str, "TM")) {
436 5f1cf8e6 2004-05-16 devnull ret.type = TM; // Terminal Message
437 5f1cf8e6 2004-05-16 devnull ret.dv = 0;
438 5f1cf8e6 2004-05-16 devnull } else if (eq(str, "COORD")) {
439 5f1cf8e6 2004-05-16 devnull ret.type = COORD;// page COORDinates
440 5f1cf8e6 2004-05-16 devnull ret.dv = 0;
441 5f1cf8e6 2004-05-16 devnull } else if (eq(str, "NE")) {
442 5f1cf8e6 2004-05-16 devnull ret.type = NE; // NEed to break page
443 5f1cf8e6 2004-05-16 devnull ret.dv = n; // if <n units left
444 5f1cf8e6 2004-05-16 devnull } else if (eq(str, "MC")) {
445 5f1cf8e6 2004-05-16 devnull ret.type = MC; // Multiple Columns
446 5f1cf8e6 2004-05-16 devnull sscanf(buf+2, "%s %d %d",
447 5f1cf8e6 2004-05-16 devnull str, &ncol, &offset);
448 5f1cf8e6 2004-05-16 devnull ret.ncol = ncol;
449 5f1cf8e6 2004-05-16 devnull ret.offset = offset;
450 5f1cf8e6 2004-05-16 devnull } else if (eq(str, "CMD")) {
451 5f1cf8e6 2004-05-16 devnull ret.type = CMD; // CoMmaNd
452 5f1cf8e6 2004-05-16 devnull sscanf(buf+2, "%s %s", str2, str);
453 5f1cf8e6 2004-05-16 devnull if (eq(str, "FC")) // Freeze 2-Col
454 5f1cf8e6 2004-05-16 devnull ret.parm = FC;
455 5f1cf8e6 2004-05-16 devnull else if (eq(str, "FL")) // FLush
456 5f1cf8e6 2004-05-16 devnull ret.parm = FL;
457 5f1cf8e6 2004-05-16 devnull else if (eq(str, "BP")) // Break Page
458 5f1cf8e6 2004-05-16 devnull ret.parm = BP;
459 5f1cf8e6 2004-05-16 devnull else ERROR "unknown command %s\n",
460 5f1cf8e6 2004-05-16 devnull str WARNING;
461 5f1cf8e6 2004-05-16 devnull } else if (eq(str, "PARM")) {
462 5f1cf8e6 2004-05-16 devnull ret.type = PARM;// PARaMeter
463 5f1cf8e6 2004-05-16 devnull sscanf(buf+2, "%s %s %d", str2, str, &ret.parm2);
464 5f1cf8e6 2004-05-16 devnull if (eq(str, "NP")) // New Page
465 5f1cf8e6 2004-05-16 devnull ret.parm = NP;
466 5f1cf8e6 2004-05-16 devnull else if (eq(str, "FO")) // FOoter
467 5f1cf8e6 2004-05-16 devnull ret.parm = FO;
468 5f1cf8e6 2004-05-16 devnull else if (eq(str, "PL")) // Page Length
469 5f1cf8e6 2004-05-16 devnull ret.parm = PL;
470 5f1cf8e6 2004-05-16 devnull else if (eq(str, "MF")) // MinFull
471 5f1cf8e6 2004-05-16 devnull ret.parm = MF;
472 5f1cf8e6 2004-05-16 devnull else if (eq(str, "CT")) // ColTol
473 5f1cf8e6 2004-05-16 devnull ret.parm = CT;
474 5f1cf8e6 2004-05-16 devnull else if (eq(str, "WARN")) //WARNings?
475 5f1cf8e6 2004-05-16 devnull ret.parm = WARN;
476 5f1cf8e6 2004-05-16 devnull else if (eq(str, "DBG"))// DeBuG
477 5f1cf8e6 2004-05-16 devnull ret.parm = DBG;
478 5f1cf8e6 2004-05-16 devnull else ERROR "unknown parameter %s\n",
479 5f1cf8e6 2004-05-16 devnull str WARNING;
480 5f1cf8e6 2004-05-16 devnull } else
481 5f1cf8e6 2004-05-16 devnull break; // out of switch
482 5f1cf8e6 2004-05-16 devnull if (firstV > 0)
483 5f1cf8e6 2004-05-16 devnull ERROR "weird x X %s in mid-VBOX\n",
484 5f1cf8e6 2004-05-16 devnull str WARNING;
485 5f1cf8e6 2004-05-16 devnull return ret;
486 5f1cf8e6 2004-05-16 devnull }
487 5f1cf8e6 2004-05-16 devnull break;
488 5f1cf8e6 2004-05-16 devnull case 'n': // end of line
489 5f1cf8e6 2004-05-16 devnull fscanf(fp, "%d %d", &n, &m);
490 5f1cf8e6 2004-05-16 devnull ret.ht = n;
491 5f1cf8e6 2004-05-16 devnull ret.base = m;
492 5f1cf8e6 2004-05-16 devnull getc(fp); // newline
493 5f1cf8e6 2004-05-16 devnull linenum++;
494 5f1cf8e6 2004-05-16 devnull sprintf(buf, "n%d %d\n", ret.ht, ret.base);
495 5f1cf8e6 2004-05-16 devnull adds(buf);
496 5f1cf8e6 2004-05-16 devnull if (!firstV++)
497 5f1cf8e6 2004-05-16 devnull baseV = curV;
498 5f1cf8e6 2004-05-16 devnull // older incarnations of this program used ret.base
499 5f1cf8e6 2004-05-16 devnull // in complicated and unreliable ways;
500 5f1cf8e6 2004-05-16 devnull // example: if ret.ht + ret.base < ret.dv, ret.base = 0
501 5f1cf8e6 2004-05-16 devnull // this was meant to avoid double-counting the space
502 5f1cf8e6 2004-05-16 devnull // around displayed equations; it didn't work
503 5f1cf8e6 2004-05-16 devnull // Now, we believe ret.base = 0, otherwise we give it
504 5f1cf8e6 2004-05-16 devnull // a value we have computed.
505 5f1cf8e6 2004-05-16 devnull if (ret.base == 0 && sawD == 0)
506 5f1cf8e6 2004-05-16 devnull return ret; // don't fiddle 0-bases
507 5f1cf8e6 2004-05-16 devnull if (ret.base != maxV - baseV) {
508 5f1cf8e6 2004-05-16 devnull ret.base = maxV - baseV;
509 5f1cf8e6 2004-05-16 devnull baseadj++;
510 5f1cf8e6 2004-05-16 devnull }
511 5f1cf8e6 2004-05-16 devnull if (ret.type != VBOX)
512 5f1cf8e6 2004-05-16 devnull ERROR "%s slug (type %d) has base = %d\n",
513 5f1cf8e6 2004-05-16 devnull ret.typename(), ret.type, ret.base WARNING;
514 5f1cf8e6 2004-05-16 devnull return ret;
515 5f1cf8e6 2004-05-16 devnull case 'p': // new page
516 5f1cf8e6 2004-05-16 devnull fscanf(fp, "%d", &n);
517 5f1cf8e6 2004-05-16 devnull ret.type = PAGE;
518 5f1cf8e6 2004-05-16 devnull curV = baseV = ret.dv = 0;
519 5f1cf8e6 2004-05-16 devnull ret.parm = n; // just in case someone needs it
520 5f1cf8e6 2004-05-16 devnull return ret;
521 5f1cf8e6 2004-05-16 devnull case 's': // size change snnn
522 5f1cf8e6 2004-05-16 devnull fscanf(fp, "%d", &size);
523 5f1cf8e6 2004-05-16 devnull sprintf(buf, "s%d\n", size);
524 5f1cf8e6 2004-05-16 devnull adds(buf);
525 5f1cf8e6 2004-05-16 devnull break;
526 5f1cf8e6 2004-05-16 devnull case 'f': // font fnnn
527 5f1cf8e6 2004-05-16 devnull fscanf(fp, "%d", &font);
528 5f1cf8e6 2004-05-16 devnull sprintf(buf, "f%d\n", font);
529 5f1cf8e6 2004-05-16 devnull adds(buf);
530 5f1cf8e6 2004-05-16 devnull break;
531 5f1cf8e6 2004-05-16 devnull case '\n':
532 5f1cf8e6 2004-05-16 devnull linenum++;
533 5f1cf8e6 2004-05-16 devnull /* fall through */
534 5f1cf8e6 2004-05-16 devnull case ' ':
535 5f1cf8e6 2004-05-16 devnull addc(c);
536 5f1cf8e6 2004-05-16 devnull break;
537 5f1cf8e6 2004-05-16 devnull case '0': case '1': case '2': case '3': case '4':
538 5f1cf8e6 2004-05-16 devnull case '5': case '6': case '7': case '8': case '9':
539 5f1cf8e6 2004-05-16 devnull // two motion digits plus a character
540 5f1cf8e6 2004-05-16 devnull addc(c);
541 5f1cf8e6 2004-05-16 devnull n = c - '0';
542 5f1cf8e6 2004-05-16 devnull addc(c = getc(fp));
543 5f1cf8e6 2004-05-16 devnull curH += 10 * n + c - '0';
544 5f1cf8e6 2004-05-16 devnull adds(getutf(fp));
545 5f1cf8e6 2004-05-16 devnull if (!firstV++)
546 5f1cf8e6 2004-05-16 devnull baseV = curV;
547 5f1cf8e6 2004-05-16 devnull break;
548 5f1cf8e6 2004-05-16 devnull case 'c': // single ascii character
549 5f1cf8e6 2004-05-16 devnull addc(c);
550 5f1cf8e6 2004-05-16 devnull adds(getutf(fp));
551 5f1cf8e6 2004-05-16 devnull if (!firstV++)
552 5f1cf8e6 2004-05-16 devnull baseV = curV;
553 5f1cf8e6 2004-05-16 devnull break;
554 5f1cf8e6 2004-05-16 devnull case 'C': // Cxyz\n
555 5f1cf8e6 2004-05-16 devnull case 'N': // Nnnn\n
556 5f1cf8e6 2004-05-16 devnull addc(c);
557 5f1cf8e6 2004-05-16 devnull while ((c = getc(fp)) != ' ' && c != '\n')
558 5f1cf8e6 2004-05-16 devnull addc(c);
559 5f1cf8e6 2004-05-16 devnull addc(c);
560 5f1cf8e6 2004-05-16 devnull if (!firstV++)
561 5f1cf8e6 2004-05-16 devnull baseV = curV;
562 5f1cf8e6 2004-05-16 devnull linenum++;
563 5f1cf8e6 2004-05-16 devnull break;
564 5f1cf8e6 2004-05-16 devnull case 'D': // draw function: D.*\n
565 5f1cf8e6 2004-05-16 devnull sawD++;
566 5f1cf8e6 2004-05-16 devnull p = bufptr(wherebuf()); // where does the D start
567 5f1cf8e6 2004-05-16 devnull addc(c);
568 5f1cf8e6 2004-05-16 devnull while ((c = getc(fp)) != '\n')
569 5f1cf8e6 2004-05-16 devnull addc(c);
570 5f1cf8e6 2004-05-16 devnull addc(c);
571 5f1cf8e6 2004-05-16 devnull if (!firstV++)
572 5f1cf8e6 2004-05-16 devnull baseV = curV;
573 5f1cf8e6 2004-05-16 devnull ocurV = curV, mxv = 0, dx = 0;
574 5f1cf8e6 2004-05-16 devnull curV += getDy(p, &dx, &mxv); // figure out how big it is
575 5f1cf8e6 2004-05-16 devnull maxV = max(max(maxV, curV), ocurV+mxv);
576 5f1cf8e6 2004-05-16 devnull curH += dx;
577 5f1cf8e6 2004-05-16 devnull linenum++;
578 5f1cf8e6 2004-05-16 devnull break;
579 5f1cf8e6 2004-05-16 devnull case 'v': // relative vertical vnnn
580 5f1cf8e6 2004-05-16 devnull addc(c);
581 5f1cf8e6 2004-05-16 devnull if (!firstV++)
582 5f1cf8e6 2004-05-16 devnull baseV = curV;
583 5f1cf8e6 2004-05-16 devnull sign = 1;
584 5f1cf8e6 2004-05-16 devnull if ((c = getc(fp)) == '-') {
585 5f1cf8e6 2004-05-16 devnull addc(c);
586 5f1cf8e6 2004-05-16 devnull sign = -1;
587 5f1cf8e6 2004-05-16 devnull c = getc(fp);
588 5f1cf8e6 2004-05-16 devnull }
589 5f1cf8e6 2004-05-16 devnull for (n = 0; isdigit(c); c = getc(fp)) {
590 5f1cf8e6 2004-05-16 devnull addc(c);
591 5f1cf8e6 2004-05-16 devnull n = 10 * n + c - '0';
592 5f1cf8e6 2004-05-16 devnull }
593 5f1cf8e6 2004-05-16 devnull ungetc(c, fp);
594 5f1cf8e6 2004-05-16 devnull curV += n * sign;
595 5f1cf8e6 2004-05-16 devnull maxV = max(maxV, curV);
596 5f1cf8e6 2004-05-16 devnull addc('\n');
597 5f1cf8e6 2004-05-16 devnull break;
598 5f1cf8e6 2004-05-16 devnull case 'w': // word space
599 5f1cf8e6 2004-05-16 devnull addc(c);
600 5f1cf8e6 2004-05-16 devnull break;
601 5f1cf8e6 2004-05-16 devnull case '#': // comment
602 5f1cf8e6 2004-05-16 devnull addc(c);
603 5f1cf8e6 2004-05-16 devnull while ((c = getc(fp)) != '\n')
604 5f1cf8e6 2004-05-16 devnull addc(c);
605 5f1cf8e6 2004-05-16 devnull addc('\n');
606 5f1cf8e6 2004-05-16 devnull linenum++;
607 5f1cf8e6 2004-05-16 devnull break;
608 5f1cf8e6 2004-05-16 devnull default:
609 5f1cf8e6 2004-05-16 devnull ERROR "unknown input character %o %c (%50.50s)\n",
610 5f1cf8e6 2004-05-16 devnull c, c, bufptr(wherebuf()-50) WARNING;
611 5f1cf8e6 2004-05-16 devnull abort();
612 5f1cf8e6 2004-05-16 devnull break;
613 5f1cf8e6 2004-05-16 devnull }
614 5f1cf8e6 2004-05-16 devnull }
615 5f1cf8e6 2004-05-16 devnull }