plan9port

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

frdraw.c (4225B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <draw.h>
      4 #include <mouse.h>
      5 #include <frame.h>
      6 
      7 void
      8 _frdrawtext(Frame *f, Point pt, Image *text, Image *back)
      9 {
     10 	Frbox *b;
     11 	int nb;
     12 
     13 	for(nb=0,b=f->box; nb<f->nbox; nb++, b++){
     14 		_frcklinewrap(f, &pt, b);
     15 		if(!f->noredraw && b->nrune >= 0)
     16 			stringbg(f->b, pt, text, ZP, f->font, (char*)b->ptr, back, ZP);
     17 		pt.x += b->wid;
     18 	}
     19 }
     20 
     21 static int
     22 nbytes(char *s0, int nr)
     23 {
     24 	char *s;
     25 	Rune r;
     26 
     27 	s = s0;
     28 	while(--nr >= 0)
     29 		s += chartorune(&r, s);
     30 	return s-s0;
     31 }
     32 
     33 void
     34 frdrawsel(Frame *f, Point pt, ulong p0, ulong p1, int issel)
     35 {
     36 	Image *back, *text;
     37 
     38 	if(f->ticked)
     39 		frtick(f, frptofchar(f, f->p0), 0);
     40 
     41 	if(p0 == p1){
     42 		frtick(f, pt, issel);
     43 		return;
     44 	}
     45 
     46 	if(issel){
     47 		back = f->cols[HIGH];
     48 		text = f->cols[HTEXT];
     49 	}else{
     50 		back = f->cols[BACK];
     51 		text = f->cols[TEXT];
     52 	}
     53 
     54 	frdrawsel0(f, pt, p0, p1, back, text);
     55 }
     56 
     57 Point
     58 frdrawsel0(Frame *f, Point pt, ulong p0, ulong p1, Image *back, Image *text)
     59 {
     60 	Frbox *b;
     61 	int nb, nr, w, x, trim;
     62 	Point qt;
     63 	uint p;
     64 	char *ptr;
     65 
     66 	if(p0 > p1)
     67 		sysfatal("libframe: frdrawsel0 p0=%lud > p1=%lud", p0, p1);
     68 
     69 	p = 0;
     70 	b = f->box;
     71 	trim = 0;
     72 	for(nb=0; nb<f->nbox && p<p1; nb++){
     73 		nr = b->nrune;
     74 		if(nr < 0)
     75 			nr = 1;
     76 		if(p+nr <= p0)
     77 			goto Continue;
     78 		if(p >= p0){
     79 			qt = pt;
     80 			_frcklinewrap(f, &pt, b);
     81 			/* fill in the end of a wrapped line */
     82 			if(pt.y > qt.y)
     83 				draw(f->b, Rect(qt.x, qt.y, f->r.max.x, pt.y), back, nil, qt);
     84 		}
     85 		ptr = (char*)b->ptr;
     86 		if(p < p0){	/* beginning of region: advance into box */
     87 			ptr += nbytes(ptr, p0-p);
     88 			nr -= (p0-p);
     89 			p = p0;
     90 		}
     91 		trim = 0;
     92 		if(p+nr > p1){	/* end of region: trim box */
     93 			nr -= (p+nr)-p1;
     94 			trim = 1;
     95 		}
     96 		if(b->nrune<0 || nr==b->nrune)
     97 			w = b->wid;
     98 		else
     99 			w = stringnwidth(f->font, ptr, nr);
    100 		x = pt.x+w;
    101 		if(x > f->r.max.x)
    102 			x = f->r.max.x;
    103 		draw(f->b, Rect(pt.x, pt.y, x, pt.y+f->font->height), back, nil, pt);
    104 		if(b->nrune >= 0)
    105 			stringnbg(f->b, pt, text, ZP, f->font, ptr, nr, back, ZP);
    106 		pt.x += w;
    107 	    Continue:
    108 		b++;
    109 		p += nr;
    110 	}
    111 	/* if this is end of last plain text box on wrapped line, fill to end of line */
    112 	if(p1>p0 &&  b>f->box && b<f->box+f->nbox && b[-1].nrune>0 && !trim){
    113 		qt = pt;
    114 		_frcklinewrap(f, &pt, b);
    115 		if(pt.y > qt.y)
    116 			draw(f->b, Rect(qt.x, qt.y, f->r.max.x, pt.y), back, nil, qt);
    117 	}
    118 	return pt;
    119 }
    120 
    121 void
    122 frredraw(Frame *f)
    123 {
    124 	int ticked;
    125 	Point pt;
    126 
    127 	if(f->p0 == f->p1){
    128 		ticked = f->ticked;
    129 		if(ticked)
    130 			frtick(f, frptofchar(f, f->p0), 0);
    131 		frdrawsel0(f, frptofchar(f, 0), 0, f->nchars, f->cols[BACK], f->cols[TEXT]);
    132 		if(ticked)
    133 			frtick(f, frptofchar(f, f->p0), 1);
    134 		return;
    135 	}
    136 
    137 	pt = frptofchar(f, 0);
    138 	pt = frdrawsel0(f, pt, 0, f->p0, f->cols[BACK], f->cols[TEXT]);
    139 	pt = frdrawsel0(f, pt, f->p0, f->p1, f->cols[HIGH], f->cols[HTEXT]);
    140 	pt = frdrawsel0(f, pt, f->p1, f->nchars, f->cols[BACK], f->cols[TEXT]);
    141 }
    142 
    143 static void
    144 _frtick(Frame *f, Point pt, int ticked)
    145 {
    146 	Rectangle r;
    147 
    148 	if(f->ticked==ticked || f->tick==0 || !ptinrect(pt, f->r))
    149 		return;
    150 	pt.x -= f->tickscale;	/* looks best just left of where requested */
    151 	r = Rect(pt.x, pt.y, pt.x+FRTICKW*f->tickscale, pt.y+f->font->height);
    152 	/* can go into left border but not right */
    153 	if(r.max.x > f->r.max.x)
    154 		r.max.x = f->r.max.x;
    155 	if(ticked){
    156 		draw(f->tickback, f->tickback->r, f->b, nil, pt);
    157 		draw(f->b, r, f->tick, nil, ZP);
    158 	}else
    159 		draw(f->b, r, f->tickback, nil, ZP);
    160 	f->ticked = ticked;
    161 }
    162 
    163 void
    164 frtick(Frame *f, Point pt, int ticked)
    165 {
    166 	if(f->tickscale != scalesize(f->display, 1)) {
    167 		if(f->ticked)
    168 			_frtick(f, pt, 0);
    169 		frinittick(f);
    170 	}
    171 	_frtick(f, pt, ticked);
    172 }
    173 
    174 Point
    175 _frdraw(Frame *f, Point pt)
    176 {
    177 	Frbox *b;
    178 	int nb, n;
    179 
    180 	for(b=f->box,nb=0; nb<f->nbox; nb++, b++){
    181 		_frcklinewrap0(f, &pt, b);
    182 		if(pt.y == f->r.max.y){
    183 			f->nchars -= _frstrlen(f, nb);
    184 			_frdelbox(f, nb, f->nbox-1);
    185 			break;
    186 		}
    187 		if(b->nrune > 0){
    188 			n = _frcanfit(f, pt, b);
    189 			if(n == 0)
    190 				break;
    191 			if(n != b->nrune){
    192 				_frsplitbox(f, nb, n);
    193 				b = &f->box[nb];
    194 			}
    195 			pt.x += b->wid;
    196 		}else{
    197 			if(b->bc == '\n'){
    198 				pt.x = f->r.min.x;
    199 				pt.y+=f->font->height;
    200 			}else
    201 				pt.x += _frnewwid(f, pt, b);
    202 		}
    203 	}
    204 	return pt;
    205 }
    206 
    207 int
    208 _frstrlen(Frame *f, int nb)
    209 {
    210 	int n;
    211 
    212 	for(n=0; nb<f->nbox; nb++)
    213 		n += NRUNE(&f->box[nb]);
    214 	return n;
    215 }