ref: a18bf6d737025e05989a826895a5c332897cf492
dir: /sys/src/cmd/jamterm/win.c/
#include <u.h> #include <libc.h> #include <draw.h> #include <thread.h> #include <mouse.h> #include <keyboard.h> #include <frame.h> #include "flayer.h" #include "samterm.h" enum{ SnapΔ = 24 * FLMARGIN, }; int max(int a, int b) { return a > b ? a : b; } int min(int a, int b) { return a < b ? a : b; } Rectangle defaultcmdrect(void) { int rw, rh, fw, fh; Rectangle r; fw = stringwidth(font, "0"); fh = font->height; rw = Dx(screen->r) / fw; rh = Dy(screen->r) / fh; r = screen->r; if(rw < 6 || rh < 3){ ; }else if(rw >= 120){ r.min.x = r.max.x - 72 * fw; r.min.y = max(r.max.y - 8 * fh, r.min.y + 2*fh); }else r.max.y = r.min.y + 2*fh + min(max(Dy(screen->r) / 6, 0), 12*fh); return r; } /* always prefer innermost border in case of ties */ static int cansnap(int a, int b, int Δ) { int δ; return (δ = abs(a - b)) <= Δ && (δ != Δ || a < b); } /* use borders of all rects next to ours as guides to snap to */ static Rectangle snaprect(Rectangle r, Flayer *l) { int i; Rectangle Δr, s, rr, c; Flayer *fl; Text *t; rr = insetrect(r, -SnapΔ); Δr = Rect(SnapΔ, SnapΔ, SnapΔ, SnapΔ); s = r; for(i=0; i<nname; i++){ t = text[i]; if(t == nil || t->nwin == 0) continue; for(fl=t->l; fl<t->l+NL; fl++){ if(fl->textfn == nil || fl == l) continue; c = fl->entire; if(!rectXrect(rr, c)) continue; if(cansnap(r.min.x, c.max.x, Δr.min.x)) /* adjacent border */ s.min.x = c.max.x, Δr.min.x = abs(r.min.x - c.max.x); else if(cansnap(r.min.x, c.min.x, Δr.min.x)) /* adjacent guide line */ s.min.x = c.min.x, Δr.min.x = abs(r.min.x - c.min.x); if(cansnap(r.min.y, c.max.y, Δr.min.y)) s.min.y = c.max.y, Δr.min.y = abs(r.min.y - c.max.y); else if(cansnap(r.min.y, c.min.y, Δr.min.y)) s.min.y = c.min.y, Δr.min.y = abs(r.min.y - c.min.y); if(cansnap(c.min.x, r.max.x, Δr.max.x)) s.max.x = c.min.x, Δr.max.x = abs(c.min.x - r.max.x); else if(cansnap(c.max.x, r.max.x, Δr.max.x)) s.max.x = c.max.x, Δr.max.x = abs(c.max.x - r.max.x); if(cansnap(c.min.y, r.max.y, Δr.max.y)) s.max.y = c.min.y, Δr.max.y = abs(c.min.y - r.max.y); else if(cansnap(c.max.y, r.max.y, Δr.max.y)) s.max.y = c.max.y, Δr.max.y = abs(c.max.y - r.max.y); } } if(cansnap(r.min.x, screen->r.min.x, Δr.min.x)) s.min.x = screen->r.min.x; if(cansnap(r.min.y, screen->r.min.y, Δr.min.y)) s.min.y = screen->r.min.y; if(cansnap(screen->r.max.x, r.max.x, Δr.max.x)) s.max.x = screen->r.max.x; if(cansnap(screen->r.max.y, r.max.y, Δr.max.y)) s.max.y = screen->r.max.y; return s; } /* in case of overlaps, always glob the smallest rect rather than * the biggest to maintain splits and selectable flayers */ static Rectangle stealrect(Point p) { int i; Rectangle c, r; Flayer *fl; Text *t; r = screen->r; for(i=0; i<nname; i++){ t = text[i]; if(t == nil || t->nwin == 0) continue; for(fl=t->l; fl<t->l+NL; fl++){ if(fl->textfn == nil || !ptinrect(p, fl->entire)) continue; c = fl->entire; if(Dx(c) * Dy(c) < Dx(r) * Dy(r)) r = c; } } return r; } static Rectangle fillvoid(Point p, Flayer *l, int new) { int i; Rectangle c, r; Flayer *fl; Text *t; r = screen->r; for(i=0; i<nname; i++){ t = text[i]; if(t == nil || t->nwin == 0) continue; for(fl=t->l; fl<t->l+NL; fl++){ c = fl->entire; if(fl->textfn == nil || !rectXrect(r, c)) continue; if(!new && fl == l) continue; if(ptinrect(p, fl->entire)) return ZR; if(c.max.x <= p.x && c.max.x > r.min.x) r.min.x = c.max.x; if(p.x <= c.min.x && c.min.x < r.max.x) r.max.x = c.min.x; if(!rectXrect(c, r)) continue; if(c.max.y <= p.y && c.max.y > r.min.y) r.min.y = c.max.y; if(p.y <= c.min.y && c.min.y < r.max.y) r.max.y = c.min.y; } if(Dx(r) < 2*font->width || Dy(r) < font->height) return ZR; } return r; } int promptrect(Rectangle *rp, Flayer *l, int new) { Point p; Rectangle r; r = getrect(3, mousectl); if(eqrect(r, ZR)){ *rp = r; return 0; /* around the minimum for libframe to not choke */ }else if(Dx(r) < 2 * stringwidth(font, "0") + 2 * FLMARGIN || Dy(r) < font->height + 2 * FLMARGIN){ p = r.min; /* mousep->xy == r.max */ if(!ptinrect(p, screen->r)) return 0; r = fillvoid(p, l, new); if(eqrect(r, ZR)) r = stealrect(p); }else r = snaprect(r, l); *rp = r; return 1; }