File:  [Research Unix] / researchv9 / jerq / src / sam / term / frinsert.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:21:59 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv9-SUN3_old, researchv9-SUN3, HEAD
researchv9-SUN3(old)

#include "frame.h"

#define	DELTA	25
static Frame		frame;
Point
bxscan(f, sp, ppt)
	Frame *f;
	uchar **sp;
	Point *ppt;
{
	register w, c, nb;
	register uchar *p;
	register Box *b;
	register uchar *s;
	int n;
	frame.r=f->r;
	frame.b=f->b;
	frame.font=f->font;
	frame.maxcharwid=f->maxcharwid;
	frame.maxtab=f->maxtab;
	frame.left=f->left;
	frame.nbox=0;
	for(n=0, nb=0; (*sp)[n]; nb++,frame.nbox++){
		if(nb==frame.nalloc)
			growbox(&frame, DELTA);
		s=&(*sp)[n];
		b=&frame.box[nb];
		if(*s=='\t' || *s=='\n'){
			b->bc=*s;
			b->wid=5000;
			b->minwid=(*s=='\n')? 0 : frame.font->info[' '].width;
			b->len=-1;
			n++;
		}else{
			for(w=0,p=s; (c=*s) && c!='\t' && c!='\n'; s++)
				w+=frame.font->info[c].width;
			*s=0;
			b->ptr=allocstr((int)(s-p+1));
			copystr(p, b->ptr);
			*s=c;
			b->wid=w;
			n+=b->len=s-p;
		}
	}
	frame.nchars=n;
	b=&frame.box[0];
	cklinewrap0(f, ppt, b);
	return draw(&frame, *ppt);
}
frinsert(f, sp, p0)
	register Frame *f;
	uchar **sp;
	Posn p0;
{
	Point pt0, pt1, ppt0, ppt1, pt;
	register Box *b;
	register n, n0, nn0;
	Rectangle r;
	int y;
	static struct{
		Point pt0, pt1;
	}*pts;
	static int nalloc=0;
	int npts;
	if(p0>f->nchars || **sp==0 || f->b==0)
		return;
	nn0=n0=findbox(f, 0, 0, p0);
	ppt0=pt0=ptofcharnb(f, p0, n0);
	ppt1=pt1=bxscan(f, sp, &ppt0);
	if(n0<f->nbox){
		cklinewrap(f, &pt0, b=&f->box[n0]);	/* for selectf() */
		cklinewrap0(f, &ppt1, b);
	}
	/*
	 * ppt0 and ppt1 are start and end of insertion as they will appear when
	 * insertion is complete. pt0 is current location of insertion position
	 * (p0); pt1 is terminal point (without line wrap) of insertion.
	 */
	if(p0==f->p0 && p0==f->p1)		/* quite likely */
		selectf(f, pt0, pt0, F_XOR);
	else
		selectp(f, F_XOR);
	/*
	 * Find point where old and new x's line up
	 * Invariants:
	 *	pt0 is where the next box (b, n0) is now
	 *	pt1 is where it will be after then insertion
	 * If pt1 goes off the rectangle, we can toss everything from there on
	 */
	for(b=&f->box[n0],npts=0;
	     pt1.x!=pt0.x && pt1.y!=f->r.corner.y && n0<f->nbox; b++,n0++,npts++){
		cklinewrap(f, &pt0, b);
		cklinewrap0(f, &pt1, b);
		if(b->len>0){
			n=canfit(f, pt1, b);
			if(n==0)
				panic("canfit==0");
			if(n!=b->len){
				splitbox(f, n0, n);
				b=&f->box[n0];
			}
		}
		if(npts==nalloc){
			gcrealloc((char **)&pts,
				npts*sizeof(pts[0]), (npts+DELTA)*sizeof(pts[0]));
			nalloc+=DELTA;
			b=&f->box[n0];
		}
		pts[npts].pt0=pt0, pts[npts].pt1=pt1;
		/* has a text box overflowed off the frame? */
		if(pt1.y==f->r.corner.y)
			break;
		advance(f, &pt0, b);
		pt1.x+=newwid(f, pt1, b);
	}
	if(pt1.y>f->r.corner.y)
		panic("frinsert pt1 too far");
	if(pt1.y==f->r.corner.y && n0<f->nbox){
		f->nchars-=frstrlen(f, n0);
		delbox(f, n0, f->nbox-1);
	}
	if(n0==f->nbox)
		f->nlines=(pt1.y-f->r.origin.y)/f->font->height+(pt1.x>f->left);
	else if(pt1.y!=pt0.y){
		int q0, q1;
		y=f->r.corner.y;
		q0=pt0.y+f->font->height, q1=pt1.y+f->font->height;
		f->nlines+=(q1-q0)/f->font->height;
		if(f->nlines>f->maxlines)
			chopframe(f, ppt1, p0, nn0);
		if(pt1.y<y){
			r=f->r, r.origin.y=q0, r.corner.y=y-(q1-q0);
			if(q1<y)
				bitblt(B, r, B, Pt(f->r.origin.x, q1), F_STORE);
			r.origin=pt0; r.corner.y=q0;
			bitblt(B, r, B, pt1, F_STORE);
		}
	}
	/*
	 * Move the old stuff down to make room.  The loop will move the stuff
	 * between the insertion and the point where the x's lined up.
	 * The bitblts above moved everything down after the point they lined up.
	 */
	for((y=pt1.y==f->r.corner.y?pt1.y:0),b=&f->box[n0-1]; --npts>=0; --b){
		pt=pts[npts].pt1;
		if(b->len>0){
			r.origin=r.corner=pts[npts].pt0;
			r.corner.x+=b->wid, r.corner.y+=f->font->height;
			bitblt(B, r, B, pt, F_STORE);
			if(pt.y<y){	/* clear bit hanging off right */
				r.origin=r.corner=pt;
				r.origin.x+=b->wid;
				r.corner.x=f->r.corner.x;
				r.corner.y+=f->font->height;
				rectf(B, r, F_CLR);
			}
			y=pt.y;
		}else{
			r.origin=r.corner=pt;
			r.corner.x+=b->wid, r.corner.y+=f->font->height;
			if(r.corner.x>=f->r.corner.x)
				r.corner.x=f->r.corner.x;
			rectf(B, r, F_CLR);
			y=pt.x==f->left? pt.y : 0;
		}
	}
	selectf(f, ppt0, ppt1, F_CLR);
	redraw(&frame, ppt0);
	addbox(f, nn0, frame.nbox);
	for(n=0; n<frame.nbox; n++)
		f->box[nn0+n]=frame.box[n];
	if(nn0>0 && f->box[nn0-1].len>=0 && ppt0.x-f->box[nn0-1].wid>=(int)f->left){
		--nn0;
		ppt0.x-=f->box[nn0].wid;
	}
	n0+=frame.nbox;
	clean(f, ppt0, nn0, n0<f->nbox-1? n0+1 : n0);
	f->nchars+=frame.nchars;
	if(f->p0>=p0)
		f->p0+=frame.nchars;
	if(f->p0>f->nchars)
		f->p0=f->nchars;
	if(f->p1>=p0)
		f->p1+=frame.nchars;
	if(f->p1>f->nchars)
		f->p1=f->nchars;
	if(pt0.x!=pt1.x)
		f->lastlinefull=pt0.x==f->left;
	selectp(f, F_XOR);
}
chopframe(f, pt, p, bn)
	register Frame *f;
	Point pt;
	register Posn p;
	int bn;
{
	register Box *b;
	for(b=&f->box[bn]; ; b++){
		if(b>=&f->box[f->nbox])
			panic("endofframe");
		cklinewrap(f, &pt, b);
		if(pt.y>=f->r.corner.y)
			break;
		p+=LEN(b);
		advance(f, &pt, b);
	}
	f->nchars=p;
	f->nlines=f->maxlines;
if(b<&f->box[f->nbox])				/* BUG */
	delbox(f, (int)(b-f->box), f->nbox-1);
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.