diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/libframe/frdraw.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/libframe/frdraw.c')
-rwxr-xr-x | sys/src/libframe/frdraw.c | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/sys/src/libframe/frdraw.c b/sys/src/libframe/frdraw.c new file mode 100755 index 000000000..6a31a8383 --- /dev/null +++ b/sys/src/libframe/frdraw.c @@ -0,0 +1,204 @@ +#include <u.h> +#include <libc.h> +#include <draw.h> +#include <thread.h> +#include <mouse.h> +#include <frame.h> + +void +_frdrawtext(Frame *f, Point pt, Image *text, Image *back) +{ + Frbox *b; + int nb; + static int x; + + for(nb=0,b=f->box; nb<f->nbox; nb++, b++){ + _frcklinewrap(f, &pt, b); + if(b->nrune >= 0){ + stringbg(f->b, pt, text, ZP, f->font, (char*)b->ptr, back, ZP); + } + pt.x += b->wid; + } +} + +static int +nbytes(char *s0, int nr) +{ + char *s; + Rune r; + + s = s0; + while(--nr >= 0) + s += chartorune(&r, s); + return s-s0; +} + +void +frdrawsel(Frame *f, Point pt, ulong p0, ulong p1, int issel) +{ + Image *back, *text; + + if(f->ticked) + frtick(f, frptofchar(f, f->p0), 0); + + if(p0 == p1){ + frtick(f, pt, issel); + return; + } + + if(issel){ + back = f->cols[HIGH]; + text = f->cols[HTEXT]; + }else{ + back = f->cols[BACK]; + text = f->cols[TEXT]; + } + + frdrawsel0(f, pt, p0, p1, back, text); +} + +Point +frdrawsel0(Frame *f, Point pt, ulong p0, ulong p1, Image *back, Image *text) +{ + Frbox *b; + int nb, nr, w, x, trim; + Point qt; + uint p; + char *ptr; + + p = 0; + b = f->box; + trim = 0; + for(nb=0; nb<f->nbox && p<p1; nb++){ + nr = b->nrune; + if(nr < 0) + nr = 1; + if(p+nr <= p0) + goto Continue; + if(p >= p0){ + qt = pt; + _frcklinewrap(f, &pt, b); + /* fill in the end of a wrapped line */ + if(pt.y > qt.y) + draw(f->b, Rect(qt.x, qt.y, f->r.max.x, pt.y), back, nil, qt); + } + ptr = (char*)b->ptr; + if(p < p0){ /* beginning of region: advance into box */ + ptr += nbytes(ptr, p0-p); + nr -= (p0-p); + p = p0; + } + trim = 0; + if(p+nr > p1){ /* end of region: trim box */ + nr -= (p+nr)-p1; + trim = 1; + } + if(b->nrune<0 || nr==b->nrune) + w = b->wid; + else + w = stringnwidth(f->font, ptr, nr); + x = pt.x+w; + if(x > f->r.max.x) + x = f->r.max.x; + draw(f->b, Rect(pt.x, pt.y, x, pt.y+f->font->height), back, nil, pt); + if(b->nrune >= 0) + stringnbg(f->b, pt, text, ZP, f->font, ptr, nr, back, ZP); + pt.x += w; + Continue: + b++; + p += nr; + } + /* if this is end of last plain text box on wrapped line, fill to end of line */ + if(p1>p0 && b>f->box && b<f->box+f->nbox && b[-1].nrune>0 && !trim){ + qt = pt; + _frcklinewrap(f, &pt, b); + if(pt.y > qt.y) + draw(f->b, Rect(qt.x, qt.y, f->r.max.x, pt.y), back, nil, qt); + } + return pt; +} + +void +frredraw(Frame *f) +{ + int ticked; + Point pt; + + if(f->p0 == f->p1){ + ticked = f->ticked; + if(ticked) + frtick(f, frptofchar(f, f->p0), 0); + frdrawsel0(f, frptofchar(f, 0), 0, f->nchars, f->cols[BACK], f->cols[TEXT]); + if(ticked) + frtick(f, frptofchar(f, f->p0), 1); + return; + } + + pt = frptofchar(f, 0); + pt = frdrawsel0(f, pt, 0, f->p0, f->cols[BACK], f->cols[TEXT]); + pt = frdrawsel0(f, pt, f->p0, f->p1, f->cols[HIGH], f->cols[HTEXT]); + pt = frdrawsel0(f, pt, f->p1, f->nchars, f->cols[BACK], f->cols[TEXT]); +} + +void +frtick(Frame *f, Point pt, int ticked) +{ + Rectangle r; + + if(f->ticked==ticked || f->tick==0 || !ptinrect(pt, f->r)) + return; + pt.x--; /* looks best just left of where requested */ + r = Rect(pt.x, pt.y, pt.x+FRTICKW, pt.y+f->font->height); + /* can go into left border but not right */ + if(r.max.x > f->r.max.x) + r.max.x = f->r.max.x; + if(ticked){ + draw(f->tickback, f->tickback->r, f->b, nil, pt); + draw(f->b, r, f->tick, nil, ZP); + }else + draw(f->b, r, f->tickback, nil, ZP); + f->ticked = ticked; +} + +Point +_frdraw(Frame *f, Point pt) +{ + Frbox *b; + int nb, n; + + for(b=f->box,nb=0; nb<f->nbox; nb++, b++){ + _frcklinewrap0(f, &pt, b); + if(pt.y == f->r.max.y){ + f->nchars -= _frstrlen(f, nb); + _frdelbox(f, nb, f->nbox-1); + break; + } + if(b->nrune > 0){ + n = _frcanfit(f, pt, b); + if(n == 0) + drawerror(f->display, "_frcanfit==0"); + if(n != b->nrune){ + _frsplitbox(f, nb, n); + b = &f->box[nb]; + } + pt.x += b->wid; + }else{ + if(b->bc == '\n'){ + pt.x = f->r.min.x; + pt.y+=f->font->height; + }else + pt.x += _frnewwid(f, pt, b); + } + } + return pt; +} + +int +_frstrlen(Frame *f, int nb) +{ + int n; + + for(n=0; nb<f->nbox; nb++) + n += NRUNE(&f->box[nb]); + return n; +} |