Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
}