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 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 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 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 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); 1537dd7cddfSDavid du Colombier sleep(60000); 1547dd7cddfSDavid du Colombier setdate(); 1557dd7cddfSDavid du Colombier } 1567dd7cddfSDavid du Colombier } 1577dd7cddfSDavid du Colombier 1587dd7cddfSDavid du Colombier int 159d9306527SDavid du Colombier alreadyseen(char *digest) 1607dd7cddfSDavid du Colombier { 1617dd7cddfSDavid du Colombier int i; 1627dd7cddfSDavid du Colombier Face *f; 1637dd7cddfSDavid du Colombier 164d9306527SDavid du Colombier if(!digest) 1657dd7cddfSDavid du Colombier return 0; 1667dd7cddfSDavid du Colombier 1677dd7cddfSDavid du Colombier /* can do accurate check */ 1687dd7cddfSDavid du Colombier for(i=0; i<nfaces; i++){ 1697dd7cddfSDavid du Colombier f = faces[i]; 1707dd7cddfSDavid du Colombier if(f->str[Sdigest]!=nil && strcmp(digest, f->str[Sdigest])==0) 1717dd7cddfSDavid du Colombier return 1; 1727dd7cddfSDavid du Colombier } 1737dd7cddfSDavid du Colombier return 0; 1747dd7cddfSDavid du Colombier } 1757dd7cddfSDavid du Colombier 1767dd7cddfSDavid du Colombier int 1777dd7cddfSDavid du Colombier torune(Rune *r, char *s, int nr) 1787dd7cddfSDavid du Colombier { 1797dd7cddfSDavid du Colombier int i; 1807dd7cddfSDavid du Colombier 1817dd7cddfSDavid du Colombier for(i=0; i<nr-1 && *s!='\0'; i++) 1827dd7cddfSDavid du Colombier s += chartorune(r+i, s); 1837dd7cddfSDavid du Colombier r[i] = L'\0'; 1847dd7cddfSDavid du Colombier return i; 1857dd7cddfSDavid du Colombier } 1867dd7cddfSDavid du Colombier 1877dd7cddfSDavid du Colombier void 1887dd7cddfSDavid du Colombier center(Font *f, Point p, char *s, Image *color) 1897dd7cddfSDavid du Colombier { 1907dd7cddfSDavid du Colombier int i, n, dx; 1917dd7cddfSDavid du Colombier Rune rbuf[32]; 1927dd7cddfSDavid du Colombier char sbuf[32*UTFmax+1]; 1937dd7cddfSDavid du Colombier 1947dd7cddfSDavid du Colombier dx = stringwidth(f, s); 1957dd7cddfSDavid du Colombier if(dx > Facesize){ 1967dd7cddfSDavid du Colombier n = torune(rbuf, s, nelem(rbuf)); 1977dd7cddfSDavid du Colombier for(i=0; i<n; i++){ 1987dd7cddfSDavid du Colombier dx = runestringnwidth(f, rbuf, i+1); 1997dd7cddfSDavid du Colombier if(dx > Facesize) 2007dd7cddfSDavid du Colombier break; 2017dd7cddfSDavid du Colombier } 2027dd7cddfSDavid du Colombier sprint(sbuf, "%.*S", i, rbuf); 2037dd7cddfSDavid du Colombier s = sbuf; 2047dd7cddfSDavid du Colombier dx = stringwidth(f, s); 2057dd7cddfSDavid du Colombier } 2067dd7cddfSDavid du Colombier p.x += (Facesize-dx)/2; 2077dd7cddfSDavid du Colombier string(screen, p, color, ZP, f, s); 2087dd7cddfSDavid du Colombier } 2097dd7cddfSDavid du Colombier 2107dd7cddfSDavid du Colombier Rectangle 2117dd7cddfSDavid du Colombier facerect(int index) /* index is geometric; 0 is always upper left face */ 2127dd7cddfSDavid du Colombier { 2137dd7cddfSDavid du Colombier Rectangle r; 2147dd7cddfSDavid du Colombier int x, y; 2157dd7cddfSDavid du Colombier 2167dd7cddfSDavid du Colombier x = index % nacross; 2177dd7cddfSDavid du Colombier y = index / nacross; 2187dd7cddfSDavid du Colombier r.min = addpt(screen->r.min, facep); 2197dd7cddfSDavid du Colombier r.min.x += x*(Facesize+Facesep); 2207dd7cddfSDavid du Colombier r.min.y += y*(Facesize+Facesep+2*mediumfont->height); 2217dd7cddfSDavid du Colombier r.max = addpt(r.min, Pt(Facesize, Facesize)); 2227dd7cddfSDavid du Colombier r.max.y += 2*mediumfont->height; 2237dd7cddfSDavid du Colombier /* simple fix to avoid drawing off screen, allowing customers to use position */ 2247dd7cddfSDavid du Colombier if(index<0 || index>=nacross*ndown) 2257dd7cddfSDavid du Colombier r.max.x = r.min.x; 2267dd7cddfSDavid du Colombier return r; 2277dd7cddfSDavid du Colombier } 2287dd7cddfSDavid du Colombier 229d9306527SDavid du Colombier static char *mon = "JanFebMarAprMayJunJulAugSepOctNovDec"; 230d9306527SDavid du Colombier char* 231d9306527SDavid du Colombier facetime(Face *f, int *recent) 232d9306527SDavid du Colombier { 233d9306527SDavid du Colombier static char buf[30]; 234d9306527SDavid du Colombier 235fb7f0c93SDavid du Colombier if((long)(now - f->time) > HhmmTime){ 236d9306527SDavid du Colombier *recent = 0; 237d9306527SDavid du Colombier sprint(buf, "%.3s %2d", mon+3*f->tm.mon, f->tm.mday); 238d9306527SDavid du Colombier return buf; 239d9306527SDavid du Colombier }else{ 240d9306527SDavid du Colombier *recent = 1; 241d9306527SDavid du Colombier sprint(buf, "%02d:%02d", f->tm.hour, f->tm.min); 242d9306527SDavid du Colombier return buf; 243d9306527SDavid du Colombier } 244d9306527SDavid du Colombier } 245d9306527SDavid du Colombier 2467dd7cddfSDavid du Colombier void 2477dd7cddfSDavid du Colombier drawface(Face *f, int i) 2487dd7cddfSDavid du Colombier { 249d9306527SDavid du Colombier char *tstr; 2507dd7cddfSDavid du Colombier Rectangle r; 2517dd7cddfSDavid du Colombier Point p; 2527dd7cddfSDavid du Colombier 2537dd7cddfSDavid du Colombier if(f == nil) 2547dd7cddfSDavid du Colombier return; 2557dd7cddfSDavid du Colombier if(i<first || i>=last) 2567dd7cddfSDavid du Colombier return; 2577dd7cddfSDavid du Colombier r = facerect(i-first); 2587dd7cddfSDavid du Colombier draw(screen, r, bgrnd, nil, ZP); 2597dd7cddfSDavid du Colombier draw(screen, r, f->bit, f->mask, ZP); 2607dd7cddfSDavid du Colombier r.min.y += Facesize; 2617dd7cddfSDavid du Colombier center(mediumfont, r.min, f->str[Suser], display->black); 2627dd7cddfSDavid du Colombier r.min.y += mediumfont->height; 263d9306527SDavid du Colombier tstr = facetime(f, &f->recent); 264d9306527SDavid du Colombier center(mediumfont, r.min, tstr, display->black); 2657dd7cddfSDavid du Colombier if(f->unknown){ 2667dd7cddfSDavid du Colombier r.min.y -= mediumfont->height + tinyfont->height + 2; 2677dd7cddfSDavid du Colombier for(p.x=-1; p.x<=1; p.x++) 2687dd7cddfSDavid du Colombier for(p.y=-1; p.y<=1; p.y++) 2697dd7cddfSDavid du Colombier center(tinyfont, addpt(r.min, p), f->str[Sdomain], display->white); 2707dd7cddfSDavid du Colombier center(tinyfont, r.min, f->str[Sdomain], display->black); 2717dd7cddfSDavid du Colombier } 2727dd7cddfSDavid du Colombier } 2737dd7cddfSDavid du Colombier 2747dd7cddfSDavid du Colombier void 275d9306527SDavid du Colombier updatetimes(void) 276d9306527SDavid du Colombier { 277d9306527SDavid du Colombier int i; 278d9306527SDavid du Colombier Face *f; 279d9306527SDavid du Colombier 280d9306527SDavid du Colombier for(i=0; i<nfaces; i++){ 281d9306527SDavid du Colombier f = faces[i]; 282d9306527SDavid du Colombier if(f == nil) 283d9306527SDavid du Colombier continue; 284d3c05884SDavid du Colombier if(((long)(now - f->time) <= HhmmTime) != f->recent) 285d9306527SDavid du Colombier drawface(f, i); 286d9306527SDavid du Colombier } 287d9306527SDavid du Colombier } 288d9306527SDavid du Colombier 289d9306527SDavid du Colombier void 2907dd7cddfSDavid du Colombier setlast(void) 2917dd7cddfSDavid du Colombier { 2927dd7cddfSDavid du Colombier last = first+nacross*ndown; 2937dd7cddfSDavid du Colombier if(last > nfaces) 2947dd7cddfSDavid du Colombier last = nfaces; 2957dd7cddfSDavid du Colombier } 2967dd7cddfSDavid du Colombier 2977dd7cddfSDavid du Colombier void 2987dd7cddfSDavid du Colombier drawarrows(void) 2997dd7cddfSDavid du Colombier { 3007dd7cddfSDavid du Colombier Point p; 3017dd7cddfSDavid du Colombier 3027dd7cddfSDavid du Colombier p = enddate; 3037dd7cddfSDavid du Colombier p.x += Facesep; 3047dd7cddfSDavid du Colombier if(p.x & 1) 3057dd7cddfSDavid du Colombier p.x++; /* align background texture */ 3067dd7cddfSDavid du Colombier leftr = rectaddpt(leftright, p); 3077dd7cddfSDavid du Colombier p.x += Dx(leftright) + Facesep; 3087dd7cddfSDavid du Colombier rightr = rectaddpt(leftright, p); 3097dd7cddfSDavid du Colombier draw(screen, leftr, first>0? blue : bgrnd, left, leftright.min); 3107dd7cddfSDavid du Colombier draw(screen, rightr, last<nfaces? blue : bgrnd, right, leftright.min); 3117dd7cddfSDavid du Colombier } 3127dd7cddfSDavid du Colombier 3137dd7cddfSDavid du Colombier void 3147dd7cddfSDavid du Colombier addface(Face *f) /* always adds at 0 */ 3157dd7cddfSDavid du Colombier { 3167dd7cddfSDavid du Colombier Face **ofaces; 3177dd7cddfSDavid du Colombier Rectangle r0, r1, r; 3187dd7cddfSDavid du Colombier int y, nx, ny; 3197dd7cddfSDavid du Colombier 3207dd7cddfSDavid du Colombier if(f == nil) 3217dd7cddfSDavid du Colombier return; 3227dd7cddfSDavid du Colombier lockdisplay(display); 3237dd7cddfSDavid du Colombier if(first != 0){ 3247dd7cddfSDavid du Colombier first = 0; 3257dd7cddfSDavid du Colombier resized(); 3267dd7cddfSDavid du Colombier } 3277dd7cddfSDavid du Colombier findbit(f); 3287dd7cddfSDavid du Colombier 3297dd7cddfSDavid du Colombier nx = nacross; 3307dd7cddfSDavid du Colombier ny = (nfaces+(nx-1)) / nx; 3317dd7cddfSDavid du Colombier 3327dd7cddfSDavid du Colombier for(y=ny; y>=0; y--){ 3337dd7cddfSDavid du Colombier /* move them along */ 3347dd7cddfSDavid du Colombier r0 = facerect(y*nx+0); 3357dd7cddfSDavid du Colombier r1 = facerect(y*nx+1); 3367dd7cddfSDavid du Colombier r = r1; 3377dd7cddfSDavid du Colombier r.max.x = r.min.x + (nx - 1)*(Facesize+Facesep); 3387dd7cddfSDavid du Colombier draw(screen, r, screen, nil, r0.min); 3397dd7cddfSDavid du Colombier /* copy one down from row above */ 3407dd7cddfSDavid du Colombier if(y != 0){ 3417dd7cddfSDavid du Colombier r = facerect((y-1)*nx+nx-1); 3427dd7cddfSDavid du Colombier draw(screen, r0, screen, nil, r.min); 3437dd7cddfSDavid du Colombier } 3447dd7cddfSDavid du Colombier } 3457dd7cddfSDavid du Colombier 3467dd7cddfSDavid du Colombier ofaces = faces; 3477dd7cddfSDavid du Colombier faces = emalloc((nfaces+1)*sizeof(Face*)); 3487dd7cddfSDavid du Colombier memmove(faces+1, ofaces, nfaces*(sizeof(Face*))); 3497dd7cddfSDavid du Colombier free(ofaces); 3507dd7cddfSDavid du Colombier nfaces++; 3517dd7cddfSDavid du Colombier setlast(); 3527dd7cddfSDavid du Colombier drawarrows(); 3537dd7cddfSDavid du Colombier faces[0] = f; 3547dd7cddfSDavid du Colombier drawface(f, 0); 3557dd7cddfSDavid du Colombier flushimage(display, 1); 3567dd7cddfSDavid du Colombier unlockdisplay(display); 3577dd7cddfSDavid du Colombier } 3587dd7cddfSDavid du Colombier 3597dd7cddfSDavid du Colombier void 3607dd7cddfSDavid du Colombier loadmboxfaces(char *maildir) 3617dd7cddfSDavid du Colombier { 3627dd7cddfSDavid du Colombier int dirfd; 3639a747e4fSDavid du Colombier Dir *d; 3649a747e4fSDavid du Colombier int i, n; 3657dd7cddfSDavid du Colombier 3667dd7cddfSDavid du Colombier dirfd = open(maildir, OREAD); 3677dd7cddfSDavid du Colombier if(dirfd >= 0){ 3687dd7cddfSDavid du Colombier chdir(maildir); 3699a747e4fSDavid du Colombier while((n = dirread(dirfd, &d)) > 0){ 3709a747e4fSDavid du Colombier for(i=0; i<n; i++) 3719a747e4fSDavid du Colombier addface(dirface(maildir, d[i].name)); 3729a747e4fSDavid du Colombier free(d); 3739a747e4fSDavid du Colombier } 3747dd7cddfSDavid du Colombier close(dirfd); 3757dd7cddfSDavid du Colombier } 3767dd7cddfSDavid du Colombier } 3777dd7cddfSDavid du Colombier 3787dd7cddfSDavid du Colombier void 3797dd7cddfSDavid du Colombier freeface(Face *f) 3807dd7cddfSDavid du Colombier { 3817dd7cddfSDavid du Colombier int i; 3827dd7cddfSDavid du Colombier 3837dd7cddfSDavid du Colombier if(f->file!=nil && f->bit!=f->file->image) 3847dd7cddfSDavid du Colombier freeimage(f->bit); 3857dd7cddfSDavid du Colombier freefacefile(f->file); 3867dd7cddfSDavid du Colombier for(i=0; i<Nstring; i++) 3877dd7cddfSDavid du Colombier free(f->str[i]); 3887dd7cddfSDavid du Colombier free(f); 3897dd7cddfSDavid du Colombier } 3907dd7cddfSDavid du Colombier 3917dd7cddfSDavid du Colombier void 3927dd7cddfSDavid du Colombier delface(int j) 3937dd7cddfSDavid du Colombier { 3947dd7cddfSDavid du Colombier Rectangle r0, r1, r; 3957dd7cddfSDavid du Colombier int nx, ny, x, y; 3967dd7cddfSDavid du Colombier 3977dd7cddfSDavid du Colombier if(j < first) 3987dd7cddfSDavid du Colombier first--; 3997dd7cddfSDavid du Colombier else if(j < last){ 4007dd7cddfSDavid du Colombier nx = nacross; 4017dd7cddfSDavid du Colombier ny = (nfaces+(nx-1)) / nx; 4027dd7cddfSDavid du Colombier x = (j-first)%nx; 4037dd7cddfSDavid du Colombier for(y=(j-first)/nx; y<ny; y++){ 4047dd7cddfSDavid du Colombier if(x != nx-1){ 4057dd7cddfSDavid du Colombier /* move them along */ 4067dd7cddfSDavid du Colombier r0 = facerect(y*nx+x); 4077dd7cddfSDavid du Colombier r1 = facerect(y*nx+x+1); 4087dd7cddfSDavid du Colombier r = r0; 4097dd7cddfSDavid du Colombier r.max.x = r.min.x + (nx - x - 1)*(Facesize+Facesep); 4107dd7cddfSDavid du Colombier draw(screen, r, screen, nil, r1.min); 4117dd7cddfSDavid du Colombier } 4127dd7cddfSDavid du Colombier if(y != ny-1){ 4137dd7cddfSDavid du Colombier /* copy one up from row below */ 4147dd7cddfSDavid du Colombier r = facerect((y+1)*nx); 4157dd7cddfSDavid du Colombier draw(screen, facerect(y*nx+nx-1), screen, nil, r.min); 4167dd7cddfSDavid du Colombier } 4177dd7cddfSDavid du Colombier x = 0; 4187dd7cddfSDavid du Colombier } 4197dd7cddfSDavid du Colombier if(last < nfaces) /* first off-screen becomes visible */ 4207dd7cddfSDavid du Colombier drawface(faces[last], last-1); 4217dd7cddfSDavid du Colombier else{ 4227dd7cddfSDavid du Colombier /* clear final spot */ 4237dd7cddfSDavid du Colombier r = facerect(last-first-1); 4247dd7cddfSDavid du Colombier draw(screen, r, bgrnd, nil, r.min); 4257dd7cddfSDavid du Colombier } 4267dd7cddfSDavid du Colombier } 4277dd7cddfSDavid du Colombier freeface(faces[j]); 4287dd7cddfSDavid du Colombier memmove(faces+j, faces+j+1, (nfaces-(j+1))*sizeof(Face*)); 4297dd7cddfSDavid du Colombier nfaces--; 4307dd7cddfSDavid du Colombier setlast(); 4317dd7cddfSDavid du Colombier drawarrows(); 4327dd7cddfSDavid du Colombier } 4337dd7cddfSDavid du Colombier 4347dd7cddfSDavid du Colombier void 4357dd7cddfSDavid du Colombier dodelete(int i) 4367dd7cddfSDavid du Colombier { 4377dd7cddfSDavid du Colombier Face *f; 4387dd7cddfSDavid du Colombier 4397dd7cddfSDavid du Colombier f = faces[i]; 4407dd7cddfSDavid du Colombier if(history){ 4417dd7cddfSDavid du Colombier free(f->str[Sshow]); 4427dd7cddfSDavid du Colombier f->str[Sshow] = estrdup(""); 4437dd7cddfSDavid du Colombier }else{ 4447dd7cddfSDavid du Colombier delface(i); 4457dd7cddfSDavid du Colombier flushimage(display, 1); 4467dd7cddfSDavid du Colombier } 4477dd7cddfSDavid du Colombier } 4487dd7cddfSDavid du Colombier 4497dd7cddfSDavid du Colombier void 4507dd7cddfSDavid du Colombier delete(char *s, char *digest) 4517dd7cddfSDavid du Colombier { 4527dd7cddfSDavid du Colombier int i; 4537dd7cddfSDavid du Colombier Face *f; 4547dd7cddfSDavid du Colombier 4557dd7cddfSDavid du Colombier lockdisplay(display); 4567dd7cddfSDavid du Colombier for(i=0; i<nfaces; i++){ 4577dd7cddfSDavid du Colombier f = faces[i]; 4587dd7cddfSDavid du Colombier if(digest != nil){ 4597dd7cddfSDavid du Colombier if(f->str[Sdigest]!=nil && strcmp(digest, f->str[Sdigest]) == 0){ 4607dd7cddfSDavid du Colombier dodelete(i); 4617dd7cddfSDavid du Colombier break; 4627dd7cddfSDavid du Colombier } 4637dd7cddfSDavid du Colombier }else{ 4647dd7cddfSDavid du Colombier if(f->str[Sshow] && strcmp(s, f->str[Sshow]) == 0){ 4657dd7cddfSDavid du Colombier dodelete(i); 4667dd7cddfSDavid du Colombier break; 4677dd7cddfSDavid du Colombier } 4687dd7cddfSDavid du Colombier } 4697dd7cddfSDavid du Colombier } 4707dd7cddfSDavid du Colombier unlockdisplay(display); 4717dd7cddfSDavid du Colombier } 4727dd7cddfSDavid du Colombier 4737dd7cddfSDavid du Colombier void 4747dd7cddfSDavid du Colombier faceproc(void) 4757dd7cddfSDavid du Colombier { 4767dd7cddfSDavid du Colombier for(;;) 4777dd7cddfSDavid du Colombier addface(nextface()); 4787dd7cddfSDavid du Colombier } 4797dd7cddfSDavid du Colombier 4807dd7cddfSDavid du Colombier void 4817dd7cddfSDavid du Colombier resized(void) 4827dd7cddfSDavid du Colombier { 4837dd7cddfSDavid du Colombier int i; 4847dd7cddfSDavid du Colombier 4857dd7cddfSDavid du Colombier nacross = (Dx(screen->r)-2*facep.x+Facesep)/(Facesize+Facesep); 4867dd7cddfSDavid du Colombier for(ndown=1; rectinrect(facerect(ndown*nacross), screen->r); ndown++) 4877dd7cddfSDavid du Colombier ; 4887dd7cddfSDavid du Colombier setlast(); 4897dd7cddfSDavid du Colombier draw(screen, screen->r, bgrnd, nil, ZP); 4907dd7cddfSDavid du Colombier enddate = ZP; 4917dd7cddfSDavid du Colombier drawtime(); 4927dd7cddfSDavid du Colombier for(i=0; i<nfaces; i++) 4937dd7cddfSDavid du Colombier drawface(faces[i], i); 4947dd7cddfSDavid du Colombier drawarrows(); 4957dd7cddfSDavid du Colombier flushimage(display, 1); 4967dd7cddfSDavid du Colombier } 4977dd7cddfSDavid du Colombier 4987dd7cddfSDavid du Colombier void 4997dd7cddfSDavid du Colombier eresized(int new) 5007dd7cddfSDavid du Colombier { 5017dd7cddfSDavid du Colombier lockdisplay(display); 5027dd7cddfSDavid du Colombier if(new && getwindow(display, Refnone) < 0) { 5037dd7cddfSDavid du Colombier fprint(2, "can't reattach to window\n"); 5047dd7cddfSDavid du Colombier killall("reattach"); 5057dd7cddfSDavid du Colombier } 5067dd7cddfSDavid du Colombier resized(); 5077dd7cddfSDavid du Colombier unlockdisplay(display); 5087dd7cddfSDavid du Colombier } 5097dd7cddfSDavid du Colombier 5107dd7cddfSDavid du Colombier int 5117dd7cddfSDavid du Colombier getmouse(Mouse *m) 5127dd7cddfSDavid du Colombier { 5137dd7cddfSDavid du Colombier int n; 5147dd7cddfSDavid du Colombier static int eof; 5157dd7cddfSDavid du Colombier char buf[128]; 5167dd7cddfSDavid du Colombier 5177dd7cddfSDavid du Colombier if(eof) 5187dd7cddfSDavid du Colombier return 0; 5197dd7cddfSDavid du Colombier for(;;){ 5207dd7cddfSDavid du Colombier n = read(mousefd, buf, sizeof(buf)); 5217dd7cddfSDavid du Colombier if(n <= 0){ 5227dd7cddfSDavid du Colombier /* so callers needn't check return value every time */ 5237dd7cddfSDavid du Colombier eof = 1; 5247dd7cddfSDavid du Colombier m->buttons = 0; 5257dd7cddfSDavid du Colombier return 0; 5267dd7cddfSDavid du Colombier } 5277dd7cddfSDavid du Colombier n = eatomouse(m, buf, n); 5287dd7cddfSDavid du Colombier if(n > 0) 5297dd7cddfSDavid du Colombier return 1; 5307dd7cddfSDavid du Colombier } 5317dd7cddfSDavid du Colombier } 5327dd7cddfSDavid du Colombier 5337dd7cddfSDavid du Colombier enum 5347dd7cddfSDavid du Colombier { 5357dd7cddfSDavid du Colombier Clicksize = 3, /* pixels */ 5367dd7cddfSDavid du Colombier }; 5377dd7cddfSDavid du Colombier 5387dd7cddfSDavid du Colombier int 5397dd7cddfSDavid du Colombier scroll(int but, Point p) 5407dd7cddfSDavid du Colombier { 5417dd7cddfSDavid du Colombier int delta; 5427dd7cddfSDavid du Colombier 5437dd7cddfSDavid du Colombier delta = 0; 5447dd7cddfSDavid du Colombier lockdisplay(display); 5457dd7cddfSDavid du Colombier if(ptinrect(p, leftr) && first>0){ 5467dd7cddfSDavid du Colombier if(but == 2) 5477dd7cddfSDavid du Colombier delta = -first; 5487dd7cddfSDavid du Colombier else{ 5497dd7cddfSDavid du Colombier delta = nacross; 5507dd7cddfSDavid du Colombier if(delta > first) 5517dd7cddfSDavid du Colombier delta = first; 5527dd7cddfSDavid du Colombier delta = -delta; 5537dd7cddfSDavid du Colombier } 5547dd7cddfSDavid du Colombier }else if(ptinrect(p, rightr) && last<nfaces){ 5557dd7cddfSDavid du Colombier if(but == 2) 5567dd7cddfSDavid du Colombier delta = (nfaces-nacross*ndown) - first; 5577dd7cddfSDavid du Colombier else{ 5587dd7cddfSDavid du Colombier delta = nacross; 5597dd7cddfSDavid du Colombier if(delta > nfaces-last) 5607dd7cddfSDavid du Colombier delta = nfaces-last; 5617dd7cddfSDavid du Colombier } 5627dd7cddfSDavid du Colombier } 5637dd7cddfSDavid du Colombier first += delta; 5647dd7cddfSDavid du Colombier last += delta; 5657dd7cddfSDavid du Colombier unlockdisplay(display); 5667dd7cddfSDavid du Colombier if(delta) 5677dd7cddfSDavid du Colombier eresized(0); 5687dd7cddfSDavid du Colombier return delta; 5697dd7cddfSDavid du Colombier } 5707dd7cddfSDavid du Colombier 5717dd7cddfSDavid du Colombier void 5727dd7cddfSDavid du Colombier click(int button, Mouse *m) 5737dd7cddfSDavid du Colombier { 5747dd7cddfSDavid du Colombier Point p; 5757dd7cddfSDavid du Colombier int i; 5767dd7cddfSDavid du Colombier 5777dd7cddfSDavid du Colombier p = m->xy; 5787dd7cddfSDavid du Colombier while(m->buttons == (1<<(button-1))) 5797dd7cddfSDavid du Colombier getmouse(m); 5807dd7cddfSDavid du Colombier if(m->buttons) 5817dd7cddfSDavid du Colombier return; 5827dd7cddfSDavid du Colombier if(abs(p.x-m->xy.x)>Clicksize || abs(p.y-m->xy.y)>Clicksize) 5837dd7cddfSDavid du Colombier return; 5847dd7cddfSDavid du Colombier switch(button){ 5857dd7cddfSDavid du Colombier case 1: 5867dd7cddfSDavid du Colombier if(scroll(1, p)) 5877dd7cddfSDavid du Colombier break; 5887dd7cddfSDavid du Colombier if(history){ 5897dd7cddfSDavid du Colombier /* click clears display */ 5907dd7cddfSDavid du Colombier lockdisplay(display); 5917dd7cddfSDavid du Colombier for(i=0; i<nfaces; i++) 5927dd7cddfSDavid du Colombier freeface(faces[i]); 5937dd7cddfSDavid du Colombier free(faces); 5947dd7cddfSDavid du Colombier faces=nil; 5957dd7cddfSDavid du Colombier nfaces = 0; 5967dd7cddfSDavid du Colombier unlockdisplay(display); 5977dd7cddfSDavid du Colombier eresized(0); 5987dd7cddfSDavid du Colombier return; 5997dd7cddfSDavid du Colombier }else{ 6007dd7cddfSDavid du Colombier for(i=first; i<last; i++) /* clear vwhois faces */ 6017dd7cddfSDavid du Colombier if(ptinrect(p, facerect(i-first)) 602*d9d5974cSDavid du Colombier && strstr(faces[i]->str[Sshow], "/XXXvwhois")){ 6037dd7cddfSDavid du Colombier delface(i); 6047dd7cddfSDavid du Colombier flushimage(display, 1); 6057dd7cddfSDavid du Colombier } 6067dd7cddfSDavid du Colombier } 6077dd7cddfSDavid du Colombier break; 6087dd7cddfSDavid du Colombier case 2: 6097dd7cddfSDavid du Colombier scroll(2, p); 6107dd7cddfSDavid du Colombier break; 6117dd7cddfSDavid du Colombier case 3: 6127dd7cddfSDavid du Colombier scroll(3, p); 6137dd7cddfSDavid du Colombier lockdisplay(display); 6147dd7cddfSDavid du Colombier for(i=first; i<last; i++) 6157dd7cddfSDavid du Colombier if(ptinrect(p, facerect(i-first))){ 6167dd7cddfSDavid du Colombier showmail(faces[i]); 6177dd7cddfSDavid du Colombier break; 6187dd7cddfSDavid du Colombier } 6197dd7cddfSDavid du Colombier unlockdisplay(display); 6207dd7cddfSDavid du Colombier break; 6217dd7cddfSDavid du Colombier } 6227dd7cddfSDavid du Colombier } 6237dd7cddfSDavid du Colombier 6247dd7cddfSDavid du Colombier void 6257dd7cddfSDavid du Colombier mouseproc(void) 6267dd7cddfSDavid du Colombier { 6277dd7cddfSDavid du Colombier Mouse mouse; 6287dd7cddfSDavid du Colombier 6297dd7cddfSDavid du Colombier while(getmouse(&mouse)){ 6307dd7cddfSDavid du Colombier if(mouse.buttons == 1) 6317dd7cddfSDavid du Colombier click(1, &mouse); 6327dd7cddfSDavid du Colombier else if(mouse.buttons == 2) 6337dd7cddfSDavid du Colombier click(2, &mouse); 6347dd7cddfSDavid du Colombier else if(mouse.buttons == 4) 6357dd7cddfSDavid du Colombier click(3, &mouse); 6367dd7cddfSDavid du Colombier 6377dd7cddfSDavid du Colombier while(mouse.buttons) 6387dd7cddfSDavid du Colombier getmouse(&mouse); 6397dd7cddfSDavid du Colombier } 6407dd7cddfSDavid du Colombier } 6417dd7cddfSDavid du Colombier 6427dd7cddfSDavid du Colombier void 6437dd7cddfSDavid du Colombier killall(char *s) 6447dd7cddfSDavid du Colombier { 6457dd7cddfSDavid du Colombier int i, pid; 6467dd7cddfSDavid du Colombier 6477dd7cddfSDavid du Colombier pid = getpid(); 6487dd7cddfSDavid du Colombier for(i=0; i<NPROC; i++) 6497dd7cddfSDavid du Colombier if(pids[i] && pids[i]!=pid) 6507dd7cddfSDavid du Colombier postnote(PNPROC, pids[i], "kill"); 6517dd7cddfSDavid du Colombier exits(s); 6527dd7cddfSDavid du Colombier } 6537dd7cddfSDavid du Colombier 6547dd7cddfSDavid du Colombier void 6557dd7cddfSDavid du Colombier startproc(void (*f)(void), int index) 6567dd7cddfSDavid du Colombier { 6577dd7cddfSDavid du Colombier int pid; 6587dd7cddfSDavid du Colombier 6597dd7cddfSDavid du Colombier switch(pid = rfork(RFPROC|RFMEM|RFNOWAIT)){ 6607dd7cddfSDavid du Colombier case -1: 6617dd7cddfSDavid du Colombier fprint(2, "faces: fork failed: %r\n"); 6627dd7cddfSDavid du Colombier killall("fork failed"); 6637dd7cddfSDavid du Colombier case 0: 6647dd7cddfSDavid du Colombier f(); 6657dd7cddfSDavid du Colombier fprint(2, "faces: %s process exits\n", procnames[index]); 6667dd7cddfSDavid du Colombier if(index >= 0) 6677dd7cddfSDavid du Colombier killall("process died"); 6687dd7cddfSDavid du Colombier exits(nil); 6697dd7cddfSDavid du Colombier } 6707dd7cddfSDavid du Colombier if(index >= 0) 6717dd7cddfSDavid du Colombier pids[index] = pid; 6727dd7cddfSDavid du Colombier } 6737dd7cddfSDavid du Colombier 6747dd7cddfSDavid du Colombier void 6755fab9909SDavid du Colombier usage(void) 6765fab9909SDavid du Colombier { 677*d9d5974cSDavid du Colombier fprint(2, "usage: faces [-hi] [-m maildir]\n"); 6785fab9909SDavid du Colombier exits("usage"); 6795fab9909SDavid du Colombier } 6805fab9909SDavid du Colombier 6815fab9909SDavid du Colombier void 6827dd7cddfSDavid du Colombier main(int argc, char *argv[]) 6837dd7cddfSDavid du Colombier { 684a3b78ba5SDavid du Colombier int i; 685a3b78ba5SDavid du Colombier 6867dd7cddfSDavid du Colombier ARGBEGIN{ 6877dd7cddfSDavid du Colombier case 'h': 6887dd7cddfSDavid du Colombier history++; 6897dd7cddfSDavid du Colombier break; 6907dd7cddfSDavid du Colombier case 'i': 6917dd7cddfSDavid du Colombier initload++; 6927dd7cddfSDavid du Colombier break; 6935fab9909SDavid du Colombier case 'm': 6945fab9909SDavid du Colombier addmaildir(EARGF(usage())); 695a3b78ba5SDavid du Colombier maildir = nil; 6965fab9909SDavid du Colombier break; 6977dd7cddfSDavid du Colombier default: 6985fab9909SDavid du Colombier usage(); 6997dd7cddfSDavid du Colombier }ARGEND 7007dd7cddfSDavid du Colombier 7017dd7cddfSDavid du Colombier if(initdraw(nil, nil, "faces") < 0){ 7027dd7cddfSDavid du Colombier fprint(2, "faces: initdraw failed: %r\n"); 7037dd7cddfSDavid du Colombier exits("initdraw"); 7047dd7cddfSDavid du Colombier } 705a3b78ba5SDavid du Colombier if(maildir) 706a3b78ba5SDavid du Colombier addmaildir(maildir); 7077dd7cddfSDavid du Colombier init(); 7087dd7cddfSDavid du Colombier unlockdisplay(display); /* initdraw leaves it locked */ 7097dd7cddfSDavid du Colombier display->locking = 1; /* tell library we're using the display lock */ 7107dd7cddfSDavid du Colombier setdate(); 7117dd7cddfSDavid du Colombier eresized(0); 7127dd7cddfSDavid du Colombier 7137dd7cddfSDavid du Colombier pids[Mainp] = getpid(); 7147dd7cddfSDavid du Colombier startproc(timeproc, Timep); 7157dd7cddfSDavid du Colombier startproc(mouseproc, Mousep); 7167dd7cddfSDavid du Colombier if(initload) 717a3b78ba5SDavid du Colombier for(i = 0; i < nmaildirs; i++) 718a3b78ba5SDavid du Colombier loadmboxfaces(maildirs[i]); 7197dd7cddfSDavid du Colombier faceproc(); 7207dd7cddfSDavid du Colombier fprint(2, "faces: %s process exits\n", procnames[Mainp]); 7217dd7cddfSDavid du Colombier killall(nil); 7227dd7cddfSDavid du Colombier } 723