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 <auth.h> 107dd7cddfSDavid du Colombier #include <fcall.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 /* 167dd7cddfSDavid du Colombier * WASHINGTON (AP) - The Food and Drug Administration warned 177dd7cddfSDavid du Colombier * consumers Wednesday not to use ``Rio'' hair relaxer products 187dd7cddfSDavid du Colombier * because they may cause severe hair loss or turn hair green.... 197dd7cddfSDavid du Colombier * The FDA urged consumers who have experienced problems with Rio 207dd7cddfSDavid du Colombier * to notify their local FDA office, local health department or the 217dd7cddfSDavid du Colombier * company at 1‑800‑543‑3002. 227dd7cddfSDavid du Colombier */ 237dd7cddfSDavid du Colombier 247dd7cddfSDavid du Colombier void resize(void); 257dd7cddfSDavid du Colombier void move(void); 267dd7cddfSDavid du Colombier void delete(void); 277dd7cddfSDavid du Colombier void hide(void); 287dd7cddfSDavid du Colombier void unhide(int); 297dd7cddfSDavid du Colombier void newtile(int); 307dd7cddfSDavid du Colombier Image *sweep(void); 317dd7cddfSDavid du Colombier Image *bandsize(Window*); 327dd7cddfSDavid du Colombier Image* drag(Window*, Rectangle*); 337dd7cddfSDavid du Colombier void refresh(Rectangle); 347dd7cddfSDavid du Colombier void resized(void); 357dd7cddfSDavid du Colombier Channel *exitchan; /* chan(int) */ 367dd7cddfSDavid du Colombier Channel *winclosechan; /* chan(Window*); */ 377dd7cddfSDavid du Colombier Rectangle viewr; 387dd7cddfSDavid du Colombier int threadrforkflag = 0; /* should be RFENVG but that hides rio from plumber */ 397dd7cddfSDavid du Colombier 407dd7cddfSDavid du Colombier void mousethread(void*); 417dd7cddfSDavid du Colombier void keyboardthread(void*); 427dd7cddfSDavid du Colombier void winclosethread(void*); 437dd7cddfSDavid du Colombier void deletethread(void*); 447dd7cddfSDavid du Colombier void initcmd(void*); 457dd7cddfSDavid du Colombier 467dd7cddfSDavid du Colombier char *fontname; 477dd7cddfSDavid du Colombier int mainpid; 487dd7cddfSDavid du Colombier 497dd7cddfSDavid du Colombier enum 507dd7cddfSDavid du Colombier { 517dd7cddfSDavid du Colombier New, 527dd7cddfSDavid du Colombier Reshape, 537dd7cddfSDavid du Colombier Move, 547dd7cddfSDavid du Colombier Delete, 557dd7cddfSDavid du Colombier Hide, 567dd7cddfSDavid du Colombier Exit, 577dd7cddfSDavid du Colombier }; 587dd7cddfSDavid du Colombier 597dd7cddfSDavid du Colombier enum 607dd7cddfSDavid du Colombier { 617dd7cddfSDavid du Colombier Cut, 627dd7cddfSDavid du Colombier Paste, 637dd7cddfSDavid du Colombier Snarf, 647dd7cddfSDavid du Colombier Plumb, 657dd7cddfSDavid du Colombier Send, 667dd7cddfSDavid du Colombier Scroll, 677dd7cddfSDavid du Colombier }; 687dd7cddfSDavid du Colombier 697dd7cddfSDavid du Colombier char *menu2str[] = { 707dd7cddfSDavid du Colombier [Cut] "cut", 717dd7cddfSDavid du Colombier [Paste] "paste", 727dd7cddfSDavid du Colombier [Snarf] "snarf", 737dd7cddfSDavid du Colombier [Plumb] "plumb", 747dd7cddfSDavid du Colombier [Send] "send", 757dd7cddfSDavid du Colombier [Scroll] "scroll", 767dd7cddfSDavid du Colombier nil 777dd7cddfSDavid du Colombier }; 787dd7cddfSDavid du Colombier 797dd7cddfSDavid du Colombier Menu menu2 = 807dd7cddfSDavid du Colombier { 817dd7cddfSDavid du Colombier menu2str 827dd7cddfSDavid du Colombier }; 837dd7cddfSDavid du Colombier 847dd7cddfSDavid du Colombier int Hidden = Exit+1; 857dd7cddfSDavid du Colombier 867dd7cddfSDavid du Colombier char *menu3str[100] = { 877dd7cddfSDavid du Colombier [New] "New", 887dd7cddfSDavid du Colombier [Reshape] "Resize", 897dd7cddfSDavid du Colombier [Move] "Move", 907dd7cddfSDavid du Colombier [Delete] "Delete", 917dd7cddfSDavid du Colombier [Hide] "Hide", 927dd7cddfSDavid du Colombier [Exit] "Exit", 937dd7cddfSDavid du Colombier nil 947dd7cddfSDavid du Colombier }; 957dd7cddfSDavid du Colombier 967dd7cddfSDavid du Colombier Menu menu3 = 977dd7cddfSDavid du Colombier { 987dd7cddfSDavid du Colombier menu3str 997dd7cddfSDavid du Colombier }; 1007dd7cddfSDavid du Colombier 1017dd7cddfSDavid du Colombier char *rcargv[] = { "rc", "-i", nil }; 1027dd7cddfSDavid du Colombier 1037dd7cddfSDavid du Colombier int errorshouldabort = 0; 1047dd7cddfSDavid du Colombier 1057dd7cddfSDavid du Colombier void 1067dd7cddfSDavid du Colombier derror(Display*, char *errorstr) 1077dd7cddfSDavid du Colombier { 1087dd7cddfSDavid du Colombier error(errorstr); 1097dd7cddfSDavid du Colombier } 1107dd7cddfSDavid du Colombier 1117dd7cddfSDavid du Colombier void 1127dd7cddfSDavid du Colombier threadmain(int argc, char *argv[]) 1137dd7cddfSDavid du Colombier { 1147dd7cddfSDavid du Colombier char *initstr, *s; 1157dd7cddfSDavid du Colombier static void *arg[1]; 1167dd7cddfSDavid du Colombier char buf[256]; 1177dd7cddfSDavid du Colombier 1187dd7cddfSDavid du Colombier if(strstr(argv[0], ".out") == nil){ 1197dd7cddfSDavid du Colombier menu3str[Exit] = nil; 1207dd7cddfSDavid du Colombier Hidden--; 1217dd7cddfSDavid du Colombier } 1227dd7cddfSDavid du Colombier initstr = nil; 1237dd7cddfSDavid du Colombier maxtab = 0; 1247dd7cddfSDavid du Colombier ARGBEGIN{ 1257dd7cddfSDavid du Colombier case 'f': 1267dd7cddfSDavid du Colombier fontname = ARGF(); 1277dd7cddfSDavid du Colombier break; 1287dd7cddfSDavid du Colombier case 'i': 1297dd7cddfSDavid du Colombier initstr = ARGF(); 1307dd7cddfSDavid du Colombier break; 1317dd7cddfSDavid du Colombier case 's': 1327dd7cddfSDavid du Colombier scrolling = TRUE; 1337dd7cddfSDavid du Colombier break; 1347dd7cddfSDavid du Colombier }ARGEND 1357dd7cddfSDavid du Colombier 1367dd7cddfSDavid du Colombier mainpid = getpid(); 1377dd7cddfSDavid du Colombier if(getwd(buf, sizeof buf) == nil) 1387dd7cddfSDavid du Colombier startdir = estrdup("."); 1397dd7cddfSDavid du Colombier else 1407dd7cddfSDavid du Colombier startdir = estrdup(buf); 1417dd7cddfSDavid du Colombier if(fontname == nil) 1427dd7cddfSDavid du Colombier fontname = getenv("font"); 1437dd7cddfSDavid du Colombier if(fontname == nil) 1447dd7cddfSDavid du Colombier fontname = "/lib/font/bit/lucm/unicode.9.font"; 1457dd7cddfSDavid du Colombier s = getenv("tabstop"); 1467dd7cddfSDavid du Colombier if(s != nil) 1477dd7cddfSDavid du Colombier maxtab = strtol(s, nil, 0); 1487dd7cddfSDavid du Colombier if(maxtab == 0) 1497dd7cddfSDavid du Colombier maxtab = 4; 1507dd7cddfSDavid du Colombier /* check font before barging ahead */ 1517dd7cddfSDavid du Colombier if(access(fontname, 0) < 0){ 1527dd7cddfSDavid du Colombier threadprint(2, "rio: can't access %s: %r\n", fontname); 1537dd7cddfSDavid du Colombier exits("font open"); 1547dd7cddfSDavid du Colombier } 1557dd7cddfSDavid du Colombier putenv("font", fontname); 1567dd7cddfSDavid du Colombier 1577dd7cddfSDavid du Colombier snarffd = open("/dev/snarf", OREAD|OCEXEC); 1587dd7cddfSDavid du Colombier 159*14414594SDavid du Colombier if(geninitdraw(nil, derror, nil, "rio", nil, Refnone) < 0){ 160*14414594SDavid du Colombier threadprint(2, "rio: can't open display: %r\n"); 161*14414594SDavid du Colombier exits("display open"); 162*14414594SDavid du Colombier } 1637dd7cddfSDavid du Colombier iconinit(); 1647dd7cddfSDavid du Colombier view = screen; 1657dd7cddfSDavid du Colombier viewr = view->r; 1667dd7cddfSDavid du Colombier mousectl = initmouse(nil, screen); 1677dd7cddfSDavid du Colombier if(mousectl == nil) 1687dd7cddfSDavid du Colombier error("can't find mouse"); 1697dd7cddfSDavid du Colombier mouse = mousectl; 1707dd7cddfSDavid du Colombier keyboardctl = initkeyboard(nil); 1717dd7cddfSDavid du Colombier if(keyboardctl == nil) 1727dd7cddfSDavid du Colombier error("can't find keyboard"); 1737dd7cddfSDavid du Colombier wscreen = allocscreen(screen, background, 0); 1747dd7cddfSDavid du Colombier if(wscreen == nil) 1757dd7cddfSDavid du Colombier error("can't allocate screen"); 1767dd7cddfSDavid du Colombier draw(view, viewr, background, nil, ZP); 1777dd7cddfSDavid du Colombier flushimage(display, 1); 1787dd7cddfSDavid du Colombier 1797dd7cddfSDavid du Colombier exitchan = chancreate(sizeof(int), 0); 1807dd7cddfSDavid du Colombier winclosechan = chancreate(sizeof(Window*), 0); 1817dd7cddfSDavid du Colombier deletechan = chancreate(sizeof(char*), 0); 1827dd7cddfSDavid du Colombier 1837dd7cddfSDavid du Colombier timerinit(); 1847dd7cddfSDavid du Colombier threadcreate(keyboardthread, nil, STACK); 1857dd7cddfSDavid du Colombier threadcreate(mousethread, nil, STACK); 1867dd7cddfSDavid du Colombier threadcreate(winclosethread, nil, STACK); 1877dd7cddfSDavid du Colombier threadcreate(deletethread, nil, STACK); 1887dd7cddfSDavid du Colombier filsys = filsysinit(xfidinit()); 1897dd7cddfSDavid du Colombier 1907dd7cddfSDavid du Colombier if(filsys == nil) 1917dd7cddfSDavid du Colombier fprint(2, "rio: can't create file system server: %r\n"); 1927dd7cddfSDavid du Colombier else{ 1937dd7cddfSDavid du Colombier errorshouldabort = 1; /* suicide if there's trouble after this */ 1947dd7cddfSDavid du Colombier if(initstr) 1957dd7cddfSDavid du Colombier proccreate(initcmd, initstr, STACK); 1967dd7cddfSDavid du Colombier notify(shutdown);/**/ 1977dd7cddfSDavid du Colombier recv(exitchan, nil); 1987dd7cddfSDavid du Colombier } 1997dd7cddfSDavid du Colombier killprocs(); 2007dd7cddfSDavid du Colombier threadexitsall(nil); 2017dd7cddfSDavid du Colombier } 2027dd7cddfSDavid du Colombier 2037dd7cddfSDavid du Colombier /* 2047dd7cddfSDavid du Colombier * /dev/snarf updates when the file is closed, so we must open our own 2057dd7cddfSDavid du Colombier * fd here rather than use snarffd 2067dd7cddfSDavid du Colombier */ 2077dd7cddfSDavid du Colombier void 2087dd7cddfSDavid du Colombier putsnarf(void) 2097dd7cddfSDavid du Colombier { 2107dd7cddfSDavid du Colombier int fd, i, n; 2117dd7cddfSDavid du Colombier 2127dd7cddfSDavid du Colombier if(snarffd<0 || nsnarf==0) 2137dd7cddfSDavid du Colombier return; 2147dd7cddfSDavid du Colombier fd = open("/dev/snarf", OWRITE); 2157dd7cddfSDavid du Colombier if(fd < 0) 2167dd7cddfSDavid du Colombier return; 2177dd7cddfSDavid du Colombier /* snarf buffer could be huge, so fprint will truncate; do it in blocks */ 2187dd7cddfSDavid du Colombier for(i=0; i<nsnarf; i+=n){ 2197dd7cddfSDavid du Colombier n = nsnarf-i; 2207dd7cddfSDavid du Colombier if(n >= 256) 2217dd7cddfSDavid du Colombier n = 256; 2227dd7cddfSDavid du Colombier if(threadprint(fd, "%.*S", n, snarf+i) < 0) 2237dd7cddfSDavid du Colombier break; 2247dd7cddfSDavid du Colombier } 2257dd7cddfSDavid du Colombier close(fd); 2267dd7cddfSDavid du Colombier } 2277dd7cddfSDavid du Colombier 2287dd7cddfSDavid du Colombier void 2297dd7cddfSDavid du Colombier getsnarf(void) 2307dd7cddfSDavid du Colombier { 2317dd7cddfSDavid du Colombier int i, n, nb, nulls; 2327dd7cddfSDavid du Colombier char *sn, buf[1024]; 2337dd7cddfSDavid du Colombier 2347dd7cddfSDavid du Colombier if(snarffd < 0) 2357dd7cddfSDavid du Colombier return; 2367dd7cddfSDavid du Colombier sn = nil; 2377dd7cddfSDavid du Colombier i = 0; 2387dd7cddfSDavid du Colombier seek(snarffd, 0, 0); 2397dd7cddfSDavid du Colombier while((n = read(snarffd, buf, sizeof buf)) > 0){ 2407dd7cddfSDavid du Colombier sn = erealloc(sn, i+n+1); 2417dd7cddfSDavid du Colombier memmove(sn+i, buf, n); 2427dd7cddfSDavid du Colombier i += n; 2437dd7cddfSDavid du Colombier sn[i] = 0; 2447dd7cddfSDavid du Colombier } 2457dd7cddfSDavid du Colombier if(i > 0){ 2467dd7cddfSDavid du Colombier snarf = runerealloc(snarf, i+1); 2477dd7cddfSDavid du Colombier cvttorunes(sn, i, snarf, &nb, &nsnarf, &nulls); 2487dd7cddfSDavid du Colombier free(sn); 2497dd7cddfSDavid du Colombier } 2507dd7cddfSDavid du Colombier } 2517dd7cddfSDavid du Colombier 2527dd7cddfSDavid du Colombier void 2537dd7cddfSDavid du Colombier initcmd(void *arg) 2547dd7cddfSDavid du Colombier { 2557dd7cddfSDavid du Colombier char *cmd; 2567dd7cddfSDavid du Colombier 2577dd7cddfSDavid du Colombier cmd = arg; 2587dd7cddfSDavid du Colombier rfork(RFENVG|RFFDG|RFNOTEG|RFNAMEG); 2597dd7cddfSDavid du Colombier procexecl(nil, "/bin/rc", "rc", "-c", cmd, 0); 2607dd7cddfSDavid du Colombier threadprint(2, "rio: exec failed: %r\n"); 2617dd7cddfSDavid du Colombier exits("exec"); 2627dd7cddfSDavid du Colombier } 2637dd7cddfSDavid du Colombier 2647dd7cddfSDavid du Colombier char *oknotes[] = 2657dd7cddfSDavid du Colombier { 2667dd7cddfSDavid du Colombier "delete", 2677dd7cddfSDavid du Colombier "hangup", 2687dd7cddfSDavid du Colombier "kill", 2697dd7cddfSDavid du Colombier "exit", 2707dd7cddfSDavid du Colombier "kilall", /* used internally by thread library during shutdown */ 2717dd7cddfSDavid du Colombier nil 2727dd7cddfSDavid du Colombier }; 2737dd7cddfSDavid du Colombier 2747dd7cddfSDavid du Colombier void 2757dd7cddfSDavid du Colombier shutdown1(void *, char *msg) 2767dd7cddfSDavid du Colombier { 2777dd7cddfSDavid du Colombier int i; 2787dd7cddfSDavid du Colombier 2797dd7cddfSDavid du Colombier killprocs(); 2807dd7cddfSDavid du Colombier for(i=0; oknotes[i]; i++) 2817dd7cddfSDavid du Colombier if(strncmp(oknotes[i], msg, strlen(oknotes[i])) == 0) 2827dd7cddfSDavid du Colombier threadexitsall(msg); 2837dd7cddfSDavid du Colombier threadprint(2, "rio %d: abort: %s\n", getpid(), msg); 2847dd7cddfSDavid du Colombier abort(); 2857dd7cddfSDavid du Colombier exits(msg); 2867dd7cddfSDavid du Colombier } 2877dd7cddfSDavid du Colombier 2887dd7cddfSDavid du Colombier void 2897dd7cddfSDavid du Colombier shutdown(void *a, char *msg) /* extra call to get stack trace on 386 */ 2907dd7cddfSDavid du Colombier { 2917dd7cddfSDavid du Colombier shutdown1(a, msg); 2927dd7cddfSDavid du Colombier } 2937dd7cddfSDavid du Colombier 2947dd7cddfSDavid du Colombier void 2957dd7cddfSDavid du Colombier killprocs(void) 2967dd7cddfSDavid du Colombier { 2977dd7cddfSDavid du Colombier int i; 2987dd7cddfSDavid du Colombier 2997dd7cddfSDavid du Colombier filsysclose(filsys); 3007dd7cddfSDavid du Colombier for(i=0; i<nwindow; i++) 3017dd7cddfSDavid du Colombier postnote(PNGROUP, window[i]->pid, "hangup"); 3027dd7cddfSDavid du Colombier remove(srvpipe); 3037dd7cddfSDavid du Colombier remove(srvwctl); 3047dd7cddfSDavid du Colombier } 3057dd7cddfSDavid du Colombier 3067dd7cddfSDavid du Colombier void 3077dd7cddfSDavid du Colombier keyboardthread(void*) 3087dd7cddfSDavid du Colombier { 3097dd7cddfSDavid du Colombier Rune buf[2][20], *rp; 3107dd7cddfSDavid du Colombier int n, i; 3117dd7cddfSDavid du Colombier 3127dd7cddfSDavid du Colombier n = 0; 3137dd7cddfSDavid du Colombier for(;;){ 3147dd7cddfSDavid du Colombier if(nelem(buf[0])!=20)threadprint(2, "NO"); 3157dd7cddfSDavid du Colombier rp = buf[n]; 3167dd7cddfSDavid du Colombier n = 1-n; 3177dd7cddfSDavid du Colombier recv(keyboardctl->c, rp); 3187dd7cddfSDavid du Colombier for(i=1; i<nelem(buf[0])-1; i++) 3197dd7cddfSDavid du Colombier if(nbrecv(keyboardctl->c, rp+i) <= 0) 3207dd7cddfSDavid du Colombier break; 3217dd7cddfSDavid du Colombier rp[i] = L'\0'; 3227dd7cddfSDavid du Colombier if(input != nil) 3237dd7cddfSDavid du Colombier sendp(input->ck, rp); 3247dd7cddfSDavid du Colombier } 3257dd7cddfSDavid du Colombier } 3267dd7cddfSDavid du Colombier 3277dd7cddfSDavid du Colombier int 3287dd7cddfSDavid du Colombier portion(int x, int lo, int hi) 3297dd7cddfSDavid du Colombier { 3307dd7cddfSDavid du Colombier x -= lo; 3317dd7cddfSDavid du Colombier hi -= lo; 3327dd7cddfSDavid du Colombier if(x < 20) 3337dd7cddfSDavid du Colombier return 0; 3347dd7cddfSDavid du Colombier if(x > hi-20) 3357dd7cddfSDavid du Colombier return 2; 3367dd7cddfSDavid du Colombier return 1; 3377dd7cddfSDavid du Colombier } 3387dd7cddfSDavid du Colombier 3397dd7cddfSDavid du Colombier int 3407dd7cddfSDavid du Colombier whichcorner(Window *w, Point p) 3417dd7cddfSDavid du Colombier { 3427dd7cddfSDavid du Colombier int i, j; 3437dd7cddfSDavid du Colombier 3447dd7cddfSDavid du Colombier i = portion(p.x, w->screenr.min.x, w->screenr.max.x); 3457dd7cddfSDavid du Colombier j = portion(p.y, w->screenr.min.y, w->screenr.max.y); 3467dd7cddfSDavid du Colombier return 3*j+i; 3477dd7cddfSDavid du Colombier } 3487dd7cddfSDavid du Colombier 3497dd7cddfSDavid du Colombier void 3507dd7cddfSDavid du Colombier cornercursor(Window *w, Point p, int force) 3517dd7cddfSDavid du Colombier { 3527dd7cddfSDavid du Colombier if(w!=nil && winborder(w, p)) 3537dd7cddfSDavid du Colombier riosetcursor(corners[whichcorner(w, p)], force); 3547dd7cddfSDavid du Colombier else 3557dd7cddfSDavid du Colombier wsetcursor(w, force); 3567dd7cddfSDavid du Colombier } 3577dd7cddfSDavid du Colombier 3587dd7cddfSDavid du Colombier /* thread to allow fsysproc to synchronize window closing with main proc */ 3597dd7cddfSDavid du Colombier void 3607dd7cddfSDavid du Colombier winclosethread(void*) 3617dd7cddfSDavid du Colombier { 3627dd7cddfSDavid du Colombier Window *w; 3637dd7cddfSDavid du Colombier 3647dd7cddfSDavid du Colombier for(;;){ 3657dd7cddfSDavid du Colombier w = recvp(winclosechan); 3667dd7cddfSDavid du Colombier wclose(w); 3677dd7cddfSDavid du Colombier } 3687dd7cddfSDavid du Colombier } 3697dd7cddfSDavid du Colombier 3707dd7cddfSDavid du Colombier /* thread to make Deleted windows that the client still holds disappear offscreen after an interval */ 3717dd7cddfSDavid du Colombier void 3727dd7cddfSDavid du Colombier deletethread(void*) 3737dd7cddfSDavid du Colombier { 3747dd7cddfSDavid du Colombier char *s; 3757dd7cddfSDavid du Colombier Image *i; 3767dd7cddfSDavid du Colombier 3777dd7cddfSDavid du Colombier for(;;){ 3787dd7cddfSDavid du Colombier s = recvp(deletechan); 3797dd7cddfSDavid du Colombier i = namedimage(display, s); 3807dd7cddfSDavid du Colombier if(i != nil){ 3817dd7cddfSDavid du Colombier /* move it off-screen to hide it, since client is slow in letting it go */ 3827dd7cddfSDavid du Colombier originwindow(i, i->r.min, view->r.max); 3837dd7cddfSDavid du Colombier } 3847dd7cddfSDavid du Colombier freeimage(i); 3857dd7cddfSDavid du Colombier free(s); 3867dd7cddfSDavid du Colombier } 3877dd7cddfSDavid du Colombier } 3887dd7cddfSDavid du Colombier 3897dd7cddfSDavid du Colombier void 3907dd7cddfSDavid du Colombier deletetimeoutproc(void *v) 3917dd7cddfSDavid du Colombier { 3927dd7cddfSDavid du Colombier char *s; 3937dd7cddfSDavid du Colombier 3947dd7cddfSDavid du Colombier s = estrdup(v); 3957dd7cddfSDavid du Colombier sleep(750); /* remove window from screen after 3/4 of a second */ 3967dd7cddfSDavid du Colombier sendp(deletechan, s); 3977dd7cddfSDavid du Colombier } 3987dd7cddfSDavid du Colombier 3997dd7cddfSDavid du Colombier void 4007dd7cddfSDavid du Colombier mousethread(void*) 4017dd7cddfSDavid du Colombier { 4027dd7cddfSDavid du Colombier int sending, inside, scrolling, moving, band; 4037dd7cddfSDavid du Colombier Window *oin, *w; 4047dd7cddfSDavid du Colombier Image *i; 4057dd7cddfSDavid du Colombier Rectangle r; 4067dd7cddfSDavid du Colombier Point xy; 4077dd7cddfSDavid du Colombier Mouse tmp; 4087dd7cddfSDavid du Colombier enum { 4097dd7cddfSDavid du Colombier MReshape, 4107dd7cddfSDavid du Colombier MMouse, 4117dd7cddfSDavid du Colombier NALT 4127dd7cddfSDavid du Colombier }; 4137dd7cddfSDavid du Colombier static Alt alts[NALT+1]; 4147dd7cddfSDavid du Colombier 4157dd7cddfSDavid du Colombier sending = FALSE; 4167dd7cddfSDavid du Colombier scrolling = FALSE; 4177dd7cddfSDavid du Colombier moving = FALSE; 4187dd7cddfSDavid du Colombier 4197dd7cddfSDavid du Colombier alts[MReshape].c = mousectl->resizec; 4207dd7cddfSDavid du Colombier alts[MReshape].v = nil; 4217dd7cddfSDavid du Colombier alts[MReshape].op = CHANRCV; 4227dd7cddfSDavid du Colombier alts[MMouse].c = mousectl->c; 4237dd7cddfSDavid du Colombier alts[MMouse].v = &mousectl->Mouse; 4247dd7cddfSDavid du Colombier alts[MMouse].op = CHANRCV; 4257dd7cddfSDavid du Colombier alts[NALT].op = CHANEND; 4267dd7cddfSDavid du Colombier 4277dd7cddfSDavid du Colombier for(;;) 4287dd7cddfSDavid du Colombier switch(alt(alts)){ 4297dd7cddfSDavid du Colombier case MReshape: 4307dd7cddfSDavid du Colombier resized(); 4317dd7cddfSDavid du Colombier break; 4327dd7cddfSDavid du Colombier case MMouse: 4337dd7cddfSDavid du Colombier Again: 4347dd7cddfSDavid du Colombier if(input!=nil && input->i!=nil){ 4357dd7cddfSDavid du Colombier /* convert to logical coordinates */ 4367dd7cddfSDavid du Colombier xy.x = mouse->xy.x + (input->i->r.min.x-input->screenr.min.x); 4377dd7cddfSDavid du Colombier xy.y = mouse->xy.y + (input->i->r.min.y-input->screenr.min.y); 4387dd7cddfSDavid du Colombier inside = ptinrect(mouse->xy, insetrect(input->screenr, Selborder)); 4397dd7cddfSDavid du Colombier if(input->mouseopen) 4407dd7cddfSDavid du Colombier scrolling = FALSE; 4417dd7cddfSDavid du Colombier else if(scrolling) 4427dd7cddfSDavid du Colombier scrolling = mouse->buttons; 4437dd7cddfSDavid du Colombier else 4447dd7cddfSDavid du Colombier scrolling = mouse->buttons && ptinrect(xy, input->scrollr); 4457dd7cddfSDavid du Colombier /* topped will be zero if window has been bottomed */ 4467dd7cddfSDavid du Colombier if(sending == FALSE && !scrolling && winborder(input, mouse->xy) && input->topped>0){ 4477dd7cddfSDavid du Colombier moving = TRUE; 4487dd7cddfSDavid du Colombier }else if(inside && (scrolling || input->mouseopen || (mouse->buttons&1))) 4497dd7cddfSDavid du Colombier sending = TRUE; 4507dd7cddfSDavid du Colombier }else 4517dd7cddfSDavid du Colombier sending = FALSE; 4527dd7cddfSDavid du Colombier if(sending){ 4537dd7cddfSDavid du Colombier if(mouse->buttons == 0){ 4547dd7cddfSDavid du Colombier cornercursor(input, mouse->xy, 0); 4557dd7cddfSDavid du Colombier sending = FALSE; 4567dd7cddfSDavid du Colombier }else 4577dd7cddfSDavid du Colombier wsetcursor(input, 0); 4587dd7cddfSDavid du Colombier tmp = mousectl->Mouse; 4597dd7cddfSDavid du Colombier tmp.xy = xy; 4607dd7cddfSDavid du Colombier send(input->mc.c, &tmp); 4617dd7cddfSDavid du Colombier continue; 4627dd7cddfSDavid du Colombier } 4637dd7cddfSDavid du Colombier w = wpointto(mouse->xy); 4647dd7cddfSDavid du Colombier /* change cursor if over anyone's border */ 4657dd7cddfSDavid du Colombier if(w != nil) 4667dd7cddfSDavid du Colombier cornercursor(w, mouse->xy, 0); 4677dd7cddfSDavid du Colombier else 4687dd7cddfSDavid du Colombier riosetcursor(nil, 0); 4697dd7cddfSDavid du Colombier if(moving && (mouse->buttons&7)){ 4707dd7cddfSDavid du Colombier oin = input; 4717dd7cddfSDavid du Colombier band = mouse->buttons & 3; 4727dd7cddfSDavid du Colombier sweeping = 1; 4737dd7cddfSDavid du Colombier if(band) 4747dd7cddfSDavid du Colombier i = bandsize(input); 4757dd7cddfSDavid du Colombier else 4767dd7cddfSDavid du Colombier i = drag(input, &r); 4777dd7cddfSDavid du Colombier sweeping = 0; 4787dd7cddfSDavid du Colombier if(i != nil){ 4797dd7cddfSDavid du Colombier if(input == oin){ 4807dd7cddfSDavid du Colombier if(band) 4817dd7cddfSDavid du Colombier wsendctlmesg(input, Reshaped, i->r, i); 4827dd7cddfSDavid du Colombier else 4837dd7cddfSDavid du Colombier wsendctlmesg(input, Moved, r, i); 4847dd7cddfSDavid du Colombier cornercursor(input, mouse->xy, 1); 4857dd7cddfSDavid du Colombier }else 4867dd7cddfSDavid du Colombier freeimage(i); 4877dd7cddfSDavid du Colombier } 4887dd7cddfSDavid du Colombier } 4897dd7cddfSDavid du Colombier if(w != nil) 4907dd7cddfSDavid du Colombier cornercursor(w, mouse->xy, 0); 4917dd7cddfSDavid du Colombier /* we're not sending the event, but if button is down maybe we should */ 4927dd7cddfSDavid du Colombier if(mouse->buttons){ 4937dd7cddfSDavid du Colombier /* w->topped will be zero if window has been bottomed */ 4947dd7cddfSDavid du Colombier if(w==nil || (w==input && w->topped>0)){ 4957dd7cddfSDavid du Colombier if(mouse->buttons & 1) 4967dd7cddfSDavid du Colombier ; 4977dd7cddfSDavid du Colombier else if(mouse->buttons & 2){ 4987dd7cddfSDavid du Colombier if(input && !input->mouseopen) 4997dd7cddfSDavid du Colombier button2menu(input); 5007dd7cddfSDavid du Colombier }else if(mouse->buttons & 4) 5017dd7cddfSDavid du Colombier button3menu(); 5027dd7cddfSDavid du Colombier }else{ 5037dd7cddfSDavid du Colombier /* if button 1 event in the window, top the window and wait for button up. */ 5047dd7cddfSDavid du Colombier /* otherwise, top the window and pass the event on */ 5057dd7cddfSDavid du Colombier if(wtop(mouse->xy) && (mouse->buttons!=1 || winborder(w, mouse->xy))) 5067dd7cddfSDavid du Colombier goto Again; 5077dd7cddfSDavid du Colombier goto Drain; 5087dd7cddfSDavid du Colombier } 5097dd7cddfSDavid du Colombier } 5107dd7cddfSDavid du Colombier moving = FALSE; 5117dd7cddfSDavid du Colombier break; 5127dd7cddfSDavid du Colombier 5137dd7cddfSDavid du Colombier Drain: 5147dd7cddfSDavid du Colombier do 5157dd7cddfSDavid du Colombier readmouse(mousectl); 5167dd7cddfSDavid du Colombier while(mousectl->buttons); 5177dd7cddfSDavid du Colombier moving = FALSE; 5187dd7cddfSDavid du Colombier goto Again; /* recalculate mouse position, cursor */ 5197dd7cddfSDavid du Colombier } 5207dd7cddfSDavid du Colombier } 5217dd7cddfSDavid du Colombier 5227dd7cddfSDavid du Colombier void 5237dd7cddfSDavid du Colombier resized(void) 5247dd7cddfSDavid du Colombier { 5257dd7cddfSDavid du Colombier Image *im; 5267dd7cddfSDavid du Colombier int i, j, ishidden; 5277dd7cddfSDavid du Colombier Rectangle r; 5287dd7cddfSDavid du Colombier Point o, n; 5297dd7cddfSDavid du Colombier Window *w; 5307dd7cddfSDavid du Colombier 5317dd7cddfSDavid du Colombier if(getwindow(display, Refnone) < 0) 5327dd7cddfSDavid du Colombier error("failed to re-attach window"); 5337dd7cddfSDavid du Colombier view = screen; 5347dd7cddfSDavid du Colombier freescreen(wscreen); 5357dd7cddfSDavid du Colombier wscreen = allocscreen(screen, background, 0); 5367dd7cddfSDavid du Colombier if(wscreen == nil) 5377dd7cddfSDavid du Colombier error("can't re-allocate screen"); 5387dd7cddfSDavid du Colombier draw(view, view->r, background, nil, ZP); 5397dd7cddfSDavid du Colombier o = subpt(viewr.max, viewr.min); 5407dd7cddfSDavid du Colombier n = subpt(view->clipr.max, view->clipr.min); 5417dd7cddfSDavid du Colombier for(i=0; i<nwindow; i++){ 5427dd7cddfSDavid du Colombier w = window[i]; 5437dd7cddfSDavid du Colombier if(w->deleted) 5447dd7cddfSDavid du Colombier continue; 5457dd7cddfSDavid du Colombier r = rectsubpt(w->i->r, viewr.min); 5467dd7cddfSDavid du Colombier r.min.x = (r.min.x*n.x)/o.x; 5477dd7cddfSDavid du Colombier r.min.y = (r.min.y*n.y)/o.y; 5487dd7cddfSDavid du Colombier r.max.x = (r.max.x*n.x)/o.x; 5497dd7cddfSDavid du Colombier r.max.y = (r.max.y*n.y)/o.y; 5507dd7cddfSDavid du Colombier r = rectaddpt(r, screen->clipr.min); 5517dd7cddfSDavid du Colombier ishidden = 0; 5527dd7cddfSDavid du Colombier for(j=0; j<nhidden; j++) 5537dd7cddfSDavid du Colombier if(w == hidden[j]){ 5547dd7cddfSDavid du Colombier ishidden = 1; 5557dd7cddfSDavid du Colombier break; 5567dd7cddfSDavid du Colombier } 5577dd7cddfSDavid du Colombier if(ishidden) 5587dd7cddfSDavid du Colombier im = allocimage(display, r, display->chan, 0, DWhite); 5597dd7cddfSDavid du Colombier else 5607dd7cddfSDavid du Colombier im = allocwindow(wscreen, r, Refbackup, DWhite); 5617dd7cddfSDavid du Colombier if(im) 5627dd7cddfSDavid du Colombier wsendctlmesg(w, Reshaped, r, im); 5637dd7cddfSDavid du Colombier } 5647dd7cddfSDavid du Colombier viewr = screen->r; 5657dd7cddfSDavid du Colombier flushimage(display, 1);} 5667dd7cddfSDavid du Colombier 5677dd7cddfSDavid du Colombier void 5687dd7cddfSDavid du Colombier button3menu(void) 5697dd7cddfSDavid du Colombier { 5707dd7cddfSDavid du Colombier int i; 5717dd7cddfSDavid du Colombier 5727dd7cddfSDavid du Colombier for(i=0; i<nhidden; i++) 5737dd7cddfSDavid du Colombier menu3str[i+Hidden] = hidden[i]->label; 5747dd7cddfSDavid du Colombier menu3str[i+Hidden] = nil; 5757dd7cddfSDavid du Colombier 5767dd7cddfSDavid du Colombier sweeping = 1; 5777dd7cddfSDavid du Colombier /*BUG: MENUHIT SHOULD TAKE FONT, COLOR, ETC. */ 5787dd7cddfSDavid du Colombier switch(i = menuhit(3, mousectl, &menu3, wscreen)){ 5797dd7cddfSDavid du Colombier case -1: 5807dd7cddfSDavid du Colombier break; 5817dd7cddfSDavid du Colombier case New: 5827dd7cddfSDavid du Colombier new(sweep(), 0, nil, "/bin/rc", nil); 5837dd7cddfSDavid du Colombier break; 5847dd7cddfSDavid du Colombier case Reshape: 5857dd7cddfSDavid du Colombier resize(); 5867dd7cddfSDavid du Colombier break; 5877dd7cddfSDavid du Colombier case Move: 5887dd7cddfSDavid du Colombier move(); 5897dd7cddfSDavid du Colombier break; 5907dd7cddfSDavid du Colombier case Delete: 5917dd7cddfSDavid du Colombier delete(); 5927dd7cddfSDavid du Colombier break; 5937dd7cddfSDavid du Colombier case Hide: 5947dd7cddfSDavid du Colombier hide(); 5957dd7cddfSDavid du Colombier break; 5967dd7cddfSDavid du Colombier case Exit: 5977dd7cddfSDavid du Colombier if(Hidden > Exit){ 5987dd7cddfSDavid du Colombier send(exitchan, nil); 5997dd7cddfSDavid du Colombier break; 6007dd7cddfSDavid du Colombier } 6017dd7cddfSDavid du Colombier /* else fall through */ 6027dd7cddfSDavid du Colombier default: 6037dd7cddfSDavid du Colombier unhide(i); 6047dd7cddfSDavid du Colombier break; 6057dd7cddfSDavid du Colombier } 6067dd7cddfSDavid du Colombier sweeping = 0; 6077dd7cddfSDavid du Colombier } 6087dd7cddfSDavid du Colombier 6097dd7cddfSDavid du Colombier void 6107dd7cddfSDavid du Colombier button2menu(Window *w) 6117dd7cddfSDavid du Colombier { 6127dd7cddfSDavid du Colombier if(w->deleted) 6137dd7cddfSDavid du Colombier return; 6147dd7cddfSDavid du Colombier incref(w); 6157dd7cddfSDavid du Colombier if(w->scrolling) 6167dd7cddfSDavid du Colombier menu2str[Scroll] = "noscroll"; 6177dd7cddfSDavid du Colombier else 6187dd7cddfSDavid du Colombier menu2str[Scroll] = "scroll"; 6197dd7cddfSDavid du Colombier switch(menuhit(2, mousectl, &menu2, wscreen)){ 6207dd7cddfSDavid du Colombier case Cut: 6217dd7cddfSDavid du Colombier wsnarf(w); 6227dd7cddfSDavid du Colombier wcut(w); 6237dd7cddfSDavid du Colombier wscrdraw(w); 6247dd7cddfSDavid du Colombier break; 6257dd7cddfSDavid du Colombier 6267dd7cddfSDavid du Colombier case Snarf: 6277dd7cddfSDavid du Colombier wsnarf(w); 6287dd7cddfSDavid du Colombier break; 6297dd7cddfSDavid du Colombier 6307dd7cddfSDavid du Colombier case Paste: 6317dd7cddfSDavid du Colombier getsnarf(); 6327dd7cddfSDavid du Colombier wpaste(w); 6337dd7cddfSDavid du Colombier wscrdraw(w); 6347dd7cddfSDavid du Colombier break; 6357dd7cddfSDavid du Colombier 6367dd7cddfSDavid du Colombier case Plumb: 6377dd7cddfSDavid du Colombier wplumb(w); 6387dd7cddfSDavid du Colombier break; 6397dd7cddfSDavid du Colombier 6407dd7cddfSDavid du Colombier case Send: 6417dd7cddfSDavid du Colombier getsnarf(); 6427dd7cddfSDavid du Colombier wsnarf(w); 6437dd7cddfSDavid du Colombier if(nsnarf == 0) 6447dd7cddfSDavid du Colombier break; 6457dd7cddfSDavid du Colombier if(w->rawing){ 6467dd7cddfSDavid du Colombier waddraw(w, snarf, nsnarf); 6477dd7cddfSDavid du Colombier if(snarf[nsnarf-1] != '\n') 6487dd7cddfSDavid du Colombier waddraw(w, L"\n", 1); 6497dd7cddfSDavid du Colombier }else{ 6507dd7cddfSDavid du Colombier winsert(w, snarf, nsnarf, w->nr); 6517dd7cddfSDavid du Colombier if(snarf[nsnarf-1] != '\n') 6527dd7cddfSDavid du Colombier winsert(w, L"\n", 1, w->nr); 6537dd7cddfSDavid du Colombier } 6547dd7cddfSDavid du Colombier wsetselect(w, w->nr, w->nr); 6557dd7cddfSDavid du Colombier wshow(w, w->nr); 6567dd7cddfSDavid du Colombier break; 6577dd7cddfSDavid du Colombier 6587dd7cddfSDavid du Colombier case Scroll: 6597dd7cddfSDavid du Colombier if(w->scrolling ^= 1) 6607dd7cddfSDavid du Colombier wshow(w, w->nr); 6617dd7cddfSDavid du Colombier break; 6627dd7cddfSDavid du Colombier } 6637dd7cddfSDavid du Colombier wclose(w); 6647dd7cddfSDavid du Colombier wsendctlmesg(w, Wakeup, ZR, nil); 6657dd7cddfSDavid du Colombier flushimage(display, 1); 6667dd7cddfSDavid du Colombier } 6677dd7cddfSDavid du Colombier 6687dd7cddfSDavid du Colombier Point 6697dd7cddfSDavid du Colombier onscreen(Point p) 6707dd7cddfSDavid du Colombier { 6717dd7cddfSDavid du Colombier p.x = max(screen->clipr.min.x, p.x); 6727dd7cddfSDavid du Colombier p.x = min(screen->clipr.max.x, p.x); 6737dd7cddfSDavid du Colombier p.y = max(screen->clipr.min.y, p.y); 6747dd7cddfSDavid du Colombier p.y = min(screen->clipr.max.y, p.y); 6757dd7cddfSDavid du Colombier return p; 6767dd7cddfSDavid du Colombier } 6777dd7cddfSDavid du Colombier 6787dd7cddfSDavid du Colombier Image* 6797dd7cddfSDavid du Colombier sweep(void) 6807dd7cddfSDavid du Colombier { 6817dd7cddfSDavid du Colombier Image *i, *oi; 6827dd7cddfSDavid du Colombier Rectangle r; 6837dd7cddfSDavid du Colombier Point p0, p; 6847dd7cddfSDavid du Colombier 6857dd7cddfSDavid du Colombier i = nil; 6867dd7cddfSDavid du Colombier riosetcursor(&crosscursor, 1); 6877dd7cddfSDavid du Colombier while(mouse->buttons == 0) 6887dd7cddfSDavid du Colombier readmouse(mousectl); 6897dd7cddfSDavid du Colombier p0 = onscreen(mouse->xy); 6907dd7cddfSDavid du Colombier p = p0; 6917dd7cddfSDavid du Colombier r.min = p; 6927dd7cddfSDavid du Colombier r.max = p; 6937dd7cddfSDavid du Colombier oi = nil; 6947dd7cddfSDavid du Colombier while(mouse->buttons == 4){ 6957dd7cddfSDavid du Colombier readmouse(mousectl); 6967dd7cddfSDavid du Colombier if(mouse->buttons != 4 && mouse->buttons != 0) 6977dd7cddfSDavid du Colombier break; 6987dd7cddfSDavid du Colombier if(!eqpt(mouse->xy, p)){ 6997dd7cddfSDavid du Colombier p = onscreen(mouse->xy); 7007dd7cddfSDavid du Colombier r = canonrect(Rpt(p0, p)); 7017dd7cddfSDavid du Colombier if(Dx(r)>5 && Dy(r)>5){ 7027dd7cddfSDavid du Colombier i = allocwindow(wscreen, r, Refnone, 0xEEEEEEFF); /* grey */ 7037dd7cddfSDavid du Colombier freeimage(oi); 7047dd7cddfSDavid du Colombier if(i == nil) 7057dd7cddfSDavid du Colombier goto Rescue; 7067dd7cddfSDavid du Colombier oi = i; 7077dd7cddfSDavid du Colombier border(i, r, Selborder, red, ZP); 7087dd7cddfSDavid du Colombier flushimage(display, 1); 7097dd7cddfSDavid du Colombier } 7107dd7cddfSDavid du Colombier } 7117dd7cddfSDavid du Colombier } 7127dd7cddfSDavid du Colombier if(mouse->buttons != 0) 7137dd7cddfSDavid du Colombier goto Rescue; 7147dd7cddfSDavid du Colombier if(i==nil || Dx(i->r)<100 || Dy(i->r)<3*font->height) 7157dd7cddfSDavid du Colombier goto Rescue; 7167dd7cddfSDavid du Colombier oi = i; 7177dd7cddfSDavid du Colombier i = allocwindow(wscreen, oi->r, Refbackup, DWhite); 7187dd7cddfSDavid du Colombier freeimage(oi); 7197dd7cddfSDavid du Colombier if(i == nil) 7207dd7cddfSDavid du Colombier goto Rescue; 7217dd7cddfSDavid du Colombier border(i, r, Selborder, red, ZP); 7227dd7cddfSDavid du Colombier cornercursor(input, mouse->xy, 1); 7237dd7cddfSDavid du Colombier return i; 7247dd7cddfSDavid du Colombier 7257dd7cddfSDavid du Colombier Rescue: 7267dd7cddfSDavid du Colombier freeimage(i); 7277dd7cddfSDavid du Colombier cornercursor(input, mouse->xy, 1); 7287dd7cddfSDavid du Colombier while(mouse->buttons) 7297dd7cddfSDavid du Colombier readmouse(mousectl); 7307dd7cddfSDavid du Colombier return nil; 7317dd7cddfSDavid du Colombier } 7327dd7cddfSDavid du Colombier 7337dd7cddfSDavid du Colombier /* 7347dd7cddfSDavid du Colombier * BUG: should interlock so applications don't change screen 7357dd7cddfSDavid du Colombier * while tmp[] holds backing store 7367dd7cddfSDavid du Colombier */ 7377dd7cddfSDavid du Colombier Image* 7387dd7cddfSDavid du Colombier drag(Window *w, Rectangle *rp) 7397dd7cddfSDavid du Colombier { 7407dd7cddfSDavid du Colombier Image *i, *ni; 7417dd7cddfSDavid du Colombier Point p, op, d, dm, om; 7427dd7cddfSDavid du Colombier Rectangle r; 7437dd7cddfSDavid du Colombier 7447dd7cddfSDavid du Colombier i = w->i; 7457dd7cddfSDavid du Colombier om = mouse->xy; 7467dd7cddfSDavid du Colombier riosetcursor(&boxcursor, 1); 7477dd7cddfSDavid du Colombier dm = subpt(mouse->xy, w->screenr.min); 7487dd7cddfSDavid du Colombier d = subpt(i->r.max, i->r.min); 7497dd7cddfSDavid du Colombier op = subpt(mouse->xy, dm); 7507dd7cddfSDavid du Colombier drawgetrect(Rect(op.x, op.y, op.x+d.x, op.y+d.y), 1); 7517dd7cddfSDavid du Colombier flushimage(display, 1); 7527dd7cddfSDavid du Colombier while(mouse->buttons == 4){ 7537dd7cddfSDavid du Colombier p = subpt(mouse->xy, dm); 7547dd7cddfSDavid du Colombier if(!eqpt(p, op)){ 7557dd7cddfSDavid du Colombier drawgetrect(Rect(op.x, op.y, op.x+d.x, op.y+d.y), 0); 7567dd7cddfSDavid du Colombier drawgetrect(Rect(p.x, p.y, p.x+d.x, p.y+d.y), 1); 7577dd7cddfSDavid du Colombier flushimage(display, 1); 7587dd7cddfSDavid du Colombier op = p; 7597dd7cddfSDavid du Colombier } 7607dd7cddfSDavid du Colombier readmouse(mousectl); 7617dd7cddfSDavid du Colombier } 7627dd7cddfSDavid du Colombier r = Rect(op.x, op.y, op.x+d.x, op.y+d.y); 7637dd7cddfSDavid du Colombier drawgetrect(r, 0); 7647dd7cddfSDavid du Colombier cornercursor(input, mouse->xy, 1); 7657dd7cddfSDavid du Colombier flushimage(display, 1); 7667dd7cddfSDavid du Colombier if(mouse->buttons!=0 || (ni=allocwindow(wscreen, r, Refbackup, DWhite))==nil){ 7677dd7cddfSDavid du Colombier moveto(mousectl, om); 7687dd7cddfSDavid du Colombier while(mouse->buttons) 7697dd7cddfSDavid du Colombier readmouse(mousectl); 7707dd7cddfSDavid du Colombier *rp = Rect(0, 0, 0, 0); 7717dd7cddfSDavid du Colombier return nil; 7727dd7cddfSDavid du Colombier } 7737dd7cddfSDavid du Colombier draw(ni, ni->r, i, nil, i->r.min); 7747dd7cddfSDavid du Colombier *rp = r; 7757dd7cddfSDavid du Colombier return ni; 7767dd7cddfSDavid du Colombier } 7777dd7cddfSDavid du Colombier 7787dd7cddfSDavid du Colombier Rectangle 7797dd7cddfSDavid du Colombier whichrect(Rectangle r, Point p, int which) 7807dd7cddfSDavid du Colombier { 7817dd7cddfSDavid du Colombier switch(which){ 7827dd7cddfSDavid du Colombier case 0: /* top left */ 7837dd7cddfSDavid du Colombier r = Rect(p.x, p.y, r.max.x, r.max.y); 7847dd7cddfSDavid du Colombier break; 7857dd7cddfSDavid du Colombier case 2: /* top right */ 7867dd7cddfSDavid du Colombier r = Rect(r.min.x, p.y, p.x, r.max.y); 7877dd7cddfSDavid du Colombier break; 7887dd7cddfSDavid du Colombier case 6: /* bottom left */ 7897dd7cddfSDavid du Colombier r = Rect(p.x, r.min.y, r.max.x, p.y); 7907dd7cddfSDavid du Colombier break; 7917dd7cddfSDavid du Colombier case 8: /* bottom right */ 7927dd7cddfSDavid du Colombier r = Rect(r.min.x, r.min.y, p.x, p.y); 7937dd7cddfSDavid du Colombier break; 7947dd7cddfSDavid du Colombier case 1: /* top edge */ 7957dd7cddfSDavid du Colombier r = Rect(r.min.x, p.y, r.max.x, r.max.y); 7967dd7cddfSDavid du Colombier break; 7977dd7cddfSDavid du Colombier case 5: /* right edge */ 7987dd7cddfSDavid du Colombier r = Rect(r.min.x, r.min.y, p.x, r.max.y); 7997dd7cddfSDavid du Colombier break; 8007dd7cddfSDavid du Colombier case 7: /* bottom edge */ 8017dd7cddfSDavid du Colombier r = Rect(r.min.x, r.min.y, r.max.x, p.y); 8027dd7cddfSDavid du Colombier break; 8037dd7cddfSDavid du Colombier case 3: /* left edge */ 8047dd7cddfSDavid du Colombier r = Rect(p.x, r.min.y, r.max.x, r.max.y); 8057dd7cddfSDavid du Colombier break; 8067dd7cddfSDavid du Colombier } 8077dd7cddfSDavid du Colombier return canonrect(r); 8087dd7cddfSDavid du Colombier } 8097dd7cddfSDavid du Colombier 8107dd7cddfSDavid du Colombier Image* 8117dd7cddfSDavid du Colombier bandsize(Window *w) 8127dd7cddfSDavid du Colombier { 8137dd7cddfSDavid du Colombier Image *i; 8147dd7cddfSDavid du Colombier Rectangle r, or; 8157dd7cddfSDavid du Colombier Point p, startp; 8167dd7cddfSDavid du Colombier int which, but; 8177dd7cddfSDavid du Colombier 8187dd7cddfSDavid du Colombier p = mouse->xy; 8197dd7cddfSDavid du Colombier startp = p; 8207dd7cddfSDavid du Colombier which = whichcorner(w, p); 8217dd7cddfSDavid du Colombier r = whichrect(w->screenr, p, which); 8227dd7cddfSDavid du Colombier drawgetrect(r, 1); 8237dd7cddfSDavid du Colombier or = r; 8247dd7cddfSDavid du Colombier but = mouse->buttons; 8257dd7cddfSDavid du Colombier while(mouse->buttons == but){ 8267dd7cddfSDavid du Colombier p = onscreen(mouse->xy); 8277dd7cddfSDavid du Colombier r = whichrect(w->screenr, p, which); 8287dd7cddfSDavid du Colombier if(!eqrect(r, or)){ 8297dd7cddfSDavid du Colombier /* not too big, not too small, just right */ 8307dd7cddfSDavid du Colombier if(Dx(r)<=Dx(viewr) && Dy(r)<=Dy(viewr) 8317dd7cddfSDavid du Colombier && Dx(r)>=100 && Dy(r)>=3*font->height){ 8327dd7cddfSDavid du Colombier drawgetrect(or, 0); 8337dd7cddfSDavid du Colombier drawgetrect(r, 1); 8347dd7cddfSDavid du Colombier flushimage(display, 1); 8357dd7cddfSDavid du Colombier or = r; 8367dd7cddfSDavid du Colombier } 8377dd7cddfSDavid du Colombier } 8387dd7cddfSDavid du Colombier readmouse(mousectl); 8397dd7cddfSDavid du Colombier } 8407dd7cddfSDavid du Colombier p = mouse->xy; 8417dd7cddfSDavid du Colombier drawgetrect(or, 0); 8427dd7cddfSDavid du Colombier flushimage(display, 1); 8437dd7cddfSDavid du Colombier wsetcursor(input, 1); 8447dd7cddfSDavid du Colombier if(mouse->buttons != 0 || Dx(or)<100 || Dy(or)<3*font->height){ 8457dd7cddfSDavid du Colombier while(mouse->buttons) 8467dd7cddfSDavid du Colombier readmouse(mousectl); 8477dd7cddfSDavid du Colombier return nil; 8487dd7cddfSDavid du Colombier } 8497dd7cddfSDavid du Colombier if(abs(p.x-startp.x)+abs(p.y-startp.y) <= 1) 8507dd7cddfSDavid du Colombier return nil; 8517dd7cddfSDavid du Colombier i = allocwindow(wscreen, or, Refbackup, DWhite); 8527dd7cddfSDavid du Colombier if(i == nil) 8537dd7cddfSDavid du Colombier return nil; 8547dd7cddfSDavid du Colombier border(i, r, Selborder, red, ZP); 8557dd7cddfSDavid du Colombier return i; 8567dd7cddfSDavid du Colombier } 8577dd7cddfSDavid du Colombier 8587dd7cddfSDavid du Colombier Window* 8597dd7cddfSDavid du Colombier pointto(int wait) 8607dd7cddfSDavid du Colombier { 8617dd7cddfSDavid du Colombier Window *w; 8627dd7cddfSDavid du Colombier 8637dd7cddfSDavid du Colombier riosetcursor(&sightcursor, 1); 8647dd7cddfSDavid du Colombier while(mouse->buttons == 0) 8657dd7cddfSDavid du Colombier readmouse(mousectl); 8667dd7cddfSDavid du Colombier if(mouse->buttons == 4) 8677dd7cddfSDavid du Colombier w = wpointto(mouse->xy); 8687dd7cddfSDavid du Colombier else 8697dd7cddfSDavid du Colombier w = nil; 8707dd7cddfSDavid du Colombier if(wait) 871*14414594SDavid du Colombier while(mouse->buttons){ 872*14414594SDavid du Colombier if(mouse->buttons!=4 && w !=nil){ /* cancel */ 873*14414594SDavid du Colombier cornercursor(input, mouse->xy, 0); 874*14414594SDavid du Colombier w = nil; 875*14414594SDavid du Colombier } 8767dd7cddfSDavid du Colombier readmouse(mousectl); 877*14414594SDavid du Colombier } 8787dd7cddfSDavid du Colombier cornercursor(input, mouse->xy, 0); 8797dd7cddfSDavid du Colombier return w; 8807dd7cddfSDavid du Colombier } 8817dd7cddfSDavid du Colombier 8827dd7cddfSDavid du Colombier void 8837dd7cddfSDavid du Colombier delete(void) 8847dd7cddfSDavid du Colombier { 8857dd7cddfSDavid du Colombier Window *w; 8867dd7cddfSDavid du Colombier 8877dd7cddfSDavid du Colombier w = pointto(TRUE); 8887dd7cddfSDavid du Colombier if(w) 8897dd7cddfSDavid du Colombier wsendctlmesg(w, Deleted, ZR, nil); 8907dd7cddfSDavid du Colombier } 8917dd7cddfSDavid du Colombier 8927dd7cddfSDavid du Colombier void 8937dd7cddfSDavid du Colombier resize(void) 8947dd7cddfSDavid du Colombier { 8957dd7cddfSDavid du Colombier Window *w; 8967dd7cddfSDavid du Colombier Image *i; 8977dd7cddfSDavid du Colombier 8987dd7cddfSDavid du Colombier w = pointto(TRUE); 8997dd7cddfSDavid du Colombier if(w == nil) 9007dd7cddfSDavid du Colombier return; 9017dd7cddfSDavid du Colombier i = sweep(); 9027dd7cddfSDavid du Colombier if(i) 9037dd7cddfSDavid du Colombier wsendctlmesg(w, Reshaped, i->r, i); 9047dd7cddfSDavid du Colombier } 9057dd7cddfSDavid du Colombier 9067dd7cddfSDavid du Colombier void 9077dd7cddfSDavid du Colombier move(void) 9087dd7cddfSDavid du Colombier { 9097dd7cddfSDavid du Colombier Window *w; 9107dd7cddfSDavid du Colombier Image *i; 9117dd7cddfSDavid du Colombier Rectangle r; 9127dd7cddfSDavid du Colombier 9137dd7cddfSDavid du Colombier w = pointto(FALSE); 9147dd7cddfSDavid du Colombier if(w == nil) 9157dd7cddfSDavid du Colombier return; 9167dd7cddfSDavid du Colombier i = drag(w, &r); 9177dd7cddfSDavid du Colombier if(i) 9187dd7cddfSDavid du Colombier wsendctlmesg(w, Moved, r, i); 9197dd7cddfSDavid du Colombier cornercursor(input, mouse->xy, 1); 9207dd7cddfSDavid du Colombier } 9217dd7cddfSDavid du Colombier 9227dd7cddfSDavid du Colombier void 9237dd7cddfSDavid du Colombier hide(void) 9247dd7cddfSDavid du Colombier { 9257dd7cddfSDavid du Colombier Window *w; 9267dd7cddfSDavid du Colombier Image *i; 9277dd7cddfSDavid du Colombier 9287dd7cddfSDavid du Colombier w = pointto(TRUE); 9297dd7cddfSDavid du Colombier if(w == nil) 9307dd7cddfSDavid du Colombier return; 9317dd7cddfSDavid du Colombier i = allocimage(display, w->screenr, w->i->chan, 0, DWhite); 9327dd7cddfSDavid du Colombier if(i){ 9337dd7cddfSDavid du Colombier hidden[nhidden++] = w; 9347dd7cddfSDavid du Colombier wsendctlmesg(w, Reshaped, ZR, i); 9357dd7cddfSDavid du Colombier } 9367dd7cddfSDavid du Colombier } 9377dd7cddfSDavid du Colombier 9387dd7cddfSDavid du Colombier void 9397dd7cddfSDavid du Colombier unhide(int h) 9407dd7cddfSDavid du Colombier { 9417dd7cddfSDavid du Colombier Window *w; 9427dd7cddfSDavid du Colombier Image *i; 9437dd7cddfSDavid du Colombier 9447dd7cddfSDavid du Colombier h -= Hidden; 9457dd7cddfSDavid du Colombier w = hidden[h]; 9467dd7cddfSDavid du Colombier if(w == nil) 9477dd7cddfSDavid du Colombier return; 9487dd7cddfSDavid du Colombier i = allocwindow(wscreen, w->i->r, Refbackup, DWhite); 9497dd7cddfSDavid du Colombier if(i == nil) 9507dd7cddfSDavid du Colombier return; 9517dd7cddfSDavid du Colombier if(i){ 9527dd7cddfSDavid du Colombier --nhidden; 9537dd7cddfSDavid du Colombier memmove(hidden+h, hidden+h+1, (nhidden-h)*sizeof(Window*)); 9547dd7cddfSDavid du Colombier wsendctlmesg(w, Reshaped, w->i->r, i); 9557dd7cddfSDavid du Colombier } 9567dd7cddfSDavid du Colombier } 9577dd7cddfSDavid du Colombier 9587dd7cddfSDavid du Colombier Window* 9597dd7cddfSDavid du Colombier new(Image *i, int pid, char *dir, char *cmd, char **argv) 9607dd7cddfSDavid du Colombier { 9617dd7cddfSDavid du Colombier Window *w; 9627dd7cddfSDavid du Colombier Mousectl *mc; 9637dd7cddfSDavid du Colombier Channel *cm, *ck, *cctl, *cpid; 9647dd7cddfSDavid du Colombier void **arg; 9657dd7cddfSDavid du Colombier 9667dd7cddfSDavid du Colombier if(i == nil) 9677dd7cddfSDavid du Colombier return nil; 9687dd7cddfSDavid du Colombier cm = chancreate(sizeof(Mouse), 0); 9697dd7cddfSDavid du Colombier ck = chancreate(sizeof(Rune*), 0); 9707dd7cddfSDavid du Colombier cctl = chancreate(sizeof(Wctlmesg), 4); 9717dd7cddfSDavid du Colombier cpid = chancreate(sizeof(int), 0); 9727dd7cddfSDavid du Colombier if(cm==nil || ck==nil || cctl==nil) 9737dd7cddfSDavid du Colombier error("new: channel alloc failed"); 9747dd7cddfSDavid du Colombier mc = emalloc(sizeof(Mousectl)); 9757dd7cddfSDavid du Colombier *mc = *mousectl; 9767dd7cddfSDavid du Colombier mc->image = i; 9777dd7cddfSDavid du Colombier mc->c = cm; 9787dd7cddfSDavid du Colombier w = wmk(i, mc, ck, cctl); 9797dd7cddfSDavid du Colombier window = erealloc(window, ++nwindow*sizeof(Window*)); 9807dd7cddfSDavid du Colombier window[nwindow-1] = w; 9817dd7cddfSDavid du Colombier threadcreate(winctl, w, 8192); 9827dd7cddfSDavid du Colombier wcurrent(w); 9837dd7cddfSDavid du Colombier flushimage(display, 1); 9847dd7cddfSDavid du Colombier if(pid == 0){ 9857dd7cddfSDavid du Colombier arg = emalloc(5*sizeof(void*)); 9867dd7cddfSDavid du Colombier arg[0] = w; 9877dd7cddfSDavid du Colombier arg[1] = cpid; 9887dd7cddfSDavid du Colombier arg[2] = cmd; 9897dd7cddfSDavid du Colombier if(argv == nil) 9907dd7cddfSDavid du Colombier arg[3] = rcargv; 9917dd7cddfSDavid du Colombier else 9927dd7cddfSDavid du Colombier arg[3] = argv; 9937dd7cddfSDavid du Colombier arg[4] = dir; 9947dd7cddfSDavid du Colombier proccreate(winshell, arg, 8192); 9957dd7cddfSDavid du Colombier pid = recvul(cpid); 9967dd7cddfSDavid du Colombier free(arg); 9977dd7cddfSDavid du Colombier } 9987dd7cddfSDavid du Colombier wsetpid(w, pid); 9997dd7cddfSDavid du Colombier wsetname(w); 10007dd7cddfSDavid du Colombier free(cpid); 10017dd7cddfSDavid du Colombier return w; 10027dd7cddfSDavid du Colombier } 1003