Page * pagewhich(Page *p, Point xy) { Page *c; if(p->child == nil) return p; for(c=p->child; c!=nil; c=c->next) if(ptinrect(xy, c->all)) return pagewhich(c, xy); return nil; }
int istextsel(Page *p, Rectangle r, int *q0, int *q1, Rune *s, Font *f) { int topinr, botinr; *q0 = *q1 = 0; topinr= ptinrect(p->top, r); if(topinr || (r.min.y>p->top.y && r.max.y<p->bot.y)) p->selecting = TRUE; botinr = ptinrect(p->bot, r); if(botinr || r.min.y>p->bot.y) p->selecting = FALSE; if(topinr || botinr) { if(topinr) *q0 = xtofchar(s, f, p->top.x-r.min.x); if(botinr) *q1 = xtofchar(s, f, p->bot.x-r.min.x); if(*q0!=0 || *q1!=0) return TRUE; } return p->selecting; }
void mousethread(void *v) { Point p; Mouse m; int i, n, prev; char buf[100]; ulong rgb; prev = -1; while(readmouse(mousectl) >= 0){ m = mousectl->m; switch(m.buttons){ case 1: while(m.buttons){ if(screen->depth > 8) n = 256; else n = 1<<screen->depth; for(i=0; i!=n; i++) if(i!=prev && ptinrect(m.xy, crect[i])){ if(ramp) rgb = grey(i); else rgb = cmap2rgb(i); sprint(buf, fmt, i, (rgb>>16)&0xFF, (rgb>>8)&0xFF, rgb&0xFF, (rgb<<8) | 0xFF); p = addpt(screen->r.min, Pt(2,2)); draw(screen, Rpt(p, addpt(p, stringsize(font, buf))), display->white, nil, p); string(screen, p, display->black, ZP, font, buf); prev=i; break; } readmouse(mousectl); m = mousectl->m; } break; case 4: switch(menuhit(3, mousectl, &menu, nil)){ case 0: threadexitsall(0); } } } }
Text* colwhich(Column *c, Point p) { int i; Window *w; if(!ptinrect(p, c->r)) return nil; for(i=0; i<c->nw; i++){ w = c->w[i]; if(ptinrect(p, w->r)){ if(ptinrect(p, w->tagtop) || ptinrect(p, w->tag.all)) return &w->tag; /* exclude partial line at bottom */ if(p.x >= w->body.scrollr.max.x && p.y >= w->body.fr.r.max.y) return nil; return &w->body; } } if(ptinrect(p, c->tag.all)) return &c->tag; return nil; }
Text* colwhich(Column *c, Point p) { int i; Window *w; if(!ptinrect(p, c->r)) return nil; if(ptinrect(p, c->tag.all)) return &c->tag; for(i=0; i<c->nw; i++){ w = c->w[i]; if(ptinrect(p, w->r)){ if(ptinrect(p, w->tag.all)) return &w->tag; return &w->body; } /* scrollr drops below w->r on low windows */ if(ptinrect(p, w->body.scrollr)) return &w->body; } return nil; }
Tnode* findnode(Tnode *t, Point p) { int i; Tnode *tt; if(ptinrect(p, rectaddpt(Rect(0,0,Nubwidth, Nubheight), t->offset))) return t; if(!t->expanded) return nil; for(i=0; i<t->nkid; i++) if(tt = findnode(t->kid[i], p)) return tt; return nil; }
void click(Point mouse) { button *bp = buttons; int func; while (bp && (bp->state == Hidden || bp->state == Unavailable || !ptinrect(mouse, bp->r))) bp = bp->next; if (!bp) return; func = (int)bp->param; if (func < 0) do_exit(); execute(bp); }
void apply(void (*f)(Icon*)) { Icon *icon; esetcursor(&sight); buttons(Down); if(mouse.buttons == 4) for(icon = h.first; icon; icon = icon->next) if(ptinrect(mouse.xy, icon->sr)){ buttons(Up); f(icon); break; } buttons(Up); esetcursor(0); }
int process_command(Point mouse) { button *bp = buttons; while (bp && (bp->state == Hidden || !ptinrect(mouse, bp->r))) bp = bp->next; if (!bp) return 0; if (bp == undo_button) { if (nhist > 0) { nhist--; show_hist(); } } else if (bp == startover_button) { unfreeze(); nhist = 0; show_hist(); } else if (bp == freeze_button) { switch (state) { case Live: state = Frozen; freeze_button->state = On; paint_fancy_button(freeze_button); break; case Frozen: unfreeze(); break; default: break; } flush_screen(); } else if (bp == primary_buttons[Cat_change_color].b || bp == primary_buttons[Cat_change_look].b || bp == primary_buttons[Cat_change_shape].b) { set_category(bp); } else { if (bp && nhist < MAXHIST) { history[nhist++] = bp; show_hist(); } } flush_screen(); return 1; }
main() { int i; point x, origin = { 0, 0 }, maxpt = { 320, 320 }; point pts[] = { -1, -1, 1, 1, 20, 300, 500, 400 }; rect screen = makerect(addpoint(maxpt, makepoint(-10, -10)), addpoint(origin, makepoint(10, 10))); for (i = 0; i < sizeof pts/sizeof pts[0]; i++) { printf("(%d,%d) is ", pts[i].x, (x = makepoint(pts[i].x, pts[i].y)).y); if (ptinrect(x, screen) == 0) printf("not "); printf("within [%d,%d; %d,%d]\n", screen.pt1.x, screen.pt1.y, screen.pt2.x, screen.pt2.y); } odd(y); return 0; }
void frtick(Frame *f, Point pt, int ticked) { Rectangle r; if(f->ticked==ticked || f->tick==0 || !ptinrect(pt, f->r)) return; pt.x--; /* looks best just left of where requested */ r = Rect(pt.x, pt.y, pt.x+FRTICKW, pt.y+f->font->height); /* can go into left border but not right */ if(r.max.x > f->r.max.x) r.max.x = f->r.max.x; if(ticked) { draw(f->tickback, f->tickback->r, f->b, nil, pt); draw(f->b, r, f->tick, nil, ZP); } else draw(f->b, r, f->tickback, nil, ZP); f->ticked = ticked; }
static char* tkentryb1m(Tk *tk, char* arg, char **ret) { TkEntry *tke = TKobj(TkEntry, tk); Point p; Rectangle hitr; char buf[32]; USED(ret); p.x = atoi(arg); tke->oldx = p.x; p = tkscrn2local(tk, p); p.y = 0; if (!tkvisiblerect(tk, &hitr) || !ptinrect(p, hitr)) return nil; snprint(buf, sizeof(buf), "to @%d", p.x); tkentryselect(tk, buf, nil); return nil; }
void add_slider(Rectangle r, char *name, char *default_label, Pixel color, b_func *func, int value) { button *b = (button *)malloc(sizeof(button)); utf8 *label[bstates]; assert(b); // allocating button memory b->type = Slider; b->r = r; b->size = (Rectangle){{0,0}, {DX(r), DY(r)}}; b->name = name; b->next = 0; b->func = func; b->init = (void *)0; b->value = value; last_button = b; if ( !(ptinrect(r.min, screen_rect) && r.max.x <= screen_rect.max.x && r.max.y <= screen_rect.max.y)) return; /* lookup configuration file alternates for our default label names. */ label[Off] = lookup(name, 0, default_label); b->pixels[Off] = make_PixMap(b->size.max); place_text(b->size.max, (void *)b->pixels[Off], label[Off], White); /* Add button to the end of the linked list */ if (buttons == 0) buttons = b; else { button *bp = buttons; while (bp->next) bp = bp->next; bp->next = b; } }
static void autoselect(Tk *tk, void *v, int cancelled) { TkEntry *tke = TKobj(TkEntry, tk); Rectangle hitr; char buf[32]; Point p; USED(v); if (cancelled) return; p = tkscrn2local(tk, Pt(tke->oldx, 0)); p.y = 0; if (tkvisiblerect(tk, &hitr) && ptinrect(p, hitr)) return; snprint(buf, sizeof(buf), "to @%d", p.x); tkentryselect(tk, buf, nil); tkdirty(tk); tkupdate(tk->env->top); }
static char* tkscrollidentify(Tk *tk, char *arg, char **val) { int gotarg; TkTop *t; char *v, buf[Tkmaxitem]; Point p; TkScroll *tks = TKobj(TkScroll, tk); t = tk->env->top; arg = tkword(t, arg, buf, buf+sizeof(buf), &gotarg); if (!gotarg) return TkBadvl; p.x = atoi(buf); tkword(t, arg, buf, buf+sizeof(buf), &gotarg); if (!gotarg) return TkBadvl; p.y = atoi(buf); if (!ptinrect(p, tkrect(tk, 0))) return nil; if (tks->orient == Tkvertical) p.x = p.y; p.x += tk->borderwidth; v = ""; if(p.x <= tks->a1) v = "arrow1"; if(p.x > tks->a1 && p.x <= tks->t1) v = "trough1"; if(p.x > tks->t1 && p.x < tks->t2) v = "slider"; if(p.x >= tks->t2 && p.x < tks->a2) v = "trough2"; if(p.x >= tks->a2) v = "arrow2"; return tkvalue(val, "%s", v); }
void main(int argc, char *argv[]) { int i, got, scr; Text *t; Rectangle r; Flayer *nwhich; int fwdbut; if (argc >= 3 && strcmp(argv[1], "-r") == 0) { machine = argv[2]; } getscreen(argc, argv); fwdbut = scrollfwdbut(); iconinit(); initio(); scratch = alloc(100*RUNESIZE); nscralloc = 100; r = screen.r; r.max.y = r.min.y+Dy(r)/5; flstart(screen.clipr); rinit(&cmd.rasp); flnew(&cmd.l[0], stgettext, 1, &cmd); flinit(&cmd.l[0], r, font); cmd.nwin = 1; which = &cmd.l[0]; cmd.tag = Untagged; outTs(Tversion, VERSION); startnewfile(Tstartcmdfile, &cmd); got = 0; for(;;got = waitforio()){ if(hasunlocked && RESHAPED()) reshape(); if(got&RHost) rcv(); if(got&RExtern){ for(i=0; cmd.l[i].textfn==0; i++) ; current(&cmd.l[i]); flsetselect(which, cmd.rasp.nrunes, cmd.rasp.nrunes); type(which, RExtern); } if(got&RKeyboard) if(which) type(which, RKeyboard); else kbdblock(); if(got&RMouse){ if(lock==2 || !ptinrect(mouse.xy, screen.r)){ mouseunblock(); continue; } nwhich = flwhich(mouse.xy); scr = which && ptinrect(mouse.xy, which->scroll); if(mouse.buttons) flushtyping(1); if (chord == 1 && !mouse.buttons) chord = 0; if (chord) chord |= mouse.buttons; else if(mouse.buttons&1){ if(nwhich){ if(nwhich!=which) current(nwhich); else if(scr) scroll(which, 1, fwdbut == 3 ? 1 : 3); else{ t=(Text *)which->user1; if(flselect(which)){ outTsl(Tdclick, t->tag, which->p0); t->lock++; }else if(t!=&cmd) outcmd(); if(mouse.buttons&1) chord = mouse.buttons; } } }else if((mouse.buttons&2) && which){ if(scr) scroll(which, 2, 2); else menu2hit(); }else if((mouse.buttons&4)){ if(scr) scroll(which, 3, fwdbut == 3 ? 3 : 1); else menu3hit(); }else if((mouse.buttons&8)){ scrollone(which, 1); }else if((mouse.buttons&16)){ scrollone(which, 3); } mouseunblock(); } if(chord) { t = (Text *)which->user1; if(!t->lock){ int w = which-t->l; if(chord&2){ cut(t, w, 1, 1); chord &= ~2; } if(chord&4){ paste(t, w); chord &= ~4; } } } } }
int menuhit(int but, Mouse *m, Menu *menu) { int i, nitem, nitemdrawn, maxwid, lasti, off, noff, wid, screenitem; bool scrolling; Rectangle r, menur, sc, textr, scrollr; Bitmap *b; Point pt; char *item; extern unsigned int cursor; unsigned int oldcursor = cursor; cursorswitch(ArrowCursor); sc = screen.clipr; clipr(&screen, screen.r); maxwid = 0; for(nitem = 0; (item = menu->item? menu->item[nitem] : (*menu->gen)(nitem)); nitem++){ i = strwidth(font, item); if(i > maxwid) maxwid = i; } if(menu->lasthit<0 || menu->lasthit>=nitem) menu->lasthit = 0; screenitem = (Dy(screen.r)-10)/(fontheight()+Vspacing); if(nitem>Maxunscroll || nitem>screenitem){ scrolling = true; nitemdrawn = Nscroll; if(nitemdrawn > screenitem) nitemdrawn = screenitem; wid = maxwid + Gap + Scrollwid; off = menu->lasthit - nitemdrawn/2; if(off < 0) off = 0; if(off > nitem-nitemdrawn) off = nitem-nitemdrawn; lasti = menu->lasthit-off; }else{ scrolling = false; nitemdrawn = nitem; wid = maxwid; off = 0; lasti = menu->lasthit; } r = inset(Rect(0, 0, wid, nitemdrawn*(fontheight()+Vspacing)), -Margin); r = rsubp(r, Pt(wid/2, lasti*(fontheight()+Vspacing)+fontheight()/2)); r = raddp(r, m->xy); pt = Pt(0, 0); if(r.max.x>screen.r.max.x) pt.x = screen.r.max.x-r.max.x; if(r.max.y>screen.r.max.y) pt.y = screen.r.max.y-r.max.y; if(r.min.x<screen.r.min.x) pt.x = screen.r.min.x-r.min.x; if(r.min.y<screen.r.min.y) pt.y = screen.r.min.y-r.min.y; menur = raddp(r, pt); textr.max.x = menur.max.x-Margin; textr.min.x = textr.max.x-maxwid; textr.min.y = menur.min.y+Margin; textr.max.y = textr.min.y + nitemdrawn*(fontheight()+Vspacing); if(scrolling){ scrollr = inset(menur, Border); scrollr.max.x = scrollr.min.x+Scrollwid; }else scrollr = Rect(0, 0, 0, 0); b = balloc(menur, screen.ldepth); if(b == 0) b = &screen; bitblt(b, menur.min, &screen, menur, S); bitblt(&screen, menur.min, &screen, menur, 0); border(&screen, menur, Blackborder, F, _bgpixel); r = menurect(textr, lasti); cursorset(divpt(add(r.min, r.max), 2)); menupaint(menu, textr, off, nitemdrawn); if(scrolling) menuscrollpaint(scrollr, off, nitem, nitemdrawn); r = menurect(textr, lasti); cursorset(divpt(add(r.min, r.max), 2)); menupaint(menu, textr, off, nitemdrawn); if(scrolling) menuscrollpaint(scrollr, off, nitem, nitemdrawn); while(m->buttons & (1<<(but-1))){ lasti = menuscan(but, m, textr, lasti); if(lasti >= 0) break; while(!ptinrect(m->xy, textr) && (m->buttons & (1<<(but-1)))){ if(scrolling && ptinrect(m->xy, scrollr)){ noff = ((m->xy.y-scrollr.min.y)*nitem)/Dy(scrollr); noff -= nitemdrawn/2; if(noff < 0) noff = 0; if(noff > nitem-nitemdrawn) noff = nitem-nitemdrawn; if(noff != off){ off = noff; menupaint(menu, textr, off, nitemdrawn); menuscrollpaint(scrollr, off, nitem, nitemdrawn); } } *m = emouse(); } } bitblt(&screen, menur.min, b, menur, S); if(b != &screen) bfree(b); clipr(&screen, sc); if(lasti >= 0){ menu->lasthit = lasti+off; return cursorswitch(oldcursor), menu->lasthit; } cursorswitch(oldcursor); return -1; }
int eenter(char *ask, char *buf, int len, Mouse *m) { int done, down, tick, n, h, w, l, i; Image *b, *save, *backcol, *bordcol; Point p, o, t; Rectangle r, sc; Event ev; Rune k; o = screen->r.min; backcol = allocimagemix(display, DPurpleblue, DWhite); bordcol = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DPurpleblue); if(backcol == nil || bordcol == nil) return -1; while(ecankbd()) ekbd(); if(m) o = m->xy; if(buf && len > 0) n = strlen(buf); else { buf = nil; len = 0; n = 0; } k = -1; tick = n; save = nil; done = down = 0; p = stringsize(font, " "); h = p.y; w = p.x; b = screen; sc = b->clipr; replclipr(b, 0, b->r); while(!done){ p = stringsize(font, buf ? buf : ""); if(ask && ask[0]){ if(buf) p.x += w; p.x += stringwidth(font, ask); } r = rectaddpt(insetrect(Rpt(ZP, p), -4), o); p.x = 0; r = rectsubpt(r, p); p = ZP; if(r.min.x < screen->r.min.x) p.x = screen->r.min.x - r.min.x; if(r.min.y < screen->r.min.y) p.y = screen->r.min.y - r.min.y; r = rectaddpt(r, p); p = ZP; if(r.max.x > screen->r.max.x) p.x = r.max.x - screen->r.max.x; if(r.max.y > screen->r.max.y) p.y = r.max.y - screen->r.max.y; r = rectsubpt(r, p); r = insetrect(r, -2); if(save == nil){ save = allocimage(display, r, b->chan, 0, DNofill); if(save == nil){ n = -1; break; } draw(save, r, b, nil, r.min); } draw(b, r, backcol, nil, ZP); border(b, r, 2, bordcol, ZP); p = addpt(r.min, Pt(6, 6)); if(ask && ask[0]){ p = string(b, p, bordcol, ZP, font, ask); if(buf) p.x += w; } if(buf){ t = p; p = stringn(b, p, display->black, ZP, font, buf, utfnlen(buf, tick)); draw(b, Rect(p.x-1, p.y, p.x+2, p.y+3), display->black, nil, ZP); draw(b, Rect(p.x, p.y, p.x+1, p.y+h), display->black, nil, ZP); draw(b, Rect(p.x-1, p.y+h-3, p.x+2, p.y+h), display->black, nil, ZP); p = string(b, p, display->black, ZP, font, buf+tick); } flushimage(display, 1); nodraw: i = Ekeyboard; if(m != nil) i |= Emouse; replclipr(b, 0, sc); i = eread(i, &ev); /* screen might have been resized */ if(b != screen || !eqrect(screen->clipr, sc)){ freeimage(save); save = nil; } b = screen; sc = b->clipr; replclipr(b, 0, b->r); switch(i){ default: done = 1; n = -1; break; case Ekeyboard: k = ev.kbdc; if(buf == nil || k == Keof || k == '\n'){ done = 1; break; } if(k == Knack || k == Kesc){ done = !n; buf[n = tick = 0] = 0; break; } if(k == Ksoh || k == Khome){ tick = 0; continue; } if(k == Kenq || k == Kend){ tick = n; continue; } if(k == Kright){ if(tick < n) tick += chartorune(&k, buf+tick); continue; } if(k == Kleft){ for(i = 0; i < n; i += l){ l = chartorune(&k, buf+tick); if(i+l >= tick){ tick = i; break; } } continue; } if(k == Ketb){ while(tick > 0){ tick--; if(tick == 0 || strchr(" !\"#$%&'()*+,-./:;<=>?@`[\\]^{|}~", buf[tick-1])) break; } buf[n = tick] = 0; break; } if(k == Kbs){ if(tick <= 0) continue; for(i = 0; i < n; i += l){ l = chartorune(&k, buf+i); if(i+l >= tick){ memmove(buf+i, buf+i+l, n - (i+l)); buf[n -= l] = 0; tick -= l; break; } } break; } if(k < 0x20 || k == Kdel || (k & 0xFF00) == KF || (k & 0xFF00) == Spec) continue; if((len-n) <= (l = runelen(k))) continue; memmove(buf+tick+l, buf+tick, n - tick); runetochar(buf+tick, &k); buf[n += l] = 0; tick += l; break; case Emouse: *m = ev.mouse; if(!ptinrect(m->xy, r)){ down = 0; goto nodraw; } if(m->buttons & 7){ down = 1; if(buf && m->xy.x >= (t.x - w)){ down = 0; for(i = 0; i < n; i += l){ l = chartorune(&k, buf+i); t.x += stringnwidth(font, buf+i, 1); if(t.x > m->xy.x) break; } tick = i; } continue; } done = down; break; } if(save){ draw(b, save->r, save, nil, save->r.min); freeimage(save); save = nil; } } replclipr(b, 0, sc); freeimage(backcol); freeimage(bordcol); flushimage(display, 1); return n; }
void threadmain(int argc, char *argv[]) { int i, got, scr, chord; Text *t; Rectangle r; Flayer *nwhich; /* * sam is talking to us on fd 0 and 1. * move these elsewhere so that if we accidentally * use 0 and 1 in other code, nothing bad happens. */ dup(0, 3); dup(1, 4); hostfd[0] = 3; hostfd[1] = 4; close(0); close(1); open("/dev/null", OREAD); if(open("/dev/tty", OWRITE) < 0) open("/dev/null", OWRITE); notify(notifyf); if(protodebug) print("getscreen\n"); getscreen(argc, argv); if(protodebug) print("iconinit\n"); iconinit(); if(protodebug) print("initio\n"); initio(); if(protodebug) print("scratch\n"); scratch = alloc(100*RUNESIZE); nscralloc = 100; r = screen->r; r.max.y = r.min.y+Dy(r)/5; if(protodebug) print("flstart\n"); flstart(screen->clipr); rinit(&cmd.rasp); flnew(&cmd.l[0], gettext, 1, &cmd); flinit(&cmd.l[0], r, font, cmdcols); cmd.nwin = 1; which = &cmd.l[0]; cmd.tag = Untagged; outTs(Tversion, VERSION); startnewfile(Tstartcmdfile, &cmd); got = 0; chord = 0; if(protodebug) print("loop\n"); for(;;got = waitforio()){ if(hasunlocked && RESIZED()) resize(); if(got&(1<<RHost)) rcv(); if(got&(1<<RPlumb)){ for(i=0; cmd.l[i].textfn==0; i++) ; current(&cmd.l[i]); flsetselect(which, cmd.rasp.nrunes, cmd.rasp.nrunes); type(which, RPlumb); } if(got&(1<<RKeyboard)) if(which) type(which, RKeyboard); else kbdblock(); if(got&(1<<RMouse)){ if(hostlock==2 || !ptinrect(mousep->xy, screen->r)){ mouseunblock(); continue; } nwhich = flwhich(mousep->xy); //scr = which && ptinrect(mousep->xy, which->scroll); scr = which && (ptinrect(mousep->xy, which->scroll) || mousep->buttons&(8|16)); if(mousep->buttons) flushtyping(1); //if(chording && chord==1 && !mousep->buttons) if((mousep->buttons&1)==0) chord = 0; //if(chording && chord) //chord |= mousep->buttons; //else if(mousep->buttons&1){ if(chord && which && which==nwhich){ chord |= mousep->buttons; t = (Text *)which->user1; if(!t->lock){ int w = which-t->l; if(chord&2){ cut(t, w, 1, 1); chord &= ~2; } if(chord&4){ paste(t, w); chord &= ~4; } } }else if(mousep->buttons&(1|8)){ //}else if(mousep->buttons&1){ if(nwhich){ if(nwhich!=which) current(nwhich); else if(scr) //scroll(which, 1); scroll(which, (mousep->buttons&8) ? 4 : 1); else{ t=(Text *)which->user1; if(flselect(which)){ outTsl(Tdclick, t->tag, which->p0); t->lock++; }else if(t!=&cmd) outcmd(); if(mousep->buttons&1) chord = mousep->buttons; } } }else if((mousep->buttons&2) && which){ if(scr) scroll(which, 2); else menu2hit(); }else if(mousep->buttons&(4|16)){ //}else if(mousep->buttons&4){ if(nwhich!=which) current(nwhich); else if(scr) //if(scr) //scroll(which, 3); scroll(which, (mousep->buttons&16) ? 5 : 3); else menu3hit(); } mouseunblock(); } } }
static void groupmouse(Control *c, Mouse *m) { Group *g; int i, lastkid; g = (Group*)c; if (g->type == Ctlstack){ i = g->selected; if (i >= 0 && g->kids[i]->mouse && ( ( ((m->buttons == 0) || (g->lastbut == 0)) && ptinrect(m->xy, g->kids[i]->rect) ) || ( ((m->buttons != 0) || (g->lastbut != 0)) && (g->lastkid == i) ) ) ) { if (debugm) fprint(2, "groupmouse %s mouse kid %s i=%d lastkid=%d buttons=%d lastbut=%d inrect=%d\n", g->name, g->kids[i]->name, i, g->lastkid, m->buttons, g->lastbut, ptinrect(m->xy, g->kids[i]->rect) ? 1 : 0); (g->kids[i]->mouse)(g->kids[i], m); g->lastkid = i; g->lastbut = m->buttons; } else { if (debugm) fprint(2, "groupmouse %s skip kid %s i=%d lastkid=%d buttons=%d lastbut=%d inrect=%d\n", g->name, g->kids[i]->name, i, g->lastkid, m->buttons, g->lastbut, ptinrect(m->xy, g->kids[i]->rect) ? 1 : 0); } return; } lastkid = -1; for(i=0; i<g->nkids; i++) { if(g->kids[i]->mouse && ( ( ((m->buttons == 0) || (g->lastbut == 0)) && ptinrect(m->xy, g->kids[i]->rect) ) || ( ((m->buttons != 0) || (g->lastbut != 0)) && (g->lastkid == i) ) ) ) { if (debugm) fprint(2, "groupmouse %s mouse kid %s i=%d lastkid=%d buttons=%d lastbut=%d inrect=%d\n", g->name, g->kids[i]->name, i, g->lastkid, m->buttons, g->lastbut, ptinrect(m->xy, g->kids[i]->rect) ? 1 : 0); (g->kids[i]->mouse)(g->kids[i], m); lastkid = i; } else { if (debugm) fprint(2, "groupmouse %s skip kid %s i=%d lastkid=%d buttons=%d lastbut=%d inrect=%d\n", g->name, g->kids[i]->name, i, g->lastkid, m->buttons, g->lastbut, ptinrect(m->xy, g->kids[i]->rect) ? 1 : 0); } } g->lastkid = lastkid; g->lastbut = m->buttons; #ifdef notdef if(m->buttons == 0){ /* buttons now up */ g->lastbut = 0; return; } if(g->lastbut == 0 && m->buttons != 0){ /* button went down, start tracking border */ switch(g->stacking){ default: return; case Vertical: p = Pt(m->xy.x, middle_of_border.y); p0 = Pt(g->r.min.x, m->xy.y); p1 = Pt(g->r.max.x, m->xy.y); break; case Horizontal: p = Pt(middle_of_border.x, m->xy.y); p0 = Pt(m->xy.x, g->r.min.y); p1 = Pt(m->xy.x, g->r.max.y); break; } // setcursor(); oi = nil; } else if (g->lastbut != 0 && s->m.buttons != 0){ /* button is down, keep tracking border */ if(!eqpt(s->m.xy, p)){ p = onscreen(s->m.xy); r = canonrect(Rpt(p0, p)); if(Dx(r)>5 && Dy(r)>5){ i = allocwindow(wscreen, r, Refnone, 0xEEEEEEFF); /* grey */ freeimage(oi); if(i == nil) goto Rescue; oi = i; border(i, r, Selborder, red, ZP); flushimage(display, 1); } } } else if (g->lastbut != 0 && s->m.buttons == 0){ /* button went up, resize kiddies */ } g->lastbut = s->m.buttons; #endif }
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; } } }
void threadmain(int argc, char *argv[]) { int i, got, scr; Text *t; Rectangle r; Flayer *nwhich; getscreen(argc, argv); iconinit(); initio(); scratch = alloc(100*RUNESIZE); nscralloc = 100; r = screen->r; r.max.y = r.min.y+Dy(r)/5; flstart(screen->clipr); rinit(&cmd.rasp); flnew(&cmd.l[0], gettext, 1, &cmd); flinit(&cmd.l[0], r, font, cmdcols); cmd.nwin = 1; which = &cmd.l[0]; cmd.tag = Untagged; outTs(Tversion, VERSION); startnewfile(Tstartcmdfile, &cmd); got = 0; for(;;got = waitforio()){ if(hasunlocked && RESIZED()) resize(); if(got&(1<<RHost)) rcv(); if(got&(1<<RPlumb)){ for(i=0; cmd.l[i].textfn==0; i++) ; current(&cmd.l[i]); flsetselect(which, cmd.rasp.nrunes, cmd.rasp.nrunes); type(which, RPlumb); } if(got&(1<<RKeyboard)) if(which) type(which, RKeyboard); else kbdblock(); if(got&(1<<RMouse)){ if(hostlock==2 || !ptinrect(mousep->xy, screen->r)){ mouseunblock(); continue; } nwhich = flwhich(mousep->xy); scr = which && ptinrect(mousep->xy, which->scroll); if(mousep->buttons) flushtyping(1); if(mousep->buttons&1){ if(nwhich){ if(nwhich!=which) current(nwhich); else if(scr) scroll(which, 1); else{ t=(Text *)which->user1; if(flselect(which)){ outTsl(Tdclick, t->tag, which->p0); t->lock++; }else if(t!=&cmd) outcmd(); } } }else if((mousep->buttons&2) && which){ if(scr) scroll(which, 2); else menu2hit(); }else if((mousep->buttons&4)){ if(scr) scroll(which, 3); else menu3hit(); } mouseunblock(); } } }
int rectinrect(struct rect r1, struct rect r) { return ptinrect(r1.ll, r) && ptinrect(r1.ur, r); }
static long mousewrite(Chan *c, void *va, long n, vlong offset) { char *p; Point pt; Cmdbuf *cb; Cmdtab *ct; char buf[64]; int nn; p = va; switch((ulong)c->qid.path){ case Qdir: error(Eisdir); case Qcursor: if(n < 2*4+2*2*16){ curs = arrow; Cursortocursor(&arrow); }else{ n = 2*4+2*2*16; curs.offset.x = BGLONG(p+0); curs.offset.y = BGLONG(p+4); memmove(curs.clr, p+8, 2*16); memmove(curs.set, p+40, 2*16); Cursortocursor(&curs); } qlock(&mouse.qlk); mouse.redraw = 1; qunlock(&mouse.qlk); return n; case Qmousectl: cb = parsecmd(va, n); if(waserror()){ free(cb); nexterror(); } ct = lookupcmd(cb, mousectlmsg, nelem(mousectlmsg)); switch(ct->index){ case CMswap: if(mouseswap) setbuttonmap("123"); else setbuttonmap("321"); mouseswap ^= 1; break; case CMscrollswap: scrollswap ^= 1; break; case CMbuttonmap: if(cb->nf == 1) setbuttonmap("123"); else setbuttonmap(cb->f[1]); break; } free(cb); poperror(); return n; case Qmouse: if(n > sizeof buf-1) n = sizeof buf -1; memmove(buf, va, n); buf[n] = 0; p = 0; pt.x = strtoul(buf+1, &p, 0); if(p == 0) error(Eshort); pt.y = strtoul(p, 0, 0); qlock(&mouse.qlk); if(ptinrect(pt, mouserect)){ mouse.mstate.xy = pt; mouse.redraw = 1; mouse.track = 1; } qunlock(&mouse.qlk); setmouse(pt); return n; case Qsnarf: if(offset+n >= SnarfSize) error("too much snarf"); if(n == 0) return 0; assert(mousedir[Qsnarf].qid.path == Qsnarf); mousedir[Qsnarf].qid.vers++; if(c->aux == nil) nn = 0; else nn = strlen(c->aux); if(offset+n > nn){ nn = offset+n; p = smalloc(nn+1); if(c->aux){ strcpy(p, c->aux); free(c->aux); } c->aux = p; } memmove(c->aux+offset, va, n); return n; } error(Egreg); return -1; }
int pl_hitpulldown(Panel *g, Mouse *m){ int oldstate, passon; Rectangle r; Panel *p, *hitme; Pulldown *pp; pp=g->data; oldstate=g->state; p=pp->pull; hitme=0; switch(g->state){ case UP: if(!ptinrect(m->xy, g->r)) g->state=UP; else if(m->buttons&7){ r=g->b->r; p->flags&=~PLACE; switch(pp->side){ case PACKN: r.min.x=g->r.min.x; r.max.y=g->r.min.y; p->flags|=PLACESW; break; case PACKS: r.min.x=g->r.min.x; r.min.y=g->r.max.y; p->flags|=PLACENW; break; case PACKE: r.min.x=g->r.max.x; r.min.y=g->r.min.y; p->flags|=PLACENW; break; case PACKW: r.max.x=g->r.min.x; r.min.y=g->r.min.y; p->flags|=PLACENE; break; case PACKCEN: r.min=g->r.min; p->flags|=PLACENW; break; } plpack(p, r); pp->save=allocimage(display, p->r, g->b->chan, 0, DNofill); if(pp->save!=0) draw(pp->save, p->r, g->b, 0, p->r.min); pl_invis(p, 0); pldraw(p, g->b); g->state=DOWN; } break; case DOWN: if(!ptinrect(m->xy, g->r)){ switch(pp->side){ default: SET(passon); break; /* doesn't happen */ case PACKN: passon=m->xy.y<g->r.min.y; break; case PACKS: passon=m->xy.y>=g->r.max.y; break; case PACKE: passon=m->xy.x>=g->r.max.x; break; case PACKW: passon=m->xy.x<g->r.min.x; break; case PACKCEN: passon=1; break; } if(passon){ hitme=p; if((m->buttons&7)==0) g->state=UP; } else g->state=UP; } else if((m->buttons&7)==0) g->state=UP; else hitme=p; if(g->state!=DOWN && pp->save){ draw(g->b, p->r, pp->save, 0, p->r.min); freeimage(pp->save); pp->save=0; pl_invis(p, 1); hitme=p; } } if(g->state!=oldstate) pldraw(g, g->b); if(hitme) plmouse(hitme, m); return g->state==DOWN; }
/* Funkcja rectinrect sprawdza, czy prostokat r1 zawiera sie w prostokacie r2. Sprawdza, czy punkty ll i ur prostokata r1 naleza do r2, jesli tak to r1 zawiera sie w r2 */ int rectinrect(struct rect r1, struct rect r2){ if(ptinrect(r1.ll,r2) == 1 && ptinrect(r1.ur,r2)==1) {return 1;} else return 0; }
int disjointrect(struct rect r1, struct rect r2) { return !(ptinrect(r2.ll, r1)) && !(ptinrect(r2.ur, r1)) && !(ptinrect(r1.ll, r2)) && !(ptinrect(r1.ur, r2)); };
int menuhit(int but, Mousectl *mc, Menu *menu, Screen *scr) { int i, nitem, nitemdrawn, maxwid, lasti, off, noff, wid, screenitem; int scrolling; Rectangle r, menur, sc, textr, scrollr; Image *b, *save, *backup; Point pt; char *item; if(back == nil) menucolors(); sc = screen->clipr; replclipr(screen, 0, screen->r); maxwid = 0; for(nitem = 0; item = menu->item? menu->item[nitem] : (*menu->gen)(nitem); nitem++){ i = stringwidth(font, item); if(i > maxwid) maxwid = i; } if(menu->lasthit<0 || menu->lasthit>=nitem) menu->lasthit = 0; screenitem = (Dy(screen->r)-10)/(font->height+Vspacing); if(nitem>Maxunscroll || nitem>screenitem){ scrolling = 1; nitemdrawn = Nscroll; if(nitemdrawn > screenitem) nitemdrawn = screenitem; wid = maxwid + Gap + Scrollwid; off = menu->lasthit - nitemdrawn/2; if(off < 0) off = 0; if(off > nitem-nitemdrawn) off = nitem-nitemdrawn; lasti = menu->lasthit-off; }else{ scrolling = 0; nitemdrawn = nitem; wid = maxwid; off = 0; lasti = menu->lasthit; } r = insetrect(Rect(0, 0, wid, nitemdrawn*(font->height+Vspacing)), -Margin); r = rectsubpt(r, Pt(wid/2, lasti*(font->height+Vspacing)+font->height/2)); r = rectaddpt(r, mc->m.xy); pt = ZP; if(r.max.x>screen->r.max.x) pt.x = screen->r.max.x-r.max.x; if(r.max.y>screen->r.max.y) pt.y = screen->r.max.y-r.max.y; if(r.min.x<screen->r.min.x) pt.x = screen->r.min.x-r.min.x; if(r.min.y<screen->r.min.y) pt.y = screen->r.min.y-r.min.y; menur = rectaddpt(r, pt); textr.max.x = menur.max.x-Margin; textr.min.x = textr.max.x-maxwid; textr.min.y = menur.min.y+Margin; textr.max.y = textr.min.y + nitemdrawn*(font->height+Vspacing); if(scrolling){ scrollr = insetrect(menur, Border); scrollr.max.x = scrollr.min.x+Scrollwid; }else scrollr = Rect(0, 0, 0, 0); if(scr){ b = allocwindow(scr, menur, Refbackup, DWhite); if(b == nil) b = screen; backup = nil; }else{ b = screen; backup = allocimage(display, menur, screen->chan, 0, -1); if(backup) draw(backup, menur, screen, nil, menur.min); } draw(b, menur, back, nil, ZP); border(b, menur, Blackborder, bord, ZP); save = allocimage(display, menurect(textr, 0), screen->chan, 0, -1); r = menurect(textr, lasti); moveto(mc, divpt(addpt(r.min, r.max), 2)); menupaint(b, menu, textr, off, nitemdrawn); if(scrolling) menuscrollpaint(b, scrollr, off, nitem, nitemdrawn); while(mc->m.buttons & (1<<(but-1))){ lasti = menuscan(b, menu, but, mc, textr, off, lasti, save); if(lasti >= 0) break; while(!ptinrect(mc->m.xy, textr) && (mc->m.buttons & (1<<(but-1)))){ if(scrolling && ptinrect(mc->m.xy, scrollr)){ noff = ((mc->m.xy.y-scrollr.min.y)*nitem)/Dy(scrollr); noff -= nitemdrawn/2; if(noff < 0) noff = 0; if(noff > nitem-nitemdrawn) noff = nitem-nitemdrawn; if(noff != off){ off = noff; menupaint(b, menu, textr, off, nitemdrawn); menuscrollpaint(b, scrollr, off, nitem, nitemdrawn); } } readmouse(mc); } } if(b != screen) freeimage(b); if(backup){ draw(screen, menur, backup, nil, menur.min); freeimage(backup); } freeimage(save); replclipr(screen, 0, sc); flushimage(display, 1); if(lasti >= 0){ menu->lasthit = lasti+off; return menu->lasthit; } return -1; }
void main(int argc, char *argv[]) { Mouse m; int i, j; unsigned short ran, score, attempt, prev, br[2]; Image *c[2]; char *fmt; level = 16; fmt = "win in %d attempts!"; ARGBEGIN{ default: goto Usage; case 'h': level=36; break; }ARGEND if(argc){ Usage: fprint(2, "usage: %s [-h]\n", argv0); exits("usage"); } if(initdraw(0,0,"memo") < 0) sysfatal("initdraw failed: %r"); srand(time(0)); memoinit(); einit(Emouse); Start: afaces(); winflag=0; prev=level+1; score=attempt=0; for(i=0;i!=level;i++) block[i].flag = Eninit; for(i=0;i!=level/2;i++){ for(j=0;j!=2;){ ran = rand()%level; if(block[ran].flag == Eninit){ block[ran].face = face[i]; block[ran].flag = Eshow; j++; } } } eresized(0); for(;;m=emouse()) if(m.buttons) break; for(i=0;i!=level;i++) block[i].flag = Ehide; redraw(); j = 0; for(;; m=emouse()){ switch(m.buttons){ case 1: while(m.buttons){ for(i=0;i!=level;i++){ if(i!=prev && ptinrect(m.xy,block[i].r)){ if(block[i].flag==Ehide && j<2){ block[i].flag = Eshow; draw(screen, block[i].r, block[i].face, nil, ZP); c[j] = block[i].face; br[j] = prev = i; j++; } break; } } m=emouse(); } break; case 4: switch(emenuhit(3, &m, &menu)) { case 0: /* restart */ goto Start; break; case 1: level=16; goto Start; break; case 2: level=36; goto Start; break; case 3: exits(0); break; } } if(j==2){ attempt++; prev = level+1; j = 0; if(c[0] == c[1]){ score++; block[br[0]].flag = Edisc; block[br[1]].flag = Edisc; } else{ block[br[0]].flag = Ehide; block[br[1]].flag = Ehide; } redraw(); continue; } if(score == level/2){ winflag = 1; sprint(buf, fmt, attempt); redraw(); for(;;m=emouse()) if(m.buttons&1 || m.buttons&4) break; goto Start; } } }