xref: /plan9/sys/src/libframe/frbox.c (revision ac1798d163cd7d251029e64d9069da932ffbf5c6)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <thread.h>
57dd7cddfSDavid du Colombier #include <mouse.h>
63e12c5d1SDavid du Colombier #include <frame.h>
73e12c5d1SDavid du Colombier 
83e12c5d1SDavid du Colombier #define	SLOP	25
93e12c5d1SDavid du Colombier 
103e12c5d1SDavid du Colombier void
_fraddbox(Frame * f,int bn,int n)113e12c5d1SDavid du Colombier _fraddbox(Frame *f, int bn, int n)	/* add n boxes after bn, shift the rest up,
123e12c5d1SDavid du Colombier 				 * box[bn+n]==box[bn] */
133e12c5d1SDavid du Colombier {
143e12c5d1SDavid du Colombier 	int i;
153e12c5d1SDavid du Colombier 
163e12c5d1SDavid du Colombier 	if(bn > f->nbox)
177dd7cddfSDavid du Colombier 		drawerror(f->display, "_fraddbox");
183e12c5d1SDavid du Colombier 	if(f->nbox+n > f->nalloc)
193e12c5d1SDavid du Colombier 		_frgrowbox(f, n+SLOP);
203e12c5d1SDavid du Colombier 	for(i=f->nbox; --i>=bn; )
213e12c5d1SDavid du Colombier 		f->box[i+n] = f->box[i];
223e12c5d1SDavid du Colombier 	f->nbox+=n;
233e12c5d1SDavid du Colombier }
243e12c5d1SDavid du Colombier 
253e12c5d1SDavid du Colombier void
_frclosebox(Frame * f,int n0,int n1)263e12c5d1SDavid du Colombier _frclosebox(Frame *f, int n0, int n1)	/* inclusive */
273e12c5d1SDavid du Colombier {
283e12c5d1SDavid du Colombier 	int i;
293e12c5d1SDavid du Colombier 
303e12c5d1SDavid du Colombier 	if(n0>=f->nbox || n1>=f->nbox || n1<n0)
317dd7cddfSDavid du Colombier 		drawerror(f->display, "_frclosebox");
323e12c5d1SDavid du Colombier 	n1++;
333e12c5d1SDavid du Colombier 	for(i=n1; i<f->nbox; i++)
343e12c5d1SDavid du Colombier 		f->box[i-(n1-n0)] = f->box[i];
353e12c5d1SDavid du Colombier 	f->nbox -= n1-n0;
363e12c5d1SDavid du Colombier }
373e12c5d1SDavid du Colombier 
383e12c5d1SDavid du Colombier void
_frdelbox(Frame * f,int n0,int n1)393e12c5d1SDavid du Colombier _frdelbox(Frame *f, int n0, int n1)	/* inclusive */
403e12c5d1SDavid du Colombier {
413e12c5d1SDavid du Colombier 	if(n0>=f->nbox || n1>=f->nbox || n1<n0)
427dd7cddfSDavid du Colombier 		drawerror(f->display, "_frdelbox");
433e12c5d1SDavid du Colombier 	_frfreebox(f, n0, n1);
443e12c5d1SDavid du Colombier 	_frclosebox(f, n0, n1);
453e12c5d1SDavid du Colombier }
463e12c5d1SDavid du Colombier 
473e12c5d1SDavid du Colombier void
_frfreebox(Frame * f,int n0,int n1)483e12c5d1SDavid du Colombier _frfreebox(Frame *f, int n0, int n1)	/* inclusive */
493e12c5d1SDavid du Colombier {
503e12c5d1SDavid du Colombier 	int i;
513e12c5d1SDavid du Colombier 
523e12c5d1SDavid du Colombier 	if(n1<n0)
533e12c5d1SDavid du Colombier 		return;
543e12c5d1SDavid du Colombier 	if(n0>=f->nbox || n1>=f->nbox)
557dd7cddfSDavid du Colombier 		drawerror(f->display, "_frfreebox");
563e12c5d1SDavid du Colombier 	n1++;
573e12c5d1SDavid du Colombier 	for(i=n0; i<n1; i++)
583e12c5d1SDavid du Colombier 		if(f->box[i].nrune >= 0)
593e12c5d1SDavid du Colombier 			free(f->box[i].ptr);
603e12c5d1SDavid du Colombier }
613e12c5d1SDavid du Colombier 
623e12c5d1SDavid du Colombier void
_frgrowbox(Frame * f,int delta)633e12c5d1SDavid du Colombier _frgrowbox(Frame *f, int delta)
643e12c5d1SDavid du Colombier {
653e12c5d1SDavid du Colombier 	f->nalloc += delta;
663e12c5d1SDavid du Colombier 	f->box = realloc(f->box, f->nalloc*sizeof(Frbox));
673e12c5d1SDavid du Colombier 	if(f->box == 0)
687dd7cddfSDavid du Colombier 		drawerror(f->display, "_frgrowbox");
693e12c5d1SDavid du Colombier }
703e12c5d1SDavid du Colombier 
713e12c5d1SDavid du Colombier static
723e12c5d1SDavid du Colombier void
dupbox(Frame * f,int bn)733e12c5d1SDavid du Colombier dupbox(Frame *f, int bn)
743e12c5d1SDavid du Colombier {
753e12c5d1SDavid du Colombier 	uchar *p;
763e12c5d1SDavid du Colombier 
773e12c5d1SDavid du Colombier 	if(f->box[bn].nrune < 0)
787dd7cddfSDavid du Colombier 		drawerror(f->display, "dupbox");
793e12c5d1SDavid du Colombier 	_fraddbox(f, bn, 1);
803e12c5d1SDavid du Colombier 	if(f->box[bn].nrune >= 0){
817dd7cddfSDavid du Colombier 		p = _frallocstr(f, NBYTE(&f->box[bn])+1);
823e12c5d1SDavid du Colombier 		strcpy((char*)p, (char*)f->box[bn].ptr);
833e12c5d1SDavid du Colombier 		f->box[bn+1].ptr = p;
843e12c5d1SDavid du Colombier 	}
853e12c5d1SDavid du Colombier }
863e12c5d1SDavid du Colombier 
873e12c5d1SDavid du Colombier static
883e12c5d1SDavid du Colombier uchar*
runeindex(uchar * p,int n)893e12c5d1SDavid du Colombier runeindex(uchar *p, int n)
903e12c5d1SDavid du Colombier {
913e12c5d1SDavid du Colombier 	int i, w;
923e12c5d1SDavid du Colombier 	Rune rune;
933e12c5d1SDavid du Colombier 
943e12c5d1SDavid du Colombier 	for(i=0; i<n; i++,p+=w)
953e12c5d1SDavid du Colombier 		if(*p < Runeself)
963e12c5d1SDavid du Colombier 			w = 1;
973e12c5d1SDavid du Colombier 		else{
983e12c5d1SDavid du Colombier 			w = chartorune(&rune, (char*)p);
993e12c5d1SDavid du Colombier 			USED(rune);
1003e12c5d1SDavid du Colombier 		}
1013e12c5d1SDavid du Colombier 	return p;
1023e12c5d1SDavid du Colombier }
1033e12c5d1SDavid du Colombier 
1043e12c5d1SDavid du Colombier static
1053e12c5d1SDavid du Colombier void
truncatebox(Frame * f,Frbox * b,int n)1063e12c5d1SDavid du Colombier truncatebox(Frame *f, Frbox *b, int n)	/* drop last n chars; no allocation done */
1073e12c5d1SDavid du Colombier {
1083e12c5d1SDavid du Colombier 	if(b->nrune<0 || b->nrune<n)
1097dd7cddfSDavid du Colombier 		drawerror(f->display, "truncatebox");
1103e12c5d1SDavid du Colombier 	b->nrune -= n;
1113e12c5d1SDavid du Colombier 	runeindex(b->ptr, b->nrune)[0] = 0;
1127dd7cddfSDavid du Colombier 	b->wid = stringwidth(f->font, (char *)b->ptr);
1133e12c5d1SDavid du Colombier }
1143e12c5d1SDavid du Colombier 
1153e12c5d1SDavid du Colombier static
1163e12c5d1SDavid du Colombier void
chopbox(Frame * f,Frbox * b,int n)1173e12c5d1SDavid du Colombier chopbox(Frame *f, Frbox *b, int n)	/* drop first n chars; no allocation done */
1183e12c5d1SDavid du Colombier {
119*ac1798d1SDavid du Colombier 	char *p;
120*ac1798d1SDavid du Colombier 
1213e12c5d1SDavid du Colombier 	if(b->nrune<0 || b->nrune<n)
1227dd7cddfSDavid du Colombier 		drawerror(f->display, "chopbox");
123*ac1798d1SDavid du Colombier 	p = (char*)runeindex(b->ptr, n);
124*ac1798d1SDavid du Colombier 	memmove((char*)b->ptr, p, strlen(p)+1);
1253e12c5d1SDavid du Colombier 	b->nrune -= n;
1267dd7cddfSDavid du Colombier 	b->wid = stringwidth(f->font, (char *)b->ptr);
1273e12c5d1SDavid du Colombier }
1283e12c5d1SDavid du Colombier 
1293e12c5d1SDavid du Colombier void
_frsplitbox(Frame * f,int bn,int n)1303e12c5d1SDavid du Colombier _frsplitbox(Frame *f, int bn, int n)
1313e12c5d1SDavid du Colombier {
1323e12c5d1SDavid du Colombier 	dupbox(f, bn);
1333e12c5d1SDavid du Colombier 	truncatebox(f, &f->box[bn], f->box[bn].nrune-n);
1343e12c5d1SDavid du Colombier 	chopbox(f, &f->box[bn+1], n);
1353e12c5d1SDavid du Colombier }
1363e12c5d1SDavid du Colombier 
1373e12c5d1SDavid du Colombier void
_frmergebox(Frame * f,int bn)1383e12c5d1SDavid du Colombier _frmergebox(Frame *f, int bn)		/* merge bn and bn+1 */
1393e12c5d1SDavid du Colombier {
1403e12c5d1SDavid du Colombier 	Frbox *b;
1413e12c5d1SDavid du Colombier 
1423e12c5d1SDavid du Colombier 	b = &f->box[bn];
1433e12c5d1SDavid du Colombier 	_frinsure(f, bn, NBYTE(&b[0])+NBYTE(&b[1])+1);
1443e12c5d1SDavid du Colombier 	strcpy((char*)runeindex(b[0].ptr, b[0].nrune), (char*)b[1].ptr);
1453e12c5d1SDavid du Colombier 	b[0].wid += b[1].wid;
1463e12c5d1SDavid du Colombier 	b[0].nrune += b[1].nrune;
1473e12c5d1SDavid du Colombier 	_frdelbox(f, bn+1, bn+1);
1483e12c5d1SDavid du Colombier }
1493e12c5d1SDavid du Colombier 
1503e12c5d1SDavid du Colombier int
_frfindbox(Frame * f,int bn,ulong p,ulong q)1513e12c5d1SDavid du Colombier _frfindbox(Frame *f, int bn, ulong p, ulong q)	/* find box containing q and put q on a box boundary */
1523e12c5d1SDavid du Colombier {
1533e12c5d1SDavid du Colombier 	Frbox *b;
1543e12c5d1SDavid du Colombier 
1553e12c5d1SDavid du Colombier 	for(b = &f->box[bn]; bn<f->nbox && p+NRUNE(b)<=q; bn++, b++)
1563e12c5d1SDavid du Colombier 		p += NRUNE(b);
1573e12c5d1SDavid du Colombier 	if(p != q)
1583e12c5d1SDavid du Colombier 		_frsplitbox(f, bn++, (int)(q-p));
1593e12c5d1SDavid du Colombier 	return bn;
1603e12c5d1SDavid du Colombier }
161