17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <thread.h>
57dd7cddfSDavid du Colombier #include <cursor.h>
67dd7cddfSDavid du Colombier #include <mouse.h>
77dd7cddfSDavid du Colombier #include <keyboard.h>
87dd7cddfSDavid du Colombier #include <frame.h>
97dd7cddfSDavid du Colombier #include <fcall.h>
107dd7cddfSDavid du Colombier #include <plumb.h>
117dd7cddfSDavid du Colombier #include "dat.h"
127dd7cddfSDavid du Colombier #include "fns.h"
137dd7cddfSDavid du Colombier
147dd7cddfSDavid du Colombier /*
157dd7cddfSDavid du Colombier * WASHINGTON (AP) - The Food and Drug Administration warned
167dd7cddfSDavid du Colombier * consumers Wednesday not to use ``Rio'' hair relaxer products
177dd7cddfSDavid du Colombier * because they may cause severe hair loss or turn hair green....
187dd7cddfSDavid du Colombier * The FDA urged consumers who have experienced problems with Rio
197dd7cddfSDavid du Colombier * to notify their local FDA office, local health department or the
207dd7cddfSDavid du Colombier * company at 1‑800‑543‑3002.
217dd7cddfSDavid du Colombier */
227dd7cddfSDavid du Colombier
237dd7cddfSDavid du Colombier void resize(void);
247dd7cddfSDavid du Colombier void move(void);
257dd7cddfSDavid du Colombier void delete(void);
267dd7cddfSDavid du Colombier void hide(void);
277dd7cddfSDavid du Colombier void unhide(int);
287dd7cddfSDavid du Colombier void newtile(int);
297dd7cddfSDavid du Colombier Image *sweep(void);
307dd7cddfSDavid du Colombier Image *bandsize(Window*);
317dd7cddfSDavid du Colombier Image* drag(Window*, Rectangle*);
327dd7cddfSDavid du Colombier void refresh(Rectangle);
337dd7cddfSDavid du Colombier void resized(void);
347dd7cddfSDavid du Colombier Channel *exitchan; /* chan(int) */
357dd7cddfSDavid du Colombier Channel *winclosechan; /* chan(Window*); */
367dd7cddfSDavid du Colombier Rectangle viewr;
379a747e4fSDavid du Colombier int threadrforkflag = 0; /* should be RFENVG but that hides rio from plumber */
387dd7cddfSDavid du Colombier
397dd7cddfSDavid du Colombier void mousethread(void*);
407dd7cddfSDavid du Colombier void keyboardthread(void*);
417dd7cddfSDavid du Colombier void winclosethread(void*);
427dd7cddfSDavid du Colombier void deletethread(void*);
437dd7cddfSDavid du Colombier void initcmd(void*);
447dd7cddfSDavid du Colombier
457dd7cddfSDavid du Colombier char *fontname;
467dd7cddfSDavid du Colombier int mainpid;
477dd7cddfSDavid du Colombier
487dd7cddfSDavid du Colombier enum
497dd7cddfSDavid du Colombier {
507dd7cddfSDavid du Colombier New,
517dd7cddfSDavid du Colombier Reshape,
527dd7cddfSDavid du Colombier Move,
537dd7cddfSDavid du Colombier Delete,
547dd7cddfSDavid du Colombier Hide,
557dd7cddfSDavid du Colombier Exit,
567dd7cddfSDavid du Colombier };
577dd7cddfSDavid du Colombier
587dd7cddfSDavid du Colombier enum
597dd7cddfSDavid du Colombier {
607dd7cddfSDavid du Colombier Cut,
617dd7cddfSDavid du Colombier Paste,
627dd7cddfSDavid du Colombier Snarf,
637dd7cddfSDavid du Colombier Plumb,
647dd7cddfSDavid du Colombier Send,
657dd7cddfSDavid du Colombier Scroll,
667dd7cddfSDavid du Colombier };
677dd7cddfSDavid du Colombier
687dd7cddfSDavid du Colombier char *menu2str[] = {
697dd7cddfSDavid du Colombier [Cut] "cut",
707dd7cddfSDavid du Colombier [Paste] "paste",
717dd7cddfSDavid du Colombier [Snarf] "snarf",
727dd7cddfSDavid du Colombier [Plumb] "plumb",
737dd7cddfSDavid du Colombier [Send] "send",
747dd7cddfSDavid du Colombier [Scroll] "scroll",
757dd7cddfSDavid du Colombier nil
767dd7cddfSDavid du Colombier };
777dd7cddfSDavid du Colombier
787dd7cddfSDavid du Colombier Menu menu2 =
797dd7cddfSDavid du Colombier {
807dd7cddfSDavid du Colombier menu2str
817dd7cddfSDavid du Colombier };
827dd7cddfSDavid du Colombier
837dd7cddfSDavid du Colombier int Hidden = Exit+1;
847dd7cddfSDavid du Colombier
857dd7cddfSDavid du Colombier char *menu3str[100] = {
867dd7cddfSDavid du Colombier [New] "New",
877dd7cddfSDavid du Colombier [Reshape] "Resize",
887dd7cddfSDavid du Colombier [Move] "Move",
897dd7cddfSDavid du Colombier [Delete] "Delete",
907dd7cddfSDavid du Colombier [Hide] "Hide",
917dd7cddfSDavid du Colombier [Exit] "Exit",
927dd7cddfSDavid du Colombier nil
937dd7cddfSDavid du Colombier };
947dd7cddfSDavid du Colombier
957dd7cddfSDavid du Colombier Menu menu3 =
967dd7cddfSDavid du Colombier {
977dd7cddfSDavid du Colombier menu3str
987dd7cddfSDavid du Colombier };
997dd7cddfSDavid du Colombier
1007dd7cddfSDavid du Colombier char *rcargv[] = { "rc", "-i", nil };
10180ee5cbfSDavid du Colombier char *kbdargv[] = { "rc", "-c", nil, nil };
1027dd7cddfSDavid du Colombier
1037dd7cddfSDavid du Colombier int errorshouldabort = 0;
1047dd7cddfSDavid du Colombier
1057dd7cddfSDavid du Colombier void
derror(Display *,char * errorstr)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
usage(void)11280ee5cbfSDavid du Colombier usage(void)
11380ee5cbfSDavid du Colombier {
11480ee5cbfSDavid du Colombier fprint(2, "usage: rio [-f font] [-i initcmd] [-k kbdcmd] [-s]\n");
11580ee5cbfSDavid du Colombier exits("usage");
11680ee5cbfSDavid du Colombier }
11780ee5cbfSDavid du Colombier
11880ee5cbfSDavid du Colombier void
threadmain(int argc,char * argv[])1197dd7cddfSDavid du Colombier threadmain(int argc, char *argv[])
1207dd7cddfSDavid du Colombier {
12180ee5cbfSDavid du Colombier char *initstr, *kbdin, *s;
1227dd7cddfSDavid du Colombier static void *arg[1];
1237dd7cddfSDavid du Colombier char buf[256];
12480ee5cbfSDavid du Colombier Image *i;
12580ee5cbfSDavid du Colombier Rectangle r;
1267dd7cddfSDavid du Colombier
1277dd7cddfSDavid du Colombier if(strstr(argv[0], ".out") == nil){
1287dd7cddfSDavid du Colombier menu3str[Exit] = nil;
1297dd7cddfSDavid du Colombier Hidden--;
1307dd7cddfSDavid du Colombier }
1317dd7cddfSDavid du Colombier initstr = nil;
13280ee5cbfSDavid du Colombier kbdin = nil;
1337dd7cddfSDavid du Colombier maxtab = 0;
1347dd7cddfSDavid du Colombier ARGBEGIN{
1357dd7cddfSDavid du Colombier case 'f':
1367dd7cddfSDavid du Colombier fontname = ARGF();
13780ee5cbfSDavid du Colombier if(fontname == nil)
13880ee5cbfSDavid du Colombier usage();
1397dd7cddfSDavid du Colombier break;
1407dd7cddfSDavid du Colombier case 'i':
1417dd7cddfSDavid du Colombier initstr = ARGF();
14280ee5cbfSDavid du Colombier if(initstr == nil)
14380ee5cbfSDavid du Colombier usage();
14480ee5cbfSDavid du Colombier break;
14580ee5cbfSDavid du Colombier case 'k':
14680ee5cbfSDavid du Colombier if(kbdin != nil)
14780ee5cbfSDavid du Colombier usage();
14880ee5cbfSDavid du Colombier kbdin = ARGF();
14980ee5cbfSDavid du Colombier if(kbdin == nil)
15080ee5cbfSDavid du Colombier usage();
1517dd7cddfSDavid du Colombier break;
1527dd7cddfSDavid du Colombier case 's':
1537dd7cddfSDavid du Colombier scrolling = TRUE;
1547dd7cddfSDavid du Colombier break;
1557dd7cddfSDavid du Colombier }ARGEND
1567dd7cddfSDavid du Colombier
1577dd7cddfSDavid du Colombier mainpid = getpid();
1587dd7cddfSDavid du Colombier if(getwd(buf, sizeof buf) == nil)
1597dd7cddfSDavid du Colombier startdir = estrdup(".");
1607dd7cddfSDavid du Colombier else
1617dd7cddfSDavid du Colombier startdir = estrdup(buf);
1627dd7cddfSDavid du Colombier if(fontname == nil)
1637dd7cddfSDavid du Colombier fontname = getenv("font");
1647dd7cddfSDavid du Colombier if(fontname == nil)
1657dd7cddfSDavid du Colombier fontname = "/lib/font/bit/lucm/unicode.9.font";
1667dd7cddfSDavid du Colombier s = getenv("tabstop");
1677dd7cddfSDavid du Colombier if(s != nil)
1687dd7cddfSDavid du Colombier maxtab = strtol(s, nil, 0);
1697dd7cddfSDavid du Colombier if(maxtab == 0)
1707dd7cddfSDavid du Colombier maxtab = 4;
1719a747e4fSDavid du Colombier free(s);
1727dd7cddfSDavid du Colombier /* check font before barging ahead */
1737dd7cddfSDavid du Colombier if(access(fontname, 0) < 0){
1749a747e4fSDavid du Colombier fprint(2, "rio: can't access %s: %r\n", fontname);
1757dd7cddfSDavid du Colombier exits("font open");
1767dd7cddfSDavid du Colombier }
1777dd7cddfSDavid du Colombier putenv("font", fontname);
1787dd7cddfSDavid du Colombier
1797dd7cddfSDavid du Colombier snarffd = open("/dev/snarf", OREAD|OCEXEC);
1807dd7cddfSDavid du Colombier
18114414594SDavid du Colombier if(geninitdraw(nil, derror, nil, "rio", nil, Refnone) < 0){
1829a747e4fSDavid du Colombier fprint(2, "rio: can't open display: %r\n");
18314414594SDavid du Colombier exits("display open");
18414414594SDavid du Colombier }
1857dd7cddfSDavid du Colombier iconinit();
1867dd7cddfSDavid du Colombier view = screen;
1877dd7cddfSDavid du Colombier viewr = view->r;
1887dd7cddfSDavid du Colombier mousectl = initmouse(nil, screen);
1897dd7cddfSDavid du Colombier if(mousectl == nil)
1907dd7cddfSDavid du Colombier error("can't find mouse");
1917dd7cddfSDavid du Colombier mouse = mousectl;
1927dd7cddfSDavid du Colombier keyboardctl = initkeyboard(nil);
1937dd7cddfSDavid du Colombier if(keyboardctl == nil)
1947dd7cddfSDavid du Colombier error("can't find keyboard");
1957dd7cddfSDavid du Colombier wscreen = allocscreen(screen, background, 0);
1967dd7cddfSDavid du Colombier if(wscreen == nil)
1977dd7cddfSDavid du Colombier error("can't allocate screen");
1987dd7cddfSDavid du Colombier draw(view, viewr, background, nil, ZP);
1997dd7cddfSDavid du Colombier flushimage(display, 1);
2007dd7cddfSDavid du Colombier
2017dd7cddfSDavid du Colombier exitchan = chancreate(sizeof(int), 0);
2027dd7cddfSDavid du Colombier winclosechan = chancreate(sizeof(Window*), 0);
2037dd7cddfSDavid du Colombier deletechan = chancreate(sizeof(char*), 0);
2047dd7cddfSDavid du Colombier
2057dd7cddfSDavid du Colombier timerinit();
2067dd7cddfSDavid du Colombier threadcreate(keyboardthread, nil, STACK);
2077dd7cddfSDavid du Colombier threadcreate(mousethread, nil, STACK);
2087dd7cddfSDavid du Colombier threadcreate(winclosethread, nil, STACK);
2097dd7cddfSDavid du Colombier threadcreate(deletethread, nil, STACK);
2107dd7cddfSDavid du Colombier filsys = filsysinit(xfidinit());
2117dd7cddfSDavid du Colombier
2127dd7cddfSDavid du Colombier if(filsys == nil)
2137dd7cddfSDavid du Colombier fprint(2, "rio: can't create file system server: %r\n");
2147dd7cddfSDavid du Colombier else{
2157dd7cddfSDavid du Colombier errorshouldabort = 1; /* suicide if there's trouble after this */
2167dd7cddfSDavid du Colombier if(initstr)
2177dd7cddfSDavid du Colombier proccreate(initcmd, initstr, STACK);
21880ee5cbfSDavid du Colombier if(kbdin){
21980ee5cbfSDavid du Colombier kbdargv[2] = kbdin;
22080ee5cbfSDavid du Colombier r = screen->r;
22180ee5cbfSDavid du Colombier r.max.x = r.min.x+300;
22280ee5cbfSDavid du Colombier r.max.y = r.min.y+80;
22380ee5cbfSDavid du Colombier i = allocwindow(wscreen, r, Refbackup, DWhite);
2243ff48bf5SDavid du Colombier wkeyboard = new(i, FALSE, scrolling, 0, nil, "/bin/rc", kbdargv);
22580ee5cbfSDavid du Colombier if(wkeyboard == nil)
22680ee5cbfSDavid du Colombier error("can't create keyboard window");
22780ee5cbfSDavid du Colombier }
228d9306527SDavid du Colombier threadnotify(shutdown, 1);
2297dd7cddfSDavid du Colombier recv(exitchan, nil);
2307dd7cddfSDavid du Colombier }
2317dd7cddfSDavid du Colombier killprocs();
2327dd7cddfSDavid du Colombier threadexitsall(nil);
2337dd7cddfSDavid du Colombier }
2347dd7cddfSDavid du Colombier
2357dd7cddfSDavid du Colombier /*
2367dd7cddfSDavid du Colombier * /dev/snarf updates when the file is closed, so we must open our own
2377dd7cddfSDavid du Colombier * fd here rather than use snarffd
2387dd7cddfSDavid du Colombier */
2397dd7cddfSDavid du Colombier void
putsnarf(void)2407dd7cddfSDavid du Colombier putsnarf(void)
2417dd7cddfSDavid du Colombier {
2427dd7cddfSDavid du Colombier int fd, i, n;
2437dd7cddfSDavid du Colombier
2447dd7cddfSDavid du Colombier if(snarffd<0 || nsnarf==0)
2457dd7cddfSDavid du Colombier return;
2467dd7cddfSDavid du Colombier fd = open("/dev/snarf", OWRITE);
2477dd7cddfSDavid du Colombier if(fd < 0)
2487dd7cddfSDavid du Colombier return;
2497dd7cddfSDavid du Colombier /* snarf buffer could be huge, so fprint will truncate; do it in blocks */
2507dd7cddfSDavid du Colombier for(i=0; i<nsnarf; i+=n){
2517dd7cddfSDavid du Colombier n = nsnarf-i;
2527dd7cddfSDavid du Colombier if(n >= 256)
2537dd7cddfSDavid du Colombier n = 256;
2549a747e4fSDavid du Colombier if(fprint(fd, "%.*S", n, snarf+i) < 0)
2557dd7cddfSDavid du Colombier break;
2567dd7cddfSDavid du Colombier }
2577dd7cddfSDavid du Colombier close(fd);
2587dd7cddfSDavid du Colombier }
2597dd7cddfSDavid du Colombier
2607dd7cddfSDavid du Colombier void
getsnarf(void)2617dd7cddfSDavid du Colombier getsnarf(void)
2627dd7cddfSDavid du Colombier {
2637dd7cddfSDavid du Colombier int i, n, nb, nulls;
2647dd7cddfSDavid du Colombier char *sn, buf[1024];
2657dd7cddfSDavid du Colombier
2667dd7cddfSDavid du Colombier if(snarffd < 0)
2677dd7cddfSDavid du Colombier return;
2687dd7cddfSDavid du Colombier sn = nil;
2697dd7cddfSDavid du Colombier i = 0;
2707dd7cddfSDavid du Colombier seek(snarffd, 0, 0);
2717dd7cddfSDavid du Colombier while((n = read(snarffd, buf, sizeof buf)) > 0){
2727dd7cddfSDavid du Colombier sn = erealloc(sn, i+n+1);
2737dd7cddfSDavid du Colombier memmove(sn+i, buf, n);
2747dd7cddfSDavid du Colombier i += n;
2757dd7cddfSDavid du Colombier sn[i] = 0;
2767dd7cddfSDavid du Colombier }
2777dd7cddfSDavid du Colombier if(i > 0){
2787dd7cddfSDavid du Colombier snarf = runerealloc(snarf, i+1);
2797dd7cddfSDavid du Colombier cvttorunes(sn, i, snarf, &nb, &nsnarf, &nulls);
2807dd7cddfSDavid du Colombier free(sn);
2817dd7cddfSDavid du Colombier }
2827dd7cddfSDavid du Colombier }
2837dd7cddfSDavid du Colombier
2847dd7cddfSDavid du Colombier void
initcmd(void * arg)2857dd7cddfSDavid du Colombier initcmd(void *arg)
2867dd7cddfSDavid du Colombier {
2877dd7cddfSDavid du Colombier char *cmd;
2887dd7cddfSDavid du Colombier
2897dd7cddfSDavid du Colombier cmd = arg;
2907dd7cddfSDavid du Colombier rfork(RFENVG|RFFDG|RFNOTEG|RFNAMEG);
291f19e7b74SDavid du Colombier procexecl(nil, "/bin/rc", "rc", "-c", cmd, nil);
2929a747e4fSDavid du Colombier fprint(2, "rio: exec failed: %r\n");
2937dd7cddfSDavid du Colombier exits("exec");
2947dd7cddfSDavid du Colombier }
2957dd7cddfSDavid du Colombier
2967dd7cddfSDavid du Colombier char *oknotes[] =
2977dd7cddfSDavid du Colombier {
2987dd7cddfSDavid du Colombier "delete",
2997dd7cddfSDavid du Colombier "hangup",
3007dd7cddfSDavid du Colombier "kill",
3017dd7cddfSDavid du Colombier "exit",
3027dd7cddfSDavid du Colombier nil
3037dd7cddfSDavid du Colombier };
3047dd7cddfSDavid du Colombier
305d9306527SDavid du Colombier int
shutdown(void *,char * msg)3069a747e4fSDavid du Colombier shutdown(void *, char *msg)
3077dd7cddfSDavid du Colombier {
3087dd7cddfSDavid du Colombier int i;
309f366f900SDavid du Colombier static Lock shutdownlk;
3107dd7cddfSDavid du Colombier
3117dd7cddfSDavid du Colombier killprocs();
3127dd7cddfSDavid du Colombier for(i=0; oknotes[i]; i++)
313f366f900SDavid du Colombier if(strncmp(oknotes[i], msg, strlen(oknotes[i])) == 0){
314f366f900SDavid du Colombier lock(&shutdownlk); /* only one can threadexitsall */
3157dd7cddfSDavid du Colombier threadexitsall(msg);
316f366f900SDavid du Colombier }
3179a747e4fSDavid du Colombier fprint(2, "rio %d: abort: %s\n", getpid(), msg);
3187dd7cddfSDavid du Colombier abort();
3197dd7cddfSDavid du Colombier exits(msg);
320d9306527SDavid du Colombier return 0;
3217dd7cddfSDavid du Colombier }
3227dd7cddfSDavid du Colombier
3237dd7cddfSDavid du Colombier void
killprocs(void)3247dd7cddfSDavid du Colombier killprocs(void)
3257dd7cddfSDavid du Colombier {
3267dd7cddfSDavid du Colombier int i;
3277dd7cddfSDavid du Colombier
3287dd7cddfSDavid du Colombier for(i=0; i<nwindow; i++)
3297dd7cddfSDavid du Colombier postnote(PNGROUP, window[i]->pid, "hangup");
3307dd7cddfSDavid du Colombier }
3317dd7cddfSDavid du Colombier
3327dd7cddfSDavid du Colombier void
keyboardthread(void *)3337dd7cddfSDavid du Colombier keyboardthread(void*)
3347dd7cddfSDavid du Colombier {
3357dd7cddfSDavid du Colombier Rune buf[2][20], *rp;
3367dd7cddfSDavid du Colombier int n, i;
3377dd7cddfSDavid du Colombier
33859cc4ca5SDavid du Colombier threadsetname("keyboardthread");
3397dd7cddfSDavid du Colombier n = 0;
3407dd7cddfSDavid du Colombier for(;;){
3417dd7cddfSDavid du Colombier rp = buf[n];
3427dd7cddfSDavid du Colombier n = 1-n;
3437dd7cddfSDavid du Colombier recv(keyboardctl->c, rp);
3447dd7cddfSDavid du Colombier for(i=1; i<nelem(buf[0])-1; i++)
3457dd7cddfSDavid du Colombier if(nbrecv(keyboardctl->c, rp+i) <= 0)
3467dd7cddfSDavid du Colombier break;
3477dd7cddfSDavid du Colombier rp[i] = L'\0';
3487dd7cddfSDavid du Colombier if(input != nil)
3497dd7cddfSDavid du Colombier sendp(input->ck, rp);
3507dd7cddfSDavid du Colombier }
3517dd7cddfSDavid du Colombier }
3527dd7cddfSDavid du Colombier
35380ee5cbfSDavid du Colombier /*
35480ee5cbfSDavid du Colombier * Used by /dev/kbdin
35580ee5cbfSDavid du Colombier */
35680ee5cbfSDavid du Colombier void
keyboardsend(char * s,int cnt)35780ee5cbfSDavid du Colombier keyboardsend(char *s, int cnt)
35880ee5cbfSDavid du Colombier {
35980ee5cbfSDavid du Colombier Rune *r;
36080ee5cbfSDavid du Colombier int i, nb, nr;
36180ee5cbfSDavid du Colombier
36280ee5cbfSDavid du Colombier r = runemalloc(cnt);
36380ee5cbfSDavid du Colombier /* BUGlet: partial runes will be converted to error runes */
36480ee5cbfSDavid du Colombier cvttorunes(s, cnt, r, &nb, &nr, nil);
36580ee5cbfSDavid du Colombier for(i=0; i<nr; i++)
36680ee5cbfSDavid du Colombier send(keyboardctl->c, &r[i]);
36780ee5cbfSDavid du Colombier free(r);
36880ee5cbfSDavid du Colombier }
36980ee5cbfSDavid du Colombier
3707dd7cddfSDavid du Colombier int
portion(int x,int lo,int hi)3717dd7cddfSDavid du Colombier portion(int x, int lo, int hi)
3727dd7cddfSDavid du Colombier {
3737dd7cddfSDavid du Colombier x -= lo;
3747dd7cddfSDavid du Colombier hi -= lo;
3757dd7cddfSDavid du Colombier if(x < 20)
3767dd7cddfSDavid du Colombier return 0;
3777dd7cddfSDavid du Colombier if(x > hi-20)
3787dd7cddfSDavid du Colombier return 2;
3797dd7cddfSDavid du Colombier return 1;
3807dd7cddfSDavid du Colombier }
3817dd7cddfSDavid du Colombier
3827dd7cddfSDavid du Colombier int
whichcorner(Window * w,Point p)3837dd7cddfSDavid du Colombier whichcorner(Window *w, Point p)
3847dd7cddfSDavid du Colombier {
3857dd7cddfSDavid du Colombier int i, j;
3867dd7cddfSDavid du Colombier
3877dd7cddfSDavid du Colombier i = portion(p.x, w->screenr.min.x, w->screenr.max.x);
3887dd7cddfSDavid du Colombier j = portion(p.y, w->screenr.min.y, w->screenr.max.y);
3897dd7cddfSDavid du Colombier return 3*j+i;
3907dd7cddfSDavid du Colombier }
3917dd7cddfSDavid du Colombier
3927dd7cddfSDavid du Colombier void
cornercursor(Window * w,Point p,int force)3937dd7cddfSDavid du Colombier cornercursor(Window *w, Point p, int force)
3947dd7cddfSDavid du Colombier {
3957dd7cddfSDavid du Colombier if(w!=nil && winborder(w, p))
3967dd7cddfSDavid du Colombier riosetcursor(corners[whichcorner(w, p)], force);
3977dd7cddfSDavid du Colombier else
3987dd7cddfSDavid du Colombier wsetcursor(w, force);
3997dd7cddfSDavid du Colombier }
4007dd7cddfSDavid du Colombier
4017dd7cddfSDavid du Colombier /* thread to allow fsysproc to synchronize window closing with main proc */
4027dd7cddfSDavid du Colombier void
winclosethread(void *)4037dd7cddfSDavid du Colombier winclosethread(void*)
4047dd7cddfSDavid du Colombier {
4057dd7cddfSDavid du Colombier Window *w;
4067dd7cddfSDavid du Colombier
40759cc4ca5SDavid du Colombier threadsetname("winclosethread");
4087dd7cddfSDavid du Colombier for(;;){
4097dd7cddfSDavid du Colombier w = recvp(winclosechan);
4107dd7cddfSDavid du Colombier wclose(w);
4117dd7cddfSDavid du Colombier }
4127dd7cddfSDavid du Colombier }
4137dd7cddfSDavid du Colombier
4147dd7cddfSDavid du Colombier /* thread to make Deleted windows that the client still holds disappear offscreen after an interval */
4157dd7cddfSDavid du Colombier void
deletethread(void *)4167dd7cddfSDavid du Colombier deletethread(void*)
4177dd7cddfSDavid du Colombier {
4187dd7cddfSDavid du Colombier char *s;
4197dd7cddfSDavid du Colombier Image *i;
4207dd7cddfSDavid du Colombier
42159cc4ca5SDavid du Colombier threadsetname("deletethread");
4227dd7cddfSDavid du Colombier for(;;){
4237dd7cddfSDavid du Colombier s = recvp(deletechan);
4247dd7cddfSDavid du Colombier i = namedimage(display, s);
4257dd7cddfSDavid du Colombier if(i != nil){
4267dd7cddfSDavid du Colombier /* move it off-screen to hide it, since client is slow in letting it go */
4277dd7cddfSDavid du Colombier originwindow(i, i->r.min, view->r.max);
4287dd7cddfSDavid du Colombier }
4297dd7cddfSDavid du Colombier freeimage(i);
4307dd7cddfSDavid du Colombier free(s);
4317dd7cddfSDavid du Colombier }
4327dd7cddfSDavid du Colombier }
4337dd7cddfSDavid du Colombier
4347dd7cddfSDavid du Colombier void
deletetimeoutproc(void * v)4357dd7cddfSDavid du Colombier deletetimeoutproc(void *v)
4367dd7cddfSDavid du Colombier {
4377dd7cddfSDavid du Colombier char *s;
4387dd7cddfSDavid du Colombier
4399a747e4fSDavid du Colombier s = v;
4407dd7cddfSDavid du Colombier sleep(750); /* remove window from screen after 3/4 of a second */
4417dd7cddfSDavid du Colombier sendp(deletechan, s);
4427dd7cddfSDavid du Colombier }
4437dd7cddfSDavid du Colombier
44480ee5cbfSDavid du Colombier /*
44580ee5cbfSDavid du Colombier * Button 6 - keyboard toggle - has been pressed.
44680ee5cbfSDavid du Colombier * Send event to keyboard, wait for button up, send that.
44780ee5cbfSDavid du Colombier * Note: there is no coordinate translation done here; this
44880ee5cbfSDavid du Colombier * is just about getting button 6 to the keyboard simulator.
44980ee5cbfSDavid du Colombier */
45080ee5cbfSDavid du Colombier void
keyboardhide(void)45180ee5cbfSDavid du Colombier keyboardhide(void)
45280ee5cbfSDavid du Colombier {
45380ee5cbfSDavid du Colombier send(wkeyboard->mc.c, mouse);
45480ee5cbfSDavid du Colombier do
45580ee5cbfSDavid du Colombier readmouse(mousectl);
45680ee5cbfSDavid du Colombier while(mouse->buttons & (1<<5));
45780ee5cbfSDavid du Colombier send(wkeyboard->mc.c, mouse);
45880ee5cbfSDavid du Colombier }
45980ee5cbfSDavid du Colombier
4607dd7cddfSDavid du Colombier void
mousethread(void *)4617dd7cddfSDavid du Colombier mousethread(void*)
4627dd7cddfSDavid du Colombier {
4637dd7cddfSDavid du Colombier int sending, inside, scrolling, moving, band;
46480ee5cbfSDavid du Colombier Window *oin, *w, *winput;
4657dd7cddfSDavid du Colombier Image *i;
4667dd7cddfSDavid du Colombier Rectangle r;
4677dd7cddfSDavid du Colombier Point xy;
4687dd7cddfSDavid du Colombier Mouse tmp;
4697dd7cddfSDavid du Colombier enum {
4707dd7cddfSDavid du Colombier MReshape,
4717dd7cddfSDavid du Colombier MMouse,
4727dd7cddfSDavid du Colombier NALT
4737dd7cddfSDavid du Colombier };
4747dd7cddfSDavid du Colombier static Alt alts[NALT+1];
4757dd7cddfSDavid du Colombier
47659cc4ca5SDavid du Colombier threadsetname("mousethread");
4777dd7cddfSDavid du Colombier sending = FALSE;
4787dd7cddfSDavid du Colombier scrolling = FALSE;
4797dd7cddfSDavid du Colombier moving = FALSE;
4807dd7cddfSDavid du Colombier
4817dd7cddfSDavid du Colombier alts[MReshape].c = mousectl->resizec;
4827dd7cddfSDavid du Colombier alts[MReshape].v = nil;
4837dd7cddfSDavid du Colombier alts[MReshape].op = CHANRCV;
4847dd7cddfSDavid du Colombier alts[MMouse].c = mousectl->c;
4857dd7cddfSDavid du Colombier alts[MMouse].v = &mousectl->Mouse;
4867dd7cddfSDavid du Colombier alts[MMouse].op = CHANRCV;
4877dd7cddfSDavid du Colombier alts[NALT].op = CHANEND;
4887dd7cddfSDavid du Colombier
4897dd7cddfSDavid du Colombier for(;;)
4907dd7cddfSDavid du Colombier switch(alt(alts)){
4917dd7cddfSDavid du Colombier case MReshape:
4927dd7cddfSDavid du Colombier resized();
4937dd7cddfSDavid du Colombier break;
4947dd7cddfSDavid du Colombier case MMouse:
49580ee5cbfSDavid du Colombier if(wkeyboard!=nil && (mouse->buttons & (1<<5))){
49680ee5cbfSDavid du Colombier keyboardhide();
49780ee5cbfSDavid du Colombier break;
49880ee5cbfSDavid du Colombier }
4997dd7cddfSDavid du Colombier Again:
50080ee5cbfSDavid du Colombier winput = input;
50180ee5cbfSDavid du Colombier /* override everything for the keyboard window */
50280ee5cbfSDavid du Colombier if(wkeyboard!=nil && ptinrect(mouse->xy, wkeyboard->screenr)){
50380ee5cbfSDavid du Colombier /* make sure it's on top; this call is free if it is */
50480ee5cbfSDavid du Colombier wtopme(wkeyboard);
50580ee5cbfSDavid du Colombier winput = wkeyboard;
50680ee5cbfSDavid du Colombier }
50780ee5cbfSDavid du Colombier if(winput!=nil && winput->i!=nil){
5087dd7cddfSDavid du Colombier /* convert to logical coordinates */
50980ee5cbfSDavid du Colombier xy.x = mouse->xy.x + (winput->i->r.min.x-winput->screenr.min.x);
51080ee5cbfSDavid du Colombier xy.y = mouse->xy.y + (winput->i->r.min.y-winput->screenr.min.y);
5119847521cSDavid du Colombier
5129847521cSDavid du Colombier /* the up and down scroll buttons are not subject to the usual rules */
5139847521cSDavid du Colombier if((mouse->buttons&(8|16)) && !winput->mouseopen)
5149847521cSDavid du Colombier goto Sending;
5159847521cSDavid du Colombier
51680ee5cbfSDavid du Colombier inside = ptinrect(mouse->xy, insetrect(winput->screenr, Selborder));
51780ee5cbfSDavid du Colombier if(winput->mouseopen)
5187dd7cddfSDavid du Colombier scrolling = FALSE;
5197dd7cddfSDavid du Colombier else if(scrolling)
5207dd7cddfSDavid du Colombier scrolling = mouse->buttons;
5217dd7cddfSDavid du Colombier else
52280ee5cbfSDavid du Colombier scrolling = mouse->buttons && ptinrect(xy, winput->scrollr);
52376f6a3b8SDavid du Colombier /* topped will be zero or less if window has been bottomed */
52480ee5cbfSDavid du Colombier if(sending == FALSE && !scrolling && winborder(winput, mouse->xy) && winput->topped>0){
5257dd7cddfSDavid du Colombier moving = TRUE;
52680ee5cbfSDavid du Colombier }else if(inside && (scrolling || winput->mouseopen || (mouse->buttons&1)))
5277dd7cddfSDavid du Colombier sending = TRUE;
5287dd7cddfSDavid du Colombier }else
5297dd7cddfSDavid du Colombier sending = FALSE;
5307dd7cddfSDavid du Colombier if(sending){
5319847521cSDavid du Colombier Sending:
5327dd7cddfSDavid du Colombier if(mouse->buttons == 0){
53380ee5cbfSDavid du Colombier cornercursor(winput, mouse->xy, 0);
5347dd7cddfSDavid du Colombier sending = FALSE;
5357dd7cddfSDavid du Colombier }else
53680ee5cbfSDavid du Colombier wsetcursor(winput, 0);
5377dd7cddfSDavid du Colombier tmp = mousectl->Mouse;
5387dd7cddfSDavid du Colombier tmp.xy = xy;
53980ee5cbfSDavid du Colombier send(winput->mc.c, &tmp);
5407dd7cddfSDavid du Colombier continue;
5417dd7cddfSDavid du Colombier }
5427dd7cddfSDavid du Colombier w = wpointto(mouse->xy);
5437dd7cddfSDavid du Colombier /* change cursor if over anyone's border */
5447dd7cddfSDavid du Colombier if(w != nil)
5457dd7cddfSDavid du Colombier cornercursor(w, mouse->xy, 0);
5467dd7cddfSDavid du Colombier else
5477dd7cddfSDavid du Colombier riosetcursor(nil, 0);
5487dd7cddfSDavid du Colombier if(moving && (mouse->buttons&7)){
54980ee5cbfSDavid du Colombier oin = winput;
5507dd7cddfSDavid du Colombier band = mouse->buttons & 3;
5517dd7cddfSDavid du Colombier sweeping = 1;
5527dd7cddfSDavid du Colombier if(band)
55380ee5cbfSDavid du Colombier i = bandsize(winput);
5547dd7cddfSDavid du Colombier else
55580ee5cbfSDavid du Colombier i = drag(winput, &r);
5567dd7cddfSDavid du Colombier sweeping = 0;
5577dd7cddfSDavid du Colombier if(i != nil){
55880ee5cbfSDavid du Colombier if(winput == oin){
5597dd7cddfSDavid du Colombier if(band)
56080ee5cbfSDavid du Colombier wsendctlmesg(winput, Reshaped, i->r, i);
5617dd7cddfSDavid du Colombier else
56280ee5cbfSDavid du Colombier wsendctlmesg(winput, Moved, r, i);
56380ee5cbfSDavid du Colombier cornercursor(winput, mouse->xy, 1);
5647dd7cddfSDavid du Colombier }else
5657dd7cddfSDavid du Colombier freeimage(i);
5667dd7cddfSDavid du Colombier }
5677dd7cddfSDavid du Colombier }
5687dd7cddfSDavid du Colombier if(w != nil)
5697dd7cddfSDavid du Colombier cornercursor(w, mouse->xy, 0);
5707dd7cddfSDavid du Colombier /* we're not sending the event, but if button is down maybe we should */
5717dd7cddfSDavid du Colombier if(mouse->buttons){
57276f6a3b8SDavid du Colombier /* w->topped will be zero or less if window has been bottomed */
57380ee5cbfSDavid du Colombier if(w==nil || (w==winput && w->topped>0)){
5749a747e4fSDavid du Colombier if(mouse->buttons & 1){
5757dd7cddfSDavid du Colombier ;
5769a747e4fSDavid du Colombier }else if(mouse->buttons & 2){
57780ee5cbfSDavid du Colombier if(winput && !winput->mouseopen)
57880ee5cbfSDavid du Colombier button2menu(winput);
5797dd7cddfSDavid du Colombier }else if(mouse->buttons & 4)
5807dd7cddfSDavid du Colombier button3menu();
5817dd7cddfSDavid du Colombier }else{
5827dd7cddfSDavid du Colombier /* if button 1 event in the window, top the window and wait for button up. */
5837dd7cddfSDavid du Colombier /* otherwise, top the window and pass the event on */
5847dd7cddfSDavid du Colombier if(wtop(mouse->xy) && (mouse->buttons!=1 || winborder(w, mouse->xy)))
5857dd7cddfSDavid du Colombier goto Again;
5867dd7cddfSDavid du Colombier goto Drain;
5877dd7cddfSDavid du Colombier }
5887dd7cddfSDavid du Colombier }
5897dd7cddfSDavid du Colombier moving = FALSE;
5907dd7cddfSDavid du Colombier break;
5917dd7cddfSDavid du Colombier
5927dd7cddfSDavid du Colombier Drain:
5937dd7cddfSDavid du Colombier do
5947dd7cddfSDavid du Colombier readmouse(mousectl);
5957dd7cddfSDavid du Colombier while(mousectl->buttons);
5967dd7cddfSDavid du Colombier moving = FALSE;
5977dd7cddfSDavid du Colombier goto Again; /* recalculate mouse position, cursor */
5987dd7cddfSDavid du Colombier }
5997dd7cddfSDavid du Colombier }
6007dd7cddfSDavid du Colombier
6017dd7cddfSDavid du Colombier void
resized(void)6027dd7cddfSDavid du Colombier resized(void)
6037dd7cddfSDavid du Colombier {
6047dd7cddfSDavid du Colombier Image *im;
6057dd7cddfSDavid du Colombier int i, j, ishidden;
6067dd7cddfSDavid du Colombier Rectangle r;
6077dd7cddfSDavid du Colombier Point o, n;
6087dd7cddfSDavid du Colombier Window *w;
6097dd7cddfSDavid du Colombier
6107dd7cddfSDavid du Colombier if(getwindow(display, Refnone) < 0)
6117dd7cddfSDavid du Colombier error("failed to re-attach window");
61259cc4ca5SDavid du Colombier freescrtemps();
6137dd7cddfSDavid du Colombier view = screen;
6147dd7cddfSDavid du Colombier freescreen(wscreen);
6157dd7cddfSDavid du Colombier wscreen = allocscreen(screen, background, 0);
6167dd7cddfSDavid du Colombier if(wscreen == nil)
6177dd7cddfSDavid du Colombier error("can't re-allocate screen");
6187dd7cddfSDavid du Colombier draw(view, view->r, background, nil, ZP);
6197dd7cddfSDavid du Colombier o = subpt(viewr.max, viewr.min);
6207dd7cddfSDavid du Colombier n = subpt(view->clipr.max, view->clipr.min);
6217dd7cddfSDavid du Colombier for(i=0; i<nwindow; i++){
6227dd7cddfSDavid du Colombier w = window[i];
6237dd7cddfSDavid du Colombier if(w->deleted)
6247dd7cddfSDavid du Colombier continue;
6257dd7cddfSDavid du Colombier r = rectsubpt(w->i->r, viewr.min);
6267dd7cddfSDavid du Colombier r.min.x = (r.min.x*n.x)/o.x;
6277dd7cddfSDavid du Colombier r.min.y = (r.min.y*n.y)/o.y;
6287dd7cddfSDavid du Colombier r.max.x = (r.max.x*n.x)/o.x;
6297dd7cddfSDavid du Colombier r.max.y = (r.max.y*n.y)/o.y;
6307dd7cddfSDavid du Colombier r = rectaddpt(r, screen->clipr.min);
6317dd7cddfSDavid du Colombier ishidden = 0;
6327dd7cddfSDavid du Colombier for(j=0; j<nhidden; j++)
6337dd7cddfSDavid du Colombier if(w == hidden[j]){
6347dd7cddfSDavid du Colombier ishidden = 1;
6357dd7cddfSDavid du Colombier break;
6367dd7cddfSDavid du Colombier }
637*666b04c8SDavid du Colombier if(ishidden){
6389a747e4fSDavid du Colombier im = allocimage(display, r, screen->chan, 0, DWhite);
639*666b04c8SDavid du Colombier r = ZR;
640*666b04c8SDavid du Colombier }else
6417dd7cddfSDavid du Colombier im = allocwindow(wscreen, r, Refbackup, DWhite);
6427dd7cddfSDavid du Colombier if(im)
6437dd7cddfSDavid du Colombier wsendctlmesg(w, Reshaped, r, im);
6447dd7cddfSDavid du Colombier }
6457dd7cddfSDavid du Colombier viewr = screen->r;
646e862f8a5SDavid du Colombier flushimage(display, 1);
647e862f8a5SDavid du Colombier }
6487dd7cddfSDavid du Colombier
6497dd7cddfSDavid du Colombier void
button3menu(void)6507dd7cddfSDavid du Colombier button3menu(void)
6517dd7cddfSDavid du Colombier {
6527dd7cddfSDavid du Colombier int i;
6537dd7cddfSDavid du Colombier
6547dd7cddfSDavid du Colombier for(i=0; i<nhidden; i++)
6557dd7cddfSDavid du Colombier menu3str[i+Hidden] = hidden[i]->label;
6567dd7cddfSDavid du Colombier menu3str[i+Hidden] = nil;
6577dd7cddfSDavid du Colombier
6587dd7cddfSDavid du Colombier sweeping = 1;
6597dd7cddfSDavid du Colombier switch(i = menuhit(3, mousectl, &menu3, wscreen)){
6607dd7cddfSDavid du Colombier case -1:
6617dd7cddfSDavid du Colombier break;
6627dd7cddfSDavid du Colombier case New:
6633ff48bf5SDavid du Colombier new(sweep(), FALSE, scrolling, 0, nil, "/bin/rc", nil);
6647dd7cddfSDavid du Colombier break;
6657dd7cddfSDavid du Colombier case Reshape:
6667dd7cddfSDavid du Colombier resize();
6677dd7cddfSDavid du Colombier break;
6687dd7cddfSDavid du Colombier case Move:
6697dd7cddfSDavid du Colombier move();
6707dd7cddfSDavid du Colombier break;
6717dd7cddfSDavid du Colombier case Delete:
6727dd7cddfSDavid du Colombier delete();
6737dd7cddfSDavid du Colombier break;
6747dd7cddfSDavid du Colombier case Hide:
6757dd7cddfSDavid du Colombier hide();
6767dd7cddfSDavid du Colombier break;
6777dd7cddfSDavid du Colombier case Exit:
6787dd7cddfSDavid du Colombier if(Hidden > Exit){
6797dd7cddfSDavid du Colombier send(exitchan, nil);
6807dd7cddfSDavid du Colombier break;
6817dd7cddfSDavid du Colombier }
6827dd7cddfSDavid du Colombier /* else fall through */
6837dd7cddfSDavid du Colombier default:
6847dd7cddfSDavid du Colombier unhide(i);
6857dd7cddfSDavid du Colombier break;
6867dd7cddfSDavid du Colombier }
6877dd7cddfSDavid du Colombier sweeping = 0;
6887dd7cddfSDavid du Colombier }
6897dd7cddfSDavid du Colombier
6907dd7cddfSDavid du Colombier void
button2menu(Window * w)6917dd7cddfSDavid du Colombier button2menu(Window *w)
6927dd7cddfSDavid du Colombier {
6937dd7cddfSDavid du Colombier if(w->deleted)
6947dd7cddfSDavid du Colombier return;
6957dd7cddfSDavid du Colombier incref(w);
6967dd7cddfSDavid du Colombier if(w->scrolling)
6977dd7cddfSDavid du Colombier menu2str[Scroll] = "noscroll";
6987dd7cddfSDavid du Colombier else
6997dd7cddfSDavid du Colombier menu2str[Scroll] = "scroll";
7007dd7cddfSDavid du Colombier switch(menuhit(2, mousectl, &menu2, wscreen)){
7017dd7cddfSDavid du Colombier case Cut:
7027dd7cddfSDavid du Colombier wsnarf(w);
7037dd7cddfSDavid du Colombier wcut(w);
7047dd7cddfSDavid du Colombier wscrdraw(w);
7057dd7cddfSDavid du Colombier break;
7067dd7cddfSDavid du Colombier
7077dd7cddfSDavid du Colombier case Snarf:
7087dd7cddfSDavid du Colombier wsnarf(w);
7097dd7cddfSDavid du Colombier break;
7107dd7cddfSDavid du Colombier
7117dd7cddfSDavid du Colombier case Paste:
7127dd7cddfSDavid du Colombier getsnarf();
7137dd7cddfSDavid du Colombier wpaste(w);
7147dd7cddfSDavid du Colombier wscrdraw(w);
7157dd7cddfSDavid du Colombier break;
7167dd7cddfSDavid du Colombier
7177dd7cddfSDavid du Colombier case Plumb:
7187dd7cddfSDavid du Colombier wplumb(w);
7197dd7cddfSDavid du Colombier break;
7207dd7cddfSDavid du Colombier
7217dd7cddfSDavid du Colombier case Send:
7227dd7cddfSDavid du Colombier getsnarf();
7237dd7cddfSDavid du Colombier wsnarf(w);
7247dd7cddfSDavid du Colombier if(nsnarf == 0)
7257dd7cddfSDavid du Colombier break;
7267dd7cddfSDavid du Colombier if(w->rawing){
7277dd7cddfSDavid du Colombier waddraw(w, snarf, nsnarf);
72859cc4ca5SDavid du Colombier if(snarf[nsnarf-1]!='\n' && snarf[nsnarf-1]!='\004')
7297dd7cddfSDavid du Colombier waddraw(w, L"\n", 1);
7307dd7cddfSDavid du Colombier }else{
7317dd7cddfSDavid du Colombier winsert(w, snarf, nsnarf, w->nr);
73259cc4ca5SDavid du Colombier if(snarf[nsnarf-1]!='\n' && snarf[nsnarf-1]!='\004')
7337dd7cddfSDavid du Colombier winsert(w, L"\n", 1, w->nr);
7347dd7cddfSDavid du Colombier }
7357dd7cddfSDavid du Colombier wsetselect(w, w->nr, w->nr);
7367dd7cddfSDavid du Colombier wshow(w, w->nr);
7377dd7cddfSDavid du Colombier break;
7387dd7cddfSDavid du Colombier
7397dd7cddfSDavid du Colombier case Scroll:
7407dd7cddfSDavid du Colombier if(w->scrolling ^= 1)
7417dd7cddfSDavid du Colombier wshow(w, w->nr);
7427dd7cddfSDavid du Colombier break;
7437dd7cddfSDavid du Colombier }
7447dd7cddfSDavid du Colombier wclose(w);
7457dd7cddfSDavid du Colombier wsendctlmesg(w, Wakeup, ZR, nil);
7467dd7cddfSDavid du Colombier flushimage(display, 1);
7477dd7cddfSDavid du Colombier }
7487dd7cddfSDavid du Colombier
7497dd7cddfSDavid du Colombier Point
onscreen(Point p)7507dd7cddfSDavid du Colombier onscreen(Point p)
7517dd7cddfSDavid du Colombier {
7527dd7cddfSDavid du Colombier p.x = max(screen->clipr.min.x, p.x);
7537dd7cddfSDavid du Colombier p.x = min(screen->clipr.max.x, p.x);
7547dd7cddfSDavid du Colombier p.y = max(screen->clipr.min.y, p.y);
7557dd7cddfSDavid du Colombier p.y = min(screen->clipr.max.y, p.y);
7567dd7cddfSDavid du Colombier return p;
7577dd7cddfSDavid du Colombier }
7587dd7cddfSDavid du Colombier
7597dd7cddfSDavid du Colombier Image*
sweep(void)7607dd7cddfSDavid du Colombier sweep(void)
7617dd7cddfSDavid du Colombier {
7627dd7cddfSDavid du Colombier Image *i, *oi;
7637dd7cddfSDavid du Colombier Rectangle r;
7647dd7cddfSDavid du Colombier Point p0, p;
7657dd7cddfSDavid du Colombier
7667dd7cddfSDavid du Colombier i = nil;
76759cc4ca5SDavid du Colombier menuing = TRUE;
7687dd7cddfSDavid du Colombier riosetcursor(&crosscursor, 1);
7697dd7cddfSDavid du Colombier while(mouse->buttons == 0)
7707dd7cddfSDavid du Colombier readmouse(mousectl);
7717dd7cddfSDavid du Colombier p0 = onscreen(mouse->xy);
7727dd7cddfSDavid du Colombier p = p0;
7737dd7cddfSDavid du Colombier r.min = p;
7747dd7cddfSDavid du Colombier r.max = p;
7757dd7cddfSDavid du Colombier oi = nil;
7767dd7cddfSDavid du Colombier while(mouse->buttons == 4){
7777dd7cddfSDavid du Colombier readmouse(mousectl);
7787dd7cddfSDavid du Colombier if(mouse->buttons != 4 && mouse->buttons != 0)
7797dd7cddfSDavid du Colombier break;
7807dd7cddfSDavid du Colombier if(!eqpt(mouse->xy, p)){
7817dd7cddfSDavid du Colombier p = onscreen(mouse->xy);
7827dd7cddfSDavid du Colombier r = canonrect(Rpt(p0, p));
7837dd7cddfSDavid du Colombier if(Dx(r)>5 && Dy(r)>5){
7847dd7cddfSDavid du Colombier i = allocwindow(wscreen, r, Refnone, 0xEEEEEEFF); /* grey */
7857dd7cddfSDavid du Colombier freeimage(oi);
7867dd7cddfSDavid du Colombier if(i == nil)
7877dd7cddfSDavid du Colombier goto Rescue;
7887dd7cddfSDavid du Colombier oi = i;
7897dd7cddfSDavid du Colombier border(i, r, Selborder, red, ZP);
7907dd7cddfSDavid du Colombier flushimage(display, 1);
7917dd7cddfSDavid du Colombier }
7927dd7cddfSDavid du Colombier }
7937dd7cddfSDavid du Colombier }
7947dd7cddfSDavid du Colombier if(mouse->buttons != 0)
7957dd7cddfSDavid du Colombier goto Rescue;
7967dd7cddfSDavid du Colombier if(i==nil || Dx(i->r)<100 || Dy(i->r)<3*font->height)
7977dd7cddfSDavid du Colombier goto Rescue;
7987dd7cddfSDavid du Colombier oi = i;
7997dd7cddfSDavid du Colombier i = allocwindow(wscreen, oi->r, Refbackup, DWhite);
8007dd7cddfSDavid du Colombier freeimage(oi);
8017dd7cddfSDavid du Colombier if(i == nil)
8027dd7cddfSDavid du Colombier goto Rescue;
8037dd7cddfSDavid du Colombier border(i, r, Selborder, red, ZP);
8047dd7cddfSDavid du Colombier cornercursor(input, mouse->xy, 1);
80559cc4ca5SDavid du Colombier goto Return;
8067dd7cddfSDavid du Colombier
8077dd7cddfSDavid du Colombier Rescue:
8087dd7cddfSDavid du Colombier freeimage(i);
80959cc4ca5SDavid du Colombier i = nil;
8107dd7cddfSDavid du Colombier cornercursor(input, mouse->xy, 1);
8117dd7cddfSDavid du Colombier while(mouse->buttons)
8127dd7cddfSDavid du Colombier readmouse(mousectl);
81359cc4ca5SDavid du Colombier
81459cc4ca5SDavid du Colombier Return:
81559cc4ca5SDavid du Colombier moveto(mousectl, mouse->xy); /* force cursor update; ugly */
81659cc4ca5SDavid du Colombier menuing = FALSE;
81759cc4ca5SDavid du Colombier return i;
8187dd7cddfSDavid du Colombier }
8197dd7cddfSDavid du Colombier
82015b88db3SDavid du Colombier void
drawedge(Image ** bp,Rectangle r)82115b88db3SDavid du Colombier drawedge(Image **bp, Rectangle r)
82215b88db3SDavid du Colombier {
82315b88db3SDavid du Colombier Image *b = *bp;
82415b88db3SDavid du Colombier if(b != nil && Dx(b->r) == Dx(r) && Dy(b->r) == Dy(r))
82515b88db3SDavid du Colombier originwindow(b, r.min, r.min);
82615b88db3SDavid du Colombier else{
82715b88db3SDavid du Colombier freeimage(b);
82815b88db3SDavid du Colombier *bp = allocwindow(wscreen, r, Refbackup, DRed);
82915b88db3SDavid du Colombier }
83015b88db3SDavid du Colombier }
83115b88db3SDavid du Colombier
83215b88db3SDavid du Colombier void
drawborder(Rectangle r,int show)83315b88db3SDavid du Colombier drawborder(Rectangle r, int show)
83415b88db3SDavid du Colombier {
83515b88db3SDavid du Colombier static Image *b[4];
83615b88db3SDavid du Colombier int i;
83715b88db3SDavid du Colombier if(show == 0){
83815b88db3SDavid du Colombier for(i = 0; i < 4; i++){
83915b88db3SDavid du Colombier freeimage(b[i]);
84015b88db3SDavid du Colombier b[i] = nil;
84115b88db3SDavid du Colombier }
84215b88db3SDavid du Colombier }else{
84315b88db3SDavid du Colombier r = canonrect(r);
84415b88db3SDavid du Colombier drawedge(&b[0], Rect(r.min.x, r.min.y, r.min.x+Borderwidth, r.max.y));
84515b88db3SDavid du Colombier drawedge(&b[1], Rect(r.min.x+Borderwidth, r.min.y, r.max.x-Borderwidth, r.min.y+Borderwidth));
84615b88db3SDavid du Colombier drawedge(&b[2], Rect(r.max.x-Borderwidth, r.min.y, r.max.x, r.max.y));
84715b88db3SDavid du Colombier drawedge(&b[3], Rect(r.min.x+Borderwidth, r.max.y-Borderwidth, r.max.x-Borderwidth, r.max.y));
84815b88db3SDavid du Colombier }
84915b88db3SDavid du Colombier }
85015b88db3SDavid du Colombier
8517dd7cddfSDavid du Colombier Image*
drag(Window * w,Rectangle * rp)8527dd7cddfSDavid du Colombier drag(Window *w, Rectangle *rp)
8537dd7cddfSDavid du Colombier {
8547dd7cddfSDavid du Colombier Image *i, *ni;
8557dd7cddfSDavid du Colombier Point p, op, d, dm, om;
8567dd7cddfSDavid du Colombier Rectangle r;
8577dd7cddfSDavid du Colombier
8587dd7cddfSDavid du Colombier i = w->i;
85959cc4ca5SDavid du Colombier menuing = TRUE;
8607dd7cddfSDavid du Colombier om = mouse->xy;
8617dd7cddfSDavid du Colombier riosetcursor(&boxcursor, 1);
8627dd7cddfSDavid du Colombier dm = subpt(mouse->xy, w->screenr.min);
8637dd7cddfSDavid du Colombier d = subpt(i->r.max, i->r.min);
8647dd7cddfSDavid du Colombier op = subpt(mouse->xy, dm);
86515b88db3SDavid du Colombier drawborder(Rect(op.x, op.y, op.x+d.x, op.y+d.y), 1);
8667dd7cddfSDavid du Colombier flushimage(display, 1);
8677dd7cddfSDavid du Colombier while(mouse->buttons == 4){
8687dd7cddfSDavid du Colombier p = subpt(mouse->xy, dm);
8697dd7cddfSDavid du Colombier if(!eqpt(p, op)){
87015b88db3SDavid du Colombier drawborder(Rect(p.x, p.y, p.x+d.x, p.y+d.y), 1);
8717dd7cddfSDavid du Colombier flushimage(display, 1);
8727dd7cddfSDavid du Colombier op = p;
8737dd7cddfSDavid du Colombier }
8747dd7cddfSDavid du Colombier readmouse(mousectl);
8757dd7cddfSDavid du Colombier }
8767dd7cddfSDavid du Colombier r = Rect(op.x, op.y, op.x+d.x, op.y+d.y);
87715b88db3SDavid du Colombier drawborder(r, 0);
87880ee5cbfSDavid du Colombier cornercursor(w, mouse->xy, 1);
87959cc4ca5SDavid du Colombier moveto(mousectl, mouse->xy); /* force cursor update; ugly */
88059cc4ca5SDavid du Colombier menuing = FALSE;
8817dd7cddfSDavid du Colombier flushimage(display, 1);
8827dd7cddfSDavid du Colombier if(mouse->buttons!=0 || (ni=allocwindow(wscreen, r, Refbackup, DWhite))==nil){
8837dd7cddfSDavid du Colombier moveto(mousectl, om);
8847dd7cddfSDavid du Colombier while(mouse->buttons)
8857dd7cddfSDavid du Colombier readmouse(mousectl);
8867dd7cddfSDavid du Colombier *rp = Rect(0, 0, 0, 0);
8877dd7cddfSDavid du Colombier return nil;
8887dd7cddfSDavid du Colombier }
8897dd7cddfSDavid du Colombier draw(ni, ni->r, i, nil, i->r.min);
8907dd7cddfSDavid du Colombier *rp = r;
8917dd7cddfSDavid du Colombier return ni;
8927dd7cddfSDavid du Colombier }
8937dd7cddfSDavid du Colombier
894ea15f0ccSDavid du Colombier Point
cornerpt(Rectangle r,Point p,int which)895ea15f0ccSDavid du Colombier cornerpt(Rectangle r, Point p, int which)
896ea15f0ccSDavid du Colombier {
897ea15f0ccSDavid du Colombier switch(which){
898ea15f0ccSDavid du Colombier case 0: /* top left */
899ea15f0ccSDavid du Colombier p = Pt(r.min.x, r.min.y);
900ea15f0ccSDavid du Colombier break;
901ea15f0ccSDavid du Colombier case 2: /* top right */
902ea15f0ccSDavid du Colombier p = Pt(r.max.x,r.min.y);
903ea15f0ccSDavid du Colombier break;
904ea15f0ccSDavid du Colombier case 6: /* bottom left */
905ea15f0ccSDavid du Colombier p = Pt(r.min.x, r.max.y);
906ea15f0ccSDavid du Colombier break;
907ea15f0ccSDavid du Colombier case 8: /* bottom right */
908ea15f0ccSDavid du Colombier p = Pt(r.max.x, r.max.y);
909ea15f0ccSDavid du Colombier break;
910ea15f0ccSDavid du Colombier case 1: /* top edge */
911ea15f0ccSDavid du Colombier p = Pt(p.x,r.min.y);
912ea15f0ccSDavid du Colombier break;
913ea15f0ccSDavid du Colombier case 5: /* right edge */
914ea15f0ccSDavid du Colombier p = Pt(r.max.x, p.y);
915ea15f0ccSDavid du Colombier break;
916ea15f0ccSDavid du Colombier case 7: /* bottom edge */
917ea15f0ccSDavid du Colombier p = Pt(p.x, r.max.y);
918ea15f0ccSDavid du Colombier break;
919ea15f0ccSDavid du Colombier case 3: /* left edge */
920ea15f0ccSDavid du Colombier p = Pt(r.min.x, p.y);
921ea15f0ccSDavid du Colombier break;
922ea15f0ccSDavid du Colombier }
923ea15f0ccSDavid du Colombier return p;
924ea15f0ccSDavid du Colombier }
925ea15f0ccSDavid du Colombier
9267dd7cddfSDavid du Colombier Rectangle
whichrect(Rectangle r,Point p,int which)9277dd7cddfSDavid du Colombier whichrect(Rectangle r, Point p, int which)
9287dd7cddfSDavid du Colombier {
9297dd7cddfSDavid du Colombier switch(which){
9307dd7cddfSDavid du Colombier case 0: /* top left */
9317dd7cddfSDavid du Colombier r = Rect(p.x, p.y, r.max.x, r.max.y);
9327dd7cddfSDavid du Colombier break;
9337dd7cddfSDavid du Colombier case 2: /* top right */
9347dd7cddfSDavid du Colombier r = Rect(r.min.x, p.y, p.x, r.max.y);
9357dd7cddfSDavid du Colombier break;
9367dd7cddfSDavid du Colombier case 6: /* bottom left */
9377dd7cddfSDavid du Colombier r = Rect(p.x, r.min.y, r.max.x, p.y);
9387dd7cddfSDavid du Colombier break;
9397dd7cddfSDavid du Colombier case 8: /* bottom right */
9407dd7cddfSDavid du Colombier r = Rect(r.min.x, r.min.y, p.x, p.y);
9417dd7cddfSDavid du Colombier break;
9427dd7cddfSDavid du Colombier case 1: /* top edge */
9437dd7cddfSDavid du Colombier r = Rect(r.min.x, p.y, r.max.x, r.max.y);
9447dd7cddfSDavid du Colombier break;
9457dd7cddfSDavid du Colombier case 5: /* right edge */
9467dd7cddfSDavid du Colombier r = Rect(r.min.x, r.min.y, p.x, r.max.y);
9477dd7cddfSDavid du Colombier break;
9487dd7cddfSDavid du Colombier case 7: /* bottom edge */
9497dd7cddfSDavid du Colombier r = Rect(r.min.x, r.min.y, r.max.x, p.y);
9507dd7cddfSDavid du Colombier break;
9517dd7cddfSDavid du Colombier case 3: /* left edge */
9527dd7cddfSDavid du Colombier r = Rect(p.x, r.min.y, r.max.x, r.max.y);
9537dd7cddfSDavid du Colombier break;
9547dd7cddfSDavid du Colombier }
9557dd7cddfSDavid du Colombier return canonrect(r);
9567dd7cddfSDavid du Colombier }
9577dd7cddfSDavid du Colombier
9587dd7cddfSDavid du Colombier Image*
bandsize(Window * w)9597dd7cddfSDavid du Colombier bandsize(Window *w)
9607dd7cddfSDavid du Colombier {
9617dd7cddfSDavid du Colombier Image *i;
9627dd7cddfSDavid du Colombier Rectangle r, or;
9637dd7cddfSDavid du Colombier Point p, startp;
9647dd7cddfSDavid du Colombier int which, but;
9657dd7cddfSDavid du Colombier
9667dd7cddfSDavid du Colombier p = mouse->xy;
967314a20f0SDavid du Colombier but = mouse->buttons;
9687dd7cddfSDavid du Colombier which = whichcorner(w, p);
96950e5f38dSDavid du Colombier p = cornerpt(w->screenr, p, which);
97050e5f38dSDavid du Colombier wmovemouse(w, p);
971ea15f0ccSDavid du Colombier readmouse(mousectl);
9727dd7cddfSDavid du Colombier r = whichrect(w->screenr, p, which);
97315b88db3SDavid du Colombier drawborder(r, 1);
9747dd7cddfSDavid du Colombier or = r;
97550e5f38dSDavid du Colombier startp = p;
976314a20f0SDavid du Colombier
9777dd7cddfSDavid du Colombier while(mouse->buttons == but){
9787dd7cddfSDavid du Colombier p = onscreen(mouse->xy);
9797dd7cddfSDavid du Colombier r = whichrect(w->screenr, p, which);
98059cc4ca5SDavid du Colombier if(!eqrect(r, or) && goodrect(r)){
98115b88db3SDavid du Colombier drawborder(r, 1);
9827dd7cddfSDavid du Colombier flushimage(display, 1);
9837dd7cddfSDavid du Colombier or = r;
9847dd7cddfSDavid du Colombier }
9857dd7cddfSDavid du Colombier readmouse(mousectl);
9867dd7cddfSDavid du Colombier }
9877dd7cddfSDavid du Colombier p = mouse->xy;
98815b88db3SDavid du Colombier drawborder(or, 0);
9897dd7cddfSDavid du Colombier flushimage(display, 1);
99080ee5cbfSDavid du Colombier wsetcursor(w, 1);
9917dd7cddfSDavid du Colombier if(mouse->buttons!=0 || Dx(or)<100 || Dy(or)<3*font->height){
9927dd7cddfSDavid du Colombier while(mouse->buttons)
9937dd7cddfSDavid du Colombier readmouse(mousectl);
9947dd7cddfSDavid du Colombier return nil;
9957dd7cddfSDavid du Colombier }
9967dd7cddfSDavid du Colombier if(abs(p.x-startp.x)+abs(p.y-startp.y) <= 1)
9977dd7cddfSDavid du Colombier return nil;
9987dd7cddfSDavid du Colombier i = allocwindow(wscreen, or, Refbackup, DWhite);
9997dd7cddfSDavid du Colombier if(i == nil)
10007dd7cddfSDavid du Colombier return nil;
10017dd7cddfSDavid du Colombier border(i, r, Selborder, red, ZP);
10027dd7cddfSDavid du Colombier return i;
10037dd7cddfSDavid du Colombier }
10047dd7cddfSDavid du Colombier
10057dd7cddfSDavid du Colombier Window*
pointto(int wait)10067dd7cddfSDavid du Colombier pointto(int wait)
10077dd7cddfSDavid du Colombier {
10087dd7cddfSDavid du Colombier Window *w;
10097dd7cddfSDavid du Colombier
101059cc4ca5SDavid du Colombier menuing = TRUE;
10117dd7cddfSDavid du Colombier riosetcursor(&sightcursor, 1);
10127dd7cddfSDavid du Colombier while(mouse->buttons == 0)
10137dd7cddfSDavid du Colombier readmouse(mousectl);
10147dd7cddfSDavid du Colombier if(mouse->buttons == 4)
10157dd7cddfSDavid du Colombier w = wpointto(mouse->xy);
10167dd7cddfSDavid du Colombier else
10177dd7cddfSDavid du Colombier w = nil;
101861e02cf5SDavid du Colombier if(wait){
101914414594SDavid du Colombier while(mouse->buttons){
102014414594SDavid du Colombier if(mouse->buttons!=4 && w !=nil){ /* cancel */
102114414594SDavid du Colombier cornercursor(input, mouse->xy, 0);
102214414594SDavid du Colombier w = nil;
102314414594SDavid du Colombier }
10247dd7cddfSDavid du Colombier readmouse(mousectl);
102514414594SDavid du Colombier }
102661e02cf5SDavid du Colombier if(w != nil && wpointto(mouse->xy) != w)
102761e02cf5SDavid du Colombier w = nil;
102861e02cf5SDavid du Colombier }
10297dd7cddfSDavid du Colombier cornercursor(input, mouse->xy, 0);
103059cc4ca5SDavid du Colombier moveto(mousectl, mouse->xy); /* force cursor update; ugly */
103159cc4ca5SDavid du Colombier menuing = FALSE;
10327dd7cddfSDavid du Colombier return w;
10337dd7cddfSDavid du Colombier }
10347dd7cddfSDavid du Colombier
10357dd7cddfSDavid du Colombier void
delete(void)10367dd7cddfSDavid du Colombier delete(void)
10377dd7cddfSDavid du Colombier {
10387dd7cddfSDavid du Colombier Window *w;
10397dd7cddfSDavid du Colombier
10407dd7cddfSDavid du Colombier w = pointto(TRUE);
10417dd7cddfSDavid du Colombier if(w)
10427dd7cddfSDavid du Colombier wsendctlmesg(w, Deleted, ZR, nil);
10437dd7cddfSDavid du Colombier }
10447dd7cddfSDavid du Colombier
10457dd7cddfSDavid du Colombier void
resize(void)10467dd7cddfSDavid du Colombier resize(void)
10477dd7cddfSDavid du Colombier {
10487dd7cddfSDavid du Colombier Window *w;
10497dd7cddfSDavid du Colombier Image *i;
10507dd7cddfSDavid du Colombier
10517dd7cddfSDavid du Colombier w = pointto(TRUE);
10527dd7cddfSDavid du Colombier if(w == nil)
10537dd7cddfSDavid du Colombier return;
10547dd7cddfSDavid du Colombier i = sweep();
10557dd7cddfSDavid du Colombier if(i)
10567dd7cddfSDavid du Colombier wsendctlmesg(w, Reshaped, i->r, i);
10577dd7cddfSDavid du Colombier }
10587dd7cddfSDavid du Colombier
10597dd7cddfSDavid du Colombier void
move(void)10607dd7cddfSDavid du Colombier move(void)
10617dd7cddfSDavid du Colombier {
10627dd7cddfSDavid du Colombier Window *w;
10637dd7cddfSDavid du Colombier Image *i;
10647dd7cddfSDavid du Colombier Rectangle r;
10657dd7cddfSDavid du Colombier
10667dd7cddfSDavid du Colombier w = pointto(FALSE);
10677dd7cddfSDavid du Colombier if(w == nil)
10687dd7cddfSDavid du Colombier return;
10697dd7cddfSDavid du Colombier i = drag(w, &r);
10707dd7cddfSDavid du Colombier if(i)
10717dd7cddfSDavid du Colombier wsendctlmesg(w, Moved, r, i);
10727dd7cddfSDavid du Colombier cornercursor(input, mouse->xy, 1);
10737dd7cddfSDavid du Colombier }
10747dd7cddfSDavid du Colombier
107580ee5cbfSDavid du Colombier int
whide(Window * w)107680ee5cbfSDavid du Colombier whide(Window *w)
10777dd7cddfSDavid du Colombier {
10787dd7cddfSDavid du Colombier Image *i;
107980ee5cbfSDavid du Colombier int j;
10807dd7cddfSDavid du Colombier
108180ee5cbfSDavid du Colombier for(j=0; j<nhidden; j++)
108280ee5cbfSDavid du Colombier if(hidden[j] == w) /* already hidden */
108380ee5cbfSDavid du Colombier return -1;
10847dd7cddfSDavid du Colombier i = allocimage(display, w->screenr, w->i->chan, 0, DWhite);
10857dd7cddfSDavid du Colombier if(i){
10867dd7cddfSDavid du Colombier hidden[nhidden++] = w;
10877dd7cddfSDavid du Colombier wsendctlmesg(w, Reshaped, ZR, i);
108880ee5cbfSDavid du Colombier return 1;
10897dd7cddfSDavid du Colombier }
109080ee5cbfSDavid du Colombier return 0;
109180ee5cbfSDavid du Colombier }
109280ee5cbfSDavid du Colombier
109380ee5cbfSDavid du Colombier int
wunhide(int h)109480ee5cbfSDavid du Colombier wunhide(int h)
109580ee5cbfSDavid du Colombier {
109680ee5cbfSDavid du Colombier Image *i;
109780ee5cbfSDavid du Colombier Window *w;
109880ee5cbfSDavid du Colombier
109980ee5cbfSDavid du Colombier w = hidden[h];
110080ee5cbfSDavid du Colombier i = allocwindow(wscreen, w->i->r, Refbackup, DWhite);
110180ee5cbfSDavid du Colombier if(i){
110280ee5cbfSDavid du Colombier --nhidden;
110380ee5cbfSDavid du Colombier memmove(hidden+h, hidden+h+1, (nhidden-h)*sizeof(Window*));
110480ee5cbfSDavid du Colombier wsendctlmesg(w, Reshaped, w->i->r, i);
110580ee5cbfSDavid du Colombier return 1;
110680ee5cbfSDavid du Colombier }
110780ee5cbfSDavid du Colombier return 0;
110880ee5cbfSDavid du Colombier }
110980ee5cbfSDavid du Colombier
111080ee5cbfSDavid du Colombier void
hide(void)111180ee5cbfSDavid du Colombier hide(void)
111280ee5cbfSDavid du Colombier {
111380ee5cbfSDavid du Colombier Window *w;
111480ee5cbfSDavid du Colombier
111580ee5cbfSDavid du Colombier w = pointto(TRUE);
111680ee5cbfSDavid du Colombier if(w == nil)
111780ee5cbfSDavid du Colombier return;
111880ee5cbfSDavid du Colombier whide(w);
11197dd7cddfSDavid du Colombier }
11207dd7cddfSDavid du Colombier
11217dd7cddfSDavid du Colombier void
unhide(int h)11227dd7cddfSDavid du Colombier unhide(int h)
11237dd7cddfSDavid du Colombier {
11247dd7cddfSDavid du Colombier Window *w;
11257dd7cddfSDavid du Colombier
11267dd7cddfSDavid du Colombier h -= Hidden;
11277dd7cddfSDavid du Colombier w = hidden[h];
11287dd7cddfSDavid du Colombier if(w == nil)
11297dd7cddfSDavid du Colombier return;
113080ee5cbfSDavid du Colombier wunhide(h);
11317dd7cddfSDavid du Colombier }
11327dd7cddfSDavid du Colombier
11337dd7cddfSDavid du Colombier Window*
new(Image * i,int hideit,int scrollit,int pid,char * dir,char * cmd,char ** argv)11343ff48bf5SDavid du Colombier new(Image *i, int hideit, int scrollit, int pid, char *dir, char *cmd, char **argv)
11357dd7cddfSDavid du Colombier {
11367dd7cddfSDavid du Colombier Window *w;
11377dd7cddfSDavid du Colombier Mousectl *mc;
11387dd7cddfSDavid du Colombier Channel *cm, *ck, *cctl, *cpid;
11397dd7cddfSDavid du Colombier void **arg;
11407dd7cddfSDavid du Colombier
11417dd7cddfSDavid du Colombier if(i == nil)
11427dd7cddfSDavid du Colombier return nil;
11437dd7cddfSDavid du Colombier cm = chancreate(sizeof(Mouse), 0);
11447dd7cddfSDavid du Colombier ck = chancreate(sizeof(Rune*), 0);
11457dd7cddfSDavid du Colombier cctl = chancreate(sizeof(Wctlmesg), 4);
11467dd7cddfSDavid du Colombier cpid = chancreate(sizeof(int), 0);
11477dd7cddfSDavid du Colombier if(cm==nil || ck==nil || cctl==nil)
11487dd7cddfSDavid du Colombier error("new: channel alloc failed");
11497dd7cddfSDavid du Colombier mc = emalloc(sizeof(Mousectl));
11507dd7cddfSDavid du Colombier *mc = *mousectl;
11517dd7cddfSDavid du Colombier mc->image = i;
11527dd7cddfSDavid du Colombier mc->c = cm;
11533ff48bf5SDavid du Colombier w = wmk(i, mc, ck, cctl, scrollit);
115459cc4ca5SDavid du Colombier free(mc); /* wmk copies *mc */
11557dd7cddfSDavid du Colombier window = erealloc(window, ++nwindow*sizeof(Window*));
11567dd7cddfSDavid du Colombier window[nwindow-1] = w;
11579a747e4fSDavid du Colombier if(hideit){
11589a747e4fSDavid du Colombier hidden[nhidden++] = w;
11599a747e4fSDavid du Colombier w->screenr = ZR;
11609a747e4fSDavid du Colombier }
11617dd7cddfSDavid du Colombier threadcreate(winctl, w, 8192);
11629a747e4fSDavid du Colombier if(!hideit)
11637dd7cddfSDavid du Colombier wcurrent(w);
11647dd7cddfSDavid du Colombier flushimage(display, 1);
11657dd7cddfSDavid du Colombier if(pid == 0){
11667dd7cddfSDavid du Colombier arg = emalloc(5*sizeof(void*));
11677dd7cddfSDavid du Colombier arg[0] = w;
11687dd7cddfSDavid du Colombier arg[1] = cpid;
11697dd7cddfSDavid du Colombier arg[2] = cmd;
11707dd7cddfSDavid du Colombier if(argv == nil)
11717dd7cddfSDavid du Colombier arg[3] = rcargv;
11727dd7cddfSDavid du Colombier else
11737dd7cddfSDavid du Colombier arg[3] = argv;
11747dd7cddfSDavid du Colombier arg[4] = dir;
11757dd7cddfSDavid du Colombier proccreate(winshell, arg, 8192);
11767dd7cddfSDavid du Colombier pid = recvul(cpid);
11777dd7cddfSDavid du Colombier free(arg);
11787dd7cddfSDavid du Colombier }
117980ee5cbfSDavid du Colombier if(pid == 0){
118080ee5cbfSDavid du Colombier /* window creation failed */
118180ee5cbfSDavid du Colombier wsendctlmesg(w, Deleted, ZR, nil);
118280ee5cbfSDavid du Colombier chanfree(cpid);
118380ee5cbfSDavid du Colombier return nil;
118480ee5cbfSDavid du Colombier }
11859a747e4fSDavid du Colombier wsetpid(w, pid, 1);
11867dd7cddfSDavid du Colombier wsetname(w);
1187ce941d97SDavid du Colombier if(dir)
1188ce941d97SDavid du Colombier w->dir = estrdup(dir);
118959cc4ca5SDavid du Colombier chanfree(cpid);
11907dd7cddfSDavid du Colombier return w;
11917dd7cddfSDavid du Colombier }
1192