plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

frbox.c (3008B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <draw.h>
      4 #include <mouse.h>
      5 #include <frame.h>
      6 
      7 #define	SLOP	25
      8 
      9 void
     10 _fraddbox(Frame *f, int bn, int n)	/* add n boxes after bn, shift the rest up,
     11 				 * box[bn+n]==box[bn] */
     12 {
     13 	int i;
     14 
     15 	if(bn > f->nbox)
     16 		drawerror(f->display, "_fraddbox");
     17 	if(f->nbox+n > f->nalloc)
     18 		_frgrowbox(f, n+SLOP);
     19 	for(i=f->nbox; --i>=bn; )
     20 		f->box[i+n] = f->box[i];
     21 	f->nbox+=n;
     22 }
     23 
     24 void
     25 _frclosebox(Frame *f, int n0, int n1)	/* inclusive */
     26 {
     27 	int i;
     28 
     29 	if(n0>=f->nbox || n1>=f->nbox || n1<n0)
     30 		drawerror(f->display, "_frclosebox");
     31 	n1++;
     32 	for(i=n1; i<f->nbox; i++)
     33 		f->box[i-(n1-n0)] = f->box[i];
     34 	f->nbox -= n1-n0;
     35 }
     36 
     37 void
     38 _frdelbox(Frame *f, int n0, int n1)	/* inclusive */
     39 {
     40 	if(n0>=f->nbox || n1>=f->nbox || n1<n0)
     41 		drawerror(f->display, "_frdelbox");
     42 	_frfreebox(f, n0, n1);
     43 	_frclosebox(f, n0, n1);
     44 }
     45 
     46 void
     47 _frfreebox(Frame *f, int n0, int n1)	/* inclusive */
     48 {
     49 	int i;
     50 
     51 	if(n1<n0)
     52 		return;
     53 	if(n0>=f->nbox || n1>=f->nbox)
     54 		drawerror(f->display, "_frfreebox");
     55 	n1++;
     56 	for(i=n0; i<n1; i++)
     57 		if(f->box[i].nrune >= 0)
     58 			free(f->box[i].ptr);
     59 }
     60 
     61 void
     62 _frgrowbox(Frame *f, int delta)
     63 {
     64 	f->nalloc += delta;
     65 	f->box = realloc(f->box, f->nalloc*sizeof(Frbox));
     66 	if(f->box == 0)
     67 		drawerror(f->display, "_frgrowbox");
     68 }
     69 
     70 static
     71 void
     72 dupbox(Frame *f, int bn)
     73 {
     74 	uchar *p;
     75 
     76 	if(f->box[bn].nrune < 0)
     77 		drawerror(f->display, "dupbox");
     78 	_fraddbox(f, bn, 1);
     79 	if(f->box[bn].nrune >= 0){
     80 		p = _frallocstr(f, NBYTE(&f->box[bn])+1);
     81 		strcpy((char*)p, (char*)f->box[bn].ptr);
     82 		f->box[bn+1].ptr = p;
     83 	}
     84 }
     85 
     86 static
     87 uchar*
     88 runeindex(uchar *p, int n)
     89 {
     90 	int i, w;
     91 	Rune rune;
     92 
     93 	for(i=0; i<n; i++,p+=w)
     94 		if(*p < Runeself)
     95 			w = 1;
     96 		else{
     97 			w = chartorune(&rune, (char*)p);
     98 			USED(rune);
     99 		}
    100 	return p;
    101 }
    102 
    103 static
    104 void
    105 truncatebox(Frame *f, Frbox *b, int n)	/* drop last n chars; no allocation done */
    106 {
    107 	if(b->nrune<0 || b->nrune<n)
    108 		drawerror(f->display, "truncatebox");
    109 	b->nrune -= n;
    110 	runeindex(b->ptr, b->nrune)[0] = 0;
    111 	b->wid = stringwidth(f->font, (char *)b->ptr);
    112 }
    113 
    114 static
    115 void
    116 chopbox(Frame *f, Frbox *b, int n)	/* drop first n chars; no allocation done */
    117 {
    118 	char *p;
    119 
    120 	if(b->nrune<0 || b->nrune<n)
    121 		drawerror(f->display, "chopbox");
    122 	p = (char*)runeindex(b->ptr, n);
    123 	memmove((char*)b->ptr, p, strlen(p)+1);
    124 	b->nrune -= n;
    125 	b->wid = stringwidth(f->font, (char *)b->ptr);
    126 }
    127 
    128 void
    129 _frsplitbox(Frame *f, int bn, int n)
    130 {
    131 	dupbox(f, bn);
    132 	truncatebox(f, &f->box[bn], f->box[bn].nrune-n);
    133 	chopbox(f, &f->box[bn+1], n);
    134 }
    135 
    136 void
    137 _frmergebox(Frame *f, int bn)		/* merge bn and bn+1 */
    138 {
    139 	Frbox *b;
    140 
    141 	b = &f->box[bn];
    142 	_frinsure(f, bn, NBYTE(&b[0])+NBYTE(&b[1])+1);
    143 	strcpy((char*)runeindex(b[0].ptr, b[0].nrune), (char*)b[1].ptr);
    144 	b[0].wid += b[1].wid;
    145 	b[0].nrune += b[1].nrune;
    146 	_frdelbox(f, bn+1, bn+1);
    147 }
    148 
    149 int
    150 _frfindbox(Frame *f, int bn, ulong p, ulong q)	/* find box containing q and put q on a box boundary */
    151 {
    152 	Frbox *b;
    153 
    154 	for(b = &f->box[bn]; bn<f->nbox && p+NRUNE(b)<=q; bn++, b++)
    155 		p += NRUNE(b);
    156 	if(p != q)
    157 		_frsplitbox(f, bn++, (int)(q-p));
    158 	return bn;
    159 }