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