]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/abaco/scrl.c
awk: make empty FS unicodely-correct.
[plan9front.git] / sys / src / cmd / abaco / scrl.c
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <memdraw.h>
5 #include <thread.h>
6 #include <cursor.h>
7 #include <mouse.h>
8 #include <keyboard.h>
9 #include <frame.h>
10 #include <plumb.h>
11 #include <html.h>
12 #include "dat.h"
13 #include "fns.h"
14
15 static Image *vscrtmp;
16 static Image *hscrtmp;
17
18 void
19 scrlresize(void)
20 {
21         freeimage(vscrtmp);
22         freeimage(hscrtmp);
23         vscrtmp = eallocimage(display, Rect(0, 0, 32, screen->r.max.y), screen->chan, 0, DNofill);
24         hscrtmp = eallocimage(display, Rect(0, 0, screen->r.max.x, 32), screen->chan, 0, DNofill);
25 }
26
27 static
28 Rectangle
29 scrpos(Rectangle r, uint p0, uint p1, uint tot)
30 {
31         Rectangle q;
32         int h;
33
34         q = r;
35         h = q.max.y-q.min.y;
36         if(tot == 0)
37                 return q;
38         if(tot > 1024*1024){
39                 tot>>=10;
40                 p0>>=10;
41                 p1>>=10;
42         }
43         if(p0 > 0)
44                 q.min.y += h*p0/tot;
45         if(p1 < tot)
46                 q.max.y -= h*(tot-p1)/tot;
47         if(q.max.y < q.min.y+2){
48                 if(q.min.y+2 <= r.max.y)
49                         q.max.y = q.min.y+2;
50                 else
51                         q.min.y = q.max.y-2;
52         }
53         return q;
54 }
55
56 void
57 textscrdraw(Text *t)
58 {
59         Rectangle r, r1, r2;
60         Image *b;
61
62         if(vscrtmp == nil)
63                 scrlresize();
64         r = t->scrollr;
65         b = vscrtmp;
66         r1 = r;
67         r1.min.x = 0;
68         r1.max.x = Dx(r);
69         r2 = scrpos(r1, t->org, t->org+t->nchars, t->rs.nr);
70         if(!eqrect(r2, t->lastsr)){
71                 t->lastsr = r2;
72                 draw(b, r1, t->cols[BORD], nil, ZP);
73                 draw(b, r2, t->cols[BACK], nil, ZP);
74                 r2.min.x = r2.max.x-1;
75                 draw(b, r2, t->cols[BORD], nil, ZP);
76                 draw(t->b, r, b, nil, Pt(0, r1.min.y));
77 /*flushimage(display, 1);/*BUG?*/
78         }
79 }
80
81 void
82 scrsleep(uint dt)
83 {
84         Timer   *timer;
85         static Alt alts[3];
86
87         timer = timerstart(dt);
88         alts[0].c = timer->c;
89         alts[0].v = nil;
90         alts[0].op = CHANRCV;
91         alts[1].c = mousectl->c;
92         alts[1].v = &mousectl->Mouse;
93         alts[1].op = CHANRCV;
94         alts[2].op = CHANEND;
95         for(;;)
96                 switch(alt(alts)){
97                 case 0:
98                         timerstop(timer);
99                         return;
100                 case 1:
101                         timercancel(timer);
102                         return;
103                 }
104 }
105
106 void
107 textscroll(Text *t, int but)
108 {
109         uint p0, oldp0;
110         Rectangle s;
111         int y, my, h, first;
112
113         s = insetrect(t->scrollr, 1);
114         h = s.max.y-s.min.y;
115         oldp0 = ~0;
116         first = TRUE;
117         do{
118                 flushimage(display, 1);
119                 my = mouse->xy.y;
120                 if(my < s.min.y)
121                         my = s.min.y;
122                 if(my >= s.max.y)
123                         my = s.max.y;
124                 if(but == 2){
125                         y = my;
126                         p0 = (vlong)t->rs.nr*(y-s.min.y)/h;
127                         if(p0 >= t->q1)
128                                 p0 = textbacknl(t, p0, 2);
129                         if(oldp0 != p0)
130                                 textsetorigin(t, p0, FALSE);
131                         oldp0 = p0;
132                         readmouse(mousectl);
133                         continue;
134                 }
135                 if(but == 1)
136                         p0 = textbacknl(t, t->org, (my-s.min.y)/t->font->height);
137                 else
138                         p0 = t->org+frcharofpt(t, Pt(s.max.x, my));
139                 if(oldp0 != p0)
140                         textsetorigin(t, p0, TRUE);
141                 oldp0 = p0;
142                 /* debounce */
143                 if(first){
144                         flushimage(display, 1);
145                         sleep(200);
146                         nbrecv(mousectl->c, &mousectl->Mouse);
147                         first = FALSE;
148                 }
149                 scrsleep(80);
150         }while(mouse->buttons & (1<<(but-1)));
151         while(mouse->buttons)
152                 readmouse(mousectl);
153 }
154
155 enum
156 {
157         Scrbord = 1,
158 };
159
160 void
161 pagescrldraw(Page *p)
162 {
163         Rectangle r1;
164         int t, d, l, h;
165
166         if(vscrtmp == nil)
167                 scrlresize();
168
169         r1 = Rect(0,0,Dx(p->hscrollr), Dy(p->hscrollr));
170         d = Dx(r1);
171         t = Dx(p->lay->r);
172         l = muldiv(p->pos.x, d, t);
173         h = muldiv(p->pos.x+d, d, t);
174         draw(hscrtmp, r1, tagcols[HIGH], nil, ZP);
175         r1.max.x = r1.min.x+h;
176         r1.min.x += l;
177         r1.min.y += Scrbord;
178         r1.max.y -= Scrbord;
179         draw(hscrtmp, r1, tagcols[BACK], nil, ZP);
180
181         r1 = Rect(0,0,Dx(p->vscrollr), Dy(p->vscrollr));
182         d = Dy(r1);
183         t = Dy(p->lay->r);
184         l = muldiv(p->pos.y, d, t);
185         h = muldiv(p->pos.y+d, d, t);
186         draw(vscrtmp, r1, tagcols[HIGH], nil, ZP);
187         r1.max.y = r1.min.y+h;
188         r1.min.y += l;
189         r1.max.x -= Scrbord;
190         r1.min.x += Scrbord;
191         draw(vscrtmp, r1, tagcols[BACK], nil, ZP);
192
193         draw(screen, p->vscrollr, vscrtmp, nil, vscrtmp->r.min);
194         draw(screen, p->hscrollr, hscrtmp, nil, hscrtmp->r.min);
195 }
196
197 void
198 pagescroll(Page *p, int but, int horizontal)
199 {
200         uint oldp0, p0;
201         Rectangle s;
202         int m, om, first, d, size;
203         int smin, smax, ss, *pos;
204
205         if(horizontal){
206                 s = insetrect(p->hscrollr, 1);
207                 ss = s.max.x - s.min.x;
208                 d = Dx(p->r);
209                 size = Dx(p->lay->r);
210                 p0 = p->pos.x;
211                 pos = &p->pos.x;
212                 smin =  s.min.x;
213                 smax = s.max.x;
214                 om = mouse->xy.x;
215         }else{
216                 s = insetrect(p->vscrollr, 1);
217                 ss = s.max.y-s.min.y;
218                 d = Dy(p->r);
219                 size = Dy(p->lay->r);
220                 p0 = p->pos.y;
221                 pos = &p->pos.y;
222                 smin =  s.min.y;
223                 smax = s.max.y;
224                 om = mouse->xy.y;
225         }
226         oldp0 = ~0;
227         first = TRUE;
228         do{
229                 flushimage(display, 1);
230                 if(horizontal)
231                         m = mouse->xy.x;
232                 else
233                         m = mouse->xy.y;
234
235                 if(but != 2){
236                         if(m > om)
237                                 m += (m-om)*Panspeed;
238                         else if(m < om)
239                                 m -= (om-m)*Panspeed;
240                 }
241
242                 if(m < smin)
243                         m = smin;
244                 if(m > smax)
245                         m = smax;
246
247                 om = m;
248                 if(but == 2){
249                         p0 = muldiv(m-smin, size, ss);
250                         p0 = max(p0, 0);
251                         p0 = min(p0,size-d);
252                         if(oldp0 != p0){
253                                 *pos = p0;
254                                 pageredraw(p);
255                         }
256                         oldp0 = p0;
257                         readmouse(mousectl);
258                         continue;
259                 }
260                 if(but == 1)
261                         p0 -= (d/2);
262                 else
263                         p0 += d/2;
264                 p0 = min(p0, size-d);
265                 p0 = max(p0, 0);
266                 if(oldp0 != p0){
267                         *pos = p0;
268                         pageredraw(p);
269                 }
270                 oldp0 = p0;
271                 /* debounce */
272                 if(first){
273                         flushimage(display, 1);
274                         sleep(200);
275                         nbrecv(mousectl->c, &mousectl->Mouse);
276                         first = FALSE;
277                 }
278                 scrsleep(80);
279         }while(mouse->buttons & (1<<(but-1)));
280         while(mouse->buttons)
281                 readmouse(mousectl);
282 }
283
284 int
285 pagescrollxy(Page *p, int x, int y)
286 {
287         int scrled;
288
289         scrled = FALSE;
290         if(x != 0){
291                 p->pos.x += x;
292                 p->pos.x = max(p->pos.x, 0);
293                 p->pos.x = min(p->pos.x, Dx(p->lay->r)-Dx(p->r));
294                 scrled =TRUE;
295         }
296         if(y != 0){
297                 p->pos.y += y;
298                 p->pos.y = max(p->pos.y, 0);
299                 p->pos.y = min(p->pos.y, Dy(p->lay->r)-Dy(p->r));
300                 scrled =TRUE;
301         }
302         return scrled;
303 }