The popup was a white box on the usually white text it covered, with no edge to tell them apart; it has a border in the separator's colour. A syllable being composed came in a bar twelve ems wide, wiping out the line under it: only candidate rows share that steady width now, a preedit alone hugs its text. A popup placed by the pointer, when the client sends no caret, was placed again on every key and so followed the mouse; it stays where it came up. Clicks on it no longer fall through to the root window and its menu. And one failed draw — a lost pointer reply, a pixmap the server refused — ended the draw thread and the popup for the rest of the session; only a dead connection does now.
209 lines
3.1 KiB
C
209 lines
3.1 KiB
C
#include <u.h>
|
|
#include <libc.h>
|
|
#include <thread.h>
|
|
#include <bio.h>
|
|
#include "ipc.h"
|
|
|
|
#define min(a, b) ((a) < (b) ? (a) : (b))
|
|
#define max(a, b) ((a) > (b) ? (a) : (b))
|
|
|
|
/* A language id is the control code of the Ctrl key that selects it. */
|
|
enum
|
|
{
|
|
LangEN = 0x14,
|
|
LangJP = 0x0e,
|
|
LangJPK = 0x0b,
|
|
LangKO = 0x13,
|
|
LangHANJA = 0x08,
|
|
LangEMOJI = 0x05,
|
|
LangVI = 0x16,
|
|
|
|
Maxrunes = 64,
|
|
Maxutf = Maxrunes * UTFmax + 1,
|
|
};
|
|
|
|
enum
|
|
{
|
|
Maxclients = 64,
|
|
Ownerpoll = 200, /* ms between a frontend's owner checks while its preedit shows */
|
|
Maxkouho = 128,
|
|
Maxdisp = 9,
|
|
|
|
Colfg = 0x000000,
|
|
Colbg = 0xffffff,
|
|
Colsep = 0xd0d0d0,
|
|
Colsel = 0x333333,
|
|
Colselfg = 0xffffff,
|
|
};
|
|
|
|
/* Popup metrics in pixels; popupscale is GDK_SCALE, for HiDPI. */
|
|
extern int popupscale;
|
|
#define Fontsz (32*popupscale)
|
|
#define PopupPad (4*popupscale)
|
|
#define PopupSep popupscale
|
|
#define PopupBorder popupscale
|
|
#define PopupNumw Fontsz
|
|
#define PopupTextw (12*Fontsz)
|
|
#define PopupBasew (2*PopupPad + PopupNumw + PopupTextw)
|
|
|
|
typedef struct Str Str;
|
|
struct Str
|
|
{
|
|
Rune r[Maxrunes];
|
|
int n;
|
|
};
|
|
|
|
/*
|
|
* What one key does to a composition: text to commit, the new pending
|
|
* text, and the new raw state (Telex key history, or pending Japanese
|
|
* romaji), given the old ones in Im.
|
|
*/
|
|
typedef struct Emit Emit;
|
|
struct Emit
|
|
{
|
|
int eat;
|
|
Str s;
|
|
Str next;
|
|
Str raw;
|
|
};
|
|
|
|
typedef struct Tnode Tnode;
|
|
struct Tnode
|
|
{
|
|
char *val;
|
|
int vlen;
|
|
int child;
|
|
int sibling;
|
|
char c;
|
|
};
|
|
|
|
typedef struct Trie Trie;
|
|
struct Trie
|
|
{
|
|
Tnode *nodes;
|
|
int n;
|
|
int cap;
|
|
};
|
|
|
|
enum
|
|
{
|
|
TrieMiss,
|
|
TriePrefix,
|
|
TrieExact,
|
|
};
|
|
|
|
typedef struct Lang Lang;
|
|
typedef struct Im Im;
|
|
struct Lang
|
|
{
|
|
int lang;
|
|
char *mapname;
|
|
char *dictname;
|
|
Emit (*trans)(Im*, Rune);
|
|
void (*back)(Im*);
|
|
Trie *map;
|
|
Trie *dict;
|
|
};
|
|
|
|
struct Im
|
|
{
|
|
Lang *l;
|
|
Str pre;
|
|
/* Telex history, or the short pending romaji in a Japanese mode. */
|
|
Str raw;
|
|
Str kouho[Maxkouho];
|
|
int nkouho;
|
|
int sel;
|
|
};
|
|
|
|
typedef struct Drawcmd Drawcmd;
|
|
typedef struct Caret Caret;
|
|
typedef struct Area Area;
|
|
struct Area
|
|
{
|
|
int x;
|
|
int y;
|
|
int w;
|
|
int h;
|
|
};
|
|
|
|
struct Caret
|
|
{
|
|
int valid;
|
|
int x;
|
|
int y;
|
|
int h;
|
|
};
|
|
|
|
struct Drawcmd
|
|
{
|
|
Str pre;
|
|
Str kouho[Maxdisp];
|
|
int nkouho;
|
|
int sel;
|
|
int first;
|
|
int total;
|
|
Caret caret;
|
|
};
|
|
|
|
/*
|
|
* Popup geometry from popuplayout: n rows from row0 of the candidates,
|
|
* each Fontsz tall; a section's y is -1 when it is absent. Numbers
|
|
* start at PopupPad, text at PopupPad+PopupNumw.
|
|
*/
|
|
typedef struct Popup Popup;
|
|
struct Popup
|
|
{
|
|
int w;
|
|
int h;
|
|
int n;
|
|
int row0;
|
|
int prey;
|
|
int sepy;
|
|
int rowsy;
|
|
int textw;
|
|
int marky;
|
|
int markx;
|
|
int markw;
|
|
Str mark;
|
|
int sely;
|
|
int selw;
|
|
};
|
|
|
|
typedef struct Keyreq Keyreq;
|
|
typedef struct Keyres Keyres;
|
|
enum
|
|
{
|
|
Cclientpreedit = 1<<0,
|
|
};
|
|
enum
|
|
{
|
|
Keypress,
|
|
Keyreset,
|
|
Keyrelease,
|
|
Keycaret,
|
|
Keycap,
|
|
};
|
|
struct Keyres
|
|
{
|
|
int eaten; /* Keycap: caller is active and capability was applied. */
|
|
Str commit;
|
|
Str preedit;
|
|
};
|
|
|
|
struct Keyreq
|
|
{
|
|
void *owner; /* stable until the context's release is acknowledged */
|
|
int cap;
|
|
int op;
|
|
u32int ks;
|
|
u32int mod;
|
|
Caret caret;
|
|
Channel *reply;
|
|
};
|
|
|
|
extern Lang langs[];
|
|
extern int nlang;
|
|
extern Channel *drawc;
|
|
extern Channel *keyc;
|