shithub: lola

Download patch

ref: a369f1f2450401b373cc4f10e7448e1af9579135
parent: fb7cc13fe8c7e198e6130f973448b13ac8614470
author: aap <aap@papnet.eu>
date: Mon Sep 30 15:48:40 EDT 2024

tracking front branch.

--- a/fs.c
+++ b/fs.c
@@ -443,6 +443,7 @@
 
 	rd = fid->omode==ORDWR || fid->omode==OREAD;
 	wr = fid->omode==ORDWR || fid->omode==OWRITE;
+	if(fid->omode != -1)
 	switch(QFILE(fid->qid.path)){
 	/* replace snarf buffer when /dev/snarf is closed */
 	case Qsnarf:
@@ -555,39 +556,46 @@
 }
 
 static char*
-readblocking(Req *r, Channel *readchan)
+waitblocking(Req *r, Channel *waitchan, Channel **replychan)
 {
 	Window *w;
-	Channel *chan;
-	Stringpair pair;
 	enum { Adata, Agone, Aflush, NALT };
 	Alt alts[NALT+1];
 
 	w = XF(r->fid)->w;
 
-	alts[Adata] = ALT(readchan, &chan, CHANRCV);
-	if(w)
-		alts[Agone] = ALT(w->gone, nil, CHANRCV);
-	else
-		alts[Agone] = ALT(nil, nil, CHANNOP);
+	*replychan = nil;
+	alts[Adata] = ALT(waitchan, replychan, CHANRCV);
+	alts[Agone] = w ? ALT(w->gone, nil, CHANRCV)
+			: ALT(nil, nil, CHANNOP);
 	alts[Aflush] = ALT(XR(r)->flush, nil, CHANRCV);
 	alts[NALT].op = CHANEND;
 	switch(alt(alts)){
-	case Adata:
-		pair.s = r->ofcall.data;
-		pair.ns = r->ifcall.count;
-		send(chan, &pair);
-		recv(chan, &pair);
-		r->ofcall.count = min(r->ifcall.count, pair.ns);
-		return nil;
-	case Agone:
-		return Edeleted;
-	case Aflush:
-		return Eflush;
+	case Adata: return nil;
+	case Agone: return Edeleted;
+	case Aflush: return Eflush;
 	}
-	return nil;	/* can't happen */
+	assert(0);	/* can't happen */
+	return nil;
 }
 
