shithub: lola

Download patch

ref: 9c6036c190a4c6d39f89b1033214620ec9d19ba0
parent: c57b0fc5c3450b175f0896e0238ea3431fde6448
author: aap <[email protected]>
date: Mon Sep 30 15:48:10 EDT 2024

tracking front branch.

--- a/data.c
+++ b/data.c
@@ -176,6 +176,9 @@
 {
 	Image *img;
 
+	if(name == nil)
+		return mkcolor(col);
+
 	name = smprint("th_%s", name);
 
 	img = namedimage(display, name);
@@ -209,16 +212,6 @@
 void
 initdata(void)
 {
-	background = getcolor("background", 0x777777FF);
-	colors[BACK] = getcolor("back", 0xFFFFFFFF);
-	colors[HIGH] = getcolor("high", 0xCCCCCCFF);
-	colors[BORD] = getcolor("bord", 0x999999FF);
-	colors[TEXT] = getcolor("text", 0x000000FF);
-	colors[HTEXT] = getcolor("htext", 0x000000FF);
-	colors[PALETEXT] = getcolor("paletext", 0x666666FF);
-	colors[HOLDTEXT] = getcolor("holdtext", DMedblue);
-	colors[PALEHOLDTEXT] = getcolor("paleholdtext", DGreyblue);
-
 	// this is probably dumb.
 	pal[0] = mkcolor(0x00000000);
 	pal[1] = mkcolor(0x000000FF);
@@ -230,4 +223,24 @@
 	pal[7] = mkcolor(0xC0C7C8FF);
 
 	inittheme();
+
+	/* these might have already been set by the theme */
+	if(background == nil)
+		background = getcolor("background", 0x777777FF);
+	if(colors[BACK] == nil)
+		colors[BACK] = getcolor("back", 0xFFFFFFFF);
+	if(colors[HIGH] == nil)
+		colors[HIGH] = getcolor("high", 0xCCCCCCFF);
+	if(colors[BORD] == nil)
+		colors[BORD] = getcolor("bord", 0x999999FF);
+	if(colors[TEXT] == nil)
+		colors[TEXT] = getcolor("text", 0x000000FF);
+	if(colors[HTEXT] == nil)
+		colors[HTEXT] = getcolor("htext", 0x000000FF);
+	if(colors[PALETEXT] == nil)
+		colors[PALETEXT] = getcolor("paletext", 0x666666FF);
+	if(colors[HOLDTEXT] == nil)
+		colors[HOLDTEXT] = getcolor("holdtext", DMedblue);
+	if(colors[PALEHOLDTEXT] == nil)
+		colors[PALEHOLDTEXT] = getcolor("paleholdtext", DGreyblue);
 }
--- a/flat.c
+++ b/flat.c
@@ -23,23 +23,26 @@
 {
 	if(w->frame == nil)
 		return;
-	int c = w->holdmode ?
-		w == focused ? TITLEHOLD : LTITLEHOLD :
-		w == focused ? TITLE : LTITLE;
+	int c = wcolsel(w);
+	int tc = TITLE + wcolsel(w);
 
-	Rectangle r = w->frame->r;
+	Rectangle r;
+	int margin;
 
 	if(!w->noborder){
+		r = w->frame->r;
 		border(w->frame, r, bordersz, wincolors[c], ZP);
-		r = insetrect(r, bordersz);
 	}
 
 	if(!w->notitle){
+		r = w->titlerect;
 		r.max.y = r.min.y + titlesz;
-		draw(w->frame, r, wincolors[c], nil, ZP);
+		draw(w->frame, r, wincolors[tc], nil, ZP);
 
-		Point pt = Pt(r.min.x, r.min.y);
-		string(w->frame, pt, wincolors[c+4], pt, font, w->label);
+		margin = w->noborder ? titlesz : titlesz + bordersz;
+		margin = (margin - font->height)/2;
+		Point pt = Pt(r.min.x, w->frame->r.min.y + margin + 1);
+		string(w->frame, pt, wincolors[TITLETEXT+c], pt, font, w->label);
 	}
 }
 
--- a/fs.c
+++ b/fs.c
@@ -464,6 +464,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:
@@ -576,39 +577,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)
 {
@@ -708,12 +716,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;
@@ -734,25 +740,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:
--- 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);
@@ -110,6 +109,7 @@
 extern Cursor *corners[9];
 void initdata(void);
 
