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" 1359cc4ca5SDavid du Colombier /* for generating syms in mkfile only: */ 1459cc4ca5SDavid du Colombier #include <bio.h> 1559cc4ca5SDavid du Colombier #include "edit.h" 167dd7cddfSDavid du Colombier 177dd7cddfSDavid du Colombier void mousethread(void*); 187dd7cddfSDavid du Colombier void keyboardthread(void*); 197dd7cddfSDavid du Colombier void waitthread(void*); 207dd7cddfSDavid du Colombier void xfidallocthread(void*); 219a747e4fSDavid du Colombier void newwindowthread(void*); 227dd7cddfSDavid du Colombier void plumbproc(void*); 237dd7cddfSDavid du Colombier 247dd7cddfSDavid du Colombier Reffont **fontcache; 257dd7cddfSDavid du Colombier int nfontcache; 267dd7cddfSDavid du Colombier char wdir[512] = "."; 277dd7cddfSDavid du Colombier Reffont *reffonts[2]; 287dd7cddfSDavid du Colombier int snarffd = -1; 297dd7cddfSDavid du Colombier int mainpid; 307dd7cddfSDavid du Colombier int plumbsendfd; 317dd7cddfSDavid du Colombier int plumbeditfd; 327dd7cddfSDavid du Colombier 337dd7cddfSDavid du Colombier enum{ 347dd7cddfSDavid du Colombier NSnarf = 1000 /* less than 1024, I/O buffer size */ 357dd7cddfSDavid du Colombier }; 367dd7cddfSDavid du Colombier Rune snarfrune[NSnarf+1]; 377dd7cddfSDavid du Colombier 387dd7cddfSDavid du Colombier char *fontnames[2] = 397dd7cddfSDavid du Colombier { 407dd7cddfSDavid du Colombier "/lib/font/bit/lucidasans/euro.8.font", 417dd7cddfSDavid du Colombier "/lib/font/bit/lucm/unicode.9.font", 427dd7cddfSDavid du Colombier }; 437dd7cddfSDavid du Colombier 447dd7cddfSDavid du Colombier Command *command; 457dd7cddfSDavid du Colombier 467dd7cddfSDavid du Colombier void acmeerrorinit(void); 477dd7cddfSDavid du Colombier void readfile(Column*, char*); 487dd7cddfSDavid du Colombier int shutdown(void*, char*); 497dd7cddfSDavid du Colombier 507dd7cddfSDavid du Colombier void 517dd7cddfSDavid du Colombier derror(Display*, char *errorstr) 527dd7cddfSDavid du Colombier { 537dd7cddfSDavid du Colombier error(errorstr); 547dd7cddfSDavid du Colombier } 557dd7cddfSDavid du Colombier 567dd7cddfSDavid du Colombier void 577dd7cddfSDavid du Colombier threadmain(int argc, char *argv[]) 587dd7cddfSDavid du Colombier { 597dd7cddfSDavid du Colombier int i; 607dd7cddfSDavid du Colombier char *p, *loadfile; 617dd7cddfSDavid du Colombier char buf[256]; 627dd7cddfSDavid du Colombier Column *c; 637dd7cddfSDavid du Colombier int ncol; 647dd7cddfSDavid du Colombier Display *d; 657dd7cddfSDavid du Colombier static void *arg[1]; 667dd7cddfSDavid du Colombier 6780ee5cbfSDavid du Colombier rfork(RFENVG|RFNAMEG); 6880ee5cbfSDavid du Colombier 697dd7cddfSDavid du Colombier ncol = -1; 707dd7cddfSDavid du Colombier 717dd7cddfSDavid du Colombier loadfile = nil; 727dd7cddfSDavid du Colombier ARGBEGIN{ 73*4fec87e5SDavid du Colombier case 'a': 74*4fec87e5SDavid du Colombier globalautoindent = TRUE; 75*4fec87e5SDavid du Colombier break; 767dd7cddfSDavid du Colombier case 'b': 777dd7cddfSDavid du Colombier bartflag = TRUE; 787dd7cddfSDavid du Colombier break; 797dd7cddfSDavid du Colombier case 'c': 807dd7cddfSDavid du Colombier p = ARGF(); 817dd7cddfSDavid du Colombier if(p == nil) 827dd7cddfSDavid du Colombier goto Usage; 837dd7cddfSDavid du Colombier ncol = atoi(p); 847dd7cddfSDavid du Colombier if(ncol <= 0) 857dd7cddfSDavid du Colombier goto Usage; 867dd7cddfSDavid du Colombier break; 877dd7cddfSDavid du Colombier case 'f': 887dd7cddfSDavid du Colombier fontnames[0] = ARGF(); 897dd7cddfSDavid du Colombier if(fontnames[0] == nil) 907dd7cddfSDavid du Colombier goto Usage; 917dd7cddfSDavid du Colombier break; 927dd7cddfSDavid du Colombier case 'F': 937dd7cddfSDavid du Colombier fontnames[1] = ARGF(); 947dd7cddfSDavid du Colombier if(fontnames[1] == nil) 957dd7cddfSDavid du Colombier goto Usage; 967dd7cddfSDavid du Colombier break; 977dd7cddfSDavid du Colombier case 'l': 987dd7cddfSDavid du Colombier loadfile = ARGF(); 997dd7cddfSDavid du Colombier if(loadfile == nil) 1007dd7cddfSDavid du Colombier goto Usage; 1017dd7cddfSDavid du Colombier break; 1027dd7cddfSDavid du Colombier default: 1037dd7cddfSDavid du Colombier Usage: 104*4fec87e5SDavid du Colombier fprint(2, "usage: acme -a -c ncol -f fontname -F fixedwidthfontname -l loadfile\n"); 1057dd7cddfSDavid du Colombier exits("usage"); 1067dd7cddfSDavid du Colombier }ARGEND 1077dd7cddfSDavid du Colombier 1087dd7cddfSDavid du Colombier cputype = getenv("cputype"); 1097dd7cddfSDavid du Colombier objtype = getenv("objtype"); 1107dd7cddfSDavid du Colombier home = getenv("home"); 1117dd7cddfSDavid du Colombier p = getenv("tabstop"); 11259cc4ca5SDavid du Colombier if(p != nil){ 1137dd7cddfSDavid du Colombier maxtab = strtoul(p, nil, 0); 11459cc4ca5SDavid du Colombier free(p); 11559cc4ca5SDavid du Colombier } 1167dd7cddfSDavid du Colombier if(maxtab == 0) 1177dd7cddfSDavid du Colombier maxtab = 4; 1189a747e4fSDavid du Colombier if(loadfile) 1199a747e4fSDavid du Colombier rowloadfonts(loadfile); 1207dd7cddfSDavid du Colombier putenv("font", fontnames[0]); 1217dd7cddfSDavid du Colombier snarffd = open("/dev/snarf", OREAD|OCEXEC); 1227dd7cddfSDavid du Colombier if(cputype){ 1237dd7cddfSDavid du Colombier sprint(buf, "/acme/bin/%s", cputype); 1247dd7cddfSDavid du Colombier bind(buf, "/bin", MBEFORE); 1257dd7cddfSDavid du Colombier } 1267dd7cddfSDavid du Colombier bind("/acme/bin", "/bin", MBEFORE); 1277dd7cddfSDavid du Colombier getwd(wdir, sizeof wdir); 1287dd7cddfSDavid du Colombier 1299a747e4fSDavid du Colombier if(geninitdraw(nil, derror, fontnames[0], "acme", nil, Refnone) < 0){ 1307dd7cddfSDavid du Colombier fprint(2, "acme: can't open display: %r\n"); 1319a747e4fSDavid du Colombier exits("geninitdraw"); 1327dd7cddfSDavid du Colombier } 1337dd7cddfSDavid du Colombier d = display; 1347dd7cddfSDavid du Colombier font = d->defaultfont; 1357dd7cddfSDavid du Colombier 1367dd7cddfSDavid du Colombier reffont.f = font; 1377dd7cddfSDavid du Colombier reffonts[0] = &reffont; 1387dd7cddfSDavid du Colombier incref(&reffont); /* one to hold up 'font' variable */ 1397dd7cddfSDavid du Colombier incref(&reffont); /* one to hold up reffonts[0] */ 1407dd7cddfSDavid du Colombier fontcache = emalloc(sizeof(Reffont*)); 1417dd7cddfSDavid du Colombier nfontcache = 1; 1427dd7cddfSDavid du Colombier fontcache[0] = &reffont; 1437dd7cddfSDavid du Colombier 1447dd7cddfSDavid du Colombier iconinit(); 1457dd7cddfSDavid du Colombier timerinit(); 1467dd7cddfSDavid du Colombier rxinit(); 1477dd7cddfSDavid du Colombier 1487dd7cddfSDavid du Colombier cwait = threadwaitchan(); 1497dd7cddfSDavid du Colombier ccommand = chancreate(sizeof(Command**), 0); 1507dd7cddfSDavid du Colombier ckill = chancreate(sizeof(Rune*), 0); 1517dd7cddfSDavid du Colombier cxfidalloc = chancreate(sizeof(Xfid*), 0); 1527dd7cddfSDavid du Colombier cxfidfree = chancreate(sizeof(Xfid*), 0); 1539a747e4fSDavid du Colombier cnewwindow = chancreate(sizeof(Channel*), 0); 1547dd7cddfSDavid du Colombier cerr = chancreate(sizeof(char*), 0); 15559cc4ca5SDavid du Colombier cedit = chancreate(sizeof(int), 0); 1567dd7cddfSDavid du Colombier cexit = chancreate(sizeof(int), 0); 1577dd7cddfSDavid du Colombier if(cwait==nil || ccommand==nil || ckill==nil || cxfidalloc==nil || cxfidfree==nil || cerr==nil || cexit==nil){ 1587dd7cddfSDavid du Colombier fprint(2, "acme: can't create initial channels: %r\n"); 1597dd7cddfSDavid du Colombier exits("channels"); 1607dd7cddfSDavid du Colombier } 1617dd7cddfSDavid du Colombier 1627dd7cddfSDavid du Colombier mousectl = initmouse(nil, screen); 1637dd7cddfSDavid du Colombier if(mousectl == nil){ 1647dd7cddfSDavid du Colombier fprint(2, "acme: can't initialize mouse: %r\n"); 1657dd7cddfSDavid du Colombier exits("mouse"); 1667dd7cddfSDavid du Colombier } 1677dd7cddfSDavid du Colombier mouse = mousectl; 1687dd7cddfSDavid du Colombier keyboardctl = initkeyboard(nil); 1697dd7cddfSDavid du Colombier if(keyboardctl == nil){ 1707dd7cddfSDavid du Colombier fprint(2, "acme: can't initialize keyboard: %r\n"); 1717dd7cddfSDavid du Colombier exits("keyboard"); 1727dd7cddfSDavid du Colombier } 1737dd7cddfSDavid du Colombier mainpid = getpid(); 1747dd7cddfSDavid du Colombier plumbeditfd = plumbopen("edit", OREAD|OCEXEC); 1757dd7cddfSDavid du Colombier if(plumbeditfd >= 0){ 1767dd7cddfSDavid du Colombier cplumb = chancreate(sizeof(Plumbmsg*), 0); 1777dd7cddfSDavid du Colombier proccreate(plumbproc, nil, STACK); 1787dd7cddfSDavid du Colombier } 1797dd7cddfSDavid du Colombier plumbsendfd = plumbopen("send", OWRITE|OCEXEC); 1807dd7cddfSDavid du Colombier 1817dd7cddfSDavid du Colombier fsysinit(); 1827dd7cddfSDavid du Colombier 1837dd7cddfSDavid du Colombier #define WPERCOL 8 1847dd7cddfSDavid du Colombier disk = diskinit(); 1857dd7cddfSDavid du Colombier if(loadfile) 1867dd7cddfSDavid du Colombier rowload(&row, loadfile, TRUE); 1877dd7cddfSDavid du Colombier else{ 1887dd7cddfSDavid du Colombier rowinit(&row, screen->clipr); 1897dd7cddfSDavid du Colombier if(ncol < 0){ 1907dd7cddfSDavid du Colombier if(argc == 0) 1917dd7cddfSDavid du Colombier ncol = 2; 1927dd7cddfSDavid du Colombier else{ 1937dd7cddfSDavid du Colombier ncol = (argc+(WPERCOL-1))/WPERCOL; 1947dd7cddfSDavid du Colombier if(ncol < 2) 1957dd7cddfSDavid du Colombier ncol = 2; 1967dd7cddfSDavid du Colombier } 1977dd7cddfSDavid du Colombier } 1987dd7cddfSDavid du Colombier if(ncol == 0) 1997dd7cddfSDavid du Colombier ncol = 2; 2007dd7cddfSDavid du Colombier for(i=0; i<ncol; i++){ 2017dd7cddfSDavid du Colombier c = rowadd(&row, nil, -1); 2027dd7cddfSDavid du Colombier if(c==nil && i==0) 2037dd7cddfSDavid du Colombier error("initializing columns"); 2047dd7cddfSDavid du Colombier } 2057dd7cddfSDavid du Colombier c = row.col[row.ncol-1]; 2067dd7cddfSDavid du Colombier if(argc == 0) 2077dd7cddfSDavid du Colombier readfile(c, wdir); 2087dd7cddfSDavid du Colombier else 2097dd7cddfSDavid du Colombier for(i=0; i<argc; i++){ 2107dd7cddfSDavid du Colombier p = utfrrune(argv[i], '/'); 2117dd7cddfSDavid du Colombier if((p!=nil && strcmp(p, "/guide")==0) || i/WPERCOL>=row.ncol) 2127dd7cddfSDavid du Colombier readfile(c, argv[i]); 2137dd7cddfSDavid du Colombier else 2147dd7cddfSDavid du Colombier readfile(row.col[i/WPERCOL], argv[i]); 2157dd7cddfSDavid du Colombier } 2167dd7cddfSDavid du Colombier } 2177dd7cddfSDavid du Colombier flushimage(display, 1); 2187dd7cddfSDavid du Colombier 2197dd7cddfSDavid du Colombier acmeerrorinit(); 2207dd7cddfSDavid du Colombier threadcreate(keyboardthread, nil, STACK); 2217dd7cddfSDavid du Colombier threadcreate(mousethread, nil, STACK); 2227dd7cddfSDavid du Colombier threadcreate(waitthread, nil, STACK); 2237dd7cddfSDavid du Colombier threadcreate(xfidallocthread, nil, STACK); 2249a747e4fSDavid du Colombier threadcreate(newwindowthread, nil, STACK); 2257dd7cddfSDavid du Colombier 2269a747e4fSDavid du Colombier threadnotify(shutdown, 1); 2277dd7cddfSDavid du Colombier recvul(cexit); 2287dd7cddfSDavid du Colombier killprocs(); 2297dd7cddfSDavid du Colombier threadexitsall(nil); 2307dd7cddfSDavid du Colombier } 2317dd7cddfSDavid du Colombier 2327dd7cddfSDavid du Colombier void 2337dd7cddfSDavid du Colombier readfile(Column *c, char *s) 2347dd7cddfSDavid du Colombier { 2357dd7cddfSDavid du Colombier Window *w; 2367dd7cddfSDavid du Colombier Rune rb[256]; 2377dd7cddfSDavid du Colombier int nb, nr; 2387dd7cddfSDavid du Colombier Runestr rs; 2397dd7cddfSDavid du Colombier 2407dd7cddfSDavid du Colombier w = coladd(c, nil, nil, -1); 2417dd7cddfSDavid du Colombier cvttorunes(s, strlen(s), rb, &nb, &nr, nil); 2427dd7cddfSDavid du Colombier rs = cleanrname((Runestr){rb, nr}); 2437dd7cddfSDavid du Colombier winsetname(w, rs.r, rs.nr); 2447dd7cddfSDavid du Colombier textload(&w->body, 0, s, 1); 2457dd7cddfSDavid du Colombier w->body.file->mod = FALSE; 2467dd7cddfSDavid du Colombier w->dirty = FALSE; 2477dd7cddfSDavid du Colombier winsettag(w); 2487dd7cddfSDavid du Colombier textscrdraw(&w->body); 2497dd7cddfSDavid du Colombier textsetselect(&w->tag, w->tag.file->nc, w->tag.file->nc); 2507dd7cddfSDavid du Colombier } 2517dd7cddfSDavid du Colombier 2527dd7cddfSDavid du Colombier char *oknotes[] ={ 2537dd7cddfSDavid du Colombier "delete", 2547dd7cddfSDavid du Colombier "hangup", 2557dd7cddfSDavid du Colombier "kill", 2567dd7cddfSDavid du Colombier "exit", 2577dd7cddfSDavid du Colombier nil 2587dd7cddfSDavid du Colombier }; 2597dd7cddfSDavid du Colombier 2607dd7cddfSDavid du Colombier int dumping; 2617dd7cddfSDavid du Colombier 2629a747e4fSDavid du Colombier int 2639a747e4fSDavid du Colombier shutdown(void*, char *msg) 2647dd7cddfSDavid du Colombier { 2657dd7cddfSDavid du Colombier int i; 2667dd7cddfSDavid du Colombier 2677dd7cddfSDavid du Colombier killprocs(); 2689a747e4fSDavid du Colombier if(!dumping && strcmp(msg, "kill")!=0 && strcmp(msg, "exit")!=0 && getpid()==mainpid){ 2697dd7cddfSDavid du Colombier dumping = TRUE; 2707dd7cddfSDavid du Colombier rowdump(&row, nil); 2717dd7cddfSDavid du Colombier } 2727dd7cddfSDavid du Colombier for(i=0; oknotes[i]; i++) 2737dd7cddfSDavid du Colombier if(strncmp(oknotes[i], msg, strlen(oknotes[i])) == 0) 2747dd7cddfSDavid du Colombier threadexitsall(msg); 2757dd7cddfSDavid du Colombier print("acme: %s\n", msg); 2767dd7cddfSDavid du Colombier abort(); 2779a747e4fSDavid du Colombier return 0; 2787dd7cddfSDavid du Colombier } 2797dd7cddfSDavid du Colombier 2807dd7cddfSDavid du Colombier void 2817dd7cddfSDavid du Colombier killprocs(void) 2827dd7cddfSDavid du Colombier { 2837dd7cddfSDavid du Colombier Command *c; 2847dd7cddfSDavid du Colombier 2857dd7cddfSDavid du Colombier fsysclose(); 2869a747e4fSDavid du Colombier // if(display) 2879a747e4fSDavid du Colombier // flushimage(display, 1); 2887dd7cddfSDavid du Colombier 2897dd7cddfSDavid du Colombier for(c=command; c; c=c->next) 2907dd7cddfSDavid du Colombier postnote(PNGROUP, c->pid, "hangup"); 2917dd7cddfSDavid du Colombier remove(acmeerrorfile); 2927dd7cddfSDavid du Colombier } 2937dd7cddfSDavid du Colombier 2947dd7cddfSDavid du Colombier static int errorfd; 2957dd7cddfSDavid du Colombier 2967dd7cddfSDavid du Colombier void 2977dd7cddfSDavid du Colombier acmeerrorproc(void *) 2987dd7cddfSDavid du Colombier { 2997dd7cddfSDavid du Colombier char *buf; 3007dd7cddfSDavid du Colombier int n; 3017dd7cddfSDavid du Colombier 3027dd7cddfSDavid du Colombier threadsetname("acmeerrorproc"); 3037dd7cddfSDavid du Colombier buf = emalloc(8192+1); 3047dd7cddfSDavid du Colombier while((n=read(errorfd, buf, 8192)) >= 0){ 3057dd7cddfSDavid du Colombier buf[n] = '\0'; 30659cc4ca5SDavid du Colombier sendp(cerr, estrdup(buf)); 3077dd7cddfSDavid du Colombier } 3087dd7cddfSDavid du Colombier } 3097dd7cddfSDavid du Colombier 3107dd7cddfSDavid du Colombier void 3117dd7cddfSDavid du Colombier acmeerrorinit(void) 3127dd7cddfSDavid du Colombier { 3137dd7cddfSDavid du Colombier int fd, pfd[2]; 3147dd7cddfSDavid du Colombier char buf[64]; 3157dd7cddfSDavid du Colombier 3167dd7cddfSDavid du Colombier if(pipe(pfd) < 0) 3177dd7cddfSDavid du Colombier error("can't create pipe"); 3187dd7cddfSDavid du Colombier sprint(acmeerrorfile, "/srv/acme.%s.%d", getuser(), mainpid); 3197dd7cddfSDavid du Colombier fd = create(acmeerrorfile, OWRITE, 0666); 3207dd7cddfSDavid du Colombier if(fd < 0){ 32159cc4ca5SDavid du Colombier remove(acmeerrorfile); 3227dd7cddfSDavid du Colombier fd = create(acmeerrorfile, OWRITE, 0666); 3237dd7cddfSDavid du Colombier if(fd < 0) 3247dd7cddfSDavid du Colombier error("can't create acmeerror file"); 3257dd7cddfSDavid du Colombier } 3267dd7cddfSDavid du Colombier sprint(buf, "%d", pfd[0]); 3277dd7cddfSDavid du Colombier write(fd, buf, strlen(buf)); 3287dd7cddfSDavid du Colombier close(fd); 3297dd7cddfSDavid du Colombier /* reopen pfd[1] close on exec */ 3307dd7cddfSDavid du Colombier sprint(buf, "/fd/%d", pfd[1]); 3317dd7cddfSDavid du Colombier errorfd = open(buf, OREAD|OCEXEC); 3327dd7cddfSDavid du Colombier if(errorfd < 0) 3337dd7cddfSDavid du Colombier error("can't re-open acmeerror file"); 3347dd7cddfSDavid du Colombier close(pfd[1]); 3357dd7cddfSDavid du Colombier close(pfd[0]); 3367dd7cddfSDavid du Colombier proccreate(acmeerrorproc, nil, STACK); 3377dd7cddfSDavid du Colombier } 3387dd7cddfSDavid du Colombier 3397dd7cddfSDavid du Colombier void 3407dd7cddfSDavid du Colombier plumbproc(void *) 3417dd7cddfSDavid du Colombier { 3427dd7cddfSDavid du Colombier Plumbmsg *m; 3437dd7cddfSDavid du Colombier 3447dd7cddfSDavid du Colombier threadsetname("plumbproc"); 3457dd7cddfSDavid du Colombier for(;;){ 3467dd7cddfSDavid du Colombier m = plumbrecv(plumbeditfd); 3477dd7cddfSDavid du Colombier if(m == nil) 3487dd7cddfSDavid du Colombier threadexits(nil); 3497dd7cddfSDavid du Colombier sendp(cplumb, m); 3507dd7cddfSDavid du Colombier } 3517dd7cddfSDavid du Colombier } 3527dd7cddfSDavid du Colombier 3537dd7cddfSDavid du Colombier void 3547dd7cddfSDavid du Colombier keyboardthread(void *) 3557dd7cddfSDavid du Colombier { 3567dd7cddfSDavid du Colombier Rune r; 3577dd7cddfSDavid du Colombier Timer *timer; 3587dd7cddfSDavid du Colombier Text *t; 3597dd7cddfSDavid du Colombier enum { KTimer, KKey, NKALT }; 3607dd7cddfSDavid du Colombier static Alt alts[NKALT+1]; 3617dd7cddfSDavid du Colombier 3627dd7cddfSDavid du Colombier alts[KTimer].c = nil; 3637dd7cddfSDavid du Colombier alts[KTimer].v = nil; 3647dd7cddfSDavid du Colombier alts[KTimer].op = CHANNOP; 3657dd7cddfSDavid du Colombier alts[KKey].c = keyboardctl->c; 3667dd7cddfSDavid du Colombier alts[KKey].v = &r; 3677dd7cddfSDavid du Colombier alts[KKey].op = CHANRCV; 3687dd7cddfSDavid du Colombier alts[NKALT].op = CHANEND; 3697dd7cddfSDavid du Colombier 3707dd7cddfSDavid du Colombier timer = nil; 3717dd7cddfSDavid du Colombier typetext = nil; 3727dd7cddfSDavid du Colombier threadsetname("keyboardthread"); 3737dd7cddfSDavid du Colombier for(;;){ 3747dd7cddfSDavid du Colombier switch(alt(alts)){ 3757dd7cddfSDavid du Colombier case KTimer: 3767dd7cddfSDavid du Colombier timerstop(timer); 3777dd7cddfSDavid du Colombier t = typetext; 3787dd7cddfSDavid du Colombier if(t!=nil && t->what==Tag){ 3797dd7cddfSDavid du Colombier winlock(t->w, 'K'); 3807dd7cddfSDavid du Colombier wincommit(t->w, t); 3817dd7cddfSDavid du Colombier winunlock(t->w); 382*4fec87e5SDavid du Colombier qlock(&row); 383*4fec87e5SDavid du Colombier flushwarnings(); 384*4fec87e5SDavid du Colombier qunlock(&row); 3857dd7cddfSDavid du Colombier flushimage(display, 1); 3867dd7cddfSDavid du Colombier } 3877dd7cddfSDavid du Colombier alts[KTimer].c = nil; 3887dd7cddfSDavid du Colombier alts[KTimer].op = CHANNOP; 3897dd7cddfSDavid du Colombier break; 3907dd7cddfSDavid du Colombier case KKey: 3917dd7cddfSDavid du Colombier casekeyboard: 3927dd7cddfSDavid du Colombier typetext = rowtype(&row, r, mouse->xy); 3937dd7cddfSDavid du Colombier t = typetext; 3949a747e4fSDavid du Colombier if(t!=nil && t->col!=nil && !(r==Kdown || r==Kleft || r==Kright)) /* scrolling doesn't change activecol */ 3957dd7cddfSDavid du Colombier activecol = t->col; 3967dd7cddfSDavid du Colombier if(t!=nil && t->w!=nil) 3977dd7cddfSDavid du Colombier t->w->body.file->curtext = &t->w->body; 3987dd7cddfSDavid du Colombier if(timer != nil) 3997dd7cddfSDavid du Colombier timercancel(timer); 4007dd7cddfSDavid du Colombier if(t!=nil && t->what==Tag) { 4017dd7cddfSDavid du Colombier timer = timerstart(500); 4027dd7cddfSDavid du Colombier alts[KTimer].c = timer->c; 4037dd7cddfSDavid du Colombier alts[KTimer].op = CHANRCV; 4047dd7cddfSDavid du Colombier }else{ 4057dd7cddfSDavid du Colombier timer = nil; 4067dd7cddfSDavid du Colombier alts[KTimer].c = nil; 4077dd7cddfSDavid du Colombier alts[KTimer].op = CHANNOP; 4087dd7cddfSDavid du Colombier } 4097dd7cddfSDavid du Colombier if(nbrecv(keyboardctl->c, &r) > 0) 4107dd7cddfSDavid du Colombier goto casekeyboard; 411*4fec87e5SDavid du Colombier qlock(&row); 412*4fec87e5SDavid du Colombier flushwarnings(); 413*4fec87e5SDavid du Colombier qunlock(&row); 4147dd7cddfSDavid du Colombier flushimage(display, 1); 4157dd7cddfSDavid du Colombier break; 4167dd7cddfSDavid du Colombier } 4177dd7cddfSDavid du Colombier } 4187dd7cddfSDavid du Colombier } 4197dd7cddfSDavid du Colombier 4207dd7cddfSDavid du Colombier void 4217dd7cddfSDavid du Colombier mousethread(void *) 4227dd7cddfSDavid du Colombier { 4237dd7cddfSDavid du Colombier Text *t, *argt; 4247dd7cddfSDavid du Colombier int but; 4257dd7cddfSDavid du Colombier uint q0, q1; 4267dd7cddfSDavid du Colombier Window *w; 4277dd7cddfSDavid du Colombier Plumbmsg *pm; 4289a747e4fSDavid du Colombier Mouse m; 4297dd7cddfSDavid du Colombier char *act; 4307dd7cddfSDavid du Colombier enum { MResize, MMouse, MPlumb, NMALT }; 4317dd7cddfSDavid du Colombier static Alt alts[NMALT+1]; 4327dd7cddfSDavid du Colombier 4337dd7cddfSDavid du Colombier threadsetname("mousethread"); 4347dd7cddfSDavid du Colombier alts[MResize].c = mousectl->resizec; 4357dd7cddfSDavid du Colombier alts[MResize].v = nil; 4367dd7cddfSDavid du Colombier alts[MResize].op = CHANRCV; 4377dd7cddfSDavid du Colombier alts[MMouse].c = mousectl->c; 4387dd7cddfSDavid du Colombier alts[MMouse].v = &mousectl->Mouse; 4397dd7cddfSDavid du Colombier alts[MMouse].op = CHANRCV; 4407dd7cddfSDavid du Colombier alts[MPlumb].c = cplumb; 4417dd7cddfSDavid du Colombier alts[MPlumb].v = ± 4427dd7cddfSDavid du Colombier alts[MPlumb].op = CHANRCV; 4437dd7cddfSDavid du Colombier if(cplumb == nil) 4447dd7cddfSDavid du Colombier alts[MPlumb].op = CHANNOP; 4457dd7cddfSDavid du Colombier alts[NMALT].op = CHANEND; 4467dd7cddfSDavid du Colombier 4477dd7cddfSDavid du Colombier for(;;){ 4487dd7cddfSDavid du Colombier switch(alt(alts)){ 4497dd7cddfSDavid du Colombier case MResize: 4507dd7cddfSDavid du Colombier if(getwindow(display, Refnone) < 0) 4517dd7cddfSDavid du Colombier error("attach to window"); 4527dd7cddfSDavid du Colombier scrlresize(); 4537dd7cddfSDavid du Colombier rowresize(&row, screen->clipr); 454*4fec87e5SDavid du Colombier qlock(&row); 455*4fec87e5SDavid du Colombier flushwarnings(); 456*4fec87e5SDavid du Colombier qunlock(&row); 4577dd7cddfSDavid du Colombier flushimage(display, 1); 4587dd7cddfSDavid du Colombier break; 4597dd7cddfSDavid du Colombier case MPlumb: 4607dd7cddfSDavid du Colombier if(strcmp(pm->type, "text") == 0){ 4617dd7cddfSDavid du Colombier act = plumblookup(pm->attr, "action"); 4627dd7cddfSDavid du Colombier if(act==nil || strcmp(act, "showfile")==0) 4637dd7cddfSDavid du Colombier plumblook(pm); 4647dd7cddfSDavid du Colombier else if(strcmp(act, "showdata")==0) 4657dd7cddfSDavid du Colombier plumbshow(pm); 4667dd7cddfSDavid du Colombier } 467*4fec87e5SDavid du Colombier qlock(&row); 468*4fec87e5SDavid du Colombier flushwarnings(); 469*4fec87e5SDavid du Colombier qunlock(&row); 4707dd7cddfSDavid du Colombier flushimage(display, 1); 4717dd7cddfSDavid du Colombier plumbfree(pm); 4727dd7cddfSDavid du Colombier break; 4737dd7cddfSDavid du Colombier case MMouse: 4749a747e4fSDavid du Colombier /* 4759a747e4fSDavid du Colombier * Make a copy so decisions are consistent; mousectl changes 4769a747e4fSDavid du Colombier * underfoot. Can't just receive into m because this introduces 4779a747e4fSDavid du Colombier * another race; see /sys/src/libdraw/mouse.c. 4789a747e4fSDavid du Colombier */ 4799a747e4fSDavid du Colombier m = mousectl->Mouse; 4807dd7cddfSDavid du Colombier qlock(&row); 4819a747e4fSDavid du Colombier t = rowwhich(&row, m.xy); 4827dd7cddfSDavid du Colombier if(t!=mousetext && mousetext!=nil && mousetext->w!=nil){ 4837dd7cddfSDavid du Colombier winlock(mousetext->w, 'M'); 4847dd7cddfSDavid du Colombier mousetext->eq0 = ~0; 4857dd7cddfSDavid du Colombier wincommit(mousetext->w, mousetext); 4867dd7cddfSDavid du Colombier winunlock(mousetext->w); 4877dd7cddfSDavid du Colombier } 4887dd7cddfSDavid du Colombier mousetext = t; 4897dd7cddfSDavid du Colombier if(t == nil) 4907dd7cddfSDavid du Colombier goto Continue; 4917dd7cddfSDavid du Colombier w = t->w; 4929a747e4fSDavid du Colombier if(t==nil || m.buttons==0) 4937dd7cddfSDavid du Colombier goto Continue; 4947dd7cddfSDavid du Colombier but = 0; 4959a747e4fSDavid du Colombier if(m.buttons == 1) 4967dd7cddfSDavid du Colombier but = 1; 4979a747e4fSDavid du Colombier else if(m.buttons == 2) 4987dd7cddfSDavid du Colombier but = 2; 4999a747e4fSDavid du Colombier else if(m.buttons == 4) 5007dd7cddfSDavid du Colombier but = 3; 5017dd7cddfSDavid du Colombier barttext = t; 5029a747e4fSDavid du Colombier if(t->what==Body && ptinrect(m.xy, t->scrollr)){ 5037dd7cddfSDavid du Colombier if(but){ 5047dd7cddfSDavid du Colombier winlock(w, 'M'); 5057dd7cddfSDavid du Colombier t->eq0 = ~0; 5067dd7cddfSDavid du Colombier textscroll(t, but); 5077dd7cddfSDavid du Colombier winunlock(w); 5087dd7cddfSDavid du Colombier } 5097dd7cddfSDavid du Colombier goto Continue; 5107dd7cddfSDavid du Colombier } 5119a747e4fSDavid du Colombier if(ptinrect(m.xy, t->scrollr)){ 5127dd7cddfSDavid du Colombier if(but){ 5137dd7cddfSDavid du Colombier if(t->what == Columntag) 5147dd7cddfSDavid du Colombier rowdragcol(&row, t->col, but); 5157dd7cddfSDavid du Colombier else if(t->what == Tag){ 5167dd7cddfSDavid du Colombier coldragwin(t->col, t->w, but); 5177dd7cddfSDavid du Colombier if(t->w) 5187dd7cddfSDavid du Colombier barttext = &t->w->body; 5197dd7cddfSDavid du Colombier } 5207dd7cddfSDavid du Colombier if(t->col) 5217dd7cddfSDavid du Colombier activecol = t->col; 5227dd7cddfSDavid du Colombier } 5237dd7cddfSDavid du Colombier goto Continue; 5247dd7cddfSDavid du Colombier } 5259a747e4fSDavid du Colombier if(m.buttons){ 5267dd7cddfSDavid du Colombier if(w) 5277dd7cddfSDavid du Colombier winlock(w, 'M'); 5287dd7cddfSDavid du Colombier t->eq0 = ~0; 5297dd7cddfSDavid du Colombier if(w) 5307dd7cddfSDavid du Colombier wincommit(w, t); 5317dd7cddfSDavid du Colombier else 5327dd7cddfSDavid du Colombier textcommit(t, TRUE); 5339a747e4fSDavid du Colombier if(m.buttons & 1){ 5347dd7cddfSDavid du Colombier textselect(t); 5357dd7cddfSDavid du Colombier if(w) 5367dd7cddfSDavid du Colombier winsettag(w); 5377dd7cddfSDavid du Colombier argtext = t; 5387dd7cddfSDavid du Colombier seltext = t; 5397dd7cddfSDavid du Colombier if(t->col) 5407dd7cddfSDavid du Colombier activecol = t->col; /* button 1 only */ 5417dd7cddfSDavid du Colombier if(t->w!=nil && t==&t->w->body) 5427dd7cddfSDavid du Colombier activewin = t->w; 5439a747e4fSDavid du Colombier }else if(m.buttons & 2){ 5447dd7cddfSDavid du Colombier if(textselect2(t, &q0, &q1, &argt)) 5457dd7cddfSDavid du Colombier execute(t, q0, q1, FALSE, argt); 5469a747e4fSDavid du Colombier }else if(m.buttons & 4){ 5477dd7cddfSDavid du Colombier if(textselect3(t, &q0, &q1)) 5487dd7cddfSDavid du Colombier look3(t, q0, q1, FALSE); 5497dd7cddfSDavid du Colombier } 5507dd7cddfSDavid du Colombier if(w) 5517dd7cddfSDavid du Colombier winunlock(w); 5527dd7cddfSDavid du Colombier goto Continue; 5537dd7cddfSDavid du Colombier } 5547dd7cddfSDavid du Colombier Continue: 555*4fec87e5SDavid du Colombier flushwarnings(); 5567dd7cddfSDavid du Colombier flushimage(display, 1); 5577dd7cddfSDavid du Colombier qunlock(&row); 5587dd7cddfSDavid du Colombier break; 5597dd7cddfSDavid du Colombier } 5607dd7cddfSDavid du Colombier } 5617dd7cddfSDavid du Colombier } 5627dd7cddfSDavid du Colombier 5637dd7cddfSDavid du Colombier /* 5647dd7cddfSDavid du Colombier * There is a race between process exiting and our finding out it was ever created. 5657dd7cddfSDavid du Colombier * This structure keeps a list of processes that have exited we haven't heard of. 5667dd7cddfSDavid du Colombier */ 5677dd7cddfSDavid du Colombier typedef struct Pid Pid; 5687dd7cddfSDavid du Colombier struct Pid 5697dd7cddfSDavid du Colombier { 5707dd7cddfSDavid du Colombier int pid; 5719a747e4fSDavid du Colombier char msg[ERRMAX]; 5727dd7cddfSDavid du Colombier Pid *next; 5737dd7cddfSDavid du Colombier }; 5747dd7cddfSDavid du Colombier 5757dd7cddfSDavid du Colombier void 5767dd7cddfSDavid du Colombier waitthread(void *) 5777dd7cddfSDavid du Colombier { 5789a747e4fSDavid du Colombier Waitmsg *w; 5797dd7cddfSDavid du Colombier Command *c, *lc; 5807dd7cddfSDavid du Colombier uint pid; 5817dd7cddfSDavid du Colombier int found, ncmd; 5827dd7cddfSDavid du Colombier Rune *cmd; 5837dd7cddfSDavid du Colombier char *err; 5847dd7cddfSDavid du Colombier Text *t; 5857dd7cddfSDavid du Colombier Pid *pids, *p, *lastp; 5867dd7cddfSDavid du Colombier enum { WErr, WKill, WWait, WCmd, NWALT }; 5877dd7cddfSDavid du Colombier Alt alts[NWALT+1]; 5887dd7cddfSDavid du Colombier 5897dd7cddfSDavid du Colombier threadsetname("waitthread"); 5907dd7cddfSDavid du Colombier pids = nil; 5917dd7cddfSDavid du Colombier alts[WErr].c = cerr; 5927dd7cddfSDavid du Colombier alts[WErr].v = &err; 5937dd7cddfSDavid du Colombier alts[WErr].op = CHANRCV; 5947dd7cddfSDavid du Colombier alts[WKill].c = ckill; 5957dd7cddfSDavid du Colombier alts[WKill].v = &cmd; 5967dd7cddfSDavid du Colombier alts[WKill].op = CHANRCV; 5977dd7cddfSDavid du Colombier alts[WWait].c = cwait; 5987dd7cddfSDavid du Colombier alts[WWait].v = &w; 5997dd7cddfSDavid du Colombier alts[WWait].op = CHANRCV; 6007dd7cddfSDavid du Colombier alts[WCmd].c = ccommand; 6017dd7cddfSDavid du Colombier alts[WCmd].v = &c; 6027dd7cddfSDavid du Colombier alts[WCmd].op = CHANRCV; 6037dd7cddfSDavid du Colombier alts[NWALT].op = CHANEND; 6047dd7cddfSDavid du Colombier 6057dd7cddfSDavid du Colombier command = nil; 6067dd7cddfSDavid du Colombier for(;;){ 6077dd7cddfSDavid du Colombier switch(alt(alts)){ 6087dd7cddfSDavid du Colombier case WErr: 6097dd7cddfSDavid du Colombier qlock(&row); 6107dd7cddfSDavid du Colombier warning(nil, "%s", err); 6117dd7cddfSDavid du Colombier free(err); 6127dd7cddfSDavid du Colombier flushimage(display, 1); 6137dd7cddfSDavid du Colombier qunlock(&row); 6147dd7cddfSDavid du Colombier break; 6157dd7cddfSDavid du Colombier case WKill: 6167dd7cddfSDavid du Colombier found = FALSE; 6177dd7cddfSDavid du Colombier ncmd = runestrlen(cmd); 6187dd7cddfSDavid du Colombier for(c=command; c; c=c->next){ 6197dd7cddfSDavid du Colombier /* -1 for blank */ 6207dd7cddfSDavid du Colombier if(runeeq(c->name, c->nname-1, cmd, ncmd) == TRUE){ 6217dd7cddfSDavid du Colombier if(postnote(PNGROUP, c->pid, "kill") < 0) 6227dd7cddfSDavid du Colombier warning(nil, "kill %S: %r\n", cmd); 6237dd7cddfSDavid du Colombier found = TRUE; 6247dd7cddfSDavid du Colombier } 6257dd7cddfSDavid du Colombier } 6267dd7cddfSDavid du Colombier if(!found) 6277dd7cddfSDavid du Colombier warning(nil, "Kill: no process %S\n", cmd); 6287dd7cddfSDavid du Colombier free(cmd); 6297dd7cddfSDavid du Colombier break; 6307dd7cddfSDavid du Colombier case WWait: 6319a747e4fSDavid du Colombier pid = w->pid; 6327dd7cddfSDavid du Colombier lc = nil; 6337dd7cddfSDavid du Colombier for(c=command; c; c=c->next){ 6347dd7cddfSDavid du Colombier if(c->pid == pid){ 6357dd7cddfSDavid du Colombier if(lc) 6367dd7cddfSDavid du Colombier lc->next = c->next; 6377dd7cddfSDavid du Colombier else 6387dd7cddfSDavid du Colombier command = c->next; 6397dd7cddfSDavid du Colombier break; 6407dd7cddfSDavid du Colombier } 6417dd7cddfSDavid du Colombier lc = c; 6427dd7cddfSDavid du Colombier } 6437dd7cddfSDavid du Colombier qlock(&row); 6447dd7cddfSDavid du Colombier t = &row.tag; 6457dd7cddfSDavid du Colombier textcommit(t, TRUE); 6467dd7cddfSDavid du Colombier if(c == nil){ 6477dd7cddfSDavid du Colombier /* helper processes use this exit status */ 6489a747e4fSDavid du Colombier if(strncmp(w->msg, "libthread", 9) != 0){ 6497dd7cddfSDavid du Colombier p = emalloc(sizeof(Pid)); 6507dd7cddfSDavid du Colombier p->pid = pid; 6519a747e4fSDavid du Colombier strncpy(p->msg, w->msg, sizeof(p->msg)); 6527dd7cddfSDavid du Colombier p->next = pids; 6537dd7cddfSDavid du Colombier pids = p; 6547dd7cddfSDavid du Colombier } 6557dd7cddfSDavid du Colombier }else{ 6567dd7cddfSDavid du Colombier if(search(t, c->name, c->nname)){ 6577dd7cddfSDavid du Colombier textdelete(t, t->q0, t->q1, TRUE); 6587dd7cddfSDavid du Colombier textsetselect(t, 0, 0); 6597dd7cddfSDavid du Colombier } 6609a747e4fSDavid du Colombier if(w->msg[0]) 6619a747e4fSDavid du Colombier warning(c->md, "%s\n", w->msg); 6627dd7cddfSDavid du Colombier flushimage(display, 1); 6637dd7cddfSDavid du Colombier } 6647dd7cddfSDavid du Colombier qunlock(&row); 6659a747e4fSDavid du Colombier free(w); 6667dd7cddfSDavid du Colombier Freecmd: 6677dd7cddfSDavid du Colombier if(c){ 66859cc4ca5SDavid du Colombier if(c->iseditcmd) 66959cc4ca5SDavid du Colombier sendul(cedit, 0); 6707dd7cddfSDavid du Colombier free(c->text); 6717dd7cddfSDavid du Colombier free(c->name); 6727dd7cddfSDavid du Colombier fsysdelid(c->md); 6737dd7cddfSDavid du Colombier free(c); 6747dd7cddfSDavid du Colombier } 6757dd7cddfSDavid du Colombier break; 6767dd7cddfSDavid du Colombier case WCmd: 6777dd7cddfSDavid du Colombier /* has this command already exited? */ 6787dd7cddfSDavid du Colombier lastp = nil; 6797dd7cddfSDavid du Colombier for(p=pids; p!=nil; p=p->next){ 6807dd7cddfSDavid du Colombier if(p->pid == c->pid){ 6817dd7cddfSDavid du Colombier if(p->msg[0]) 6827dd7cddfSDavid du Colombier warning(c->md, "%s\n", p->msg); 6837dd7cddfSDavid du Colombier if(lastp == nil) 6847dd7cddfSDavid du Colombier pids = p->next; 6857dd7cddfSDavid du Colombier else 6867dd7cddfSDavid du Colombier lastp->next = p->next; 6877dd7cddfSDavid du Colombier free(p); 6887dd7cddfSDavid du Colombier goto Freecmd; 6897dd7cddfSDavid du Colombier } 6907dd7cddfSDavid du Colombier lastp = p; 6917dd7cddfSDavid du Colombier } 6927dd7cddfSDavid du Colombier c->next = command; 6937dd7cddfSDavid du Colombier command = c; 6947dd7cddfSDavid du Colombier qlock(&row); 6957dd7cddfSDavid du Colombier t = &row.tag; 6967dd7cddfSDavid du Colombier textcommit(t, TRUE); 6977dd7cddfSDavid du Colombier textinsert(t, 0, c->name, c->nname, TRUE); 6987dd7cddfSDavid du Colombier textsetselect(t, 0, 0); 6997dd7cddfSDavid du Colombier flushimage(display, 1); 7007dd7cddfSDavid du Colombier qunlock(&row); 7017dd7cddfSDavid du Colombier break; 7027dd7cddfSDavid du Colombier } 7037dd7cddfSDavid du Colombier } 7047dd7cddfSDavid du Colombier } 7057dd7cddfSDavid du Colombier 7067dd7cddfSDavid du Colombier void 7077dd7cddfSDavid du Colombier xfidallocthread(void*) 7087dd7cddfSDavid du Colombier { 7097dd7cddfSDavid du Colombier Xfid *xfree, *x; 7107dd7cddfSDavid du Colombier enum { Alloc, Free, N }; 7117dd7cddfSDavid du Colombier static Alt alts[N+1]; 7127dd7cddfSDavid du Colombier 7137dd7cddfSDavid du Colombier threadsetname("xfidallocthread"); 7147dd7cddfSDavid du Colombier alts[Alloc].c = cxfidalloc; 7157dd7cddfSDavid du Colombier alts[Alloc].v = nil; 7167dd7cddfSDavid du Colombier alts[Alloc].op = CHANRCV; 7177dd7cddfSDavid du Colombier alts[Free].c = cxfidfree; 7187dd7cddfSDavid du Colombier alts[Free].v = &x; 7197dd7cddfSDavid du Colombier alts[Free].op = CHANRCV; 7207dd7cddfSDavid du Colombier alts[N].op = CHANEND; 7217dd7cddfSDavid du Colombier 7227dd7cddfSDavid du Colombier xfree = nil; 7237dd7cddfSDavid du Colombier for(;;){ 7247dd7cddfSDavid du Colombier switch(alt(alts)){ 7257dd7cddfSDavid du Colombier case Alloc: 7267dd7cddfSDavid du Colombier x = xfree; 7277dd7cddfSDavid du Colombier if(x) 7287dd7cddfSDavid du Colombier xfree = x->next; 7297dd7cddfSDavid du Colombier else{ 7307dd7cddfSDavid du Colombier x = emalloc(sizeof(Xfid)); 7317dd7cddfSDavid du Colombier x->c = chancreate(sizeof(void(*)(Xfid*)), 0); 7327dd7cddfSDavid du Colombier x->arg = x; 7337dd7cddfSDavid du Colombier threadcreate(xfidctl, x->arg, STACK); 7347dd7cddfSDavid du Colombier } 7357dd7cddfSDavid du Colombier sendp(cxfidalloc, x); 7367dd7cddfSDavid du Colombier break; 7377dd7cddfSDavid du Colombier case Free: 7387dd7cddfSDavid du Colombier x->next = xfree; 7397dd7cddfSDavid du Colombier xfree = x; 7407dd7cddfSDavid du Colombier break; 7417dd7cddfSDavid du Colombier } 7427dd7cddfSDavid du Colombier } 7437dd7cddfSDavid du Colombier } 7447dd7cddfSDavid du Colombier 7459a747e4fSDavid du Colombier /* this thread, in the main proc, allows fsysproc to get a window made without doing graphics */ 7469a747e4fSDavid du Colombier void 7479a747e4fSDavid du Colombier newwindowthread(void*) 7489a747e4fSDavid du Colombier { 7499a747e4fSDavid du Colombier Window *w; 7509a747e4fSDavid du Colombier 7519a747e4fSDavid du Colombier threadsetname("newwindowthread"); 7529a747e4fSDavid du Colombier 7539a747e4fSDavid du Colombier for(;;){ 7549a747e4fSDavid du Colombier /* only fsysproc is talking to us, so synchronization is trivial */ 7559a747e4fSDavid du Colombier recvp(cnewwindow); 756d9306527SDavid du Colombier w = makenewwindow(nil); 7579a747e4fSDavid du Colombier winsettag(w); 7589a747e4fSDavid du Colombier sendp(cnewwindow, w); 7599a747e4fSDavid du Colombier } 7609a747e4fSDavid du Colombier } 7619a747e4fSDavid du Colombier 7627dd7cddfSDavid du Colombier Reffont* 7637dd7cddfSDavid du Colombier rfget(int fix, int save, int setfont, char *name) 7647dd7cddfSDavid du Colombier { 7657dd7cddfSDavid du Colombier Reffont *r; 7667dd7cddfSDavid du Colombier Font *f; 7677dd7cddfSDavid du Colombier int i; 7687dd7cddfSDavid du Colombier 7697dd7cddfSDavid du Colombier r = nil; 7707dd7cddfSDavid du Colombier if(name == nil){ 7717dd7cddfSDavid du Colombier name = fontnames[fix]; 7727dd7cddfSDavid du Colombier r = reffonts[fix]; 7737dd7cddfSDavid du Colombier } 7747dd7cddfSDavid du Colombier if(r == nil){ 7757dd7cddfSDavid du Colombier for(i=0; i<nfontcache; i++) 7767dd7cddfSDavid du Colombier if(strcmp(name, fontcache[i]->f->name) == 0){ 7777dd7cddfSDavid du Colombier r = fontcache[i]; 7787dd7cddfSDavid du Colombier goto Found; 7797dd7cddfSDavid du Colombier } 78059cc4ca5SDavid du Colombier f = openfont(display, name); 7817dd7cddfSDavid du Colombier if(f == nil){ 7827dd7cddfSDavid du Colombier warning(nil, "can't open font file %s: %r\n", name); 7837dd7cddfSDavid du Colombier return nil; 7847dd7cddfSDavid du Colombier } 7857dd7cddfSDavid du Colombier r = emalloc(sizeof(Reffont)); 7867dd7cddfSDavid du Colombier r->f = f; 7877dd7cddfSDavid du Colombier fontcache = realloc(fontcache, (nfontcache+1)*sizeof(Reffont*)); 7887dd7cddfSDavid du Colombier fontcache[nfontcache++] = r; 7897dd7cddfSDavid du Colombier } 7907dd7cddfSDavid du Colombier Found: 7917dd7cddfSDavid du Colombier if(save){ 7927dd7cddfSDavid du Colombier incref(r); 7937dd7cddfSDavid du Colombier if(reffonts[fix]) 7947dd7cddfSDavid du Colombier rfclose(reffonts[fix]); 7957dd7cddfSDavid du Colombier reffonts[fix] = r; 7969a747e4fSDavid du Colombier free(fontnames[fix]); 7977dd7cddfSDavid du Colombier fontnames[fix] = name; 7987dd7cddfSDavid du Colombier } 7997dd7cddfSDavid du Colombier if(setfont){ 8007dd7cddfSDavid du Colombier reffont.f = r->f; 8017dd7cddfSDavid du Colombier incref(r); 8027dd7cddfSDavid du Colombier rfclose(reffonts[0]); 8037dd7cddfSDavid du Colombier font = r->f; 8047dd7cddfSDavid du Colombier reffonts[0] = r; 8057dd7cddfSDavid du Colombier incref(r); 8067dd7cddfSDavid du Colombier iconinit(); 8077dd7cddfSDavid du Colombier } 8087dd7cddfSDavid du Colombier incref(r); 8097dd7cddfSDavid du Colombier return r; 8107dd7cddfSDavid du Colombier } 8117dd7cddfSDavid du Colombier 8127dd7cddfSDavid du Colombier void 8137dd7cddfSDavid du Colombier rfclose(Reffont *r) 8147dd7cddfSDavid du Colombier { 8157dd7cddfSDavid du Colombier int i; 8167dd7cddfSDavid du Colombier 8177dd7cddfSDavid du Colombier if(decref(r) == 0){ 8187dd7cddfSDavid du Colombier for(i=0; i<nfontcache; i++) 8197dd7cddfSDavid du Colombier if(r == fontcache[i]) 8207dd7cddfSDavid du Colombier break; 8217dd7cddfSDavid du Colombier if(i >= nfontcache) 8227dd7cddfSDavid du Colombier warning(nil, "internal error: can't find font in cache\n"); 8237dd7cddfSDavid du Colombier else{ 8247dd7cddfSDavid du Colombier nfontcache--; 8257dd7cddfSDavid du Colombier memmove(fontcache+i, fontcache+i+1, (nfontcache-i)*sizeof(Reffont*)); 8267dd7cddfSDavid du Colombier } 8277dd7cddfSDavid du Colombier freefont(r->f); 8287dd7cddfSDavid du Colombier free(r); 8297dd7cddfSDavid du Colombier } 8307dd7cddfSDavid du Colombier } 8317dd7cddfSDavid du Colombier 8327dd7cddfSDavid du Colombier Cursor boxcursor = { 8337dd7cddfSDavid du Colombier {-7, -7}, 8347dd7cddfSDavid du Colombier {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 8357dd7cddfSDavid du Colombier 0xFF, 0xFF, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 8367dd7cddfSDavid du Colombier 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xFF, 0xFF, 8377dd7cddfSDavid du Colombier 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 8387dd7cddfSDavid du Colombier {0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 8397dd7cddfSDavid du Colombier 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 8407dd7cddfSDavid du Colombier 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 8417dd7cddfSDavid du Colombier 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x00, 0x00} 8427dd7cddfSDavid du Colombier }; 8437dd7cddfSDavid du Colombier 8447dd7cddfSDavid du Colombier void 8457dd7cddfSDavid du Colombier iconinit(void) 8467dd7cddfSDavid du Colombier { 8477dd7cddfSDavid du Colombier Rectangle r; 8487dd7cddfSDavid du Colombier Image *tmp; 8497dd7cddfSDavid du Colombier 8507dd7cddfSDavid du Colombier /* Blue */ 8517dd7cddfSDavid du Colombier tagcols[BACK] = allocimagemix(display, DPalebluegreen, DWhite); 8529a747e4fSDavid du Colombier tagcols[HIGH] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DPalegreygreen); 8539a747e4fSDavid du Colombier tagcols[BORD] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DPurpleblue); 8547dd7cddfSDavid du Colombier tagcols[TEXT] = display->black; 8557dd7cddfSDavid du Colombier tagcols[HTEXT] = display->black; 8567dd7cddfSDavid du Colombier 8577dd7cddfSDavid du Colombier /* Yellow */ 8587dd7cddfSDavid du Colombier textcols[BACK] = allocimagemix(display, DPaleyellow, DWhite); 8599a747e4fSDavid du Colombier textcols[HIGH] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DDarkyellow); 8609a747e4fSDavid du Colombier textcols[BORD] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DYellowgreen); 8617dd7cddfSDavid du Colombier textcols[TEXT] = display->black; 8627dd7cddfSDavid du Colombier textcols[HTEXT] = display->black; 8637dd7cddfSDavid du Colombier 8647dd7cddfSDavid du Colombier if(button){ 8657dd7cddfSDavid du Colombier freeimage(button); 8667dd7cddfSDavid du Colombier freeimage(modbutton); 8677dd7cddfSDavid du Colombier freeimage(colbutton); 8687dd7cddfSDavid du Colombier } 8697dd7cddfSDavid du Colombier 8707dd7cddfSDavid du Colombier r = Rect(0, 0, Scrollwid+2, font->height+1); 8719a747e4fSDavid du Colombier button = allocimage(display, r, screen->chan, 0, DNofill); 8727dd7cddfSDavid du Colombier draw(button, r, tagcols[BACK], nil, r.min); 8737dd7cddfSDavid du Colombier r.max.x -= 2; 8747dd7cddfSDavid du Colombier border(button, r, 2, tagcols[BORD], ZP); 8757dd7cddfSDavid du Colombier 8767dd7cddfSDavid du Colombier r = button->r; 8779a747e4fSDavid du Colombier modbutton = allocimage(display, r, screen->chan, 0, DNofill); 8787dd7cddfSDavid du Colombier draw(modbutton, r, tagcols[BACK], nil, r.min); 8797dd7cddfSDavid du Colombier r.max.x -= 2; 8807dd7cddfSDavid du Colombier border(modbutton, r, 2, tagcols[BORD], ZP); 8817dd7cddfSDavid du Colombier r = insetrect(r, 2); 8829a747e4fSDavid du Colombier tmp = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DMedblue); 8837dd7cddfSDavid du Colombier draw(modbutton, r, tmp, nil, ZP); 8847dd7cddfSDavid du Colombier freeimage(tmp); 8857dd7cddfSDavid du Colombier 8867dd7cddfSDavid du Colombier r = button->r; 8879a747e4fSDavid du Colombier colbutton = allocimage(display, r, screen->chan, 0, DPurpleblue); 8887dd7cddfSDavid du Colombier 8899a747e4fSDavid du Colombier but2col = allocimage(display, r, screen->chan, 1, 0xAA0000FF); 8909a747e4fSDavid du Colombier but3col = allocimage(display, r, screen->chan, 1, 0x006600FF); 8917dd7cddfSDavid du Colombier } 8927dd7cddfSDavid du Colombier 8937dd7cddfSDavid du Colombier /* 8947dd7cddfSDavid du Colombier * /dev/snarf updates when the file is closed, so we must open our own 8957dd7cddfSDavid du Colombier * fd here rather than use snarffd 8967dd7cddfSDavid du Colombier */ 8977dd7cddfSDavid du Colombier 8987dd7cddfSDavid du Colombier /* rio truncates larges snarf buffers, so this avoids using the 8997dd7cddfSDavid du Colombier * service if the string is huge */ 9007dd7cddfSDavid du Colombier 9017dd7cddfSDavid du Colombier #define MAXSNARF 100*1024 9027dd7cddfSDavid du Colombier 9037dd7cddfSDavid du Colombier void 9047dd7cddfSDavid du Colombier putsnarf(void) 9057dd7cddfSDavid du Colombier { 9067dd7cddfSDavid du Colombier int fd, i, n; 9077dd7cddfSDavid du Colombier 9087dd7cddfSDavid du Colombier if(snarffd<0 || snarfbuf.nc==0) 9097dd7cddfSDavid du Colombier return; 9107dd7cddfSDavid du Colombier if(snarfbuf.nc > MAXSNARF) 9117dd7cddfSDavid du Colombier return; 9127dd7cddfSDavid du Colombier fd = open("/dev/snarf", OWRITE); 9137dd7cddfSDavid du Colombier if(fd < 0) 9147dd7cddfSDavid du Colombier return; 9157dd7cddfSDavid du Colombier for(i=0; i<snarfbuf.nc; i+=n){ 9167dd7cddfSDavid du Colombier n = snarfbuf.nc-i; 9177dd7cddfSDavid du Colombier if(n >= NSnarf) 9187dd7cddfSDavid du Colombier n = NSnarf; 9197dd7cddfSDavid du Colombier bufread(&snarfbuf, i, snarfrune, n); 9207dd7cddfSDavid du Colombier if(fprint(fd, "%.*S", n, snarfrune) < 0) 9217dd7cddfSDavid du Colombier break; 9227dd7cddfSDavid du Colombier } 9237dd7cddfSDavid du Colombier close(fd); 9247dd7cddfSDavid du Colombier } 9257dd7cddfSDavid du Colombier 9267dd7cddfSDavid du Colombier void 9277dd7cddfSDavid du Colombier getsnarf() 9287dd7cddfSDavid du Colombier { 9297dd7cddfSDavid du Colombier int nulls; 9307dd7cddfSDavid du Colombier 9317dd7cddfSDavid du Colombier if(snarfbuf.nc > MAXSNARF) 9327dd7cddfSDavid du Colombier return; 9337dd7cddfSDavid du Colombier if(snarffd < 0) 9347dd7cddfSDavid du Colombier return; 9357dd7cddfSDavid du Colombier seek(snarffd, 0, 0); 9367dd7cddfSDavid du Colombier bufreset(&snarfbuf); 9377dd7cddfSDavid du Colombier bufload(&snarfbuf, 0, snarffd, &nulls); 9387dd7cddfSDavid du Colombier } 939