#ifndef lint
static char sccsid[] = "@(#)tree.c	4.4 (Berkeley) 8/25/84";
#endif

#include "compact.h"

insert(ch)
	int ch;
{
	register struct node *pp;
	register struct son *pson, *bson;
	union cio d;
	register struct index *wt;

	wt = NEW;
	pp = bottom++;
	pson = &pp->sons[RIGHT];
	bson = &bottom->sons[LEFT];
	bottom->fath.fp = pp;
	in[ch].flags = (SEEN | FBIT);
	d.integ = bson->sp.ch = pson->sp.ch;
	in[ch].fp = in[d.integ].fp = pson->sp.p = wt->pt = bottom;
	bottom->fath.flags = (LLEAF | RLEAF | FBIT);
	pp->fath.flags &= ~RLEAF;
	in[d.integ].flags = SEEN;

	bson->count = pson->count;
	bson->top = pson->top;
	bson++;
	bson->sp.ch = ch;
	bson->count = 0;
	bson->top = pson->top->next = wt;
	wt->next = NULL;
}

uptree(ch)
	int ch;
{
	register struct node *r;
	union treep q, s;
	int rs, ts, rflags, tflags;
	longint rc, qc, sc;
	struct node *t;
	register struct son *rson, *tson;
	register struct index *rt, *qt, *st;

	r = in[ch].fp;
	rs = in[ch].flags & FBIT;

	do {
		rson = &r->sons[rs];
		rc = ++rson->count;
		rt = rson->top;
		for (;;) {
			if (rs) {
				s.p = r + 1;
				if (r == bottom) {
					sc = rc - 2;
					st = NULL;
				} else {
					sc = (r+1)->sons[LEFT].count;
					st = (r+1)->sons[LEFT].top;
				}
				qc = r->sons[LEFT].count;
				qt = r->sons[LEFT].top;
			} else {
				s.p = r;
				sc = r->sons[RIGHT].count;
				st = r->sons[RIGHT].top;
				if (r == dict) {
					qc = rc + 1;
					qt = head;
					break;
				} else {
					qc = (r-1)->sons[RIGHT].count;
					qt = (r-1)->sons[RIGHT].top;
				}
			}
			if (rc <= qc)
				break;

			t = qt->pt;
			ts = LEFT;
			tson = &t->sons[LEFT];
			if (rc <= tson->count) {
				tson++;
				ts++;
			}

			/* exchange pointers of (t, ts) and (r, rs) */
			q.ch = tson->sp.ch;
			s.ch = rson->sp.ch;
			tson->sp.ch = s.ch;
			rson->sp.ch = q.ch;
			exch(t, ts, q.ch, r, rs);
			exch(r, rs, s.ch, t, ts);

			rflags = (rs ? RLEAF : LLEAF);
			tflags = (ts ? RLEAF : LLEAF);
			if (((r->fath.flags & rflags) << rs) ^ ((t->fath.flags & tflags) << ts)) {
				r->fath.flags ^= rflags;
				t->fath.flags ^= tflags;
			}

			tson->count++;
			rson->count--;
			if (ts)
				qt->pt++;
			r = t;
			rs = ts;
			rson = tson;
		}

		if (rc == qc) {
			rson->top = qt;
			if (rc > sc + 1) {
				qt->next = st;
				/* dispose of rt */
				rt->next = flist;
				flist = rt;
			} else
				st->pt = s.p;
		} else if (rc == sc + 1) {
			/* create new index at rt */
			rt = NEW;
			rt->next = st;
			rt->pt = r;
			qt->next = rt;
			if (st)
				st->pt = s.p;
			rson->top = rt;
		}
		rs = r->fath.flags & FBIT;
		r = r->fath.fp;
	} while (r);
	dirp = head->next;
	dirq = dirp->next;
}

exch(v, vs, x, w, ws)
	struct node *v, *w;
	union treep x;
	int vs, ws;
{

	if (v->fath.flags & (vs ? RLEAF : LLEAF)) {
		in[x.ch].fp = w;
		in[x.ch].flags &= ~01;
		if (ws)
			in[x.ch].flags |= ws;
	} else {
		x.p->fath.fp = w;
		x.p->fath.flags &= ~01;
		if (ws)
			x.p->fath.flags |= ws;
	}
}
