xref: /plan9/sys/src/cmd/faces/main.c (revision 53b9a8487798c7301d999d284e212f6e6cb40d59)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <plumb.h>
57dd7cddfSDavid du Colombier #include <regexp.h>
67dd7cddfSDavid du Colombier #include <event.h>	/* for support routines only */
77dd7cddfSDavid du Colombier #include <bio.h>
87dd7cddfSDavid du Colombier #include "faces.h"
97dd7cddfSDavid du Colombier 
107dd7cddfSDavid du Colombier int	history = 0;	/* use old interface, showing history of mailbox rather than current state */
117dd7cddfSDavid du Colombier int	initload = 0;	/* initialize program with contents of mail box */
127dd7cddfSDavid du Colombier 
137dd7cddfSDavid du Colombier enum
147dd7cddfSDavid du Colombier {
157dd7cddfSDavid du Colombier 	Facesep = 6,	/* must be even to avoid damaging background stipple */
167dd7cddfSDavid du Colombier 	Infolines = 9,
17d3c05884SDavid du Colombier 
18d3c05884SDavid du Colombier 	HhmmTime = 18*60*60,	/* max age of face to display hh:mm time */
197dd7cddfSDavid du Colombier };
207dd7cddfSDavid du Colombier 
217dd7cddfSDavid du Colombier enum
227dd7cddfSDavid du Colombier {
237dd7cddfSDavid du Colombier 	Mainp,
247dd7cddfSDavid du Colombier 	Timep,
257dd7cddfSDavid du Colombier 	Mousep,
267dd7cddfSDavid du Colombier 	NPROC
277dd7cddfSDavid du Colombier };
287dd7cddfSDavid du Colombier 
297dd7cddfSDavid du Colombier int pids[NPROC];
307dd7cddfSDavid du Colombier char *procnames[] = {
317dd7cddfSDavid du Colombier 	"main",
327dd7cddfSDavid du Colombier 	"time",
337dd7cddfSDavid du Colombier 	"mouse"
347dd7cddfSDavid du Colombier };
357dd7cddfSDavid du Colombier 
367dd7cddfSDavid du Colombier Rectangle leftright = {0, 0, 20, 15};
377dd7cddfSDavid du Colombier 
387dd7cddfSDavid du Colombier uchar leftdata[] = {
397dd7cddfSDavid du Colombier 	0x00, 0x80, 0x00, 0x01, 0x80, 0x00, 0x03, 0x80,
407dd7cddfSDavid du Colombier 	0x00, 0x07, 0x80, 0x00, 0x0f, 0x00, 0x00, 0x1f,
417dd7cddfSDavid du Colombier 	0xff, 0xf0, 0x3f, 0xff, 0xf0, 0xff, 0xff, 0xf0,
427dd7cddfSDavid du Colombier 	0x3f, 0xff, 0xf0, 0x1f, 0xff, 0xf0, 0x0f, 0x00,
437dd7cddfSDavid du Colombier 	0x00, 0x07, 0x80, 0x00, 0x03, 0x80, 0x00, 0x01,
447dd7cddfSDavid du Colombier 	0x80, 0x00, 0x00, 0x80, 0x00
457dd7cddfSDavid du Colombier };
467dd7cddfSDavid du Colombier 
477dd7cddfSDavid du Colombier uchar rightdata[] = {
487dd7cddfSDavid du Colombier 	0x00, 0x10, 0x00, 0x00, 0x18, 0x00, 0x00, 0x1c,
497dd7cddfSDavid du Colombier 	0x00, 0x00, 0x1e, 0x00, 0x00, 0x0f, 0x00, 0xff,
507dd7cddfSDavid du Colombier 	0xff, 0x80, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xf0,
517dd7cddfSDavid du Colombier 	0xff, 0xff, 0xc0, 0xff, 0xff, 0x80, 0x00, 0x0f,
527dd7cddfSDavid du Colombier 	0x00, 0x00, 0x1e, 0x00, 0x00, 0x1c, 0x00, 0x00,
537dd7cddfSDavid du Colombier 	0x18, 0x00, 0x00, 0x10, 0x00
547dd7cddfSDavid du Colombier };
557dd7cddfSDavid du Colombier 
567dd7cddfSDavid du Colombier Image	*blue;		/* full arrow */
577dd7cddfSDavid du Colombier Image	*bgrnd;		/* pale blue background color */
587dd7cddfSDavid du Colombier Image	*left;		/* left-pointing arrow mask */
597dd7cddfSDavid du Colombier Image	*right;		/* right-pointing arrow mask */
607dd7cddfSDavid du Colombier Font	*tinyfont;
617dd7cddfSDavid du Colombier Font	*mediumfont;
627dd7cddfSDavid du Colombier Font	*datefont;
637dd7cddfSDavid du Colombier int	first, last;	/* first and last visible face; last is first invisible */
647dd7cddfSDavid du Colombier int	nfaces;
657dd7cddfSDavid du Colombier int	mousefd;
667dd7cddfSDavid du Colombier int	nacross;
677dd7cddfSDavid du Colombier int	ndown;
687dd7cddfSDavid du Colombier 
697dd7cddfSDavid du Colombier char	date[64];
707dd7cddfSDavid du Colombier Face	**faces;
717dd7cddfSDavid du Colombier char	*maildir = "/mail/fs/mbox";
72d9306527SDavid du Colombier ulong	now;
737dd7cddfSDavid du Colombier 
747dd7cddfSDavid du Colombier Point	datep = { 8, 6 };
757dd7cddfSDavid du Colombier Point	facep = { 8, 6+0+4 };	/* 0 updated to datefont->height in init() */
767dd7cddfSDavid du Colombier Point	enddate;			/* where date ends on display; used to place arrows */
777dd7cddfSDavid du Colombier Rectangle	leftr;			/* location of left arrow on display */
787dd7cddfSDavid du Colombier Rectangle	rightr;		/* location of right arrow on display */
79d9306527SDavid du Colombier void updatetimes(void);
807dd7cddfSDavid du Colombier 
817dd7cddfSDavid du Colombier void
setdate(void)827dd7cddfSDavid du Colombier setdate(void)
837dd7cddfSDavid du Colombier {
84d9306527SDavid du Colombier 	now = time(nil);
85d9306527SDavid du Colombier 	strcpy(date, ctime(now));
867dd7cddfSDavid du Colombier 	date[4+4+3+5] = '\0';	/* change from Thu Jul 22 14:28:43 EDT 1999\n to Thu Jul 22 14:28 */
877dd7cddfSDavid du Colombier }
887dd7cddfSDavid du Colombier 
897dd7cddfSDavid du Colombier void
init(void)907dd7cddfSDavid du Colombier init(void)
917dd7cddfSDavid du Colombier {
927dd7cddfSDavid du Colombier 	mousefd = open("/dev/mouse", OREAD);
937dd7cddfSDavid du Colombier 	if(mousefd < 0){
947dd7cddfSDavid du Colombier 		fprint(2, "faces: can't open mouse: %r\n");
957dd7cddfSDavid du Colombier 		exits("mouse");
967dd7cddfSDavid du Colombier 	}
977dd7cddfSDavid du Colombier 	initplumb();
987dd7cddfSDavid du Colombier 
997dd7cddfSDavid du Colombier 	/* make background color */
1007dd7cddfSDavid du Colombier 	bgrnd = allocimagemix(display, DPalebluegreen, DWhite);
1019a747e4fSDavid du Colombier 	blue = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x008888FF);	/* blue-green */
1027dd7cddfSDavid du Colombier 	left = allocimage(display, leftright, GREY1, 0, DWhite);
1037dd7cddfSDavid du Colombier 	right = allocimage(display, leftright, GREY1, 0, DWhite);
1047dd7cddfSDavid du Colombier 	if(bgrnd==nil || blue==nil || left==nil || right==nil){
1057dd7cddfSDavid du Colombier 		fprint(2, "faces: can't create images: %r\n");
1067dd7cddfSDavid du Colombier 		exits("image");
1077dd7cddfSDavid du Colombier 	}
1087dd7cddfSDavid du Colombier 
1097dd7cddfSDavid du Colombier 	loadimage(left, leftright, leftdata, sizeof leftdata);
1107dd7cddfSDavid du Colombier 	loadimage(right, leftright, rightdata, sizeof rightdata);
1117dd7cddfSDavid du Colombier 
1127dd7cddfSDavid du Colombier 	/* initialize little fonts */
1137dd7cddfSDavid du Colombier 	tinyfont = openfont(display, "/lib/font/bit/misc/ascii.5x7.font");
1147dd7cddfSDavid du Colombier 	if(tinyfont == nil)
1157dd7cddfSDavid du Colombier 		tinyfont = font;
1167dd7cddfSDavid du Colombier 	mediumfont = openfont(display, "/lib/font/bit/pelm/latin1.8.font");
1177dd7cddfSDavid du Colombier 	if(mediumfont == nil)
1187dd7cddfSDavid du Colombier 		mediumfont = font;
1197dd7cddfSDavid du Colombier 	datefont = font;
1207dd7cddfSDavid du Colombier 
1217dd7cddfSDavid du Colombier 	facep.y += datefont->height;
1227dd7cddfSDavid du Colombier 	if(datefont->height & 1)	/* stipple parity */
1237dd7cddfSDavid du Colombier 		facep.y++;
1247dd7cddfSDavid du Colombier 	faces = nil;
1257dd7cddfSDavid du Colombier }
1267dd7cddfSDavid du Colombier 
1277dd7cddfSDavid du Colombier void
drawtime(void)1287dd7cddfSDavid du Colombier drawtime(void)
1297dd7cddfSDavid du Colombier {
1307dd7cddfSDavid du Colombier 	Rectangle r;
1317dd7cddfSDavid du Colombier 
1327dd7cddfSDavid du Colombier 	r.min = addpt(screen->r.min, datep);
1337dd7cddfSDavid du Colombier 	if(eqpt(enddate, ZP)){
1347dd7cddfSDavid du Colombier 		enddate = r.min;
1357dd7cddfSDavid du Colombier 		enddate.x += stringwidth(datefont, "Wed May 30 22:54");	/* nice wide string */
1367dd7cddfSDavid du Colombier 		enddate.x += Facesep;	/* for safety */
1377dd7cddfSDavid du Colombier 	}
1387dd7cddfSDavid du Colombier 	r.max.x = enddate.x;
1397dd7cddfSDavid du Colombier 	r.max.y = enddate.y+datefont->height;
1407dd7cddfSDavid du Colombier 	draw(screen, r, bgrnd, nil, ZP);
1417dd7cddfSDavid du Colombier 	string(screen, r.min, display->black, ZP, datefont, date);
1427dd7cddfSDavid du Colombier }
1437dd7cddfSDavid du Colombier 
1447dd7cddfSDavid du Colombier void
timeproc(void)1457dd7cddfSDavid du Colombier timeproc(void)
1467dd7cddfSDavid du Colombier {
1477dd7cddfSDavid du Colombier 	for(;;){
1487dd7cddfSDavid du Colombier 		lockdisplay(display);
1497dd7cddfSDavid du Colombier 		drawtime();
150d9306527SDavid du Colombier 		updatetimes();
1517dd7cddfSDavid du Colombier 		flushimage(display, 1);
1527dd7cddfSDavid du Colombier 		unlockdisplay(display);
153*53b9a848SDavid du Colombier 		now = time(nil);
154*53b9a848SDavid du Colombier 		sleep(((60 - now%60) + 1)*1000); /* wait for minute to change */
1557dd7cddfSDavid du Colombier 		setdate();
1567dd7cddfSDavid du Colombier 	}
1577dd7cddfSDavid du Colombier }
1587dd7cddfSDavid du Colombier 
1597dd7cddfSDavid du Colombier int
alreadyseen(char * digest)160d9306527SDavid du Colombier alreadyseen(char *digest)
1617dd7cddfSDavid du Colombier {
1627dd7cddfSDavid du Colombier 	int i;
1637dd7cddfSDavid du Colombier 	Face *f;
1647dd7cddfSDavid du Colombier 
165d9306527SDavid du Colombier 	if(!digest)
1667dd7cddfSDavid du Colombier 		return 0;
1677dd7cddfSDavid du Colombier 
1687dd7cddfSDavid du Colombier 	/* can do accurate check */
1697dd7cddfSDavid du Colombier 	for(i=0; i<nfaces; i++){
1707dd7cddfSDavid du Colombier 		f = faces[i];
1717dd7cddfSDavid du Colombier 		if(f->str[Sdigest]!=nil && strcmp(digest, f->str[Sdigest])==0)
1727dd7cddfSDavid du Colombier 			return 1;
1737dd7cddfSDavid du Colombier 	}
1747dd7cddfSDavid du Colombier 	return 0;
1757dd7cddfSDavid du Colombier }
1767dd7cddfSDavid du Colombier 
1777dd7cddfSDavid du Colombier int
torune(Rune * r,char * s,int nr)1787dd7cddfSDavid du Colombier torune(Rune *r, char *s, int nr)
1797dd7cddfSDavid du Colombier {
1807dd7cddfSDavid du Colombier 	int i;
1817dd7cddfSDavid du Colombier 
1827dd7cddfSDavid du Colombier 	for(i=0; i<nr-1 && *s!='\0'; i++)
1837dd7cddfSDavid du Colombier 		s += chartorune(r+i, s);
1847dd7cddfSDavid du Colombier 	r[i] = L'\0';
1857dd7cddfSDavid du Colombier 	return i;
1867dd7cddfSDavid du Colombier }
1877dd7cddfSDavid du Colombier 
1887dd7cddfSDavid du Colombier void
center(Font * f,Point p,char * s,Image * color)1897dd7cddfSDavid du Colombier center(Font *f, Point p, char *s, Image *color)
1907dd7cddfSDavid du Colombier {
1917dd7cddfSDavid du Colombier 	int i, n, dx;
1927dd7cddfSDavid du Colombier 	Rune rbuf[32];
1937dd7cddfSDavid du Colombier 	char sbuf[32*UTFmax+1];
1947dd7cddfSDavid du Colombier 
1957dd7cddfSDavid du Colombier 	dx = stringwidth(f, s);
1967dd7cddfSDavid du Colombier 	if(dx > Facesize){
1977dd7cddfSDavid du Colombier 		n = torune(rbuf, s, nelem(rbuf));
1987dd7cddfSDavid du Colombier 		for(i=0; i<n; i++){
1997dd7cddfSDavid du Colombier 			dx = runestringnwidth(f, rbuf, i+1);
2007dd7cddfSDavid du Colombier 			if(dx > Facesize)
2017dd7cddfSDavid du Colombier 				break;
2027dd7cddfSDavid du Colombier 		}
2037dd7cddfSDavid du Colombier 		sprint(sbuf, "%.*S", i, rbuf);
2047dd7cddfSDavid du Colombier 		s = sbuf;
2057dd7cddfSDavid du Colombier 		dx = stringwidth(f, s);
2067dd7cddfSDavid du Colombier 	}
2077dd7cddfSDavid du Colombier 	p.x += (Facesize-dx)/2;
2087dd7cddfSDavid du Colombier 	string(screen, p, color, ZP, f, s);
2097dd7cddfSDavid du Colombier }
2107dd7cddfSDavid du Colombier 
2117dd7cddfSDavid du Colombier Rectangle
facerect(int index)2127dd7cddfSDavid du Colombier facerect(int index)	/* index is geometric; 0 is always upper left face */
2137dd7cddfSDavid du Colombier {
2147dd7cddfSDavid du Colombier 	Rectangle r;
2157dd7cddfSDavid du Colombier 	int x, y;
2167dd7cddfSDavid du Colombier 
2177dd7cddfSDavid du Colombier 	x = index % nacross;
2187dd7cddfSDavid du Colombier 	y = index / nacross;
2197dd7cddfSDavid du Colombier 	r.min = addpt(screen->r.min, facep);
2207dd7cddfSDavid du Colombier 	r.min.x += x*(Facesize+Facesep);
2217dd7cddfSDavid du Colombier 	r.min.y += y*(Facesize+Facesep+2*mediumfont->height);
2227dd7cddfSDavid du Colombier 	r.max = addpt(r.min, Pt(Facesize, Facesize));
2237dd7cddfSDavid du Colombier 	r.max.y += 2*mediumfont->height;
2247dd7cddfSDavid du Colombier 	/* simple fix to avoid drawing off screen, allowing customers to use position */
2257dd7cddfSDavid du Colombier 	if(index<0 || index>=nacross*ndown)
2267dd7cddfSDavid du Colombier 		r.max.x = r.min.x;
2277dd7cddfSDavid du Colombier 	return r;
2287dd7cddfSDavid du Colombier }
2297dd7cddfSDavid du Colombier 
230d9306527SDavid du Colombier static char *mon = "JanFebMarAprMayJunJulAugSepOctNovDec";
231d9306527SDavid du Colombier char*
facetime(Face * f,int * recent)232d9306527SDavid du Colombier facetime(Face *f, int *recent)
233d9306527SDavid du Colombier {
234d9306527SDavid du Colombier 	static char buf[30];
235d9306527SDavid du Colombier 
236fb7f0c93SDavid du Colombier 	if((long)(now - f->time) > HhmmTime){
237d9306527SDavid du Colombier 		*recent = 0;
238d9306527SDavid du Colombier 		sprint(buf, "%.3s %2d", mon+3*f->tm.mon, f->tm.mday);
239d9306527SDavid du Colombier 		return buf;
240d9306527SDavid du Colombier 	}else{
241d9306527SDavid du Colombier 		*recent = 1;
242d9306527SDavid du Colombier 		sprint(buf, "%02d:%02d", f->tm.hour, f->tm.min);
243d9306527SDavid du Colombier 		return buf;
244d9306527SDavid du Colombier 	}
245d9306527SDavid du Colombier }
246d9306527SDavid du Colombier 
2477dd7cddfSDavid du Colombier void
drawface(Face * f,int i)2487dd7cddfSDavid du Colombier drawface(Face *f, int i)
2497dd7cddfSDavid du Colombier {
250d9306527SDavid du Colombier 	char *tstr;
2517dd7cddfSDavid du Colombier 	Rectangle r;
2527dd7cddfSDavid du Colombier 	Point p;
2537dd7cddfSDavid du Colombier 
2547dd7cddfSDavid du Colombier 	if(f == nil)
2557dd7cddfSDavid du Colombier 		return;
2567dd7cddfSDavid du Colombier 	if(i<first || i>=last)
2577dd7cddfSDavid du Colombier 		return;
2587dd7cddfSDavid du Colombier 	r = facerect(i-first);
2597dd7cddfSDavid du Colombier 	draw(screen, r, bgrnd, nil, ZP);
2607dd7cddfSDavid du Colombier 	draw(screen, r, f->bit, f->mask, ZP);
2617dd7cddfSDavid du Colombier 	r.min.y += Facesize;
2627dd7cddfSDavid du Colombier 	center(mediumfont, r.min, f->str[Suser], display->black);
2637dd7cddfSDavid du Colombier 	r.min.y += mediumfont->height;
264d9306527SDavid du Colombier 	tstr = facetime(f, &f->recent);
265d9306527SDavid du Colombier 	center(mediumfont, r.min, tstr, display->black);
2667dd7cddfSDavid du Colombier 	if(f->unknown){
2677dd7cddfSDavid du Colombier 		r.min.y -= mediumfont->height + tinyfont->height + 2;
2687dd7cddfSDavid du Colombier 		for(p.x=-1; p.x<=1; p.x++)
2697dd7cddfSDavid du Colombier 			for(p.y=-1; p.y<=1; p.y++)
2707dd7cddfSDavid du Colombier 				center(tinyfont, addpt(r.min, p), f->str[Sdomain], display->white);
2717dd7cddfSDavid du Colombier 		center(tinyfont, r.min, f->str[Sdomain], display->black);
2727dd7cddfSDavid du Colombier 	}
2737dd7cddfSDavid du Colombier }
2747dd7cddfSDavid du Colombier 
2757dd7cddfSDavid du Colombier void
updatetimes(void)276d9306527SDavid du Colombier updatetimes(void)
277d9306527SDavid du Colombier {
278d9306527SDavid du Colombier 	int i;
279d9306527SDavid du Colombier 	Face *f;
280d9306527SDavid du Colombier 
281d9306527SDavid du Colombier 	for(i=0; i<nfaces; i++){
282d9306527SDavid du Colombier 		f = faces[i];
283d9306527SDavid du Colombier 		if(f == nil)
284d9306527SDavid du Colombier 			continue;
285d3c05884SDavid du Colombier 		if(((long)(now - f->time) <= HhmmTime) != f->recent)
286d9306527SDavid du Colombier 			drawface(f, i);
287d9306527SDavid du Colombier 	}
288d9306527SDavid du Colombier }
289d9306527SDavid du Colombier 
290d9306527SDavid du Colombier void
setlast(void)2917dd7cddfSDavid du Colombier setlast(void)
2927dd7cddfSDavid du Colombier {
2937dd7cddfSDavid du Colombier 	last = first+nacross*ndown;
2947dd7cddfSDavid du Colombier 	if(last > nfaces)
2957dd7cddfSDavid du Colombier 		last = nfaces;
2967dd7cddfSDavid du Colombier }
2977dd7cddfSDavid du Colombier 
2987dd7cddfSDavid du Colombier void
drawarrows(void)2997dd7cddfSDavid du Colombier drawarrows(void)
3007dd7cddfSDavid du Colombier {
3017dd7cddfSDavid du Colombier 	Point p;
3027dd7cddfSDavid du Colombier 
3037dd7cddfSDavid du Colombier 	p = enddate;
3047dd7cddfSDavid du Colombier 	p.x += Facesep;
3057dd7cddfSDavid du Colombier 	if(p.x & 1)
3067dd7cddfSDavid du Colombier 		p.x++;	/* align background texture */
3077dd7cddfSDavid du Colombier 	leftr = rectaddpt(leftright, p);
3087dd7cddfSDavid du Colombier 	p.x += Dx(leftright) + Facesep;
3097dd7cddfSDavid du Colombier 	rightr = rectaddpt(leftright, p);
3107dd7cddfSDavid du Colombier 	draw(screen, leftr, first>0? blue : bgrnd, left, leftright.min);
3117dd7cddfSDavid du Colombier 	draw(screen, rightr, last<nfaces? blue : bgrnd, right, leftright.min);
3127dd7cddfSDavid du Colombier }
3137dd7cddfSDavid du Colombier 
3147dd7cddfSDavid du Colombier void
addface(Face * f)3157dd7cddfSDavid du Colombier addface(Face *f)	/* always adds at 0 */
3167dd7cddfSDavid du Colombier {
3177dd7cddfSDavid du Colombier 	Face **ofaces;
3187dd7cddfSDavid du Colombier 	Rectangle r0, r1, r;
3197dd7cddfSDavid du Colombier 	int y, nx, ny;
3207dd7cddfSDavid du Colombier 
3217dd7cddfSDavid du Colombier 	if(f == nil)
3227dd7cddfSDavid du Colombier 		return;
3237dd7cddfSDavid du Colombier 	lockdisplay(display);
3247dd7cddfSDavid du Colombier 	if(first != 0){
3257dd7cddfSDavid du Colombier 		first = 0;
3267dd7cddfSDavid du Colombier 		resized();
3277dd7cddfSDavid du Colombier 	}
3287dd7cddfSDavid du Colombier 	findbit(f);
3297dd7cddfSDavid du Colombier 
3307dd7cddfSDavid du Colombier 	nx = nacross;
3317dd7cddfSDavid du Colombier 	ny = (nfaces+(nx-1)) / nx;
3327dd7cddfSDavid du Colombier 
3337dd7cddfSDavid du Colombier 	for(y=ny; y>=0; y--){
3347dd7cddfSDavid du Colombier 		/* move them along */
3357dd7cddfSDavid du Colombier 		r0 = facerect(y*nx+0);
3367dd7cddfSDavid du Colombier 		r1 = facerect(y*nx+1);
3377dd7cddfSDavid du Colombier 		r = r1;
3387dd7cddfSDavid du Colombier 		r.max.x = r.min.x + (nx - 1)*(Facesize+Facesep);
3397dd7cddfSDavid du Colombier 		draw(screen, r, screen, nil, r0.min);
3407dd7cddfSDavid du Colombier 		/* copy one down from row above */
3417dd7cddfSDavid du Colombier 		if(y != 0){
3427dd7cddfSDavid du Colombier 			r = facerect((y-1)*nx+nx-1);
3437dd7cddfSDavid du Colombier 			draw(screen, r0, screen, nil, r.min);
3447dd7cddfSDavid du Colombier 		}
3457dd7cddfSDavid du Colombier 	}
3467dd7cddfSDavid du Colombier 
3477dd7cddfSDavid du Colombier 	ofaces = faces;
3487dd7cddfSDavid du Colombier 	faces = emalloc((nfaces+1)*sizeof(Face*));
3497dd7cddfSDavid du Colombier 	memmove(faces+1, ofaces, nfaces*(sizeof(Face*)));
3507dd7cddfSDavid du Colombier 	free(ofaces);
3517dd7cddfSDavid du Colombier 	nfaces++;
3527dd7cddfSDavid du Colombier 	setlast();
3537dd7cddfSDavid du Colombier 	drawarrows();
3547dd7cddfSDavid du Colombier 	faces[0] = f;
3557dd7cddfSDavid du Colombier 	drawface(f, 0);
3567dd7cddfSDavid du Colombier 	flushimage(display, 1);
3577dd7cddfSDavid du Colombier 	unlockdisplay(display);
3587dd7cddfSDavid du Colombier }
3597dd7cddfSDavid du Colombier 
3607dd7cddfSDavid du Colombier void
loadmboxfaces(char * maildir)3617dd7cddfSDavid du Colombier loadmboxfaces(char *maildir)
3627dd7cddfSDavid du Colombier {
3637dd7cddfSDavid du Colombier 	int dirfd;
3649a747e4fSDavid du Colombier 	Dir *d;
3659a747e4fSDavid du Colombier 	int i, n;
3667dd7cddfSDavid du Colombier 
3677dd7cddfSDavid du Colombier 	dirfd = open(maildir, OREAD);
3687dd7cddfSDavid du Colombier 	if(dirfd >= 0){
3697dd7cddfSDavid du Colombier 		chdir(maildir);
3709a747e4fSDavid du Colombier 		while((n = dirread(dirfd, &d)) > 0){
3719a747e4fSDavid du Colombier 			for(i=0; i<n; i++)
3729a747e4fSDavid du Colombier 				addface(dirface(maildir, d[i].name));
3739a747e4fSDavid du Colombier 			free(d);
3749a747e4fSDavid du Colombier 		}
3757dd7cddfSDavid du Colombier 		close(dirfd);
3767dd7cddfSDavid du Colombier 	}
3777dd7cddfSDavid du Colombier }
3787dd7cddfSDavid du Colombier 
3797dd7cddfSDavid du Colombier void
freeface(Face * f)3807dd7cddfSDavid du Colombier freeface(Face *f)
3817dd7cddfSDavid du Colombier {
3827dd7cddfSDavid du Colombier 	int i;
3837dd7cddfSDavid du Colombier 
3847dd7cddfSDavid du Colombier 	if(f->file!=nil && f->bit!=f->file->image)
3857dd7cddfSDavid du Colombier 		freeimage(f->bit);
3867dd7cddfSDavid du Colombier 	freefacefile(f->file);
3877dd7cddfSDavid du Colombier 	for(i=0; i<Nstring; i++)
3887dd7cddfSDavid du Colombier 		free(f->str[i]);
3897dd7cddfSDavid du Colombier 	free(f);
3907dd7cddfSDavid du Colombier }
3917dd7cddfSDavid du Colombier 
3927dd7cddfSDavid du Colombier void
delface(int j)3937dd7cddfSDavid du Colombier delface(int j)
3947dd7cddfSDavid du Colombier {
3957dd7cddfSDavid du Colombier 	Rectangle r0, r1, r;
3967dd7cddfSDavid du Colombier 	int nx, ny, x, y;
3977dd7cddfSDavid du Colombier 
3987dd7cddfSDavid du Colombier 	if(j < first)
3997dd7cddfSDavid du Colombier 		first--;
4007dd7cddfSDavid du Colombier 	else if(j < last){
4017dd7cddfSDavid du Colombier 		nx = nacross;
4027dd7cddfSDavid du Colombier 		ny = (nfaces+(nx-1)) / nx;
4037dd7cddfSDavid du Colombier 		x = (j-first)%nx;
4047dd7cddfSDavid du Colombier 		for(y=(j-first)/nx; y<ny; y++){
4057dd7cddfSDavid du Colombier 			if(x != nx-1){
4067dd7cddfSDavid du Colombier 				/* move them along */
4077dd7cddfSDavid du Colombier 				r0 = facerect(y*nx+x);
4087dd7cddfSDavid du Colombier 				r1 = facerect(y*nx+x+1);
4097dd7cddfSDavid du Colombier 				r = r0;
4107dd7cddfSDavid du Colombier 				r.max.x = r.min.x + (nx - x - 1)*(Facesize+Facesep);
4117dd7cddfSDavid du Colombier 				draw(screen, r, screen, nil, r1.min);
4127dd7cddfSDavid du Colombier 			}
4137dd7cddfSDavid du Colombier 			if(y != ny-1){
4147dd7cddfSDavid du Colombier 				/* copy one up from row below */
4157dd7cddfSDavid du Colombier 				r = facerect((y+1)*nx);
4167dd7cddfSDavid du Colombier 				draw(screen, facerect(y*nx+nx-1), screen, nil, r.min);
4177dd7cddfSDavid du Colombier 			}
4187dd7cddfSDavid du Colombier 			x = 0;
4197dd7cddfSDavid du Colombier 		}
4207dd7cddfSDavid du Colombier 		if(last < nfaces)	/* first off-screen becomes visible */
4217dd7cddfSDavid du Colombier 			drawface(faces[last], last-1);
4227dd7cddfSDavid du Colombier 		else{
4237dd7cddfSDavid du Colombier 			/* clear final spot */
4247dd7cddfSDavid du Colombier 			r = facerect(last-first-1);
4257dd7cddfSDavid du Colombier 			draw(screen, r, bgrnd, nil, r.min);
4267dd7cddfSDavid du Colombier 		}
4277dd7cddfSDavid du Colombier 	}
4287dd7cddfSDavid du Colombier 	freeface(faces[j]);
4297dd7cddfSDavid du Colombier 	memmove(faces+j, faces+j+1, (nfaces-(j+1))*sizeof(Face*));
4307dd7cddfSDavid du Colombier 	nfaces--;
4317dd7cddfSDavid du Colombier 	setlast();
4327dd7cddfSDavid du Colombier 	drawarrows();
4337dd7cddfSDavid du Colombier }
4347dd7cddfSDavid du Colombier 
4357dd7cddfSDavid du Colombier void
dodelete(int i)4367dd7cddfSDavid du Colombier dodelete(int i)
4377dd7cddfSDavid du Colombier {
4387dd7cddfSDavid du Colombier 	Face *f;
4397dd7cddfSDavid du Colombier 
4407dd7cddfSDavid du Colombier 	f = faces[i];
4417dd7cddfSDavid du Colombier 	if(history){
4427dd7cddfSDavid du Colombier 		free(f->str[Sshow]);
4437dd7cddfSDavid du Colombier 		f->str[Sshow] = estrdup("");
4447dd7cddfSDavid du Colombier 	}else{
4457dd7cddfSDavid du Colombier 		delface(i);
4467dd7cddfSDavid du Colombier 		flushimage(display, 1);
4477dd7cddfSDavid du Colombier 	}
4487dd7cddfSDavid du Colombier }
4497dd7cddfSDavid du Colombier 
4507dd7cddfSDavid du Colombier void
delete(char * s,char * digest)4517dd7cddfSDavid du Colombier delete(char *s, char *digest)
4527dd7cddfSDavid du Colombier {
4537dd7cddfSDavid du Colombier 	int i;
4547dd7cddfSDavid du Colombier 	Face *f;
4557dd7cddfSDavid du Colombier 
4567dd7cddfSDavid du Colombier 	lockdisplay(display);
4577dd7cddfSDavid du Colombier 	for(i=0; i<nfaces; i++){
4587dd7cddfSDavid du Colombier 		f = faces[i];
4597dd7cddfSDavid du Colombier 		if(digest != nil){
4607dd7cddfSDavid du Colombier 			if(f->str[Sdigest]!=nil && strcmp(digest, f->str[Sdigest]) == 0){
4617dd7cddfSDavid du Colombier 				dodelete(i);
4627dd7cddfSDavid du Colombier 				break;
4637dd7cddfSDavid du Colombier 			}
4647dd7cddfSDavid du Colombier 		}else{
4657dd7cddfSDavid du Colombier 			if(f->str[Sshow] && strcmp(s, f->str[Sshow]) == 0){
4667dd7cddfSDavid du Colombier 				dodelete(i);
4677dd7cddfSDavid du Colombier 				break;
4687dd7cddfSDavid du Colombier 			}
4697dd7cddfSDavid du Colombier 		}
4707dd7cddfSDavid du Colombier 	}
4717dd7cddfSDavid du Colombier 	unlockdisplay(display);
4727dd7cddfSDavid du Colombier }
4737dd7cddfSDavid du Colombier 
4747dd7cddfSDavid du Colombier void
faceproc(void)4757dd7cddfSDavid du Colombier faceproc(void)
4767dd7cddfSDavid du Colombier {
4777dd7cddfSDavid du Colombier 	for(;;)
4787dd7cddfSDavid du Colombier 		addface(nextface());
4797dd7cddfSDavid du Colombier }
4807dd7cddfSDavid du Colombier 
4817dd7cddfSDavid du Colombier void
resized(void)4827dd7cddfSDavid du Colombier resized(void)
4837dd7cddfSDavid du Colombier {
4847dd7cddfSDavid du Colombier 	int i;
4857dd7cddfSDavid du Colombier 
4867dd7cddfSDavid du Colombier 	nacross = (Dx(screen->r)-2*facep.x+Facesep)/(Facesize+Facesep);
4877dd7cddfSDavid du Colombier 	for(ndown=1; rectinrect(facerect(ndown*nacross), screen->r); ndown++)
4887dd7cddfSDavid du Colombier 		;
4897dd7cddfSDavid du Colombier 	setlast();
4907dd7cddfSDavid du Colombier 	draw(screen, screen->r, bgrnd, nil, ZP);
4917dd7cddfSDavid du Colombier 	enddate = ZP;
4927dd7cddfSDavid du Colombier 	drawtime();
4937dd7cddfSDavid du Colombier 	for(i=0; i<nfaces; i++)
4947dd7cddfSDavid du Colombier 		drawface(faces[i], i);
4957dd7cddfSDavid du Colombier 	drawarrows();
4967dd7cddfSDavid du Colombier 	flushimage(display, 1);
4977dd7cddfSDavid du Colombier }
4987dd7cddfSDavid du Colombier 
4997dd7cddfSDavid du Colombier void
eresized(int new)5007dd7cddfSDavid du Colombier eresized(int new)
5017dd7cddfSDavid du Colombier {
5027dd7cddfSDavid du Colombier 	lockdisplay(display);
5037dd7cddfSDavid du Colombier 	if(new && getwindow(display, Refnone) < 0) {
5047dd7cddfSDavid du Colombier 		fprint(2, "can't reattach to window\n");
5057dd7cddfSDavid du Colombier 		killall("reattach");
5067dd7cddfSDavid du Colombier 	}
5077dd7cddfSDavid du Colombier 	resized();
5087dd7cddfSDavid du Colombier 	unlockdisplay(display);
5097dd7cddfSDavid du Colombier }
5107dd7cddfSDavid du Colombier 
5117dd7cddfSDavid du Colombier int
getmouse(Mouse * m)5127dd7cddfSDavid du Colombier getmouse(Mouse *m)
5137dd7cddfSDavid du Colombier {
5147dd7cddfSDavid du Colombier 	int n;
5157dd7cddfSDavid du Colombier 	static int eof;
5167dd7cddfSDavid du Colombier 	char buf[128];
5177dd7cddfSDavid du Colombier 
5187dd7cddfSDavid du Colombier 	if(eof)
5197dd7cddfSDavid du Colombier 		return 0;
5207dd7cddfSDavid du Colombier 	for(;;){
5217dd7cddfSDavid du Colombier 		n = read(mousefd, buf, sizeof(buf));
5227dd7cddfSDavid du Colombier 		if(n <= 0){
5237dd7cddfSDavid du Colombier 			/* so callers needn't check return value every time */
5247dd7cddfSDavid du Colombier 			eof = 1;
5257dd7cddfSDavid du Colombier 			m->buttons = 0;
5267dd7cddfSDavid du Colombier 			return 0;
5277dd7cddfSDavid du Colombier 		}
5287dd7cddfSDavid du Colombier 		n = eatomouse(m, buf, n);
5297dd7cddfSDavid du Colombier 		if(n > 0)
5307dd7cddfSDavid du Colombier 			return 1;
5317dd7cddfSDavid du Colombier 	}
5327dd7cddfSDavid du Colombier }
5337dd7cddfSDavid du Colombier 
5347dd7cddfSDavid du Colombier enum
5357dd7cddfSDavid du Colombier {
5367dd7cddfSDavid du Colombier 	Clicksize	= 3,		/* pixels */
5377dd7cddfSDavid du Colombier };
5387dd7cddfSDavid du Colombier 
5397dd7cddfSDavid du Colombier int
scroll(int but,Point p)5407dd7cddfSDavid du Colombier scroll(int but, Point p)
5417dd7cddfSDavid du Colombier {
5427dd7cddfSDavid du Colombier 	int delta;
5437dd7cddfSDavid du Colombier 
5447dd7cddfSDavid du Colombier 	delta = 0;
5457dd7cddfSDavid du Colombier 	lockdisplay(display);
5467dd7cddfSDavid du Colombier 	if(ptinrect(p, leftr) && first>0){
5477dd7cddfSDavid du Colombier 		if(but == 2)
5487dd7cddfSDavid du Colombier 			delta = -first;
5497dd7cddfSDavid du Colombier 		else{
5507dd7cddfSDavid du Colombier 			delta = nacross;
5517dd7cddfSDavid du Colombier 			if(delta > first)
5527dd7cddfSDavid du Colombier 				delta = first;
5537dd7cddfSDavid du Colombier 			delta = -delta;
5547dd7cddfSDavid du Colombier 		}
5557dd7cddfSDavid du Colombier 	}else if(ptinrect(p, rightr) && last<nfaces){
5567dd7cddfSDavid du Colombier 		if(but == 2)
5577dd7cddfSDavid du Colombier 			delta = (nfaces-nacross*ndown) - first;
5587dd7cddfSDavid du Colombier 		else{
5597dd7cddfSDavid du Colombier 			delta = nacross;
5607dd7cddfSDavid du Colombier 			if(delta > nfaces-last)
5617dd7cddfSDavid du Colombier 				delta = nfaces-last;
5627dd7cddfSDavid du Colombier 		}
5637dd7cddfSDavid du Colombier 	}
5647dd7cddfSDavid du Colombier 	first += delta;
5657dd7cddfSDavid du Colombier 	last += delta;
5667dd7cddfSDavid du Colombier 	unlockdisplay(display);
5677dd7cddfSDavid du Colombier 	if(delta)
5687dd7cddfSDavid du Colombier 		eresized(0);
5697dd7cddfSDavid du Colombier 	return delta;
5707dd7cddfSDavid du Colombier }
5717dd7cddfSDavid du Colombier 
5727dd7cddfSDavid du Colombier void
click(int button,Mouse * m)5737dd7cddfSDavid du Colombier click(int button, Mouse *m)
5747dd7cddfSDavid du Colombier {
5757dd7cddfSDavid du Colombier 	Point p;
5767dd7cddfSDavid du Colombier 	int i;
5777dd7cddfSDavid du Colombier 
5787dd7cddfSDavid du Colombier 	p = m->xy;
5797dd7cddfSDavid du Colombier 	while(m->buttons == (1<<(button-1)))
5807dd7cddfSDavid du Colombier 		getmouse(m);
5817dd7cddfSDavid du Colombier 	if(m->buttons)
5827dd7cddfSDavid du Colombier 		return;
5837dd7cddfSDavid du Colombier 	if(abs(p.x-m->xy.x)>Clicksize || abs(p.y-m->xy.y)>Clicksize)
5847dd7cddfSDavid du Colombier 		return;
5857dd7cddfSDavid du Colombier 	switch(button){
5867dd7cddfSDavid du Colombier 	case 1:
5877dd7cddfSDavid du Colombier 		if(scroll(1, p))
5887dd7cddfSDavid du Colombier 			break;
5897dd7cddfSDavid du Colombier 		if(history){
5907dd7cddfSDavid du Colombier 			/* click clears display */
5917dd7cddfSDavid du Colombier 			lockdisplay(display);
5927dd7cddfSDavid du Colombier 			for(i=0; i<nfaces; i++)
5937dd7cddfSDavid du Colombier 				freeface(faces[i]);
5947dd7cddfSDavid du Colombier 			free(faces);
5957dd7cddfSDavid du Colombier 			faces=nil;
5967dd7cddfSDavid du Colombier 			nfaces = 0;
5977dd7cddfSDavid du Colombier 			unlockdisplay(display);
5987dd7cddfSDavid du Colombier 			eresized(0);
5997dd7cddfSDavid du Colombier 			return;
6007dd7cddfSDavid du Colombier 		}else{
6017dd7cddfSDavid du Colombier 			for(i=first; i<last; i++)	/* clear vwhois faces */
6027dd7cddfSDavid du Colombier 				if(ptinrect(p, facerect(i-first))
603d9d5974cSDavid du Colombier 				&& strstr(faces[i]->str[Sshow], "/XXXvwhois")){
6047dd7cddfSDavid du Colombier 					delface(i);
6057dd7cddfSDavid du Colombier 					flushimage(display, 1);
6067dd7cddfSDavid du Colombier 				}
6077dd7cddfSDavid du Colombier 		}
6087dd7cddfSDavid du Colombier 		break;
6097dd7cddfSDavid du Colombier 	case 2:
6107dd7cddfSDavid du Colombier 		scroll(2, p);
6117dd7cddfSDavid du Colombier 		break;
6127dd7cddfSDavid du Colombier 	case 3:
6137dd7cddfSDavid du Colombier 		scroll(3, p);
6147dd7cddfSDavid du Colombier 		lockdisplay(display);
6157dd7cddfSDavid du Colombier 		for(i=first; i<last; i++)
6167dd7cddfSDavid du Colombier 			if(ptinrect(p, facerect(i-first))){
6177dd7cddfSDavid du Colombier 				showmail(faces[i]);
6187dd7cddfSDavid du Colombier 				break;
6197dd7cddfSDavid du Colombier 			}
6207dd7cddfSDavid du Colombier 		unlockdisplay(display);
6217dd7cddfSDavid du Colombier 		break;
6227dd7cddfSDavid du Colombier 	}
6237dd7cddfSDavid du Colombier }
6247dd7cddfSDavid du Colombier 
6257dd7cddfSDavid du Colombier void
mouseproc(void)6267dd7cddfSDavid du Colombier mouseproc(void)
6277dd7cddfSDavid du Colombier {
6287dd7cddfSDavid du Colombier 	Mouse mouse;
6297dd7cddfSDavid du Colombier 
6307dd7cddfSDavid du Colombier 	while(getmouse(&mouse)){
6317dd7cddfSDavid du Colombier 		if(mouse.buttons == 1)
6327dd7cddfSDavid du Colombier 			click(1, &mouse);
6337dd7cddfSDavid du Colombier 		else if(mouse.buttons == 2)
6347dd7cddfSDavid du Colombier 			click(2, &mouse);
6357dd7cddfSDavid du Colombier 		else if(mouse.buttons == 4)
6367dd7cddfSDavid du Colombier 			click(3, &mouse);
6377dd7cddfSDavid du Colombier 
6387dd7cddfSDavid du Colombier 		while(mouse.buttons)
6397dd7cddfSDavid du Colombier 			getmouse(&mouse);
6407dd7cddfSDavid du Colombier 	}
6417dd7cddfSDavid du Colombier }
6427dd7cddfSDavid du Colombier 
6437dd7cddfSDavid du Colombier void
killall(char * s)6447dd7cddfSDavid du Colombier killall(char *s)
6457dd7cddfSDavid du Colombier {
6467dd7cddfSDavid du Colombier 	int i, pid;
6477dd7cddfSDavid du Colombier 
6487dd7cddfSDavid du Colombier 	pid = getpid();
6497dd7cddfSDavid du Colombier 	for(i=0; i<NPROC; i++)
6507dd7cddfSDavid du Colombier 		if(pids[i] && pids[i]!=pid)
6517dd7cddfSDavid du Colombier 			postnote(PNPROC, pids[i], "kill");
6527dd7cddfSDavid du Colombier 	exits(s);
6537dd7cddfSDavid du Colombier }
6547dd7cddfSDavid du Colombier 
6557dd7cddfSDavid du Colombier void
startproc(void (* f)(void),int index)6567dd7cddfSDavid du Colombier startproc(void (*f)(void), int index)
6577dd7cddfSDavid du Colombier {
6587dd7cddfSDavid du Colombier 	int pid;
6597dd7cddfSDavid du Colombier 
6607dd7cddfSDavid du Colombier 	switch(pid = rfork(RFPROC|RFMEM|RFNOWAIT)){
6617dd7cddfSDavid du Colombier 	case -1:
6627dd7cddfSDavid du Colombier 		fprint(2, "faces: fork failed: %r\n");
6637dd7cddfSDavid du Colombier 		killall("fork failed");
6647dd7cddfSDavid du Colombier 	case 0:
6657dd7cddfSDavid du Colombier 		f();
6667dd7cddfSDavid du Colombier 		fprint(2, "faces: %s process exits\n", procnames[index]);
6677dd7cddfSDavid du Colombier 		if(index >= 0)
6687dd7cddfSDavid du Colombier 			killall("process died");
6697dd7cddfSDavid du Colombier 		exits(nil);
6707dd7cddfSDavid du Colombier 	}
6717dd7cddfSDavid du Colombier 	if(index >= 0)
6727dd7cddfSDavid du Colombier 		pids[index] = pid;
6737dd7cddfSDavid du Colombier }
6747dd7cddfSDavid du Colombier 
6757dd7cddfSDavid du Colombier void
usage(void)6765fab9909SDavid du Colombier usage(void)
6775fab9909SDavid du Colombier {
678d9d5974cSDavid du Colombier 	fprint(2, "usage: faces [-hi] [-m maildir]\n");
6795fab9909SDavid du Colombier 	exits("usage");
6805fab9909SDavid du Colombier }
6815fab9909SDavid du Colombier 
6825fab9909SDavid du Colombier void
main(int argc,char * argv[])6837dd7cddfSDavid du Colombier main(int argc, char *argv[])
6847dd7cddfSDavid du Colombier {
685a3b78ba5SDavid du Colombier 	int i;
686a3b78ba5SDavid du Colombier 
6877dd7cddfSDavid du Colombier 	ARGBEGIN{
6887dd7cddfSDavid du Colombier 	case 'h':
6897dd7cddfSDavid du Colombier 		history++;
6907dd7cddfSDavid du Colombier 		break;
6917dd7cddfSDavid du Colombier 	case 'i':
6927dd7cddfSDavid du Colombier 		initload++;
6937dd7cddfSDavid du Colombier 		break;
6945fab9909SDavid du Colombier 	case 'm':
6955fab9909SDavid du Colombier 		addmaildir(EARGF(usage()));
696a3b78ba5SDavid du Colombier 		maildir = nil;
6975fab9909SDavid du Colombier 		break;
6987dd7cddfSDavid du Colombier 	default:
6995fab9909SDavid du Colombier 		usage();
7007dd7cddfSDavid du Colombier 	}ARGEND
7017dd7cddfSDavid du Colombier 
7027dd7cddfSDavid du Colombier 	if(initdraw(nil, nil, "faces") < 0){
7037dd7cddfSDavid du Colombier 		fprint(2, "faces: initdraw failed: %r\n");
7047dd7cddfSDavid du Colombier 		exits("initdraw");
7057dd7cddfSDavid du Colombier 	}
706a3b78ba5SDavid du Colombier 	if(maildir)
707a3b78ba5SDavid du Colombier 		addmaildir(maildir);
7087dd7cddfSDavid du Colombier 	init();
7097dd7cddfSDavid du Colombier 	unlockdisplay(display);	/* initdraw leaves it locked */
7107dd7cddfSDavid du Colombier 	display->locking = 1;	/* tell library we're using the display lock */
7117dd7cddfSDavid du Colombier 	setdate();
7127dd7cddfSDavid du Colombier 	eresized(0);
7137dd7cddfSDavid du Colombier 
7147dd7cddfSDavid du Colombier 	pids[Mainp] = getpid();
7157dd7cddfSDavid du Colombier 	startproc(timeproc, Timep);
7167dd7cddfSDavid du Colombier 	startproc(mouseproc, Mousep);
7177dd7cddfSDavid du Colombier 	if(initload)
718a3b78ba5SDavid du Colombier 		for(i = 0; i < nmaildirs; i++)
719a3b78ba5SDavid du Colombier 		 loadmboxfaces(maildirs[i]);
7207dd7cddfSDavid du Colombier 	faceproc();
7217dd7cddfSDavid du Colombier 	fprint(2, "faces: %s process exits\n", procnames[Mainp]);
7227dd7cddfSDavid du Colombier 	killall(nil);
7237dd7cddfSDavid du Colombier }
724