plan9port

[fork] Plan 9 from user space
git clone git://src.adamsgaard.dk/plan9port # fast
git clone https://src.adamsgaard.dk/plan9port.git # slow
Log | Files | Refs | README | LICENSE Back to index

range.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 *);