📄 acme.c
字号:
*/ m = mousectl->Mouse; qlock(&row); t = rowwhich(&row, m.xy); if(t!=mousetext && mousetext!=nil && mousetext->w!=nil){ winlock(mousetext->w, 'M'); mousetext->eq0 = ~0; wincommit(mousetext->w, mousetext); winunlock(mousetext->w); } mousetext = t; if(t == nil) goto Continue; w = t->w; if(t==nil || m.buttons==0) goto Continue; but = 0; if(m.buttons == 1) but = 1; else if(m.buttons == 2) but = 2; else if(m.buttons == 4) but = 3; barttext = t; if(t->what==Body && ptinrect(m.xy, t->scrollr)){ if(but){ winlock(w, 'M'); t->eq0 = ~0; textscroll(t, but); winunlock(w); } goto Continue; } /* scroll buttons, wheels, etc. */ if(t->what==Body && w != nil && (m.buttons & (8|16))){ if(m.buttons & 8) but = Kscrolloneup; else but = Kscrollonedown; winlock(w, 'M'); t->eq0 = ~0; texttype(t, but); winunlock(w); goto Continue; } if(ptinrect(m.xy, t->scrollr)){ if(but){ if(t->what == Columntag) rowdragcol(&row, t->col, but); else if(t->what == Tag){ coldragwin(t->col, t->w, but); if(t->w) barttext = &t->w->body; } if(t->col) activecol = t->col; } goto Continue; } if(m.buttons){ if(w) winlock(w, 'M'); t->eq0 = ~0; if(w) wincommit(w, t); else textcommit(t, TRUE); if(m.buttons & 1){ textselect(t); if(w) winsettag(w); argtext = t; seltext = t; if(t->col) activecol = t->col; /* button 1 only */ if(t->w!=nil && t==&t->w->body) activewin = t->w; }else if(m.buttons & 2){ if(textselect2(t, &q0, &q1, &argt)) execute(t, q0, q1, FALSE, argt); }else if(m.buttons & 4){ if(textselect3(t, &q0, &q1)) look3(t, q0, q1, FALSE); } if(w) winunlock(w); goto Continue; } Continue: qunlock(&row); break; } }}/* * There is a race between process exiting and our finding out it was ever created. * This structure keeps a list of processes that have exited we haven't heard of. */typedef struct Pid Pid;struct Pid{ int pid; char msg[ERRMAX]; Pid *next;};voidwaitthread(void *){ Waitmsg *w; Command *c, *lc; uint pid; int found, ncmd; Rune *cmd; char *err; Text *t; Pid *pids, *p, *lastp; enum { WErr, WKill, WWait, WCmd, NWALT }; Alt alts[NWALT+1]; threadsetname("waitthread"); pids = nil; alts[WErr].c = cerr; alts[WErr].v = &err; alts[WErr].op = CHANRCV; alts[WKill].c = ckill; alts[WKill].v = &cmd; alts[WKill].op = CHANRCV; alts[WWait].c = cwait; alts[WWait].v = &w; alts[WWait].op = CHANRCV; alts[WCmd].c = ccommand; alts[WCmd].v = &c; alts[WCmd].op = CHANRCV; alts[NWALT].op = CHANEND; command = nil; for(;;){ switch(alt(alts)){ case WErr: qlock(&row); warning(nil, "%s", err); free(err); flushimage(display, 1); qunlock(&row); break; case WKill: found = FALSE; ncmd = runestrlen(cmd); for(c=command; c; c=c->next){ /* -1 for blank */ if(runeeq(c->name, c->nname-1, cmd, ncmd) == TRUE){ if(postnote(PNGROUP, c->pid, "kill") < 0) warning(nil, "kill %S: %r\n", cmd); found = TRUE; } } if(!found) warning(nil, "Kill: no process %S\n", cmd); free(cmd); break; case WWait: pid = w->pid; lc = nil; for(c=command; c; c=c->next){ if(c->pid == pid){ if(lc) lc->next = c->next; else command = c->next; break; } lc = c; } qlock(&row); t = &row.tag; textcommit(t, TRUE); if(c == nil){ /* helper processes use this exit status */ if(strncmp(w->msg, "libthread", 9) != 0){ p = emalloc(sizeof(Pid)); p->pid = pid; strncpy(p->msg, w->msg, sizeof(p->msg)); p->next = pids; pids = p; } }else{ if(search(t, c->name, c->nname)){ textdelete(t, t->q0, t->q1, TRUE); textsetselect(t, 0, 0); } if(w->msg[0]) warning(c->md, "%s\n", w->msg); flushimage(display, 1); } qunlock(&row); free(w); Freecmd: if(c){ if(c->iseditcmd) sendul(cedit, 0); free(c->text); free(c->name); fsysdelid(c->md); free(c); } break; case WCmd: /* has this command already exited? */ lastp = nil; for(p=pids; p!=nil; p=p->next){ if(p->pid == c->pid){ if(p->msg[0]) warning(c->md, "%s\n", p->msg); if(lastp == nil) pids = p->next; else lastp->next = p->next; free(p); goto Freecmd; } lastp = p; } c->next = command; command = c; qlock(&row); t = &row.tag; textcommit(t, TRUE); textinsert(t, 0, c->name, c->nname, TRUE); textsetselect(t, 0, 0); flushimage(display, 1); qunlock(&row); break; } }}voidxfidallocthread(void*){ Xfid *xfree, *x; enum { Alloc, Free, N }; static Alt alts[N+1]; threadsetname("xfidallocthread"); alts[Alloc].c = cxfidalloc; alts[Alloc].v = nil; alts[Alloc].op = CHANRCV; alts[Free].c = cxfidfree; alts[Free].v = &x; alts[Free].op = CHANRCV; alts[N].op = CHANEND; xfree = nil; for(;;){ switch(alt(alts)){ case Alloc: x = xfree; if(x) xfree = x->next; else{ x = emalloc(sizeof(Xfid)); x->c = chancreate(sizeof(void(*)(Xfid*)), 0); x->arg = x; threadcreate(xfidctl, x->arg, STACK); } sendp(cxfidalloc, x); break; case Free: x->next = xfree; xfree = x; break; } }}/* this thread, in the main proc, allows fsysproc to get a window made without doing graphics */voidnewwindowthread(void*){ Window *w; threadsetname("newwindowthread"); for(;;){ /* only fsysproc is talking to us, so synchronization is trivial */ recvp(cnewwindow); w = makenewwindow(nil); winsettag(w); sendp(cnewwindow, w); }}Reffont*rfget(int fix, int save, int setfont, char *name){ Reffont *r; Font *f; int i; r = nil; if(name == nil){ name = fontnames[fix]; r = reffonts[fix]; } if(r == nil){ for(i=0; i<nfontcache; i++) if(strcmp(name, fontcache[i]->f->name) == 0){ r = fontcache[i]; goto Found; } f = openfont(display, name); if(f == nil){ warning(nil, "can't open font file %s: %r\n", name); return nil; } r = emalloc(sizeof(Reffont)); r->f = f; fontcache = erealloc(fontcache, (nfontcache+1)*sizeof(Reffont*)); fontcache[nfontcache++] = r; } Found: if(save){ incref(r); if(reffonts[fix]) rfclose(reffonts[fix]); reffonts[fix] = r; if(name != fontnames[fix]){ free(fontnames[fix]); fontnames[fix] = estrdup(name); } } if(setfont){ reffont.f = r->f; incref(r); rfclose(reffonts[0]); font = r->f; reffonts[0] = r; incref(r); iconinit(); } incref(r); return r;}voidrfclose(Reffont *r){ int i; if(decref(r) == 0){ for(i=0; i<nfontcache; i++) if(r == fontcache[i]) break; if(i >= nfontcache) warning(nil, "internal error: can't find font in cache\n"); else{ nfontcache--; memmove(fontcache+i, fontcache+i+1, (nfontcache-i)*sizeof(Reffont*)); } freefont(r->f); free(r); }}Cursor boxcursor = { {-7, -7}, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, {0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x00, 0x00}};voidiconinit(void){ Rectangle r; Image *tmp; /* Blue */ tagcols[BACK] = allocimagemix(display, DPalebluegreen, DWhite); tagcols[HIGH] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DPalegreygreen); tagcols[BORD] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DPurpleblue); tagcols[TEXT] = display->black; tagcols[HTEXT] = display->black; /* Yellow */ textcols[BACK] = allocimagemix(display, DPaleyellow, DWhite); textcols[HIGH] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DDarkyellow); textcols[BORD] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DYellowgreen); textcols[TEXT] = display->black; textcols[HTEXT] = display->black; if(button){ freeimage(button); freeimage(modbutton); freeimage(colbutton); } r = Rect(0, 0, Scrollwid+2, font->height+1); button = allocimage(display, r, screen->chan, 0, DNofill); draw(button, r, tagcols[BACK], nil, r.min); r.max.x -= 2; border(button, r, 2, tagcols[BORD], ZP); r = button->r; modbutton = allocimage(display, r, screen->chan, 0, DNofill); draw(modbutton, r, tagcols[BACK], nil, r.min); r.max.x -= 2; border(modbutton, r, 2, tagcols[BORD], ZP); r = insetrect(r, 2); tmp = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DMedblue); draw(modbutton, r, tmp, nil, ZP); freeimage(tmp); r = button->r; colbutton = allocimage(display, r, screen->chan, 0, DPurpleblue); but2col = allocimage(display, r, screen->chan, 1, 0xAA0000FF); but3col = allocimage(display, r, screen->chan, 1, 0x006600FF);}/* * /dev/snarf updates when the file is closed, so we must open our own * fd here rather than use snarffd *//* rio truncates larges snarf buffers, so this avoids using the * service if the string is huge */#define MAXSNARF 100*1024voidputsnarf(void){ int fd, i, n; if(snarffd<0 || snarfbuf.nc==0) return; if(snarfbuf.nc > MAXSNARF) return; fd = open("/dev/snarf", OWRITE); if(fd < 0) return; for(i=0; i<snarfbuf.nc; i+=n){ n = snarfbuf.nc-i; if(n >= NSnarf) n = NSnarf; bufread(&snarfbuf, i, snarfrune, n); if(fprint(fd, "%.*S", n, snarfrune) < 0) break; } close(fd);}voidgetsnarf(){ int nulls; if(snarfbuf.nc > MAXSNARF) return; if(snarffd < 0) return; seek(snarffd, 0, 0); bufreset(&snarfbuf); bufload(&snarfbuf, 0, snarffd, &nulls);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -