1681 lines · 33.9 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <draw.h>#include <thread.h>#include <cursor.h>#include <mouse.h>#include <keyboard.h>#include <frame.h>#include <fcall.h>#include <plumb.h>#include <9pclient.h>#include "dat.h"#include "fns.h" Buffer	snarfbuf; /* * These functions get called as: * *	fn(et, t, argt, flag1, flag1, flag2, s, n); * * Where the arguments are: * *	et: the Text* in which the executing event (click) occurred *	t: the Text* containing the current selection (Edit, Cut, Snarf, Paste) *	argt: the Text* containing the argument for a 2-1 click. *	e->flag1: from Exectab entry * 	e->flag2: from Exectab entry *	s: the command line remainder (e.g., "x" if executing "Dump x") *	n: length of s  (s is *not* NUL-terminated) */ void doabort(Text*, Text*, Text*, int, int, Rune*, int);void	del(Text*, Text*, Text*, int, int, Rune*, int);void	delcol(Text*, Text*, Text*, int, int, Rune*, int);void	dotfiles(Text*, Text*, Text*, int, int, Rune*, int);void	dump(Text*, Text*, Text*, int, int, Rune*, int);void	edit(Text*, Text*, Text*, int, int, Rune*, int);void	xexit(Text*, Text*, Text*, int, int, Rune*, int);void	fontx(Text*, Text*, Text*, int, int, Rune*, int);void	get(Text*, Text*, Text*, int, int, Rune*, int);void	id(Text*, Text*, Text*, int, int, Rune*, int);void	incl(Text*, Text*, Text*, int, int, Rune*, int);void	indent(Text*, Text*, Text*, int, int, Rune*, int);void	xkill(Text*, Text*, Text*, int, int, Rune*, int);void	local(Text*, Text*, Text*, int, int, Rune*, int);void	look(Text*, Text*, Text*, int, int, Rune*, int);void	newcol(Text*, Text*, Text*, int, int, Rune*, int);void	paste(Text*, Text*, Text*, int, int, Rune*, int);void	put(Text*, Text*, Text*, int, int, Rune*, int);void	putall(Text*, Text*, Text*, int, int, Rune*, int);void	rev(Text*, Text*, Text*, int, int, Rune*, int);void	sendx(Text*, Text*, Text*, int, int, Rune*, int);void	sort(Text*, Text*, Text*, int, int, Rune*, int);void	tab(Text*, Text*, Text*, int, int, Rune*, int);void	zeroxx(Text*, Text*, Text*, int, int, Rune*, int); typedef struct Exectab Exectab;struct Exectab{	Rune	*name;	void	(*fn)(Text*, Text*, Text*, int, int, Rune*, int);	int		mark;	int		flag1;	int		flag2;}; static Rune LAbort[] = { 'A', 'b', 'o', 'r', 't', 0 };static Rune LCut[] = { 'C', 'u', 't', 0 };static Rune LDel[] = { 'D', 'e', 'l', 0 };static Rune LDelcol[] = { 'D', 'e', 'l', 'c', 'o', 'l', 0 };static Rune LDelete[] = { 'D', 'e', 'l', 'e', 't', 'e', 0 };static Rune LDump[] = { 'D', 'u', 'm', 'p', 0 };static Rune LEdit[] = { 'E', 'd', 'i', 't', 0 };static Rune LExit[] = { 'E', 'x', 'i', 't', 0 };static Rune LFont[] = { 'F', 'o', 'n', 't', 0 };static Rune LGet[] = { 'G', 'e', 't', 0 };static Rune LID[] = { 'I', 'D', 0 };static Rune LIncl[] = { 'I', 'n', 'c', 'l', 0 };static Rune LIndent[] = { 'I', 'n', 'd', 'e', 'n', 't', 0 };static Rune LKill[] = { 'K', 'i', 'l', 'l', 0 };static Rune LLoad[] = { 'L', 'o', 'a', 'd', 0 };static Rune LLocal[] = { 'L', 'o', 'c', 'a', 'l', 0 };static Rune LLook[] = { 'L', 'o', 'o', 'k', 0 };static Rune LNew[] = { 'N', 'e', 'w', 0 };static Rune LNewcol[] = { 'N', 'e', 'w', 'c', 'o', 'l', 0 };static Rune LPaste[] = { 'P', 'a', 's', 't', 'e', 0 };static Rune LPut[] = { 'P', 'u', 't', 0 };static Rune LPutall[] = { 'P', 'u', 't', 'a', 'l', 'l', 0 };static Rune LRedo[] = { 'R', 'e', 'd', 'o', 0 };static Rune LRev[] = { 'R', 'e', 'v', 0 };static Rune LSend[] = { 'S', 'e', 'n', 'd', 0 };static Rune LSnarf[] = { 'S', 'n', 'a', 'r', 'f', 0 };static Rune LSort[] = { 'S', 'o', 'r', 't', 0 };static Rune LTab[] = { 'T', 'a', 'b', 0 };static Rune LUndo[] = { 'U', 'n', 'd', 'o', 0 };static Rune LZerox[] = { 'Z', 'e', 'r', 'o', 'x', 0 }; Exectab exectab[] = {	{ LAbort,		doabort,	FALSE,	XXX,		XXX,		},	{ LCut,		cut,		TRUE,	TRUE,	TRUE	},	{ LDel,		del,		FALSE,	FALSE,	XXX		},	{ LDelcol,		delcol,	FALSE,	XXX,		XXX		},	{ LDelete,		del,		FALSE,	TRUE,	XXX		},	{ LDump,		dump,	FALSE,	TRUE,	XXX		},	{ LEdit,		edit,		FALSE,	XXX,		XXX		},	{ LExit,		xexit,	FALSE,	XXX,		XXX		},	{ LFont,		fontx,	FALSE,	XXX,		XXX		},	{ LGet,		get,		FALSE,	TRUE,	XXX		},	{ LID,		id,		FALSE,	XXX,		XXX		},	{ LIncl,		incl,		FALSE,	XXX,		XXX		},	{ LIndent,		indent,	FALSE,	XXX,		XXX		},	{ LKill,		xkill,		FALSE,	XXX,		XXX		},	{ LLoad,		dump,	FALSE,	FALSE,	XXX		},	{ LLocal,		local,	FALSE,	XXX,		XXX		},	{ LLook,		look,		FALSE,	XXX,		XXX		},	{ LNew,		new,		FALSE,	XXX,		XXX		},	{ LNewcol,	newcol,	FALSE,	XXX,		XXX		},	{ LPaste,		paste,	TRUE,	TRUE,	XXX		},	{ LPut,		put,		FALSE,	XXX,		XXX		},	{ LPutall,		putall,	FALSE,	XXX,		XXX		},	{ LRedo,		undo,	FALSE,	FALSE,	XXX		},	{ LRev,		rev,	FALSE,	FALSE,	XXX		},	{ LSend,		sendx,	TRUE,	XXX,		XXX		},	{ LSnarf,		cut,		FALSE,	TRUE,	FALSE	},	{ LSort,		sort,		FALSE,	XXX,		XXX		},	{ LTab,		tab,		FALSE,	XXX,		XXX		},	{ LUndo,		undo,	FALSE,	TRUE,	XXX		},	{ LZerox,		zeroxx,	FALSE,	XXX,		XXX		},	{ nil, 			0,		0,		0,		0		}}; Exectab*lookup(Rune *r, int n){	Exectab *e;	int nr; 	r = skipbl(r, n, &n);	if(n == 0)		return nil;	findbl(r, n, &nr);	nr = n-nr;	for(e=exectab; e->name; e++)		if(runeeq(r, nr, e->name, runestrlen(e->name)) == TRUE)			return e;	return nil;} intisexecc(int c){	if(isfilec(c))		return 1;	return c=='<' || c=='|' || c=='>';} voidexecute(Text *t, uint aq0, uint aq1, int external, Text *argt){	uint q0, q1;	Rune *r, *s;	char *b, *a, *aa;	Exectab *e;	int c, n, f;	Runestr dir; 	q0 = aq0;	q1 = aq1;	if(q1 == q0){	/* expand to find word (actually file name) */		/* if in selection, choose selection */		if(t->q1>t->q0 && t->q0<=q0 && q0<=t->q1){			q0 = t->q0;			q1 = t->q1;		}else{			while(q1<t->file->b.nc && isexecc(c=textreadc(t, q1)) && c!=':')				q1++;			while(q0>0 && isexecc(c=textreadc(t, q0-1)) && c!=':')				q0--;			if(q1 == q0)				return;		}	}	r = runemalloc(q1-q0);	bufread(&t->file->b, q0, r, q1-q0);	e = lookup(r, q1-q0);	if(!external && t->w!=nil && t->w->nopen[QWevent]>0){		f = 0;		if(e)			f |= 1;		if(q0!=aq0 || q1!=aq1){			bufread(&t->file->b, aq0, r, aq1-aq0);			f |= 2;		}		aa = getbytearg(argt, TRUE, TRUE, &a);		if(a){				if(strlen(a) > EVENTSIZE){	/* too big; too bad */				free(aa);				free(a);				warning(nil, "argument string too long\n");				return;			}			f |= 8;		}		c = 'x';		if(t->what == Body)			c = 'X';		n = aq1-aq0;		if(n <= EVENTSIZE)			winevent(t->w, "%c%d %d %d %d %.*S\n", c, aq0, aq1, f, n, n, r);		else			winevent(t->w, "%c%d %d %d 0 \n", c, aq0, aq1, f, n);		if(q0!=aq0 || q1!=aq1){			n = q1-q0;			bufread(&t->file->b, q0, r, n);			if(n <= EVENTSIZE)				winevent(t->w, "%c%d %d 0 %d %.*S\n", c, q0, q1, n, n, r);			else				winevent(t->w, "%c%d %d 0 0 \n", c, q0, q1, n);		}		if(a){			winevent(t->w, "%c0 0 0 %d %s\n", c, utflen(a), a);			if(aa)				winevent(t->w, "%c0 0 0 %d %s\n", c, utflen(aa), aa);			else				winevent(t->w, "%c0 0 0 0 \n", c);		}		free(r);		free(aa);		free(a);		return;	}	if(e){		if(e->mark && seltext!=nil)		if(seltext->what == Body){			seq++;			filemark(seltext->w->body.file);		}		s = skipbl(r, q1-q0, &n);		s = findbl(s, n, &n);		s = skipbl(s, n, &n);		(*e->fn)(t, seltext, argt, e->flag1, e->flag2, s, n);		free(r);		return;	} 	b = runetobyte(r, q1-q0);	free(r);	dir = dirname(t, nil, 0);	if(dir.nr==1 && dir.r[0]=='.'){	/* sigh */		free(dir.r);		dir.r = nil;		dir.nr = 0;	}	aa = getbytearg(argt, TRUE, TRUE, &a);	if(t->w)		incref(&t->w->ref);	run(t->w, b, dir.r, dir.nr, TRUE, aa, a, FALSE);} char*printarg(Text *argt, uint q0, uint q1){	char *buf; 	if(argt->what!=Body || argt->file->name==nil)		return nil;	buf = emalloc(argt->file->nname+32);	if(q0 == q1)		sprint(buf, "%.*S:#%d", argt->file->nname, argt->file->name, q0);	else		sprint(buf, "%.*S:#%d,#%d", argt->file->nname, argt->file->name, q0, q1);	return buf;} char*getarg(Text *argt, int doaddr, int dofile, Rune **rp, int *nrp){	int n;	Expand e;	char *a; 	*rp = nil;	*nrp = 0;	if(argt == nil)		return nil;	a = nil;	textcommit(argt, TRUE);	if(expand(argt, argt->q0, argt->q1, &e)){		free(e.bname);		if(e.nname && dofile){			e.name = runerealloc(e.name, e.nname+1);			if(doaddr)				a = printarg(argt, e.q0, e.q1);			*rp = e.name;			*nrp = e.nname;			return a;		}		free(e.name);	}else{		e.q0 = argt->q0;		e.q1 = argt->q1;	}	n = e.q1 - e.q0;	*rp = runemalloc(n+1);	bufread(&argt->file->b, e.q0, *rp, n);	if(doaddr)		a = printarg(argt, e.q0, e.q1);	*nrp = n;	return a;} char*getbytearg(Text *argt, int doaddr, int dofile, char **bp){	Rune *r;	int n;	char *aa; 	*bp = nil;	aa = getarg(argt, doaddr, dofile, &r, &n);	if(r == nil)		return nil;	*bp = runetobyte(r, n);	free(r);	return aa;} voiddoabort(Text *__0, Text *_0, Text *_1, int _2, int _3, Rune *_4, int _5){	static int n; 	USED(__0);	USED(_0);	USED(_1);	USED(_2);	USED(_3);	USED(_4);	USED(_5); 	if(n++ == 0)		warning(nil, "executing Abort again will call abort()\n");	else		abort();} voidnewcol(Text *et, Text *_0, Text *_1, int _2, int _3, Rune *_4, int _5){	Column *c; 	USED(_0);	USED(_1);	USED(_2);	USED(_3);	USED(_4);	USED(_5); 	c = rowadd(et->row, nil, -1);	if(c)		winsettag(coladd(c, nil, nil, -1));} voiddelcol(Text *et, Text *_0, Text *_1, int _2, int _3, Rune *_4, int _5){	int i;	Column *c;	Window *w; 	USED(_0);	USED(_1);	USED(_2);	USED(_3);	USED(_4);	USED(_5); 	c = et->col;	if(c==nil || colclean(c)==0)		return;	for(i=0; i<c->nw; i++){		w = c->w[i];		if(w->nopen[QWevent]+w->nopen[QWaddr]+w->nopen[QWdata]+w->nopen[QWxdata] > 0){			warning(nil, "can't delete column; %.*S is running an external command\n", w->body.file->nname, w->body.file->name);			return;		}	}	rowclose(et->col->row, et->col, TRUE);} voiddel(Text *et, Text *_0, Text *_1, int flag1, int _2, Rune *_3, int _4){	USED(_0);	USED(_1);	USED(_2);	USED(_3);	USED(_4); 	if(et->col==nil || et->w == nil)		return;	if(flag1 || et->w->body.file->ntext>1 || winclean(et->w, FALSE))		colclose(et->col, et->w, TRUE);} voidrev(Text *et, Text *_1, Text *_2, int _3, int _4, Rune *_5, int _6){	USED(_1);	USED(_2);	USED(_3);	USED(_4);	USED(_4);	USED(_6); 	if (et->w->backwards) 		et->w->backwards = 0;	else 		et->w->backwards = 1;} voidsort(Text *et, Text *_0, Text *_1, int _2, int _3, Rune *_4, int _5){	USED(_0);	USED(_1);	USED(_2);	USED(_3);	USED(_4);	USED(_5); 	if(et->col)		colsort(et->col);} uintseqof(Window *w, int isundo){	/* if it's undo, see who changed with us */	if(isundo)		return w->body.file->seq;	/* if it's redo, see who we'll be sync'ed up with */	return fileredoseq(w->body.file);} voidundo(Text *et, Text *_0, Text *_1, int flag1, int _2, Rune *_3, int _4){	int i, j;	Column *c;	Window *w;	uint seq; 	USED(_0);	USED(_1);	USED(_2);	USED(_3);	USED(_4); 	if(et==nil || et->w== nil)		return;	seq = seqof(et->w, flag1);	if(seq == 0){		/* nothing to undo */		return;	}	/*	 * Undo the executing window first. Its display will update. other windows	 * in the same file will not call show() and jump to a different location in the file.	 * Simultaneous changes to other files will be chaotic, however.	 */	winundo(et->w, flag1);	for(i=0; i<row.ncol; i++){		c = row.col[i];		for(j=0; j<c->nw; j++){			w = c->w[j];			if(w == et->w)				continue;			if(seqof(w, flag1) == seq)				winundo(w, flag1);		}	}} char*getname(Text *t, Text *argt, Rune *arg, int narg, int isput){	char *s;	Rune *r;	int i, n, promote;	Runestr dir; 	getarg(argt, FALSE, TRUE, &r, &n);	promote = FALSE;	if(r == nil)		promote = TRUE;	else if(isput){		/* if are doing a Put, want to synthesize name even for non-existent file */		/* best guess is that file name doesn't contain a slash */

Lines 1–500 of 1681.