henesyinit from p9f47575dc5 years agoHistory
987 lines · 15.9 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <libg.h>#include <frame.h>#include <regexp.h>#include <bio.h>#include "dat.h"#include "fns.h" int	maxargc;int	argc;char	**argv;Rune	*qbuf;ulong	maxqbuf; void	Xcut(int, char*[], Page*, Text*);void	Xexit(int, char*[], Page*, Text*);void	Xopen(int, char*[], Page*, Text*);void	Xnew(int, char*[], Page*, Text*);void	Xpaste(int, char*[], Page*, Text*);void	Xsnarf(int, char*[], Page*, Text*);void	Xpattern(int, char*[], Page*, Text*);void	Xtext(int, char*[], Page*, Text*);void	Xsplit(int, char*[], Page*, Text*);void	Xwrite(int, char*[], Page*, Text*);void	Xput(int, char*[], Page*, Text*);void	Xget(int, char*[], Page*, Text*);void	Xclose(int, char*[], Page*, Text*);void	Xgoto(int, char*[], Page*, Text*); struct{	char	*name;	void	(*f)(int, char*[], Page*, Text*);}builtin[] = {	"Cut",		Xcut,	"Exit",		Xexit,	"Xopen",	Xopen,	/* note change of name! */	"New",		Xnew,	"Paste",	Xpaste,	"Pattern",	Xpattern,	"Text",		Xtext,	"Snarf",	Xsnarf,	"Split",	Xsplit,	"Write",	Xwrite,	"Get!",		Xget,	"Put!",		Xput,	"Close!",	Xclose,	"Open",		Xgoto,	/* note change of name! */	0,		0,}; /* * Put str, preceded by a tab, in tag; also remove it from tag. */ voidputtag(Page *p, char *str, ulong q0){	Rune *r; 	textinsert(&p->tag, L"\t", q0, 0, 0);	r = tmprstr(str);	textinsert(&p->tag, r, q0+1, 0, 0);	free(r);} voidunputtag(Page *p, char *str){	int l;	Rune *r, *s;	Text *t;  	t = &p->tag;	s = t->s;	if(s == 0)		return;	r = tmprstr(str);	l = rstrlen(r);	while(s = rstrchr(s, '\t')){	/* assign = */		s++;		if(rstrncmp(s, r, l)==0 && strchr(" \t", s[l])){			t->q0 = (s-t->s)-1;			t->q1 = t->q0+l+1;			cut(t, 0);			break;		}	}	free(r);} voidlookup(char *s){	int i;	char *n; 	for(i=0; n=builtin[i].name; i++){		if(strcmp(s, n) == 0){			puttag(rootpage, n, 0);			bflush();			(*builtin[i].f)(argc, argv, page, curt);			unputtag(rootpage, n);			return;		}	}	xtrn(argc, argv, page, curt);} voidfreeargs(void){	int i; 	for(i=0; i<argc; i++)		free(argv[i]);	argc = 0;} voidnewarg(Rune *str, ulong n){	char *s; 	if(maxargc <= argc+1){	/* room for null pointer at argv[argc] */		maxargc += 10;		argv = erealloc(argv, maxargc*sizeof(char*));	}	s = cstr(str, n);	argv[argc++] = s;	argv[argc] = 0;} voidextend(Text *t, ulong *pp0, ulong *pp1, char *blanks){	ulong p0, p1; 	p0 = *pp0;	p1 = *pp1;	while(p0>0 && utfrune(blanks, t->s[p0-1])==0)		--p0;	while(p1<t->n && utfrune(blanks, t->s[p1])==0)		p1++;	*pp0 = p0;	*pp1 = p1;} ulongnextarg(Text *t, ulong p0, ulong p1, char *blanks){	ulong p;	int i; 	while(p0<p1 && utfrune(blanks, t->s[p0]))		p0++;	if(p1>p0 && t->s[p0]=='\''){	/* quoted strings */		p0++;	/* skip ' */		i = 0;		while(p0 < p1){			if(t->s[p0] == '\''){				p0++;				if(p0==p1 || t->s[p0]!='\'')					break;			}			if(i <= maxqbuf){				maxqbuf += 64;				qbuf = erealloc(qbuf, maxqbuf*sizeof(Rune));			}			qbuf[i++] = t->s[p0++];		}		newarg(qbuf, i);		return p0;	}	p = p0;	while(p0<p1 && utfrune(blanks, t->s[p0])==0)		p0++;	if(p < p1)		newarg(t->s+p, p0-p);	return p0;} voidargs(Text *t, ulong p0, ulong p1){	freeargs(); 	/*	 * Extract command and initial arguments	 */	if(p0 == p1){		extend(t, &p0, &p1, " \t\n");		if(p1 == p0)			return;		newarg(t->s+p0, p1-p0);	}else{		while(p1 > p0)			p0 = nextarg(t, p0, p1, " \t\n");	}	/* BUG: should be able to pass selection */} voidexecute(Text *t, ulong p0, ulong p1){	args(t, p0, p1);	if(argc)		lookup(argv[0]);} voidXcut(int argc, char *argv[], Page *page, Text *curt){	USED(argc, argv, page);	if(curt)		cut(curt, 1);} voidXpaste(int argc, char *argv[], Page *page, Text *curt){	USED(argc, argv, page);	if(curt)		paste(curt);} voidXsnarf(int argc, char *argv[], Page *page, Text *curt){	USED(argc, argv, page);	if(curt)		snarf(curt);} voidXsplit(int argc, char *argv[], Page *page, Text *curt){	USED(argc, argv, curt);	pagesplit(page, 1-page->parent->ver);} voidXexit(int argc, char *argv[], Page *page, Text *curt){	USED(argc, argv, page, curt);	exits(0);} /* * Exact match */Page*findopen1(Page *p, Rune *name){	Rune *s;	int n;	Page *q;     Again:	if(p == 0)		return p;	s = p->tag.s;	if(s){		n = rstrlen(name);		if(p->tag.n>=n && rstrncmp(name, s, n)==0)		if(p->tag.n==n || utfrune(" \t", s[n]))			return p;	}	q = findopen1(p->down, name);	if(q)		return q;	p = p->next;	goto Again;} /* * Basename match; exact match is known not to work */Page*findopen2(Page *p, Rune *name){	Rune *s, *t, *u;	int n;	Page *q;     Again:	if(p == 0)		return p;	s = p->tag.s;	if(s && rstrchr(s, '/')){		for(t=s; !utfrune(" \t", *t); t++)			;		u = s-1;		do{			s = u+1;			u = rstrchr(s, '/');		}while(u && u < t);		n = rstrlen(name);		if(p->tag.n>=n && rstrncmp(name, s, n)==0)		if(p->tag.n==n || utfrune(" \t", s[n]))			return p;	}	q = findopen2(p->next, name);	if(q)		return q;    Down:	p = p->down;	goto Again;} Page*findopen(Rune *name, int exact){	Page *p; 	if(name[0] == 0)		return 0;	p = findopen1(rootpage, name);	if(!exact && !p && !rstrchr(name, '/'))		p = findopen2(rootpage, name);	if(p){		/* make sure we can see it */		if(!p->visible || p->body.maxlines<2)			pagetop(p, p->r.min, 0);	}	return p;} Rune*endslash(Rune *an){	Rune *n; 	n = an;	if(n==0 || *n==0)		return 0;	while(*n){		if(utfrune(" \t", *n))			break;		n++;	}	while(--n >= an)		if(*n == '/')			return n+1;	return 0;} voidnamefix(char *n){	char *e, *p, *q, *r; 	e = n+strlen(n);	/* reduce multiple slashes */	for(q=n; q<e; q++)		while(q[0]=='/' && q[1]=='/'){			memmove(q+1, q+2, e-(q+2)+1);			--e;		}	/* lose ./ */	for(q=n; q<e; q++)		while(q[0]=='/' && q[1]=='.' && (q[2]=='/' || q+2==e)){			memmove(q+1, q+3, e-(q+3)+1);			--e;		}    Again:	/* reduce initial /../ */	p = n;	while(p[0]=='/' && p[1]=='.' && p[2]=='.' && p[3]=='/'){		memmove(p, p+3, e-(p+3)+1);		e -= 3;	}	/* skip initial ../ */	p = n;	while(p[0]=='.' && p[1]=='.' && p[2]=='/')		p += 3;	/* look for /..; can't be at beginning */	for(q=p; q<e; q++)		if(q[0]=='/' && q[1]=='.' && q[2]=='.' && (q[3]=='/' || q+3==e))			break;	if(q < e){		/* q points to /.. */		r = q;		q += 3;		while(r>p && r[-1]!='/')			--r;		if(r > p)			--r;		/* r points to /file/.. */		memmove(r, q, e-q+1);		e -= q-r;		goto Again;	}} Page*open1(int argc, char *argv[], Page *page, Text *curt, Page* (*f)(char*, Page*)){	int n;	Rune *name, *name1;	Rune *d0, *d1;	ulong p0, p1;	char *c;	Page *p, *parent; 	p = 0;	if(argc > 1){		if(curt)			parent = curt->page->parent;		else			parent = page->parent;		for(n=1; n<argc; n++)			p = (*f)(argv[n], parent);	}else{		if(curt==0 || curt->n==0)			return 0;		p0 = curt->q0;		p1 = curt->q1;		d1 = 0;		if(p0 == p1){			d1 = endslash(curt->page->tag.s);			extend(curt, &p0, &p1, " \t\n\"'<>");		}		n = p1-p0;		if(n == 0)			return 0;		/*		 * If can derive a directory name and file name		 * does not begin with / prepend directory name		 */		if(d1 && curt->s[p0]!='/'){			d0 = curt->page->tag.s;			name = emalloc(((d1-d0)+n+1)*sizeof(Rune));			memmove(name, d0, (d1-d0)*sizeof(Rune));			memmove(name+(d1-d0), curt->s+p0, n*sizeof(Rune));			name[(d1-d0)+n] = 0;		}else{			name = emalloc((n+1)*sizeof(Rune));			memmove(name, curt->s+p0, n*sizeof(Rune));			name[n] = 0;		}		/* toss leading ./  */		name1 = name;		if(rstrncmp(name, L"./", 2)==0){			name += 2;			while(*name == '/')				name++;			if(*name == 0)	/* whoops */				name = name1;		}		c = cstr(name, rstrlen(name));		p = (*f)(c, curt->page->parent);		free(c);		free(name1);	}	if(p)		newsel(&p->body);	return p;} voidreadfile(int fd, Text *t, ulong q0){	Dir d;	int i, c, ne, ndir;	Rune *r;	uchar *s, *dir;	ulong q1;	Biobuf *b;	uchar buf[DIRLEN]; 	dirfstat(fd, &d);	q1 = q0;	if(d.mode & CHDIR){		ndir = 0;		ne = 0;		dir = 0;		while(read(fd, buf, DIRLEN) > 0){			if(ndir == ne){				ndir += 32;				dir = erealloc(dir, ndir*(NAMELEN+1));			}			c = strlen((char*)buf)+2;			s = dir+ne*(NAMELEN+1);			memmove(s, buf, c);			s[c-2] = '\n';			s[c-1] = 0;			ne++;		}		if(dir){			qsort(dir, ne, NAMELEN+1, (int(*)(void*,void*))strcmp);			for(i=0; i<ne; i++){				s = dir+i*(NAMELEN+1);				r = tmprstr((char*)s);				c = rstrlen(r);				Strinsert(t, r, c, q1);				free(r);				q1 += c;

Lines 1–500 of 987.