170 lines
3.7 KiB
C
170 lines
3.7 KiB
C
#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));
|
|
}
|