page.h (4303B)
1 extern queue squeue; // the three queues on which ranges reside 2 extern queue bfqueue; 3 extern queue ufqueue; 4 5 extern double minfull; 6 7 extern double coltol; 8 9 int anymore(); 10 11 // The following is used in some calls to range::enqueue(int = 0). 12 #define ANDBLOCK 1 13 14 class page; 15 16 enum { DRAFT = 0, FINAL = 1 }; 17 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 }; 29 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 }; 73 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 }; 84 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 }; 117 118 // functions in page.c 119 int main(int, char **);