#include "dat.h" #include "fn.h" enum { Asciitofull = 0xFEE0, }; static void fill(u32int *buf, int n, u32int color) { int i; for(i = 0; i < n; i++) buf[i] = color; } static void fillrect(u32int *buf, int w, int h, int x, int y, int rw, int rh, u32int color) { int x0, x1, y0, y1; x0 = min(max(x, 0), w); x1 = min(max(x + max(rw, 0), 0), w); y0 = min(max(y, 0), h); y1 = min(max(y + max(rh, 0), 0), h); for(; y0 < y1; y0++) fill(buf + y0*w + x0, max(x1 - x0, 0), color); } int pagemarker(char *buf, int nbuf, int first, int shown, int total) { if(nbuf <= 0) return 0; buf[0] = 0; if(total <= Maxdisp || shown <= 0) return 0; return snprint(buf, nbuf, "%d-%d/%d", first + 1, first + shown, total); } void popuplayout(Drawcmd *dc, int screenw, Popup *p) { char buf[32]; vlong width; Str mark; int i, maxw, nmark, npre, roww, y; memset(p, 0, sizeof *p); p->prey = -1; p->sepy = -1; p->rowsy = -1; p->markx = -1; p->marky = -1; p->sely = -1; p->n = min(max(dc->nkouho, 0), Maxdisp); npre = dc->pre.n != 0; if(p->n == 0 && !npre) return; maxw = npre ? textwidth(&dc->pre) : 0; roww = 0; for(i = 0; i < p->n; i++) roww = max(roww, textwidth(&dc->kouho[i])); if(p->n != 0) maxw = max(maxw, PopupNumw + roww); nmark = pagemarker(buf, sizeof buf, dc->first, p->n, dc->total); if(nmark != 0){ sinit(&mark, buf, nmark); maxw = max(maxw, textwidth(&mark)); } width = (vlong)maxw + 2*PopupPad; p->w = min(min(max(width, 1), Imgw), max(screenw, 0)); y = PopupPad; if(npre){ p->prey = y; y += Fontsz; } if(npre && p->n != 0){ p->sepy = y; y += PopupSep; } if(p->n != 0){ p->rowsy = y; y += p->n*Fontsz; } if(nmark != 0){ p->marky = y; y += Fontsz; } p->h = y + PopupPad; p->numx = PopupPad; p->textx = PopupPad + PopupNumw; p->textw = max(p->w - PopupPad - p->textx, 0); if(nmark != 0){ p->markw = min(textwidth(&mark), max(p->w - 2*PopupPad, 0)); p->markx = p->w - PopupPad - p->markw; } p->selx = PopupPad; p->selw = max(p->w - 2*PopupPad, 0); if(dc->sel >= 0 && dc->sel < p->n) p->sely = p->rowsy + dc->sel*Fontsz; } void popupdraw(u32int *img, Drawcmd *dc, Popup *p) { char buf[32]; Str mark, num; u32int color; int i, nmark, y; if(img == nil || p->n < 0 || p->n > Maxdisp || p->w <= 0 || p->w > Imgw || p->h <= 0 || p->h > Imgh) return; fill(img, p->w*p->h, Colbg); if(p->prey >= 0) textdrawfit(img, p->w, p->h, PopupPad, p->prey, max(p->w - 2*PopupPad, 0), &dc->pre); if(p->sepy >= 0) fillrect(img, p->w, p->h, PopupPad, p->sepy, p->w - 2*PopupPad, PopupSep, Colsep); if(p->sely >= 0) fillrect(img, p->w, p->h, p->selx, p->sely, p->selw, Fontsz, Colsel); for(i = 0, y = p->rowsy; i < p->n; i++, y += Fontsz){ color = i == dc->sel ? Colselfg : Colfg; sclear(&num); sputr(&num, '1' + i + Asciitofull); textdrawfitcolor(img, p->w, p->h, p->numx, y, min(PopupNumw, max(p->w - PopupPad - p->numx, 0)), color, &num); textdrawfitcolor(img, p->w, p->h, p->textx, y, p->textw, color, &dc->kouho[i]); } nmark = pagemarker(buf, sizeof buf, dc->first, p->n, dc->total); if(nmark != 0 && p->marky >= 0){ sinit(&mark, buf, nmark); textdrawfit(img, p->w, p->h, p->markx, p->marky, p->markw, &mark); } } void popupposition(Caret *caret, int pointerx, int pointery, int screenw, int screenh, int w, int h, int *x, int *y) { vlong below, px, py, xmax, ymax; if(caret->valid){ px = caret->x; below = (vlong)caret->y + max(caret->h, 0); if(below >= 0 && below + h <= screenh) py = below; else py = (vlong)caret->y - h; }else{ px = (vlong)pointerx + 10; py = (vlong)pointery + 10; } xmax = max((vlong)screenw - w, 0); ymax = max((vlong)screenh - h, 0); *x = max(0, min(px, xmax)); *y = max(0, min(py, ymax)); }