680 lines · 11.8 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 "dat.h"#include "edit.h"#include "fns.h" static char	linex[]="\n";static char	wordx[]=" \t\n";struct cmdtab cmdtab[]={/*	cmdc	text	regexp	addr	defcmd	defaddr	count	token	 fn	*/	'\n',	0,	0,	0,	0,	aDot,	0,	0,	nl_cmd,	'a',	1,	0,	0,	0,	aDot,	0,	0,	a_cmd,	'b',	0,	0,	0,	0,	aNo,	0,	linex,	b_cmd,	'c',	1,	0,	0,	0,	aDot,	0,	0,	c_cmd,	'd',	0,	0,	0,	0,	aDot,	0,	0,	d_cmd,	'e',	0,	0,	0,	0,	aNo,	0,	wordx,	e_cmd,	'f',	0,	0,	0,	0,	aNo,	0,	wordx,	f_cmd,	'g',	0,	1,	0,	'p',	aDot,	0,	0,	g_cmd,	'i',	1,	0,	0,	0,	aDot,	0,	0,	i_cmd,	'm',	0,	0,	1,	0,	aDot,	0,	0,	m_cmd,	'p',	0,	0,	0,	0,	aDot,	0,	0,	p_cmd,	'r',	0,	0,	0,	0,	aDot,	0,	wordx,	e_cmd,	's',	0,	1,	0,	0,	aDot,	1,	0,	s_cmd,	't',	0,	0,	1,	0,	aDot,	0,	0,	m_cmd,	'u',	0,	0,	0,	0,	aNo,	2,	0,	u_cmd,	'v',	0,	1,	0,	'p',	aDot,	0,	0,	g_cmd,	'w',	0,	0,	0,	0,	aAll,	0,	wordx,	w_cmd,	'x',	0,	1,	0,	'p',	aDot,	0,	0,	x_cmd,	'y',	0,	1,	0,	'p',	aDot,	0,	0,	x_cmd,	'=',	0,	0,	0,	0,	aDot,	0,	linex,	eq_cmd,	'B',	0,	0,	0,	0,	aNo,	0,	linex,	B_cmd,	'D',	0,	0,	0,	0,	aNo,	0,	linex,	D_cmd,	'X',	0,	1,	0,	'f',	aNo,	0,	0,	X_cmd,	'Y',	0,	1,	0,	'f',	aNo,	0,	0,	X_cmd,	'<',	0,	0,	0,	0,	aDot,	0,	linex,	pipe_cmd,	'|',	0,	0,	0,	0,	aDot,	0,	linex,	pipe_cmd,	'>',	0,	0,	0,	0,	aDot,	0,	linex,	pipe_cmd,/* deliberately unimplemented:	'k',	0,	0,	0,	0,	aDot,	0,	0,	k_cmd,	'n',	0,	0,	0,	0,	aNo,	0,	0,	n_cmd,	'q',	0,	0,	0,	0,	aNo,	0,	0,	q_cmd,	'!',	0,	0,	0,	0,	aNo,	0,	linex,	plan9_cmd, */	0,	0,	0,	0,	0,	0,	0,	0,}; Cmd	*parsecmd(int);Addr	*compoundaddr(void);Addr	*simpleaddr(void);void	freecmd(void);void	okdelim(int); Rune	*cmdstartp;Rune	*cmdendp;Rune	*cmdp;Channel	*editerrc; String	*lastpat;int	patset; List	cmdlist;List	addrlist;List	stringlist;Text	*curtext;int	editing = Inactive; String*	newstring(int); voideditthread(void*){	Cmd *cmdp; 	threadsetname("editthread");	while((cmdp=parsecmd(0)) != 0){//		ocurfile = curfile;//		loaded = curfile && !curfile->unread;		if(cmdexec(curtext, cmdp) == 0)			break;		freecmd();	}	sendp(editerrc, nil);} voidallelogterm(Window *w, void*){	elogterm(w->body.file);} voidalleditinit(Window *w, void*){	textcommit(&w->tag, TRUE);	textcommit(&w->body, TRUE);	w->body.file->editclean = FALSE;} voidallupdate(Window *w, void*){	Text *t;	int i;	File *f; 	t = &w->body;	f = t->file;	if(f->curtext != t)	/* do curtext only */		return;	if(f->elog.type == Null)		elogterm(f);	else if(f->elog.type != Empty){		elogapply(f);		if(f->editclean){			f->mod = FALSE;			for(i=0; i<f->ntext; i++)				f->text[i]->w->dirty = FALSE;		}	}	textsetselect(t, t->q0, t->q1);	textscrdraw(t);	winsettag(w);} voidediterror(char *fmt, ...){	va_list arg;	char *s; 	va_start(arg, fmt);	s = vsmprint(fmt, arg);	va_end(arg);	freecmd();	allwindows(allelogterm, nil);	/* truncate the edit logs */	sendp(editerrc, s);	threadexits(nil);} voideditcmd(Text *ct, Rune *r, uint n){	char *err; 	if(n == 0)		return;	if(2*n > RBUFSIZE){		warning(nil, "string too long\n");		return;	} 	allwindows(alleditinit, nil);	if(cmdstartp)		free(cmdstartp);	cmdstartp = runemalloc(n+2);	runemove(cmdstartp, r, n);	if(r[n-1] != '\n')		cmdstartp[n++] = '\n';	cmdstartp[n] = '\0';	cmdendp = cmdstartp+n;	cmdp = cmdstartp;	if(ct->w == nil)		curtext = nil;	else		curtext = &ct->w->body;	resetxec();	if(editerrc == nil){		editerrc = chancreate(sizeof(char*), 0);		lastpat = allocstring(0);	}	threadcreate(editthread, nil, STACK);	err = recvp(editerrc);	editing = Inactive;	if(err != nil){		if(err[0] != '\0')			warning(nil, "Edit: %s\n", err);		free(err);	} 	/* update everyone whose edit log has data */	allwindows(allupdate, nil);} intgetch(void){	if(cmdp == cmdendp)		return -1;	return *cmdp++;} intnextc(void){	if(cmdp == cmdendp)		return -1;	return *cmdp;} voidungetch(void){	if(--cmdp < cmdstartp)		error("ungetch");} longgetnum(int signok){	long n;	int c, sign; 	n = 0;	sign = 1;	if(signok>1 && nextc()=='-'){		sign = -1;		getch();	}	if((c=nextc())<'0' || '9'<c)	/* no number defaults to 1 */		return sign;	while('0'<=(c=getch()) && c<='9')		n = n*10 + (c-'0');	ungetch();	return sign*n;} intcmdskipbl(void){	int c;	do		c = getch();	while(c==' ' || c=='\t');	if(c >= 0)		ungetch();	return c;} /* * Check that list has room for one more element. */voidgrowlist(List *l){	if(l->listptr==0 || l->nalloc==0){		l->nalloc = INCR;		l->listptr = emalloc(INCR*sizeof(void*));		l->nused = 0;	}else if(l->nused == l->nalloc){		l->listptr = erealloc(l->listptr, (l->nalloc+INCR)*sizeof(void*));		memset(l->ptr+l->nalloc, 0, INCR*sizeof(void*));		l->nalloc += INCR;	}} /* * Remove the ith element from the list */voiddellist(List *l, int i){	memmove(&l->ptr[i], &l->ptr[i+1], (l->nused-(i+1))*sizeof(void*));	l->nused--;} /* * Add a new element, whose position is i, to the list */voidinslist(List *l, int i, void *v){	growlist(l);	memmove(&l->ptr[i+1], &l->ptr[i], (l->nused-i)*sizeof(void*));	l->ptr[i] = v;	l->nused++;} voidlistfree(List *l){	free(l->listptr);	free(l);} String*allocstring(int n){	String *s; 	s = emalloc(sizeof(String));	s->n = n;	s->nalloc = n+10;	s->r = emalloc(s->nalloc*sizeof(Rune));	s->r[n] = '\0';	return s;} voidfreestring(String *s){	free(s->r);	free(s);} Cmd*newcmd(void){	Cmd *p; 	p = emalloc(sizeof(Cmd));	inslist(&cmdlist, cmdlist.nused, p);	return p;} String*newstring(int n){	String *p; 	p = allocstring(n);	inslist(&stringlist, stringlist.nused, p);	return p;} Addr*newaddr(void){	Addr *p; 	p = emalloc(sizeof(Addr));	inslist(&addrlist, addrlist.nused, p);	return p;} voidfreecmd(void){	int i; 	while(cmdlist.nused > 0)		free(cmdlist.ucharptr[--cmdlist.nused]);	while(addrlist.nused > 0)		free(addrlist.ucharptr[--addrlist.nused]);	while(stringlist.nused>0){		i = --stringlist.nused;		freestring(stringlist.stringptr[i]);	}} voidokdelim(int c){	if(c=='\\' || ('a'<=c && c<='z')	|| ('A'<=c && c<='Z') || ('0'<=c && c<='9'))		editerror("bad delimiter %c\n", c);} voidatnl(void){	int c; 	cmdskipbl();	c = getch();	if(c != '\n')		editerror("newline expected (saw %C)", c);} voidStraddc(String *s, int c){	if(s->n+1 >= s->nalloc){		s->nalloc += 10;		s->r = erealloc(s->r, s->nalloc*sizeof(Rune));	}	s->r[s->n++] = c;	s->r[s->n] = '\0';} voidgetrhs(String *s, int delim, int cmd){	int c; 	while((c = getch())>0 && c!=delim && c!='\n'){		if(c == '\\'){			if((c=getch()) <= 0)				error("bad right hand side");			if(c == '\n'){				ungetch();				c='\\';			}else if(c == 'n')				c='\n';			else if(c!=delim && (cmd=='s' || c!='\\'))	/* s does its own */				Straddc(s, '\\');		}		Straddc(s, c);	}	ungetch();	/* let client read whether delimiter, '\n' or whatever */} String *collecttoken(char *end){	String *s = newstring(0);	int c; 	while((c=nextc())==' ' || c=='\t')		Straddc(s, getch()); /* blanks significant for getname() */	while((c=getch())>0 && utfrune(end, c)==0)		Straddc(s, c);	if(c != '\n')		atnl();	return s;} String *collecttext(void){	String *s;	int begline, i, c, delim; 	s = newstring(0);	if(cmdskipbl()=='\n'){		getch();		i = 0;		do{			begline = i;			while((c = getch())>0 && c!='\n')				i++, Straddc(s, c);			i++, Straddc(s, '\n');			if(c < 0)				goto Return;		}while(s->r[begline]!='.' || s->r[begline+1]!='\n');		s->r[s->n-2] = '\0';		s->n -= 2;	}else{		okdelim(delim = getch());		getrhs(s, delim, 'a');		if(nextc()==delim)			getch();		atnl();	}    Return:	return s;} intcmdlookup(int c){	int i; 	for(i=0; cmdtab[i].cmdc; i++)		if(cmdtab[i].cmdc == c)			return i;	return -1;} Cmd*parsecmd(int nest){	int i, c;	struct cmdtab *ct;	Cmd *cp, *ncp;	Cmd cmd; 	cmd.next = cmd.cmd = 0;	cmd.re = 0;	cmd.flag = cmd.num = 0;	cmd.addr = compoundaddr();	if(cmdskipbl() == -1)		return 0;	if((c=getch())==-1)		return 0;	cmd.cmdc = c;	if(cmd.cmdc=='c' && nextc()=='d'){	/* sleazy two-character case */		getch();		/* the 'd' */		cmd.cmdc='c'|0x100;	}	i = cmdlookup(cmd.cmdc);	if(i >= 0){		if(cmd.cmdc == '\n')			goto Return;	/* let nl_cmd work it all out */		ct = &cmdtab[i];		if(ct->defaddr==aNo && cmd.addr)			editerror("command takes no address");		if(ct->count)			cmd.num = getnum(ct->count);		if(ct->regexp){			/* x without pattern -> .*\n, indicated by cmd.re==0 */			/* X without pattern is all files */			if((ct->cmdc!='x' && ct->cmdc!='X') ||			   ((c = nextc())!=' ' && c!='\t' && c!='\n')){

Lines 1–500 of 680.