Blob


1 extern queue squeue; // the three queues on which ranges reside
2 extern queue bfqueue;
3 extern queue ufqueue;
5 extern double minfull;
7 extern double coltol;
9 int anymore();
11 // The following is used in some calls to range::enqueue(int = 0).
12 #define ANDBLOCK 1
14 class page;
16 enum { DRAFT = 0, FINAL = 1 };
18 // The mergestream currpage->stage serves as a staging area for page makeup:
19 // when primed, it contains a minimal acceptable chunk of input ranges.
20 // The page must either take or leave everything that's on stage.
21 class mergestream : public queue {
22 page *currpage; // current page that's accepting stuff
23 public:
24 mergestream(page *cp) { currpage = cp; unblock(); }
25 void unblock();
26 int prime(); // stage next legal chunk
27 void pend(); // process pending chunk on stage
28 };
30 // The multicol currpage->twocol is the two-column piece of the page to which
31 // two-column ranges are currently being added.
32 // The page sets htavail to indicate how tall it is allowed to become.
33 // All ranges on definite must be placed when the multicol is printed.
34 // Each of these definite ranges also resides on one of column[0] and [1],
35 // which represent the current best guess about how to divide definite
36 // between the two columns.
37 class multicol : public range {
38 page *currpage; // current page that's accepting stuff
39 stream definite; // definitely on page
40 stream scratch; // for trial compositions
41 stream column[2]; // left (0) and right (1) columns
42 int leftblocked; // OK to add to left column?
43 int htavail; // max possible ht, set by page::tryout()
44 int prevhtavail; // max 2-colht last time we added something
45 friend class page;
46 public:
47 multicol(page *cp) { currpage = cp;
48 leftblocked = 0;
49 htavail = 0;
50 prevhtavail = -1;
51 setgoal(NOGOAL); }
52 // the two-column piece behaves as part
53 // of the stream of single-column input.
54 int numcol() { return 1; }
55 int nonempty() { return definite.more(); }
56 void choosecol(range *, int);// add first arg to one or other column
57 void choosecol(stream*, int);// add *all ranges on first arg*
58 // to one or other column
59 // NOT the same as a mapcar of the
60 // preceding function over the ranges
61 // on the first argument!
62 void compose(int); // divide into two columns
63 void tryout(); // decide which column gets stage contents
64 void stretch(int); // justify both columns to given height
65 int print(int curv, int col);
66 int height(); // an upper bound on actual height
67 int rawht() { return max(column[0].rawht(), column[1].rawht()); }
68 void reheight(int *cv, int *mv)
69 { *cv += height(); *mv = max(*mv, *cv); }
70 void dump();
71 int isvbox() { return nonempty(); } // during trimspace()
72 };
74 // These sentinel ranges are used to separate the ranges on twocol::definite
75 // into the chunks in which they came from the staging area.
76 // Thus, they preserve the results of the computation that was done to prime
77 // page::stage.
78 class sentrange : public range {
79 public:
80 sentrange() { }
81 int numcol() { return 2; }
82 int issentinel() { return 1; }
83 };
85 class page {
86 int pagesize; // allowed maximum height
87 int prevncol; // was last item tried 1- or 2-column?
88 int vsince; // how many vboxes from "current" BS
89 // (to avoid putting a single line on
90 // a page with a very large floatable)
91 stream definite; // definitely on page, in input order
92 stream scratch; // playground in which to alter page
93 void cmdproc(); // process any of several commands
94 void parmproc(); // process any of several parameters
95 void tryout(); // see whether current stage contents fit
96 void compose(int); // float and trim current page contents
97 void makescratch(int); // fill scratch area
98 void commit(); // accept the items on stage
99 void welsh(); // reject the items on stage
100 void adddef(range *r); // add to one of the definite queues
101 // (definite or twocol->definite)
102 public:
103 mergestream *stage;
104 friend class mergestream;
105 multicol *twocol;
106 friend class multicol;
107 page(int p) { pagesize = p;
108 prevncol = 1;
109 vsince = 0;
110 stage = new mergestream(this);
111 twocol = new multicol(this); }
112 ~page() { definite.freeall(); scratch.freeall(); }
113 void fill();
114 int blank() { return !definite.more() && !twocol->definite.more();}
115 void print();
116 };
118 // functions in page.c
119 int main(int, char **);