+extern int tabwidth;
 extern bool scrolling;
 extern bool notitle;
 extern int ndeskx;
@@ -251,6 +251,7 @@
 extern Window *focused, *cursorwin;
 extern Point screenoff;
 
+int wcolsel(Window *w);
 void wtitlectl(Window *w);
 void wdecor(Window *w);
 void wmaximize(Window *w);
@@ -270,7 +271,7 @@
 void wraise(Window *w);
 void wlower(Window *w);
 void wfocus(Window *w);
-void wremove(Window *w);
+void wunfocus(Window *w);
 int whide(Window *w);
 int wunhide(Window *w);
 void wsethold(Window *w, int hold);
--- a/main.c
+++ b/main.c
@@ -1,5 +1,6 @@
 #include "inc.h"
 
+int tabwidth;
 bool scrolling;
 bool notitle;
 int ndeskx = 3;
@@ -463,7 +464,7 @@
 		Send,
 		Scroll
 	};
-	static char *menu2str[] = {
+	static char *str[] = {
 		"cut",
 		"paste",
 		"snarf",
@@ -473,7 +474,7 @@
 		"scroll",
 		nil
 	};
-	static Menu menu2 = { menu2str };
+	static Menu menu = { str };
 
 	int sel;
 	Text *x;
@@ -480,8 +481,8 @@
 	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);