+static char*
+readblocking(Req *r, Channel *readchan)
+{
+	Channel *chan;
+	Stringpair pair;
+	char *err;
+
+	if(err = waitblocking(r, readchan, &chan))
+		return err;
+	pair.s = r->ofcall.data;
+	pair.ns = r->ifcall.count;
+	send(chan, &pair);
+	recv(chan, &pair);
+	r->ofcall.count = min(r->ifcall.count, pair.ns);
+	return nil;
+}
+
 static void
 xread(Req *r)
 {
@@ -679,12 +687,10 @@
 	Text *x;
 	vlong offset;
 	u32int count;
-	char *data, *p, *e;
+	char *data, *p, *e, *err;
 	Point pt;
-	Channel *kbd;
+	Channel *chan;
 	Stringpair pair;
-	enum { Adata, Agone, Aflush, NALT };
-	Alt alts[NALT+1];
 
 	xf = XF(r->fid);
 	w = xf->w;
@@ -705,25 +711,15 @@
 	switch(f){
 	case Qtext:
 	case Qcons:
-		alts[Adata] = ALT(w->conswrite, &kbd, CHANRCV);
-		alts[Agone] = ALT(w->gone, nil, CHANRCV);
-		alts[Aflush] = ALT(XR(r)->flush, nil, CHANRCV);
-		alts[NALT].op = CHANEND;
-		switch(alt(alts)){
-		case Adata:
-			cnvsize(&xf->cnv, count);
-			memmove(xf->cnv.buf+xf->cnv.n, data, count);
-			xf->cnv.n += count;
-			pair = b2r(&xf->cnv);
-			send(kbd, &pair);
-			break;
-		case Agone:
-			respond(r, Edeleted);
+		if(err = waitblocking(r, w->conswrite, &chan)){
+			respond(r, err);
 			return;
-		case Aflush:
-			respond(r, Eflush);
-			return;
 		}
+		cnvsize(&xf->cnv, count);
+		memmove(xf->cnv.buf+xf->cnv.n, data, count);
+		xf->cnv.n += count;
+		pair = b2r(&xf->cnv);
+		send(chan, &pair);
 		break;
 
 	case Qconsctl:
@@ -991,8 +987,15 @@
 	return 0;
 }
 
+static void
+srvthread(void*)
+{
+	threadsetname("fs");
+	srv(&fsys);
+}
+
 void
-fs(void)
+startfs(void)
 {
 	io9p = ioproc();
 
@@ -1003,7 +1006,7 @@
 	snprint(srvpipe, sizeof(srvpipe), "lola.%s.%lud", user, (ulong)getpid());
 	post(srvpipe, fsysfd);
 //	chatty9p++;
-	srv(&fsys);
+	threadcreate(srvthread, nil, mainstacksize);
 }
 
 int
--- a/inc.h
+++ b/inc.h
@@ -64,7 +64,7 @@
 	int posx;
 };
 
-void xinit(Text *x, Rectangle textr, Rectangle scrollr, Font *ft, Image *b, Image **cols);
+void xinit(Text *x, Rectangle textr, Rectangle scrollr, int tabwidth, Font *ft, Image *b, Image **cols);
 void xsetrects(Text *x, Rectangle textr, Rectangle scrollr);
 void xclear(Text *x);
 void xredraw(Text *x);
@@ -77,7 +77,6 @@
 void xscrdraw(Text *x);
 void xscroll(Text *x, Mousectl *mc, int but);
 void xscrolln(Text *x, int n);
-void xtickupdn(Text *x, int d);
 void xshow(Text *x, uint q0);
 void xplacetick(Text *x, uint q);
 void xtype(Text *x, Rune r);
@@ -89,7 +88,6 @@
 void xpaste(Text *x);
 void xsend(Text *x);
 int xplumb(Text *w, char *src, char *dir, int maxsize);
-void freescrtemps(void);
 
 enum
 {
@@ -118,6 +116,7 @@
 
 extern Screen *wscreen;
 extern Mousectl *mctl;
+extern int tabwidth;
 extern int scrolling;
 extern char *startdir;
 extern int shiftdown;
@@ -298,7 +297,7 @@
 
 
 extern Srv fsys;
-void fs(void);
+void startfs(void);
 int fsmount(int id);
 
 #define	runemalloc(n)		malloc((n)*sizeof(Rune))
--- a/main.c
+++ b/main.c
@@ -2,7 +2,8 @@
 
 RKeyboardctl *kbctl;
 Mousectl *mctl;
-int scrolling = 1;
+int tabwidth;
+int scrolling;
 char *startdir;
 int shiftdown;
 int gotscreen;
@@ -20,6 +21,29 @@
 			write(windows[i]->notefd, "hangup", 6);
 }
 
+static char *oknotes[] ={
+	"delete",
+	"hangup",
+	"kill",
+	"exit",
+	nil,	// for debugging
+	nil
+};
+
+int
+notehandler(void*, char *msg)
+{
+	int i;
+
+	killprocs();
+	for(i = 0; oknotes[i]; i++)
+		if(strncmp(oknotes[i], msg, strlen(oknotes[i])) == 0)
+			threadexitsall(msg);
+	fprint(2, "lola %d: abort: %s\n", getpid(), msg);
+	abort();
+	return 0;
+}
+
 /*
  * /dev/snarf updates when the file is closed, so we must open our own
  * fd here rather than use snarffd
@@ -420,57 +444,37 @@
 }
 
 
-enum {
-	Cut,
-	Paste,
-	Snarf,
-	Plumb,
-	Look,
-	Send,
-	Scroll
-};
-char *menu2str[] = {
-	"cut",
-	"paste",
-	"snarf",
-	"plumb",
-	"look",
-	"send",
-	"scroll",
-	nil
-};
-Menu menu2 = { menu2str };
-
-enum {
-	New,
-	Reshape,
-	Move,
-	Delete,
-	Hide,
-	Exit
-};
-int Hidden = Exit+1;
-char *menu3str[7 + MAXWINDOWS] = {
-	"New",
-	"Resize",
-	"Move",
-	"Delete",
-	"Hide",
-	"Exit",
-	nil
-};
-Menu menu3 = { menu3str };
-
 void
 btn2menu(Window *w)
 {
+	enum {
+		Cut,
+		Paste,
+		Snarf,
+		Plumb,
+		Look,
+		Send,
+		Scroll
+	};
+	static char *str[] = {
+		"cut",
+		"paste",
+		"snarf",
+		"plumb",
+		"look",
+		"send",
+		"scroll",
+		nil
+	};
+	static Menu menu = { str };
+
 	int sel;
 	Text *x;
 	Cursor *c;
 
 	x = &w->text;
-	menu2str[Scroll] = w->scrolling ? "noscroll" : "scroll";
-	sel = menuhit(2, mctl, &menu2, wscreen);
+	str[Scroll] = w->scrolling ? "noscroll" : "scroll";
+	sel = menuhit(2, mctl, &menu, wscreen);
 	switch(sel){
 	case Cut:
 		xsnarf(x);
@@ -508,6 +512,26 @@
 void
 btn3menu(void)
 {
+	enum {
+		New,
+		Reshape,
+		Move,
+		Delete,
+		Hide,
+		Exit
+	};
+	int Hidden = Exit+1;
+	static char *str[7 + MAXWINDOWS] = {
+		"New",
+		"Resize",
+		"Move",
+		"Delete",
+		"Hide",
+		"Exit",
+		nil
+	};
+	static Menu menu = { str };
+
 	static Window *hidden[MAXWINDOWS];
 	int nhidden;
 	Window *w, *t;
@@ -518,13 +542,13 @@
 		t = windows[i];
 		if(t->hidden || obscured(t, t->img->r, t->higher)){
 			hidden[nhidden] = windows[i];
-			menu3str[nhidden+Hidden] = windows[i]->label;
+			str[nhidden+Hidden] = windows[i]->label;
 			nhidden++;	
 		}
 	}
-	menu3str[nhidden+Hidden] = nil;
+	str[nhidden+Hidden] = nil;
 
-	sel = menuhit(3, mctl, &menu3, wscreen);
+	sel = menuhit(3, mctl, &menu, wscreen);
 	switch(sel){
 	case New:
 		sweep(nil);
@@ -572,6 +596,7 @@
 		cursorwin = w;
 again:
 		if(w == nil){
+			/* background */
 			setcursornormal(nil);
 			if(mctl->buttons & 4)
 				btn3menu();
@@ -587,9 +612,10 @@
 					bandresize(w);
 			}
 		}else if(w != focused){
+			/* inactive window */
 			wsetcursor(w);
 			if(mctl->buttons & 7 ||
-			   mctl->buttons & (8|16) && focused->mouseopen){
+			   mctl->buttons & (8|16) && focused && focused->mouseopen){
 				wraise(w);
 				wfocus(w);
 				if(mctl->buttons & 1)
@@ -598,6 +624,7 @@
 					goto again;
 			}
 		}else if(!w->mouseopen){
+			/* active text window */
 			wsetcursor(w);
 			if(mctl->buttons && topwin != w)
 				wraise(w);
@@ -611,6 +638,7 @@
 			if(mctl->buttons & 4)
 				btn3menu();
 		}else{
+			/* active graphics window */
 			wsetcursor(w);
 			drainmouse(mctl, w);
 		}
