📄 control.c
字号:
#include <u.h>#include <libc.h>#include <draw.h>#include <thread.h>#include <mouse.h>#include <keyboard.h>#include <control.h>static int debug = 0;enum /* alts */{ AKey, AMouse, ACtl, AExit, NALT};static Controlset **controlset;int ncontrolset;int ctldeletequits;char *alignnames[Nalignments] = { [Aupperleft] = "upperleft", [Auppercenter] = "uppercenter", [Aupperright] = "upperright", [Acenterleft] = "centerleft", [Acenter] = "center", [Acenterright] = "centerright", [Alowerleft] = "lowerleft", [Alowercenter] = "lowercenter", [Alowerright] = "lowerright",};char *ctltypenames[Ntypes] = { [Ctlunknown] = "unknown", [Ctlbox] = "box", [Ctlbutton] = "button", [Ctlentry] = "entry", [Ctlkeyboard] = "keyboard", [Ctllabel] = "label", [Ctlmenu] = "menu", [Ctlradio] = "radio", [Ctlscribble] = "scribble", [Ctlslider] = "slider", [Ctltabs] = "tabs", [Ctltext] = "text", [Ctltextbutton] = "textbutton", [Ctltextbutton3] = "textbutton3", [Ctlgroup] = "group", // divider between controls and metacontrols [Ctlboxbox] = "boxbox", [Ctlcolumn] = "column", [Ctlrow] = "row", [Ctlstack] = "stack", [Ctltab] = "tab",};static void _ctlcmd(Controlset*, char*);static void _ctlcontrol(Controlset*, char*);static char*_mkctlcmd(Control *c, char *fmt, va_list arg){ char *name, *p, *both; name = quotestrdup(c->name); if(name == nil) ctlerror("quotestrdup in ctlprint failed"); p = vsmprint(fmt, arg); if(p == nil){ free(name); ctlerror("vsmprint1 in ctlprint failed"); } both = ctlmalloc(strlen(name)+strlen(p)+2); strcpy(both, name); strcat(both, " "); strcat(both, p); free(name); free(p); return both;}intctlprint(Control *c, char *fmt, ...){ int n; char *p; va_list arg; va_start(arg, fmt); p = _mkctlcmd(c, fmt, arg); va_end(arg); n = sendp(c->controlset->ctl, p); yield(); return n;}void_ctlprint(Control *c, char *fmt, ...){ char *p; va_list arg; va_start(arg, fmt); p = _mkctlcmd(c, fmt, arg); va_end(arg); _ctlcmd(c->controlset, p); free(p);}int_ctllookup(char *s, char *tab[], int ntab){ int i; for(i=0; i<ntab; i++) if(tab[i] != nil && strcmp(s, tab[i]) == 0) return i; return -1;}static Control*_newcontrol(Controlset *cs, uint n, char *name, char *type){ Control *c; for(c=cs->controls; c; c=c->next) if(strcmp(c->name, name) == 0){ werrstr("control %q already defined", name); return nil; } c = ctlmalloc(n); c->screen = cs->screen; c->name = ctlstrdup(name); c->type = _ctllookup(type, ctltypenames, Ntypes); if (c->type < 0) ctlerror("unknown type: %s", type); c->event = chancreate(sizeof(char*), 64); c->data = chancreate(sizeof(char*), 0); c->size = Rect(1, 1, _Ctlmaxsize, _Ctlmaxsize); c->hidden = 0; c->ctl = nil; c->mouse = nil; c->key = nil; c->exit = nil; c->setsize = nil; c->controlset = cs; c->next = cs->controls; cs->controls = c; return c;}static voidcontrolsetthread(void *v){ Controlset *cs; Mouse mouse; Control *f; int prevbut, n, i; Alt alts[NALT+1]; char tmp[64], *str; Rune buf[2][20], *rp; cs = v; snprint(tmp, sizeof tmp, "controlsetthread 0x%p", cs); threadsetname(tmp); alts[AKey].c = cs->kbdc; alts[AKey].v = &rp; alts[AKey].op = CHANRCV; alts[AMouse].c = cs->mousec; alts[AMouse].v = &mouse; alts[AMouse].op = CHANRCV; alts[ACtl].c = cs->ctl; alts[ACtl].v = &str; alts[ACtl].op = CHANRCV; alts[AExit].c = cs->csexitc; alts[AExit].v = nil; alts[AExit].op = CHANRCV; alts[NALT].op = CHANEND; cs->focus = nil; prevbut=0; n = 0; for(;;){ /* toggle so we can receive in one buffer while client processes the other */ alts[AKey].v = buf[n]; rp = buf[n]; n = 1-n; switch(alt(alts)){ case AKey: if(ctldeletequits && rp[0]=='\177') ctlerror("delete"); for(i=1; i<nelem(buf[0])-1; i++) if(nbrecv(cs->kbdc, rp+i) <= 0) break; rp[i] = L'\0'; if(cs->focus && cs->focus->key) cs->focus->key(cs->focus, rp); break; case AMouse: /* is this a focus change? */ if(prevbut) /* don't change focus if button was down */ goto Send; if(cs->focus!=nil && cs->focus->hidden == 0 && ptinrect(mouse.xy, cs->focus->rect)) goto Send; if(cs->clicktotype == 0) goto Change; /* click to type: only change if button is down */ if(mouse.buttons == 0) goto Send; Change: /* change of focus */ if(cs->focus != nil) _ctlprint(cs->focus, "focus 0"); cs->focus = nil; for(f=cs->actives; f!=nil; f=f->nextactive) if(f->hidden == 0 && f->mouse && ptinrect(mouse.xy, f->rect)){ cs->focus = f; _ctlprint(f, "focus 1"); if (f->mouse) { if (debug) fprint(2, "f->mouse %s\n", f->name); f->mouse(f, &mouse); } break; } Send: if(cs->focus && cs->focus->mouse) { if (debug) fprint(2, "cs->focus->mouse %s\n", cs->focus->name); cs->focus->mouse(cs->focus, &mouse); } prevbut=mouse.buttons; break; case ACtl: _ctlcontrol(cs, str); free(str); break; case AExit: threadexits(nil); } }}Control*_createctl(Controlset *cs, char *type, uint size, char *name){ Control *c; c = _newcontrol(cs, size, name, type); if(c == nil) ctlerror("can't create %s control %q: %r", type, name); return c;}voidclosecontrol(Control *c){ Control *prev, *p; if(c == nil) return; if (c == c->controlset->focus) c->controlset->focus = nil; if(c->exit) c->exit(c); prev = nil; for(p=c->controlset->controls; p; p=p->next){ if(p == c) break; prev = p; } if(p == nil) ctlerror("closecontrol: no such control %q %p\n", c->name, c); if(prev == nil) c->controlset->controls = c->next; else prev->next = c->next; /* is it active? if so, delete from active list */ prev = nil; for(p=c->controlset->actives; p; p=p->nextactive){ if(p == c) break; prev = p; } if(p != nil){ if(prev == nil) c->controlset->actives = c->nextactive; else prev->nextactive = c->nextactive; } if(!c->wevent) chanfree(c->event); if(!c->wdata) chanfree(c->data); free(c->name); free(c->format); free(c);}Control*controlcalled(char *name){ Control *c; int i; for(i=0; i<ncontrolset; i++) for(c=controlset[i]->controls; c; c=c->next) if(strcmp(c->name, name) == 0) return c; return nil;}voidctlerror(char *fmt, ...){ va_list arg; char buf[256]; va_start(arg, fmt); vfprint(2, fmt, arg); va_end(arg); write(2, "\n", 1); threadexitsall(buf);}Rune*_ctlrunestr(char *s){ Rune *r, *ret; ret = r = ctlmalloc((utflen(s)+1)*sizeof(Rune)); while(*s != '\0') s += chartorune(r++, s); *r = L'\0'; return ret;}char*_ctlstrrune(Rune *r){ char *s; s = ctlmalloc(runestrlen(r)*UTFmax+1); sprint(s, "%S", r); return s;}void*ctlmalloc(uint n){ void *p; p = mallocz(n, 1); if(p == nil) ctlerror("control allocation failed: %r"); return p;}void*ctlrealloc(void *p, uint n){ p = realloc(p, n); if(p == nil) ctlerror("control reallocation failed: %r"); return p;}char*ctlstrdup(char *s){ char *t; t = strdup(s); if(t == nil) ctlerror("control strdup(%q) failed: %r", s); return t;}static voidctokenize(char *s, CParse *cp){ snprint(cp->str, sizeof cp->str, "%s", s); cp->args = cp->pargs; cp->nargs = tokenize(s, cp->args, nelem(cp->pargs));}static intctlparse(CParse *cp, char *s, int hasreceiver){ int i; char *t; /* keep original string for good error messages */ strncpy(cp->str, s, sizeof cp->str); cp->str[sizeof cp->str - 1] = '\0'; ctokenize(s, cp); if(cp->nargs == 0) return -1; /* strip leading sender name if present */ cp->sender = nil; i = strlen(cp->args[0])-1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -