]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/abaco/exec.c
abacos tcs.h is automatically generated
[plan9front.git] / sys / src / cmd / abaco / exec.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 void    del(Text *, Text *, int, int, Rune *, int);
16 void    delcol(Text *, Text *, int, int, Rune *, int);
17 void    cut(Text *, Text *, int, int, Rune *, int);
18 void    exit(Text *, Text *, int, int, Rune *, int);
19 void    get(Text *, Text *, int, int, Rune *, int);
20 void    go(Text *,Text *,  int, int, Rune *, int);
21 void    google(Text *,Text *,  int, int, Rune *, int);
22 void    new(Text*, Text *, int, int, Rune *, int);
23 void    newcol(Text*, Text *, int, int, Rune *, int);
24 void    paste(Text *, Text *, int, int, Rune *, int);
25 void    sort(Text *, Text *, int, int, Rune *, int);
26 void    stop(Text *, Text *, int, int, Rune *, int);
27 void    debug(Text *, Text *, int, int, Rune *, int);
28
29 typedef struct Exectab Exectab;
30 struct Exectab
31 {
32         Rune    *name;
33         void    (*fn)(Text *, Text *, int, int, Rune *, int);
34         int             flag1;
35         int             flag2;
36 };
37
38 Exectab exectab[] = {
39         { L"Back",              go,             FALSE,  XXX             },
40         { L"Cut",               cut,            TRUE,   TRUE    },
41         { L"Debug",     debug,  XXX,            XXX             },
42         { L"Del",               del,            XXX,            XXX             },
43         { L"Delcol",    delcol, FALSE,  TRUE    },
44         { L"Exit",              exit,           XXX,            XXX             },
45         { L"Get",               get,            XXX,            XXX             },
46         { L"Google",    google, XXX,            XXX             },
47         { L"New",               new,            XXX,            XXX             },
48         { L"Newcol",    newcol, XXX,            XXX             },
49         { L"Next",              go,             TRUE,   XXX             },
50         { L"Paste",             paste,  TRUE,   XXX             },
51         { L"Snarf",             cut,            TRUE,   FALSE   },
52         { L"Stop",              stop,           XXX,            XXX             },
53         { L"Sort",              sort,           XXX,            XXX             },
54         { nil,                  nil,            0,              0               },
55 };
56
57 static
58 Exectab*
59 lookup(Rune *r, int n)
60 {
61         Exectab *e;
62         int nr;
63
64         r = skipbl(r, n, &n);
65         if(n == 0)
66                 return nil;
67         findbl(r, n, &nr);
68         nr = n-nr;
69         for(e=exectab; e->name; e++)
70                 if(runeeq(r, nr, e->name, runestrlen(e->name)) == TRUE)
71                         return e;
72         return nil;
73 }
74
75 int
76 isexecc(int c)
77 {
78         if(isalnum(c))
79                 return 1;
80         return c=='<' || c=='|' || c=='>';
81 }
82
83 void
84 execute(Text *t, uint aq0, uint aq1, Text *)
85 {
86         uint q0, q1;
87         Rune *r, *s;
88         Exectab *e;
89         int c, n;
90
91         q0 = aq0;
92         q1 = aq1;
93         if(q1 == q0){   /* expand to find word (actually file name) */
94                 /* if in selection, choose selection */
95                 if(t->q1>t->q0 && t->q0<=q0 && q0<=t->q1){
96                         q0 = t->q0;
97                         q1 = t->q1;
98                 }else{
99                         while(q1<t->rs.nr && isexecc(c=t->rs.r[q1]) && c!=':')
100                                 q1++;
101                         while(q0>0 && isexecc(c=t->rs.r[q0-1]) && c!=':')
102                                 q0--;
103                         if(q1 == q0)
104                                 return;
105                 }
106         }
107         r = runemalloc(q1-q0);
108         runemove(r, t->rs.r+q0, q1-q0);
109         e = lookup(r, q1-q0);
110         if(e){
111                 s = skipbl(r, q1-q0, &n);
112                 s = findbl(s, n, &n);
113                 s = skipbl(s, n, &n);
114                 (*e->fn)(t, seltext, e->flag1, e->flag2, s, n);
115         }
116         free(r);
117 }
118
119 void
120 newcol(Text *et, Text *, int, int, Rune *, int)
121 {
122         Column *c;
123
124         c = rowadd(et->row, nil, -1);
125         if(c)
126                 winsettag(coladd(c, nil, nil, -1));
127 }
128
129 void
130 delcol(Text *t, Text *, int, int, Rune *, int)
131 {
132         Column *c;
133
134         c = t->col;
135         if(c==nil || colclean(c)==0)
136                 return;
137
138         rowclose(c->row, c, TRUE);
139 }
140
141 void
142 del(Text *et, Text *, int flag1, int, Rune *, int)
143 {
144         if(et->w==nil)
145                 return;
146
147         if(flag1 || winclean(et->w, FALSE))
148                 colclose(et->col, et->w, TRUE);
149 }
150
151 void
152 sort(Text *et, Text *, int, int, Rune *, int)
153 {
154         if(et->col)
155                 colsort(et->col);
156 }
157
158 void
159 exit(Text *, Text *, int, int, Rune *, int)
160 {
161         sendul(cexit, 0);
162         threadexits(nil);
163 }
164
165 void
166 debug(Text *, Text *, int, int, Rune *, int)
167 {
168         Column *c;
169         int i, j;
170
171         for(j=0; j<row.ncol; j++){
172                 c = row.col[j];
173                 for(i=0; i<c->nw; i++){
174                         fprint(2, "Col: %d; Win: %d\n", j, i);
175                         windebug(c->w[i]);
176                 }
177         }
178 }
179
180 void
181 stop(Text *t, Text *, int, int, Rune *, int)
182 {
183         if(t==nil || t->w==nil)
184                 return;
185
186         pageabort(&t->w->page);
187 }
188
189 void
190 get(Text *t, Text *, int, int, Rune *, int)
191 {
192         Window *w;
193         int dohist;
194
195         if(t==nil || t->w==nil)
196                 return;
197         w = t->w;
198         if(w->url.rs.nr == 0)
199                 return;
200
201         dohist = FALSE;
202         if(w->page.url==nil || runestreq(w->page.url->act, w->url.rs)==FALSE)
203                 dohist = TRUE;
204
205         pageget(&w->page, &w->url.rs, nil, HGet, dohist);
206 }
207
208 void
209 go(Text *et, Text *t, int isnext, int, Rune *, int)
210 {
211         if(et!=nil && et->w!=nil)
212                 t = et;
213         if(t==nil || t->w==nil)
214                 return;
215
216         wingohist(t->w, isnext);
217 }
218
219 void
220 cut(Text *, Text *t, int dosnarf, int docut, Rune *, int)
221 {
222         Runestr rs;
223         uint u;
224
225         if(selpage){
226                 if(dosnarf && !docut && !eqpt(selpage->top, selpage->bot))
227                         pagesnarf(selpage);
228                 return;
229         }
230         if(t==nil){
231                 /* can only happen if seltext == nil */
232                 return;
233         }
234         if(t->q0 > t->q1){
235                 u = t->q0;
236                 t->q0 = t->q1;
237                 t->q1 =u;
238         }
239
240         if(t->q0 == t->q1)
241                 return;
242
243         if(dosnarf){
244                 rs.nr = t->q1-t->q0;
245                 rs.r = runemalloc(rs.nr);
246                 runemove(rs.r, t->rs.r+t->q0, rs.nr);
247                 putsnarf(&rs);
248                 closerunestr(&rs);
249         }
250         if(docut){
251                 textdelete(t, t->q0, t->q1);
252                 textsetselect(t, t->q0, t->q0);
253                 if(t->w)
254                         textscrdraw(t);
255         }else if(dosnarf)       /* Snarf command */
256                 argtext = t;
257 }
258
259 void
260 paste(Text *, Text *t, int selectall, int, Rune *, int)
261 {
262         Runestr rs;
263         uint q1;
264
265         if(t == nil)
266                 return;
267
268         getsnarf(&rs);
269         if(rs.nr == 0)
270                 return;
271
272         cut(t, t, FALSE, TRUE, nil, 0);
273         textinsert(t, t->q0, rs.r, rs.nr);
274         q1 = t->q0+rs.nr;
275         if(selectall)
276                 textsetselect(t, t->q0, q1);
277         else
278                 textsetselect(t, q1, q1);
279         if(t->w)
280                 textscrdraw(t);
281
282         closerunestr(&rs);
283 }
284
285 typedef struct  Expand Expand;
286
287 struct Expand
288 {
289         uint    q0;
290         uint    q1;
291         Rune    *name;
292         int     nname;
293         int     jump;
294         union{
295                 Text    *at;
296                 Rune    *ar;
297         };
298         int     (*agetc)(void*, uint);
299         int     a0;
300         int     a1;
301 };
302
303 int
304 expand(Text *t, uint q0, uint q1, Expand *e)
305 {
306         memset(e, 0, sizeof *e);
307
308         /* if in selection, choose selection */
309         e->jump = TRUE;
310         if(q1==q0 && t->q1>t->q0 && t->q0<=q0 && q0<=t->q1){
311                 q0 = t->q0;
312                 q1 = t->q1;
313                 if(t->what == Tag)
314                         e->jump = FALSE;
315         }
316         if(q0 == q1){
317                 while(q1<t->rs.nr && isalnum(t->rs.r[q1]))
318                         q1++;
319                 while(q0>0 && isalnum(t->rs.r[q0-1]))
320                         q0--;
321         }
322         e->q0 = q0;
323         e->q1 = q1;
324         return q1 > q0;
325 }
326
327 void
328 look3(Text *t, uint q0, uint q1)
329 {
330         Expand e;
331         Text *ct;
332         Runestr rs;
333         char buf[32];
334         Rune *r, c;
335         uint p;
336         int n;
337
338         ct = seltext;
339         if(ct == nil)
340                 ct = seltext = t;
341         if(expand(t, q0, q1, &e) == FALSE)
342                 return;
343         if(plumbsendfd >= 0){
344                 /* send whitespace-delimited word to plumber */
345                 buf[0] = '\0';
346                 if(q1 == q0){
347                         if(t->q1>t->q0 && t->q0<=q0 && q0<=t->q1){
348                                 q0 = t->q0;
349                                 q1 = t->q1;
350                         }else{
351                                 p = q0;
352                                 while(q0>0 && (c=t->rs.r[q0-1])!=L' ' && c!=L'\t' && c!=L'\n')
353                                         q0--;
354                                 while(q1<t->rs.nr && (c=t->rs.r[q1])!=L' ' && c!=L'\t' && c!=L'\n')
355                                         q1++;
356                                 if(q1 == q0)
357                                         return;
358                                 sprint(buf, "click=%d", p-q0);
359                         }
360                 }
361                 rs.r = runemalloc(q1-q0);
362                 runemove(rs.r, t->rs.r+q0, q1-q0);
363                 rs.nr = q1-q0;
364                 if(plumbrunestr(&rs, buf) >= 0){
365                         closerunestr(&rs);
366                         return;
367                 }
368                 /* plumber failed to match; fall through */
369         }
370         if(t == ct)
371                 textsetselect(ct, e.q1, e.q1);
372         n = e.q1 - e.q0;
373         r = runemalloc(n);
374         runemove(r, t->rs.r+e.q0, n);
375         if(search(ct, r, n) && e.jump)
376                 moveto(mousectl, addpt(frptofchar(ct, ct->p0), Pt(4, ct->font->height-4)));
377
378         free(r);
379 }
380
381 int
382 search(Text *ct, Rune *r, uint n)
383 {
384         uint q, nb, maxn;
385         int around;
386         Rune *s, *b, *c;
387
388         if(n==0 || n>ct->rs.nr || 2*n>RBUFSIZE)
389                 return FALSE;
390
391         maxn = max(n*2, RBUFSIZE);
392         s = runemalloc(RBUFSIZE);
393         b = s;
394         nb = 0;
395         b[nb] = 0;
396         around = 0;
397         q = ct->q1;
398         for(;;){
399                 if(q >= ct->rs.nr){
400                         q = 0;
401                         around = 1;
402                         nb = 0;
403                         b[nb] = 0;
404                 }
405                 if(nb > 0){
406                         c = runestrchr(b, r[0]);
407                         if(c == nil){
408                                 q += nb;
409                                 nb = 0;
410                                 b[nb] = 0;
411                                 if(around && q>=ct->q1)
412                                         break;
413                                 continue;
414                         }
415                         q += (c-b);
416                         nb -= (c-b);
417                         b = c;
418                 }
419                 /* reload if buffer covers neither string nor rest of file */
420                 if(nb<n && nb!=ct->rs.nr-q){
421                         nb = ct->rs.nr-q;
422                         if(nb >= maxn)
423                                 nb = maxn-1;
424                         runemove(s, ct->rs.r+q, nb);
425                         b = s;
426                         b[nb] = '\0';
427                 }
428                 /* this runeeq is fishy but the null at b[nb] makes it safe */
429                 if(runeeq(b, n, r, n) == TRUE){
430                         if(ct->w)
431                                 textshow(ct, q, q+n, 1);
432                         else{
433                                 ct->q0 = q;
434                                 ct->q1 = q+n;
435                         }
436                         seltext = ct;
437                         free(s);
438                         return TRUE;
439                 }
440                 if(around && q>=ct->q1)
441                         break;
442                 --nb;
443                 b++;
444                 q++;
445         }
446         free(s);
447         return FALSE;
448 }
449
450 Window*
451 lookpage(Rune *s, int n)
452 {
453         int i, j;
454         Window *w;
455         Column *c;
456         Page *p;
457
458         /* avoid terminal slash on directories */
459         if(n>1 && s[n-1] == '/')
460                 --n;
461         for(j=0; j<row.ncol; j++){
462                 c = row.col[j];
463                 for(i=0; i<c->nw; i++){
464                         w = c->w[i];
465                         p = &w->page;
466                         if(p->url && runeeq(p->url->src.r, p->url->src.nr, s, n))
467                                 if(w->col != nil)
468                                         return w;
469                 }
470         }
471         return nil;
472 }
473
474 Window *
475 openpage(Page *p, Runestr *rs)
476 {
477         Window *w;
478
479         if(!validurl(rs->r))
480                 return nil;
481
482         w = lookpage(rs->r, rs->nr);
483         if(w){
484                 p = &w->page;
485                 if(!p->col->safe && Dy(p->r)==0) /* window is obscured by full-column window */
486                         colgrow(p->col, p->col->w[0], 1);
487         }else{
488                 w = makenewwindow(p);
489                 winsettag(w);
490                 pageget(&w->page, rs, nil, HGet, TRUE);
491         }
492         return w;
493 }
494
495 void
496 plumblook(Plumbmsg *m)
497 {
498         Runestr rs;
499
500         if(m->ndata >= BUFSIZE){
501                 fprint(2, "insanely long file name (%d bytes) in plumb message (%.32s...)\n", m->ndata, m->data);
502                 return;
503         }
504         if(m->data[0] == '\0')
505                 return;
506
507         bytetorunestr(m->data, &rs);
508         openpage(nil, &rs);
509         closerunestr(&rs);
510 }
511
512 void
513 new(Text *et, Text *, int, int, Rune *, int)
514 {
515         if(et->col != nil)
516                 winsettag(coladd(et->col, nil, nil, -1));
517 }
518
519 void
520 google(Text *, Text *, int, int, Rune *arg, int narg)
521 {
522         Runestr rs;
523         Rune *s;
524
525         s = ucvt(arg);
526         rs.r = runesmprint("http://www.google.com/search?hl=en&ie=UTF-8&q=%.*S", narg, s);
527         rs.nr = runestrlen(rs.r);
528         openpage(nil, &rs);
529         free(s);
530         closerunestr(&rs);
531 }