@@ -632,7 +660,6 @@
 			sysfatal("resize failed: %r");
 		nr = screen->clipr;
 
-		freescrtemps();
 		freescreen(wscreen);
 		wscreen = allocscreen(screen, background, 0);
 		draw(screen, screen->r, background, nil, ZP);
@@ -761,16 +788,71 @@
 }
 
 void
-threadmain(int, char *[])
+initcmd(void *arg)
 {
+	char *cmd;
+	char *wsys;
+	int fd;
+
+	cmd = arg;
+	rfork(RFENVG|RFFDG|RFNOTEG|RFNAMEG);
+	wsys = getenv("wsys");
+	fd = open(wsys, ORDWR);
+	if(fd < 0)
+		fprint(2, "lola: failed to open wsys: %r\n");
+	if(mount(fd, -1, "/mnt/wsys", MREPL, "none") < 0)
+		fprint(2, "lola: failed to mount wsys: %r\n");
+	if(bind("/mnt/wsys", "/dev/", MBEFORE) < 0)
+		fprint(2, "lola: failed to bind wsys: %r\n");
+	free(wsys);
+	close(fd);
+	procexecl(nil, "/bin/rc", "rc", "-c", cmd, nil);
+	fprint(2, "lola: exec failed: %r\n");
+	exits("exec");
+}
+
+void
+usage(void)
+{
+	fprint(2, "usage: lola [-i initcmd] [-s]\n");
+	exits("usage");
+}
+
+void
+threadmain(int argc, char *argv[])
+{
+	char *initstr, *s;
 	char buf[256];
-//rfork(RFENVG);
-//newwindow("-dx 1280 -dy 800");
+if(strcmp(argv[0]+1, ".out") == 0){
+rfork(RFENVG);
+newwindow("-dx 1280 -dy 800");
+scrolling = TRUE;
+oknotes[nelem(oknotes)-2] = "interrupt";
+}
 
+	initstr = nil;
+	ARGBEGIN{
+	case 'i':
+		initstr = EARGF(usage());
+		break;
+	case 's':
+		scrolling = TRUE;
+		break;
+	default:
+		usage();
+	}ARGEND
+
 	if(getwd(buf, sizeof(buf)) == nil)
 		startdir = estrdup(".");
 	else
 		startdir = estrdup(buf);
+	s = getenv("tabstop");
+	if(s)
+		tabwidth = strtol(s, nil, 0);
+	if(tabwidth == 0)
+		tabwidth = 4;
+	free(s);
+
 	if(initdraw(nil, nil, "lola") < 0)
 		sysfatal("initdraw: %r");
 	kbctl = initkbd(nil, nil);
@@ -800,6 +882,10 @@
 
 	flushimage(display, 1);
 
-	fs();
-	// not reached
+	startfs();
+
+	if(initstr)
+		proccreate(initcmd, initstr, mainstacksize);
+
+	threadnotify(notehandler, 1);
 }
