示例#1
0
文件: xfid.c 项目: fr1tz/nadir
int
xfidruneread(Xfid *x, Text *t, uint q0, uint q1)
{
	Fcall fc;
	Window *w;
	Rune *r, junk;
	char *b, *b1;
	uint q, boff;
	int i, rw, m, n, nr, nb;

	w = t->w;
	wincommit(w, t);
	r = fbufalloc();
	b = fbufalloc();
	b1 = fbufalloc();
	n = 0;
	q = q0;
	boff = 0;
	while(q<q1 && n<x->fcall.count){
		nr = q1-q;
		if(nr > BUFSIZE/UTFmax)
			nr = BUFSIZE/UTFmax;
		bufread(&t->file->b, q, r, nr);
		nb = snprint(b, BUFSIZE+1, "%.*S", nr, r);
		m = nb;
		if(boff+m > x->fcall.count){
			i = x->fcall.count - boff;
			/* copy whole runes only */
			m = 0;
			nr = 0;
			while(m < i){
				rw = chartorune(&junk, b+m);
				if(m+rw > i)
					break;
				m += rw;
				nr++;
			}
			if(m == 0)
				break;
		}
		memmove(b1+n, b, m);
		n += m;
		boff += nb;
		q += nr;
	}
	fbuffree(r);
	fbuffree(b);
	fc.count = n;
	fc.data = b1;
	respond(x, &fc, nil);
	fbuffree(b1);
	return q-q0;
}
示例#2
0
文件: sele.c 项目: fr1tz/nadir
void
newsel(Text* t)
{
	int n, m, q, q0, q1;
	Rune *r;
	char *s;

	q0 = t->q0;

	q1 = t->q1;
	if(q0 == q1)
		return;

	latestselectionid++;

	free(selectionprocarg_context);
	if(t->file->name) 
		selectionprocarg_context = runetobyte(t->file->name, t->file->nname);
	else
		selectionprocarg_context = strdup(getsrvname());

	char* text = 0; 
	int ntext = 0;

	r = fbufalloc();
	s = fbufalloc();
	for(q=q0; q<q1; q+=n)
	{
		n = q1 - q;
		if(n > BUFSIZE/UTFmax)
			n = BUFSIZE/UTFmax;
		bufread(&t->file->b, q, r, n);
		m = snprint(s, BUFSIZE+1, "%.*S", n, r);
		text = realloc(text, ntext + m);
		memcpy(text + ntext, s, m);
		ntext += m;
	}
	fbuffree(r);
	fbuffree(s);

	free(selectionprocarg_text);
	selectionprocarg_text = text;
	selectionprocarg_ntext = ntext;

	latestselectiontext = t;

	proccreate(selectionproc, nil, STACK);
}
示例#3
0
文件: file.c 项目: 00001/plan9port
void
fileundelete(File *f, Buffer *delta, uint p0, uint p1)
{
	Undo u;
	Rune *buf;
	uint i, n;

	/* undo a deletion by inserting */
	u.type = Insert;
	u.mod = f->mod;
	u.seq = f->seq;
	u.p0 = p0;
	u.n = p1-p0;
	buf = fbufalloc();
	for(i=p0; i<p1; i+=n){
		n = p1 - i;
		if(n > RBUFSIZE)
			n = RBUFSIZE;
		bufread(&f->b, i, buf, n);
		bufinsert(delta, delta->nc, buf, n);
	}
	fbuffree(buf);
	bufinsert(delta, delta->nc, (Rune*)&u, Undosize);

}
示例#4
0
void
textfill(Text *t)
{
	Rune *rp;
	int i, n, m, nl;

	if(t->lastlinefull || t->nofill)
		return;
	if(t->ncache > 0)
		typecommit(t);
	rp = fbufalloc();
	do{
		n = t->file->nc-(t->org+t->nchars);
		if(n == 0)
			break;
		if(n > 2000)	/* educated guess at reasonable amount */
			n = 2000;
		bufread(t->file, t->org+t->nchars, rp, n);
		/*
		 * it's expensive to frinsert more than we need, so
		 * count newlines.
		 */
		nl = t->maxlines-t->nlines;
		m = 0;
		for(i=0; i<n; ){
			if(rp[i++] == '\n'){
				m++;
				if(m >= nl)
					break;
			}
		}
		frinsert(t, rp, rp+i, t->nchars);
	}while(t->lastlinefull == FALSE);
	fbuffree(rp);
}
示例#5
0
文件: xfid.c 项目: fr1tz/nadir
void
xfidindexread(Xfid *x)
{
	Fcall fc;
	int i, j, m, n, nmax, isbuf, cnt, off;
	Window *w;
	char *b;
	Rune *r;
	Column *c;

	qlock(&row.lk);
	nmax = 0;
	for(j=0; j<row.ncol; j++){
		c = row.col[j];
		for(i=0; i<c->nw; i++){
			w = c->w[i];
			nmax += Ctlsize + w->tag.file->b.nc*UTFmax + 1;
		}
	}
	nmax++;
	isbuf = (nmax<=RBUFSIZE);
	if(isbuf)
		b = (char*)x->buf;
	else
		b = emalloc(nmax);
	r = fbufalloc();
	n = 0;
	for(j=0; j<row.ncol; j++){
		c = row.col[j];
		for(i=0; i<c->nw; i++){
			w = c->w[i];
			/* only show the currently active window of a set */
			if(w->body.file->curtext != &w->body)
				continue;
			winctlprint(w, b+n, 0);
			n += Ctlsize;
			m = min(RBUFSIZE, w->tag.file->b.nc);
			bufread(&w->tag.file->b, 0, r, m);
			m = n + snprint(b+n, nmax-n-1, "%.*S", m, r);
			while(n<m && b[n]!='\n')
				n++;
			b[n++] = '\n';
		}
	}
	qunlock(&row.lk);
	off = x->fcall.offset;
	cnt = x->fcall.count;
	if(off > n)
		off = n;
	if(off+cnt > n)
		cnt = n-off;
	fc.count = cnt;
	memmove(r, b+off, cnt);
	fc.data = (char*)r;
	if(!isbuf)
		free(b);
	respond(x, &fc, nil);
	fbuffree(r);
}
示例#6
0
文件: file.c 项目: aahud/harvey
void
fileundo(File *f, int isundo, int canredo, uint *q0p, uint *q1p, int flag)
{
	Undo u;
	Rune *buf;
	uint i, n, up;
	uint stop;
	Buffer *delta, *epsilon;

	if(isundo){
		/* undo; reverse delta onto epsilon, seq decreases */
		delta = &f->delta;
		epsilon = &f->epsilon;
		stop = f->seq;
	}else{
		/* redo; reverse epsilon onto delta, seq increases */
		delta = &f->epsilon;
		epsilon = &f->delta;
		stop = 0;	/* don't know yet */
	}

	raspstart(f);
	while(delta->nc > 0){
		/* rasp and buffer are in sync; sync with wire if needed */
		if(needoutflush())
			raspflush(f);
		up = delta->nc-Undosize;
		bufread(delta, up, (Rune*)&u, Undosize);
		if(isundo){
			if(u.seq < stop){
				f->seq = u.seq;
				raspdone(f, flag);
				return;
			}
		}else{
			if(stop == 0)
				stop = u.seq;
			if(u.seq > stop){
				raspdone(f, flag);
				return;
			}
		}
		switch(u.type){
		default:
			panic("undo unknown u.type");
			break;

		case Delete:
			f->seq = u.seq;
			if(canredo)
				fileundelete(f, epsilon, u.p0, u.p0+u.n);
			f->mod = u.mod;
			bufdelete(&f->Buffer, u.p0, u.p0+u.n);
			raspdelete(f, u.p0, u.p0+u.n, flag);
			*q0p = u.p0;
			*q1p = u.p0;
			break;

		case Insert:
			f->seq = u.seq;
			if(canredo)
				fileuninsert(f, epsilon, u.p0, u.n);
			f->mod = u.mod;
			up -= u.n;
			buf = fbufalloc();
			for(i=0; i<u.n; i+=n){
				n = u.n - i;
				if(n > RBUFSIZE)
					n = RBUFSIZE;
				bufread(delta, up+i, buf, n);
				bufinsert(&f->Buffer, u.p0+i, buf, n);
				raspinsert(f, u.p0+i, buf, n, flag);
			}
			fbuffree(buf);
			*q0p = u.p0;
			*q1p = u.p0+u.n;
			break;

		case Filename:
			f->seq = u.seq;
			if(canredo)
				fileunsetname(f, epsilon);
			f->mod = u.mod;
			up -= u.n;

			Strinsure(&f->name, u.n+1);
			bufread(delta, up, f->name.s, u.n);
			f->name.s[u.n] = 0;
			f->name.n = u.n;
			fixname(&f->name);
			sortname(f);
			break;
		case Dot:
			f->seq = u.seq;
			if(canredo)
				fileunsetdot(f, epsilon, f->dot.r);
			f->mod = u.mod;
			f->dot.r.p1 = u.p0;
			f->dot.r.p2 = u.p0 + u.n;
			break;
		case Mark:
			f->seq = u.seq;
			if(canredo)
				fileunsetmark(f, epsilon, f->mark);
			f->mod = u.mod;
			f->mark.p1 = u.p0;
			f->mark.p2 = u.p0 + u.n;
			break;
		}
		bufdelete(delta, up, delta->nc);
	}
	if(isundo)
		f->seq = 0;
	raspdone(f, flag);
}
示例#7
0
文件: file.c 项目: 00001/plan9port
void
fileundo(File *f, int isundo, uint *q0p, uint *q1p)
{
	Undo u;
	Rune *buf;
	uint i, j, n, up;
	uint stop;
	Buffer *delta, *epsilon;

	if(isundo){
		/* undo; reverse delta onto epsilon, seq decreases */
		delta = &f->delta;
		epsilon = &f->epsilon;
		stop = f->seq;
	}else{
		/* redo; reverse epsilon onto delta, seq increases */
		delta = &f->epsilon;
		epsilon = &f->delta;
		stop = 0;	/* don't know yet */
	}

	buf = fbufalloc();
	while(delta->nc > 0){
		up = delta->nc-Undosize;
		bufread(delta, up, (Rune*)&u, Undosize);
		if(isundo){
			if(u.seq < stop){
				f->seq = u.seq;
				goto Return;
			}
		}else{
			if(stop == 0)
				stop = u.seq;
			if(u.seq > stop)
				goto Return;
		}
		switch(u.type){
		default:
			fprint(2, "undo: 0x%ux\n", u.type);
			abort();
			break;

		case Delete:
			f->seq = u.seq;
			fileundelete(f, epsilon, u.p0, u.p0+u.n);
			f->mod = u.mod;
			bufdelete(&f->b, u.p0, u.p0+u.n);
			for(j=0; j<f->ntext; j++)
				textdelete(f->text[j], u.p0, u.p0+u.n, FALSE);
			*q0p = u.p0;
			*q1p = u.p0;
			break;

		case Insert:
			f->seq = u.seq;
			fileuninsert(f, epsilon, u.p0, u.n);
			f->mod = u.mod;
			up -= u.n;
			for(i=0; i<u.n; i+=n){
				n = u.n - i;
				if(n > RBUFSIZE)
					n = RBUFSIZE;
				bufread(delta, up+i, buf, n);
				bufinsert(&f->b, u.p0+i, buf, n);
				for(j=0; j<f->ntext; j++)
					textinsert(f->text[j], u.p0+i, buf, n, FALSE);
			}
			*q0p = u.p0;
			*q1p = u.p0+u.n;
			break;

		case Filename:
			f->seq = u.seq;
			fileunsetname(f, epsilon);
			f->mod = u.mod;
			up -= u.n;
			free(f->name);
			if(u.n == 0)
				f->name = nil;
			else
				f->name = runemalloc(u.n);
			bufread(delta, up, f->name, u.n);
			f->nname = u.n;
			break;
		}
		bufdelete(delta, up, delta->nc);
	}
	if(isundo)
		f->seq = 0;
    Return:
	fbuffree(buf);
}
示例#8
0
uint
textload(Text *t, uint q0, char *file, int setqid)
{
	Rune *rp;
	Dirlist *dl, **dlp;
	int fd, i, j, n, ndl, nulls;
	uint q, q1;
	Dir *d, *dbuf;
	char *tmp;
	Text *u;

	if(t->ncache!=0 || t->file->nc || t->w==nil || t!=&t->w->body)
		error("text.load");
	if(t->w->isdir && t->file->nname==0){
		warning(nil, "empty directory name\n");
		return 0;
	}
	fd = open(file, OREAD);
	if(fd < 0){
		warning(nil, "can't open %s: %r\n", file);
		return 0;
	}
	d = dirfstat(fd);
	if(d == nil){
		warning(nil, "can't fstat %s: %r\n", file);
		goto Rescue;
	}
	nulls = FALSE;
	if(d->qid.type & QTDIR){
		/* this is checked in get() but it's possible the file changed underfoot */
		if(t->file->ntext > 1){
			warning(nil, "%s is a directory; can't read with multiple windows on it\n", file);
			goto Rescue;
		}
		t->w->isdir = TRUE;
		t->w->filemenu = FALSE;
		if(t->file->name[t->file->nname-1] != '/'){
			rp = runemalloc(t->file->nname+1);
			runemove(rp, t->file->name, t->file->nname);
			rp[t->file->nname] = '/';
			winsetname(t->w, rp, t->file->nname+1);
			free(rp);
		}
		dlp = nil;
		ndl = 0;
		dbuf = nil;
		while((n=dirread(fd, &dbuf)) > 0){
			for(i=0; i<n; i++){
				dl = emalloc(sizeof(Dirlist));
				j = strlen(dbuf[i].name);
				tmp = emalloc(j+1+1);
				memmove(tmp, dbuf[i].name, j);
				if(dbuf[i].qid.type & QTDIR)
					tmp[j++] = '/';
				tmp[j] = '\0';
				dl->r = bytetorune(tmp, &dl->nr);
				dl->wid = stringwidth(t->font, tmp);
				free(tmp);
				ndl++;
				dlp = realloc(dlp, ndl*sizeof(Dirlist*));
				dlp[ndl-1] = dl;
			}
			free(dbuf);
		}
		qsort(dlp, ndl, sizeof(Dirlist*), dircmp);
		t->w->dlp = dlp;
		t->w->ndl = ndl;
		textcolumnate(t, dlp, ndl);
		q1 = t->file->nc;
	}else{
		t->w->isdir = FALSE;
		t->w->filemenu = TRUE;
		q1 = q0 + fileload(t->file, q0, fd, &nulls);
	}
	if(setqid){
		t->file->dev = d->dev;
		t->file->mtime = d->mtime;
		t->file->qidpath = d->qid.path;
	}
	close(fd);
	rp = fbufalloc();
	for(q=q0; q<q1; q+=n){
		n = q1-q;
		if(n > RBUFSIZE)
			n = RBUFSIZE;
		bufread(t->file, q, rp, n);
		if(q < t->org)
			t->org += n;
		else if(q <= t->org+t->nchars)
			frinsert(t, rp, rp+n, q-t->org);
		if(t->lastlinefull)
			break;
	}
	fbuffree(rp);
	for(i=0; i<t->file->ntext; i++){
		u = t->file->text[i];
		if(u != t){
			if(u->org > u->file->nc)	/* will be 0 because of reset(), but safety first */
				u->org = 0;
			textresize(u, u->all);
			textbacknl(u, u->org, 0);	/* go to beginning of line */
		}
		textsetselect(u, q0, q0);
	}
	if(nulls)
		warning(nil, "%s: NUL bytes elided\n", file);
	free(d);
	return q1-q0;

    Rescue:
	close(fd);
	return 0;
}
示例#9
0
文件: xfid.c 项目: fr1tz/nadir
void
xfidopen(Xfid *x)
{
	Fcall fc;
	Window *w;
	Text *t;
	char *s;
	Rune *r;
	int m, n, q, q0, q1;

	w = x->f->w;
	t = &w->body;
	q = FILE(x->f->qid);
	if(w){
		winlock(w, 'E');
		switch(q){
		case QWaddr:
			if(w->nopen[q]++ == 0){
				w->addr = range(0, 0);
				w->limit = range(-1,-1);
			}
			break;
		case QWdata:
		case QWxdata:
			w->nopen[q]++;
			break;
		case QWevent:
			if(w->nopen[q]++ == 0){
				if(!w->isdir && w->col!=nil){
					w->filemenu = FALSE;
					winsettag(w);
				}
			}
			break;
		case QWrdsel:
			/*
			 * Use a temporary file.
			 * A pipe would be the obvious, but we can't afford the
			 * broken pipe notification.  Using the code to read QWbody
			 * is n², which should probably also be fixed.  Even then,
			 * though, we'd need to squirrel away the data in case it's
			 * modified during the operation, e.g. by |sort
			 */
			if(w->rdselfd > 0){
				winunlock(w);
				respond(x, &fc, Einuse);
				return;
			}
			w->rdselfd = tempfile();
			if(w->rdselfd < 0){
				winunlock(w);
				respond(x, &fc, "can't create temp file");
				return;
			}
			w->nopen[q]++;
			q0 = t->q0;
			q1 = t->q1;
			r = fbufalloc();
			s = fbufalloc();
			while(q0 < q1){
				n = q1 - q0;
				if(n > BUFSIZE/UTFmax)
					n = BUFSIZE/UTFmax;
				bufread(&t->file->b, q0, r, n);
				m = snprint(s, BUFSIZE+1, "%.*S", n, r);
				if(write(w->rdselfd, s, m) != m){
					warning(nil, "can't write temp file for pipe command %r\n");
					break;
				}
				q0 += n;
			}
			fbuffree(s);
			fbuffree(r);
			break;
		case QWwrsel:
			w->nopen[q]++;
			seq++;
			filemark(t->file);
			cut(t, t, nil, FALSE, TRUE, nil, 0);
			w->wrselrange = range(t->q1, t->q1);
			w->nomark = TRUE;
			break;
		case QWeditout:
			if(editing == FALSE){
				winunlock(w);
				respond(x, &fc, Eperm);
				return;
			}
			if(!canqlock(&w->editoutlk)){
				winunlock(w);
				respond(x, &fc, Einuse);
				return;
			}
			w->wrselrange = range(t->q1, t->q1);
			break;
		}
		winunlock(w);
	}
	else{
		switch(q){
		case Qeditout:
			if(!canqlock(&editoutlk)){
				respond(x, &fc, Einuse);
				return;
			}
			break;
		}
	}
	fc.qid = x->f->qid;
	fc.iounit = messagesize-IOHDRSZ;
	x->f->open = TRUE;
	respond(x, &fc, nil);
}
示例#10
0
文件: xfid.c 项目: fr1tz/nadir
void
xfidutfread(Xfid *x, Text *t, uint q1, int qid)
{
	Fcall fc;
	Window *w;
	Rune *r;
	char *b, *b1;
	uint q, off, boff;
	int m, n, nr, nb;

	w = t->w;
	wincommit(w, t);
	off = x->fcall.offset;
	r = fbufalloc();
	b = fbufalloc();
	b1 = fbufalloc();
	n = 0;
	if(qid==w->utflastqid && off>=w->utflastboff && w->utflastq<=q1){
		boff = w->utflastboff;
		q = w->utflastq;
	}else{
		/* BUG: stupid code: scan from beginning */
		boff = 0;
		q = 0;
	}
	w->utflastqid = qid;
	while(q<q1 && n<x->fcall.count){
		/*
		 * Updating here avoids partial rune problem: we're always on a
		 * char boundary. The cost is we will usually do one more read
		 * than we really need, but that's better than being n^2.
		 */
		w->utflastboff = boff;
		w->utflastq = q;
		nr = q1-q;
		if(nr > BUFSIZE/UTFmax)
			nr = BUFSIZE/UTFmax;
		bufread(&t->file->b, q, r, nr);
		nb = snprint(b, BUFSIZE+1, "%.*S", nr, r);
		if(boff >= off){
			m = nb;
			if(boff+m > off+x->fcall.count)
				m = off+x->fcall.count - boff;
			memmove(b1+n, b, m);
			n += m;
		}else if(boff+nb > off){
			if(n != 0)
				error("bad count in utfrune");
			m = nb - (off-boff);
			if(m > x->fcall.count)
				m = x->fcall.count;
			memmove(b1, b+(off-boff), m);
			n += m;
		}
		boff += nb;
		q += nr;
	}
	fbuffree(r);
	fbuffree(b);
	fc.count = n;
	fc.data = b1;
	respond(x, &fc, nil);
	fbuffree(b1);
}
示例#11
0
文件: xfid.c 项目: fr1tz/nadir
void
xfidctlwrite(Xfid *x, Window *w)
{
	Fcall fc;
	int i, m, n, nb, nr, nulls;
	Rune *r;
	char *err, *p, *pp, *q, *e;
	int isfbuf, scrdraw, settag;
	Text *t;

	err = nil;
	e = x->fcall.data+x->fcall.count;
	scrdraw = FALSE;
	settag = FALSE;
	isfbuf = TRUE;
	if(x->fcall.count < RBUFSIZE)
		r = fbufalloc();
	else{
		isfbuf = FALSE;
		r = emalloc(x->fcall.count*UTFmax+1);
	}
	x->fcall.data[x->fcall.count] = 0;
	textcommit(&w->tag, TRUE);
	for(n=0; n<x->fcall.count; n+=m){
		p = x->fcall.data+n;
		if(strncmp(p, "lock", 4) == 0){	/* make window exclusive use */
			qlock(&w->ctllock);
			w->ctlfid = x->f->fid;
			m = 4;
		}else
		if(strncmp(p, "unlock", 6) == 0){	/* release exclusive use */
			w->ctlfid = ~0;
			qunlock(&w->ctllock);
			m = 6;
		}else
		if(strncmp(p, "clean", 5) == 0){	/* mark window 'clean', seq=0 */
			t = &w->body;
			t->eq0 = ~0;
			filereset(t->file);
			t->file->mod = FALSE;
			w->dirty = FALSE;
			settag = TRUE;
			m = 5;
		}else
		if(strncmp(p, "dirty", 5) == 0){	/* mark window 'dirty' */
			t = &w->body;
			/* doesn't change sequence number, so "Put" won't appear.  it shouldn't. */
			t->file->mod = TRUE;
			w->dirty = TRUE;
			settag = TRUE;
			m = 5;
		}else
		if(strncmp(p, "show", 4) == 0){	/* show dot */
			t = &w->body;
			textshow(t, t->q0, t->q1, 1);
			m = 4;
		}else
		if(strncmp(p, "name ", 5) == 0){	/* set file name */
			pp = p+5;
			m = 5;
			q = memchr(pp, '\n', e-pp);
			if(q==nil || q==pp){
				err = Ebadctl;
				break;
			}
			*q = 0;
			nulls = FALSE;
			cvttorunes(pp, q-pp, r, &nb, &nr, &nulls);
			if(nulls){
				err = "nulls in file name";
				break;
			}
			for(i=0; i<nr; i++)
				if(r[i] <= ' '){
					err = "bad character in file name";
					goto out;
				}
out:
			seq++;
			filemark(w->body.file);
			winsetname(w, r, nr);
			m += (q+1) - pp;
		}else
		if(strncmp(p, "dump ", 5) == 0){	/* set dump string */
			pp = p+5;
			m = 5;
			q = memchr(pp, '\n', e-pp);
			if(q==nil || q==pp){
				err = Ebadctl;
				break;
			}
			*q = 0;
			nulls = FALSE;
			cvttorunes(pp, q-pp, r, &nb, &nr, &nulls);
			if(nulls){
				err = "nulls in dump string";
				break;
			}
			w->dumpstr = runetobyte(r, nr);
			m += (q+1) - pp;
		}else
		if(strncmp(p, "dumpdir ", 8) == 0){	/* set dump directory */
			pp = p+8;
			m = 8;
			q = memchr(pp, '\n', e-pp);
			if(q==nil || q==pp){
				err = Ebadctl;
				break;
			}
			*q = 0;
			nulls = FALSE;
			cvttorunes(pp, q-pp, r, &nb, &nr, &nulls);
			if(nulls){
				err = "nulls in dump directory string";
				break;
			}
			w->dumpdir = runetobyte(r, nr);
			m += (q+1) - pp;
		}else
		if(strncmp(p, "delete", 6) == 0){	/* delete for sure */
			colclose(w->col, w, TRUE);
			m = 6;
		}else
		if(strncmp(p, "del", 3) == 0){	/* delete, but check dirty */
			if(!winclean(w, TRUE)){
				err = "file dirty";
				break;
			}
			colclose(w->col, w, TRUE);
			m = 3;
		}else
		if(strncmp(p, "get", 3) == 0){	/* get file */
			get(&w->body, nil, nil, FALSE, XXX, nil, 0);
			m = 3;
		}else
		if(strncmp(p, "put", 3) == 0){	/* put file */
			put(&w->body, nil, nil, XXX, XXX, nil, 0);
			m = 3;
		}else
		if(strncmp(p, "dot=addr", 8) == 0){	/* set dot */
			textcommit(&w->body, TRUE);
			clampaddr(w);
			w->body.q0 = w->addr.q0;
			w->body.q1 = w->addr.q1;
			textsetselect(&w->body, w->body.q0, w->body.q1);
			settag = TRUE;
			m = 8;
		}else
		if(strncmp(p, "addr=dot", 8) == 0){	/* set addr */
			w->addr.q0 = w->body.q0;
			w->addr.q1 = w->body.q1;
			m = 8;
		}else
		if(strncmp(p, "limit=addr", 10) == 0){	/* set limit */
			textcommit(&w->body, TRUE);
			clampaddr(w);
			w->limit.q0 = w->addr.q0;
			w->limit.q1 = w->addr.q1;
			m = 10;
		}else
		if(strncmp(p, "nomark", 6) == 0){	/* turn off automatic marking */
			w->nomark = TRUE;
			m = 6;
		}else
		if(strncmp(p, "mark", 4) == 0){	/* mark file */
			seq++;
			filemark(w->body.file);
			settag = TRUE;
			m = 4;
		}else
		if(strncmp(p, "nomenu", 6) == 0){	/* turn off automatic menu */
			w->filemenu = FALSE;
			m = 6;
		}else
		if(strncmp(p, "menu", 4) == 0){	/* enable automatic menu */
			w->filemenu = TRUE;
			m = 4;
		}else
		if(strncmp(p, "noscroll", 8) == 0){	/* turn off automatic scrolling */
			w->noscroll = TRUE;
			m = 8;
		}else
		if(strncmp(p, "cleartag", 8) == 0){	/* wipe tag right of bar */
			wincleartag(w);
			settag = TRUE;
			m = 8;
		}else
		if(strncmp(p, "scroll", 6) == 0){	/* turn on automatic scrolling (writes to body only) */
			w->noscroll = FALSE;
			m = 6;
		}else{
			err = Ebadctl;
			break;
		}
		while(p[m] == '\n')
			m++;
	}

	if(isfbuf)
		fbuffree(r);
	else
		free(r);
	if(err)
		n = 0;
	fc.count = n;
	respond(x, &fc, err);
	if(settag)
		winsettag(w);
	if(scrdraw)
		textscrdraw(&w->body);
}
示例#12
0
文件: xfid.c 项目: fr1tz/nadir
void
xfideventwrite(Xfid *x, Window *w)
{
	Fcall fc;
	int m, n;
	Rune *r;
	char *err, *p, *q;
	int isfbuf;
	Text *t;
	int c;
	uint q0, q1;

	err = nil;
	isfbuf = TRUE;
	if(x->fcall.count < RBUFSIZE)
		r = fbufalloc();
	else{
		isfbuf = FALSE;
		r = emalloc(x->fcall.count*UTFmax+1);
	}
	for(n=0; n<x->fcall.count; n+=m){
		p = x->fcall.data+n;
		w->owner = *p++;	/* disgusting */
		c = *p++;
		while(*p == ' ')
			p++;
		q0 = strtoul(p, &q, 10);
		if(q == p)
			goto Rescue;
		p = q;
		while(*p == ' ')
			p++;
		q1 = strtoul(p, &q, 10);
		if(q == p)
			goto Rescue;
		p = q;
		while(*p == ' ')
			p++;
		if(*p++ != '\n')
			goto Rescue;
		m = p-(x->fcall.data+n);
		if('a'<=c && c<='z')
			t = &w->tag;
		else if('A'<=c && c<='Z')
			t = &w->body;
		else
			goto Rescue;
		if(q0>t->file->b.nc || q1>t->file->b.nc || q0>q1)
			goto Rescue;

		qlock(&row.lk);	/* just like mousethread */
		switch(c){
		case 'x':
		case 'X':
			execute(t, q0, q1, TRUE, nil);
			break;
		case 'l':
		case 'L':
			look3(t, q0, q1, TRUE, FALSE);
			break;
		default:
			qunlock(&row.lk);
			goto Rescue;
		}
		qunlock(&row.lk);

	}

    Out:
	if(isfbuf)
		fbuffree(r);
	else
		free(r);
	if(err)
		n = 0;
	fc.count = n;
	respond(x, &fc, err);
	return;

    Rescue:
	err = Ebadevent;
	goto Out;
}
示例#13
0
文件: xfid.c 项目: fr1tz/nadir
void
xfidread(Xfid *x)
{
	Fcall fc;
	int n, q;
	uint off;
	char *b;
	char buf[256];
	Window *w;

	q = FILE(x->f->qid);
	w = x->f->w;
	if(w == nil){
		fc.count = 0;
		switch(q){
		case Qcons:
		case Qlabel:
			break;
		case Qindex:
			xfidindexread(x);
			return;
		default:
			warning(nil, "unknown qid %d\n", q);
			break;
		}
		respond(x, &fc, nil);
		return;
	}
	winlock(w, 'F');
	if(w->col == nil){
		winunlock(w);
		respond(x, &fc, Edel);
		return;
	}
	off = x->fcall.offset;
	switch(q){
	case QWaddr:
		textcommit(&w->body, TRUE);
		clampaddr(w);
		sprint(buf, "%11d %11d ", w->addr.q0, w->addr.q1);
		goto Readbuf;

	case QWbody:
		xfidutfread(x, &w->body, w->body.file->b.nc, QWbody);
		break;

	case QWctl:
		b = winctlprint(w, buf, 1);
		goto Readb;

	Readbuf:
		b = buf;
	Readb:
		n = strlen(b);
		if(off > n)
			off = n;
		if(off+x->fcall.count > n)
			x->fcall.count = n-off;
		fc.count = x->fcall.count;
		fc.data = b+off;
		respond(x, &fc, nil);
		if(b != buf)
			free(b);
		break;

	case QWevent:
		xfideventread(x, w);
		break;

	case QWdata:
		/* BUG: what should happen if q1 > q0? */
		if(w->addr.q0 > w->body.file->b.nc){
			respond(x, &fc, Eaddr);
			break;
		}
		w->addr.q0 += xfidruneread(x, &w->body, w->addr.q0, w->body.file->b.nc);
		w->addr.q1 = w->addr.q0;
		break;

	case QWxdata:
		/* BUG: what should happen if q1 > q0? */
		if(w->addr.q0 > w->body.file->b.nc){
			respond(x, &fc, Eaddr);
			break;
		}
		w->addr.q0 += xfidruneread(x, &w->body, w->addr.q0, w->addr.q1);
		break;

	case QWtag:
		xfidutfread(x, &w->tag, w->tag.file->b.nc, QWtag);
		break;

	case QWrdsel:
		seek(w->rdselfd, off, 0);
		n = x->fcall.count;
		if(n > BUFSIZE)
			n = BUFSIZE;
		b = fbufalloc();
		n = read(w->rdselfd, b, n);
		if(n < 0){
			respond(x, &fc, "I/O error in temp file");
			break;
		}
		fc.count = n;
		fc.data = b;
		respond(x, &fc, nil);
		fbuffree(b);
		break;

	default:
		sprint(buf, "unknown qid %d in read", q);
		respond(x, &fc, nil);
	}
	winunlock(w);
}
示例#14
0
文件: sele.c 项目: fr1tz/nadir
void
putxsel(Text* t)
{
	char* av[] = { "setguisel", 0, 0 };
	int pfd[2], sfd[3], pid, n, m, q, q0, q1;
	Rune *r;
	char *s;

	q0 = t->q0;

	q1 = t->q1;
	if(q0 == q1)
		return;

	if(pipe(pfd) < 0)
	{
		warning(nil, "putxsel: can't create pipe");
		return;
	}
	fcntl(pfd[0], F_SETFD, FD_CLOEXEC);
	fcntl(pfd[1], F_SETFD, FD_CLOEXEC);

	sfd[0] = pfd[0];
	sfd[1] = open("/dev/null", OWRITE);
	sfd[2] = dup(erroutfd, -1);

	if(t->file->name) 
		av[1] = runetobyte(t->file->name, t->file->nname);

	pid = threadspawn(sfd, av[0], av);

	free(av[1]);

	if(pid == -1)
	{
		warning(nil, "can't spawn thread %s: %r\n", av[0]);
		return;
	}	

	r = fbufalloc();
	s = fbufalloc();
	for(q=q0; q<q1; q+=n)
	{
		n = q1 - q;
		if(n > BUFSIZE/UTFmax)
			n = BUFSIZE/UTFmax;
		bufread(&t->file->b, q, r, n);
		m = snprint(s, BUFSIZE+1, "%.*S", n, r);
		if(write(pfd[1], s, m) != m)
		{
			warning(nil, "error writing to setguisel: %r\n");
			break;
		}
	}
	fbuffree(r);
	fbuffree(s);

	close(pfd[1]);

	newsel(t);
}
示例#15
0
int
rowload(Row *row, char *file, int initing)
{
	int i, j, line, percent, y, nr, nfontr, n, ns, ndumped, dumpid, x, fd;
	Biobuf *b, *bout;
	char *buf, *l, *t, *fontname;
	Rune *r, rune, *fontr;
	Column *c, *c1, *c2;
	uint q0, q1;
	Rectangle r1, r2;
	Window *w;

	buf = fbufalloc();
	if(file == nil){
		if(home == nil){
			warning(nil, "can't find file for load: $home not defined\n");
			goto Rescue1;
		}
		sprint(buf, "%s/acme.dump", home);
		file = buf;
	}
	b = Bopen(file, OREAD);
	if(b == nil){
		warning(nil, "can't open load file %s: %r\n", file);
		goto Rescue1;
	}
	/* current directory */
	line = 0;
	l = rdline(b, &line);
	if(l == nil)
		goto Rescue2;
	l[Blinelen(b)-1] = 0;
	if(chdir(l) < 0){
		warning(nil, "can't chdir %s\n", l);
		goto Rescue2;
	}
	/* global fonts */
	for(i=0; i<2; i++){
		l = rdline(b, &line);
		if(l == nil)
			goto Rescue2;
		l[Blinelen(b)-1] = 0;
		if(*l && strcmp(l, fontnames[i])!=0)
			rfget(i, TRUE, i==0 && initing, l);
	}
	if(initing && row->ncol==0)
		rowinit(row, screen->clipr);
	l = rdline(b, &line);
	if(l == nil)
		goto Rescue2;
	j = Blinelen(b)/12;
	if(j<=0 || j>10)
		goto Rescue2;
	for(i=0; i<j; i++){
		percent = atoi(l+i*12);
		if(percent<0 || percent>=100)
			goto Rescue2;
		x = row->r.min.x+percent*Dx(row->r)/100;
		if(i < row->ncol){
			if(i == 0)
				continue;
			c1 = row->col[i-1];
			c2 = row->col[i];
			r1 = c1->r;
			r2 = c2->r;
			r1.max.x = x;
			r2.min.x = x+Border;
			if(Dx(r1) < 50 || Dx(r2) < 50)
				continue;
			draw(screen, Rpt(r1.min, r2.max), display->white, nil, ZP);
			colresize(c1, r1);
			colresize(c2, r2);
			r2.min.x = x;
			r2.max.x = x+Border;
			draw(screen, r2, display->black, nil, ZP);
		}
		if(i >= row->ncol)
			rowadd(row, nil, x);
	}
	for(;;){
		l = rdline(b, &line);
		if(l == nil)
			break;
		dumpid = 0;
		switch(l[0]){
		case 'e':
			if(Blinelen(b) < 1+5*12+1)
				goto Rescue2;
			l = rdline(b, &line);	/* ctl line; ignored */
			if(l == nil)
				goto Rescue2;
			l = rdline(b, &line);	/* directory */
			if(l == nil)
				goto Rescue2;
			l[Blinelen(b)-1] = 0;
			if(*l == '\0'){
				if(home == nil)
					r = bytetorune("./", &nr);
				else{
					t = emalloc(strlen(home)+1+1);
					sprint(t, "%s/", home);
					r = bytetorune(t, &nr);
					free(t);
				}
			}else
				r = bytetorune(l, &nr);
			l = rdline(b, &line);	/* command */
			if(l == nil)
				goto Rescue2;
			t = emalloc(Blinelen(b)+1);
			memmove(t, l, Blinelen(b));
			run(nil, t, r, nr, TRUE, nil, nil, FALSE);
			/* r is freed in run() */
			continue;
		case 'f':
			if(Blinelen(b) < 1+5*12+1)
				goto Rescue2;
			fontname = l+1+5*12;
			ndumped = -1;
			break;
		case 'F':
			if(Blinelen(b) < 1+6*12+1)
				goto Rescue2;
			fontname = l+1+6*12;
			ndumped = atoi(l+1+5*12+1);
			break;
		case 'x':
			if(Blinelen(b) < 1+5*12+1)
				goto Rescue2;
			fontname = l+1+5*12;
			ndumped = -1;
			dumpid = atoi(l+1+1*12);
			break;
		default:
			goto Rescue2;
		}
		l[Blinelen(b)-1] = 0;
		fontr = nil;
		nfontr = 0;
		if(*fontname)
			fontr = bytetorune(fontname, &nfontr);
		i = atoi(l+1+0*12);
		j = atoi(l+1+1*12);
		q0 = atoi(l+1+2*12);
		q1 = atoi(l+1+3*12);
		percent = atoi(l+1+4*12);
		if(i<0 || i>10)
			goto Rescue2;
		if(i > row->ncol)
			i = row->ncol;
		c = row->col[i];
		y = c->r.min.y+(percent*Dy(c->r))/100;
		if(y<c->r.min.y || y>=c->r.max.y)
			y = -1;
		if(dumpid == 0)
			w = coladd(c, nil, nil, y);
		else
			w = coladd(c, nil, lookid(dumpid, TRUE), y);
		if(w == nil)
			continue;
		w->dumpid = j;
		l = rdline(b, &line);
		if(l == nil)
			goto Rescue2;
		l[Blinelen(b)-1] = 0;
		r = bytetorune(l+5*12, &nr);
		ns = -1;
		for(n=0; n<nr; n++){
			if(r[n] == '/')
				ns = n;
			if(r[n] == ' ')
				break;
		}
		if(dumpid == 0)
			winsetname(w, r, n);
		for(; n<nr; n++)
			if(r[n] == '|')
				break;
		wincleartag(w);
		textinsert(&w->tag, w->tag.file->nc, r+n+1, nr-(n+1), TRUE);
		if(ndumped >= 0){
			/* simplest thing is to put it in a file and load that */
			sprint(buf, "/tmp/d%d.%.4sacme", getpid(), getuser());
			fd = create(buf, OWRITE|ORCLOSE, 0600);
			if(fd < 0){
				free(r);
				warning(nil, "can't create temp file: %r\n");
				goto Rescue2;
			}
			bout = emalloc(sizeof(Biobuf));
			Binit(bout, fd, OWRITE);
			for(n=0; n<ndumped; n++){
				rune = Bgetrune(b);
				if(rune == '\n')
					line++;
				if(rune == (Rune)Beof){
					free(r);
					Bterm(bout);
					free(bout);
					close(fd);
					goto Rescue2;
				}
				Bputrune(bout, rune);
			}
			Bterm(bout);
			free(bout);
			textload(&w->body, 0, buf, 1);
			close(fd);
			w->body.file->mod = TRUE;
			for(n=0; n<w->body.file->ntext; n++)
				w->body.file->text[n]->w->dirty = TRUE;
			winsettag(w);
		}else if(dumpid==0 && r[ns+1]!='+' && r[ns+1]!='-')
			get(&w->body, nil, nil, FALSE, XXX, nil, 0);
		if(fontr){
			fontx(&w->body, nil, nil, 0, 0, fontr, nfontr);
			free(fontr);
		}
		free(r);
		if(q0>w->body.file->nc || q1>w->body.file->nc || q0>q1)
			q0 = q1 = 0;
		textshow(&w->body, q0, q1, 1);
		w->maxlines = min(w->body.nlines, max(w->maxlines, w->body.maxlines));
	}
	Bterm(b);
	fbuffree(buf);
	return TRUE;

Rescue2:
	warning(nil, "bad load file %s:%d\n", file, line);
	Bterm(b);
Rescue1:
	fbuffree(buf);
	return FALSE;
}
示例#16
0
void
rowdump(Row *row, char *file)
{
	int i, j, fd, m, n, dumped;
	uint q0, q1;
	Biobuf *b;
	char *buf, *a, *fontname;
	Rune *r;
	Column *c;
	Window *w, *w1;
	Text *t;

	if(row->ncol == 0)
		return;
	buf = fbufalloc();
	if(file == nil){
		if(home == nil){
			warning(nil, "can't find file for dump: $home not defined\n");
			goto Rescue;
		}
		sprint(buf, "%s/acme.dump", home);
		file = buf;
	}
	fd = create(file, OWRITE, 0600);
	if(fd < 0){
		warning(nil, "can't open %s: %r\n", file);
		goto Rescue;
	}
	b = emalloc(sizeof(Biobuf));
	Binit(b, fd, OWRITE);
	r = fbufalloc();
	Bprint(b, "%s\n", wdir);
	Bprint(b, "%s\n", fontnames[0]);
	Bprint(b, "%s\n", fontnames[1]);
	for(i=0; i<row->ncol; i++){
		c = row->col[i];
		Bprint(b, "%11d", 100*(c->r.min.x-row->r.min.x)/Dx(row->r));
		if(i == row->ncol-1)
			Bputc(b, '\n');
		else
			Bputc(b, ' ');
	}
	for(i=0; i<row->ncol; i++){
		c = row->col[i];
		for(j=0; j<c->nw; j++)
			c->w[j]->body.file->dumpid = 0;
	}
	for(i=0; i<row->ncol; i++){
		c = row->col[i];
		for(j=0; j<c->nw; j++){
			w = c->w[j];
			wincommit(w, &w->tag);
			t = &w->body;
			/* windows owned by others get special treatment */
			if(w->nopen[QWevent] > 0)
				if(w->dumpstr == nil)
					continue;
			/* zeroxes of external windows are tossed */
			if(t->file->ntext > 1)
				for(n=0; n<t->file->ntext; n++){
					w1 = t->file->text[n]->w;
					if(w == w1)
						continue;
					if(w1->nopen[QWevent])
						goto Continue2;
				}
			fontname = "";
			if(t->reffont->f != font)
				fontname = t->reffont->f->name;
			if(t->file->nname)
				a = runetobyte(t->file->name, t->file->nname);
			else
				a = emalloc(1);
			if(t->file->dumpid){
				dumped = FALSE;
				Bprint(b, "x%11d %11d %11d %11d %11d %s\n", i, t->file->dumpid,
					w->body.q0, w->body.q1,
					100*(w->r.min.y-c->r.min.y)/Dy(c->r),
					fontname);
			}else if(w->dumpstr){
				dumped = FALSE;
				Bprint(b, "e%11d %11d %11d %11d %11d %s\n", i, t->file->dumpid,
					0, 0,
					100*(w->r.min.y-c->r.min.y)/Dy(c->r),
					fontname);
			}else if((w->dirty==FALSE && access(a, 0)==0) || w->isdir){
				dumped = FALSE;
				t->file->dumpid = w->id;
				Bprint(b, "f%11d %11d %11d %11d %11d %s\n", i, w->id,
					w->body.q0, w->body.q1,
					100*(w->r.min.y-c->r.min.y)/Dy(c->r),
					fontname);
			}else{
				dumped = TRUE;
				t->file->dumpid = w->id;
				Bprint(b, "F%11d %11d %11d %11d %11d %11d %s\n", i, j,
					w->body.q0, w->body.q1,
					100*(w->r.min.y-c->r.min.y)/Dy(c->r),
					w->body.file->nc, fontname);
			}
			free(a);
			winctlprint(w, buf, 0);
			Bwrite(b, buf, strlen(buf));
			m = min(RBUFSIZE, w->tag.file->nc);
			bufread(w->tag.file, 0, r, m);
			n = 0;
			while(n<m && r[n]!='\n')
				n++;
			r[n++] = '\n';
			Bprint(b, "%.*S", n, r);
			if(dumped){
				q0 = 0;
				q1 = t->file->nc;
				while(q0 < q1){
					n = q1 - q0;
					if(n > BUFSIZE/UTFmax)
						n = BUFSIZE/UTFmax;
					bufread(t->file, q0, r, n);
					Bprint(b, "%.*S", n, r);
					q0 += n;
				}
			}
			if(w->dumpstr){
				if(w->dumpdir)
					Bprint(b, "%s\n%s\n", w->dumpdir, w->dumpstr);
				else
					Bprint(b, "\n%s\n", w->dumpstr);
			}
    Continue2:;
		}
	}
	Bterm(b);
	close(fd);
	free(b);
	fbuffree(r);

   Rescue:
	fbuffree(buf);
}
示例#17
0
文件: look.c 项目: 9fans/plan9port
int
search(Text *ct, Rune *r, uint n)
{
	uint q, nb, maxn;
	int around;
	Rune *s, *b, *c;

	if(n==0 || n>ct->file->b.nc)
		return FALSE;
	if(2*n > RBUFSIZE){
		warning(nil, "string too long\n");
		return FALSE;
	}
	maxn = max(2*n, RBUFSIZE);
	s = fbufalloc();
	b = s;
	nb = 0;
	b[nb] = 0;
	around = 0;
	q = ct->q1;
	for(;;){
		if(q >= ct->file->b.nc){
			q = 0;
			around = 1;
			nb = 0;
			b[nb] = 0;
		}
		if(nb > 0){
			c = runestrchr(b, r[0]);
			if(c == nil){
				q += nb;
				nb = 0;
				b[nb] = 0;
				if(around && q>=ct->q1)
					break;
				continue;
			}
			q += (c-b);
			nb -= (c-b);
			b = c;
		}
		/* reload if buffer covers neither string nor rest of file */
		if(nb<n && nb!=ct->file->b.nc-q){
			nb = ct->file->b.nc-q;
			if(nb >= maxn)
				nb = maxn-1;
			bufread(&ct->file->b, q, s, nb);
			b = s;
			b[nb] = '\0';
		}
		/* this runeeq is fishy but the null at b[nb] makes it safe */
		if(runeeq(b, n, r, n)==TRUE){
			if(ct->w){
				textshow(ct, q, q+n, 1);
				winsettag(ct->w);
			}else{
				ct->q0 = q;
				ct->q1 = q+n;
			}
			seltext = ct;
			fbuffree(s);
			return TRUE;
		}
		--nb;
		b++;
		q++;
		if(around && q>=ct->q1)
			break;
	}
	fbuffree(s);
	return FALSE;
}