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);
29 typedef struct Exectab Exectab;
33 void (*fn)(Text *, Text *, int, int, Rune *, int);
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 },
59 lookup(Rune *r, int n)
69 for(e=exectab; e->name; e++)
70 if(runeeq(r, nr, e->name, runestrlen(e->name)) == TRUE)
80 return c=='<' || c=='|' || c=='>';
84 execute(Text *t, uint aq0, uint aq1, Text *)
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){
99 while(q1<t->rs.nr && isexecc(c=t->rs.r[q1]) && c!=':')
101 while(q0>0 && isexecc(c=t->rs.r[q0-1]) && c!=':')
107 r = runemalloc(q1-q0);
108 runemove(r, t->rs.r+q0, q1-q0);
109 e = lookup(r, q1-q0);
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);
120 newcol(Text *et, Text *, int, int, Rune *, int)
124 c = rowadd(et->row, nil, -1);
126 winsettag(coladd(c, nil, nil, -1));
130 delcol(Text *t, Text *, int, int, Rune *, int)
135 if(c==nil || colclean(c)==0)
138 rowclose(c->row, c, TRUE);
142 del(Text *et, Text *, int flag1, int, Rune *, int)
147 if(flag1 || winclean(et->w, FALSE))
148 colclose(et->col, et->w, TRUE);
152 sort(Text *et, Text *, int, int, Rune *, int)
159 exit(Text *, Text *, int, int, Rune *, int)
166 debug(Text *, Text *, int, int, Rune *, int)
171 for(j=0; j<row.ncol; j++){
173 for(i=0; i<c->nw; i++){
174 fprint(2, "Col: %d; Win: %d\n", j, i);
181 stop(Text *t, Text *, int, int, Rune *, int)
183 if(t==nil || t->w==nil)
186 pageabort(&t->w->page);
190 get(Text *t, Text *, int, int, Rune *, int)
195 if(t==nil || t->w==nil)
198 if(w->url.rs.nr == 0)
202 if(w->page.url==nil || runestreq(w->page.url->act, w->url.rs)==FALSE)
205 pageget(&w->page, &w->url.rs, nil, HGet, dohist);
209 go(Text *et, Text *t, int isnext, int, Rune *, int)
211 if(et!=nil && et->w!=nil)
213 if(t==nil || t->w==nil)
216 wingohist(t->w, isnext);
220 cut(Text *, Text *t, int dosnarf, int docut, Rune *, int)
226 if(dosnarf && !docut && !eqpt(selpage->top, selpage->bot))
231 /* can only happen if seltext == nil */
245 rs.r = runemalloc(rs.nr);
246 runemove(rs.r, t->rs.r+t->q0, rs.nr);
251 textdelete(t, t->q0, t->q1);
252 textsetselect(t, t->q0, t->q0);
255 }else if(dosnarf) /* Snarf command */
260 paste(Text *, Text *t, int selectall, int, Rune *, int)
272 cut(t, t, FALSE, TRUE, nil, 0);
273 textinsert(t, t->q0, rs.r, rs.nr);
276 textsetselect(t, t->q0, q1);
278 textsetselect(t, q1, q1);
285 typedef struct Expand Expand;
298 int (*agetc)(void*, uint);
304 expand(Text *t, uint q0, uint q1, Expand *e)
306 memset(e, 0, sizeof *e);
308 /* if in selection, choose selection */
310 if(q1==q0 && t->q1>t->q0 && t->q0<=q0 && q0<=t->q1){
317 while(q1<t->rs.nr && isalnum(t->rs.r[q1]))
319 while(q0>0 && isalnum(t->rs.r[q0-1]))
328 look3(Text *t, uint q0, uint q1)
341 if(expand(t, q0, q1, &e) == FALSE)
343 if(plumbsendfd >= 0){
344 /* send whitespace-delimited word to plumber */
347 if(t->q1>t->q0 && t->q0<=q0 && q0<=t->q1){
352 while(q0>0 && (c=t->rs.r[q0-1])!=L' ' && c!=L'\t' && c!=L'\n')
354 while(q1<t->rs.nr && (c=t->rs.r[q1])!=L' ' && c!=L'\t' && c!=L'\n')
358 sprint(buf, "click=%d", p-q0);
361 rs.r = runemalloc(q1-q0);
362 runemove(rs.r, t->rs.r+q0, q1-q0);
364 if(plumbrunestr(&rs, buf) >= 0){
368 /* plumber failed to match; fall through */
371 textsetselect(ct, e.q1, e.q1);
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)));
382 search(Text *ct, Rune *r, uint n)
388 if(n==0 || n>ct->rs.nr || 2*n>RBUFSIZE)
391 maxn = max(n*2, RBUFSIZE);
392 s = runemalloc(RBUFSIZE);
406 c = runestrchr(b, r[0]);
411 if(around && q>=ct->q1)
419 /* reload if buffer covers neither string nor rest of file */
420 if(nb<n && nb!=ct->rs.nr-q){
424 runemove(s, ct->rs.r+q, nb);
428 /* this runeeq is fishy but the null at b[nb] makes it safe */
429 if(runeeq(b, n, r, n) == TRUE){
431 textshow(ct, q, q+n, 1);
440 if(around && q>=ct->q1)
451 lookpage(Rune *s, int n)
458 /* avoid terminal slash on directories */
459 if(n>1 && s[n-1] == '/')
461 for(j=0; j<row.ncol; j++){
463 for(i=0; i<c->nw; i++){
466 if(p->url && runeeq(p->url->src.r, p->url->src.nr, s, n))
475 openpage(Page *p, Runestr *rs)
482 w = lookpage(rs->r, rs->nr);
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);
488 w = makenewwindow(p);
490 pageget(&w->page, rs, nil, HGet, TRUE);
496 plumblook(Plumbmsg *m)
500 if(m->ndata >= BUFSIZE){
501 fprint(2, "insanely long file name (%d bytes) in plumb message (%.32s...)\n", m->ndata, m->data);
504 if(m->data[0] == '\0')
507 bytetorunestr(m->data, &rs);
513 new(Text *et, Text *, int, int, Rune *, int)
516 winsettag(coladd(et->col, nil, nil, -1));
520 google(Text *, Text *, int, int, Rune *arg, int narg)
526 rs.r = runesmprint("http://www.google.com/search?hl=en&ie=UTF-8&q=%.*S", narg, s);
527 rs.nr = runestrlen(rs.r);