Example #1
0
void
textset(Text *t, Rune*r, int n)
{
	textdelete(t, 0, t->rs.nr);
	textinsert(t, 0, r, n);
	textsetselect(t, t->q0, t->q1);
}
Example #2
0
void
colinit(Column *c, Rectangle r)
{
	Rectangle r1;
	Text *t;

	draw(screen, r, display->white, nil, ZP);
	c->r = r;
	c->w = nil;
	c->nw = 0;
	t = &c->tag;
	t->w = nil;
	t->col = c;
	r1 = r;
	r1.max.y = r1.min.y + font->height;
	textinit(t, fileaddtext(nil, t), r1, &reffont, tagcols);
	t->what = Columntag;
	r1.min.y = r1.max.y;
	r1.max.y += Border;
	draw(screen, r1, display->black, nil, ZP);
	textinsert(t, 0, L"New Cut Paste Snarf Sort Zerox Delcol ", 38, TRUE);
	textsetselect(t, t->file->nc, t->file->nc);
	draw(screen, t->scrollr, colbutton, nil, colbutton->r.min);
	c->safe = TRUE;
}
Example #3
0
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;
}
Example #4
0
void
textinsert(Text *t, uint q0, Rune *r, uint n, int tofile)
{
	int c, i;
	Text *u;

	if(tofile && t->ncache != 0)
		error("text.insert");
	if(n == 0)
		return;
	if(tofile){
		fileinsert(t->file, q0, r, n);
		if(t->what == Body){
			t->w->dirty = TRUE;
			t->w->utflastqid = -1;
		}
		if(t->file->ntext > 1)
			for(i=0; i<t->file->ntext; i++){
				u = t->file->text[i];
				if(u != t){
					u->w->dirty = TRUE;	/* always a body */
					textinsert(u, q0, r, n, FALSE);
					textsetselect(u, u->q0, u->q1);
					textscrdraw(u);
				}
			}
					
	}
	if(q0 < t->iq1)
		t->iq1 += n;
	if(q0 < t->q1)
		t->q1 += n;
	if(q0 < t->q0)
		t->q0 += n;
	if(q0 < t->org)
		t->org += n;
	else if(q0 <= t->org+t->fr.nchars)
		frinsert(&t->fr, r, r+n, q0-t->org);
	if(t->w){
		c = 'i';
		if(t->what == Body)
			c = 'I';
		if(n <= EVENTSIZE)
			winevent(t->w, "%c%d %d 0 %d %.*S\n", c, q0, q0+n, n, n, r);
		else
			winevent(t->w, "%c%d %d 0 0 \n", c, q0, q0+n, n);
	}
}
Example #5
0
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");
}
Example #6
0
File: sele.c Project: 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);
}
Example #7
0
File: rows.c Project: 99years/plan9
void
rowinit(Row *row, Rectangle r)
{
	Rectangle r1;
	Text *t;

	draw(screen, r, display->white, nil, ZP);
	row->r = r;
	row->col = nil;
	row->ncol = 0;
	r1 = r;
	r1.max.y = r1.min.y + font->height;
	t = &row->tag;
	textinit(t, screen, r1, font, tagcols);
	t->what = Rowtag;
	t->row = row;
	t->w = nil;
	t->col = nil;
	r1.min.y = r1.max.y;
	r1.max.y += Border;
	draw(screen, r1, display->black, nil, ZP);
	textinsert(t, 0, L"Newcol Google Exit ", 19);
	textsetselect(t, t->rs.nr, t->rs.nr);
}
Example #8
0
void
rowinit(Row *row, Rectangle r)
{
	Rectangle r1;
	Text *t;

	draw(screen, r, display->white, nil, ZP);
	row->r = r;
	row->col = nil;
	row->ncol = 0;
	r1 = r;
	r1.max.y = r1.min.y + font->height;
	t = &row->tag;
	textinit(t, fileaddtext(nil, t), r1, rfget(FALSE, FALSE, FALSE, nil), tagcols);
	t->what = Rowtag;
	t->row = row;
	t->w = nil;
	t->col = nil;
	r1.min.y = r1.max.y;
	r1.max.y += Border;
	draw(screen, r1, display->black, nil, ZP);
	textinsert(t, 0, L"Newcol Kill Putall Dump Exit ", 29, TRUE);
	textsetselect(t, t->file->nc, t->file->nc);
}
Example #9
0
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);
}
Example #10
0
void
waitthread(void *v)
{
	Waitmsg *w;
	Command *c, *lc;
	uint pid;
	int found, ncmd;
	Rune *cmd;
	char *err;
	Text *t;
	Pid *pids, *p, *lastp;
	enum { WErr, WKill, WWait, WCmd, NWALT };
	Alt alts[NWALT+1];

	USED(v);
	threadsetname("waitthread");
	pids = nil;
	alts[WErr].c = cerr;
	alts[WErr].v = &err;
	alts[WErr].op = CHANRCV;
	alts[WKill].c = ckill;
	alts[WKill].v = &cmd;
	alts[WKill].op = CHANRCV;
	alts[WWait].c = cwait;
	alts[WWait].v = &w;
	alts[WWait].op = CHANRCV;
	alts[WCmd].c = ccommand;
	alts[WCmd].v = &c;
	alts[WCmd].op = CHANRCV;
	alts[NWALT].op = CHANEND;

	command = nil;
	for(;;){
		switch(alt(alts)){
		case WErr:
			qlock(&row.lk);
			warning(nil, "%s", err);
			free(err);
			flushimage(display, 1);
			qunlock(&row.lk);
			break;
		case WKill:
			found = FALSE;
			ncmd = runestrlen(cmd);
			for(c=command; c; c=c->next){
				/* -1 for blank */
				if(runeeq(c->name, c->nname-1, cmd, ncmd) == TRUE){
					if(postnote(PNGROUP, c->pid, "kill") < 0)
						warning(nil, "kill %S: %r\n", cmd);
					found = TRUE;
				}
			}
			if(!found)
				warning(nil, "Kill: no process %S\n", cmd);
			free(cmd);
			break;
		case WWait:
			pid = w->pid;
			lc = nil;
			for(c=command; c; c=c->next){
				if(c->pid == pid){
					if(lc)
						lc->next = c->next;
					else
						command = c->next;
					break;
				}
				lc = c;
			}
			qlock(&row.lk);
			t = &row.tag;
			textcommit(t, TRUE);
			if(c == nil){
				/* helper processes use this exit status */
				if(strncmp(w->msg, "libthread", 9) != 0){
					p = emalloc(sizeof(Pid));
					p->pid = pid;
					strncpy(p->msg, w->msg, sizeof(p->msg));
					p->next = pids;
					pids = p;
				}
			}else{
				if(search(t, c->name, c->nname)){
					textdelete(t, t->q0, t->q1, TRUE);
					textsetselect(t, 0, 0);
				}
				if(w->msg[0])
					warning(c->md, "%.*S: exit %s\n", c->nname-1, c->name, w->msg);
				flushimage(display, 1);
			}
			qunlock(&row.lk);
			free(w);
    Freecmd:
			if(c){
				if(c->iseditcmd)
					sendul(cedit, 0);
				free(c->text);
				free(c->name);
				fsysdelid(c->md);
				free(c);
			}
			break;
		case WCmd:
			/* has this command already exited? */
			lastp = nil;
			for(p=pids; p!=nil; p=p->next){
				if(p->pid == c->pid){
					if(p->msg[0])
						warning(c->md, "%s\n", p->msg);
					if(lastp == nil)
						pids = p->next;
					else
						lastp->next = p->next;
					free(p);
					goto Freecmd;
				}
				lastp = p;
			}
			c->next = command;
			command = c;
			qlock(&row.lk);
			t = &row.tag;
			textcommit(t, TRUE);
			textinsert(t, 0, c->name, c->nname, TRUE);
			textsetselect(t, 0, 0);
			flushimage(display, 1);
			qunlock(&row.lk);
			break;
		}
	}
}
Example #11
0
void
texttype(Text *t, Rune r)
{
	uint q0, q1;
	int nb, n;
	int nr;
	Rune *rp;

	if(t->what!=Textarea && r=='\n'){
		if(t->what==Urltag)
			get(t, t, XXX, XXX, nil, 0);
		return;
	}
	if(t->what==Tag && (r==Kscrollonedown || r==Kscrolloneup))
		return;

	nr = 1;
	rp = &r;
	switch(r){
	case Kleft:
		if(t->q0 > 0)
			textshow(t, t->q0-1, t->q0-1, TRUE);
		return;
	case Kright:
		if(t->q1 < t->rs.nr)
			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:
		textshow(t, 0, 0, FALSE);
		return;
	case Kend:
		textshow(t, t->rs.nr, t->rs.nr, FALSE);
		return;
	case 0x01:	/* ^A: beginning of line */
		/* go to where ^U would erase, if not already at BOL */
		nb = 0;
		if(t->q0>0 && t->rs.r[t->q0-1]!='\n')
			nb = textbswidth(t, 0x15);
		textshow(t, t->q0-nb, t->q0-nb, TRUE);
		return;
	case 0x05:	/* ^E: end of line */
		q0 = t->q0;
		while(q0<t->rs.nr && t->rs.r[q0]!='\n')
			q0++;
		textshow(t, q0, q0, TRUE);
		return;
	}
	if(t->q1 > t->q0)
		cut(t, t, TRUE, TRUE, nil, 0);

	textshow(t, t->q0, t->q0, TRUE);
	switch(r){
	case 0x08:	/* ^H: erase character */
	case 0x15:	/* ^U: erase line */
	case 0x17:	/* ^W: erase word */
		if(t->q0 == 0)	/* nothing to erase */
			return;
		nb = textbswidth(t, r);
		q1 = t->q0;
		q0 = q1-nb;
		/* if selection is at beginning of window, avoid deleting invisible text */
		if(q0 < t->org){
			q0 = t->org;
			nb = q1-q0;
		}
		if(nb > 0){
			textdelete(t, q0, q0+nb);
			textsetselect(t, q0, q0);
		}
		return;
	}
	/* otherwise ordinary character; just insert */
	textinsert(t, t->q0, &r, 1);
	if(rp != &r)
		free(rp);
	textsetselect(t, t->q0+nr, t->q0+nr);
	if(t->what == Textarea)
		textscrdraw(t);
}
Example #12
0
File: xfid.c Project: 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);
}
Example #13
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;
}
Example #14
0
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;
}
Example #15
0
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);
}