コード例 #1
0
ファイル: util.c プロジェクト: carriercomm/plan9-gpl
Window*
errorwin1(Rune *dir, int ndir, Rune **incl, int nincl)
{
	Window *w;
	Rune *r;
	int i, n;

	r = runemalloc(ndir+8);
	if(n = ndir){	/* assign = */
		runemove(r, dir, ndir);
		r[n++] = L'/';
	}
	runemove(r+n, L"+Errors", 7);
	n += 7;
	w = lookfile(r, n);
	if(w == nil){
		if(row.ncol == 0)
			if(rowadd(&row, nil, -1) == nil)
				error("can't create column to make error window");
		w = coladd(row.col[row.ncol-1], nil, nil, -1);
		w->filemenu = FALSE;
		winsetname(w, r, n);
	}
	free(r);
	for(i=nincl; --i>=0; ){
		n = runestrlen(incl[i]);
		r = runemalloc(n);
		runemove(r, incl[i], n);
		winaddincl(w, r, n);
	}
	w->autoindent = globalautoindent;
	return w;
}
コード例 #2
0
ファイル: text.c プロジェクト: AustenConrad/plan-9
void
textfill(Text *t)
{
	Rune *rp;
	int i, n, m, nl;

	if(t->lastlinefull)
		return;
	rp = runemalloc(BUFSIZE*8);
	do{
		n = t->rs.nr-(t->org+t->nchars);
		if(n == 0)
			break;
		if(n > 2000)	/* educated guess at reasonable amount */
			n = 2000;
		runemove(rp, t->rs.r+(t->org+t->nchars), 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);
	free(rp);
}
コード例 #3
0
ファイル: util.c プロジェクト: grobe0ba/plan9front
void
copyrunestr(Runestr *a, Runestr *b)
{
    closerunestr(a);
    a->r = runemalloc(b->nr+1);
    runemove(a->r, b->r, b->nr);
    a->r[b->nr] = 0;
    a->nr = b->nr;
}
コード例 #4
0
ファイル: file.c プロジェクト: 00001/plan9port
void
filesetname(File *f, Rune *name, int n)
{
	if(f->seq > 0)
		fileunsetname(f, &f->delta);
	free(f->name);
	f->name = runemalloc(n);
	runemove(f->name, name, n);
	f->nname = n;
	f->unread = TRUE;
}
コード例 #5
0
ファイル: util.c プロジェクト: carriercomm/plan9-gpl
Rune*
bytetorune(char *s, int *ip)
{
	Rune *r;
	int nb, nr;

	nb = strlen(s);
	r = runemalloc(nb+1);
	cvttorunes(s, nb, r, &nb, &nr, nil);
	r[nr] = '\0';
	*ip = nr;
	return r;
}
コード例 #6
0
ファイル: util.c プロジェクト: grobe0ba/plan9front
void
bytetorunestr(char *s, Runestr *rs)
{
    Rune *r;
    int nb, nr;

    nb = strlen(s);
    r = runemalloc(nb+1);
    cvttorunes(s, nb, r, &nb, &nr, nil);
    r[nr] = '\0';
    rs->nr = nr;
    rs->r = r;
}
コード例 #7
0
ファイル: text.c プロジェクト: carriercomm/plan9-gpl
uint
textbsinsert(Text *t, uint q0, Rune *r, uint n, int tofile, int *nrp)
{
	Rune *bp, *tp, *up;
	int i, initial;

	if(t->what == Tag){	/* can't happen but safety first: mustn't backspace over file name */
    Err:
		textinsert(t, q0, r, n, tofile);
		*nrp = n;
		return q0;
	}
	bp = r;
	for(i=0; i<n; i++)
		if(*bp++ == '\b'){
			--bp;
			initial = 0;
			tp = runemalloc(n);
			runemove(tp, r, i);
			up = tp+i;
			for(; i<n; i++){
				*up = *bp++;
				if(*up == '\b')
					if(up == tp)
						initial++;
					else
						--up;
				else
					up++;
			}
			if(initial){
				if(initial > q0)
					initial = q0;
				q0 -= initial;
				textdelete(t, q0, q0+initial, tofile);
			}
			n = up-tp;
			textinsert(t, q0, tp, n, tofile);
			free(tp);
			*nrp = n;
			return q0;
		}
	goto Err;
}
コード例 #8
0
ファイル: edit.c プロジェクト: npe9/harvey
void
editcmd(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] != '\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);
}
コード例 #9
0
ファイル: buff.c プロジェクト: AustenConrad/plan-9
uint
bufload(Buffer *b, uint q0, int fd, int *nulls)
{
	char *p;
	Rune *r;
	int l, m, n, nb, nr;
	uint q1;

	if(q0 > b->nc)
		panic("internal error: bufload");
	p = malloc((Maxblock+UTFmax+1)*sizeof p[0]);
	if(p == nil)
		panic("bufload: malloc failed");
	r = runemalloc(Maxblock);
	m = 0;
	n = 1;
	q1 = q0;
	/*
	 * At top of loop, may have m bytes left over from
	 * last pass, possibly representing a partial rune.
	 */
	while(n > 0){
		n = read(fd, p+m, Maxblock);
		if(n < 0){
			error(Ebufload);
			break;
		}
		m += n;
		p[m] = 0;
		l = m;
		if(n > 0)
			l -= UTFmax;
		cvttorunes(p, l, r, &nb, &nr, nulls);
		memmove(p, p+nb, m-nb);
		m -= nb;
		bufinsert(b, q1, r, nr);
		q1 += nr;
	}
	free(p);
	free(r);
	return q1-q0;
}
コード例 #10
0
ファイル: acme.c プロジェクト: UNGLinux/9base
void
acmegetsnarf(void)
{
	char *s;
	int nb, nr, nulls, len;
	Rune *r;

	s = getsnarf();
	if(s == nil || s[0]==0){
		free(s);
		return;
	}

	len = strlen(s);
	r = runemalloc(len+1);
	cvttorunes(s, len, r, &nb, &nr, &nulls);
	bufreset(&snarfbuf);
	bufinsert(&snarfbuf, 0, r, nr);
	free(r);
	free(s);
}
コード例 #11
0
ファイル: sele.c プロジェクト: fr1tz/nadir
void
getxselarg(Text* t)
{
	char* av[] = { "xsel2arg", 0 };
	int pfd[2], sfd[3], pid, n, nb, nr, nulls;
	char buf[1024];
	Rune *r;

	textdelete(t, 0, t->file->b.nc, TRUE);

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

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

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

	while(0 < (n = read(pfd[1],  buf, 1024)))
	{
		r = runemalloc(n+1);
		cvttorunes(buf, n, r, &nb, &nr, &nulls);
		textinsert(t, 0, r, nr, TRUE);
		free(r);
	}

	textsetselect(t, 0, t->file->b.nc);
}
コード例 #12
0
ファイル: look.c プロジェクト: 9fans/plan9port
Runestr
dirname(Text *t, Rune *r, int n)
{
	Rune *b, c;
	uint m, nt;
	int slash;
	Runestr tmp;

	b = nil;
	if(t==nil || t->w==nil)
		goto Rescue;
	nt = t->w->tag.file->b.nc;
	if(nt == 0)
		goto Rescue;
	if(n>=1 && r[0]=='/')
		goto Rescue;
	b = runemalloc(nt+n+1);
	bufread(&t->w->tag.file->b, 0, b, nt);
	slash = -1;
	for(m=0; m<nt; m++){
		c = b[m];
		if(c == '/')
			slash = m;
		if(c==' ' || c=='\t')
			break;
	}
	if(slash < 0)
		goto Rescue;
	runemove(b+slash+1, r, n);
	free(r);
	return cleanrname(runestr(b, slash+1+n));

    Rescue:
	free(b);
	tmp = runestr(r, n);
	if(r)
		return cleanrname(tmp);
	return tmp;
}
コード例 #13
0
ファイル: text.c プロジェクト: carriercomm/plan9-gpl
void
textsetorigin(Text *t, uint org, int exact)
{
	int i, a, fixup;
	Rune *r;
	uint n;

	if(org>0 && !exact){
		/* org is an estimate of the char posn; find a newline */
		/* don't try harder than 256 chars */
		for(i=0; i<256 && org<t->file->nc; i++){
			if(textreadc(t, org) == '\n'){
				org++;
				break;
			}
			org++;
		}
	}
	a = org-t->org;
	fixup = 0;
	if(a>=0 && a<t->nchars){
		frdelete(t, 0, a);
		fixup = 1;	/* frdelete can leave end of last line in wrong selection mode; it doesn't know what follows */
	}
	else if(a<0 && -a<t->nchars){
		n = t->org - org;
		r = runemalloc(n);
		bufread(t->file, org, r, n);
		frinsert(t, r, r+n, 0);
		free(r);
	}else
		frdelete(t, 0, t->nchars);
	t->org = org;
	textfill(t);
	textscrdraw(t);
	textsetselect(t, t->q0, t->q1);
	if(fixup && t->p1 > t->p0)
		frdrawsel(t, frptofchar(t, t->p1-1), t->p1-1, t->p1, 1);
}
コード例 #14
0
ファイル: look.c プロジェクト: 9fans/plan9port
void
plumbshow(Plumbmsg *m)
{
	Window *w;
	Rune rb[256], *r;
	int nb, nr;
	Runestr rs;
	char *name, *p, namebuf[16];

	drawtopwindow();
	w = makenewwindow(nil);
	name = plumblookup(m->attr, "filename");
	if(name == nil){
		name = namebuf;
		nuntitled++;
		snprint(namebuf, sizeof namebuf, "Untitled-%d", nuntitled);
	}
	p = nil;
	if(name[0]!='/' && m->wdir!=nil && m->wdir[0]!='\0'){
		nb = strlen(m->wdir) + 1 + strlen(name) + 1;
		p = emalloc(nb);
		snprint(p, nb, "%s/%s", m->wdir, name);
		name = p;
	}
	cvttorunes(name, strlen(name), rb, &nb, &nr, nil);
	free(p);
	rs = cleanrname(runestr(rb, nr));
	winsetname(w, rs.r, rs.nr);
	r = runemalloc(m->ndata);
	cvttorunes(m->data, m->ndata, r, &nb, &nr, nil);
	textinsert(&w->body, 0, r, nr, TRUE);
	free(r);
	w->body.file->mod = FALSE;
	w->dirty = FALSE;
	winsettag(w);
	textscrdraw(&w->body);
	textsetselect(&w->tag, w->tag.file->b.nc, w->tag.file->b.nc);
	xfidlog(w, "new");
}
コード例 #15
0
ファイル: look.c プロジェクト: 9fans/plan9port
Runestr
includefile(Rune *dir, Rune *file, int nfile)
{
	int m, n;
	char *a;
	Rune *r;
	static Rune Lslash[] = { '/', 0 };

	m = runestrlen(dir);
	a = emalloc((m+1+nfile)*UTFmax+1);
	sprint(a, "%S/%.*S", dir, nfile, file);
	n = access(a, 0);
	free(a);
	if(n < 0)
		return runestr(nil, 0);
	r = runemalloc(m+1+nfile);
	runemove(r, dir, m);
	runemove(r+m, Lslash, 1);
	runemove(r+m+1, file, nfile);
	free(file);
	return cleanrname(runestr(r, m+1+nfile));
}
コード例 #16
0
ファイル: main.c プロジェクト: 99years/plan9
void
getsnarf(Runestr *rs)
{
	int i, n, nb, nulls;
	char *sn, buf[BUFSIZE];

	if(snarffd < 0)
		return;
	sn = nil;
	i = 0;
	seek(snarffd, 0, 0);
	while((n=read(snarffd, buf, sizeof(buf))) > 0){
		sn = erealloc(sn, i+n+1);
		memmove(sn+i, buf, n);
		i += n;
		sn[i] = 0;
	}
	if(i > 0){
		rs->r = runemalloc(i+1);
		cvttorunes(sn, i, rs->r, &nb, &rs->nr, &nulls);
		free(sn);
	}
}
コード例 #17
0
ファイル: util.c プロジェクト: carriercomm/plan9-gpl
/*
 * Incoming window should be locked. 
 * It will be unlocked and returned window
 * will be locked in its place.
 */
