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