@@ -683,7 +684,8 @@
 				}else{
 					/* title bar */
 					setcursornormal(nil);
-					wtitlectl(w);
+					if(ptinrect(mctl->xy, w->titlerect))
+						wtitlectl(w);
 				}
 			}else if(w != focused){
 				/* inactive window */
@@ -922,7 +924,7 @@
 void
 threadmain(int argc, char *argv[])
 {
-	char *initstr;
+	char *initstr, *s;
 	char buf[256];
 if(strcmp(argv[0]+1, ".out") == 0){
 rfork(RFENVG);
@@ -951,6 +953,13 @@
 		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);
@@ -969,6 +978,9 @@
 	gotscreen = access("/dev/screen", AEXIST)==0;
 
 	initdata();
+	/* hack to get menu colors referenced,
+	 * so setting them with initstr will work */
+	btn12menu();
 
 	wscreen = allocscreen(screen, background, 0);
 	fakebg = allocwindow(wscreen, screen->r, Refbackup, DNofill);
--- a/simple.c
+++ b/simple.c
@@ -26,7 +26,6 @@
 {
 	USED(down);
 
-//	border(img, r, 1, col, ZP);
 	r = centerrect(r, icon->r);
 	draw(img, r, col, icon, ZP);
 }
@@ -56,40 +55,40 @@
 {
 	if(w->frame == nil)
 		return;
-	int c = w->holdmode ?
-		w == focused ? TITLEHOLD : LTITLEHOLD :
-		w == focused ? TITLE : LTITLE;
-	int c2 = w == focused ? FRAME : LFRAME;
+	int sel = wcolsel(w);
+	int c = TITLE + sel;
+	int c1 = TITLETEXT + sel;
+	int c2 = FRAME + (sel&1);
 
 	Rectangle r, b1, b2, b3;
+	int margin;
 
 	if(!w->noborder){
 		r = w->frame->r;
 		border(w->frame, r, bordersz, wincolors[c], ZP);
 		border(w->frame, r, 1, wincolors[c2], ZP);
-		border(w->frame, insetrect(w->contrect,-1), 1, wincolors[c2], ZP);
 	}
 
 	if(!w->notitle){
 		r = w->titlerect;
-		r.max.y--;
 		draw(w->frame, r, wincolors[c], nil, ZP);
 
 		b1 = r;
-b1.max.x -= bordersz/2;
+		b1.max.x -= bordersz/2;
 		b1.min.x = b1.max.x - titlesz + bordersz;
 		b1.max.y = b1.min.y + Dx(b1);
 		b2 = rectsubpt(b1, Pt(titlesz, 0));
 		b3 = rectsubpt(b2, Pt(titlesz, 0));
-		btn(w->frame, b1, wincolors[c+4], icons[3], 0);
-		btn(w->frame, b2, wincolors[c+4], icons[1+w->maximized], 0);
-		btn(w->frame, b3, wincolors[c+4], icons[0], 0);
+		btn(w->frame, b1, wincolors[c1], icons[3], 0);
+		btn(w->frame, b2, wincolors[c1], icons[1+w->maximized], 0);
+		btn(w->frame, b3, wincolors[c1], icons[0], 0);
 
-r.min.x += bordersz/2;
-r.min.y -= 2;
-		Point pt = Pt(r.min.x, r.min.y);
-		string(w->frame, pt, wincolors[c+4], pt, font, w->label);
+		margin = w->noborder ? titlesz : titlesz + bordersz;
+		margin = (margin - font->height)/2;
+		Point pt = Pt(r.min.x, w->frame->r.min.y + margin + 1);
+		string(w->frame, pt, wincolors[c1], pt, font, w->label);
 	}
+	border(w->frame, insetrect(w->contrect,-1), 1, wincolors[c2], ZP);
 }
 
 void
@@ -99,25 +98,20 @@
 		wraise(w);
 		wfocus(w);
 		if(mctl->buttons & 1) {
-			int c = w->holdmode ?
-				w == focused ? TITLEHOLD : LTITLEHOLD :
-				w == focused ? TITLE : LTITLE;
+			int c = TITLETEXT + wcolsel(w);
 
 			Rectangle r = w->titlerect;
+			r.max.x -= bordersz/2;
 			Rectangle br = Rect(0,0,titlesz-bordersz,titlesz-bordersz);
-r.max.x -= bordersz/2;
 			Rectangle br1 = rectaddpt(br, Pt(r.max.x-titlesz+bordersz, r.min.y));
 			Rectangle br2 = rectsubpt(br1, Pt(titlesz, 0));
 			Rectangle br3 = rectsubpt(br2, Pt(titlesz, 0));
-			// hack...
-			if(w->notitle)
-				br1 = br2 = br3 = Rect(0,0,0,0);
 
 			if(ptinrect(mctl->xy, br1)){
-				if(btnctl(w->frame, br1, wincolors[c+4], icons[3]))
+				if(btnctl(w->frame, br1, wincolors[c], icons[3]))
 					wdelete(w);
 			}else if(ptinrect(mctl->xy, br2)){
-				if(btnctl(w->frame, br2, wincolors[c+4], icons[1+w->maximized])){
+				if(btnctl(w->frame, br2, wincolors[c], icons[1+w->maximized])){
 					if(w->maximized)
 						wrestore(w);
 					else
@@ -124,7 +118,7 @@
 						wmaximize(w);
 				}
 			}else if(ptinrect(mctl->xy, br3)){
-				if(btnctl(w->frame, br3, wincolors[c+4], icons[0]))
+				if(btnctl(w->frame, br3, wincolors[c], icons[0]))
 					whide(w);
 			}else if(!w->maximized)
 				grab(w, 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;
@@ -434,30 +436,6 @@
 	else
 		q0 = x->org+frcharofpt(x, Pt(x->Frame.r.min.x, x->Frame.r.min.y+n*x->font->height));
 	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;
--- a/wctl.c
+++ b/wctl.c
@@ -8,7 +8,7 @@
 char	Ewalloc[]		= "window allocation failed in wctl request";
 
 /* >= Top are disallowed if mouse button is pressed.
- * >= New need a window. */
+ * > New need a window. */
 enum
 {
 	Screenoffset,
@@ -104,10 +104,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;
 }
 
@@ -139,6 +139,8 @@
 Rectangle
 rectonscreen(Rectangle r)
 {
+//TODO(vdesk) this changes
+return r;
 	shift(&r.min.x, &r.max.x, screen->r.min.x, screen->r.max.x);
 	shift(&r.min.y, &r.max.y, screen->r.min.y, screen->r.max.y);
 	return r;
@@ -423,7 +425,7 @@
 
 	switch(cmd.cmd){
 	case Screenoffset:
-		screenoffset(r.min.x, r.min.y);
+		screenoffset(cmd.r.min.x, cmd.r.min.y);
 		return nil;
 	case Screenrefresh:
 		refresh();
--- a/win3.c
+++ b/win3.c
@@ -102,10 +102,12 @@
 	if(w->frame == nil)
 		return;
 
-	Rectangle r = w->frame->r;
+	int inact = w != focused;
+	Rectangle r;
 
 	if(!w->noborder){
-		border(w->frame, r, bordersz, wincolors[w == focused ? ColBorder : ColBorderInact], ZP);
+		r = w->frame->r;
+		border(w->frame, r, bordersz, wincolors[ColBorder + inact], ZP);
 		border(w->frame, r, 1, wincolors[ColFrame], ZP);
 		border(w->frame, insetrect(r,3), 1, wincolors[ColFrame], ZP);
 
@@ -128,8 +130,9 @@
 	}
 
 	if(!w->notitle){
-		r.max.y = r.min.y + titlesz-1;
-		draw(w->frame, r, wincolors[w == focused ? ColTitle : ColTitleInact], nil, ZP);
+		r = w->titlerect;
+		r.max.y -= 1;
+		draw(w->frame, r, wincolors[ColTitle + inact], nil, ZP);
 		draw(w->frame, Rect(r.min.x,r.max.y,r.max.x,r.max.y+1), wincolors[ColFrame], nil, ZP);
 
 		// menu
@@ -139,18 +142,18 @@
 
 		// max/restore
 		br.max.x = r.max.x;
-		br.min.x = br.max.x-titlesz-1;
+		br.min.x = br.max.x-titlesz+1;
 		winbtn(w->frame, br, icons[1+w->maximized], 0);
 		border(w->frame, insetrect(br,-1), 1, display->black, ZP);
 
 		// min
-		br = rectaddpt(br, Pt(-titlesz-2,0));
+		br = rectaddpt(br, Pt(-titlesz,0));
 		winbtn(w->frame, br, icons[0], 0);
 		border(w->frame, insetrect(br,-1), 1, display->black, ZP);
 
 		int sp = (Dx(r)-stringwidth(font, w->label))/2;
 		Point pt = Pt(r.min.x+sp, r.min.y);
-		string(w->frame, pt, wincolors[w == focused ? ColTitleText : ColTitleTextInact], pt, font, w->label);
+		string(w->frame, pt, wincolors[ColTitleText + inact], pt, font, w->label);
 	}
 }
 
@@ -166,11 +169,8 @@
 				r = insetrect(r, bordersz);
 			Rectangle br = Rect(0,0,titlesz-1,titlesz-1);
 			Rectangle br1 = rectaddpt(br, r.min);
-			Rectangle br2 = rectaddpt(br1, Pt(Dx(r)-titlesz-1, 0));
-			Rectangle br3 = rectaddpt(br2, Pt(-titlesz-2, 0));
-			// hack...
-			if(w->notitle)
-				br1 = br2 = br3 = Rect(0,0,0,0);
+			Rectangle br2 = rectaddpt(br1, Pt(Dx(r)-titlesz+1, 0));
+			Rectangle br3 = rectaddpt(br2, Pt(-titlesz, 0));
 
 			if(ptinrect(mctl->xy, br1)){
 				if(winbtnctlflat(w->frame, br1, icons[3], icons[4]))
--- a/win95.c
+++ b/win95.c
@@ -74,17 +74,19 @@
 	if(w->frame == nil)
 		return;
 
-	Rectangle r = w->frame->r;
+	int inact = w != focused;
+	Rectangle r;
 
 	if(!w->noborder){
+		r = w->frame->r;
 		border(w->frame, r, bordersz, wincolors[ColDefault], ZP);
 		winframe(w->frame, r);
-		r = insetrect(r, bordersz);
 	}
 
 	if(!w->notitle){
-		r.max.y = r.min.y + titlesz-1;
-		draw(w->frame, r, wincolors[w == focused ? ColTitle : ColTitleInact], nil, ZP);
+		r = w->titlerect;
+		r.max.y -= 1;
+		draw(w->frame, r, wincolors[ColTitle + inact], nil, ZP);
 		draw(w->frame, Rect(r.min.x,r.max.y,r.max.x,r.max.y+1), wincolors[ColDefault], nil, ZP);
 
 		// draw buttons
@@ -100,7 +102,7 @@
 		draw(w->frame, br, icons[4], icons[4], ZP);
 
 		Point pt = Pt(r.min.x + 2 + titlesz-1, r.min.y);
-		string(w->frame, pt, wincolors[w == focused ? ColTitleText : ColTitleTextInact], pt, font, w->label);
+		string(w->frame, pt, wincolors[ColTitleText + inact], pt, font, w->label);
 	}
 }
 
@@ -111,17 +113,12 @@
 		wraise(w);
 		wfocus(w);
 		if(mctl->buttons & 1) {
-			Rectangle r = w->frame->r;
-			if(!w->noborder)
-				r = insetrect(r, bordersz);
-			r.max.y = r.min.y + titlesz-1;
+			Rectangle r = w->titlerect;
+			r.max.y -= 1;
 			Rectangle br1 = insetrect(r, 2);
 			br1.min.x = br1.max.x - Dy(br1) - 2;
 			Rectangle br2 = rectaddpt(br1, Pt(-Dx(br1)-2, 0));
 			Rectangle br3 = rectaddpt(br1, Pt(-2*Dx(br1)-2, 0));
-			// hack...
-			if(w->notitle)
-				br1 = br2 = br3 = Rect(0,0,0,0);
 
 			if(ptinrect(mctl->xy, br1)){
 				if(winbtnctl(w->frame, br1, icons[3]))
--- a/wind.c
+++ b/wind.c
@@ -83,9 +83,16 @@
 	w->textr.min.x = w->scrollr.max.x + 4;
 }
 
+int
+wcolsel(Window *w)
+{
+	return (w != focused) + w->holdmode*2;
+}
+
 void
 wsetcolors(Window *w)
 {
+// TODO: this should use wcolsel
 	int c = w->holdmode ?
 		w == focused ? HOLDTEXT : PALEHOLDTEXT :
 		w == focused ? TEXT : PALETEXT;
@@ -92,7 +99,15 @@
 	w->text.cols[TEXT] = colors[c];
 }
 
+/* get rid of the window visually */
 static void
+wremove(Window *w)
+{
+	if(w->frame)
+		originwindow(w->frame, w->frame->r.min, screen->r.max);
+}
+
+static void
 wfreeimages(Window *w)
 {
 	if(w->frame == nil)
@@ -129,7 +144,7 @@
 	w->content = allocwindow(s, w->contrect, Refnone, DNofill);
 	assert(w->content);
 	draw(w->frame, w->frame->r, colors[BACK], nil, ZP);
-	xinit(&w->text, w->textr, w->scrollr, font, w->content, colors);
+	xinit(&w->text, w->textr, w->scrollr, tabwidth, font, w->content, colors);
 
 	wrepaint(w);
 }
@@ -233,6 +248,7 @@
 		 * so win thread doesn't exit too early */
 		incref(w);
 		wremove(w);
+		wunfocus(w);
 		wclose(w);
 		decref(w);
 		if(!inwinthread(w))
@@ -330,6 +346,7 @@
 wdelete(Window *w)
 {
 	wremove(w);
+	wunfocus(w);
 	wsendmsg(w, Deleted);
 }
 
@@ -421,13 +438,9 @@
 	wfocuschanged(focused);
 }
 
-/* Take away focus but also get rid of the window visually.
- * For hiding/deleting */
 void
-wremove(Window *w)
+wunfocus(Window *w)
 {
-	if(!w->deleted)
-		originwindow(w->frame, w->frame->r.min, screen->r.max);
 	if(w == focused)
 		wfocus(nil);
 }
@@ -439,6 +452,7 @@
 		return -1;
 	incref(w);
 	wremove(w);
+	wunfocus(w);
 	w->hidden = TRUE;
 	w->wctlready = TRUE;
 	wsendmsg(w, Wakeup);