URI:
       tpage.h - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tpage.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 **);