]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libframe/frdraw.c
Import sources from 2011-03-30 iso image - lib
[plan9front.git] / sys / src / libframe / frdraw.c
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <thread.h>
5 #include <mouse.h>
6 #include <frame.h>
7
8 void
9 _frdrawtext(Frame *f, Point pt, Image *text, Image *back)
10 {
11         Frbox *b;
12         int nb;
13         static int x;
14
15         for(nb=0,b=f->box; nb<f->nbox; nb++, b++){
16                 _frcklinewrap(f, &pt, b);
17                 if(b->nrune >= 0){
18                         stringbg(f->b, pt, text, ZP, f->font, (char*)b->ptr, back, ZP);
19                 }
20                 pt.x += b->wid;
21         }
22 }
23
24 static int
25 nbytes(char *s0, int nr)
26 {
27         char *s;
28         Rune r;
29
30         s = s0;
31         while(--nr >= 0)
32                 s += chartorune(&r, s);
33         return s-s0;
34 }
35
36 void
37 frdrawsel(Frame *f, Point pt, ulong p0, ulong p1, int issel)
38 {
39         Image *back, *text;
40
41         if(f->ticked)
42                 frtick(f, frptofchar(f, f->p0), 0);
43
44         if(p0 == p1){
45                 frtick(f, pt, issel);
46                 return;
47         }
48
49         if(issel){
50                 back = f->cols[HIGH];
51                 text = f->cols[HTEXT];
52         }else{
53                 back = f->cols[BACK];
54                 text = f->cols[TEXT];
55         }
56
57         frdrawsel0(f, pt, p0, p1, back, text);
58 }
59
60 Point
61 frdrawsel0(Frame *f, Point pt, ulong p0, ulong p1, Image *back, Image *text)
62 {
63         Frbox *b;
64         int nb, nr, w, x, trim;
65         Point qt;
66         uint p;
67         char *ptr;
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 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--; /* looks best just left of where requested */
151         r = Rect(pt.x, pt.y, pt.x+FRTICKW, 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 Point
164 _frdraw(Frame *f, Point pt)
165 {
166         Frbox *b;
167         int nb, n;
168
169         for(b=f->box,nb=0; nb<f->nbox; nb++, b++){
170                 _frcklinewrap0(f, &pt, b);
171                 if(pt.y == f->r.max.y){
172                         f->nchars -= _frstrlen(f, nb);
173                         _frdelbox(f, nb, f->nbox-1);
174                         break;
175                 }
176                 if(b->nrune > 0){
177                         n = _frcanfit(f, pt, b);
178                         if(n == 0)
179                                 drawerror(f->display, "_frcanfit==0");
180                         if(n != b->nrune){
181                                 _frsplitbox(f, nb, n);
182                                 b = &f->box[nb];
183                         }
184                         pt.x += b->wid;
185                 }else{
186                         if(b->bc == '\n'){
187                                 pt.x = f->r.min.x;
188                                 pt.y+=f->font->height;
189                         }else
190                                 pt.x += _frnewwid(f, pt, b);
191                 }
192         }
193         return pt;
194 }
195
196 int
197 _frstrlen(Frame *f, int nb)
198 {
199         int n;
200
201         for(n=0; nb<f->nbox; nb++)
202                 n += NRUNE(&f->box[nb]);
203         return n;
204 }