--- a/text.c
+++ b/text.c
@@ -8,9 +8,11 @@
 };
 
 void
-xinit(Text *x, Rectangle textr, Rectangle scrollr, Font *ft, Image *b, Image **cols)
+xinit(Text *x, Rectangle textr, Rectangle scrollr, int tabwidth, Font *ft, Image *b, Image **cols)
 {
+	frclear(x, FALSE);
 	frinit(x, textr, ft, b, cols);
+	x->maxtab = x->maxtab/8*tabwidth;
 	x->i = b;
 	x->scrollr = scrollr;
 	x->lastsr = ZR;
@@ -111,6 +113,7 @@
 		w->org += n;
 	else if(q0 <= w->org+w->nchars)
 		frinsert(w, r, r+n, q0-w->org);
+	xscrdraw(w);
 	return q0;
 }
 
@@ -271,29 +274,6 @@
  * Scrolling
  */
 
-static Image *scrtmp;
-
-static Image*
-scrtemps(void)
-{
-	int h;
-
-	if(scrtmp == nil){
-		h = BIG*Dy(screen->r);
-		scrtmp = allocimage(display, Rect(0, 0, 32, h), screen->chan, 0, DNofill);
-	}
-	return scrtmp;
-}
-
-void
-freescrtemps(void)
-{
-	if(scrtmp){
-		freeimage(scrtmp);
-		scrtmp = nil;
-	}
-}
-
 static Rectangle
 scrpos(Rectangle r, uint p0, uint p1, uint tot)
 {
@@ -325,27 +305,17 @@
 void
 xscrdraw(Text *w)
 {
-	Rectangle r, r1, r2;
-	Image *b;
+	Rectangle r1, r2;
 
-	b = scrtemps();
-	if(b == nil || w->i == nil)
+	if(w->i == nil)
 		return;
-	r = w->scrollr;
-	r1 = r;
-	r1.min.x = 0;
-	r1.max.x = Dx(r);
+
+	r1 = w->scrollr;
 	r2 = scrpos(r1, w->org, w->org+w->nchars, w->nr);
 	if(!eqrect(r2, w->lastsr)){
 		w->lastsr = r2;
-		/* move r1, r2 to (0,0) to avoid clipping */
-		r2 = rectsubpt(r2, r1.min);
-		r1 = rectsubpt(r1, r1.min);
-		draw(b, r1, w->cols[BORD], nil, ZP);
-		draw(b, r2, w->cols[BACK], nil, ZP);
-		r2.min.x = r2.max.x-1;
-		draw(b, r2, w->cols[BORD], nil, ZP);
-		draw(w->i, r, b, nil, Pt(0, r1.min.y));
+		draw(w->i, r1, w->cols[BORD], nil, ZP);
+		draw(w->i, insetrect(r2,1), w->cols[BACK], nil, ZP);
 	}
 }
 
@@ -468,30 +438,6 @@
 	xsetorigin(x, q0, TRUE);
 }
 
