1 5f1cf8e6 2004-05-16 devnull #include <math.h>
2 5f1cf8e6 2004-05-16 devnull #include "misc.h"
3 5f1cf8e6 2004-05-16 devnull #include "slug.h"
4 5f1cf8e6 2004-05-16 devnull #include "range.h"
6 5f1cf8e6 2004-05-16 devnull void sprange::reheight(int *cv, int *mv)
8 5f1cf8e6 2004-05-16 devnull if (*cv != *mv)
9 5f1cf8e6 2004-05-16 devnull ERROR "slug %d: an imbedded SP, line %d\n",
10 5f1cf8e6 2004-05-16 devnull first->serialno(), first->lineno() WARNING;
11 5f1cf8e6 2004-05-16 devnull *cv += dv;
12 5f1cf8e6 2004-05-16 devnull *mv = max(*mv, *cv);
15 5f1cf8e6 2004-05-16 devnull void sprange::rerawht(int *cv, int *mv)
17 5f1cf8e6 2004-05-16 devnull *cv += rawht();
18 5f1cf8e6 2004-05-16 devnull *mv = max(*mv, *cv);
21 5f1cf8e6 2004-05-16 devnull void nestrange::restore()
23 5f1cf8e6 2004-05-16 devnull subrange->restoreall();
26 5f1cf8e6 2004-05-16 devnull void stream::freeall() // not a destructor; called explicitly
28 5f1cf8e6 2004-05-16 devnull strblk *p, *q;
29 5f1cf8e6 2004-05-16 devnull for (p = first; p; p = q) {
30 5f1cf8e6 2004-05-16 devnull q = p->next;
31 5f1cf8e6 2004-05-16 devnull delete p;
33 5f1cf8e6 2004-05-16 devnull first = last = curr = 0;
36 5f1cf8e6 2004-05-16 devnull void stream::dump()
38 5f1cf8e6 2004-05-16 devnull for (stream s = *this; s.more(); s.advance())
39 5f1cf8e6 2004-05-16 devnull s.current()->dump();
42 5f1cf8e6 2004-05-16 devnull void stream::rdump()
44 5f1cf8e6 2004-05-16 devnull for (stream s = *this; s.more(); s.advance())
45 5f1cf8e6 2004-05-16 devnull s.current()->rdump();
48 5f1cf8e6 2004-05-16 devnull int stream::restoreall()
50 5f1cf8e6 2004-05-16 devnull for (stream s = *this; s.more(); s.advance())
51 5f1cf8e6 2004-05-16 devnull s.current()->restore();
52 5f1cf8e6 2004-05-16 devnull return measure(this);
55 5f1cf8e6 2004-05-16 devnull range *stream::append(range *r)
57 5f1cf8e6 2004-05-16 devnull if (last == 0)
58 5f1cf8e6 2004-05-16 devnull curr = first = last = new strblk;
60 5f1cf8e6 2004-05-16 devnull last->next = new strblk;
61 5f1cf8e6 2004-05-16 devnull last = last->next;
62 5f1cf8e6 2004-05-16 devnull if (curr == 0)
63 5f1cf8e6 2004-05-16 devnull curr = last;
65 5f1cf8e6 2004-05-16 devnull last->next = 0;
66 5f1cf8e6 2004-05-16 devnull return last->rp = r;
69 5f1cf8e6 2004-05-16 devnull void stream::split() // duplicate current() range
71 5f1cf8e6 2004-05-16 devnull strblk *s2 = new strblk;
72 5f1cf8e6 2004-05-16 devnull range *r2 = curr->rp->clone();
73 5f1cf8e6 2004-05-16 devnull s2->rp = r2;
74 5f1cf8e6 2004-05-16 devnull s2->next = curr->next;
75 5f1cf8e6 2004-05-16 devnull if (last == curr)
76 5f1cf8e6 2004-05-16 devnull last = s2;
77 5f1cf8e6 2004-05-16 devnull curr->next = s2;
78 5f1cf8e6 2004-05-16 devnull curr->rp->killkids(); // children only in the 2nd one
79 5f1cf8e6 2004-05-16 devnull // r2->crosslink(r1);
82 5f1cf8e6 2004-05-16 devnull int stream::height()
85 5f1cf8e6 2004-05-16 devnull stream s = *this;
86 5f1cf8e6 2004-05-16 devnull for (h = 0; s.more(); s.advance())
87 5f1cf8e6 2004-05-16 devnull h += s.current()->height();
88 5f1cf8e6 2004-05-16 devnull return h;
91 5f1cf8e6 2004-05-16 devnull int stream::rawht()
94 5f1cf8e6 2004-05-16 devnull stream s = *this;
95 5f1cf8e6 2004-05-16 devnull for (h = 0; s.more(); s.advance())
96 5f1cf8e6 2004-05-16 devnull h += s.current()->rawht();
97 5f1cf8e6 2004-05-16 devnull return h;
100 5f1cf8e6 2004-05-16 devnull int measure(stream *sp) // record high-water mark of stream
101 5f1cf8e6 2004-05-16 devnull { // sets nested stream heights
102 5f1cf8e6 2004-05-16 devnull stream s = *sp;
103 5f1cf8e6 2004-05-16 devnull int curv, maxv;
104 5f1cf8e6 2004-05-16 devnull for (maxv = curv = 0; s.more(); s.advance())
105 5f1cf8e6 2004-05-16 devnull s.current()->reheight(&curv, &maxv);
106 5f1cf8e6 2004-05-16 devnull return maxv;
109 5f1cf8e6 2004-05-16 devnull int rawmeasure(stream *sp)
111 5f1cf8e6 2004-05-16 devnull stream s = *sp;
112 5f1cf8e6 2004-05-16 devnull int curv, maxv;
113 5f1cf8e6 2004-05-16 devnull for (maxv = curv = 0; s.more(); s.advance())
114 5f1cf8e6 2004-05-16 devnull s.current()->rerawht(&curv, &maxv);
115 5f1cf8e6 2004-05-16 devnull return maxv;
118 5f1cf8e6 2004-05-16 devnull void nestrange::rdump()
121 5f1cf8e6 2004-05-16 devnull if (subrange)
122 5f1cf8e6 2004-05-16 devnull subrange->rdump();
125 5f1cf8e6 2004-05-16 devnull void nestrange::killkids()
127 5f1cf8e6 2004-05-16 devnull subrange = new stream;
130 5f1cf8e6 2004-05-16 devnull int nestrange::print(int curv, int col)
132 5f1cf8e6 2004-05-16 devnull int ocurv = curv;
133 5f1cf8e6 2004-05-16 devnull first->slugout(col);
134 5f1cf8e6 2004-05-16 devnull for (stream s = *subrange; s.more(); s.advance())
135 5f1cf8e6 2004-05-16 devnull curv = s.current()->print(curv, col);
136 5f1cf8e6 2004-05-16 devnull return ocurv + height();
139 5f1cf8e6 2004-05-16 devnull #define macroclone(rangetype) range *rangetype::clone() {\
140 5f1cf8e6 2004-05-16 devnull rangetype *t = new rangetype;\
141 5f1cf8e6 2004-05-16 devnull *t = *this;\
142 5f1cf8e6 2004-05-16 devnull return t; }
144 5f1cf8e6 2004-05-16 devnull macroclone(usrange);
145 5f1cf8e6 2004-05-16 devnull macroclone(ufrange);
146 5f1cf8e6 2004-05-16 devnull macroclone(bfrange);
148 5f1cf8e6 2004-05-16 devnull #undef macroclone
150 5f1cf8e6 2004-05-16 devnull #define macropickgoal(rangetype) void rangetype::pickgoal(int acv, double scale) {\
151 5f1cf8e6 2004-05-16 devnull if (scale > 1) {\
152 5f1cf8e6 2004-05-16 devnull goalV = (int)(scale*goalV);\
153 5f1cf8e6 2004-05-16 devnull goal2 = (int)(scale*goal2);\
155 5f1cf8e6 2004-05-16 devnull if (abs(acv - goalV) > abs(acv-goal2))\
156 5f1cf8e6 2004-05-16 devnull goalV = goal2; }
158 5f1cf8e6 2004-05-16 devnull macropickgoal(ufrange)
159 5f1cf8e6 2004-05-16 devnull macropickgoal(bfrange)
161 5f1cf8e6 2004-05-16 devnull #undef macropickgoal
163 5f1cf8e6 2004-05-16 devnull range *generator::next()
165 5f1cf8e6 2004-05-16 devnull range *r;
166 5f1cf8e6 2004-05-16 devnull if (child) {
167 5f1cf8e6 2004-05-16 devnull if ((r = child->next()) != 0)
168 5f1cf8e6 2004-05-16 devnull return r;
169 5f1cf8e6 2004-05-16 devnull delete child;
170 5f1cf8e6 2004-05-16 devnull child = 0;
172 5f1cf8e6 2004-05-16 devnull if (!s.more())
173 5f1cf8e6 2004-05-16 devnull return 0;
174 5f1cf8e6 2004-05-16 devnull r = s.current();
175 5f1cf8e6 2004-05-16 devnull if (r->isnested())
176 5f1cf8e6 2004-05-16 devnull child = new generator(r->children());
177 5f1cf8e6 2004-05-16 devnull s.advance();
178 5f1cf8e6 2004-05-16 devnull return r;
181 5f1cf8e6 2004-05-16 devnull range *queue::enqueue(range *r)
183 5f1cf8e6 2004-05-16 devnull if (dbg & 8)
184 5f1cf8e6 2004-05-16 devnull printf("#entering queue::enqueue()\n");
185 5f1cf8e6 2004-05-16 devnull check("queue::enqueue");
186 5f1cf8e6 2004-05-16 devnull if (!last || last->rp->serialno() < r->serialno()) // common case
187 5f1cf8e6 2004-05-16 devnull return append(r);
188 5f1cf8e6 2004-05-16 devnull if (dbg & 8)
189 5f1cf8e6 2004-05-16 devnull printf("#queue::enqueue() pushing back\n");
190 5f1cf8e6 2004-05-16 devnull newguy = new strblk;
191 5f1cf8e6 2004-05-16 devnull newguy->rp = r;
192 5f1cf8e6 2004-05-16 devnull if (r->serialno() < first->rp->serialno()) {
193 5f1cf8e6 2004-05-16 devnull newguy->next = first;
194 5f1cf8e6 2004-05-16 devnull curr = first = newguy;
195 5f1cf8e6 2004-05-16 devnull return newguy->rp;
197 5f1cf8e6 2004-05-16 devnull if (dbg & 8)
198 5f1cf8e6 2004-05-16 devnull printf("#queue::enqueue() searching down queue\n");
199 5f1cf8e6 2004-05-16 devnull for (curr = first;
200 5f1cf8e6 2004-05-16 devnull next() && next()->serialno() < r->serialno();
201 5f1cf8e6 2004-05-16 devnull curr = curr->next)
203 5f1cf8e6 2004-05-16 devnull newguy->next = curr->next;
204 5f1cf8e6 2004-05-16 devnull curr->next = newguy;
205 5f1cf8e6 2004-05-16 devnull curr = first; // restore important queue condition
206 5f1cf8e6 2004-05-16 devnull return newguy->rp;
209 5f1cf8e6 2004-05-16 devnull range *queue::dequeue()
211 5f1cf8e6 2004-05-16 devnull if (dbg & 8)
212 5f1cf8e6 2004-05-16 devnull printf("#entering queue::dequeue()\n");
213 5f1cf8e6 2004-05-16 devnull check("queue::dequeue");
214 5f1cf8e6 2004-05-16 devnull curr = first->next;
215 5f1cf8e6 2004-05-16 devnull range *retval = first->rp;
216 5f1cf8e6 2004-05-16 devnull delete first;
217 5f1cf8e6 2004-05-16 devnull first = curr;
218 5f1cf8e6 2004-05-16 devnull if (!curr)
219 5f1cf8e6 2004-05-16 devnull last = 0;
220 5f1cf8e6 2004-05-16 devnull return retval;
223 5f1cf8e6 2004-05-16 devnull // ================================================================================
225 5f1cf8e6 2004-05-16 devnull // functions that munge the troff output stored in slugs[]
227 5f1cf8e6 2004-05-16 devnull // ================================================================================
229 5f1cf8e6 2004-05-16 devnull static void doprefix(FILE *fp) // copy 1st "x" commands to output
233 5f1cf8e6 2004-05-16 devnull while ((c = getc(fp)) != EOF) {
234 5f1cf8e6 2004-05-16 devnull if (c != 'x') {
235 5f1cf8e6 2004-05-16 devnull ungetc(c, fp);
238 5f1cf8e6 2004-05-16 devnull putchar(c);
240 5f1cf8e6 2004-05-16 devnull putchar(c = getc(fp));
241 5f1cf8e6 2004-05-16 devnull } while (c != '\n');
242 5f1cf8e6 2004-05-16 devnull linenum++;
244 5f1cf8e6 2004-05-16 devnull // printf("x font 1 R\n"); // horrible kludge: ensure a font for first f1 command
247 5f1cf8e6 2004-05-16 devnull #define DELTASLUGS 15000
249 5f1cf8e6 2004-05-16 devnull static slug *slugs = 0;
250 5f1cf8e6 2004-05-16 devnull static int nslugs = 0; // slugs has nslugs slots
251 5f1cf8e6 2004-05-16 devnull static slug *slugp = 0; // next free slug in slugs
253 5f1cf8e6 2004-05-16 devnull static void readslugs(FILE *fp)
255 5f1cf8e6 2004-05-16 devnull if ((slugs = (slug *) malloc((nslugs = DELTASLUGS)*sizeof(slug))) == NULL)
256 5f1cf8e6 2004-05-16 devnull ERROR "no room for %d-slug array\n", nslugs FATAL;
257 5f1cf8e6 2004-05-16 devnull slugp = slugs;
258 5f1cf8e6 2004-05-16 devnull for (slugp = slugs; ; slugp++) {
259 5f1cf8e6 2004-05-16 devnull if (slugp >= slugs+nslugs-2) {
260 5f1cf8e6 2004-05-16 devnull int where = slugp - slugs;
261 5f1cf8e6 2004-05-16 devnull if ((slugs = (slug *) realloc((char *) slugs, (nslugs += DELTASLUGS)*sizeof(slug))) == NULL)
262 5f1cf8e6 2004-05-16 devnull ERROR "no room for %d slugs\n", nslugs FATAL;
263 5f1cf8e6 2004-05-16 devnull ERROR "now slug array can hold %d slugs\n", nslugs WARNING;
264 5f1cf8e6 2004-05-16 devnull slugp = slugs + where;
266 5f1cf8e6 2004-05-16 devnull *slugp = getslug(fp);
267 5f1cf8e6 2004-05-16 devnull if (slugp->type == EOF)
270 5f1cf8e6 2004-05-16 devnull *++slugp = eofslug();
271 5f1cf8e6 2004-05-16 devnull printf("# %d slugs\n", slugp-slugs);
274 5f1cf8e6 2004-05-16 devnull static slug *findend(slug *sp)
276 5f1cf8e6 2004-05-16 devnull slug *p;
277 5f1cf8e6 2004-05-16 devnull for (p = sp; p->type == sp->type; p++) // skip runs
278 5f1cf8e6 2004-05-16 devnull ; // espec UF UF UF
279 5f1cf8e6 2004-05-16 devnull for ( ; p < slugp; p++)
280 5f1cf8e6 2004-05-16 devnull switch (p->type) {
281 5f1cf8e6 2004-05-16 devnull case US:
282 5f1cf8e6 2004-05-16 devnull case UF:
283 5f1cf8e6 2004-05-16 devnull case BF:
284 5f1cf8e6 2004-05-16 devnull case PT:
285 5f1cf8e6 2004-05-16 devnull case BT:
286 5f1cf8e6 2004-05-16 devnull p = findend(p);
288 5f1cf8e6 2004-05-16 devnull case END:
289 5f1cf8e6 2004-05-16 devnull return p;
291 5f1cf8e6 2004-05-16 devnull ERROR "walked past EOF in findend looking for %d (%s), line %d\n",
292 5f1cf8e6 2004-05-16 devnull sp->type, sp->typename(), sp->lineno() FATAL;
293 5f1cf8e6 2004-05-16 devnull return sp;
296 5f1cf8e6 2004-05-16 devnull static int markp(int i, int n, int parm)
297 5f1cf8e6 2004-05-16 devnull { // should VBOX i of n be marked to brevent breaking after it?
298 5f1cf8e6 2004-05-16 devnull if (i >= n-1)
299 5f1cf8e6 2004-05-16 devnull return 0;
300 5f1cf8e6 2004-05-16 devnull return i <= parm-2 || i >= n-parm;
303 5f1cf8e6 2004-05-16 devnull static void markbreak(slug *p)
305 5f1cf8e6 2004-05-16 devnull // Mark impermissible breakpoints in BS's.
306 5f1cf8e6 2004-05-16 devnull // The parm field of a VBOX is >0 if we shouldn't break after it.
307 75347226 2004-05-17 devnull int parm = 0; // how many lines must stay on page
308 5f1cf8e6 2004-05-16 devnull int goahead = 1; // true until we see the next BS
309 5f1cf8e6 2004-05-16 devnull int nowmark = 0; // true when we should be marking
310 5f1cf8e6 2004-05-16 devnull int n = 0;
311 5f1cf8e6 2004-05-16 devnull while (p->type == BS)
312 5f1cf8e6 2004-05-16 devnull parm = p++->parm; // latest BS parm applies
313 5f1cf8e6 2004-05-16 devnull slug *op = p;
314 5f1cf8e6 2004-05-16 devnull while (goahead) {
315 5f1cf8e6 2004-05-16 devnull switch (p->type) {
316 5f1cf8e6 2004-05-16 devnull case VBOX: // count VBOXes so second pass knows
317 5f1cf8e6 2004-05-16 devnull if (p->dv > 0) // knows how far to end of BS
320 5f1cf8e6 2004-05-16 devnull case US: // mark around EQ/EN, etc.
321 5f1cf8e6 2004-05-16 devnull nowmark = 1;
322 5f1cf8e6 2004-05-16 devnull p = findend(p);
324 5f1cf8e6 2004-05-16 devnull case UF: // but not around floats, PTs, and BTs
325 5f1cf8e6 2004-05-16 devnull case BF:
326 5f1cf8e6 2004-05-16 devnull case PT:
327 5f1cf8e6 2004-05-16 devnull case BT:
328 5f1cf8e6 2004-05-16 devnull p = findend(p);
330 5f1cf8e6 2004-05-16 devnull case SP: // naked SP: probable macro botch
331 5f1cf8e6 2004-05-16 devnull nowmark = 1; // mark around it anyhow
333 5f1cf8e6 2004-05-16 devnull case BS: // beginning of next paragraph
334 5f1cf8e6 2004-05-16 devnull case END: // probable macro botch
335 5f1cf8e6 2004-05-16 devnull case EOF:
336 5f1cf8e6 2004-05-16 devnull goahead = 0; // stop work after marking
337 5f1cf8e6 2004-05-16 devnull nowmark = 1;
338 5f1cf8e6 2004-05-16 devnull default:
342 5f1cf8e6 2004-05-16 devnull if (nowmark) {
343 5f1cf8e6 2004-05-16 devnull int i = 0; // VBOX counter for second pass
344 5f1cf8e6 2004-05-16 devnull while (op < p) {
345 5f1cf8e6 2004-05-16 devnull switch (op->type) {
346 5f1cf8e6 2004-05-16 devnull case VBOX:
347 5f1cf8e6 2004-05-16 devnull if (op->dv > 0)
348 5f1cf8e6 2004-05-16 devnull op->parm = markp(i, n, parm);
351 5f1cf8e6 2004-05-16 devnull case US: // caused second pass to begin
352 5f1cf8e6 2004-05-16 devnull case SP:
353 5f1cf8e6 2004-05-16 devnull case BS:
354 5f1cf8e6 2004-05-16 devnull case END:
355 5f1cf8e6 2004-05-16 devnull case EOF:
358 5f1cf8e6 2004-05-16 devnull case UF: // skip on this pass too
359 5f1cf8e6 2004-05-16 devnull case BF:
360 5f1cf8e6 2004-05-16 devnull case PT:
361 5f1cf8e6 2004-05-16 devnull case BT:
362 5f1cf8e6 2004-05-16 devnull op = findend(op);
364 5f1cf8e6 2004-05-16 devnull default:
369 5f1cf8e6 2004-05-16 devnull if (i != n)
370 5f1cf8e6 2004-05-16 devnull ERROR "markbreak failed : i %d n %d\n",
371 5f1cf8e6 2004-05-16 devnull i, n WARNING;
373 5f1cf8e6 2004-05-16 devnull nowmark = n = 0;
378 5f1cf8e6 2004-05-16 devnull static void fixslugs() // adjust bases and dv's, set parameters, etc.
380 5f1cf8e6 2004-05-16 devnull slug *p, *prevV = 0;
381 5f1cf8e6 2004-05-16 devnull for (p = slugs; p < slugp; p++) {
382 5f1cf8e6 2004-05-16 devnull if (p->type == VBOX) {
383 5f1cf8e6 2004-05-16 devnull prevV = p;
384 5f1cf8e6 2004-05-16 devnull continue;
386 5f1cf8e6 2004-05-16 devnull if (p->base != 0) {
387 5f1cf8e6 2004-05-16 devnull ERROR "%s slug (type %d) has base = %d, line %d\n",
388 5f1cf8e6 2004-05-16 devnull p->typename(), p->type, p->base, p->lineno() WARNING;
390 5f1cf8e6 2004-05-16 devnull if ((p->type == SP) || (p->type == NE))
391 5f1cf8e6 2004-05-16 devnull continue;
392 5f1cf8e6 2004-05-16 devnull if (p->type == PAGE)
393 5f1cf8e6 2004-05-16 devnull prevV = 0;
394 5f1cf8e6 2004-05-16 devnull if (p->dv != 0)
395 5f1cf8e6 2004-05-16 devnull if (prevV) {
396 5f1cf8e6 2004-05-16 devnull prevV->base = max(prevV->base, p->dv);
397 5f1cf8e6 2004-05-16 devnull p->dv = 0;
398 5f1cf8e6 2004-05-16 devnull } else {
399 5f1cf8e6 2004-05-16 devnull ERROR "%s slug (type %d) has dv = %d, line %d\n",
400 5f1cf8e6 2004-05-16 devnull p->typename(), p->type, p->dv, p->lineno() WARNING;
403 5f1cf8e6 2004-05-16 devnull prevV = 0;
404 5f1cf8e6 2004-05-16 devnull int firstNP = 0, firstFO = 0, firstPL = 0;
405 5f1cf8e6 2004-05-16 devnull for (p = slugs; p < slugp; p++) {
406 5f1cf8e6 2004-05-16 devnull switch (p->type) {
407 5f1cf8e6 2004-05-16 devnull // adjust the dv in a sequence of VBOXes
408 5f1cf8e6 2004-05-16 devnull // by subtracting from each the base of the preceding VBOX
409 5f1cf8e6 2004-05-16 devnull case VBOX:
410 5f1cf8e6 2004-05-16 devnull if (prevV)
411 5f1cf8e6 2004-05-16 devnull p->dv -= prevV->base;
412 5f1cf8e6 2004-05-16 devnull prevV = p;
414 5f1cf8e6 2004-05-16 devnull case SP:
415 5f1cf8e6 2004-05-16 devnull p->dv = max(p->dv, 0);
417 5f1cf8e6 2004-05-16 devnull case PAGE:
418 5f1cf8e6 2004-05-16 devnull p->neutralize();
419 5f1cf8e6 2004-05-16 devnull prevV = 0;
421 5f1cf8e6 2004-05-16 devnull // record only first "declarations" of Page Top and bottom (FO);
422 5f1cf8e6 2004-05-16 devnull case PARM:
423 5f1cf8e6 2004-05-16 devnull switch (p->parm) {
424 5f1cf8e6 2004-05-16 devnull case NP:
425 5f1cf8e6 2004-05-16 devnull if (firstNP++ == 0)
426 5f1cf8e6 2004-05-16 devnull pagetop = p->parm2;
427 5f1cf8e6 2004-05-16 devnull p->neutralize();
429 5f1cf8e6 2004-05-16 devnull case FO:
430 5f1cf8e6 2004-05-16 devnull if (firstFO++ == 0)
431 5f1cf8e6 2004-05-16 devnull pagebot = p->parm2;
432 5f1cf8e6 2004-05-16 devnull p->neutralize();
434 5f1cf8e6 2004-05-16 devnull case PL:
435 5f1cf8e6 2004-05-16 devnull if (firstPL++ == 0)
436 5f1cf8e6 2004-05-16 devnull physbot = p->parm2;
437 5f1cf8e6 2004-05-16 devnull p->neutralize();
441 5f1cf8e6 2004-05-16 devnull // things that begin groups; not US, which should nest properly
442 5f1cf8e6 2004-05-16 devnull case UF:
443 5f1cf8e6 2004-05-16 devnull case BF:
444 5f1cf8e6 2004-05-16 devnull while ((p+1)->type == p->type) {
445 5f1cf8e6 2004-05-16 devnull // join adjacent identical
446 5f1cf8e6 2004-05-16 devnull (p+1)->parm2 = p->parm; // parm is latest
447 5f1cf8e6 2004-05-16 devnull // parm2 is previous
448 5f1cf8e6 2004-05-16 devnull p->neutralize(); // so it's not seen later
452 5f1cf8e6 2004-05-16 devnull // none of the above
453 5f1cf8e6 2004-05-16 devnull case US:
454 5f1cf8e6 2004-05-16 devnull case PT:
455 5f1cf8e6 2004-05-16 devnull case BT:
456 5f1cf8e6 2004-05-16 devnull case BS:
457 5f1cf8e6 2004-05-16 devnull case END:
458 5f1cf8e6 2004-05-16 devnull case TM:
459 5f1cf8e6 2004-05-16 devnull case COORD:
460 5f1cf8e6 2004-05-16 devnull case NE:
461 5f1cf8e6 2004-05-16 devnull case MC:
462 5f1cf8e6 2004-05-16 devnull case CMD:
463 5f1cf8e6 2004-05-16 devnull case EOF:
465 5f1cf8e6 2004-05-16 devnull default:
466 5f1cf8e6 2004-05-16 devnull ERROR "Unknown slug type %d in fixslugs, line %d\n",
467 5f1cf8e6 2004-05-16 devnull p->type, p->lineno() WARNING;
471 5f1cf8e6 2004-05-16 devnull int pagesize = pagebot - pagetop;
472 5f1cf8e6 2004-05-16 devnull if (pagesize == 0)
473 5f1cf8e6 2004-05-16 devnull ERROR "Page dimensions not declared\n" FATAL;
474 5f1cf8e6 2004-05-16 devnull if (physbot == 0)
475 5f1cf8e6 2004-05-16 devnull physbot = pagebot + pagetop;
476 5f1cf8e6 2004-05-16 devnull printf("# page top %d bot %d size %d physbot %d\n",
477 5f1cf8e6 2004-05-16 devnull pagetop, pagebot, pagesize, physbot);
478 5f1cf8e6 2004-05-16 devnull for (p = slugs; p < slugp; p++) {
479 5f1cf8e6 2004-05-16 devnull switch (p->type) {
480 5f1cf8e6 2004-05-16 devnull // normalize float parameters
481 5f1cf8e6 2004-05-16 devnull case BF:
482 5f1cf8e6 2004-05-16 devnull case UF:
483 5f1cf8e6 2004-05-16 devnull // primary goal
484 5f1cf8e6 2004-05-16 devnull p->parm = max(min(p->parm-pagetop, pagesize), 0);
485 5f1cf8e6 2004-05-16 devnull // secondary goal
486 5f1cf8e6 2004-05-16 devnull p->parm2 = max(min(p->parm2-pagetop, pagesize), 0);
488 5f1cf8e6 2004-05-16 devnull // normalize need parameters
489 5f1cf8e6 2004-05-16 devnull case NE:
490 5f1cf8e6 2004-05-16 devnull p->dv = max( min(p->dv, pagesize), 0);
492 5f1cf8e6 2004-05-16 devnull // mark permissible breaks
493 5f1cf8e6 2004-05-16 devnull case BS:
494 5f1cf8e6 2004-05-16 devnull markbreak(p);
497 5f1cf8e6 2004-05-16 devnull if (dbg & 1)
498 5f1cf8e6 2004-05-16 devnull p->dump();
502 5f1cf8e6 2004-05-16 devnull void checkout()
504 5f1cf8e6 2004-05-16 devnull for (slug *p = slugs; p < slugp; p++)
505 5f1cf8e6 2004-05-16 devnull switch (p->type) {
506 5f1cf8e6 2004-05-16 devnull case PT:
507 5f1cf8e6 2004-05-16 devnull case BT:
508 5f1cf8e6 2004-05-16 devnull p = findend(p);
510 5f1cf8e6 2004-05-16 devnull case SP:
511 5f1cf8e6 2004-05-16 devnull case VBOX:
512 5f1cf8e6 2004-05-16 devnull if (p->seen != 1)
513 5f1cf8e6 2004-05-16 devnull ERROR "%s slug %d seen %d times\n",
514 5f1cf8e6 2004-05-16 devnull p->typename(), p->serialno(),
515 5f1cf8e6 2004-05-16 devnull p->seen WARNING;
520 5f1cf8e6 2004-05-16 devnull eofrange *lastrange;
521 5f1cf8e6 2004-05-16 devnull stream ptlist, btlist;
523 5f1cf8e6 2004-05-16 devnull static slug *makeranges(slug *p, stream *s, int level)
525 5f1cf8e6 2004-05-16 devnull stream *t;
527 5f1cf8e6 2004-05-16 devnull for ( ; p < slugp; p++)
528 5f1cf8e6 2004-05-16 devnull switch (p->type) {
529 5f1cf8e6 2004-05-16 devnull case VBOX:
530 5f1cf8e6 2004-05-16 devnull s->append(new vboxrange(p));
532 5f1cf8e6 2004-05-16 devnull case SP:
533 5f1cf8e6 2004-05-16 devnull s->append(new sprange(p));
535 5f1cf8e6 2004-05-16 devnull case BS:
536 5f1cf8e6 2004-05-16 devnull s->append(new bsrange(p));
538 5f1cf8e6 2004-05-16 devnull case US:
539 5f1cf8e6 2004-05-16 devnull s->append(new usrange(p, t = new stream));
540 5f1cf8e6 2004-05-16 devnull p = makeranges(p+1, t, level+1);
542 5f1cf8e6 2004-05-16 devnull case BF:
543 5f1cf8e6 2004-05-16 devnull s->append(new bfrange(p, t = new stream));
544 5f1cf8e6 2004-05-16 devnull p = makeranges(p+1, t, level+1);
546 5f1cf8e6 2004-05-16 devnull case UF:
547 5f1cf8e6 2004-05-16 devnull s->append(new ufrange(p, t = new stream));
548 5f1cf8e6 2004-05-16 devnull p = makeranges(p+1, t, level+1);
550 5f1cf8e6 2004-05-16 devnull case PT:
551 5f1cf8e6 2004-05-16 devnull ptlist.append(new ptrange(p, t = new stream));
552 5f1cf8e6 2004-05-16 devnull p = makeranges(p+1, t, level+1);
554 5f1cf8e6 2004-05-16 devnull case BT:
555 5f1cf8e6 2004-05-16 devnull btlist.append(new btrange(p, t = new stream));
556 5f1cf8e6 2004-05-16 devnull p = makeranges(p+1, t, level+1);
558 5f1cf8e6 2004-05-16 devnull case END:
559 5f1cf8e6 2004-05-16 devnull s->append(new endrange(p));
560 5f1cf8e6 2004-05-16 devnull return p;
561 5f1cf8e6 2004-05-16 devnull case TM:
562 5f1cf8e6 2004-05-16 devnull s->append(new tmrange(p));
564 5f1cf8e6 2004-05-16 devnull case COORD:
565 5f1cf8e6 2004-05-16 devnull s->append(new coordrange(p));
567 5f1cf8e6 2004-05-16 devnull case NE:
568 5f1cf8e6 2004-05-16 devnull if (level) {
569 5f1cf8e6 2004-05-16 devnull ERROR "Nested NE commands are ignored, line %d\n",
570 5f1cf8e6 2004-05-16 devnull p->lineno() WARNING;
571 5f1cf8e6 2004-05-16 devnull p->dv = 0;
573 5f1cf8e6 2004-05-16 devnull s->append(new nerange(p));
575 5f1cf8e6 2004-05-16 devnull case MC:
576 5f1cf8e6 2004-05-16 devnull s->append(new mcrange(p));
578 5f1cf8e6 2004-05-16 devnull case CMD:
579 5f1cf8e6 2004-05-16 devnull if (level)
580 5f1cf8e6 2004-05-16 devnull ERROR "Nested command ignored, line %d\n",
581 5f1cf8e6 2004-05-16 devnull p->lineno() WARNING;
582 5f1cf8e6 2004-05-16 devnull s->append(new cmdrange(p));
584 5f1cf8e6 2004-05-16 devnull case PARM:
585 5f1cf8e6 2004-05-16 devnull if (level)
586 5f1cf8e6 2004-05-16 devnull ERROR "Nested parameter ignored, line %d\n",
587 5f1cf8e6 2004-05-16 devnull p->lineno() WARNING;
588 5f1cf8e6 2004-05-16 devnull s->append(new parmrange(p));
590 5f1cf8e6 2004-05-16 devnull case EOF:
591 5f1cf8e6 2004-05-16 devnull lastrange = new eofrange(p);
592 5f1cf8e6 2004-05-16 devnull return 0;
594 5f1cf8e6 2004-05-16 devnull return p;
597 5f1cf8e6 2004-05-16 devnull static queue text; // unexamined input ranges; the real data
599 5f1cf8e6 2004-05-16 devnull void startup(FILE *fp)
601 5f1cf8e6 2004-05-16 devnull doprefix(fp); // peel off 'x' commands
602 5f1cf8e6 2004-05-16 devnull readslugs(fp); // read everything into slugs[]
603 5f1cf8e6 2004-05-16 devnull fixslugs(); // measure parameters and clean up
604 5f1cf8e6 2004-05-16 devnull makeranges(slugs, &text, 0); // add range superstructure
605 5f1cf8e6 2004-05-16 devnull measure(&text); // heights of nested things
606 5f1cf8e6 2004-05-16 devnull rawmeasure(&text);
607 5f1cf8e6 2004-05-16 devnull while (text.more()) {
608 5f1cf8e6 2004-05-16 devnull range *r = text.dequeue();
609 5f1cf8e6 2004-05-16 devnull if (dbg & 2)
610 5f1cf8e6 2004-05-16 devnull r->dump();
611 5f1cf8e6 2004-05-16 devnull r->enqueue();