henesyinit from p9fce6d0435 years agoHistory
1039 lines · 20.5 KB · Text
RawDownload
#include <alef.h>#include <libg.h>#include <frame.h>#include <fcall.h>#include "dat.h"#include "fns.h" Buffer	snarfbuf; void	del(Text*, Text*, Text*, int, int, Rune*, int);void	delcol(Text*, Text*, Text*, int, int, Rune*, int);void	dump(Text*, Text*, Text*, int, int, Rune*, int);void	exit(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	kill(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	send(Text*, Text*, Text*, int, int, Rune*, int);void	sort(Text*, Text*, Text*, int, int, Rune*, int);void	undo(Text*, Text*, Text*, int, int, Rune*, int);void	zeroxx(Text*, Text*, Text*, int, int, Rune*, int); aggr Exectab{	Rune	*name;	void	(*fn)(Text*, Text*, Text*, int, int, Rune*, int);	int		mark;	int		flag1;	int		flag2;}; Exectab exectab[] = {	{ $"Cut",		cut,		TRUE,	TRUE,	TRUE	},	{ $"Del",		del,		FALSE,	FALSE,	XXX		},	{ $"Delcol",	delcol,	FALSE,	XXX,		XXX		},	{ $"Delete",	del,		FALSE,	TRUE,	XXX		},	{ $"Dump",	dump,	FALSE,	TRUE,	XXX		},	{ $"Exit",		exit,		FALSE,	XXX,		XXX		},	{ $"Font",		fontx,	FALSE,	XXX,		XXX		},	{ $"Get",		get,		FALSE,	TRUE,	XXX		},	{ $"ID",		id,		FALSE,	XXX,		XXX		},	{ $"Incl",		incl,		FALSE,	XXX,		XXX		},	{ $"Kill",		kill,		FALSE,	XXX,		XXX		},	{ $"Load",		dump,	FALSE,	FALSE,	XXX		},	{ $"Local",		local,	FALSE,	XXX,		XXX		},	{ $"Look",		look,		FALSE,	XXX,		XXX		},	{ $"New",		new,		FALSE,	XXX,		XXX		},	{ $"Newcol",	newcol,	FALSE,	XXX,		XXX		},	{ $"Paste",		paste,	TRUE,	XXX,		XXX		},	{ $"Put",		put,		FALSE,	XXX,		XXX		},	{ $"Putall",	putall,	FALSE,	XXX,		XXX		},	{ $"Redo",		undo,	FALSE,	FALSE,	XXX		},	{ $"Send",		send,	TRUE,	XXX,		XXX		},	{ $"Snarf",		cut,		FALSE,	TRUE,	FALSE	},	{ $"Sort",		sort,		FALSE,	XXX,		XXX		},	{ $"Undo",		undo,	FALSE,	TRUE,	XXX		},	{ $"Zerox",	zeroxx,	FALSE,	XXX,		XXX		},	{ nil, 			nil,		0,		0,		0		},}; Exectab*lookup(Rune *r, int n){	Exectab *e;	int nr; 	(r, n) = skipbl(r, n);	if(n == 0)		return nil;	(nil, nr) = findbl(r, n);	nr = n-nr;	for(e=exectab; e->name; e++)		if(runeeq(r, nr, e->name, runestrlen(e->name)) == TRUE)			return e;	return nil;} voidexecute(Text *t, uint aq0, uint aq1, int external, Text *argt){	uint q0, q1;	Rune *r, *s, *dir;	byte *b, *a, *aa;	Exectab *e;	int c, n, f; 	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->nc && isfilec(c=t->readc(q1)) && c!=':')				q1++;			while(q0>0 && isfilec(c=t->readc(q0-1)) && c!=':')				q0--;			if(q1 == q0)				return;		}	}	r = runemalloc(q1-q0);	t->file->read(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){			t->file->read(aq0, r, aq1-aq0);			f |= 2;		}		(aa, a) = getbytearg(argt, TRUE, TRUE);		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)			t->w->event("%c%d %d %d %d %.*S\n", c, aq0, aq1, f, n, n, r);		else			t->w->event("%c%d %d %d 0 \n", c, aq0, aq1, f, n);		if(q0!=aq0 || q1!=aq1){			n = q1-q0;			t->file->read(q0, r, n);			if(n <= EVENTSIZE)				t->w->event("%c%d %d 0 %d %.*S\n", c, q0, q1, n, n, r);			else				t->w->event("%c%d %d 0 0 \n", c, q0, q1, n);		}		if(a){			t->w->event("%c0 0 0 %d %s\n", c, utflen(a), a);			if(aa)				t->w->event("%c0 0 0 %d %s\n", c, utflen(aa), aa);			else				t->w->event("%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++;			seltext->w->body.file->mark();		}		(s, n) = skipbl(r, q1-q0);		(s, n) = findbl(s, n);		(s, n) = skipbl(s, n);		(*e->fn)(t, seltext, argt, e->flag1, e->flag2, s, n);		free(r);		return;	} 	b = runetobyte(r, q1-q0);	free(r);	(dir, n) = dirname(t, nil, 0);	if(n==1 && dir[0]=='.'){	/* sigh */		free(dir);		dir = nil;		n = 0;	}	(aa, a) = getbytearg(argt, TRUE, TRUE);	if(t->w)		t->w->inc();	proc run(t->w, b, dir, n, TRUE, aa, a);} byte*printarg(Text *argt, uint q0, uint q1){	byte *buf; 	if(argt->what!=Body || argt->file->name==nil)		return nil;	buf = malloc(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;} (byte*, Rune*, int)getarg(Text *argt, int doaddr, int dofile){	Rune *r;	int n;	Expand e;	byte *a; 	if(argt == nil)		return (nil, nil, 0);	a = nil;	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);			return (a, e.name, e.nname);		}		free(e.name);	}else{		e.q0 = argt->q0;		e.q1 = argt->q1;	}	n = e.q1 - e.q0;	r = runemalloc(n+1);	argt->file->read(e.q0, r, n);	if(doaddr)		a = printarg(argt, e.q0, e.q1);	return(a, r, n);} (byte*, byte*)getbytearg(Text *argt, int doaddr, int dofile){	Rune *r;	int n;	byte *b, *aa; 	(aa, r, n) = getarg(argt, doaddr, dofile);	if(r == nil)		return (nil, nil);	b = runetobyte(r, n);	free(r);	return (aa, b);} voidnewcol(Text *et, Text*, Text*, int, int, Rune*, int){	Column *c; 	c = et->row->add(nil, -1);	if(c)		c->add(nil, nil, -1)->settag();} voiddelcol(Text *et, Text*, Text*, int, int, Rune*, int){	if(et->col!=nil && et->col->clean())		et->col->row->close(et->col, TRUE);} voiddel(Text *et, Text*, Text*, int flag1, int, Rune*, int){	if(et->col==nil || et->w == nil)		return;	if(flag1 || et->w->body.file->ntext>1 || et->w->clean(FALSE))		et->col->close(et->w, TRUE);} voidsort(Text *et, Text*, Text*, int, int, Rune*, int){	if(et->col)		et->col->sort();} voidundo(Text *et, Text*, Text*, int flag1, int, Rune*, int){	if(et)		et->w->undo(flag1);} byte*getname(Text *t, Text *argt, Rune *arg, int narg, int isput){	byte *s;	Rune *r, *dir;	int i, n, ndir, promote; 	(nil, r, n) = getarg(argt, FALSE, TRUE);	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 */		promote = TRUE;		for(i=0; i<n; i++)			if(r[i] == '/'){				promote = FALSE;				break;			}		if(promote){			t = argt;			arg = r;			narg = n;		}	}	if(promote){		n = narg;		if(n <= 0){			s = runetobyte(t->file->name, t->file->nname);			return s;		}		/* prefix with directory name if necessary */		dir = nil;		ndir = 0;		if(n>0 && arg[0]!='/'){			(dir, ndir) = dirname(t, nil, 0);			if(n==1 && dir[0]=='.'){	/* sigh */				free(dir);				dir = nil;				ndir = 0;			}		}		if(dir){			r = runemalloc(ndir+n+1);			runemove(r, dir, ndir);			free(dir);			runemove(r+ndir, arg, n);			n += ndir;		}else{			r = runemalloc(n+1);			runemove(r, arg, n);		}	}	s = runetobyte(r, n);	free(r);	if(strlen(s) == 0){		free(s);		s = nil;	}	return s;} voidzeroxx(Text *et, Text *t, Text*, int, int, Rune*, int){	Window *nw;	int c, locked; 	locked = FALSE;	if(t!=nil && t->w!=nil && t->w!=et->w){		locked = TRUE;		c = 'M';		if(et->w)			c = et->w->owner;		t->w->lock(c);	}	if(t == nil)		t = et;	if(t==nil || t->w==nil)		return;	t = &t->w->body;	if(t->w->isdir)		warning(nil, "%.*S is a directory; Zerox illegal\n", t->file->nname, t->file->name);	else{		nw = t->w->col->add(nil, t->w, -1);		/* ugly: fix locks so w->unlock works */		nw->lock1(t->w->owner);	}	if(locked)		t->w->unlock();} voidget(Text *et, Text *t, Text *argt, int flag1, int, Rune *arg, int narg){	byte *name;	Rune *r;	int i, n, dirty;	Window *w;	Text *u;	Dir d; 	if(flag1)		if(et==nil || et->w==nil)			return;	if(!et->w->isdir && (et->w->body.file->nc>0 && !et->w->clean(TRUE)))		return;	w = et->w;	t = &w->body;	name = getname(t, argt, arg, narg, FALSE);	if(name == nil){		warning(nil, "no file name\n");		return;	}	if(t->file->ntext>1 && dirstat(name, &d)==0 && d.qid.path & CHDIR){		warning(nil, "%s is a directory; can't read with multiple windows on it\n", name);		return;	}	(r, n) = bytetorune(name);	for(i=0; i<t->file->ntext; i++){		u = t->file->text[i];		/* second and subsequent calls with zero an already empty buffer, but OK */		u->reset();		u->w->dirfree();	}	t->load(0, name);	if(runeeq(r, n, t->file->name, t->file->nname)){		t->file->mod = FALSE;		dirty = FALSE;	}else{		t->file->mod = TRUE;		dirty = TRUE;	}	for(i=0; i<t->file->ntext; i++)		t->file->text[i]->w->dirty = dirty;	free(name);	free(r);	w->settag();	for(i=0; i<t->file->ntext; i++){		u = t->file->text[i];		u->w->tag.setselect(u->w->tag.file->nc, u->w->tag.file->nc);		u->scrdraw();	}} voidput(Text *et, Text *t, Text *argt, int, int, Rune *arg, int narg){	uint q0, q1, n, m, nname;	Rune *r, *namer;	byte *s, *name;	Window *w;	int i, fd;	Dir d; 	if(et==nil || et->w==nil || et->w->isdir)		return;	w = et->w;	t = &w->body;	rescue{		free(name);		free(namer);		return;	}	name = getname(t, argt, arg, narg, TRUE);	if(name == nil){		warning(nil, "no file name\n");		return;	}	(namer, nname) = bytetorune(name);	fd = create(name, OWRITE, 0666);	if(fd < 0){		warning(nil, "can't create file %s: %r\n", name);		raise;	}	r = fbufalloc();	s = fbufalloc();	rescue{		fbuffree(s);		fbuffree(r);		close(fd);		raise;	}	if(dirfstat(fd, &d)>=0 && (d.mode&CHAPPEND) && d.length>0){		warning(nil, "%s not written; file is append only\n", name);		raise;	}	q0 = 0;	q1 = t->file->nc;	while(q0 < q1){		n = q1 - q0;		if(n > BUFSIZE/UTFmax)			n = BUFSIZE/UTFmax;		t->file->read(q0, r, n);		m = snprint(s, BUFSIZE+1, "%.*S", n, r);		if(write(fd, s, m) != m){			warning(nil, "can't write file %s: %r\n", name);			raise;		}		q0 += n;	}	if(runeeq(namer, nname, t->file->name, t->file->nname)){		t->file->mod = FALSE;		w->dirty = FALSE;	}	for(i=0; i<t->file->ntext; i++){		t->file->text[i]->w->putseq = t->file->seq;		t->file->text[i]->w->dirty = w->dirty;	}	fbuffree(s);	fbuffree(r);

Lines 1–500 of 1039.