119 lines
4.2 KiB
C++
119 lines
4.2 KiB
C++
extern queue squeue; // the three queues on which ranges reside
|
|
extern queue bfqueue;
|
|
extern queue ufqueue;
|
|
|
|
extern double minfull;
|
|
|
|
extern double coltol;
|
|
|
|
int anymore();
|
|
|
|
// The following is used in some calls to range::enqueue(int = 0).
|
|
#define ANDBLOCK 1
|
|
|
|
class page;
|
|
|
|
enum { DRAFT = 0, FINAL = 1 };
|
|
|
|
// The mergestream currpage->stage serves as a staging area for page makeup:
|
|
// when primed, it contains a minimal acceptable chunk of input ranges.
|
|
// The page must either take or leave everything that's on stage.
|
|
class mergestream : public queue {
|
|
page *currpage; // current page that's accepting stuff
|
|
public:
|
|
mergestream(page *cp) { currpage = cp; unblock(); }
|
|
void unblock();
|
|
int prime(); // stage next legal chunk
|
|
void pend(); // process pending chunk on stage
|
|
};
|
|
|
|
// The multicol currpage->twocol is the two-column piece of the page to which
|
|
// two-column ranges are currently being added.
|
|
// The page sets htavail to indicate how tall it is allowed to become.
|
|
// All ranges on definite must be placed when the multicol is printed.
|
|
// Each of these definite ranges also resides on one of column[0] and [1],
|
|
// which represent the current best guess about how to divide definite
|
|
// between the two columns.
|
|
class multicol : public range {
|
|
page *currpage; // current page that's accepting stuff
|
|
stream definite; // definitely on page
|
|
stream scratch; // for trial compositions
|
|
stream column[2]; // left (0) and right (1) columns
|
|
int leftblocked; // OK to add to left column?
|
|
int htavail; // max possible ht, set by page::tryout()
|
|
int prevhtavail; // max 2-colht last time we added something
|
|
friend class page;
|
|
public:
|
|
multicol(page *cp) { currpage = cp;
|
|
leftblocked = 0;
|
|
htavail = 0;
|
|
prevhtavail = -1;
|
|
setgoal(NOGOAL); }
|
|
// the two-column piece behaves as part
|
|
// of the stream of single-column input.
|
|
int numcol() { return 1; }
|
|
int nonempty() { return definite.more(); }
|
|
void choosecol(range *, int);// add first arg to one or other column
|
|
void choosecol(stream*, int);// add *all ranges on first arg*
|
|
// to one or other column
|
|
// NOT the same as a mapcar of the
|
|
// preceding function over the ranges
|
|
// on the first argument!
|
|
void compose(int); // divide into two columns
|
|
void tryout(); // decide which column gets stage contents
|
|
void stretch(int); // justify both columns to given height
|
|
int print(int curv, int col);
|
|
int height(); // an upper bound on actual height
|
|
int rawht() { return max(column[0].rawht(), column[1].rawht()); }
|
|
void reheight(int *cv, int *mv)
|
|
{ *cv += height(); *mv = max(*mv, *cv); }
|
|
void dump();
|
|
int isvbox() { return nonempty(); } // during trimspace()
|
|
};
|
|
|
|
// These sentinel ranges are used to separate the ranges on twocol::definite
|
|
// into the chunks in which they came from the staging area.
|
|
// Thus, they preserve the results of the computation that was done to prime
|
|
// page::stage.
|
|
class sentrange : public range {
|
|
public:
|
|
sentrange() { }
|
|
int numcol() { return 2; }
|
|
int issentinel() { return 1; }
|
|
};
|
|
|
|
class page {
|
|
int pagesize; // allowed maximum height
|
|
int prevncol; // was last item tried 1- or 2-column?
|
|
int vsince; // how many vboxes from "current" BS
|
|
// (to avoid putting a single line on
|
|
// a page with a very large floatable)
|
|
stream definite; // definitely on page, in input order
|
|
stream scratch; // playground in which to alter page
|
|
void cmdproc(); // process any of several commands
|
|
void parmproc(); // process any of several parameters
|
|
void tryout(); // see whether current stage contents fit
|
|
void compose(int); // float and trim current page contents
|
|
void makescratch(int); // fill scratch area
|
|
void commit(); // accept the items on stage
|
|
void welsh(); // reject the items on stage
|
|
void adddef(range *r); // add to one of the definite queues
|
|
// (definite or twocol->definite)
|
|
public:
|
|
mergestream *stage;
|
|
friend class mergestream;
|
|
multicol *twocol;
|
|
friend class multicol;
|
|
page(int p) { pagesize = p;
|
|
prevncol = 1;
|
|
vsince = 0;
|
|
stage = new mergestream(this);
|
|
twocol = new multicol(this); }
|
|
~page() { definite.freeall(); scratch.freeall(); }
|
|
void fill();
|
|
int blank() { return !definite.more() && !twocol->definite.more();}
|
|
void print();
|
|
};
|
|
|
|
// functions in page.c
|
|
int main(int, char **);
|