-/* move tick up or down while staying at the same x position */
-void
-xtickupdn(Text *x, int d)
-{
-	Point p;
-	int py;
-	uint q0;
-
-	xshow(x, x->q0);
-	p = frptofchar(x, x->q0-x->org);
-	if(x->posx >= 0)
-		p.x = x->posx;
-	py = p.y;
-	p.y += d*x->font->height;
-	if(p.y < x->Frame.r.min.y ||
-	   p.y > x->Frame.r.max.y-x->font->height){
-		xscrolln(x, d);
-		p.y = py;
-	}
-	q0 = x->org+frcharofpt(x, p);
-	xsetselect(x, q0, q0);
-	x->posx = p.x;
-}
-
 static Text	*selecttext;
 static Mousectl *selectmc;
 static uint	selectq;
@@ -531,7 +477,7 @@
 int
 iswordrune(Rune r)
 {
-	return isalpharune(r) || isdigitrune(r);
+	return r == '_' || isalpharune(r) || isdigitrune(r);
 }
 
 static int
--- a/wctl.c
+++ b/wctl.c
@@ -87,10 +87,10 @@
 	while(*s!='\0' && !isspacerune(*s))
 		s++;
 	for(i=0; tab[i]!=nil; i++)
-		if(strncmp(tab[i], t, strlen(tab[i])) == 0){
+		if(s-t > 0 && strncmp(tab[i], t, s-t) == 0){
 			*sp = s;
 			return i;
-	}
+		}
 	return -1;
 }
 
--- a/wind.c
+++ b/wind.c
@@ -76,11 +76,20 @@
 	w->text.cols[TEXT] = colors[c];
 }
 
+/* get rid of the window visually */
 static void
+wremove(Window *w)
+{
+	if(w->img)
+		originwindow(w->img, w->img->r.min, screen->r.max);
+}
+
+static void
 wsetsize(Window *w, Rectangle r)
 {
 	Rectangle hr;
 
+	wremove(w);
 	if(w->img)
 		freeimage(w->img);
 	if(w->hidden){
@@ -89,9 +98,10 @@
 		originwindow(w->img, r.min, hr.min);
 	}else
 		w->img = allocwindow(wscreen, r, Refbackup, DNofill);
+	w->mc.image = w->img;
 	wcalcrects(w);
 	draw(w->img, w->img->r, colors[BACK], nil, ZP);
-	xinit(&w->text, w->textr, w->scrollr, font, w->img, colors);
+	xinit(&w->text, w->textr, w->scrollr, tabwidth, font, w->img, colors);
 }
 
 static int id = 1;
@@ -117,7 +127,6 @@
 	windows[nwindows++] = w;
 
 	w->mc.c = chancreate(sizeof(Mouse), 16);
-
 	w->gone = chancreate(sizeof(int), 0);
 	w->kbd = chancreate(sizeof(char*), 16);
 	w->ctl = chancreate(sizeof(int), 0);
@@ -175,12 +184,10 @@
 			memmove(&windows[i], &windows[i+1], (nwindows-i)*sizeof(Window*));
 			break;
 		}
-	if(w->img){
-		/* rio does this, not sure if useful */
-		originwindow(w->img, w->img->r.min, screen->r.max);
+	if(w->img)
 		freeimage(w->img);
-	}
 	w->img = nil;
+	w->mc.image = nil;
 	flushimage(display, 1);
 }
 
@@ -198,11 +205,12 @@
 		/* increment ref count temporarily
 		 * so win thread doesn't exit too early */
 		incref(w);
+		wremove(w);
 		wunfocus(w);
 		wclose(w);
+		decref(w);
 		if(!inwinthread(w))
 			wsendmsg(w, Wakeup);
-		decref(w);
 	}else
 		assert(w->ref > 0);
 }
@@ -294,6 +302,7 @@
 void
 wdelete(Window *w)
 {
+	wremove(w);
 	wunfocus(w);
 	wsendmsg(w, Deleted);
 }
@@ -416,10 +425,10 @@
 	if(w->hidden)
 		return -1;
 	incref(w);
+	wremove(w);
 	wunfocus(w);
 	w->hidden = TRUE;
 	w->wctlready = TRUE;
-	originwindow(w->img, w->img->r.min, screen->r.max);
 	wsendmsg(w, Wakeup);
 	wrelease(w);
 	return 1;
@@ -959,7 +968,7 @@
 			break;
 
 		case AComplete:
-			if(w->img!=nil){
+			if(w->img){
 				if(!comp->advance)
 					showcandidates(w, comp);
 				if(comp->advance){