popup: refine the input panel
This commit is contained in:
29
dat.h
29
dat.h
@@ -18,6 +18,9 @@ enum
|
||||
LangVI = 0x16,
|
||||
|
||||
Fontsz = 32,
|
||||
PopupPad = 4,
|
||||
PopupSep = 1,
|
||||
PopupNumw = Fontsz,
|
||||
Maxrunes = 64,
|
||||
Maxutf = Maxrunes * UTFmax + 1,
|
||||
};
|
||||
@@ -28,11 +31,13 @@ enum
|
||||
Maxkouho = 32,
|
||||
Maxdisp = 9,
|
||||
Imgw = (Maxrunes + 3) * Fontsz,
|
||||
Imgh = (Maxdisp + 2) * Fontsz,
|
||||
Imgh = 2*PopupPad + (Maxdisp + 2)*Fontsz + PopupSep,
|
||||
|
||||
Colfg = 0x000000,
|
||||
Colbg = 0xffffff,
|
||||
Colsel = 0xcccccc,
|
||||
Colsep = 0xd0d0d0,
|
||||
Colsel = 0x333333,
|
||||
Colselfg = 0xffffff,
|
||||
};
|
||||
|
||||
typedef struct Str Str;
|
||||
@@ -137,6 +142,26 @@ struct Drawcmd
|
||||
Caret caret;
|
||||
};
|
||||
|
||||
typedef struct Popup Popup;
|
||||
struct Popup
|
||||
{
|
||||
int w;
|
||||
int h;
|
||||
int n;
|
||||
int prey;
|
||||
int sepy;
|
||||
int rowsy;
|
||||
int numx;
|
||||
int textx;
|
||||
int textw;
|
||||
int markx;
|
||||
int marky;
|
||||
int markw;
|
||||
int selx;
|
||||
int sely;
|
||||
int selw;
|
||||
};
|
||||
|
||||
typedef struct Keyreq Keyreq;
|
||||
typedef struct Keyres Keyres;
|
||||
enum
|
||||
|
||||
3
fn.h
3
fn.h
@@ -30,6 +30,8 @@ void dictlookup(Dictreq*, Dictres*);
|
||||
void drawthread(void*);
|
||||
void popupposition(Caret*, int, int, int, int, int, int, int*, int*);
|
||||
int pagemarker(char*, int, int, int, int);
|
||||
void popuplayout(Drawcmd*, int, Popup*);
|
||||
void popupdraw(u32int*, Drawcmd*, Popup*);
|
||||
void imthread(void*);
|
||||
Emit transmap(Im*, Rune);
|
||||
Emit transko(Im*, Rune);
|
||||
@@ -50,3 +52,4 @@ int textinit(void);
|
||||
int textwidth(Str*);
|
||||
void textdraw(u32int*, int, int, int, int, Str*);
|
||||
void textdrawfit(u32int*, int, int, int, int, int, Str*);
|
||||
void textdrawfitcolor(u32int*, int, int, int, int, int, u32int, Str*);
|
||||
|
||||
21
font.c
21
font.c
@@ -117,12 +117,13 @@ textwidth(Str *s)
|
||||
}
|
||||
|
||||
static void
|
||||
drawtext(u32int *buf, int w, int h, int x, int y, int fit, Str *s)
|
||||
drawtext(u32int *buf, int w, int h, int x, int y, int fit, u32int color,
|
||||
Str *s)
|
||||
{
|
||||
PangoRectangle r;
|
||||
cairo_surface_t *surface;
|
||||
cairo_t *cr;
|
||||
int stride;
|
||||
int b, g, red, stride;
|
||||
|
||||
if(layout == nil)
|
||||
return;
|
||||
@@ -156,7 +157,10 @@ drawtext(u32int *buf, int w, int h, int x, int y, int fit, Str *s)
|
||||
cairo_rectangle(cr, 0, y, w, Fontsz);
|
||||
cairo_clip(cr);
|
||||
cairo_move_to(cr, x - r.x, y + (Fontsz - r.height) / 2 - r.y);
|
||||
cairo_set_source_rgb(cr, 0, 0, 0);
|
||||
red = color >> 16 & 0xff;
|
||||
g = color >> 8 & 0xff;
|
||||
b = color & 0xff;
|
||||
cairo_set_source_rgb(cr, red / 255.0, g / 255.0, b / 255.0);
|
||||
pango_cairo_show_layout(cr, layout);
|
||||
}
|
||||
cairo_destroy(cr);
|
||||
@@ -167,11 +171,18 @@ drawtext(u32int *buf, int w, int h, int x, int y, int fit, Str *s)
|
||||
void
|
||||
textdraw(u32int *buf, int w, int h, int x, int y, Str *s)
|
||||
{
|
||||
drawtext(buf, w, h, x, y, -1, s);
|
||||
drawtext(buf, w, h, x, y, -1, Colfg, s);
|
||||
}
|
||||
|
||||
void
|
||||
textdrawfit(u32int *buf, int w, int h, int x, int y, int fit, Str *s)
|
||||
{
|
||||
drawtext(buf, w, h, x, y, fit, s);
|
||||
drawtext(buf, w, h, x, y, fit, Colfg, s);
|
||||
}
|
||||
|
||||
void
|
||||
textdrawfitcolor(u32int *buf, int w, int h, int x, int y, int fit,
|
||||
u32int color, Str *s)
|
||||
{
|
||||
drawtext(buf, w, h, x, y, fit, color, s);
|
||||
}
|
||||
|
||||
132
popup_layout.c
132
popup_layout.c
@@ -1,6 +1,33 @@
|
||||
#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)
|
||||
{
|
||||
@@ -13,6 +40,111 @@ pagemarker(char *buf, int nbuf, int first, int shown, int total)
|
||||
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)
|
||||
|
||||
@@ -179,7 +179,7 @@ font_render(struct ct *t)
|
||||
static char *plain[] = { "A", "가", "あ", "漢", "☆", "𠀋" };
|
||||
u32int *buf, *mem;
|
||||
Str a, heart, longrow, missing;
|
||||
int i, natural, w, x, y;
|
||||
int i, maxx, maxy, minx, miny, natural, w, x, y;
|
||||
|
||||
mem = emalloc((Testn + 2 * Guard) * sizeof mem[0]);
|
||||
fillpixels(mem, Testn + 2 * Guard, guardcolor);
|
||||
@@ -231,6 +231,21 @@ font_render(struct ct *t)
|
||||
}
|
||||
CT_EQ_INT(t, natural, textwidth(&longrow));
|
||||
|
||||
fillpixels(buf, Testn, Colsel);
|
||||
textdrawfitcolor(buf, Testw, Testh, 2*Fontsz, Fontsz,
|
||||
2*Fontsz, Colselfg, &longrow);
|
||||
CT_CHECK(t, (Colselfg & Rgbmask) != (Colsel & Rgbmask));
|
||||
if(CT_CHECK(t, inkbounds(buf, Colsel,
|
||||
&minx, &miny, &maxx, &maxy))){
|
||||
CT_CHECK(t, minx >= 2*Fontsz);
|
||||
CT_CHECK(t, maxx < 4*Fontsz);
|
||||
CT_CHECK(t, miny >= Fontsz);
|
||||
CT_CHECK(t, maxy < 2*Fontsz);
|
||||
}
|
||||
checkoutside(t, buf, Colsel, Fontsz);
|
||||
checkguards(t, mem);
|
||||
CT_EQ_INT(t, natural, textwidth(&longrow));
|
||||
|
||||
missing = mkstr("\xF4\x8F\xBF\xBF");
|
||||
for(i = 0; i < 32; i++){
|
||||
textdraw(buf, Testw, Testh, Fontsz, Fontsz, &heart);
|
||||
|
||||
@@ -1,6 +1,41 @@
|
||||
#include "test.h"
|
||||
#include <limits.h>
|
||||
|
||||
enum {
|
||||
Rgbmask = 0xffffff,
|
||||
};
|
||||
|
||||
static u32int
|
||||
pixel(u32int *img, Popup *p, int x, int y)
|
||||
{
|
||||
return img[y*p->w + x] & Rgbmask;
|
||||
}
|
||||
|
||||
static int
|
||||
rectcolor(u32int *img, Popup *p, int x0, int y0, int x1, int y1,
|
||||
u32int color)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
color &= Rgbmask;
|
||||
for(y = y0; y < y1; y++)
|
||||
for(x = x0; x < x1; x++)
|
||||
if(pixel(img, p, x, y) != color)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
checkpadding(struct ct *t, u32int *img, Popup *p)
|
||||
{
|
||||
CT_CHECK(t, rectcolor(img, p, 0, 0, p->w, PopupPad, Colbg));
|
||||
CT_CHECK(t, rectcolor(img, p, 0, p->h - PopupPad,
|
||||
p->w, p->h, Colbg));
|
||||
CT_CHECK(t, rectcolor(img, p, 0, 0, PopupPad, p->h, Colbg));
|
||||
CT_CHECK(t, rectcolor(img, p, p->w - PopupPad, 0,
|
||||
p->w, p->h, Colbg));
|
||||
}
|
||||
|
||||
void
|
||||
popup_layout(struct ct *t)
|
||||
{
|
||||
@@ -22,7 +57,11 @@ popup_layout(struct ct *t)
|
||||
};
|
||||
char buf[32];
|
||||
Caret caret;
|
||||
int i, n, x, y;
|
||||
Drawcmd dc;
|
||||
Popup p;
|
||||
Str longrow;
|
||||
u32int c, *img;
|
||||
int i, ink, markink, n, numink, selbg, textink, x, y;
|
||||
|
||||
for(i = 0; i < nelem(markers); i++){
|
||||
n = pagemarker(buf, sizeof buf, markers[i].first,
|
||||
@@ -30,7 +69,8 @@ popup_layout(struct ct *t)
|
||||
CT_EQ_INT(t, strlen(markers[i].want), n);
|
||||
CT_CHECK(t, strcmp(markers[i].want, buf) == 0);
|
||||
}
|
||||
CT_EQ_INT(t, (1 + Maxdisp + 1) * Fontsz, Imgh);
|
||||
CT_EQ_INT(t, 2*PopupPad + (1 + Maxdisp + 1)*Fontsz + PopupSep,
|
||||
Imgh);
|
||||
|
||||
memset(&caret, 0, sizeof caret);
|
||||
popupposition(&caret, 40, 50, 800, 600, 100, 60, &x, &y);
|
||||
@@ -81,4 +121,157 @@ popup_layout(struct ct *t)
|
||||
INT_MAX, INT_MAX, &x, &y);
|
||||
CT_EQ_INT(t, 0, x);
|
||||
CT_EQ_INT(t, 0, y);
|
||||
|
||||
if(!CT_CHECK(t, textinit()))
|
||||
return;
|
||||
|
||||
/* Empty sections reserve nothing. */
|
||||
memset(&dc, 0, sizeof dc);
|
||||
dc.sel = -1;
|
||||
popuplayout(&dc, Imgw, &p);
|
||||
CT_EQ_INT(t, 0, p.w);
|
||||
CT_EQ_INT(t, 0, p.h);
|
||||
CT_EQ_INT(t, -1, p.prey);
|
||||
CT_EQ_INT(t, -1, p.rowsy);
|
||||
CT_EQ_INT(t, -1, p.marky);
|
||||
|
||||
/* Preedit only. */
|
||||
dc.pre = mkstr("preedit");
|
||||
popuplayout(&dc, Imgw, &p);
|
||||
CT_EQ_INT(t, PopupPad, p.prey);
|
||||
CT_EQ_INT(t, -1, p.sepy);
|
||||
CT_EQ_INT(t, -1, p.rowsy);
|
||||
CT_EQ_INT(t, -1, p.marky);
|
||||
CT_EQ_INT(t, 2*PopupPad + Fontsz, p.h);
|
||||
|
||||
/* Candidates only. */
|
||||
memset(&dc, 0, sizeof dc);
|
||||
dc.sel = -1;
|
||||
dc.nkouho = 2;
|
||||
dc.kouho[0] = mkstr("short");
|
||||
dc.kouho[1] = mkstr("candidate");
|
||||
popuplayout(&dc, Imgw, &p);
|
||||
CT_EQ_INT(t, -1, p.prey);
|
||||
CT_EQ_INT(t, -1, p.sepy);
|
||||
CT_EQ_INT(t, PopupPad, p.rowsy);
|
||||
CT_EQ_INT(t, -1, p.marky);
|
||||
CT_EQ_INT(t, 2*PopupPad + 2*Fontsz, p.h);
|
||||
CT_EQ_INT(t, PopupPad, p.numx);
|
||||
CT_EQ_INT(t, p.numx + PopupNumw, p.textx);
|
||||
CT_EQ_INT(t, p.w - PopupPad, p.textx + p.textw);
|
||||
|
||||
/* Preedit and candidates meet at one separator, with no empty rows. */
|
||||
dc.pre = mkstr("preedit");
|
||||
popuplayout(&dc, Imgw, &p);
|
||||
CT_EQ_INT(t, PopupPad, p.prey);
|
||||
CT_EQ_INT(t, p.prey + Fontsz, p.sepy);
|
||||
CT_EQ_INT(t, p.sepy + PopupSep, p.rowsy);
|
||||
CT_EQ_INT(t, -1, p.marky);
|
||||
CT_EQ_INT(t, p.rowsy + 2*Fontsz + PopupPad, p.h);
|
||||
CT_EQ_INT(t, 2*PopupPad + 3*Fontsz + PopupSep, p.h);
|
||||
|
||||
/* The largest panel includes all sections and fits its backing image. */
|
||||
memset(&dc, 0, sizeof dc);
|
||||
dc.pre = mkstr("preedit");
|
||||
dc.nkouho = Maxdisp;
|
||||
dc.sel = 4;
|
||||
dc.first = 0;
|
||||
dc.total = Maxdisp + 1;
|
||||
sclear(&longrow);
|
||||
for(i = 0; i < Maxrunes; i++)
|
||||
sputr(&longrow, 'W');
|
||||
for(i = 0; i < Maxdisp; i++)
|
||||
dc.kouho[i] = mkstr(i == dc.sel ? "M" : "candidate");
|
||||
dc.kouho[0] = longrow;
|
||||
popuplayout(&dc, Imgw, &p);
|
||||
CT_EQ_INT(t, Maxdisp, p.n);
|
||||
CT_EQ_INT(t, PopupPad, p.prey);
|
||||
CT_EQ_INT(t, p.prey + Fontsz, p.sepy);
|
||||
CT_EQ_INT(t, p.sepy + PopupSep, p.rowsy);
|
||||
CT_EQ_INT(t, p.rowsy + Maxdisp*Fontsz, p.marky);
|
||||
CT_EQ_INT(t, p.marky + Fontsz + PopupPad, p.h);
|
||||
CT_EQ_INT(t, Imgh, p.h);
|
||||
CT_CHECK(t, p.w > 2*PopupPad + PopupNumw);
|
||||
CT_CHECK(t, p.w <= Imgw);
|
||||
CT_CHECK(t, p.h <= Imgh);
|
||||
CT_EQ_INT(t, p.w - PopupPad, p.markx + p.markw);
|
||||
CT_EQ_INT(t, PopupPad, p.selx);
|
||||
CT_EQ_INT(t, p.w - 2*PopupPad, p.selw);
|
||||
CT_EQ_INT(t, p.rowsy + dc.sel*Fontsz, p.sely);
|
||||
CT_EQ_INT(t, PopupPad, p.numx);
|
||||
CT_EQ_INT(t, p.numx + PopupNumw, p.textx);
|
||||
CT_EQ_INT(t, p.w - PopupPad, p.textx + p.textw);
|
||||
|
||||
img = emalloc(Imgw*Imgh*sizeof img[0]);
|
||||
popupdraw(img, &dc, &p);
|
||||
checkpadding(t, img, &p);
|
||||
for(x = 0; x < p.w; x++)
|
||||
CT_EQ_UINT(t,
|
||||
x >= PopupPad && x < p.w - PopupPad ? Colsep : Colbg,
|
||||
pixel(img, &p, x, p.sepy));
|
||||
|
||||
/* Selection paint and both foreground columns stay inside the row. */
|
||||
selbg = numink = textink = 0;
|
||||
for(y = p.sely; y < p.sely + Fontsz; y++){
|
||||
for(x = 0; x < p.w; x++){
|
||||
c = pixel(img, &p, x, y);
|
||||
if(x < p.selx || x >= p.selx + p.selw){
|
||||
CT_EQ_UINT(t, Colbg, c);
|
||||
continue;
|
||||
}
|
||||
if(c == (Colsel & Rgbmask)){
|
||||
selbg++;
|
||||
continue;
|
||||
}
|
||||
CT_CHECK(t,
|
||||
(x >= p.numx && x < p.numx + PopupNumw) ||
|
||||
(x >= p.textx && x < p.textx + p.textw));
|
||||
if(x < p.numx + PopupNumw)
|
||||
numink++;
|
||||
else
|
||||
textink++;
|
||||
}
|
||||
}
|
||||
CT_CHECK(t, Colsel != Colselfg);
|
||||
CT_CHECK(t, selbg > p.selw*Fontsz/2);
|
||||
CT_CHECK(t, numink > 0);
|
||||
CT_CHECK(t, textink > 0);
|
||||
|
||||
/* The marker occupies only its compact, right-aligned footer box. */
|
||||
markink = 0;
|
||||
for(y = p.marky; y < p.marky + Fontsz; y++){
|
||||
for(x = 0; x < p.w; x++){
|
||||
if(pixel(img, &p, x, y) == (Colbg & Rgbmask))
|
||||
continue;
|
||||
markink++;
|
||||
CT_CHECK(t, x >= p.markx && x < p.markx + p.markw);
|
||||
}
|
||||
}
|
||||
CT_CHECK(t, markink > 0);
|
||||
|
||||
/* A fitted long row is bounded by the fixed candidate content area. */
|
||||
memset(&dc, 0, sizeof dc);
|
||||
dc.sel = -1;
|
||||
dc.nkouho = 1;
|
||||
dc.kouho[0] = longrow;
|
||||
n = textwidth(&longrow);
|
||||
popuplayout(&dc, 6*Fontsz, &p);
|
||||
CT_CHECK(t, n > p.textw);
|
||||
CT_EQ_INT(t, PopupPad, p.rowsy);
|
||||
CT_EQ_INT(t, p.w - PopupPad, p.textx + p.textw);
|
||||
popupdraw(img, &dc, &p);
|
||||
ink = 0;
|
||||
for(y = p.rowsy; y < p.rowsy + Fontsz; y++){
|
||||
for(x = 0; x < p.w; x++){
|
||||
c = pixel(img, &p, x, y);
|
||||
if(x < PopupPad || x >= p.w - PopupPad)
|
||||
CT_EQ_UINT(t, Colbg, c);
|
||||
if(x >= p.textx && x < p.textx + p.textw &&
|
||||
c != (Colbg & Rgbmask))
|
||||
ink++;
|
||||
}
|
||||
}
|
||||
CT_CHECK(t, ink > 0);
|
||||
CT_EQ_INT(t, n, textwidth(&longrow));
|
||||
free(img);
|
||||
}
|
||||
|
||||
76
win.c
76
win.c
@@ -2,10 +2,6 @@
|
||||
#include "dat.h"
|
||||
#include "fn.h"
|
||||
|
||||
enum {
|
||||
Asciitofull = 0xFEE0,
|
||||
};
|
||||
|
||||
static xcb_connection_t *conn;
|
||||
static xcb_screen_t *scr;
|
||||
static xcb_window_t win;
|
||||
@@ -146,46 +142,6 @@ wininit(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
fill(u32int *buf, int n, u32int color)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < n; i++)
|
||||
buf[i] = color;
|
||||
}
|
||||
|
||||
static void
|
||||
drawkouho(Drawcmd *dc, int n, int w, int h)
|
||||
{
|
||||
char buf[32];
|
||||
int nmark, npre, sely, y, i;
|
||||
Str mark, num, *s;
|
||||
|
||||
if(w <= 0 || w > Imgw || h <= 0 || h > Imgh)
|
||||
return;
|
||||
fill(img, w * h, Colbg);
|
||||
npre = dc->pre.n != 0;
|
||||
if(npre)
|
||||
textdraw(img, w, h, 0, 0, &dc->pre);
|
||||
if(dc->sel >= 0 && dc->sel < n){
|
||||
sely = (npre + dc->sel) * Fontsz;
|
||||
fill(img + sely * w, Fontsz * w, Colsel);
|
||||
}
|
||||
for(i = 0, y = npre * Fontsz; i < n; i++, y += Fontsz){
|
||||
s = &dc->kouho[i];
|
||||
sclear(&num);
|
||||
sputr(&num, '1' + i + Asciitofull);
|
||||
textdraw(img, w, h, 0, y, &num);
|
||||
textdrawfit(img, w, h, 2*Fontsz, y, w - 2*Fontsz, s);
|
||||
}
|
||||
nmark = pagemarker(buf, sizeof buf, dc->first, n, dc->total);
|
||||
if(nmark != 0){
|
||||
sinit(&mark, buf, nmark);
|
||||
textdraw(img, w, h, 0, y, &mark);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
putimage(int w, int h)
|
||||
{
|
||||
@@ -207,32 +163,20 @@ winhide(void)
|
||||
static int
|
||||
winshow(Drawcmd *dc)
|
||||
{
|
||||
char buf[32];
|
||||
vlong width;
|
||||
int nmark, npre, px, py, w, h, i, n, maxw;
|
||||
Str mark;
|
||||
Popup p;
|
||||
int px, py;
|
||||
u32int vals[4];
|
||||
xcb_query_pointer_reply_t *ptr;
|
||||
xcb_query_pointer_cookie_t cookie;
|
||||
|
||||
n = min(max(dc->nkouho, 0), Maxdisp);
|
||||
npre = dc->pre.n != 0;
|
||||
if(n == 0 && npre == 0){
|
||||
if(dc->nkouho <= 0 && dc->pre.n == 0){
|
||||
return winhide();
|
||||
}
|
||||
maxw = textwidth(&dc->pre);
|
||||
for(i = 0; i < n; i++)
|
||||
maxw = max(maxw, textwidth(&dc->kouho[i]));
|
||||
nmark = pagemarker(buf, sizeof buf, dc->first, n, dc->total);
|
||||
if(nmark != 0){
|
||||
sinit(&mark, buf, nmark);
|
||||
maxw = max(maxw, textwidth(&mark));
|
||||
}
|
||||
vals[3] = h = (n + npre + (nmark != 0)) * Fontsz;
|
||||
width = (vlong)maxw + 3*Fontsz;
|
||||
vals[2] = w = min(min(max(width, 1), Imgw), scr->width_in_pixels);
|
||||
if(w <= 0 || w > Imgw || h <= 0 || h > Imgh)
|
||||
popuplayout(dc, scr->width_in_pixels, &p);
|
||||
if(p.w <= 0 || p.w > Imgw || p.h <= 0 || p.h > Imgh)
|
||||
return 0;
|
||||
vals[2] = p.w;
|
||||
vals[3] = p.h;
|
||||
px = py = 0;
|
||||
if(!dc->caret.valid){
|
||||
cookie = xcb_query_pointer(conn, scr->root);
|
||||
@@ -244,7 +188,7 @@ winshow(Drawcmd *dc)
|
||||
free(ptr);
|
||||
}
|
||||
popupposition(&dc->caret, px, py, scr->width_in_pixels,
|
||||
scr->height_in_pixels, w, h, &px, &py);
|
||||
scr->height_in_pixels, p.w, p.h, &px, &py);
|
||||
vals[1] = py;
|
||||
vals[0] = px;
|
||||
xcb_configure_window(conn, win,
|
||||
@@ -252,8 +196,8 @@ winshow(Drawcmd *dc)
|
||||
XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
|
||||
vals);
|
||||
xcb_map_window(conn, win);
|
||||
drawkouho(dc, n, w, h);
|
||||
putimage(w, h);
|
||||
popupdraw(img, dc, &p);
|
||||
putimage(p.w, p.h);
|
||||
return xcb_flush(conn) > 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user