void mousethread(void *v) { Text *t, *argt; int but; uint q0, q1; Window *w; Plumbmsg *pm; Mouse m; char *act; enum { MResize, MMouse, MPlumb, MWarnings, NMALT }; static Alt alts[NMALT+1]; USED(v); threadsetname("mousethread"); alts[MResize].c = mousectl->resizec; alts[MResize].v = nil; alts[MResize].op = CHANRCV; alts[MMouse].c = mousectl->c; alts[MMouse].v = &mousectl->m; alts[MMouse].op = CHANRCV; alts[MPlumb].c = cplumb; alts[MPlumb].v = ± alts[MPlumb].op = CHANRCV; alts[MWarnings].c = cwarn; alts[MWarnings].v = nil; alts[MWarnings].op = CHANRCV; if(cplumb == nil) alts[MPlumb].op = CHANNOP; alts[NMALT].op = CHANEND; for(;;){ qlock(&row.lk); flushwarnings(); qunlock(&row.lk); flushimage(display, 1); switch(alt(alts)){ case MResize: if(getwindow(display, Refnone) < 0) error("attach to window"); draw(screen, screen->r, display->white, nil, ZP); iconinit(); scrlresize(); rowresize(&row, screen->clipr); break; case MPlumb: if(strcmp(pm->type, "text") == 0){ act = plumblookup(pm->attr, "action"); if(act==nil || strcmp(act, "showfile")==0) plumblook(pm); else if(strcmp(act, "showdata")==0) plumbshow(pm); } plumbfree(pm); break; case MWarnings: break; case MMouse: /* * Make a copy so decisions are consistent; mousectl changes * underfoot. Can't just receive into m because this introduces * another race; see /sys/src/libdraw/mouse.c. */ m = mousectl->m; qlock(&row.lk); 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){ if(swapscrollbuttons){ if(but == 1) but = 3; else if(but == 3) but = 1; } winlock(w, 'M'); t->eq0 = ~0; textscroll(t, but); winunlock(w); } goto Continue; } /* scroll buttons, wheels, etc. */ if(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.lk); break; } } }
static void groupctl(Control *c, CParse *cp) { int cmd, i, n; Rectangle r; Group *g; g = (Group*)c; cmd = _ctllookup(cp->args[0], cmds, nelem(cmds)); switch(cmd){ case EAdd: for (i = 1; i < cp->nargs; i++){ c = controlcalled(cp->args[i]); if (c == nil) ctlerror("%q: no such control: %s", g->name, cp->args[i]); _ctladdgroup(g, c); } if (g->setsize) g->setsize((Control*)g); break; case EBorder: _ctlargcount(g, cp, 2); if(cp->iargs[1] < 0) ctlerror("%q: bad border: %c", g->name, cp->str); g->border = cp->iargs[1]; break; case EBordercolor: _ctlargcount(g, cp, 2); _setctlimage(g, &g->bordercolor, cp->args[1]); break; case EFocus: /* ignore focus change */ break; case EHide: _ctlargcount(g, cp, 1); for (i = 0; i < g->nkids; i++) if (g->kids[i]->ctl) _ctlprint(g->kids[i], "hide"); g->hidden = 1; break; case EImage: _ctlargcount(g, cp, 2); _setctlimage(g, &g->image, cp->args[1]); break; case ERect: _ctlargcount(g, cp, 5); r.min.x = cp->iargs[1]; r.min.y = cp->iargs[2]; r.max.x = cp->iargs[3]; r.max.y = cp->iargs[4]; if(Dx(r)<=0 || Dy(r)<=0) ctlerror("%q: bad rectangle: %s", g->name, cp->str); g->rect = r; r = insetrect(r, g->border); if (g->nkids == 0) return; switch(g->type){ case Ctlboxbox: boxboxresize(g, r); break; case Ctlcolumn: columnresize(g, r); break; case Ctlrow: rowresize(g, r); break; case Ctlstack: stackresize(g, r); break; } break; case ERemove: _ctlargcount(g, cp, 2); for (n = 0; n < g->nkids; n++) if (strcmp(cp->args[1], g->kids[n]->name) == 0) break; if (n == g->nkids) ctlerror("%s: remove nonexistent control: %q", g->name, cp->args[1]); removegroup(g, n); if (g->setsize) g->setsize((Control*)g); break; case EReveal: g->hidden = 0; if (debugr) fprint(2, "reveal %s\n", g->name); if (g->type == Ctlstack){ if (cp->nargs == 2){ if (cp->iargs[1] < 0 || cp->iargs[1] >= g->nkids) ctlerror("%s: control out of range: %q", g->name, cp->str); g->selected = cp->iargs[1]; }else _ctlargcount(g, cp, 1); for (i = 0; i < g->nkids; i++) if (g->kids[i]->ctl){ if (g->selected == i){ if (debugr) fprint(2, "reveal %s: reveal kid %s\n", g->name, g->kids[i]->name); _ctlprint(g->kids[i], "reveal"); }else{ if (debugr) fprint(2, "reveal %s: hide kid %s\n", g->name, g->kids[i]->name); _ctlprint(g->kids[i], "hide"); } } break; } _ctlargcount(g, cp, 1); if (debug) fprint(2, "reveal %s: border %R/%d\n", g->name, g->rect, g->border); border(g->screen, g->rect, g->border, g->bordercolor->image, g->bordercolor->image->r.min); r = insetrect(g->rect, g->border); if (debug) fprint(2, "reveal %s: draw %R\n", g->name, r); draw(g->screen, r, g->image->image, nil, g->image->image->r.min); for (i = 0; i < g->nkids; i++) if (g->kids[i]->ctl) _ctlprint(g->kids[i], "reveal"); break; case EShow: _ctlargcount(g, cp, 1); if (g->hidden) break; // pass it on to the kiddies if (debug) fprint(2, "show %s: border %R/%d\n", g->name, g->rect, g->border); border(g->screen, g->rect, g->border, g->bordercolor->image, g->bordercolor->image->r.min); r = insetrect(g->rect, g->border); if (debug) fprint(2, "show %s: draw %R\n", g->name, r); draw(g->screen, r, g->image->image, nil, g->image->image->r.min); for (i = 0; i < g->nkids; i++) if (g->kids[i]->ctl){ if (debug) fprint(2, "show %s: kid %s: %q\n", g->name, g->kids[i]->name, cp->str); _ctlprint(g->kids[i], "show"); } flushimage(display, 1); break; case ESize: r.max = Pt(_Ctlmaxsize, _Ctlmaxsize); if (g->type == Ctlboxbox) _ctlargcount(g, cp, 5); switch(cp->nargs){ default: ctlerror("%s: args of %q", g->name, cp->str); case 1: /* recursively set size */ g->mansize = 0; if (g->setsize) g->setsize((Control*)g); break; case 5: _ctlargcount(g, cp, 5); r.max.x = cp->iargs[3]; r.max.y = cp->iargs[4]; /* fall through */ case 3: r.min.x = cp->iargs[1]; r.min.y = cp->iargs[2]; if(r.min.x<=0 || r.min.y<=0 || r.max.x<=0 || r.max.y<=0 || r.max.x < r.min.x || r.max.y < r.min.y) ctlerror("%q: bad sizes: %s", g->name, cp->str); g->size = r; g->mansize = 1; break; } break; case ESeparation: if (g->type != Ctlstack){ _ctlargcount(g, cp, 2); if(cp->iargs[1] < 0) ctlerror("%q: illegal value: %c", g->name, cp->str); g->separation = cp->iargs[1]; break; } // fall through for Ctlstack default: ctlerror("%q: unrecognized message '%s'", g->name, cp->str); break; } }
void mousethread(void *) { Plumbmsg *pm; Mouse m; Text *t; int but; enum { MResize, MMouse, MPlumb, MRefresh, NMALT }; static Alt alts[NMALT+1]; threadsetname("mousethread"); alts[MResize].c = mousectl->resizec; alts[MResize].v = nil; alts[MResize].op = CHANRCV; alts[MMouse].c = mousectl->c; alts[MMouse].v = &mousectl->Mouse; alts[MMouse].op = CHANRCV; alts[MPlumb].c = cplumb; alts[MPlumb].v = ± alts[MPlumb].op = CHANRCV; alts[MRefresh].c = crefresh; alts[MRefresh].v = nil; alts[MRefresh].op = CHANRCV; if(cplumb == nil) alts[MPlumb].op = CHANNOP; alts[NMALT].op = CHANEND; for(;;){ qlock(&row); flushrefresh(); qunlock(&row); flushimage(display, 1); switch(alt(alts)){ case MResize: if(getwindow(display, Refnone) < 0) error("resized"); scrlresize(); tmpresize(); rowresize(&row, screen->clipr); break; case MPlumb: plumblook(pm); plumbfree(pm); break; case MRefresh: break; case MMouse: m = mousectl->Mouse; if(m.buttons == 0) continue; qlock(&row); but = 0; if(m.buttons == 1) but = 1; else if(m.buttons == 2) but = 2; else if(m.buttons == 4) but = 3; if(m.buttons & (8|16)){ if(m.buttons & 8) but = Kscrolloneup; else but = Kscrollonedown; rowwhich(&row, m.xy, but, TRUE); }else if(but){ t = rowwhich(&row, m.xy, but, FALSE); if(t) textmouse(t, m.xy, but); } qunlock(&row); break; } } }