URI:
       trange.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
       ---
       trange.h (10274B)
       ---
            1 const int        NOGOAL = -1;
            2 
            3 class stream;
            4 
            5 enum primeflush { NO, YES, EXPECTED, UNEXPECTED };        // mergestream::prime()
            6 
            7 // Ranges do two things.  They interpose a layer between slugs and the rest
            8 // of the program; this is important because of the grossness of the slug
            9 // data structure (made necessary by its origins in troff output).  Ranges also
           10 // group together other ranges into meaningful chunks like unbreakable stream
           11 // objects, floatable objects, and page headers and footers.
           12 // Member function height() returns a range's height as of the latest composition.
           13 // Member function rawht() returns the range's original height in the input.
           14 class range {
           15   protected:
           16         slug        *first;                // earliest slug in range
           17         int        accumV;                // accumulated V to this point
           18   public:
           19         range()                { first = 0; accumV = 0; }
           20         range(slug *p)        { first = p; accumV = 0; }
           21         virtual ~range() { }
           22         char        *headstr()                {
           23                 return first ? first->headstr() : (char*)""; }
           24         char        *typename()                { return first->typename(); }
           25         int        serialno()                { return first->serialno(); }
           26         int        lineno()                { return first->lineno(); }
           27         virtual void        dump()                { first->dump(); }
           28         virtual void        rdump()                { dump(); }
           29         virtual int        print(int cv, int col)        {
           30                 first->slugout(col); return cv; }
           31         virtual int        floatable()        { return 0; }
           32         virtual int        brkafter()        { return 1; }
           33         virtual int        isnested()        { return 0; }
           34         virtual int        issp()                { return 0; }
           35         virtual int        isvbox()        { return 0; }
           36         virtual int        isneed()        { return 0; }
           37         virtual int        iscmd()                { return 0; }
           38         virtual int        cmdtype()        { return -1; }
           39         virtual int        isparm()        { return 0; }
           40         virtual int        parmtype()        { return -1; }
           41         virtual int        parm()                { return -1; }
           42         virtual int        breakable()        { return 0; }
           43         virtual int        forceflush()        { return UNEXPECTED; }
           44         virtual int        pn()                { return 0; }
           45         virtual stream        *children()        { return 0; }        // see page::peeloff()
           46         virtual void        killkids()        { }
           47         virtual void        enqueue(int = 0);
           48         virtual int        height()        { return 0; }
           49         virtual int        rawht()                { return 0; }
           50         virtual int        needht()        { return 0; }
           51         virtual void        reheight(int *, int *)        { }
           52         virtual void        rerawht(int *, int *)        { }
           53         virtual void        setheight(int) { }
           54         virtual void        restore()        { }                // goals of floatables
           55         virtual int        goal()                { return NOGOAL; }
           56         int                accum()                { return accumV; }
           57         void                setaccum(int n)        { accumV = n; }
           58         virtual        void        setgoal(int)        { }
           59         virtual void        pickgoal(int, double)        { }
           60         virtual int        numcol()        { return first->numcol(); }
           61         virtual int        issentinel()        { return 0; }
           62         virtual range        *clone()        { return 0; }
           63         virtual int        breaking()        { return 0; }
           64         virtual void        setbreaking()        { }
           65 };
           66 
           67 class vboxrange : public range {
           68         int        dv;                // inherited from slug
           69         int        base;                // inherited from slug
           70         int        brk;                // 0 => ok to break after, 1 => no break
           71   public:
           72         vboxrange(slug *p) : range(p) { dv = p->dv; base = p->base; brk = p->parm; }
           73         void        dump() {
           74                 printf("#### VBOX brk? %d dv %d ht %d\n", brk, dv, dv+base); }
           75         int        print(int cv, int col) {
           76                 printf("V%d\n", cv += dv); first->slugout(col); return cv+base; }
           77         int        brkafter()                { return !brk; }
           78         int        isvbox()                { return 1; }
           79         int        forceflush()                { return NO; }
           80         int        height()                { return dv + base; }
           81         int        rawht()                        { return first->dv + first->base; }
           82         void        reheight(int *cv, int *mv) {
           83                 *cv += dv+base; *mv = max(*mv, *cv); }
           84         void        rerawht(int *cv, int *mv) {
           85                 *cv += rawht(); *mv = max(*mv, *cv); }
           86 };
           87 
           88 class sprange : public range {
           89         int dv;
           90   public:
           91         sprange(slug *p) : range(p) { dv = first->dv; }
           92         void        dump() {
           93                 printf("#### SP dv %d (originally %d)\n", dv, first->dv); }
           94         int        print(int cv, int col)        {
           95                 first->slugout(col); return cv + dv; }
           96         int        issp()                        { return 1; }
           97         int        forceflush()                { return YES; }
           98         int        height()                { return dv; }
           99         int        rawht()                        { return first->dv; }
          100         void        reheight(int *, int *);
          101         void        rerawht(int *, int *);
          102         void        setheight(int n)        { dv = n; }
          103 };
          104 
          105 class tmrange : public range {
          106   public:
          107         tmrange(slug *p) : range(p)        { }
          108         int        forceflush()                { return NO; }
          109         int        print(int cv, int col)        { first->slugout(col); return cv; }
          110 };
          111 
          112 class coordrange : public range {
          113   public:
          114         coordrange(slug *p) : range(p)        { }
          115         int        forceflush()                { return NO; }
          116         int        print(int cv, int col)
          117                 { first->slugout(col); printf(" Y %d\n", cv); return cv; }
          118 };
          119 
          120 class nerange : public range {
          121   public:
          122         nerange(slug *p) : range(p)        { }
          123         int        isneed()                { return 1; }
          124         int        forceflush()                { return YES; }
          125         int        needht()                { return first->dv; }
          126 };
          127 
          128 class mcrange : public range {
          129   public:
          130         mcrange(slug *p) : range(p)        { }
          131         int        forceflush()                { return YES; }
          132 };
          133 
          134 class cmdrange : public range {
          135   public:
          136         cmdrange(slug *p) : range(p)        { }
          137         int        iscmd()                        { return 1; }
          138         int        forceflush()                { return YES; }
          139         int        cmdtype()                { return first->parm; }
          140 };
          141 
          142 class parmrange : public range {
          143   public:
          144         parmrange(slug *p) : range(p)        { }
          145         int        isparm()                { return 1; }
          146         int        forceflush()                { return YES; }
          147         int        parmtype()                { return first->parm; }
          148         int        parm()                        { return first->parm2; }
          149 };
          150 
          151 class bsrange : public range {
          152   public:
          153         bsrange(slug *p) : range(p)        { }
          154         int        forceflush()                { return NO; }
          155         int        print(int cv, int col)        { first->slugout(col); return cv; }
          156 };
          157 
          158 class endrange : public range {
          159   public:
          160         endrange(slug *p) : range(p)        { }
          161         int        forceflush()                { return UNEXPECTED; }
          162 };
          163 
          164 class eofrange : public range {
          165   public:
          166         eofrange(slug *p) : range(p)        { }
          167         int        forceflush()                { return UNEXPECTED; }
          168 };
          169 
          170 extern eofrange *lastrange;        // the EOF block (trailer, etc.) goes here
          171 
          172 int measure(stream *);
          173 int rawmeasure(stream *);
          174 
          175 // A nestrange packages together a sequence of ranges, its subrange.
          176 // Other parts of the program reach in and alter the dimensions of
          177 // some of these ranges, so when the height of a range is requested
          178 // it is computed completely afresh.
          179 // (Note:  the alternative, of keeping around many copies of ranges
          180 // with different dimensions, was abandoned because of the difficulty
          181 // of ensuring that exactly one copy of each original range would be
          182 // output.)
          183 class nestrange : public range {
          184   protected:
          185         stream        *subrange;
          186         int isbreaking;
          187         int rawdv;
          188   public:
          189         nestrange() : range()        { subrange = 0; isbreaking = 0; rawdv = -1; }
          190         nestrange(slug *p, stream *s) : range(p)
          191                                 { subrange = s; isbreaking = 0; rawdv = -1; }
          192         void        rdump();
          193         virtual void restore();
          194         stream        *children()        { return subrange; }
          195         void        killkids();
          196         int        height()        { return measure(subrange); }
          197         int        rawht()                { if (rawdv < 0 || isbreaking) rawdv = rawmeasure(subrange);
          198                                         return rawdv; }
          199         void        reheight(int *cv, int *mv) {
          200                         *mv += measure(subrange); *cv = max(*mv, *cv); }
          201         void        rerawht(int *cv, int *mv) {
          202                         *mv += rawht(); *cv = max(*mv, *cv); }
          203         int        isnested()        { return 1; }
          204         int        forceflush()        { return EXPECTED; }
          205         int        print(int cv, int col);
          206         int        breaking()        { return isbreaking; }
          207         void        setbreaking()        { isbreaking++; }
          208 };
          209 
          210 class usrange : public nestrange {
          211   public:
          212         usrange()        { }
          213         usrange(slug *p, stream *s) : nestrange(p, s) {}
          214         void dump() { printf("#### US        dv %d\n", height()); }
          215         range        *clone();
          216 };
          217 
          218 class ufrange : public nestrange {
          219         int        goalV, goal2;
          220   public:
          221         ufrange()        { }
          222         ufrange(slug *p, stream *s) : nestrange(p, s) {
          223                 goalV = p->parm; goal2 = p->parm2; }
          224         void         dump() { printf("#### UF   dv %d goal %d goal2 %d\n",
          225                 height(), goalV, goal2); }
          226         int        floatable()        { return 1; }
          227         void        enqueue(int = 0);
          228         range        *clone();
          229         int        goal()                { return goalV; }
          230         void        setgoal(int n)        { goalV = goal2 = n; }
          231         void        pickgoal(int acv, double scale);
          232         void        restore()        { goalV = first->parm; goal2 = first->ht; }
          233 };
          234 
          235 class bfrange : public nestrange {
          236         int        goalV, goal2;
          237   public:
          238         bfrange()        { }
          239         bfrange(slug *p, stream *s) : nestrange(p, s) {
          240                 goalV = p->parm; goal2 = p->parm2; }
          241         void         dump() { printf("#### BF   dv %d goal %d goal2 %d\n",
          242                 height(), goalV, goal2); }
          243         int        floatable()        { return 1; }
          244         void        enqueue(int = 0);
          245         range        *clone();
          246         int        goal()                { return goalV; }
          247         void        setgoal(int n)        { goalV = goal2 = n; }
          248         void        pickgoal(int acv, double scale);
          249         void        restore()        { goalV = first->parm; goal2 = first->parm2; }
          250         int        breakable()        { return 1; }        // can be broken
          251 };
          252 
          253 class ptrange : public nestrange {
          254         int        pgno;
          255   public:
          256         int        pn()        { return pgno; }
          257         ptrange(slug *p, stream *s) : nestrange(p, s) { pgno = p->parm; }
          258         void         dump() { printf("#### PT   pgno %d dv %d\n", pgno, height()); }
          259 };
          260 
          261 class btrange : public nestrange {
          262         int        pgno;
          263   public:
          264         btrange(slug *p, stream *s) : nestrange(p, s) { pgno = p->parm; }
          265         void         dump() { printf("#### BT   pgno %d dv %d\n", pgno, height()); }
          266 };
          267 
          268 // A stream is a sequence of ranges; we use this data structure a lot
          269 // to traverse various sequences that crop up in page-making.
          270 class stream {
          271   protected:
          272 public:
          273         struct strblk {                // ranges are linked by these blocks
          274                 strblk        *next;
          275                 range        *rp;
          276         };
          277         strblk        *first;
          278         strblk        *last;
          279         strblk        *curr;
          280   public:
          281         stream()                { curr = last = first = 0; }
          282         stream(range *r)        { curr = last = first = new strblk;
          283                                         last->rp = r; last->next = 0; }
          284         void        freeall();        // note:  not a destructor
          285         void        dump();                // top level
          286         void        rdump();        // recursive
          287         int        restoreall();
          288         range        *current()        { return curr->rp; }
          289         range        *next()                { return curr && curr->next ? curr->next->rp : 0; }
          290         void        advance()        { curr = curr->next; }
          291         range        *append(range *r);
          292         void        split();
          293         int        more()                { return curr && curr->rp; }
          294         int        height();
          295         int        rawht();
          296 };
          297 
          298 // A generator iterates through all the ranges of a stream
          299 // (not just the root ranges of nestranges).
          300 class generator {
          301         stream        s;
          302         generator *child;
          303   public:
          304         generator()                { child = 0; }
          305         generator(stream *sp)        { s = *sp; child = 0; }
          306         range        *next();
          307 };
          308 
          309 extern stream        ptlist, btlist;                // page titles
          310 
          311 #undef INFINITY
          312 #define INFINITY 1000001
          313 
          314 // A queue is a distinguished kind of stream.
          315 // It keeps its contents in order by the serial numbers of the ranges.
          316 // A queue can be blocked from dequeuing something to indicate
          317 // that it's not worth considering the queue again on a given page.
          318 class queue : public stream {
          319         strblk        *newguy;
          320   protected:
          321         int        blocked;
          322         void        check(char *);
          323   public:
          324         queue() : blocked(0)        { }
          325         range        *enqueue(range *r);
          326         range        *dequeue();
          327         void        block()                { blocked = 1; }
          328         void        unblock()        { blocked = 0; }
          329         int        more()                { return !blocked && stream::more(); }
          330         int        empty()                { return !stream::more(); }
          331         int        serialno()        { return empty() ? INFINITY : current()->serialno(); }
          332 };
          333 
          334 // functions in range.c
          335 void checkout();
          336 void startup(FILE *);