popup: refine the input panel
This commit is contained in:
29
dat.h
29
dat.h
@@ -18,6 +18,9 @@ enum
|
|||||||
LangVI = 0x16,
|
LangVI = 0x16,
|
||||||
|
|
||||||
Fontsz = 32,
|
Fontsz = 32,
|
||||||
|
PopupPad = 4,
|
||||||
|
PopupSep = 1,
|
||||||
|
PopupNumw = Fontsz,
|
||||||
Maxrunes = 64,
|
Maxrunes = 64,
|
||||||
Maxutf = Maxrunes * UTFmax + 1,
|
Maxutf = Maxrunes * UTFmax + 1,
|
||||||
};
|
};
|
||||||
@@ -28,11 +31,13 @@ enum
|
|||||||
Maxkouho = 32,
|
Maxkouho = 32,
|
||||||
Maxdisp = 9,
|
Maxdisp = 9,
|
||||||
Imgw = (Maxrunes + 3) * Fontsz,
|
Imgw = (Maxrunes + 3) * Fontsz,
|
||||||
Imgh = (Maxdisp + 2) * Fontsz,
|
Imgh = 2*PopupPad + (Maxdisp + 2)*Fontsz + PopupSep,
|
||||||
|
|
||||||
Colfg = 0x000000,
|
Colfg = 0x000000,
|
||||||
Colbg = 0xffffff,
|
Colbg = 0xffffff,
|
||||||
Colsel = 0xcccccc,
|
Colsep = 0xd0d0d0,
|
||||||
|
Colsel = 0x333333,
|
||||||
|
Colselfg = 0xffffff,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct Str Str;
|
typedef struct Str Str;
|
||||||
@@ -137,6 +142,26 @@ struct Drawcmd
|
|||||||
Caret caret;
|
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 Keyreq Keyreq;
|
||||||
typedef struct Keyres Keyres;
|
typedef struct Keyres Keyres;
|
||||||
enum
|
enum
|
||||||
|
|||||||
3
fn.h
3
fn.h
@@ -30,6 +30,8 @@ void dictlookup(Dictreq*, Dictres*);
|
|||||||
void drawthread(void*);
|
void drawthread(void*);
|
||||||
void popupposition(Caret*, int, int, int, int, int, int, int*, int*);
|
void popupposition(Caret*, int, int, int, int, int, int, int*, int*);
|
||||||
int pagemarker(char*, int, int, int, int);
|
int pagemarker(char*, int, int, int, int);
|
||||||
|
void popuplayout(Drawcmd*, int, Popup*);
|
||||||
|
void popupdraw(u32int*, Drawcmd*, Popup*);
|
||||||
void imthread(void*);
|
void imthread(void*);
|
||||||
Emit transmap(Im*, Rune);
|
Emit transmap(Im*, Rune);
|
||||||
Emit transko(Im*, Rune);
|
Emit transko(Im*, Rune);
|
||||||
@@ -50,3 +52,4 @@ int textinit(void);
|
|||||||
int textwidth(Str*);
|
int textwidth(Str*);
|
||||||
void textdraw(u32int*, int, int, int, int, Str*);
|
void textdraw(u32int*, int, int, int, int, Str*);
|
||||||
void textdrawfit(u32int*, int, 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
|
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;
|
PangoRectangle r;
|
||||||
cairo_surface_t *surface;
|
cairo_surface_t *surface;
|
||||||
cairo_t *cr;
|
cairo_t *cr;
|
||||||
int stride;
|
int b, g, red, stride;
|
||||||
|
|
||||||
if(layout == nil)
|
if(layout == nil)
|
||||||
return;
|
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_rectangle(cr, 0, y, w, Fontsz);
|
||||||
cairo_clip(cr);
|
cairo_clip(cr);
|
||||||
cairo_move_to(cr, x - r.x, y + (Fontsz - r.height) / 2 - r.y);
|
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);
|
pango_cairo_show_layout(cr, layout);
|
||||||
}
|
}
|
||||||
cairo_destroy(cr);
|
cairo_destroy(cr);
|
||||||
@@ -167,11 +171,18 @@ drawtext(u32int *buf, int w, int h, int x, int y, int fit, Str *s)
|
|||||||
void
|
void
|
||||||
textdraw(u32int *buf, int w, int h, int x, int y, Str *s)
|
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
|
void
|
||||||
textdrawfit(u32int *buf, int w, int h, int x, int y, int fit, Str *s)
|
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 "dat.h"
|
||||||
#include "fn.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
|
int
|
||||||
pagemarker(char *buf, int nbuf, int first, int shown, int total)
|
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);
|
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
|
void
|
||||||
popupposition(Caret *caret, int pointerx, int pointery, int screenw,
|
popupposition(Caret *caret, int pointerx, int pointery, int screenw,
|
||||||
int screenh, int w, int h, int *x, int *y)
|
int screenh, int w, int h, int *x, int *y)
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ font_render(struct ct *t)
|
|||||||
static char *plain[] = { "A", "가", "あ", "漢", "☆", "𠀋" };
|
static char *plain[] = { "A", "가", "あ", "漢", "☆", "𠀋" };
|
||||||
u32int *buf, *mem;
|
u32int *buf, *mem;
|
||||||
Str a, heart, longrow, missing;
|
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]);
|
mem = emalloc((Testn + 2 * Guard) * sizeof mem[0]);
|
||||||
fillpixels(mem, Testn + 2 * Guard, guardcolor);
|
fillpixels(mem, Testn + 2 * Guard, guardcolor);
|
||||||
@@ -231,6 +231,21 @@ font_render(struct ct *t)
|
|||||||
}
|
}
|
||||||
CT_EQ_INT(t, natural, textwidth(&longrow));
|
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");
|
missing = mkstr("\xF4\x8F\xBF\xBF");
|
||||||
for(i = 0; i < 32; i++){
|
for(i = 0; i < 32; i++){
|
||||||
textdraw(buf, Testw, Testh, Fontsz, Fontsz, &heart);
|
textdraw(buf, Testw, Testh, Fontsz, Fontsz, &heart);
|
||||||
|
|||||||
@@ -1,6 +1,41 @@
|
|||||||
#include "test.h"
|
#include "test.h"
|
||||||
#include <limits.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
|
void
|
||||||
popup_layout(struct ct *t)
|
popup_layout(struct ct *t)
|
||||||
{
|
{
|
||||||
@@ -22,7 +57,11 @@ popup_layout(struct ct *t)
|
|||||||
};
|
};
|
||||||
char buf[32];
|
char buf[32];
|
||||||
Caret caret;
|
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++){
|
for(i = 0; i < nelem(markers); i++){
|
||||||
n = pagemarker(buf, sizeof buf, markers[i].first,
|
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_EQ_INT(t, strlen(markers[i].want), n);
|
||||||
CT_CHECK(t, strcmp(markers[i].want, buf) == 0);
|
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);
|
memset(&caret, 0, sizeof caret);
|
||||||
popupposition(&caret, 40, 50, 800, 600, 100, 60, &x, &y);
|
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);
|
INT_MAX, INT_MAX, &x, &y);
|
||||||
CT_EQ_INT(t, 0, x);
|
CT_EQ_INT(t, 0, x);
|
||||||
CT_EQ_INT(t, 0, y);
|
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 "dat.h"
|
||||||
#include "fn.h"
|
#include "fn.h"
|
||||||
|
|
||||||
enum {
|
|
||||||
Asciitofull = 0xFEE0,
|
|
||||||
};
|
|
||||||
|
|
||||||
static xcb_connection_t *conn;
|
static xcb_connection_t *conn;
|
||||||
static xcb_screen_t *scr;
|
static xcb_screen_t *scr;
|
||||||
static xcb_window_t win;
|
static xcb_window_t win;
|
||||||
@@ -146,46 +142,6 @@ wininit(void)
|
|||||||
return 1;
|
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
|
static void
|
||||||
putimage(int w, int h)
|
putimage(int w, int h)
|
||||||
{
|
{
|
||||||
@@ -207,32 +163,20 @@ winhide(void)
|
|||||||
static int
|
static int
|
||||||
winshow(Drawcmd *dc)
|
winshow(Drawcmd *dc)
|
||||||
{
|
{
|
||||||
char buf[32];
|
Popup p;
|
||||||
vlong width;
|
int px, py;
|
||||||
int nmark, npre, px, py, w, h, i, n, maxw;
|
|
||||||
Str mark;
|
|
||||||
u32int vals[4];
|
u32int vals[4];
|
||||||
xcb_query_pointer_reply_t *ptr;
|
xcb_query_pointer_reply_t *ptr;
|
||||||
xcb_query_pointer_cookie_t cookie;
|
xcb_query_pointer_cookie_t cookie;
|
||||||
|
|
||||||
n = min(max(dc->nkouho, 0), Maxdisp);
|
if(dc->nkouho <= 0 && dc->pre.n == 0){
|
||||||
npre = dc->pre.n != 0;
|
|
||||||
if(n == 0 && npre == 0){
|
|
||||||
return winhide();
|
return winhide();
|
||||||
}
|
}
|
||||||
maxw = textwidth(&dc->pre);
|
popuplayout(dc, scr->width_in_pixels, &p);
|
||||||
for(i = 0; i < n; i++)
|
if(p.w <= 0 || p.w > Imgw || p.h <= 0 || p.h > Imgh)
|
||||||
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)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
vals[2] = p.w;
|
||||||
|
vals[3] = p.h;
|
||||||
px = py = 0;
|
px = py = 0;
|
||||||
if(!dc->caret.valid){
|
if(!dc->caret.valid){
|
||||||
cookie = xcb_query_pointer(conn, scr->root);
|
cookie = xcb_query_pointer(conn, scr->root);
|
||||||
@@ -244,7 +188,7 @@ winshow(Drawcmd *dc)
|
|||||||
free(ptr);
|
free(ptr);
|
||||||
}
|
}
|
||||||
popupposition(&dc->caret, px, py, scr->width_in_pixels,
|
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[1] = py;
|
||||||
vals[0] = px;
|
vals[0] = px;
|
||||||
xcb_configure_window(conn, win,
|
xcb_configure_window(conn, win,
|
||||||
@@ -252,8 +196,8 @@ winshow(Drawcmd *dc)
|
|||||||
XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
|
XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
|
||||||
vals);
|
vals);
|
||||||
xcb_map_window(conn, win);
|
xcb_map_window(conn, win);
|
||||||
drawkouho(dc, n, w, h);
|
popupdraw(img, dc, &p);
|
||||||
putimage(w, h);
|
putimage(p.w, p.h);
|
||||||
return xcb_flush(conn) > 0;
|
return xcb_flush(conn) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user