xref: /plan9-contrib/sys/src/cmd/acme/rows.c (revision 2c2299ce0e1270fbef669a6f1c8a8e80dfa5d69c)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <thread.h>
57dd7cddfSDavid du Colombier #include <cursor.h>
67dd7cddfSDavid du Colombier #include <mouse.h>
77dd7cddfSDavid du Colombier #include <keyboard.h>
87dd7cddfSDavid du Colombier #include <frame.h>
97dd7cddfSDavid du Colombier #include <fcall.h>
107dd7cddfSDavid du Colombier #include <bio.h>
117dd7cddfSDavid du Colombier #include <plumb.h>
127dd7cddfSDavid du Colombier #include "dat.h"
137dd7cddfSDavid du Colombier #include "fns.h"
147dd7cddfSDavid du Colombier 
157dd7cddfSDavid du Colombier void
rowinit(Row * row,Rectangle r)167dd7cddfSDavid du Colombier rowinit(Row *row, Rectangle r)
177dd7cddfSDavid du Colombier {
187dd7cddfSDavid du Colombier 	Rectangle r1;
197dd7cddfSDavid du Colombier 	Text *t;
207dd7cddfSDavid du Colombier 
217dd7cddfSDavid du Colombier 	draw(screen, r, display->white, nil, ZP);
227dd7cddfSDavid du Colombier 	row->r = r;
237dd7cddfSDavid du Colombier 	row->col = nil;
247dd7cddfSDavid du Colombier 	row->ncol = 0;
257dd7cddfSDavid du Colombier 	r1 = r;
267dd7cddfSDavid du Colombier 	r1.max.y = r1.min.y + font->height;
277dd7cddfSDavid du Colombier 	t = &row->tag;
287dd7cddfSDavid du Colombier 	textinit(t, fileaddtext(nil, t), r1, rfget(FALSE, FALSE, FALSE, nil), tagcols);
297dd7cddfSDavid du Colombier 	t->what = Rowtag;
307dd7cddfSDavid du Colombier 	t->row = row;
317dd7cddfSDavid du Colombier 	t->w = nil;
327dd7cddfSDavid du Colombier 	t->col = nil;
337dd7cddfSDavid du Colombier 	r1.min.y = r1.max.y;
347dd7cddfSDavid du Colombier 	r1.max.y += Border;
357dd7cddfSDavid du Colombier 	draw(screen, r1, display->black, nil, ZP);
367dd7cddfSDavid du Colombier 	textinsert(t, 0, L"Newcol Kill Putall Dump Exit ", 29, TRUE);
377dd7cddfSDavid du Colombier 	textsetselect(t, t->file->nc, t->file->nc);
387dd7cddfSDavid du Colombier }
397dd7cddfSDavid du Colombier 
407dd7cddfSDavid du Colombier Column*
rowadd(Row * row,Column * c,int x)417dd7cddfSDavid du Colombier rowadd(Row *row, Column *c, int x)
427dd7cddfSDavid du Colombier {
437dd7cddfSDavid du Colombier 	Rectangle r, r1;
447dd7cddfSDavid du Colombier 	Column *d;
457dd7cddfSDavid du Colombier 	int i;
467dd7cddfSDavid du Colombier 
477dd7cddfSDavid du Colombier 	d = nil;
487dd7cddfSDavid du Colombier 	r = row->r;
497dd7cddfSDavid du Colombier 	r.min.y = row->tag.r.max.y+Border;
507dd7cddfSDavid du Colombier 	if(x<r.min.x && row->ncol>0){	/*steal 40% of last column by default */
517dd7cddfSDavid du Colombier 		d = row->col[row->ncol-1];
527dd7cddfSDavid du Colombier 		x = d->r.min.x + 3*Dx(d->r)/5;
537dd7cddfSDavid du Colombier 	}
547dd7cddfSDavid du Colombier 	/* look for column we'll land on */
557dd7cddfSDavid du Colombier 	for(i=0; i<row->ncol; i++){
567dd7cddfSDavid du Colombier 		d = row->col[i];
577dd7cddfSDavid du Colombier 		if(x < d->r.max.x)
587dd7cddfSDavid du Colombier 			break;
597dd7cddfSDavid du Colombier 	}
607dd7cddfSDavid du Colombier 	if(row->ncol > 0){
617dd7cddfSDavid du Colombier 		if(i < row->ncol)
627dd7cddfSDavid du Colombier 			i++;	/* new column will go after d */
637dd7cddfSDavid du Colombier 		r = d->r;
647dd7cddfSDavid du Colombier 		if(Dx(r) < 100)
657dd7cddfSDavid du Colombier 			return nil;
667dd7cddfSDavid du Colombier 		draw(screen, r, display->white, nil, ZP);
677dd7cddfSDavid du Colombier 		r1 = r;
687dd7cddfSDavid du Colombier 		r1.max.x = min(x, r.max.x-50);
697dd7cddfSDavid du Colombier 		if(Dx(r1) < 50)
707dd7cddfSDavid du Colombier 			r1.max.x = r1.min.x+50;
717dd7cddfSDavid du Colombier 		colresize(d, r1);
727dd7cddfSDavid du Colombier 		r1.min.x = r1.max.x;
737dd7cddfSDavid du Colombier 		r1.max.x = r1.min.x+Border;
747dd7cddfSDavid du Colombier 		draw(screen, r1, display->black, nil, ZP);
757dd7cddfSDavid du Colombier 		r.min.x = r1.max.x;
767dd7cddfSDavid du Colombier 	}
777dd7cddfSDavid du Colombier 	if(c == nil){
787dd7cddfSDavid du Colombier 		c = emalloc(sizeof(Column));
797dd7cddfSDavid du Colombier 		colinit(c, r);
807dd7cddfSDavid du Colombier 		incref(&reffont);
817dd7cddfSDavid du Colombier 	}else
827dd7cddfSDavid du Colombier 		colresize(c, r);
837dd7cddfSDavid du Colombier 	c->row = row;
847dd7cddfSDavid du Colombier 	c->tag.row = row;
857dd7cddfSDavid du Colombier 	row->col = realloc(row->col, (row->ncol+1)*sizeof(Column*));
867dd7cddfSDavid du Colombier 	memmove(row->col+i+1, row->col+i, (row->ncol-i)*sizeof(Column*));
877dd7cddfSDavid du Colombier 	row->col[i] = c;
887dd7cddfSDavid du Colombier 	row->ncol++;
897dd7cddfSDavid du Colombier 	clearmouse();
907dd7cddfSDavid du Colombier 	return c;
917dd7cddfSDavid du Colombier }
927dd7cddfSDavid du Colombier 
937dd7cddfSDavid du Colombier void
rowresize(Row * row,Rectangle r)947dd7cddfSDavid du Colombier rowresize(Row *row, Rectangle r)
957dd7cddfSDavid du Colombier {
967dd7cddfSDavid du Colombier 	int i, dx, odx;
977dd7cddfSDavid du Colombier 	Rectangle r1, r2;
987dd7cddfSDavid du Colombier 	Column *c;
997dd7cddfSDavid du Colombier 
1007dd7cddfSDavid du Colombier 	dx = Dx(r);
1017dd7cddfSDavid du Colombier 	odx = Dx(row->r);
1027dd7cddfSDavid du Colombier 	row->r = r;
1037dd7cddfSDavid du Colombier 	r1 = r;
1047dd7cddfSDavid du Colombier 	r1.max.y = r1.min.y + font->height;
105*2c2299ceSDavid du Colombier 	textresize(&row->tag, r1, TRUE);
1067dd7cddfSDavid du Colombier 	r1.min.y = r1.max.y;
1077dd7cddfSDavid du Colombier 	r1.max.y += Border;
1087dd7cddfSDavid du Colombier 	draw(screen, r1, display->black, nil, ZP);
1097dd7cddfSDavid du Colombier 	r.min.y = r1.max.y;
1107dd7cddfSDavid du Colombier 	r1 = r;
1117dd7cddfSDavid du Colombier 	r1.max.x = r1.min.x;
1127dd7cddfSDavid du Colombier 	for(i=0; i<row->ncol; i++){
1137dd7cddfSDavid du Colombier 		c = row->col[i];
1147dd7cddfSDavid du Colombier 		r1.min.x = r1.max.x;
1157dd7cddfSDavid du Colombier 		if(i == row->ncol-1)
1167dd7cddfSDavid du Colombier 			r1.max.x = r.max.x;
1177dd7cddfSDavid du Colombier 		else
1187dd7cddfSDavid du Colombier 			r1.max.x = r1.min.x+Dx(c->r)*dx/odx;
1197dd7cddfSDavid du Colombier 		if(i > 0){
1207dd7cddfSDavid du Colombier 			r2 = r1;
1217dd7cddfSDavid du Colombier 			r2.max.x = r2.min.x+Border;
1227dd7cddfSDavid du Colombier 			draw(screen, r2, display->black, nil, ZP);
1237dd7cddfSDavid du Colombier 			r1.min.x = r2.max.x;
1247dd7cddfSDavid du Colombier 		}
1257dd7cddfSDavid du Colombier 		colresize(c, r1);
1267dd7cddfSDavid du Colombier 	}
1277dd7cddfSDavid du Colombier }
1287dd7cddfSDavid du Colombier 
1297dd7cddfSDavid du Colombier void
rowdragcol(Row * row,Column * c,int)1307dd7cddfSDavid du Colombier rowdragcol(Row *row, Column *c, int)
1317dd7cddfSDavid du Colombier {
1327dd7cddfSDavid du Colombier 	Rectangle r;
1337dd7cddfSDavid du Colombier 	int i, b, x;
1347dd7cddfSDavid du Colombier 	Point p, op;
1357dd7cddfSDavid du Colombier 	Column *d;
1367dd7cddfSDavid du Colombier 
1377dd7cddfSDavid du Colombier 	clearmouse();
1387dd7cddfSDavid du Colombier 	setcursor(mousectl, &boxcursor);
1397dd7cddfSDavid du Colombier 	b = mouse->buttons;
1407dd7cddfSDavid du Colombier 	op = mouse->xy;
1417dd7cddfSDavid du Colombier 	while(mouse->buttons == b)
1427dd7cddfSDavid du Colombier 		readmouse(mousectl);
1437dd7cddfSDavid du Colombier 	setcursor(mousectl, nil);
1447dd7cddfSDavid du Colombier 	if(mouse->buttons){
1457dd7cddfSDavid du Colombier 		while(mouse->buttons)
1467dd7cddfSDavid du Colombier 			readmouse(mousectl);
1477dd7cddfSDavid du Colombier 		return;
1487dd7cddfSDavid du Colombier 	}
1497dd7cddfSDavid du Colombier 
1507dd7cddfSDavid du Colombier 	for(i=0; i<row->ncol; i++)
1517dd7cddfSDavid du Colombier 		if(row->col[i] == c)
1527dd7cddfSDavid du Colombier 			goto Found;
1537dd7cddfSDavid du Colombier 	error("can't find column");
1547dd7cddfSDavid du Colombier 
1557dd7cddfSDavid du Colombier   Found:
1567dd7cddfSDavid du Colombier 	p = mouse->xy;
1577dd7cddfSDavid du Colombier 	if((abs(p.x-op.x)<5 && abs(p.y-op.y)<5))
1587dd7cddfSDavid du Colombier 		return;
1597dd7cddfSDavid du Colombier 	if((i>0 && p.x<row->col[i-1]->r.min.x) || (i<row->ncol-1 && p.x>c->r.max.x)){
1607dd7cddfSDavid du Colombier 		/* shuffle */
1617dd7cddfSDavid du Colombier 		x = c->r.min.x;
1627dd7cddfSDavid du Colombier 		rowclose(row, c, FALSE);
1637dd7cddfSDavid du Colombier 		if(rowadd(row, c, p.x) == nil)	/* whoops! */
1647dd7cddfSDavid du Colombier 		if(rowadd(row, c, x) == nil)		/* WHOOPS! */
1657dd7cddfSDavid du Colombier 		if(rowadd(row, c, -1)==nil){		/* shit! */
1667dd7cddfSDavid du Colombier 			rowclose(row, c, TRUE);
1677dd7cddfSDavid du Colombier 			return;
1687dd7cddfSDavid du Colombier 		}
1697dd7cddfSDavid du Colombier 		colmousebut(c);
1707dd7cddfSDavid du Colombier 		return;
1717dd7cddfSDavid du Colombier 	}
172348c7de8SDavid du Colombier 	if(i == 0)
173348c7de8SDavid du Colombier 		return;
1747dd7cddfSDavid du Colombier 	d = row->col[i-1];
1757dd7cddfSDavid du Colombier 	if(p.x < d->r.min.x+80+Scrollwid)
1767dd7cddfSDavid du Colombier 		p.x = d->r.min.x+80+Scrollwid;
1777dd7cddfSDavid du Colombier 	if(p.x > c->r.max.x-80-Scrollwid)
1787dd7cddfSDavid du Colombier 		p.x = c->r.max.x-80-Scrollwid;
1797dd7cddfSDavid du Colombier 	r = d->r;
1807dd7cddfSDavid du Colombier 	r.max.x = c->r.max.x;
1817dd7cddfSDavid du Colombier 	draw(screen, r, display->white, nil, ZP);
1827dd7cddfSDavid du Colombier 	r.max.x = p.x;
1837dd7cddfSDavid du Colombier 	colresize(d, r);
1847dd7cddfSDavid du Colombier 	r = c->r;
1857dd7cddfSDavid du Colombier 	r.min.x = p.x;
1867dd7cddfSDavid du Colombier 	r.max.x = r.min.x;
1877dd7cddfSDavid du Colombier 	r.max.x += Border;
1887dd7cddfSDavid du Colombier 	draw(screen, r, display->black, nil, ZP);
1897dd7cddfSDavid du Colombier 	r.min.x = r.max.x;
1907dd7cddfSDavid du Colombier 	r.max.x = c->r.max.x;
1917dd7cddfSDavid du Colombier 	colresize(c, r);
1927dd7cddfSDavid du Colombier 	colmousebut(c);
1937dd7cddfSDavid du Colombier }
1947dd7cddfSDavid du Colombier 
1957dd7cddfSDavid du Colombier void
rowclose(Row * row,Column * c,int dofree)1967dd7cddfSDavid du Colombier rowclose(Row *row, Column *c, int dofree)
1977dd7cddfSDavid du Colombier {
1987dd7cddfSDavid du Colombier 	Rectangle r;
1997dd7cddfSDavid du Colombier 	int i;
2007dd7cddfSDavid du Colombier 
2017dd7cddfSDavid du Colombier 	for(i=0; i<row->ncol; i++)
2027dd7cddfSDavid du Colombier 		if(row->col[i] == c)
2037dd7cddfSDavid du Colombier 			goto Found;
2047dd7cddfSDavid du Colombier 	error("can't find column");
2057dd7cddfSDavid du Colombier   Found:
2067dd7cddfSDavid du Colombier 	r = c->r;
2077dd7cddfSDavid du Colombier 	if(dofree)
2087dd7cddfSDavid du Colombier 		colcloseall(c);
2097dd7cddfSDavid du Colombier 	memmove(row->col+i, row->col+i+1, (row->ncol-i)*sizeof(Column*));
2107dd7cddfSDavid du Colombier 	row->ncol--;
2117dd7cddfSDavid du Colombier 	row->col = realloc(row->col, row->ncol*sizeof(Column*));
2127dd7cddfSDavid du Colombier 	if(row->ncol == 0){
2137dd7cddfSDavid du Colombier 		draw(screen, r, display->white, nil, ZP);
2147dd7cddfSDavid du Colombier 		return;
2157dd7cddfSDavid du Colombier 	}
2167dd7cddfSDavid du Colombier 	if(i == row->ncol){		/* extend last column right */
2177dd7cddfSDavid du Colombier 		c = row->col[i-1];
2187dd7cddfSDavid du Colombier 		r.min.x = c->r.min.x;
2197dd7cddfSDavid du Colombier 		r.max.x = row->r.max.x;
2207dd7cddfSDavid du Colombier 	}else{			/* extend next window left */
2217dd7cddfSDavid du Colombier 		c = row->col[i];
2227dd7cddfSDavid du Colombier 		r.max.x = c->r.max.x;
2237dd7cddfSDavid du Colombier 	}
2247dd7cddfSDavid du Colombier 	draw(screen, r, display->white, nil, ZP);
2257dd7cddfSDavid du Colombier 	colresize(c, r);
2267dd7cddfSDavid du Colombier }
2277dd7cddfSDavid du Colombier 
2287dd7cddfSDavid du Colombier Column*
rowwhichcol(Row * row,Point p)2297dd7cddfSDavid du Colombier rowwhichcol(Row *row, Point p)
2307dd7cddfSDavid du Colombier {
2317dd7cddfSDavid du Colombier 	int i;
2327dd7cddfSDavid du Colombier 	Column *c;
2337dd7cddfSDavid du Colombier 
2347dd7cddfSDavid du Colombier 	for(i=0; i<row->ncol; i++){
2357dd7cddfSDavid du Colombier 		c = row->col[i];
2367dd7cddfSDavid du Colombier 		if(ptinrect(p, c->r))
2377dd7cddfSDavid du Colombier 			return c;
2387dd7cddfSDavid du Colombier 	}
2397dd7cddfSDavid du Colombier 	return nil;
2407dd7cddfSDavid du Colombier }
2417dd7cddfSDavid du Colombier 
2427dd7cddfSDavid du Colombier Text*
rowwhich(Row * row,Point p)2437dd7cddfSDavid du Colombier rowwhich(Row *row, Point p)
2447dd7cddfSDavid du Colombier {
2457dd7cddfSDavid du Colombier 	Column *c;
2467dd7cddfSDavid du Colombier 
2477dd7cddfSDavid du Colombier 	if(ptinrect(p, row->tag.all))
2487dd7cddfSDavid du Colombier 		return &row->tag;
2497dd7cddfSDavid du Colombier 	c = rowwhichcol(row, p);
2507dd7cddfSDavid du Colombier 	if(c)
2517dd7cddfSDavid du Colombier 		return colwhich(c, p);
2527dd7cddfSDavid du Colombier 	return nil;
2537dd7cddfSDavid du Colombier }
2547dd7cddfSDavid du Colombier 
2557dd7cddfSDavid du Colombier Text*
rowtype(Row * row,Rune r,Point p)2567dd7cddfSDavid du Colombier rowtype(Row *row, Rune r, Point p)
2577dd7cddfSDavid du Colombier {
2587dd7cddfSDavid du Colombier 	Window *w;
2597dd7cddfSDavid du Colombier 	Text *t;
2607dd7cddfSDavid du Colombier 
2617dd7cddfSDavid du Colombier 	clearmouse();
2627dd7cddfSDavid du Colombier 	qlock(row);
2637dd7cddfSDavid du Colombier 	if(bartflag)
2647dd7cddfSDavid du Colombier 		t = barttext;
2657dd7cddfSDavid du Colombier 	else
2667dd7cddfSDavid du Colombier 		t = rowwhich(row, p);
2677dd7cddfSDavid du Colombier 	if(t!=nil && !(t->what==Tag && ptinrect(p, t->scrollr))){
2687dd7cddfSDavid du Colombier 		w = t->w;
2697dd7cddfSDavid du Colombier 		if(w == nil)
2707dd7cddfSDavid du Colombier 			texttype(t, r);
2717dd7cddfSDavid du Colombier 		else{
2727dd7cddfSDavid du Colombier 			winlock(w, 'K');
2737dd7cddfSDavid du Colombier 			wintype(w, t, r);
274*2c2299ceSDavid du Colombier 			/* Expand tag if necessary */
275*2c2299ceSDavid du Colombier 			if(t->what == Tag){
276*2c2299ceSDavid du Colombier 				t->w->tagsafe = FALSE;
277*2c2299ceSDavid du Colombier 				if(r == '\n')
278*2c2299ceSDavid du Colombier 					t->w->tagexpand = TRUE;
279*2c2299ceSDavid du Colombier 				winresize(w, w->r, TRUE, TRUE);
280*2c2299ceSDavid du Colombier 			}
2817dd7cddfSDavid du Colombier 			winunlock(w);
2827dd7cddfSDavid du Colombier 		}
2837dd7cddfSDavid du Colombier 	}
2847dd7cddfSDavid du Colombier 	qunlock(row);
2857dd7cddfSDavid du Colombier 	return t;
2867dd7cddfSDavid du Colombier }
2877dd7cddfSDavid du Colombier 
2887dd7cddfSDavid du Colombier int
rowclean(Row * row)2897dd7cddfSDavid du Colombier rowclean(Row *row)
2907dd7cddfSDavid du Colombier {
2917dd7cddfSDavid du Colombier 	int clean;
2927dd7cddfSDavid du Colombier 	int i;
2937dd7cddfSDavid du Colombier 
2947dd7cddfSDavid du Colombier 	clean = TRUE;
2957dd7cddfSDavid du Colombier 	for(i=0; i<row->ncol; i++)
2967dd7cddfSDavid du Colombier 		clean &= colclean(row->col[i]);
2977dd7cddfSDavid du Colombier 	return clean;
2987dd7cddfSDavid du Colombier }
2997dd7cddfSDavid du Colombier 
3007dd7cddfSDavid du Colombier void
rowdump(Row * row,char * file)3017dd7cddfSDavid du Colombier rowdump(Row *row, char *file)
3027dd7cddfSDavid du Colombier {
3037dd7cddfSDavid du Colombier 	int i, j, fd, m, n, dumped;
3047dd7cddfSDavid du Colombier 	uint q0, q1;
3057dd7cddfSDavid du Colombier 	Biobuf *b;
3067dd7cddfSDavid du Colombier 	char *buf, *a, *fontname;
3077dd7cddfSDavid du Colombier 	Rune *r;
3087dd7cddfSDavid du Colombier 	Column *c;
3097dd7cddfSDavid du Colombier 	Window *w, *w1;
3107dd7cddfSDavid du Colombier 	Text *t;
3117dd7cddfSDavid du Colombier 
3127dd7cddfSDavid du Colombier 	if(row->ncol == 0)
3137dd7cddfSDavid du Colombier 		return;
3147dd7cddfSDavid du Colombier 	buf = fbufalloc();
3157dd7cddfSDavid du Colombier 	if(file == nil){
3167dd7cddfSDavid du Colombier 		if(home == nil){
3177dd7cddfSDavid du Colombier 			warning(nil, "can't find file for dump: $home not defined\n");
3187dd7cddfSDavid du Colombier 			goto Rescue;
3197dd7cddfSDavid du Colombier 		}
3207dd7cddfSDavid du Colombier 		sprint(buf, "%s/acme.dump", home);
3217dd7cddfSDavid du Colombier 		file = buf;
3227dd7cddfSDavid du Colombier 	}
3237dd7cddfSDavid du Colombier 	fd = create(file, OWRITE, 0600);
3247dd7cddfSDavid du Colombier 	if(fd < 0){
3257dd7cddfSDavid du Colombier 		warning(nil, "can't open %s: %r\n", file);
3267dd7cddfSDavid du Colombier 		goto Rescue;
3277dd7cddfSDavid du Colombier 	}
3287dd7cddfSDavid du Colombier 	b = emalloc(sizeof(Biobuf));
3297dd7cddfSDavid du Colombier 	Binit(b, fd, OWRITE);
3307dd7cddfSDavid du Colombier 	r = fbufalloc();
3317dd7cddfSDavid du Colombier 	Bprint(b, "%s\n", wdir);
3327dd7cddfSDavid du Colombier 	Bprint(b, "%s\n", fontnames[0]);
3337dd7cddfSDavid du Colombier 	Bprint(b, "%s\n", fontnames[1]);
3347dd7cddfSDavid du Colombier 	for(i=0; i<row->ncol; i++){
3357dd7cddfSDavid du Colombier 		c = row->col[i];
3367dd7cddfSDavid du Colombier 		Bprint(b, "%11d", 100*(c->r.min.x-row->r.min.x)/Dx(row->r));
3377dd7cddfSDavid du Colombier 		if(i == row->ncol-1)
3387dd7cddfSDavid du Colombier 			Bputc(b, '\n');
3397dd7cddfSDavid du Colombier 		else
3407dd7cddfSDavid du Colombier 			Bputc(b, ' ');
3417dd7cddfSDavid du Colombier 	}
3427dd7cddfSDavid du Colombier 	for(i=0; i<row->ncol; i++){
3437dd7cddfSDavid du Colombier 		c = row->col[i];
3447dd7cddfSDavid du Colombier 		for(j=0; j<c->nw; j++)
3457dd7cddfSDavid du Colombier 			c->w[j]->body.file->dumpid = 0;
3467dd7cddfSDavid du Colombier 	}
3477dd7cddfSDavid du Colombier 	for(i=0; i<row->ncol; i++){
3487dd7cddfSDavid du Colombier 		c = row->col[i];
3497dd7cddfSDavid du Colombier 		for(j=0; j<c->nw; j++){
3507dd7cddfSDavid du Colombier 			w = c->w[j];
3517dd7cddfSDavid du Colombier 			wincommit(w, &w->tag);
3527dd7cddfSDavid du Colombier 			t = &w->body;
3537dd7cddfSDavid du Colombier 			/* windows owned by others get special treatment */
3547dd7cddfSDavid du Colombier 			if(w->nopen[QWevent] > 0)
3557dd7cddfSDavid du Colombier 				if(w->dumpstr == nil)
3567dd7cddfSDavid du Colombier 					continue;
3577dd7cddfSDavid du Colombier 			/* zeroxes of external windows are tossed */
3587dd7cddfSDavid du Colombier 			if(t->file->ntext > 1)
3597dd7cddfSDavid du Colombier 				for(n=0; n<t->file->ntext; n++){
3607dd7cddfSDavid du Colombier 					w1 = t->file->text[n]->w;
3617dd7cddfSDavid du Colombier 					if(w == w1)
3627dd7cddfSDavid du Colombier 						continue;
3637dd7cddfSDavid du Colombier 					if(w1->nopen[QWevent])
3647dd7cddfSDavid du Colombier 						goto Continue2;
3657dd7cddfSDavid du Colombier 				}
3667dd7cddfSDavid du Colombier 			fontname = "";
3677dd7cddfSDavid du Colombier 			if(t->reffont->f != font)
3687dd7cddfSDavid du Colombier 				fontname = t->reffont->f->name;
3697dd7cddfSDavid du Colombier 			if(t->file->nname)
3707dd7cddfSDavid du Colombier 				a = runetobyte(t->file->name, t->file->nname);
3717dd7cddfSDavid du Colombier 			else
3727dd7cddfSDavid du Colombier 				a = emalloc(1);
3737dd7cddfSDavid du Colombier 			if(t->file->dumpid){
3747dd7cddfSDavid du Colombier 				dumped = FALSE;
3757dd7cddfSDavid du Colombier 				Bprint(b, "x%11d %11d %11d %11d %11d %s\n", i, t->file->dumpid,
3767dd7cddfSDavid du Colombier 					w->body.q0, w->body.q1,
3777dd7cddfSDavid du Colombier 					100*(w->r.min.y-c->r.min.y)/Dy(c->r),
3787dd7cddfSDavid du Colombier 					fontname);
3797dd7cddfSDavid du Colombier 			}else if(w->dumpstr){
3807dd7cddfSDavid du Colombier 				dumped = FALSE;
3817dd7cddfSDavid du Colombier 				Bprint(b, "e%11d %11d %11d %11d %11d %s\n", i, t->file->dumpid,
3827dd7cddfSDavid du Colombier 					0, 0,
3837dd7cddfSDavid du Colombier 					100*(w->r.min.y-c->r.min.y)/Dy(c->r),
3847dd7cddfSDavid du Colombier 					fontname);
3857dd7cddfSDavid du Colombier 			}else if((w->dirty==FALSE && access(a, 0)==0) || w->isdir){
3867dd7cddfSDavid du Colombier 				dumped = FALSE;
3877dd7cddfSDavid du Colombier 				t->file->dumpid = w->id;
3887dd7cddfSDavid du Colombier 				Bprint(b, "f%11d %11d %11d %11d %11d %s\n", i, w->id,
3897dd7cddfSDavid du Colombier 					w->body.q0, w->body.q1,
3907dd7cddfSDavid du Colombier 					100*(w->r.min.y-c->r.min.y)/Dy(c->r),
3917dd7cddfSDavid du Colombier 					fontname);
3927dd7cddfSDavid du Colombier 			}else{
3937dd7cddfSDavid du Colombier 				dumped = TRUE;
3947dd7cddfSDavid du Colombier 				t->file->dumpid = w->id;
3957dd7cddfSDavid du Colombier 				Bprint(b, "F%11d %11d %11d %11d %11d %11d %s\n", i, j,
3967dd7cddfSDavid du Colombier 					w->body.q0, w->body.q1,
3977dd7cddfSDavid du Colombier 					100*(w->r.min.y-c->r.min.y)/Dy(c->r),
3987dd7cddfSDavid du Colombier 					w->body.file->nc, fontname);
3997dd7cddfSDavid du Colombier 			}
4007dd7cddfSDavid du Colombier 			free(a);
4019a747e4fSDavid du Colombier 			winctlprint(w, buf, 0);
4027dd7cddfSDavid du Colombier 			Bwrite(b, buf, strlen(buf));
4037dd7cddfSDavid du Colombier 			m = min(RBUFSIZE, w->tag.file->nc);
4047dd7cddfSDavid du Colombier 			bufread(w->tag.file, 0, r, m);
4057dd7cddfSDavid du Colombier 			n = 0;
4067dd7cddfSDavid du Colombier 			while(n<m && r[n]!='\n')
4077dd7cddfSDavid du Colombier 				n++;
4087dd7cddfSDavid du Colombier 			r[n++] = '\n';
4097dd7cddfSDavid du Colombier 			Bprint(b, "%.*S", n, r);
4107dd7cddfSDavid du Colombier 			if(dumped){
4117dd7cddfSDavid du Colombier 				q0 = 0;
4127dd7cddfSDavid du Colombier 				q1 = t->file->nc;
4137dd7cddfSDavid du Colombier 				while(q0 < q1){
4147dd7cddfSDavid du Colombier 					n = q1 - q0;
4157dd7cddfSDavid du Colombier 					if(n > BUFSIZE/UTFmax)
4167dd7cddfSDavid du Colombier 						n = BUFSIZE/UTFmax;
4177dd7cddfSDavid du Colombier 					bufread(t->file, q0, r, n);
4187dd7cddfSDavid du Colombier 					Bprint(b, "%.*S", n, r);
4197dd7cddfSDavid du Colombier 					q0 += n;
4207dd7cddfSDavid du Colombier 				}
4217dd7cddfSDavid du Colombier 			}
4227dd7cddfSDavid du Colombier 			if(w->dumpstr){
4237dd7cddfSDavid du Colombier 				if(w->dumpdir)
4247dd7cddfSDavid du Colombier 					Bprint(b, "%s\n%s\n", w->dumpdir, w->dumpstr);
4257dd7cddfSDavid du Colombier 				else
4267dd7cddfSDavid du Colombier 					Bprint(b, "\n%s\n", w->dumpstr);
4277dd7cddfSDavid du Colombier 			}
4287dd7cddfSDavid du Colombier     Continue2:;
4297dd7cddfSDavid du Colombier 		}
4307dd7cddfSDavid du Colombier 	}
4317dd7cddfSDavid du Colombier 	Bterm(b);
4327dd7cddfSDavid du Colombier 	close(fd);
4337dd7cddfSDavid du Colombier 	free(b);
4347dd7cddfSDavid du Colombier 	fbuffree(r);
4357dd7cddfSDavid du Colombier 
4367dd7cddfSDavid du Colombier    Rescue:
4377dd7cddfSDavid du Colombier 	fbuffree(buf);
4387dd7cddfSDavid du Colombier }
4397dd7cddfSDavid du Colombier 
4407dd7cddfSDavid du Colombier static
4417dd7cddfSDavid du Colombier char*
rdline(Biobuf * b,int * linep)4427dd7cddfSDavid du Colombier rdline(Biobuf *b, int *linep)
4437dd7cddfSDavid du Colombier {
4447dd7cddfSDavid du Colombier 	char *l;
4457dd7cddfSDavid du Colombier 
4467dd7cddfSDavid du Colombier 	l = Brdline(b, '\n');
4477dd7cddfSDavid du Colombier 	if(l)
4487dd7cddfSDavid du Colombier 		(*linep)++;
4497dd7cddfSDavid du Colombier 	return l;
4507dd7cddfSDavid du Colombier }
4517dd7cddfSDavid du Colombier 
4529a747e4fSDavid du Colombier /*
4539a747e4fSDavid du Colombier  * Get font names from load file so we don't load fonts we won't use
4549a747e4fSDavid du Colombier  */
4559a747e4fSDavid du Colombier void
rowloadfonts(char * file)4569a747e4fSDavid du Colombier rowloadfonts(char *file)
4579a747e4fSDavid du Colombier {
4589a747e4fSDavid du Colombier 	int i;
4599a747e4fSDavid du Colombier 	Biobuf *b;
4609a747e4fSDavid du Colombier 	char *l;
4619a747e4fSDavid du Colombier 
4629a747e4fSDavid du Colombier 	b = Bopen(file, OREAD);
4639a747e4fSDavid du Colombier 	if(b == nil)
4649a747e4fSDavid du Colombier 		return;
4659a747e4fSDavid du Colombier 	/* current directory */
4669a747e4fSDavid du Colombier 	l = Brdline(b, '\n');
4679a747e4fSDavid du Colombier 	if(l == nil)
4689a747e4fSDavid du Colombier 		goto Return;
4699a747e4fSDavid du Colombier 	/* global fonts */
4709a747e4fSDavid du Colombier 	for(i=0; i<2; i++){
4719a747e4fSDavid du Colombier 		l = Brdline(b, '\n');
4729a747e4fSDavid du Colombier 		if(l == nil)
4739a747e4fSDavid du Colombier 			goto Return;
4749a747e4fSDavid du Colombier 		l[Blinelen(b)-1] = 0;
4756d0d1481SDavid du Colombier 		if(*l && strcmp(l, fontnames[i])!=0){
4766d0d1481SDavid du Colombier 			free(fontnames[i]);
4779a747e4fSDavid du Colombier 			fontnames[i] = estrdup(l);
4789a747e4fSDavid du Colombier 		}
4796d0d1481SDavid du Colombier 	}
4809a747e4fSDavid du Colombier     Return:
4819a747e4fSDavid du Colombier 	Bterm(b);
4829a747e4fSDavid du Colombier }
4839a747e4fSDavid du Colombier 
4844b30ca09SDavid du Colombier int
rowload(Row * row,char * file,int initing)4857dd7cddfSDavid du Colombier rowload(Row *row, char *file, int initing)
4867dd7cddfSDavid du Colombier {
4877dd7cddfSDavid du Colombier 	int i, j, line, percent, y, nr, nfontr, n, ns, ndumped, dumpid, x, fd;
4887dd7cddfSDavid du Colombier 	Biobuf *b, *bout;
4897dd7cddfSDavid du Colombier 	char *buf, *l, *t, *fontname;
4907dd7cddfSDavid du Colombier 	Rune *r, rune, *fontr;
4917dd7cddfSDavid du Colombier 	Column *c, *c1, *c2;
4927dd7cddfSDavid du Colombier 	uint q0, q1;
4937dd7cddfSDavid du Colombier 	Rectangle r1, r2;
4947dd7cddfSDavid du Colombier 	Window *w;
4957dd7cddfSDavid du Colombier 
4967dd7cddfSDavid du Colombier 	buf = fbufalloc();
4977dd7cddfSDavid du Colombier 	if(file == nil){
4987dd7cddfSDavid du Colombier 		if(home == nil){
4997dd7cddfSDavid du Colombier 			warning(nil, "can't find file for load: $home not defined\n");
5007dd7cddfSDavid du Colombier 			goto Rescue1;
5017dd7cddfSDavid du Colombier 		}
5027dd7cddfSDavid du Colombier 		sprint(buf, "%s/acme.dump", home);
5037dd7cddfSDavid du Colombier 		file = buf;
5047dd7cddfSDavid du Colombier 	}
5057dd7cddfSDavid du Colombier 	b = Bopen(file, OREAD);
5067dd7cddfSDavid du Colombier 	if(b == nil){
5077dd7cddfSDavid du Colombier 		warning(nil, "can't open load file %s: %r\n", file);
5087dd7cddfSDavid du Colombier 		goto Rescue1;
5097dd7cddfSDavid du Colombier 	}
5107dd7cddfSDavid du Colombier 	/* current directory */
5117dd7cddfSDavid du Colombier 	line = 0;
5127dd7cddfSDavid du Colombier 	l = rdline(b, &line);
5137dd7cddfSDavid du Colombier 	if(l == nil)
5147dd7cddfSDavid du Colombier 		goto Rescue2;
5157dd7cddfSDavid du Colombier 	l[Blinelen(b)-1] = 0;
5167dd7cddfSDavid du Colombier 	if(chdir(l) < 0){
5177dd7cddfSDavid du Colombier 		warning(nil, "can't chdir %s\n", l);
5187dd7cddfSDavid du Colombier 		goto Rescue2;
5197dd7cddfSDavid du Colombier 	}
5207dd7cddfSDavid du Colombier 	/* global fonts */
5217dd7cddfSDavid du Colombier 	for(i=0; i<2; i++){
5227dd7cddfSDavid du Colombier 		l = rdline(b, &line);
5237dd7cddfSDavid du Colombier 		if(l == nil)
5247dd7cddfSDavid du Colombier 			goto Rescue2;
5257dd7cddfSDavid du Colombier 		l[Blinelen(b)-1] = 0;
5267dd7cddfSDavid du Colombier 		if(*l && strcmp(l, fontnames[i])!=0)
5276d0d1481SDavid du Colombier 			rfget(i, TRUE, i==0 && initing, l);
5287dd7cddfSDavid du Colombier 	}
5297dd7cddfSDavid du Colombier 	if(initing && row->ncol==0)
5307dd7cddfSDavid du Colombier 		rowinit(row, screen->clipr);
5317dd7cddfSDavid du Colombier 	l = rdline(b, &line);
5327dd7cddfSDavid du Colombier 	if(l == nil)
5337dd7cddfSDavid du Colombier 		goto Rescue2;
5347dd7cddfSDavid du Colombier 	j = Blinelen(b)/12;
5357dd7cddfSDavid du Colombier 	if(j<=0 || j>10)
5367dd7cddfSDavid du Colombier 		goto Rescue2;
5377dd7cddfSDavid du Colombier 	for(i=0; i<j; i++){
5387dd7cddfSDavid du Colombier 		percent = atoi(l+i*12);
5397dd7cddfSDavid du Colombier 		if(percent<0 || percent>=100)
5407dd7cddfSDavid du Colombier 			goto Rescue2;
5417dd7cddfSDavid du Colombier 		x = row->r.min.x+percent*Dx(row->r)/100;
5427dd7cddfSDavid du Colombier 		if(i < row->ncol){
5437dd7cddfSDavid du Colombier 			if(i == 0)
5447dd7cddfSDavid du Colombier 				continue;
5457dd7cddfSDavid du Colombier 			c1 = row->col[i-1];
5467dd7cddfSDavid du Colombier 			c2 = row->col[i];
5477dd7cddfSDavid du Colombier 			r1 = c1->r;
5487dd7cddfSDavid du Colombier 			r2 = c2->r;
5497dd7cddfSDavid du Colombier 			r1.max.x = x;
5507dd7cddfSDavid du Colombier 			r2.min.x = x+Border;
5517dd7cddfSDavid du Colombier 			if(Dx(r1) < 50 || Dx(r2) < 50)
5527dd7cddfSDavid du Colombier 				continue;
5537dd7cddfSDavid du Colombier 			draw(screen, Rpt(r1.min, r2.max), display->white, nil, ZP);
5547dd7cddfSDavid du Colombier 			colresize(c1, r1);
5557dd7cddfSDavid du Colombier 			colresize(c2, r2);
5567dd7cddfSDavid du Colombier 			r2.min.x = x;
5577dd7cddfSDavid du Colombier 			r2.max.x = x+Border;
5587dd7cddfSDavid du Colombier 			draw(screen, r2, display->black, nil, ZP);
5597dd7cddfSDavid du Colombier 		}
5607dd7cddfSDavid du Colombier 		if(i >= row->ncol)
5617dd7cddfSDavid du Colombier 			rowadd(row, nil, x);
5627dd7cddfSDavid du Colombier 	}
5637dd7cddfSDavid du Colombier 	for(;;){
5647dd7cddfSDavid du Colombier 		l = rdline(b, &line);
5657dd7cddfSDavid du Colombier 		if(l == nil)
5667dd7cddfSDavid du Colombier 			break;
5677dd7cddfSDavid du Colombier 		dumpid = 0;
5687dd7cddfSDavid du Colombier 		switch(l[0]){
5697dd7cddfSDavid du Colombier 		case 'e':
5707dd7cddfSDavid du Colombier 			if(Blinelen(b) < 1+5*12+1)
5717dd7cddfSDavid du Colombier 				goto Rescue2;
5727dd7cddfSDavid du Colombier 			l = rdline(b, &line);	/* ctl line; ignored */
5737dd7cddfSDavid du Colombier 			if(l == nil)
5747dd7cddfSDavid du Colombier 				goto Rescue2;
5757dd7cddfSDavid du Colombier 			l = rdline(b, &line);	/* directory */
5767dd7cddfSDavid du Colombier 			if(l == nil)
5777dd7cddfSDavid du Colombier 				goto Rescue2;
5787dd7cddfSDavid du Colombier 			l[Blinelen(b)-1] = 0;
5797dd7cddfSDavid du Colombier 			if(*l == '\0'){
5807dd7cddfSDavid du Colombier 				if(home == nil)
5817dd7cddfSDavid du Colombier 					r = bytetorune("./", &nr);
5827dd7cddfSDavid du Colombier 				else{
5837dd7cddfSDavid du Colombier 					t = emalloc(strlen(home)+1+1);
5847dd7cddfSDavid du Colombier 					sprint(t, "%s/", home);
5857dd7cddfSDavid du Colombier 					r = bytetorune(t, &nr);
5867dd7cddfSDavid du Colombier 					free(t);
5877dd7cddfSDavid du Colombier 				}
5887dd7cddfSDavid du Colombier 			}else
5897dd7cddfSDavid du Colombier 				r = bytetorune(l, &nr);
5907dd7cddfSDavid du Colombier 			l = rdline(b, &line);	/* command */
5917dd7cddfSDavid du Colombier 			if(l == nil)
5927dd7cddfSDavid du Colombier 				goto Rescue2;
5937dd7cddfSDavid du Colombier 			t = emalloc(Blinelen(b)+1);
5947dd7cddfSDavid du Colombier 			memmove(t, l, Blinelen(b));
59559cc4ca5SDavid du Colombier 			run(nil, t, r, nr, TRUE, nil, nil, FALSE);
5967dd7cddfSDavid du Colombier 			/* r is freed in run() */
5977dd7cddfSDavid du Colombier 			continue;
5987dd7cddfSDavid du Colombier 		case 'f':
5997dd7cddfSDavid du Colombier 			if(Blinelen(b) < 1+5*12+1)
6007dd7cddfSDavid du Colombier 				goto Rescue2;
6017dd7cddfSDavid du Colombier 			fontname = l+1+5*12;
6027dd7cddfSDavid du Colombier 			ndumped = -1;
6037dd7cddfSDavid du Colombier 			break;
6047dd7cddfSDavid du Colombier 		case 'F':
6057dd7cddfSDavid du Colombier 			if(Blinelen(b) < 1+6*12+1)
6067dd7cddfSDavid du Colombier 				goto Rescue2;
6077dd7cddfSDavid du Colombier 			fontname = l+1+6*12;
6087dd7cddfSDavid du Colombier 			ndumped = atoi(l+1+5*12+1);
6097dd7cddfSDavid du Colombier 			break;
6107dd7cddfSDavid du Colombier 		case 'x':
6117dd7cddfSDavid du Colombier 			if(Blinelen(b) < 1+5*12+1)
6127dd7cddfSDavid du Colombier 				goto Rescue2;
6137dd7cddfSDavid du Colombier 			fontname = l+1+5*12;
6147dd7cddfSDavid du Colombier 			ndumped = -1;
6157dd7cddfSDavid du Colombier 			dumpid = atoi(l+1+1*12);
6167dd7cddfSDavid du Colombier 			break;
6177dd7cddfSDavid du Colombier 		default:
6187dd7cddfSDavid du Colombier 			goto Rescue2;
6197dd7cddfSDavid du Colombier 		}
6207dd7cddfSDavid du Colombier 		l[Blinelen(b)-1] = 0;
6217dd7cddfSDavid du Colombier 		fontr = nil;
6227dd7cddfSDavid du Colombier 		nfontr = 0;
6237dd7cddfSDavid du Colombier 		if(*fontname)
6247dd7cddfSDavid du Colombier 			fontr = bytetorune(fontname, &nfontr);
6257dd7cddfSDavid du Colombier 		i = atoi(l+1+0*12);
6267dd7cddfSDavid du Colombier 		j = atoi(l+1+1*12);
6277dd7cddfSDavid du Colombier 		q0 = atoi(l+1+2*12);
6287dd7cddfSDavid du Colombier 		q1 = atoi(l+1+3*12);
6297dd7cddfSDavid du Colombier 		percent = atoi(l+1+4*12);
6307dd7cddfSDavid du Colombier 		if(i<0 || i>10)
6317dd7cddfSDavid du Colombier 			goto Rescue2;
6327dd7cddfSDavid du Colombier 		if(i > row->ncol)
6337dd7cddfSDavid du Colombier 			i = row->ncol;
6347dd7cddfSDavid du Colombier 		c = row->col[i];
6357dd7cddfSDavid du Colombier 		y = c->r.min.y+(percent*Dy(c->r))/100;
6367dd7cddfSDavid du Colombier 		if(y<c->r.min.y || y>=c->r.max.y)
6377dd7cddfSDavid du Colombier 			y = -1;
6387dd7cddfSDavid du Colombier 		if(dumpid == 0)
6397dd7cddfSDavid du Colombier 			w = coladd(c, nil, nil, y);
6407dd7cddfSDavid du Colombier 		else
6417dd7cddfSDavid du Colombier 			w = coladd(c, nil, lookid(dumpid, TRUE), y);
6427dd7cddfSDavid du Colombier 		if(w == nil)
6437dd7cddfSDavid du Colombier 			continue;
6447dd7cddfSDavid du Colombier 		w->dumpid = j;
6457dd7cddfSDavid du Colombier 		l = rdline(b, &line);
6467dd7cddfSDavid du Colombier 		if(l == nil)
6477dd7cddfSDavid du Colombier 			goto Rescue2;
6487dd7cddfSDavid du Colombier 		l[Blinelen(b)-1] = 0;
6497dd7cddfSDavid du Colombier 		r = bytetorune(l+5*12, &nr);
6507dd7cddfSDavid du Colombier 		ns = -1;
6517dd7cddfSDavid du Colombier 		for(n=0; n<nr; n++){
6527dd7cddfSDavid du Colombier 			if(r[n] == '/')
6537dd7cddfSDavid du Colombier 				ns = n;
6547dd7cddfSDavid du Colombier 			if(r[n] == ' ')
6557dd7cddfSDavid du Colombier 				break;
6567dd7cddfSDavid du Colombier 		}
6577dd7cddfSDavid du Colombier 		if(dumpid == 0)
6587dd7cddfSDavid du Colombier 			winsetname(w, r, n);
6597dd7cddfSDavid du Colombier 		for(; n<nr; n++)
6607dd7cddfSDavid du Colombier 			if(r[n] == '|')
6617dd7cddfSDavid du Colombier 				break;
6627dd7cddfSDavid du Colombier 		wincleartag(w);
6637dd7cddfSDavid du Colombier 		textinsert(&w->tag, w->tag.file->nc, r+n+1, nr-(n+1), TRUE);
6647dd7cddfSDavid du Colombier 		if(ndumped >= 0){
6657dd7cddfSDavid du Colombier 			/* simplest thing is to put it in a file and load that */
6667dd7cddfSDavid du Colombier 			sprint(buf, "/tmp/d%d.%.4sacme", getpid(), getuser());
6677dd7cddfSDavid du Colombier 			fd = create(buf, OWRITE|ORCLOSE, 0600);
6687dd7cddfSDavid du Colombier 			if(fd < 0){
6692af003dfSDavid du Colombier 				free(r);
6707dd7cddfSDavid du Colombier 				warning(nil, "can't create temp file: %r\n");
6717dd7cddfSDavid du Colombier 				goto Rescue2;
6727dd7cddfSDavid du Colombier 			}
6737dd7cddfSDavid du Colombier 			bout = emalloc(sizeof(Biobuf));
6747dd7cddfSDavid du Colombier 			Binit(bout, fd, OWRITE);
6757dd7cddfSDavid du Colombier 			for(n=0; n<ndumped; n++){
6767dd7cddfSDavid du Colombier 				rune = Bgetrune(b);
6777dd7cddfSDavid du Colombier 				if(rune == '\n')
6787dd7cddfSDavid du Colombier 					line++;
67929b83c63SDavid du Colombier 				if(rune == (Rune)Beof){
6802af003dfSDavid du Colombier 					free(r);
6817dd7cddfSDavid du Colombier 					Bterm(bout);
6827dd7cddfSDavid du Colombier 					free(bout);
6837dd7cddfSDavid du Colombier 					close(fd);
6847dd7cddfSDavid du Colombier 					goto Rescue2;
6857dd7cddfSDavid du Colombier 				}
6867dd7cddfSDavid du Colombier 				Bputrune(bout, rune);
6877dd7cddfSDavid du Colombier 			}
6887dd7cddfSDavid du Colombier 			Bterm(bout);
6897dd7cddfSDavid du Colombier 			free(bout);
6907dd7cddfSDavid du Colombier 			textload(&w->body, 0, buf, 1);
6917dd7cddfSDavid du Colombier 			close(fd);
6927dd7cddfSDavid du Colombier 			w->body.file->mod = TRUE;
6937dd7cddfSDavid du Colombier 			for(n=0; n<w->body.file->ntext; n++)
6947dd7cddfSDavid du Colombier 				w->body.file->text[n]->w->dirty = TRUE;
6957dd7cddfSDavid du Colombier 			winsettag(w);
6967dd7cddfSDavid du Colombier 		}else if(dumpid==0 && r[ns+1]!='+' && r[ns+1]!='-')
6977dd7cddfSDavid du Colombier 			get(&w->body, nil, nil, FALSE, XXX, nil, 0);
6987dd7cddfSDavid du Colombier 		if(fontr){
6997dd7cddfSDavid du Colombier 			fontx(&w->body, nil, nil, 0, 0, fontr, nfontr);
7007dd7cddfSDavid du Colombier 			free(fontr);
7017dd7cddfSDavid du Colombier 		}
7022af003dfSDavid du Colombier 		free(r);
7037dd7cddfSDavid du Colombier 		if(q0>w->body.file->nc || q1>w->body.file->nc || q0>q1)
7047dd7cddfSDavid du Colombier 			q0 = q1 = 0;
7059a747e4fSDavid du Colombier 		textshow(&w->body, q0, q1, 1);
7067dd7cddfSDavid du Colombier 		w->maxlines = min(w->body.nlines, max(w->maxlines, w->body.maxlines));
7077dd7cddfSDavid du Colombier 	}
7087dd7cddfSDavid du Colombier 	Bterm(b);
7097dd7cddfSDavid du Colombier 	fbuffree(buf);
7104b30ca09SDavid du Colombier 	return TRUE;
7117dd7cddfSDavid du Colombier 
7127dd7cddfSDavid du Colombier Rescue2:
7137dd7cddfSDavid du Colombier 	warning(nil, "bad load file %s:%d\n", file, line);
7147dd7cddfSDavid du Colombier 	Bterm(b);
7154b30ca09SDavid du Colombier Rescue1:
7164b30ca09SDavid du Colombier 	fbuffree(buf);
7174b30ca09SDavid du Colombier 	return FALSE;
7187dd7cddfSDavid du Colombier }
71959cc4ca5SDavid du Colombier 
72059cc4ca5SDavid du Colombier void
allwindows(void (* f)(Window *,void *),void * arg)72159cc4ca5SDavid du Colombier allwindows(void (*f)(Window*, void*), void *arg)
72259cc4ca5SDavid du Colombier {
72359cc4ca5SDavid du Colombier 	int i, j;
72459cc4ca5SDavid du Colombier 	Column *c;
72559cc4ca5SDavid du Colombier 
72659cc4ca5SDavid du Colombier 	for(i=0; i<row.ncol; i++){
72759cc4ca5SDavid du Colombier 		c = row.col[i];
72859cc4ca5SDavid du Colombier 		for(j=0; j<c->nw; j++)
72959cc4ca5SDavid du Colombier 			(*f)(c->w[j], arg);
73059cc4ca5SDavid du Colombier 	}
73159cc4ca5SDavid du Colombier }
732