Window*
errorwinforwin(Window *w)
{
	int i, n, nincl, owner;
	Rune **incl;
	Runestr dir;
	Text *t;

	t = &w->body;
	dir = dirname(t, nil, 0);
	if(dir.nr==1 && dir.r[0]=='.'){	/* sigh */
		free(dir.r);
		dir.r = nil;
		dir.nr = 0;
	}
	incl = nil;
	nincl = w->nincl;
	if(nincl > 0){
		incl = emalloc(nincl*sizeof(Rune*));
		for(i=0; i<nincl; i++){
			n = runestrlen(w->incl[i]);
			incl[i] = runemalloc(n+1);
			runemove(incl[i], w->incl[i], n);
		}
	}
	owner = w->owner;
	winunlock(w);
	for(;;){
		w = errorwin1(dir.r, dir.nr, incl, nincl);
		winlock(w, owner);
		if(w->col != nil)
			break;
		/* window deleted too fast */
		winunlock(w);
	}
	return w;
}
コード例 #18
0
ファイル: util.c プロジェクト: grobe0ba/plan9front
Rune*
ucvt(Rune* s)
{
    Rune* u;
    char *t;
    int i, c, n, j, len;

    t = smprint("%S", s);
    n = strlen(t);
    len = 0;
    for(i=0; i<n; i++) {
        c = t[i];
        if(inclass(c, L"- /$_@.!*'(),a-zA-Z0-9"))
            len++;
        else
            len += 3;
    }
    u = runemalloc(len+1);
    j = 0;

    for(i=0; i<n; i++) {
        c = t[i];
        if(inclass(c, L"-/$_@.!*'(),a-zA-Z0-9"))
            u[j++] = c;
        else if(c == ' ')
            u[j++] = '+';
        else {
            u[j++] = '%';
            u[j++] = hexdigit((c >> 4)&15);
            u[j++] = hexdigit(c&15);
        }
    }
    u[j] = 0;
    free(t);
    return u;
}
コード例 #19
0
ファイル: text.c プロジェクト: carriercomm/plan9-gpl
void
texttype(Text *t, Rune r)
{
	uint q0, q1;
	int nnb, nb, n, i;
	int nr;
	Rune *rp;
	Text *u;

	if(t->what!=Body && r=='\n')
		return;
	nr = 1;
	rp = &r;
	switch(r){
	case Kleft:
		if(t->q0 > 0){
			typecommit(t);
			textshow(t, t->q0-1, t->q0-1, TRUE);
		}
		return;
	case Kright:
		if(t->q1 < t->file->nc){
			typecommit(t);
			textshow(t, t->q1+1, t->q1+1, TRUE);
		}
		return;
	case Kdown:
		n = t->maxlines/3;
		goto case_Down;
	case Kscrollonedown:
		n = mousescrollsize(t->maxlines);
		if(n <= 0)
			n = 1;
		goto case_Down;
	case Kpgdown:
		n = 2*t->maxlines/3;
	case_Down:
		q0 = t->org+frcharofpt(t, Pt(t->r.min.x, t->r.min.y+n*t->font->height));
		textsetorigin(t, q0, TRUE);
		return;
	case Kup:
		n = t->maxlines/3;
		goto case_Up;
	case Kscrolloneup:
		n = mousescrollsize(t->maxlines);
		goto case_Up;
	case Kpgup:
		n = 2*t->maxlines/3;
	case_Up:
		q0 = textbacknl(t, t->org, n);
		textsetorigin(t, q0, TRUE);
		return;
	case Khome:
		typecommit(t);
		textshow(t, 0, 0, FALSE);
		return;
	case Kend:
		typecommit(t);
		textshow(t, t->file->nc, t->file->nc, FALSE);
		return;
	case 0x01:	/* ^A: beginning of line */
		typecommit(t);
		/* go to where ^U would erase, if not already at BOL */
		nnb = 0;
		if(t->q0>0 && textreadc(t, t->q0-1)!='\n')
			nnb = textbswidth(t, 0x15);
		textshow(t, t->q0-nnb, t->q0-nnb, TRUE);
		return;
	case 0x05:	/* ^E: end of line */
		typecommit(t);
		q0 = t->q0;
		while(q0<t->file->nc && textreadc(t, q0)!='\n')
			q0++;
		textshow(t, q0, q0, TRUE);
		return;
	}
	if(t->what == Body){
		seq++;
		filemark(t->file);
	}
	if(t->q1 > t->q0){
		if(t->ncache != 0)
			error("text.type");
		cut(t, t, nil, TRUE, TRUE, nil, 0);
		t->eq0 = ~0;
	}
	textshow(t, t->q0, t->q0, 1);
	switch(r){
	case 0x06:
	case Kins:
		rp = textcomplete(t);
		if(rp == nil)
			return;
		nr = runestrlen(rp);
		break;	/* fall through to normal insertion case */
	case 0x1B:
		if(t->eq0 != ~0)
			textsetselect(t, t->eq0, t->q0);
		if(t->ncache > 0)
			typecommit(t);
		return;
	case 0x08:	/* ^H: erase character */
	case 0x15:	/* ^U: erase line */
	case 0x17:	/* ^W: erase word */
		if(t->q0 == 0)	/* nothing to erase */
			return;
		nnb = textbswidth(t, r);
		q1 = t->q0;
		q0 = q1-nnb;
		/* if selection is at beginning of window, avoid deleting invisible text */
		if(q0 < t->org){
			q0 = t->org;
			nnb = q1-q0;
		}
		if(nnb <= 0)
			return;
		for(i=0; i<t->file->ntext; i++){
			u = t->file->text[i];
			u->nofill = TRUE;
			nb = nnb;
			n = u->ncache;
			if(n > 0){
				if(q1 != u->cq0+n)
					error("text.type backspace");
				if(n > nb)
					n = nb;
				u->ncache -= n;
				textdelete(u, q1-n, q1, FALSE);
				nb -= n;
			}
			if(u->eq0==q1 || u->eq0==~0)
				u->eq0 = q0;
			if(nb && u==t)
				textdelete(u, q0, q0+nb, TRUE);
			if(u != t)
				textsetselect(u, u->q0, u->q1);
			else
				textsetselect(t, q0, q0);
			u->nofill = FALSE;
		}
		for(i=0; i<t->file->ntext; i++)
			textfill(t->file->text[i]);
		return;
	case '\n':
		if(t->w->autoindent){
			/* find beginning of previous line using backspace code */
			nnb = textbswidth(t, 0x15); /* ^U case */
			rp = runemalloc(nnb + 1);
			nr = 0;
			rp[nr++] = r;
			for(i=0; i<nnb; i++){
				r = textreadc(t, t->q0-nnb+i);
				if(r != ' ' && r != '\t')
					break;
				rp[nr++] = r;
			}
		}
		break; /* fall through to normal code */
	}
	/* otherwise ordinary character; just insert, typically in caches of all texts */
	for(i=0; i<t->file->ntext; i++){
		u = t->file->text[i];
		if(u->eq0 == ~0)
			u->eq0 = t->q0;
		if(u->ncache == 0)
			u->cq0 = t->q0;
		else if(t->q0 != u->cq0+u->ncache)
			error("text.type cq1");
		textinsert(u, t->q0, rp, nr, FALSE);
		if(u != t)
			textsetselect(u, u->q0, u->q1);
		if(u->ncache+nr > u->ncachealloc){
			u->ncachealloc += 10 + nr;
			u->cache = runerealloc(u->cache, u->ncachealloc);
		}
		runemove(u->cache+u->ncache, rp, nr);
		u->ncache += nr;
	}
	if(rp != &r)
		free(rp);
	textsetselect(t, t->q0+nr, t->q0+nr);
	if(r=='\n' && t->w!=nil)
		wincommit(t->w, t);
}
コード例 #20
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);
}
コード例 #21
0
ファイル: text.c プロジェクト: carriercomm/plan9-gpl
Rune*
textcomplete(Text *t)
{
	int i, nstr, npath;
	uint q;
	Rune tmp[200];
	Rune *str, *path;
	Rune *rp;
	Completion *c;
	char *s, *dirs;
	Runestr dir;

	/* control-f: filename completion; works back to white space or / */
	if(t->q0<t->file->nc && textreadc(t, t->q0)>' ')	/* must be at end of word */
		return nil;
	nstr = textfilewidth(t, t->q0, TRUE);
	str = runemalloc(nstr);
	npath = textfilewidth(t, t->q0-nstr, FALSE);
	path = runemalloc(npath);

	c = nil;
	rp = nil;
	dirs = nil;

	q = t->q0-nstr;
	for(i=0; i<nstr; i++)
		str[i] = textreadc(t, q++);
	q = t->q0-nstr-npath;
	for(i=0; i<npath; i++)
		path[i] = textreadc(t, q++);
	/* is path rooted? if not, we need to make it relative to window path */
	if(npath>0 && path[0]=='/')
		dir = (Runestr){path, npath};
	else{
		dir = dirname(t, nil, 0);
		if(dir.nr + 1 + npath > nelem(tmp)){
			free(dir.r);
			goto Return;
		}
		if(dir.nr == 0){
			dir.nr = 1;
			dir.r = runestrdup(L".");
		}
		runemove(tmp, dir.r, dir.nr);
		tmp[dir.nr] = '/';
		runemove(tmp+dir.nr+1, path, npath);
		free(dir.r);
		dir.r = tmp;
		dir.nr += 1+npath;
		dir = cleanrname(dir);
	}

	s = smprint("%.*S", nstr, str);
	dirs = smprint("%.*S", dir.nr, dir.r);
	c = complete(dirs, s);
	free(s);
	if(c == nil){
		warning(nil, "error attempting completion: %r\n");
		goto Return;
	}

	if(!c->advance){
		warning(nil, "%.*S%s%.*S*%s\n",
			dir.nr, dir.r,
			dir.nr>0 && dir.r[dir.nr-1]!='/' ? "/" : "",
			nstr, str,
			c->nmatch? "" : ": no matches in:");
		for(i=0; i<c->nfile; i++)
			warning(nil, " %s\n", c->filename[i]);
	}

	if(c->advance)
		rp = runesmprint("%s", c->string);
	else
		rp = nil;
  Return:
	freecompletion(c);
	free(dirs);
	free(str);
	free(path);
	return rp;
}
コード例 #22
0
ファイル: text.c プロジェクト: 00001/plan9port
void
texttype(Text *t, Rune r)
{
	uint q0, q1;
	int nnb, nb, n, i;
	int nr;
	Rune *rp;
	Text *u;

	if(t->what!=Body && t->what!=Tag && r=='\n')
		return;
	if(t->what == Tag)
		t->w->tagsafe = FALSE;

	nr = 1;
	rp = &r;
	switch(r){
	case Kleft:
		typecommit(t);
		if(t->q0 > 0)
			textshow(t, t->q0-1, t->q0-1, TRUE);
		return;
	case Kright:
		typecommit(t);
		if(t->q1 < t->file->b.nc)
			textshow(t, t->q1+1, t->q1+1, TRUE);
		return;
	case Kdown:
		if(t->what == Tag)
			goto Tagdown;
		n = t->fr.maxlines/3;
		goto case_Down;
	case Kscrollonedown:
		if(t->what == Tag)
			goto Tagdown;
		n = mousescrollsize(t->fr.maxlines);
		if(n <= 0)
			n = 1;
		goto case_Down;
	case Kpgdown:
		n = 2*t->fr.maxlines/3;
	case_Down:
		q0 = t->org+frcharofpt(&t->fr, Pt(t->fr.r.min.x, t->fr.r.min.y+n*t->fr.font->height));
		textsetorigin(t, q0, TRUE);
		return;
	case Kup:
		if(t->what == Tag)
			goto Tagup;
		n = t->fr.maxlines/3;
		goto case_Up;
	case Kscrolloneup:
		if(t->what == Tag)
			goto Tagup;
		n = mousescrollsize(t->fr.maxlines);
		goto case_Up;
	case Kpgup:
		n = 2*t->fr.maxlines/3;
	case_Up:
		q0 = textbacknl(t, t->org, n);
		textsetorigin(t, q0, TRUE);
		return;
	case Khome:
		typecommit(t);
		if(t->org > t->iq1) {
			q0 = textbacknl(t, t->iq1, 1);
			textsetorigin(t, q0, TRUE);
		} else
			textshow(t, 0, 0, FALSE);
		return;
	case Kend:
		typecommit(t);
		if(t->iq1 > t->org+t->fr.nchars) {
			if(t->iq1 > t->file->b.nc) {
				// should not happen, but does. and it will crash textbacknl.
				t->iq1 = t->file->b.nc;
			}
			q0 = textbacknl(t, t->iq1, 1);
			textsetorigin(t, q0, TRUE);
		} else
			textshow(t, t->file->b.nc, t->file->b.nc, FALSE);
		return;
	case 0x01:	/* ^A: beginning of line */
		typecommit(t);
		/* go to where ^U would erase, if not already at BOL */
		nnb = 0;
		if(t->q0>0 && textreadc(t, t->q0-1)!='\n')
			nnb = textbswidth(t, 0x15);
		textshow(t, t->q0-nnb, t->q0-nnb, TRUE);
		return;
	case 0x05:	/* ^E: end of line */
		typecommit(t);
		q0 = t->q0;
		while(q0<t->file->b.nc && textreadc(t, q0)!='\n')
			q0++;
		textshow(t, q0, q0, TRUE);
		return;
	case Kcmd+'c':	/* %C: copy */
		typecommit(t);
		cut(t, t, nil, TRUE, FALSE, nil, 0);
		return;
	case Kcmd+'z':	/* %Z: undo */
	 	typecommit(t);
		undo(t, nil, nil, TRUE, 0, nil, 0);
		return;

	Tagdown:
		/* expand tag to show all text */
		if(!t->w->tagexpand){
			t->w->tagexpand = TRUE;
			winresize(t->w, t->w->r, FALSE, TRUE);
		}
		return;
	
	Tagup:
		/* shrink tag to single line */
		if(t->w->tagexpand){
			t->w->tagexpand = FALSE;
			t->w->taglines = 1;
			winresize(t->w, t->w->r, FALSE, TRUE);
		}
		return;
	}
	if(t->what == Body){
		seq++;
		filemark(t->file);
	}
	/* cut/paste must be done after the seq++/filemark */
	switch(r){
	case Kcmd+'x':	/* %X: cut */
		typecommit(t);
		if(t->what == Body){
			seq++;
			filemark(t->file);
		}
		cut(t, t, nil, TRUE, TRUE, nil, 0);
		textshow(t, t->q0, t->q0, 1);
		t->iq1 = t->q0;
		return;
	case Kcmd+'v':	/* %V: paste */
		typecommit(t);
		if(t->what == Body){
			seq++;
			filemark(t->file);
		}
		paste(t, t, nil, TRUE, FALSE, nil, 0);
		textshow(t, t->q0, t->q1, 1);
		t->iq1 = t->q1;
		return;
	}
	if(t->q1 > t->q0){
		if(t->ncache != 0)
			error("text.type");
		cut(t, t, nil, TRUE, TRUE, nil, 0);
		t->eq0 = ~0;
	}
	textshow(t, t->q0, t->q0, 1);
	switch(r){
	case 0x06:	/* ^F: complete */
	case Kins:
		typecommit(t);
		rp = textcomplete(t);
		if(rp == nil)
			return;
		nr = runestrlen(rp);
		break;	/* fall through to normal insertion case */
	case 0x1B:
		if(t->eq0 != ~0) {
			if(t->eq0 <= t->q0)
				textsetselect(t, t->eq0, t->q0);
			else
				textsetselect(t, t->q0, t->eq0);
		}
		if(t->ncache > 0)
			typecommit(t);
		t->iq1 = t->q0;
		return;
	case 0x08:	/* ^H: erase character */
	case 0x15:	/* ^U: erase line */
	case 0x17:	/* ^W: erase word */
		if(t->q0 == 0)	/* nothing to erase */
			return;
		nnb = textbswidth(t, r);
		q1 = t->q0;
		q0 = q1-nnb;
		/* if selection is at beginning of window, avoid deleting invisible text */
		if(q0 < t->org){
			q0 = t->org;
			nnb = q1-q0;
		}
		if(nnb <= 0)
			return;
		for(i=0; i<t->file->ntext; i++){
			u = t->file->text[i];
			u->nofill = TRUE;
			nb = nnb;
			n = u->ncache;
			if(n > 0){
				if(q1 != u->cq0+n)
					error("text.type backspace");
				if(n > nb)
					n = nb;
				u->ncache -= n;
				textdelete(u, q1-n, q1, FALSE);
				nb -= n;
			}
			if(u->eq0==q1 || u->eq0==~0)
				u->eq0 = q0;
			if(nb && u==t)
				textdelete(u, q0, q0+nb, TRUE);
			if(u != t)
				textsetselect(u, u->q0, u->q1);
			else
				textsetselect(t, q0, q0);
			u->nofill = FALSE;
		}
		for(i=0; i<t->file->ntext; i++)
			textfill(t->file->text[i]);
		t->iq1 = t->q0;
		return;
	case '\n':
		if(t->w->autoindent){
			/* find beginning of previous line using backspace code */
			nnb = textbswidth(t, 0x15); /* ^U case */
			rp = runemalloc(nnb + 1);
			nr = 0;
			rp[nr++] = r;
			for(i=0; i<nnb; i++){
				r = textreadc(t, t->q0-nnb+i);
				if(r != ' ' && r != '\t')
					break;
				rp[nr++] = r;
			}
		}
		break; /* fall through to normal code */
	}
	/* otherwise ordinary character; just insert, typically in caches of all texts */
	for(i=0; i<t->file->ntext; i++){
		u = t->file->text[i];
		if(u->eq0 == ~0)
			u->eq0 = t->q0;
		if(u->ncache == 0)
			u->cq0 = t->q0;
		else if(t->q0 != u->cq0+u->ncache)
			error("text.type cq1");
		/*
		 * Change the tag before we add to ncache,
		 * so that if the window body is resized the
		 * commit will not find anything in ncache.
		 */
		if(u->what==Body && u->ncache == 0){
			u->needundo = TRUE;
			winsettag(t->w);
			u->needundo = FALSE;
		}
		textinsert(u, t->q0, rp, nr, FALSE);
		if(u != t)
			textsetselect(u, u->q0, u->q1);
		if(u->ncache+nr > u->ncachealloc){
			u->ncachealloc += 10 + nr;
			u->cache = runerealloc(u->cache, u->ncachealloc);
		}
		runemove(u->cache+u->ncache, rp, nr);
		u->ncache += nr;
	}
	if(rp != &r)
		free(rp);
	textsetselect(t, t->q0+nr, t->q0+nr);
	if(r=='\n' && t->w!=nil)
		wincommit(t->w, t);
	t->iq1 = t->q0;
}
コード例 #23
0
ファイル: text.c プロジェクト: carriercomm/plan9-gpl
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;
}
コード例 #24
0
ファイル: look.c プロジェクト: 9fans/plan9port
int
expandfile(Text *t, uint q0, uint q1, Expand *e)
{
	int i, n, nname, colon, eval;
	uint amin, amax;
	Rune *r, c;
	Window *w;
	Runestr rs;

	amax = q1;
	if(q1 == q0){
		colon = -1;
		while(q1<t->file->b.nc && isfilec(c=textreadc(t, q1))){
			if(c == ':'){
				colon = q1;
				break;
			}
			q1++;
		}
		while(q0>0 && (isfilec(c=textreadc(t, q0-1)) || isaddrc(c) || isregexc(c))){
			q0--;
			if(colon<0 && c==':')
				colon = q0;
		}
		/*
		 * if it looks like it might begin file: , consume address chars after :
		 * otherwise terminate expansion at :
		 */
		if(colon >= 0){
			q1 = colon;
			if(colon<t->file->b.nc-1 && isaddrc(textreadc(t, colon+1))){
				q1 = colon+1;
				while(q1<t->file->b.nc && isaddrc(textreadc(t, q1)))
					q1++;
			}
		}
		if(q1 > q0)
			if(colon >= 0){	/* stop at white space */
				for(amax=colon+1; amax<t->file->b.nc; amax++)
					if((c=textreadc(t, amax))==' ' || c=='\t' || c=='\n')
						break;
			}else
				amax = t->file->b.nc;
	}
	amin = amax;
	e->q0 = q0;
	e->q1 = q1;
	n = q1-q0;
	if(n == 0)
		return FALSE;
	/* see if it's a file name */
	r = runemalloc(n);
	bufread(&t->file->b, q0, r, n);
	/* first, does it have bad chars? */
	nname = -1;
	for(i=0; i<n; i++){
		c = r[i];
		if(c==':' && nname<0){
			if(q0+i+1<t->file->b.nc && (i==n-1 || isaddrc(textreadc(t, q0+i+1))))
				amin = q0+i;
			else
				goto Isntfile;
			nname = i;
		}
	}
	if(nname == -1)
		nname = n;
	for(i=0; i<nname; i++)
		if(!isfilec(r[i]))
			goto Isntfile;
	/*
	 * See if it's a file name in <>, and turn that into an include
	 * file name if so.  Should probably do it for "" too, but that's not
	 * restrictive enough syntax and checking for a #include earlier on the
	 * line would be silly.
	 */
	if(q0>0 && textreadc(t, q0-1)=='<' && q1<t->file->b.nc && textreadc(t, q1)=='>'){
		rs = includename(t, r, nname);
		r = rs.r;
		nname = rs.nr;
	}
	else if(amin == q0)
		goto Isfile;
	else{
		rs = dirname(t, r, nname);
		r = rs.r;
		nname = rs.nr;
	}
	e->bname = runetobyte(r, nname);
	/* if it's already a window name, it's a file */
	w = lookfile(r, nname);
	if(w != nil)
		goto Isfile;
	/* if it's the name of a file, it's a file */
	if(ismtpt(e->bname) || access(e->bname, 0) < 0){
		free(e->bname);
		e->bname = nil;
		goto Isntfile;
	}

  Isfile:
	e->name = r;
	e->nname = nname;
	e->u.at = t;
	e->a0 = amin+1;
	eval = FALSE;
	address(TRUE, nil, range(-1,-1), range(0,0), t, e->a0, amax, tgetc, &eval, (uint*)&e->a1);
	return TRUE;

   Isntfile:
	free(r);
	return FALSE;
}
コード例 #25
0
ファイル: look.c プロジェクト: 9fans/plan9port
Window*
openfile(Text *t, Expand *e)
{
	Range r;
	Window *w, *ow;
	int eval, i, n;
	Rune *rp;
	Runestr rs;
	uint dummy;

	r.q0 = 0;
	r.q1 = 0;
	if(e->nname == 0){
		w = t->w;
		if(w == nil)
			return nil;
	}else{
		w = lookfile(e->name, e->nname);
		if(w == nil && e->name[0] != '/'){
			/*
			 * Unrooted path in new window.
			 * This can happen if we type a pwd-relative path
			 * in the topmost tag or the column tags.  
			 * Most of the time plumber takes care of these,
			 * but plumber might not be running or might not
			 * be configured to accept plumbed directories.
			 * Make the name a full path, just like we would if
			 * opening via the plumber.
			 */
			n = utflen(wdir)+1+e->nname+1;
			rp = runemalloc(n);
			runesnprint(rp, n, "%s/%.*S", wdir, e->nname, e->name);
			rs = cleanrname(runestr(rp, n-1));
			free(e->name);
			e->name = rs.r;
			e->nname = rs.nr;
			w = lookfile(e->name, e->nname);
		}
	}
	if(w){
		t = &w->body;
		if(!t->col->safe && t->fr.maxlines==0) /* window is obscured by full-column window */
			colgrow(t->col, t->col->w[0], 1);
	}else{
		ow = nil;
		if(t)
			ow = t->w;
		w = makenewwindow(t);
		t = &w->body;
		winsetname(w, e->name, e->nname);
		if(textload(t, 0, e->bname, 1) >= 0)
			t->file->unread = FALSE;
		t->file->mod = FALSE;
		t->w->dirty = FALSE;
		winsettag(t->w);
		textsetselect(&t->w->tag, t->w->tag.file->b.nc, t->w->tag.file->b.nc);
		if(ow != nil){
			for(i=ow->nincl; --i>=0; ){
				n = runestrlen(ow->incl[i]);
				rp = runemalloc(n);
				runemove(rp, ow->incl[i], n);
				winaddincl(w, rp, n);
			}
			w->autoindent = ow->autoindent;
		}else
			w->autoindent = globalautoindent;
		xfidlog(w, "new");
	}
	if(e->a1 == e->a0)
		eval = FALSE;
	else{
		eval = TRUE;
		r = address(TRUE, t, range(-1,-1), range(t->q0, t->q1), e->u.at, e->a0, e->a1, e->agetc, &eval, &dummy);
		if(r.q0 > r.q1) {
			eval = FALSE;
			warning(nil, "addresses out of order\n");
		}
		if(eval == FALSE)
			e->jump = FALSE;	/* don't jump if invalid address */
	}
	if(eval == FALSE){
		r.q0 = t->q0;
		r.q1 = t->q1;
	}
	textshow(t, r.q0, r.q1, 1);
	winsettag(t->w);
	seltext = t;
	if(e->jump)
		moveto(mousectl, addpt(frptofchar(&t->fr, t->fr.p0), Pt(4, font->height-4)));
	return w;
}
コード例 #26
0
ファイル: look.c プロジェクト: 9fans/plan9port
void
look3(Text *t, uint q0, uint q1, int external)
{
	int n, c, f, expanded;
	Text *ct;
	Expand e;
	Rune *r;
	uint p;
	Plumbmsg *m;
	Runestr dir;
	char buf[32];

	ct = seltext;
	if(ct == nil)
		seltext = t;
	expanded = expand(t, q0, q1, &e);
	if(!external && t->w!=nil && t->w->nopen[QWevent]>0){
		/* send alphanumeric expansion to external client */
		if(expanded == FALSE)
			return;
		f = 0;
		if((e.u.at!=nil && t->w!=nil) || (e.nname>0 && lookfile(e.name, e.nname)!=nil))
			f = 1;		/* acme can do it without loading a file */
		if(q0!=e.q0 || q1!=e.q1)
			f |= 2;	/* second (post-expand) message follows */
		if(e.nname)
			f |= 4;	/* it's a file name */
		c = 'l';
		if(t->what == Body)
			c = 'L';
		n = q1-q0;
		if(n <= EVENTSIZE){
			r = runemalloc(n);
			bufread(&t->file->b, q0, r, n);
			winevent(t->w, "%c%d %d %d %d %.*S\n", c, q0, q1, f, n, n, r);
			free(r);
		}else
			winevent(t->w, "%c%d %d %d 0 \n", c, q0, q1, f, n);
		if(q0==e.q0 && q1==e.q1)
			return;
		if(e.nname){
			n = e.nname;
			if(e.a1 > e.a0)
				n += 1+(e.a1-e.a0);
			r = runemalloc(n);
			runemove(r, e.name, e.nname);
			if(e.a1 > e.a0){
				r[e.nname] = ':';
				bufread(&e.u.at->file->b, e.a0, r+e.nname+1, e.a1-e.a0);
			}
		}else{
			n = e.q1 - e.q0;
			r = runemalloc(n);
			bufread(&t->file->b, e.q0, r, n);
		}
		f &= ~2;
		if(n <= EVENTSIZE)
			winevent(t->w, "%c%d %d %d %d %.*S\n", c, e.q0, e.q1, f, n, n, r);
		else
			winevent(t->w, "%c%d %d %d 0 \n", c, e.q0, e.q1, f, n);
		free(r);
		goto Return;
	}
	if(plumbsendfid != nil){
		/* send whitespace-delimited word to plumber */
		m = emalloc(sizeof(Plumbmsg));
		m->src = estrdup("acme");
		m->dst = nil;
		dir = dirname(t, nil, 0);
		if(dir.nr==1 && dir.r[0]=='.'){	/* sigh */
			free(dir.r);
			dir.r = nil;
			dir.nr = 0;
		}
		if(dir.nr == 0)
			m->wdir = estrdup(wdir);
		else
			m->wdir = runetobyte(dir.r, dir.nr);
		free(dir.r);
		m->type = estrdup("text");
		m->attr = nil;
		buf[0] = '\0';
		if(q1 == q0){
			if(t->q1>t->q0 && t->q0<=q0 && q0<=t->q1){
				q0 = t->q0;
				q1 = t->q1;
			}else{
				p = q0;
				while(q0>0 && (c=tgetc(t, q0-1))!=' ' && c!='\t' && c!='\n')
					q0--;
				while(q1<t->file->b.nc && (c=tgetc(t, q1))!=' ' && c!='\t' && c!='\n')
					q1++;
				if(q1 == q0){
					plumbfree(m);
					goto Return;
				}
				sprint(buf, "click=%d", p-q0);
				m->attr = plumbunpackattr(buf);
			}
		}
		r = runemalloc(q1-q0);
		bufread(&t->file->b, q0, r, q1-q0);
		m->data = runetobyte(r, q1-q0);
		m->ndata = strlen(m->data);
		free(r);
		if(m->ndata<messagesize-1024 && plumbsendtofid(plumbsendfid, m) >= 0){
			plumbfree(m);
			goto Return;
		}
		plumbfree(m);
		/* plumber failed to match; fall through */
	}

	/* interpret alphanumeric string ourselves */
	if(expanded == FALSE)
		return;
	if(e.name || e.u.at)
		openfile(t, &e);
	else{
		if(t->w == nil)
			return;
		ct = &t->w->body;
		if(t->w != ct->w)
			winlock(ct->w, 'M');
		if(t == ct)
			textsetselect(ct, e.q1, e.q1);
		n = e.q1 - e.q0;
		r = runemalloc(n);
		bufread(&t->file->b, e.q0, r, n);
		if(search(ct, r, n) && e.jump)
			moveto(mousectl, addpt(frptofchar(&ct->fr, ct->fr.p0), Pt(4, ct->fr.font->height-4)));
		if(t->w != ct->w)
			winunlock(ct->w);
		free(r);
	}

   Return:
	free(e.name);
	free(e.bname);
}
コード例 #27
0
ファイル: xfid.c プロジェクト: fr1tz/nadir
void
xfidwrite(Xfid *x)
{
	Fcall fc;
	int c, cnt, qid, q, nb, nr, eval;
	char buf[64], *err;
	Window *w;
	Rune *r;
	Range a;
	Text *t;
	uint q0, tq0, tq1;

	qid = FILE(x->f->qid);
	w = x->f->w;
	if(w){
		c = 'F';
		if(qid==QWtag || qid==QWbody)
			c = 'E';
		winlock(w, c);
		if(w->col == nil){
			winunlock(w);
			respond(x, &fc, Edel);
			return;
		}
	}
	x->fcall.data[x->fcall.count] = 0;
	switch(qid){
	case Qcons:
		w = errorwin(x->f->mntdir, 'X');
		t=&w->body;
		goto BodyTag;

	case Qlabel:
		fc.count = x->fcall.count;
		respond(x, &fc, nil);
		break;

	case QWaddr:
		x->fcall.data[x->fcall.count] = 0;
		r = bytetorune(x->fcall.data, &nr);
		t = &w->body;
		wincommit(w, t);
		eval = TRUE;
		a = address(FALSE, t, w->limit, w->addr, r, 0, nr, rgetc, &eval, (uint*)&nb);
		free(r);
		if(nb < nr){
			respond(x, &fc, Ebadaddr);
			break;
		}
		if(!eval){
			respond(x, &fc, Eaddr);
			break;
		}
		w->addr = a;
		fc.count = x->fcall.count;
		respond(x, &fc, nil);
		break;

	case Qeditout:
	case QWeditout:
		r = bytetorune(x->fcall.data, &nr);
		if(w)
			err = edittext(w, w->wrselrange.q1, r, nr);
		else
			err = edittext(nil, 0, r, nr);
		free(r);
		if(err != nil){
			respond(x, &fc, err);
			break;
		}
		fc.count = x->fcall.count;
		respond(x, &fc, nil);
		break;

	case QWerrors:
		w = errorwinforwin(w);
		t = &w->body;
		goto BodyTag;

	case QWbody:
	case QWwrsel:
		t = &w->body;
		goto BodyTag;

	case QWctl:
		xfidctlwrite(x, w);
		break;

	case QWdata:
		a = w->addr;
		t = &w->body;
		wincommit(w, t);
		if(a.q0>t->file->b.nc || a.q1>t->file->b.nc){
			respond(x, &fc, Eaddr);
			break;
		}
		r = runemalloc(x->fcall.count);
		cvttorunes(x->fcall.data, x->fcall.count, r, &nb, &nr, nil);
		if(w->nomark == FALSE){
			seq++;
			filemark(t->file);
		}
		q0 = a.q0;
		if(a.q1 > q0){
			textdelete(t, q0, a.q1, TRUE);
			w->addr.q1 = q0;
		}
		tq0 = t->q0;
		tq1 = t->q1;
		textinsert(t, q0, r, nr, TRUE);
		if(tq0 >= q0)
			tq0 += nr;
		if(tq1 >= q0)
			tq1 += nr;
		textsetselect(t, tq0, tq1);
		if(!t->w->noscroll)
			textshow(t, q0, q0+nr, 0);
		textscrdraw(t);
		winsettag(w);
		free(r);
		w->addr.q0 += nr;
		w->addr.q1 = w->addr.q0;
		fc.count = x->fcall.count;
		respond(x, &fc, nil);
		break;

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

	case QWtag:
		t = &w->tag;
		goto BodyTag;

	BodyTag:
		q = x->f->nrpart;
		cnt = x->fcall.count;
		if(q > 0){
			memmove(x->fcall.data+q, x->fcall.data, cnt);	/* there's room; see fsysproc */
			memmove(x->fcall.data, x->f->rpart, q);
			cnt += q;
			x->f->nrpart = 0;
		}
		r = runemalloc(cnt);
		cvttorunes(x->fcall.data, cnt-UTFmax, r, &nb, &nr, nil);
		/* approach end of buffer */
		while(fullrune(x->fcall.data+nb, cnt-nb)){
			c = nb;
			nb += chartorune(&r[nr], x->fcall.data+c);
			if(r[nr])
				nr++;
		}
		if(nb < cnt){
			memmove(x->f->rpart, x->fcall.data+nb, cnt-nb);
			x->f->nrpart = cnt-nb;
		}
		if(nr > 0){
			wincommit(w, t);
			if(qid == QWwrsel){
				q0 = w->wrselrange.q1;
				if(q0 > t->file->b.nc)
					q0 = t->file->b.nc;
			}else
				q0 = t->file->b.nc;
			if(qid == QWtag)
				textinsert(t, q0, r, nr, TRUE);
			else{
				if(w->nomark == FALSE){
					seq++;
					filemark(t->file);
				}
				q0 = textbsinsert(t, q0, r, nr, TRUE, &nr);
				textsetselect(t, t->q0, t->q1);	/* insert could leave it somewhere else */
				if(qid!=QWwrsel && !t->w->noscroll)
					textshow(t, q0+nr, q0+nr, 1);
				textscrdraw(t);
			}
			winsettag(w);
			if(qid == QWwrsel)
				w->wrselrange.q1 += nr;
			free(r);
		}
		fc.count = x->fcall.count;
		respond(x, &fc, nil);
		break;

	default:
		sprint(buf, "unknown qid %d in write", qid);
		respond(x, &fc, buf);
		break;
	}
	if(w)
		winunlock(w);
}
コード例 #28
0
ファイル: util.c プロジェクト: grobe0ba/plan9front
static
void
fixtext1(Item **list)
{
    Itext *text, *ntext;
    Item *it, *prev;
    Rune *s, *s1, *s2;
    int n;

    if(*list == nil)
        return;

    prev = nil;
    for(it=*list; it!=nil; it=prev->next) {
        if(it->tag!=Itexttag || forceitem(it))
            goto Continue;

        text = (Itext *)it;
        s = text->s;
        while(*s && isspacerune(*s))
            s++;
        if(!*s) {
            if(prev == nil)
                prev = *list = it->next;
            else
                prev->next = it->next;

            it->next = nil;
            freeitems(it);
            if(prev == nil)
                return;
            continue;
        }
        n = 0;
        while(s[n] && !isspacerune(s[n]))
            n++;

        if(!s[n])
            goto Continue;

        s1 = runemalloc(n+1);
        s1 = runemove(s1, s, n);
        s1[n] = L'\0';
        s += n;

        while(*s && isspacerune(*s))
            s++;

        if(*s) {
            n = runestrlen(s);
            s2 = runemalloc(n+1);
            runemove(s2, s, n);
            s2[n] = L'\0';
            ntext = emalloc(sizeof(Itext));
            ntext->s = s2;
            ntext->ascent = text->ascent;
            ntext->anchorid = text->anchorid;
            ntext->state = text->state&~(IFbrk|IFbrksp|IFnobrk|IFcleft|IFcright);
            ntext->tag = text->tag;
            ntext->fnt = text->fnt;
            ntext->fg = text->fg;
            ntext->ul = text->ul;
            ntext->next = (Item *)text->next;
            text->next = (Item *)ntext;
        }
        free(text->s);
        text->s = s1;
Continue:
        prev = it;
    }
}