first commit

This commit is contained in:
Hojun-Cho 2025-12-23 20:21:56 +09:00
commit dcd1147638
148 changed files with 176109 additions and 0 deletions

58
.gitignore vendored Normal file
View File

@ -0,0 +1,58 @@
strans
strans-xim
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
# debug information files
*.dwo

19
Makefile Normal file
View File

@ -0,0 +1,19 @@
CC = 9c
LD = 9l
CFLAGS = -Wall -Wextra -O2
PROG = strans
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
all: $(PROG)
$(PROG): $(OBJS)
$(LD) -o $@ $(OBJS) -lthread -lString -lbio -lxcb -lm
$(OBJS): dat.h fn.h ipc.h
clean:
rm -f $(OBJS) $(PROG)
.PHONY: all clean

131
dat.h Normal file
View File

@ -0,0 +1,131 @@
#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))
enum
{
LangEN = 0x14,
LangJP = 0x0e,
LangJPK = 0x0b,
LangKO = 0x13,
Fontsz = 32,
Fontbase = 4,
Nglyphs = 65536,
};
enum
{
Maxclients = 64,
Maxkouho = 32,
Maxdisp = 8,
Imgw = 512,
Imgh = Maxdisp * Fontsz + 8,
Colfg = 0x000000,
Colbg = 0xffffff,
Colsel = 0xcccccc,
};
typedef struct Str Str;
struct Str
{
Rune r[64];
int n;
};
typedef struct Emit Emit;
struct Emit
{
int eat;
int flush;
Str s;
Str next;
Str dict;
};
typedef struct Hnode Hnode;
struct Hnode
{
int filled;
int next;
char *key;
int klen;
char *kana;
int kanalen;
};
typedef struct Hmap Hmap;
struct Hmap
{
int nbs;
int nsz;
int len;
int cap;
uchar *nodes;
};
typedef struct Lang Lang;
typedef struct Im Im;
struct Lang
{
int lang;
char *mapname;
char *dictname;
Hmap *map;
Hmap *dict;
Emit (*trans)(Im*, Rune);
};
struct Im
{
Lang *l;
Str line;
Str kouho[Maxkouho];
int nkouho;
int sel;
};
typedef struct Drawcmd Drawcmd;
struct Drawcmd
{
Str kouho[Maxkouho];
int nkouho;
int sel;
};
typedef struct Keyreq Keyreq;
struct Keyreq
{
int fd;
u32int ks;
u32int mod;
};
typedef struct Dictreq Dictreq;
struct Dictreq
{
Str key;
Str line;
int lang;
};
typedef struct Dictres Dictres;
struct Dictres
{
Str key;
Str kouho[Maxkouho];
int nkouho;
};
extern Lang langs[];
extern int nlang;
extern Channel *drawc;
extern Channel *keyc;
extern Channel *dictreqc;
extern Channel *dictresc;

104
dict.c Normal file
View File

@ -0,0 +1,104 @@
#include "dat.h"
#include "fn.h"
static void
dictlkup(Dictreq *req, Dictres *res)
{
Lang *l;
Hmap *dict;
Hnode *n;
char *p, *e, *sp;
Str tmp;
res->nkouho = 0;
if(req->key.n == 0)
return;
res->kouho[0] = req->key;
res->nkouho = 1;
l = getlang(req->lang);
dict = l ? l->dict : nil;
if(dict == nil)
return;
n = hmapget(dict, &req->key);
if(n == nil || n->kanalen == 0)
return;
p = n->kana;
e = p + n->kanalen;
while(res->nkouho < Maxkouho && p < e){
sp = p;
while(p < e && *p != ' ')
p++;
sinit(&tmp, sp, p - sp);
if(scmp(&tmp, &req->key) != 0)
res->kouho[res->nkouho++] = tmp;
if(p < e)
p++;
}
}
void
dictthread(void*)
{
Dictreq req;
Dictres res;
threadsetname("dict");
for(;;){
if(chanrecv(dictreqc, &req) < 0)
break;
while(channbrecv(dictreqc, &req) > 0)
;
dictlkup(&req, &res);
res.key = req.line;
chansend(dictresc, &res);
}
}
static Hmap*
opendict(char *path)
{
Hmap *h;
Biobuf *b;
Str key, val;
char *line, *tab;
int len;
b = Bopen(path, OREAD);
if(b == nil)
die("can't open: %s", path);
h = hmapalloc(4096, 0);
while((line = Brdstr(b, '\n', 1)) != nil){
len = strlen(line);
if(len == 0 || line[0] == ';'){
free(line);
continue;
}
tab = strchr(line, '\t');
if(tab == nil || tab >= line + len - 1){
free(line);
continue;
}
*tab = '\0';
sinit(&key, line, tab - line);
sinit(&val, tab+1, len - (tab - line) - 1);
hmapset(&h, &key, &val);
free(line);
}
Bterm(b);
return h;
}
void
dictinit(char *dir)
{
char path[1024];
int i;
for(i = 0; i < nlang; i++){
if(langs[i].dictname == nil)
continue;
snprint(path, sizeof(path), "%s/%s.dict", dir, langs[i].dictname);
langs[i].dict = opendict(path);
}
}

34
fn.h Normal file
View File

@ -0,0 +1,34 @@
void die(char*, ...);
void sinit(Str*, char*, int);
void sclear(Str*);
void sputr(Str*, Rune);
void spopr(Str*);
void sappend(Str*, Str*);
int scmp(Str*, Str*);
int stoutf(Str*, char*, int);
Rune slastr(Str*);
Hmap* hmapalloc(int, int);
int hmapset(Hmap**, Str*, Str*);
Hnode* hmapget(Hmap*, Str*);
int mapget(Hmap*, Str*, Str*);
Lang* getlang(int);
void mapinit(char*);
void dictinit(char*);
void dictthread(void*);
void drawthread(void*);
void imthread(void*);
Emit trans(Im*, Rune);
Emit jptrans(Im*, Rune);
void srvthread(void*);
void* emalloc(ulong);
void* erealloc(void*, ulong);
void fontinit(char*);
void putfont(u32int*, int, int, int, int, Rune);

87
font.c Normal file
View File

@ -0,0 +1,87 @@
#define STB_TRUETYPE_IMPLEMENTATION
#include "stb_truetype.h"
#include "dat.h"
#include "fn.h"
typedef struct Glyph Glyph;
struct Glyph
{
uchar *bmp;
int w, h, ox, oy;
};
static stbtt_fontinfo font;
static uchar *fontdata;
static float scale;
static Glyph cache[Nglyphs];
static u32int blendtab[2][256];
static u32int
blend(u32int bg, int a)
{
int r, g, b, inv;
inv = 255 - a;
r = (bg >> 16 & 0xff) * inv / 255;
g = (bg >> 8 & 0xff) * inv / 255;
b = (bg & 0xff) * inv / 255;
return (r << 16) | (g << 8) | b;
}
void
fontinit(char *path)
{
int fd, a;
long sz, n;
fd = open(path, OREAD);
if(fd < 0)
die("can't open font: %s", path);
sz = seek(fd, 0, 2);
seek(fd, 0, 0);
fontdata = emalloc(sz);
n = readn(fd, fontdata, sz);
close(fd);
if(n != sz)
die("can't read font: %s", path);
if(!stbtt_InitFont(&font, fontdata, stbtt_GetFontOffsetForIndex(fontdata, 0)))
die("can't init font: %s", path);
scale = stbtt_ScaleForPixelHeight(&font, Fontsz);
for(a = 0; a < 256; a++){
blendtab[0][a] = blend(Colbg, a);
blendtab[1][a] = blend(Colsel, a);
}
}
void
putfont(u32int *buf, int w, int h, int px, int py, Rune r)
{
Glyph *g;
int i, j, x, y, a, sel;
u32int *p;
if(r >= Nglyphs)
return;
g = &cache[r];
if(g->bmp == nil){
g->bmp = stbtt_GetCodepointBitmap(&font, scale, scale, r, &g->w, &g->h, &g->ox, &g->oy);
if(g->bmp == nil)
return;
}
for(j = 0; j < g->h; j++){
y = py + j + g->oy + Fontsz - Fontbase;
if(y < 0 || y >= h)
continue;
for(i = 0; i < g->w; i++){
x = px + i + g->ox;
if(x < 0 || x >= w)
continue;
a = g->bmp[j * g->w + i];
if(a > 0){
p = &buf[y * w + x];
sel = (*p == Colsel) ? 1 : 0;
*p = blendtab[sel][a];
}
}
}
}

Binary file not shown.

1
font/font.otf Symbolic link
View File

@ -0,0 +1 @@
NotoSansMonoCJKsc-Regular.otf

129
hash.c Normal file
View File

@ -0,0 +1,129 @@
#include "dat.h"
#include "fn.h"
enum {
Tagsize = sizeof(Hnode),
};
static uvlong
hash(Str *s)
{
uvlong h;
int i;
h = 7;
for(i = 0; i < s->n; i++)
h = h*31 + s->r[i];
return h;
}
Hmap*
hmapalloc(int nbuckets, int size)
{
void *store;
Hmap *h;
int nsz;
nsz = Tagsize + size;
store = emalloc(sizeof(*h) + nbuckets * nsz);
h = store;
h->nbs = nbuckets;
h->nsz = nsz;
h->len = h->cap = nbuckets;
h->nodes = (uchar*)store + sizeof(*h);
return h;
}
static int
keycmp(Hnode *n, Str *key)
{
char buf[256];
int len;
len = stoutf(key, buf, sizeof(buf));
if(n->klen != len)
return 1;
return memcmp(n->key, buf, len);
}
Hnode*
hmapget(Hmap *h, Str *key)
{
Hnode *n;
uchar *v;
v = h->nodes + (hash(key) % h->nbs) * h->nsz;
for(;;){
n = (Hnode*)v;
if(n->filled && keycmp(n, key) == 0)
return n;
if(n->next == 0)
break;
v = h->nodes + n->next * h->nsz;
}
return nil;
}
static char*
str2dup(Str *s)
{
char buf[256];
char *p;
int n;
n = stoutf(s, buf, sizeof(buf));
p = emalloc(n + 1);
memmove(p, buf, n);
p[n] = '\0';
return p;
}
int
hmapset(Hmap **store, Str *key, Str *kana)
{
Hnode *n;
uchar *v;
Hmap *h;
int next;
vlong diff;
h = *store;
v = h->nodes + (hash(key) % h->nbs) * h->nsz;
for(;;){
n = (Hnode*)v;
next = n->next;
if(n->filled == 0)
goto replace;
if(keycmp(n, key) == 0)
goto replace;
if(next == 0)
break;
v = h->nodes + next * h->nsz;
}
if(h->cap == h->len){
diff = v - h->nodes;
h->cap *= 2;
*store = erealloc(*store, sizeof(*h) + h->cap * h->nsz);
h = *store;
h->nodes = (uchar*)*store + sizeof(*h);
v = h->nodes + diff;
n = (Hnode*)v;
}
n->next = h->len;
memset(h->nodes + h->len * h->nsz, 0, h->nsz);
h->len++;
v = h->nodes + n->next * h->nsz;
n = (Hnode*)v;
replace:
if(n->filled == 0){
n->key = str2dup(key);
n->klen = strlen(n->key);
n->filled = 1;
}
n->next = next;
if(kana->n > 0){
n->kana = str2dup(kana);
n->kanalen = strlen(n->kana);
}
return 0;
}

20
ipc.h Normal file
View File

@ -0,0 +1,20 @@
// req: 4 bytes [type, mod, key lo, key hi]
// resp: 2+n bytes [type, n, ...]
enum
{
Kspec = 0xf000,
Kback = Kspec|0x08,
Ktab = Kspec|0x09,
Kret = Kspec|0x0d,
Kesc = Kspec|0x1b,
Kup = Kspec|0x52,
Kdown = Kspec|0x54,
Kshift = Kspec|0xe1,
Ksuper = Kspec|0xeb,
Mshift = 1<<0,
Mctrl = 1<<2,
Malt = 1<<3,
Msuper = 1<<6,
};

80
jp.c Normal file
View File

@ -0,0 +1,80 @@
#include "dat.h"
#include "fn.h"
Emit
jptrans(Im *im, Rune c)
{
Emit e;
Str key, kana;
Hmap *h;
Rune last;
int hira;
memset(&e, 0, sizeof(e));
h = im->l->map;
hira = (im->l->lang == LangJP);
key = im->line;
sputr(&key, c);
if(hmapget(h, &key)){
e.eat = 1;
e.next = key;
mapget(h, &key, &e.dict);
return e;
}
last = slastr(&im->line);
if(last == 0)
goto flush;
key = im->line;
key.n--;
if(mapget(h, &key, &kana)){
sclear(&key);
sputr(&key, last);
sputr(&key, c);
if(hmapget(h, &key)){
e.eat = 1;
e.s = kana;
sputr(&e.next, last);
sputr(&e.next, c);
mapget(h, &e.next, &e.dict);
return e;
}
}
if(c == 'n' && last == 'n'){
key = im->line;
key.n--;
if(mapget(h, &key, &kana)){
e.eat = 1;
e.s = kana;
sputr(&e.s, hira ? 0x3093 : 0x30F3);
sputr(&e.next, c);
mapget(h, &e.next, &e.dict);
return e;
}
}
if(c == last && strchr("kgsztdbpmjfchryw", c)){
key = im->line;
key.n--;
if(mapget(h, &key, &kana)){
e.eat = 1;
e.s = kana;
sputr(&e.s, hira ? 0x3063 : 0x30C3);
sputr(&e.next, c);
mapget(h, &e.next, &e.dict);
return e;
}
}
flush:
mapget(h, &im->line, &e.s);
sclear(&key);
sputr(&key, c);
if(hmapget(h, &key) == nil){
e.flush = 1;
sputr(&e.s, c);
return e;
}
e.eat = 1;
sputr(&e.next, c);
mapget(h, &e.next, &e.dict);
return e;
}

76
main.c Normal file
View File

@ -0,0 +1,76 @@
#include "dat.h"
#include "fn.h"
Channel *drawc;
Channel *keyc;
Channel *dictreqc;
Channel *dictresc;
char *fontpath;
int
threadmaybackground(void)
{
return 1;
}
void
usage(void)
{
fprint(2, "usage: strans mapdir fontpath\n");
threadexitsall("usage");
}
void
die(char *fmt, ...)
{
va_list ap;
fprint(2, "strans: ");
va_start(ap, fmt);
vfprint(2, fmt, ap);
va_end(ap);
fprint(2, "\n");
threadexitsall("die");
}
void*
emalloc(ulong n)
{
void *p;
p = malloc(n);
if(p == nil)
die("out of memory");
memset(p, 0, n);
return p;
}
void*
erealloc(void *p, ulong n)
{
p = realloc(p, n);
if(p == nil)
die("out of memory");
return p;
}
void
threadmain(int argc, char **argv)
{
if(argc != 3)
usage();
fontpath = argv[2];
drawc = chancreate(sizeof(Drawcmd), 0);
keyc = chancreate(sizeof(Keyreq), 0);
dictreqc = chancreate(sizeof(Dictreq), 4);
dictresc = chancreate(sizeof(Dictres), 0);
mapinit(argv[1]);
dictinit(argv[1]);
proccreate(drawthread, nil, 16384);
proccreate(srvthread, nil, 16384);
threadcreate(dictthread, nil, 16384);
threadcreate(imthread, nil, 16384);
threadexits(nil);
}

12
map/README Normal file
View File

@ -0,0 +1,12 @@
#
# The following are a set of tools to obtain and process dictionaries from the SKK project in order to use them with ktrans(1).
#
# grabskkdicts pulls the skk kana-kanji conversion dictionaries from the skk-dev/dict repo.
# skk2ktrans takes an skk dictionary and converts it into a kanji jisho suitable to be used with ktrans(1).
#
# You can fetch and convert all the dictionaries by running this file.
#
grabskkdicts
for(d in skkdicts/SKK-JISYO.*)
<$d skk2ktrans >$d.jisho

2
map/grabskkdicts Executable file
View File

@ -0,0 +1,2 @@
#!/bin/rc
git/clone https://github.com/skk-dev/dict skkdicts

382
map/hangul.dict Normal file
View File

@ -0,0 +1,382 @@
;; Korean autocomplete dictionary for ktrans
;; Format: prefix completion1 completion2 ...
;;
;; Initial consonants (초성)
ㄱ 가 감사 감사합니다 강남 고마워 고맙습니다 괜찮아 그래 그럼 기다려 가능 가격 가게 가방 가족 간단 갈게 같이 거기 건강 검색 결과 경우 계속 고객 공부 관련 괜찮습니다 교육 구매 그냥 그런데 그리고 근데 금방 기능 기대 기본 길이
ㄴ 나 네 내일 너무 노래 누구 뭐 나중에 남자 내용 넣어 놓고 느낌 다음
ㄷ 다 대 더 도 동 다시 다음 단어 답변 대단 대화 도움 도착 동생 등록 드릴게요
ㄹ 라 로 리 레 뭐라고
ㅁ 만 먼저 메시지 모르겠어 모두 뭐 뭐야 뭐라고 뭔가 미안 미안해 문제 문의
ㅂ 바로 반갑습니다 방금 방법 별로 보내 보여줘 부탁 부탁드립니다 분명 비밀번호
ㅅ 사 사람 사랑 사용 사진 상관없어 생각 서비스 선택 설명 성공 소개 수고 수정 시간 시작 신청 실패 싶어
ㅇ 아 아니 아니요 아마 안녕 안녕하세요 알겠습니다 알았어 어디 어떻게 어서오세요 없어 에러 여기 여보세요 연락 열심히 예 오늘 오랜만 오케이 완료 왜 요청 우리 원래 위치 유저 으로 응 이거 이것 이름 이메일 이미 이상 이유 이해 인사 일단 입력 있어
ㅈ 자 잘 잘가 잘됐다 잠깐 잠시 저 전화 정말 제가 제발 조금 좀 좋아 좋겠다 주문 주세요 중요 즐거운 지금 직접 진짜 질문 집
ㅊ 참 참고 찾아 처리 처음 천만에요 최고 최근 추가 축하 출발 취소
ㅋ 카드 커피 컴퓨터 코드 클릭 큰
ㅌ 탈퇴 통화 특히
ㅍ 파일 편하게 포함 필요 필수
ㅎ 하 하나 하루 하세요 하지마 한 한번 항상 해결 해봐 해야 해주세요 핸드폰 행복 확인 회원 회의 휴대폰
;;
;; Common prefixes (일반 접두어)
가 가격 가게 가능 가다 가방 가수 가요 가을 가장 가족 가지
간 간단 간식 간장 간호사
갈 갈게 갈비 갈색
감 감기 감사 감사합니다 감사해요 감자 감정
강 강남 강아지 강의 강조
같 같아 같아요 같은 같이
개 개발 개발자 개선 개인 개정
거 거기 거래 거리 거의 거짓말
건 건강 건물 건의
걱 걱정 걱정마
검 검사 검색 검토
게 게시판 게임
결 결과 결론 결정 결제 결혼
경 경기 경험 경우 경제
계 계속 계시 계약 계정 계좌 계획
고 고객 고급 고기 고등학교 고마워 고맙습니다 고민 고양이 고장
곧 곧 곧바로
공 공간 공개 공부 공사 공유 공지 공항
과 과거 과연 과일 과장 과정
관 관계 관련 관리 관심
괜 괜찮아 괜찮아요 괜찮습니다
교 교사 교수 교육 교통 교환
구 구글 구독 구매 구분 구성 구입 구체적
국 국가 국내 국민 국어 국제
그 그거 그게 그것 그냥 그녀 그니까 그대 그대로 그때 그래 그래도 그래서 그러나 그러니까 그러면 그런 그런데 그럼 그렇게 그리고 그림 그만
근 근데 근무 근본 근처
글 글 글쎄 글자
금 금방 금액 금요일 금지
급 급하게 급해
기 기간 기능 기다려 기대 기본 기분 기사 기술 기억 기업 기준 기타 기회
길 길 길이
김 김밥 김치
까 까먹었어 까지
깜 깜빡 깜짝
꼭 꼭
끝 끝 끝났어 끝내
나 나 나도 나라 나머지 나빠 나오다 나와 나이 나중 나중에
날 날씨 날짜
남 남기다 남자 남편
내 내가 내년 내려 내리다 내용 내일
너 너 너무 너희
넣 넣다 넣어
네 네 네가 네이버
넷 넷플릭스
노 노래 노력 노트북
놀 놀라 놀러
농 농담
높 높은 높이
누 누가 누구 누나
눈 눈 눈물
뉴 뉴스
느 느낌 느린
늦 늦게 늦었어
다 다 다녀오다 다니다 다른 다르다 다시 다양 다음 다행 다행이다
단 단계 단순 단어 단위 단점 단체
달 달 달라 달러 달리
담 담당 담당자 담배
답 답글 답변 답장
당 당근 당분간 당신 당연 당장
대 대기 대단 대략 대부분 대신 대체 대충 대표 대학 대학교 대화 대해
더 더 더욱
덕 덕분
데 데이터
도 도대체 도서관 도시 도와줘 도움 도착 도전
독 독서
돈 돈
동 동네 동생 동시 동안 동영상 동의
돼 돼 돼요 됐어
되 되게 되다 되면
두 두 두고 두번째
뒤 뒤 뒤에
드 드디어 드라마 드리다 드릴게요 드세요
등 등록 등등
따 따라 따로
딱 딱
때 때 때문 때문에
또 또 또는 또한
똑 똑같이
뛰 뛰어
라 라면 라이브
로 로그인 로그아웃
리 리뷰
마 마다 마셔 마시다 마음 마지막 마찬가지 마침
막 막 막상
만 만 만나 만나다 만나서 반가워요 만들다 만약 만원 만큼 만족
많 많다 많아 많이
말 말 말고 말씀 말야 말이야
맛 맛 맛있어 맛있다
망 망했다
맞 맞아 맞아요 맞춤
매 매번 매우 매일 매장
머 머리
먹 먹고 먹다 먹어
먼 먼저
멀 멀다 멀리
메 메뉴 메모 메시지 메일
며 며칠
면 면접
명 명 명단 명확
몇 몇 몇개 몇번
모 모두 모든 모르겠어 모르다 모레 모양 모임
목 목록 목요일 목적
몰 몰라 몰랐어
못 못 못하다 못해
무 무료 무슨 무엇 무조건
문 문서 문의 문자 문제
물 물 물건 물론 물어보다
뭐 뭐 뭐야 뭐라고 뭔가 뭘
미 미국 미래 미리 미안 미안해 미안합니다 미팅
믿 믿다 믿어
밑 밑에
바 바꾸다 바뀌다 바라다 바로 바쁘다 바쁘면
박 박사
반 반 반갑습니다 반드시 반복
받 받다 받아 받았어
발 발생 발전 발표
밤 밤
밥 밥
방 방금 방법 방문 방송 방식 방향
배 배 배달 배송 배우다
백 백 백만
버 버그 버리다 버전
번 번 번역 번호
벌 벌써
범 범위
법 법
별 별로
변 변경 변화
병 병원
보 보고 보고서 보내다 보다 보면 보여줘 보이다 보통 보호
복 복사 복잡
본 본인
봐 봐 봐요 봐줘
부 부끄러워 부디 부모님 부분 부장 부족 부탁 부탁드립니다 부탁해
분 분 분명 분석 분위기
불 불가능 불편 불행
비 비교 비밀 비밀번호 비슷 비용
빠 빠르게 빠르다 빠른 빨리
빼 빼다 빼고
사 사고 사람 사랑 사랑해 사무실 사실 사업 사용 사용자 사이 사이트 사장 사전 사진 사회
산 산
살 살다 살펴보다
상 상관 상관없어 상담 상대 상세 상태 상품 상황
새 새로 새로운 새벽
색 색 색상
생 생각 생각해 생기다 생산 생일 생활
서 서로 서류 서버 서비스 서울
선 선물 선배 선생님 선택
설 설명 설정 설치
성 성공 성격 성능 성함
세 세계 세금 세부 세상 세요
소 소개 소리 소비자 소식 소중 소프트웨어
속 속도
손 손 손님
솔 솔직히
송 송금
쇼 쇼핑
수 수 수고 수고하세요 수량 수업 수요일 수정 수준 수출
숙 숙제
순 순서
술 술
쉬 쉬다 쉬운 쉽게
스 스마트폰 스케줄 스트레스 스타일
슬 슬프다
시 시 시간 시스템 시작 시장 시험
식 식당 식사
신 신경 신고 신용 신제품 신청 신호 신뢰 신규
실 실례 실수 실제 실패 실행 실험 실화
심 심각 심심
싶 싶다 싶어 싶으면
싸 싸다 싸움
쓰 쓰다 쓰레기 쓸
씨 씨
아 아 아까 아끼다 아니 아니요 아님 아마 아무 아버지 아이 아이디 아직 아침 아파 아프다
안 안 안내 안녕 안녕하세요 안되다 안전
알 알겠습니다 알겠어 알다 알려줘 알림 알바 알았어
앞 앞으로 앞에
애 애인
야 야
약 약 약간 약속
얘 얘기
어 어 어느 어디 어떤 어떻게 어렵다 어머니 어서 어제 어쩌면 어차피 어플
언 언니 언제 언젠가
얼 얼굴 얼마 얼마나
업 업그레이드 업데이트 업로드 업무 업체
없 없다 없어 없으면
에 에러
여 여기 여러 여름 여보세요 여자 여전히 여행
역 역시
연 연결 연구 연락 연습 연휴
열 열다 열심히
영 영상 영수증 영어 영업 영향 영화
예 예 예를 들어 예상 예약 예전 예정
오 오늘 오다 오래 오랜만 오른쪽 오빠 오전 오케이 오후
올 올라가다 올려 올리다 올해
와 와 와이파이 왔어
완 완료 완벽 완전
왜 왜
외 외국
요 요금 요새 요즘 요청
욕 욕
용 용 용도
우 우리 우선 우연히
운 운동 운영 운전
울 울다 울어
원 원 원래 원인 원하다 원해
월 월 월급 월요일
웹 웹사이트
위 위 위에 위주 위치 위해
유 유명 유용 유저 유지 유튜브 유행
으 으로 으면
은 은 은행
을 을
음 음 음식 음악
응 응 응답
의 의견 의미 의문 의사
이 이 이거 이것 이곳 이기다 이따 이때 이래 이런 이렇게 이름 이리 이메일 이미 이번 이상 이야기 이용 이유 이제 이전 이쪽 이틀 이해 이해하다
인 인간 인기 인사 인스타그램 인정 인증 인터넷 인터뷰
일 일 일단 일반 일부 일상 일요일 일을 일자 일정 일찍 일하다
읽 읽다 읽어
잃 잃다 잃어버리다
입 입금 입력 입장 입학
있 있다 있어 있으면
자 자 자기 자꾸 자다 자동 자료 자세히 자신 자연 자유 자주
작 작년 작동 작성 작업 작은 작품
잔 잔
잘 잘 잘가 잘됐다 잘못 잘하다
잠 잠 잠깐 잠시
장 장 장기 장난 장소 장점
잡 잡다 잡아
재 재미 재밌다 재밌어
저 저 저거 저기 저녁 저도 저렇게 저번 저장 저희
적 적다 적용 적절 적어도
전 전 전공 전달 전문 전부 전에 전자 전체 전혀 전화
절 절대 절반
점 점 점검 점심 점점
접 접속 접수 접근
정 정기 정도 정리 정말 정보 정상 정신 정식 정확
제 제가 제공 제대로 제목 제발 제안 제외 제일 제품
젤 젤
조 조건 조금 조사 조심 조절 조용 조치
존 존경 존재 존중
졸 졸려
종 종류 종종
좀 좀
좋 좋겠다 좋다 좋아 좋아요 좋아하다 좋은
죄 죄송 죄송합니다
주 주 주간 주로 주말 주문 주변 주세요 주소 주요 주의 주인 주제
준 준비
줄 줄 줄게
중 중간 중국 중심 중에 중요
즉 즉시
즐 즐거운 즐겁다 즐기다
증 증가
지 지각 지금 지나다 지난 지루 지역 지원 지인 지정 지출
직 직업 직원 직장 직접
진 진심 진짜 진행
질 질문 질서
집 집 집중
짧 짧은
짧 짧다
쪽 쪽 쪽으로
찍 찍다 찍어
차 차 차이 차후
참 참 참고 참여 참으로
찾 찾고 찾다 찾아 찾으면
채 채널 채팅
책 책 책임
처 처리 처음
천 천만에요 천원
철 철저
첫 첫 첫번째
청 청소 청구
체 체크 체험
초 초 초대 초반 초보
최 최고 최근 최대 최소 최선 최신 최적 최종
추 추가 추석 추천 추후
축 축하 축하드립니다 축하합니다 축하해
출 출근 출력 출발 출시 출장
충 충분 충전
취 취미 취소 취업 취향
치 치킨
친 친구 친절 친척
카 카드 카메라 카카오 카카오톡 카페
칼 칼퇴
커 커뮤니티 커피 커피숍
컨 컨디션 컨텐츠
컴 컴퓨터
케 케이스
코 코드 코로나
콘 콘서트 콘텐츠
클 클래스 클라이언트 클릭
큰 큰 큰일
타 타다 타이밍
탈 탈퇴
테 테스트 테이블
토 토요일
통 통신 통역 통장 통화
투 투자
특 특별 특별히 특이 특징 특히
틀 틀리다 틀림없이
티 티켓 티비
파 파악 파일 파티
판 판단 판매
팔 팔다 팔로우
팀 팀 팀장
패 패스워드
편 편리 편안 편의 편지 편하게 편하다
평 평가 평균 평소 평일
폰 폰
표 표 표시 표현
품 품질
프 프로그램 프로젝트 프로필
플 플랜
피 피곤 피드백 피하다
필 필수 필요 필요하다
하 하 하고 하나 하는 하다 하루 하면 하세요 하지마 하지만
한 한 한국 한글 한달 한두 한번 한편 한테
할 할 할게 할인
함 함께 함수
합 합계 합니다 합의
항 항목 항상
해 해 해결 해도 해봐 해볼게 해서 해야 해요 해외 해주세요
핵 핵심
행 행동 행복 행사
향 향상
허 허락
현 현금 현상 현재 현황
혹 혹시
홈 홈페이지
화 화 화나다 화요일 화이팅 화인 화장실
확 확대 확보 확실 확실히 확인
환 환경 환불 환영
활 활동 활용
회 회 회사 회식 회원 회의
효 효과
후 후 후기 후에
휴 휴가 휴대폰 휴식 휴일
흔 흔히
힘 힘 힘내 힘들다 힘들어
;;
;; Common phrases (자주 쓰는 문장)
감사합 감사합니다
고맙습 고맙습니다
고마워 고마워요
괜찮습 괜찮습니다
반갑습 반갑습니다
안녕하 안녕하세요 안녕하십니까
알겠습 알겠습니다
죄송합 죄송합니다
축하합 축하합니다
수고하 수고하세요 수고하셨습니다
미안합 미안합니다
실례합 실례합니다
부탁드 부탁드립니다
감사해 감사해요
고마워 고마워요
미안해 미안해요
안녕히 안녕히 가세요 안녕히 계세요
잘부탁 잘부탁드립니다
오랜만 오랜만이에요 오랜만입니다
좋은하 좋은하루

7586
map/kanji.dict Normal file

File diff suppressed because it is too large Load Diff

28294
map/pinyin.dict Normal file

File diff suppressed because it is too large Load Diff

2
map/skk2ktrans Executable file
View File

@ -0,0 +1,2 @@
#!/bin/rc
tcs -sf ujis | awk '$1 !~ /;;/ {gsub("(^\/|\/$)", "", $2); gsub(" ", " "); gsub("\/", " ", $2);} {print}'

83100
map/wubi.dict Normal file

File diff suppressed because it is too large Load Diff

9
run.sh Executable file
View File

@ -0,0 +1,9 @@
#!/bin/sh
pkill strans
pkill strans-xim
sleep 1
./strans map font/font.otf &
sleep 1
xim/strans-xim &

55
srv.c Normal file
View File

@ -0,0 +1,55 @@
#include "dat.h"
#include "fn.h"
static char adir[40];
static void
sendkey(int fd, u32int ks, u32int mod)
{
Keyreq kr;
kr.fd = fd;
kr.ks = ks;
kr.mod = mod;
chansend(keyc, &kr);
}
static void
clientthread(void *arg)
{
int fd;
uchar req[4];
fd = (int)(uintptr)arg;
threadsetname("client %d", fd);
while(read(fd, req, 4) == 4)
sendkey(fd, req[2] | (req[3] << 8), req[1]);
close(fd);
}
static void
srvinit(void)
{
char addr[64];
snprint(addr, sizeof(addr), "unix!/tmp/strans.%d", getuid());
remove(addr + 5);
if(announce(addr, adir) < 0)
die("announce: %r");
}
void
srvthread(void*)
{
char ldir[40];
int fd;
threadsetname("srv");
srvinit();
for(;;){
fd = listen(adir, ldir);
if(fd < 0)
continue;
proccreate(clientthread, (void*)(uintptr)fd, 8192);
}
}

5079
stb_truetype.h Normal file

File diff suppressed because it is too large Load Diff

86
str.c Normal file
View File

@ -0,0 +1,86 @@
#include "dat.h"
#include "fn.h"
enum
{
Maxrunes = nelem(((Str*)0)->r),
};
void
sinit(Str *s, char *src, int n)
{
int len;
s->n = 0;
while(n > 0 && s->n < Maxrunes){
len = chartorune(&s->r[s->n], src);
s->n++;
src += len;
n -= len;
}
}
void
sclear(Str *s)
{
s->n = 0;
}
void
sputr(Str *s, Rune r)
{
if(s->n >= Maxrunes)
die("sputr overflow");
s->r[s->n++] = r;
}
void
spopr(Str *s)
{
if(s->n > 0)
s->r[--s->n] = 0;
}
void
sappend(Str *dst, Str *src)
{
int i;
for(i = 0; i < src->n && dst->n < Maxrunes; i++)
dst->r[dst->n++] = src->r[i];
}
int
scmp(Str *a, Str *b)
{
int i;
if(a->n != b->n)
return 1;
for(i = 0; i < a->n; i++)
if(a->r[i] != b->r[i])
return 1;
return 0;
}
int
stoutf(Str *s, char *buf, int sz)
{
int i, n, len;
n = 0;
for(i = 0; i < s->n && n < sz - UTFmax; i++){
len = runetochar(buf + n, &s->r[i]);
n += len;
}
buf[n] = '\0';
return n;
}
Rune
slastr(Str *s)
{
if(s->n < 1)
return 0;
return s->r[s->n-1];
}

372
strans.c Normal file
View File

@ -0,0 +1,372 @@
#include "dat.h"
#include "fn.h"
static Im im;
Lang langs[] = {
{LangJP, "hira", "kanji", nil, nil, jptrans},
{LangJPK, "kata", "kanji", nil, nil, jptrans},
{LangKO, "hangul", "hangul", nil, nil, trans},
};
int nlang = nelem(langs);
static void
clearkouho(void)
{
im.nkouho = 0;
im.sel = 0;
}
static void
setkouho(Dictres *res)
{
int i;
clearkouho();
for(i = 0; i < res->nkouho; i++){
im.kouho[i] = res->kouho[i];
im.nkouho++;
}
}
static void
show(void)
{
Drawcmd dc;
int i;
dc.nkouho = im.nkouho;
dc.sel = im.sel;
for(i = 0; i < dc.nkouho; i++)
dc.kouho[i] = im.kouho[i];
chansend(drawc, &dc);
}
static void
dictq(void)
{
Str dict;
Dictreq req;
if(!mapget(im.l->map, &im.line, &dict)){
clearkouho();
show();
return;
}
req.key = dict;
req.lang = im.l->lang;
req.line = im.line;
channbsend(dictreqc, &req);
}
static int
checklang(int c)
{
Lang *l;
l = getlang(c);
if(l == nil && c != LangEN)
return 0;
im.l = l;
return 1;
}
static void
commit(Str *com)
{
Str kana;
if(mapget(im.l->map, &im.line, &kana))
sappend(com, &kana);
sclear(&im.line);
}
static int
dotrans(Rune c, Str *com)
{
Emit e;
Dictreq req;
e = im.l->trans(&im, c);
if(e.s.n > 0)
sappend(com, &e.s);
sclear(&im.line);
sappend(&im.line, &e.next);
if(e.eat && e.dict.n > 0){
req.key = e.dict;
req.lang = im.l->lang;
req.line = im.line;
channbsend(dictreqc, &req);
}
return e.eat;
}
Lang*
getlang(int lang)
{
int i;
for(i = 0; i < nelem(langs); i++)
if(langs[i].lang == lang)
return &langs[i];
return nil;
}
Emit
trans(Im *im, Rune c)
{
Emit e = {0};
Str key, kana;
Hmap *h;
Rune last;
h = im->l->map;
key = im->line;
sputr(&key, c);
if(hmapget(h, &key)){
e.eat = 1;
e.next = key;
mapget(h, &key, &e.dict);
return e;
}
last = slastr(&im->line);
if(last == 0)
goto flush;
key = im->line;
key.n--;
if(mapget(h, &key, &kana)){
sclear(&key);
sputr(&key, last);
sputr(&key, c);
if(hmapget(h, &key)){
e.eat = 1;
e.s = kana;
sputr(&e.next, last);
sputr(&e.next, c);
mapget(h, &e.next, &e.dict);
return e;
}
}
flush:
mapget(h, &im->line, &e.s);
sclear(&key);
sputr(&key, c);
if(hmapget(h, &key) == nil){
e.flush = 1;
sputr(&e.s, c);
return e;
}
e.eat = 1;
sputr(&e.next, c);
mapget(h, &e.next, &e.dict);
return e;
}
static void
reset(void)
{
sclear(&im.line);
clearkouho();
show();
}
static int
keystroke(u32int ks, u32int mod, Str *com)
{
int n, off;
if(ks == Ksuper || ks == Kshift)
return 1;
if(ks == Kdown || ks == Kup){
if(im.nkouho == 0)
return 0;
if(ks == Kdown && im.sel < im.nkouho - 1)
im.sel++;
if(ks == Kup && im.sel > 0)
im.sel--;
show();
return 1;
}
n = ks - '1';
off = 0;
if(im.sel >= Maxdisp)
off = im.sel - Maxdisp + 1;
if(n >= 0 && n < Maxdisp && off + n < im.nkouho){
sappend(com, &im.kouho[off + n]);
reset();
return 1;
}
if(ks == Ktab || ks == Kret){
if(im.sel >= 0 && im.sel < im.nkouho){
sappend(com, &im.kouho[im.sel]);
reset();
return 1;
}
if(im.line.n > 0){
commit(com);
reset();
return 1;
}
return 0;
}
if(ks == Kback){
if(im.line.n == 0)
return 0;
spopr(&im.line);
if(im.line.n == 0){
reset();
return 1;
}
dictq();
return 1;
}
if(ks == Kesc){
if(im.line.n == 0)
return 0;
reset();
return 1;
}
if(ks >= Kspec || (mod & (Malt|Msuper))){
commit(com);
reset();
return 0;
}
if(mod & Mctrl){
reset();
if(ks >= 'a' && ks <= 'z')
ks -= 'a' - 1;
if(checklang(ks))
return 1;
return 0;
}
if(im.l == nil)
return 0;
if(ks > 0x7f || !isalpha(ks)){
commit(com);
sputr(com, ks);
reset();
return 1;
}
return dotrans(ks, com);
}
static void
init(void)
{
memset(&im, 0, sizeof(im));
}
void
imthread(void*)
{
Keyreq kr;
Dictres res;
Str com;
uchar out[256];
int n, len, r;
Alt alts[] = {
{keyc, &kr, CHANRCV, nil},
{dictresc, &res, CHANRCV, nil},
{nil, nil, CHANEND, nil},
};
threadsetname("im");
init();
for(;;){
switch(alt(alts)){
case 0:
sclear(&com);
r = keystroke(kr.ks, kr.mod, &com);
out[0] = r;
out[1] = 0;
n = 2;
if(com.n > 0){
len = stoutf(&com, (char*)(out+2), sizeof(out)-2);
out[1] = len;
n += len;
}
write(kr.fd, out, n);
break;
case 1:
if(scmp(&res.key, &im.line) == 0){
setkouho(&res);
show();
}
break;
}
}
}
int
mapget(Hmap *h, Str *key, Str *out)
{
Hnode *n;
if(key->n == 0)
return 0;
n = hmapget(h, key);
if(n == nil || n->kanalen == 0)
return 0;
sinit(out, n->kana, n->kanalen);
return 1;
}
static Hmap*
openmap(char *path)
{
Hmap *h;
Biobuf *b;
Str key, val, empty;
char *line, *tab;
int i, klen;
b = Bopen(path, OREAD);
if(b == nil)
die("can't open: %s", path);
h = hmapalloc(1024, 0);
sclear(&empty);
while((line = Brdstr(b, '\n', 1)) != nil){
if(line[0] == '\0'){
free(line);
continue;
}
tab = strchr(line, '\t');
if(tab == nil || tab[1] == '\0')
die("malformed map: %s", path);
*tab = '\0';
klen = strlen(line);
sinit(&key, line, klen);
sinit(&val, tab+1, strlen(tab+1));
hmapset(&h, &key, &val);
for(i = 1; i < klen; i++){
sinit(&key, line, i);
if(hmapget(h, &key) == nil)
hmapset(&h, &key, &empty);
}
free(line);
}
Bterm(b);
return h;
}
void
mapinit(char *dir)
{
char path[1024];
int i;
for(i = 0; i < nelem(langs); i++){
if(langs[i].mapname == nil)
continue;
snprint(path, sizeof(path), "%s/%s.map", dir, langs[i].mapname);
langs[i].map = openmap(path);
}
}

144
win.c Normal file
View File

@ -0,0 +1,144 @@
#include <xcb/xcb.h>
#include "dat.h"
#include "fn.h"
enum {
Asciitofull = 0xFEE0,
};
extern char *fontpath;
static xcb_connection_t *conn;
static xcb_screen_t *scr;
static xcb_window_t win;
static xcb_gcontext_t gc;
static u32int *img;
static int depth;
static xcb_screen_t*
getscr(xcb_connection_t *c, int n)
{
xcb_screen_iterator_t i;
for(i = xcb_setup_roots_iterator(xcb_get_setup(c)); i.rem; xcb_screen_next(&i))
if(n-- == 0)
return i.data;
return nil;
}
static void
wininit(void)
{
int n;
u32int mask, vals[4];
conn = xcb_connect(nil, &n);
if(conn == nil || xcb_connection_has_error(conn))
die("xcb_connect");
scr = getscr(conn, n);
if(scr == nil)
die("no screen");
depth = scr->root_depth;
win = xcb_generate_id(conn);
mask = XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL |
XCB_CW_OVERRIDE_REDIRECT | XCB_CW_SAVE_UNDER;
vals[0] = Colbg;
vals[1] = 0;
vals[2] = 1;
vals[3] = 1;
xcb_create_window(conn, XCB_COPY_FROM_PARENT, win, scr->root,
0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
scr->root_visual, mask, vals);
gc = xcb_generate_id(conn);
xcb_create_gc(conn, gc, win, 0, nil);
img = emalloc(Imgw * Imgh * sizeof(img[0]));
fontinit(fontpath);
}
static void
drawstr(u32int *buf, int x, int y, Rune *r, int n, int maxw, int maxh)
{
while(n-- > 0){
putfont(buf, maxw, maxh, x, y, *r++);
x += Fontsz;
}
}
static void
drawkouho(Drawcmd *dc, int first, int n, int w, int h)
{
int sely, y, i;
Str *s;
sely = 2 + (dc->sel - first) * Fontsz;
memset(img, (uchar)Colbg, w * h * sizeof(u32int));
memset(img + sely * w, (uchar)Colsel, Fontsz * w * sizeof(u32int));
for(y = 2, i = 0; i < n; i++, y += Fontsz){
s = &dc->kouho[first+i];
putfont(img, w, h, 0, y, '1' + i + Asciitofull);
drawstr(img, 2*Fontsz, y, s->r, s->n, w, h);
}
}
static void
putimage(int w, int h)
{
xcb_put_image(conn, XCB_IMAGE_FORMAT_Z_PIXMAP, win, gc,
w, h, 0, 0, 0, depth, w * h * 4, (u8int*)img);
xcb_flush(conn);
}
static void
winhide(void)
{
xcb_unmap_window(conn, win);
xcb_flush(conn);
}
static void
winshow(Drawcmd *dc)
{
int px, py, w, h, i, n, first, maxw;
u32int vals[4];
xcb_query_pointer_reply_t *ptr;
xcb_query_pointer_cookie_t cookie;
cookie = xcb_query_pointer(conn, scr->root);
first = dc->sel >= Maxdisp ? dc->sel - Maxdisp + 1 : 0;
n = min(dc->nkouho - first, Maxdisp);
maxw = 0;
for(i = 0; i < n; i++)
maxw = max(maxw, dc->kouho[first+i].n);
ptr = xcb_query_pointer_reply(conn, cookie, nil);
if(ptr == nil)
die("xcb_query_pointer");
px = ptr->root_x + 10;
py = ptr->root_y + 10;
free(ptr);
vals[3] = h = n * Fontsz + 4;
vals[2] = w = (maxw + 3) * Fontsz;
vals[1] = py = max(0, min(py, scr->height_in_pixels - h));
vals[0] = px = max(0, min(px, scr->width_in_pixels - w));
xcb_configure_window(conn, win,
XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y |
XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
vals);
xcb_map_window(conn, win);
drawkouho(dc, first, n, w, h);
putimage(w, h);
}
void
drawthread(void*)
{
Drawcmd dc;
threadsetname("draw");
wininit();
while(chanrecv(drawc, &dc) > 0){
if(dc.nkouho == 0)
winhide();
else
winshow(&dc);
}
}

28
xim/Makefile Normal file
View File

@ -0,0 +1,28 @@
CC = cc
CFLAGS = -Wall -Wextra -O2 -I.. -Ixcb-imdkit/src
PROG = strans-xim
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
LIBS = xcb-imdkit/libxcb-imdkit.a xcb-util/libxcb-util.a
all: $(PROG)
$(PROG): $(OBJS) $(LIBS)
$(CC) -o $@ $(OBJS) $(LIBS) -lxcb
$(OBJS): ../ipc.h
xcb-imdkit/libxcb-imdkit.a: xcb-util/libxcb-util.a
$(MAKE) -C xcb-imdkit
xcb-util/libxcb-util.a:
$(MAKE) -C xcb-util
clean:
rm -f $(OBJS) $(PROG)
$(MAKE) -C xcb-imdkit clean
$(MAKE) -C xcb-util clean
.PHONY: all clean

233
xim/main.c Normal file
View File

@ -0,0 +1,233 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <xcb/xcb.h>
#include "imdkit.h"
#include "encoding.h"
#include "ipc.h"
static xcb_connection_t *conn;
static xcb_im_t *xim;
static int srvfd;
static xcb_keysym_t *kmap;
static uint8_t minkc, maxkc;
static uint8_t symsper;
static char *encs[] = {"COMPOUND_TEXT", "en_US.UTF-8", ""};
static uint32_t styles[] = {
XCB_IM_PreeditNothing | XCB_IM_StatusNothing,
XCB_IM_PreeditNone | XCB_IM_StatusNone,
};
static void
die(char *msg)
{
fprintf(stderr, "strans-xim: %s\n", msg);
exit(1);
}
static void
kinit(void)
{
xcb_get_keyboard_mapping_cookie_t c;
xcb_get_keyboard_mapping_reply_t *r;
const xcb_setup_t *setup;
xcb_keysym_t *syms;
int i, n;
setup = xcb_get_setup(conn);
if(setup == NULL)
die("xcb_get_setup failed");
minkc = setup->min_keycode;
maxkc = setup->max_keycode;
c = xcb_get_keyboard_mapping(conn, minkc, maxkc - minkc + 1);
r = xcb_get_keyboard_mapping_reply(conn, c, NULL);
if(r == NULL)
die("keyboard mapping failed");
symsper = r->keysyms_per_keycode;
n = xcb_get_keyboard_mapping_keysyms_length(r);
kmap = malloc(n * sizeof(xcb_keysym_t));
if(kmap == NULL)
die("malloc failed");
syms = xcb_get_keyboard_mapping_keysyms(r);
for(i = 0; i < n; i++)
kmap[i] = syms[i];
free(r);
}
static uint32_t
kget(uint8_t kc, uint16_t state)
{
int col;
if(kmap == NULL || kc < minkc || kc > maxkc)
return 0;
col = (state & Mshift) ? 1 : 0;
if(col >= symsper)
col = 0;
return kmap[(kc - minkc) * symsper + col];
}
static xcb_screen_t*
getscreen(int scr)
{
xcb_screen_iterator_t iter;
const xcb_setup_t *setup;
setup = xcb_get_setup(conn);
if(setup == NULL)
die("xcb_get_setup failed");
iter = xcb_setup_roots_iterator(setup);
for(; iter.rem; scr--, xcb_screen_next(&iter))
if(scr == 0)
return iter.data;
die("no screen");
return NULL;
}
static void
commit(xcb_im_input_context_t *ic, char *s, int len)
{
char *ct;
size_t clen;
if(len == 0)
return;
ct = xcb_utf8_to_compound_text(s, len, &clen);
if(ct == NULL)
return;
xcb_im_commit_string(xim, ic, XCB_XIM_LOOKUP_CHARS, ct, clen, 0);
xcb_flush(conn);
free(ct);
}
static void
srvconnect(void)
{
struct sockaddr_un addr;
srvfd = socket(AF_UNIX, SOCK_STREAM, 0);
if(srvfd < 0)
die("socket failed");
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
snprintf(addr.sun_path, sizeof(addr.sun_path), "/tmp/strans.%d", getuid());
if(connect(srvfd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
die("can't connect to strans");
}
static int
readresp(xcb_im_input_context_t *ic)
{
unsigned char buf[64];
int n;
if(read(srvfd, buf, 2) != 2)
return -1;
n = buf[1];
if(n > 0 && (size_t)n < sizeof(buf) && read(srvfd, buf+2, n) == n)
commit(ic, (char*)(buf+2), n);
return buf[0];
}
static void
kpress(xcb_im_input_context_t *ic, xcb_key_press_event_t *ev)
{
unsigned char buf[4];
uint32_t key;
key = kget(ev->detail, ev->state);
if(key >= 0xff00)
key = Kspec + (key - 0xff00);
buf[0] = 0;
buf[1] = ev->state;
buf[2] = key;
buf[3] = key >> 8;
if(write(srvfd, buf, 4) != 4)
die("write failed");
if(readresp(ic) == 0)
xcb_im_forward_event(xim, ic, ev);
xcb_flush(conn);
}
static void
reset(xcb_im_input_context_t *ic)
{
unsigned char buf[4];
buf[0] = 0;
buf[1] = 0;
buf[2] = Kesc & 0xff;
buf[3] = Kesc >> 8;
if(write(srvfd, buf, 4) != 4)
die("write failed");
readresp(ic);
}
static void
callback(xcb_im_t *im, xcb_im_client_t *client, xcb_im_input_context_t *ic,
const xcb_im_packet_header_fr_t *hdr, void *frame, void *arg, void *user)
{
xcb_key_press_event_t *ev;
switch(hdr->major_opcode){
case XCB_XIM_FORWARD_EVENT:
ev = arg;
if(ev != NULL && (ev->response_type & ~0x80) == XCB_KEY_PRESS)
kpress(ic, ev);
break;
case XCB_XIM_UNSET_IC_FOCUS:
reset(ic);
break;
}
}
static void
ximinit(void)
{
xcb_screen_t *screen;
xcb_window_t win;
xcb_im_styles_t st;
xcb_im_encodings_t enc;
int scr;
st.nStyles = 2;
st.styles = styles;
enc.nEncodings = 3;
enc.encodings = encs;
xcb_compound_text_init();
conn = xcb_connect(NULL, &scr);
if(conn == NULL || xcb_connection_has_error(conn))
die("xcb_connect failed");
screen = getscreen(scr);
kinit();
win = xcb_generate_id(conn);
xcb_create_window(conn, XCB_COPY_FROM_PARENT, win, screen->root,
0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
screen->root_visual, 0, NULL);
xim = xcb_im_create(conn, scr, win, "strans",
XCB_IM_ALL_LOCALES, &st, NULL, NULL, &enc,
XCB_EVENT_MASK_KEY_PRESS, callback, NULL);
if(xim == NULL || !xcb_im_open_im(xim))
die("xcb_im failed");
}
int
main(void)
{
xcb_generic_event_t *ev;
srvconnect();
ximinit();
for(;;){
ev = xcb_wait_for_event(conn);
if(ev == NULL)
break;
xcb_im_filter_event(xim, ev);
free(ev);
}
return 0;
}

View File

@ -0,0 +1,58 @@
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -4
ConstructorInitializerIndentWidth: 4
AlignEscapedNewlinesLeft: false
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AlwaysBreakTemplateDeclarations: true
AlwaysBreakBeforeMultilineStrings: false
BreakBeforeBinaryOperators: false
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BinPackParameters: true
ColumnLimit: 80
ConstructorInitializerAllOnOneLineOrOnePerLine: false
DerivePointerAlignment: false
ExperimentalAutoDetectBinPacking: false
IndentCaseLabels: false
IndentWrappedFunctionNames: false
IndentFunctionDeclarationAfterType: false
MaxEmptyLinesToKeep: 1
KeepEmptyLinesAtTheStartOfBlocks: true
NamespaceIndentation: None
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakString: 1000
PenaltyBreakFirstLessLess: 120
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
SpacesBeforeTrailingComments: 1
Cpp11BracedListStyle: true
Standard: Cpp11
IndentWidth: 4
TabWidth: 4
UseTab: Never
BreakBeforeBraces: Attach
SpacesInParentheses: false
SpacesInAngles: false
SpaceInEmptyParentheses: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: true
SpaceBeforeAssignmentOperators: true
ContinuationIndentWidth: 4
CommentPragmas: '^ IWYU pragma:'
ForEachMacros: [ Q_FOREACH, BOOST_FOREACH ]
SpaceBeforeParens: ControlStatements
DisableFormat: false
SortIncludes: true
...

View File

@ -0,0 +1,2 @@
xlibi18n/**
ximproto-gen.h

View File

@ -0,0 +1,55 @@
name: CI
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
clang-format:
name: Check clang-format
runs-on: ubuntu-latest
container: archlinux:latest
steps:
- name: Install dependencies
run: |
pacman -Syu --noconfirm git clang diffutils
git config --global --add safe.directory $GITHUB_WORKSPACE
- uses: actions/checkout@v4
- uses: fcitx/github-actions@clang-format
check:
name: Build and test
needs: clang-format
runs-on: ubuntu-latest
container: archlinux:latest
strategy:
fail-fast: false
matrix:
compiler: [gcc, clang]
include:
- compiler: gcc
cxx_compiler: g++
- compiler: clang
cxx_compiler: clang++
env:
CC: ${{ matrix.compiler }}
CXX: ${{ matrix.cxx_compiler }}
steps:
- name: Install dependencies
run: |
pacman -Syu --noconfirm base-devel clang cmake ninja extra-cmake-modules xcb-util xcb-util-keysyms
- name: Init CodeQL
uses: github/codeql-action/init@v3
with:
languages: c
- uses: actions/checkout@v4
- name: Build and Install
uses: fcitx/github-actions@cmake
with:
path: .
- name: Test
run: |
ctest --test-dir build
- name: CodeQL Analysis
uses: github/codeql-action/analyze@v2

6
xim/xcb-imdkit/.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
*.kdev4
build*/
*~
*.swp
cscope.*
i18nIMProto.c

View File

@ -0,0 +1,54 @@
cmake_minimum_required(VERSION 3.8)
project(xcb-imdkit VERSION 1.0.9)
find_package(ECM 0.0.11 REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
option(USE_SYSTEM_UTHASH "Enable system utash" On)
include(GenerateExportHeader)
include(CheckFunctionExists)
include(CMakePackageConfigHelpers)
include(ECMSetupVersion)
include(ECMGenerateHeaders)
include(uninstall)
if (USE_SYSTEM_UTHASH)
find_package(UTHash)
endif()
if (NOT TARGET UTHash::UTHash)
add_library(UTHash::UTHash INTERFACE IMPORTED )
set_target_properties(UTHash::UTHash PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/uthash"
)
endif()
set(CMAKE_C_EXTENSIONS OFF)
set(CMAKE_C_STANDARD_REQUIRED TRUE)
set(CMAKE_C_STANDARD 11)
include(GNUInstallDirs)
# directory needed by bsd
if(NOT CMAKE_INSTALL_LIBDATADIR)
set(CMAKE_INSTALL_LIBDATADIR "${CMAKE_INSTALL_LIBDIR}" CACHE PATH "libdata root (LIBDIR)")
set(CMAKE_INSTALL_LIBDATADIR "${CMAKE_INSTALL_LIBDIR}")
mark_as_advanced(CMAKE_INSTALL_LIBDATADIR)
endif()
set(CMAKECONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/XCBImdkit")
add_definitions(-D_GNU_SOURCE)
set(CMAKE_C_FLAGS "-fPIC -Wall -Wextra -Wno-unused-parameter -fvisibility=hidden ${CMAKE_C_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed -Wl,--no-undefined ${CMAKE_SHARED_LINKER_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS "-Wl,--as-needed ${CMAKE_MODULE_LINKER_FLAGS}")
find_package(XCB REQUIRED COMPONENTS XCB UTIL KEYSYMS)
enable_testing()
add_subdirectory(src)
add_subdirectory(test)
# Write out the features
feature_summary (WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES)

View File

@ -0,0 +1,467 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies of this license
document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts as the
successor of the GNU Library Public License, version 2, hence the version
number 2.1.]
Preamble
The licenses for most software are designed to take away your freedom to share
and change it. By contrast, the GNU General Public Licenses are intended to
guarantee your freedom to share and change free software--to make sure the
software is free for all its users.
This license, the Lesser General Public License, applies to some specially
designated software packages--typically libraries--of the Free Software Foundation
and other authors who decide to use it. You can use it too, but we suggest
you first think carefully about whether this license or the ordinary General
Public License is the better strategy to use in any particular case, based
on the explanations below.
When we speak of free software, we are referring to freedom of use, not price.
Our General Public Licenses are designed to make sure that you have the freedom
to distribute copies of free software (and charge for this service if you
wish); that you receive source code or can get it if you want it; that you
can change the software and use pieces of it in new free programs; and that
you are informed that you can do these things.
To protect your rights, we need to make restrictions that forbid distributors
to deny you these rights or to ask you to surrender these rights. These restrictions
translate to certain responsibilities for you if you distribute copies of
the library or if you modify it.
For example, if you distribute copies of the library, whether gratis or for
a fee, you must give the recipients all the rights that we gave you. You must
make sure that they, too, receive or can get the source code. If you link
other code with the library, you must provide complete object files to the
recipients, so that they can relink them with the library after making changes
to the library and recompiling it. And you must show them these terms so they
know their rights.
We protect your rights with a two-step method: (1) we copyright the library,
and (2) we offer you this license, which gives you legal permission to copy,
distribute and/or modify the library.
To protect each distributor, we want to make it very clear that there is no
warranty for the free library. Also, if the library is modified by someone
else and passed on, the recipients should know that what they have is not
the original version, so that the original author's reputation will not be
affected by problems that might be introduced by others.
Finally, software patents pose a constant threat to the existence of any free
program. We wish to make sure that a company cannot effectively restrict the
users of a free program by obtaining a restrictive license from a patent holder.
Therefore, we insist that any patent license obtained for a version of the
library must be consistent with the full freedom of use specified in this
license.
Most GNU software, including some libraries, is covered by the ordinary GNU
General Public License. This license, the GNU Lesser General Public License,
applies to certain designated libraries, and is quite different from the ordinary
General Public License. We use this license for certain libraries in order
to permit linking those libraries into non-free programs.
When a program is linked with a library, whether statically or using a shared
library, the combination of the two is legally speaking a combined work, a
derivative of the original library. The ordinary General Public License therefore
permits such linking only if the entire combination fits its criteria of freedom.
The Lesser General Public License permits more lax criteria for linking other
code with the library.
We call this license the "Lesser" General Public License because it does Less
to protect the user's freedom than the ordinary General Public License. It
also provides other free software developers Less of an advantage over competing
non-free programs. These disadvantages are the reason we use the ordinary
General Public License for many libraries. However, the Lesser license provides
advantages in certain special circumstances.
For example, on rare occasions, there may be a special need to encourage the
widest possible use of a certain library, so that it becomes a de-facto standard.
To achieve this, non-free programs must be allowed to use the library. A more
frequent case is that a free library does the same job as widely used non-free
libraries. In this case, there is little to gain by limiting the free library
to free software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free programs
enables a greater number of people to use a large body of free software. For
example, permission to use the GNU C Library in non-free programs enables
many more people to use the whole GNU operating system, as well as its variant,
the GNU/Linux operating system.
Although the Lesser General Public License is Less protective of the users'
freedom, it does ensure that the user of a program that is linked with the
Library has the freedom and the wherewithal to run that program using a modified
version of the Library.
The precise terms and conditions for copying, distribution and modification
follow. Pay close attention to the difference between a "work based on the
library" and a "work that uses the library". The former contains code derived
from the library, whereas the latter must be combined with the library in
order to run.
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other program
which contains a notice placed by the copyright holder or other authorized
party saying it may be distributed under the terms of this Lesser General
Public License (also called "this License"). Each licensee is addressed as
"you".
A "library" means a collection of software functions and/or data prepared
so as to be conveniently linked with application programs (which use some
of those functions and data) to form executables.
The "Library", below, refers to any such software library or work which has
been distributed under these terms. A "work based on the Library" means either
the Library or any derivative work under copyright law: that is to say, a
work containing the Library or a portion of it, either verbatim or with modifications
and/or translated straightforwardly into another language. (Hereinafter, translation
is included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for making modifications
to it. For a library, complete source code means all the source code for all
modules it contains, plus any associated interface definition files, plus
the scripts used to control compilation and installation of the library.
Activities other than copying, distribution and modification are not covered
by this License; they are outside its scope. The act of running a program
using the Library is not restricted, and output from such a program is covered
only if its contents constitute a work based on the Library (independent of
the use of the Library in a tool for writing it). Whether that is true depends
on what the Library does and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's complete source
code as you receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice and disclaimer
of warranty; keep intact all the notices that refer to this License and to
the absence of any warranty; and distribute a copy of this License along with
the Library.
You may charge a fee for the physical act of transferring a copy, and you
may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Library or any portion of it,
thus forming a work based on the Library, and copy and distribute such modifications
or work under the terms of Section 1 above, provided that you also meet all
of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices stating that
you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no charge to all
third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a table of
data to be supplied by an application program that uses the facility, other
than as an argument passed when the facility is invoked, then you must make
a good faith effort to ensure that, in the event an application does not supply
such function or table, the facility still operates, and performs whatever
part of its purpose remains meaningful.
(For example, a function in a library to compute square roots has a purpose
that is entirely well-defined independent of the application. Therefore, Subsection
2d requires that any application-supplied function or table used by this function
must be optional: if the application does not supply it, the square root function
must still compute square roots.)
These requirements apply to the modified work as a whole. If identifiable
sections of that work are not derived from the Library, and can be reasonably
considered independent and separate works in themselves, then this License,
and its terms, do not apply to those sections when you distribute them as
separate works. But when you distribute the same sections as part of a whole
which is a work based on the Library, the distribution of the whole must be
on the terms of this License, whose permissions for other licensees extend
to the entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest your
rights to work written entirely by you; rather, the intent is to exercise
the right to control the distribution of derivative or collective works based
on the Library.
In addition, mere aggregation of another work not based on the Library with
the Library (or with a work based on the Library) on a volume of a storage
or distribution medium does not bring the other work under the scope of this
License.
3. You may opt to apply the terms of the ordinary GNU General Public License
instead of this License to a given copy of the Library. To do this, you must
alter all the notices that refer to this License, so that they refer to the
ordinary GNU General Public License, version 2, instead of to this License.
(If a newer version than version 2 of the ordinary GNU General Public License
has appeared, then you can specify that version instead if you wish.) Do not
make any other change in these notices.
Once this change is made in a given copy, it is irreversible for that copy,
so the ordinary GNU General Public License applies to all subsequent copies
and derivative works made from that copy.
This option is useful when you wish to copy part of the code of the Library
into a program that is not a library.
4. You may copy and distribute the Library (or a portion or derivative of
it, under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you accompany it with the complete corresponding
machine-readable source code, which must be distributed under the terms of
Sections 1 and 2 above on a medium customarily used for software interchange.
If distribution of object code is made by offering access to copy from a designated
place, then offering equivalent access to copy the source code from the same
place satisfies the requirement to distribute the source code, even though
third parties are not compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the Library, but
is designed to work with the Library by being compiled or linked with it,
is called a "work that uses the Library". Such a work, in isolation, is not
a derivative work of the Library, and therefore falls outside the scope of
this License.
However, linking a "work that uses the Library" with the Library creates an
executable that is a derivative of the Library (because it contains portions
of the Library), rather than a "work that uses the library". The executable
is therefore covered by this License. Section 6 states terms for distribution
of such executables.
When a "work that uses the Library" uses material from a header file that
is part of the Library, the object code for the work may be a derivative work
of the Library even though the source code is not. Whether this is true is
especially significant if the work can be linked without the Library, or if
the work is itself a library. The threshold for this to be true is not precisely
defined by law.
If such an object file uses only numerical parameters, data structure layouts
and accessors, and small macros and small inline functions (ten lines or less
in length), then the use of the object file is unrestricted, regardless of
whether it is legally a derivative work. (Executables containing this object
code plus portions of the Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may distribute
the object code for the work under the terms of Section 6. Any executables
containing that work also fall under Section 6, whether or not they are linked
directly with the Library itself.
6. As an exception to the Sections above, you may also combine or link a "work
that uses the Library" with the Library to produce a work containing portions
of the Library, and distribute that work under terms of your choice, provided
that the terms permit modification of the work for the customer's own use
and reverse engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the Library
is used in it and that the Library and its use are covered by this License.
You must supply a copy of this License. If the work during execution displays
copyright notices, you must include the copyright notice for the Library among
them, as well as a reference directing the user to the copy of this License.
Also, you must do one of these things:
a) Accompany the work with the complete corresponding machine-readable source
code for the Library including whatever changes were used in the work (which
must be distributed under Sections 1 and 2 above); and, if the work is an
executable linked with the Library, with the complete machine-readable "work
that uses the Library", as object code and/or source code, so that the user
can modify the Library and then relink to produce a modified executable containing
the modified Library. (It is understood that the user who changes the contents
of definitions files in the Library will not necessarily be able to recompile
the application to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the Library. A
suitable mechanism is one that (1) uses at run time a copy of the library
already present on the user's computer system, rather than copying library
functions into the executable, and (2) will operate properly with a modified
version of the library, if the user installs one, as long as the modified
version is interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at least three years,
to give the same user the materials specified in Subsection 6a, above, for
a charge no more than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy from a designated
place, offer equivalent access to copy the above specified materials from
the same place.
e) Verify that the user has already received a copy of these materials or
that you have already sent this user a copy.
For an executable, the required form of the "work that uses the Library" must
include any data and utility programs needed for reproducing the executable
from it. However, as a special exception, the materials to be distributed
need not include anything that is normally distributed (in either source or
binary form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component itself
accompanies the executable.
It may happen that this requirement contradicts the license restrictions of
other proprietary libraries that do not normally accompany the operating system.
Such a contradiction means you cannot use both them and the Library together
in an executable that you distribute.
7. You may place library facilities that are a work based on the Library side-by-side
in a single library together with other library facilities not covered by
this License, and distribute such a combined library, provided that the separate
distribution of the work based on the Library and of the other library facilities
is otherwise permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work based on the
Library, uncombined with any other library facilities. This must be distributed
under the terms of the Sections above.
b) Give prominent notice with the combined library of the fact that part of
it is a work based on the Library, and explaining where to find the accompanying
uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute the Library
except as expressly provided under this License. Any attempt otherwise to
copy, modify, sublicense, link with, or distribute the Library is void, and
will automatically terminate your rights under this License. However, parties
who have received copies, or rights, from you under this License will not
have their licenses terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not signed
it. However, nothing else grants you permission to modify or distribute the
Library or its derivative works. These actions are prohibited by law if you
do not accept this License. Therefore, by modifying or distributing the Library
(or any work based on the Library), you indicate your acceptance of this License
to do so, and all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the Library),
the recipient automatically receives a license from the original licensor
to copy, distribute, link with or modify the Library subject to these terms
and conditions. You may not impose any further restrictions on the recipients'
exercise of the rights granted herein. You are not responsible for enforcing
compliance by third parties with this License.
11. If, as a consequence of a court judgment or allegation of patent infringement
or for any other reason (not limited to patent issues), conditions are imposed
on you (whether by court order, agreement or otherwise) that contradict the
conditions of this License, they do not excuse you from the conditions of
this License. If you cannot distribute so as to satisfy simultaneously your
obligations under this License and any other pertinent obligations, then as
a consequence you may not distribute the Library at all. For example, if a
patent license would not permit royalty-free redistribution of the Library
by all those who receive copies directly or indirectly through you, then the
only way you could satisfy both it and this License would be to refrain entirely
from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any patents
or other property right claims or to contest validity of any such claims;
this section has the sole purpose of protecting the integrity of the free
software distribution system which is implemented by public license practices.
Many people have made generous contributions to the wide range of software
distributed through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing to
distribute software through any other system and a licensee cannot impose
that choice.
This section is intended to make thoroughly clear what is believed to be a
consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in certain
countries either by patents or by copyrighted interfaces, the original copyright
holder who places the Library under this License may add an explicit geographical
distribution limitation excluding those countries, so that distribution is
permitted only in or among countries not thus excluded. In such case, this
License incorporates the limitation as if written in the body of this License.
13. The Free Software Foundation may publish revised and/or new versions of
the Lesser General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to address
new problems or concerns.
Each version is given a distinguishing version number. If the Library specifies
a version number of this License which applies to it and "any later version",
you have the option of following the terms and conditions either of that version
or of any later version published by the Free Software Foundation. If the
Library does not specify a license version number, you may choose any version
ever published by the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free programs
whose distribution conditions are incompatible with these, write to the author
to ask for permission. For software which is copyrighted by the Free Software
Foundation, write to the Free Software Foundation; we sometimes make exceptions
for this. Our decision will be guided by the two goals of preserving the free
status of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY
"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE
THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE
OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA
OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES
OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH
HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest possible
use to the public, we recommend making it free software that everyone can
redistribute and change. You can do so by permitting redistribution under
these terms (or, alternatively, under the terms of the ordinary General Public
License).
To apply these terms, attach the following notices to the library. It is safest
to attach them to the start of each source file to most effectively convey
the exclusion of warranty; and each file should have at least the "copyright"
line and a pointer to where the full notice is found.
< one line to give the library's name and an idea of what it does. >
Copyright (C) < year > < name of author >
This library is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at your option)
any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License along
with this library; if not, write to the Free Software Foundation, Inc., 51
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information
on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your school,
if any, to sign a "copyright disclaimer" for the library, if necessary. Here
is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in
the library `Frob' (a library for tweaking knobs) written
by James Random Hacker.
< signature of Ty Coon > , 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

21
xim/xcb-imdkit/Makefile Normal file
View File

@ -0,0 +1,21 @@
CC = cc
CFLAGS = -Wall -Wextra -O2 -fPIC -Isrc -I. -Iuthash -Isrc/xlibi18n -I../xcb-util
AR = ar
SRCS = src/imdkit.c src/encoding.c src/protocolhandler.c \
src/ximproto.c src/parser.c src/message.c src/common.c \
src/xlibi18n/lcCharSet.c src/xlibi18n/lcCT.c src/xlibi18n/lcUTF8.c
OBJS = $(SRCS:.c=.o)
all: libxcb-imdkit.a
libxcb-imdkit.a: $(OBJS)
$(AR) rcs $@ $(OBJS)
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
clean:
rm -f $(OBJS) libxcb-imdkit.a
.PHONY: all clean

29
xim/xcb-imdkit/README.md Normal file
View File

@ -0,0 +1,29 @@
xcb-imdkit
==============================
xcb-imdkit is an implementation of xim protocol in xcb, comparing with the
implementation of IMDkit with Xlib, and xim inside Xlib, it has less memory
foot print, better performance, and safer on malformed client.
And not to say it's all asynchronous and it works with xcb.
Though, it doesn't have complete protocol support, since some part of the protocol
is never used. Those parts include:
- XIM_EXT_SET_EVENT_MASK (no im actually use this)
- XIM_EXT_FORWARD_EVENT (it's not any better than forward event)
- XIM_AUTH (IMDkit doesn't implement this, Xlib only has stub, so still no implementation.)
- XIM_STR_CONVERSION (Synchronous protocol, but not used anywhere)
- Locale check on client side, this is actually very evil for input method.
- Only X transport is supported.
To build this project, you need:
libxcb, xcb-util, xcb-util-keysym
Commands:
mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX=/usr ..
make
sudo make install
xcb-imdkit is released under LGPLv2+, and it is using uthash internally,
which is released under BSD-license.

View File

@ -0,0 +1,18 @@
set(UTHASH_PREFIX "" CACHE PATH "Prefix uthash was installed into")
find_path(UTHash_INCLUDE_DIR NAMES uthash.h HINTS ${UTHASH_PREFIX} PATH_SUFFIXES include)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(UTHash
FOUND_VAR
UTHash_FOUND
REQUIRED_VARS
UTHash_INCLUDE_DIR
)
if(UTHash_FOUND AND NOT TARGET UTHash::UTHash)
add_library(UTHash::UTHash INTERFACE IMPORTED )
set_target_properties(UTHash::UTHash PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${EXECINFO_INCLUDE_DIR}"
)
endif()

View File

@ -0,0 +1,21 @@
if (NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
message(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
string(REGEX REPLACE "\n" ";" files "${files}")
foreach (file ${files})
message(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
if (EXISTS "$ENV{DESTDIR}${file}" OR IS_SYMLINK "$ENV{DESTDIR}${file}")
execute_process(
COMMAND @CMAKE_COMMAND@ -E remove "$ENV{DESTDIR}${file}"
OUTPUT_VARIABLE rm_out
RESULT_VARIABLE rm_retval
)
if(NOT ${rm_retval} EQUAL 0)
message(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
endif (NOT ${rm_retval} EQUAL 0)
else (EXISTS "$ENV{DESTDIR}${file}" OR IS_SYMLINK "$ENV{DESTDIR}${file}")
message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
endif (EXISTS "$ENV{DESTDIR}${file}" OR IS_SYMLINK "$ENV{DESTDIR}${file}")
endforeach(file)

View File

@ -0,0 +1,8 @@
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE @ONLY)
add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)

View File

@ -0,0 +1,67 @@
ecm_setup_version(
PROJECT
VARIABLE_PREFIX XCB_IMDKIT
VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/xcb-imdkit_version.h"
PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/XCBImdkitConfigVersion.cmake"
SOVERSION 1
)
configure_package_config_file(
"${CMAKE_CURRENT_SOURCE_DIR}/XCBImdkitConfig.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/XCBImdkitConfig.cmake"
INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR}
)
set(XCB_IMDKIT_HEADERS
imdkit.h ximcommon.h ximproto.h ximproto-gen.h imclient.h encoding.h "${CMAKE_CURRENT_BINARY_DIR}/xcbimdkit_export.h"
)
add_library(xcb-imdkit SHARED
parser.c ximproto.c imdkit.c protocolhandler.c message.c common.c imclient.c clientprotocolhandler.c
encoding.c
xlibi18n/lcCT.c
xlibi18n/lcUTF8.c
xlibi18n/lcCharSet.c
)
generate_export_header(xcb-imdkit BASE_NAME XCBImdkit)
add_library(XCBImdkit::XCBImdkit ALIAS xcb-imdkit)
target_include_directories(xcb-imdkit
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
INTERFACE $<INSTALL_INTERFACE:${CMAKE_INSTALL_FULL_INCLUDEDIR}>)
set_target_properties(xcb-imdkit PROPERTIES
VERSION ${XCB_IMDKIT_VERSION}
SOVERSION ${XCB_IMDKIT_SOVERSION}
C_VISIBILITY_PRESET hidden
LINK_FLAGS "-Wl,--no-undefined"
EXPORT_NAME XCBImdkit)
target_link_libraries(xcb-imdkit
PUBLIC XCB::XCB
PRIVATE XCB::UTIL UTHash::UTHash)
configure_file(xcb-imdkit.pc.in ${CMAKE_CURRENT_BINARY_DIR}/xcb-imdkit.pc @ONLY)
install(TARGETS xcb-imdkit EXPORT XCBImdkitLibraryTargets LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}")
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/xcb-imdkit.pc
DESTINATION "${CMAKE_INSTALL_LIBDATADIR}/pkgconfig")
install(FILES ${XCB_IMDKIT_HEADERS} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/xcb-imdkit")
install (
EXPORT XCBImdkitLibraryTargets
DESTINATION "${CMAKECONFIG_INSTALL_DIR}"
FILE XCBImdkitLibraryTargets.cmake
NAMESPACE XCBImdkit::
)
install (
FILES "${CMAKE_CURRENT_BINARY_DIR}/XCBImdkitConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/XCBImdkitConfigVersion.cmake"
DESTINATION "${CMAKECONFIG_INSTALL_DIR}"
COMPONENT Devel
)

View File

@ -0,0 +1,3 @@
@PACKAGE_INIT@
include("${CMAKE_CURRENT_LIST_DIR}/XCBImdkitLibraryTargets.cmake")

View File

@ -0,0 +1,855 @@
/*
* SPDX-FileCopyrightText: 2014 Weng Xuetian <wengxt@gmail.com>
*
* SPDX-License-Identifier: LGPL-2.1-only
*
*/
#include "clientprotocolhandler.h"
#include "common.h"
#include "imclient_p.h"
#include "parser.h"
#include "uthash.h"
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <xcb/xproto.h>
bool _xcb_xim_send_query_extension(xcb_xim_t *im) {
xcb_im_query_extension_fr_t frame;
xcb_im_str_fr_t extensions[ARRAY_SIZE(Default_Extension)];
frame.input_method_ID = im->connect_id;
frame.extensions_supported_by_the_IM_library.size =
ARRAY_SIZE(Default_Extension);
frame.extensions_supported_by_the_IM_library.items = extensions;
for (uint32_t i = 0; i < frame.extensions_supported_by_the_IM_library.size;
i++) {
extensions[i].length_of_string = strlen(Default_Extension[i].name);
extensions[i].string = (uint8_t *)Default_Extension[i].name;
}
bool fail;
_xcb_xim_send_frame(im, frame, fail);
if (!fail) {
im->open_state = XIM_OPEN_WAIT_EXTENSION_REPLY;
}
return !fail;
}
bool _xcb_xim_send_encoding_negotiation(xcb_xim_t *im) {
xcb_im_encoding_negotiation_fr_t frame;
xcb_im_str_fr_t encodings[2];
int idx = 0;
if (im->use_compound_text) {
encodings[idx].length_of_string = strlen("COMPOUND_TEXT");
encodings[idx].string = (uint8_t *)"COMPOUND_TEXT";
idx++;
}
if (im->use_utf8_string) {
encodings[idx].length_of_string = strlen("UTF8_STRING");
encodings[idx].string = (uint8_t *)"UTF8_STRING";
idx++;
}
frame.input_method_ID = im->connect_id;
frame.supported_list_of_encoding_in_IM_library.size = idx;
frame.supported_list_of_encoding_in_IM_library.items = encodings;
frame.list_of_encodings_supported_in_th.size = 0;
frame.list_of_encodings_supported_in_th.items = 0;
bool fail;
_xcb_xim_send_frame(im, frame, fail);
if (!fail) {
im->open_state = XIM_OPEN_WAIT_ENCODING_REPLY;
}
return !fail;
}
void _xcb_xim_handle_open_reply(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
if (im->open_state != XIM_OPEN_WAIT_OPEN_REPLY) {
return;
}
xcb_im_open_reply_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
im->connect_id = frame.input_method_ID;
// construct a name based attr table
for (uint32_t i = 0; i < frame.IM_attribute_supported.size; i++) {
xcb_im_ximattr_fr_t *subframe = &frame.IM_attribute_supported.items[i];
if (subframe->length_of_im_attribute == 0) {
continue;
}
xcb_xim_imattr_table_t *imattr = NULL;
HASH_FIND(hh, im->imattr, subframe->im_attribute,
subframe->length_of_im_attribute, imattr);
if (imattr) {
continue;
}
imattr = malloc(sizeof(xcb_xim_imattr_table_t));
imattr->attr.attribute_ID = subframe->attribute_ID;
imattr->attr.type_of_the_value = subframe->type_of_the_value;
imattr->attr.length_of_im_attribute = subframe->length_of_im_attribute;
imattr->attr.im_attribute =
malloc((imattr->attr.length_of_im_attribute + 1) * sizeof(uint8_t));
imattr->attr.im_attribute[imattr->attr.length_of_im_attribute] = 0;
memcpy(imattr->attr.im_attribute, subframe->im_attribute,
imattr->attr.length_of_im_attribute);
HASH_ADD_KEYPTR(hh, im->imattr, imattr->attr.im_attribute,
imattr->attr.length_of_im_attribute, imattr);
}
for (uint32_t i = 0; i < frame.IC_attribute_supported.size; i++) {
xcb_im_xicattr_fr_t *subframe = &frame.IC_attribute_supported.items[i];
if (subframe->length_of_ic_attribute == 0) {
continue;
}
xcb_xim_icattr_table_t *icattr = NULL;
HASH_FIND(hh, im->icattr, subframe->ic_attribute,
subframe->length_of_ic_attribute, icattr);
if (icattr) {
continue;
}
icattr = malloc(sizeof(xcb_xim_icattr_table_t));
icattr->attr.attribute_ID = subframe->attribute_ID;
icattr->attr.type_of_the_value = subframe->type_of_the_value;
icattr->attr.length_of_ic_attribute = subframe->length_of_ic_attribute;
icattr->attr.ic_attribute =
malloc((icattr->attr.length_of_ic_attribute + 1) * sizeof(uint8_t));
icattr->attr.ic_attribute[icattr->attr.length_of_ic_attribute] = 0;
memcpy(icattr->attr.ic_attribute, subframe->ic_attribute,
icattr->attr.length_of_ic_attribute);
HASH_ADD_KEYPTR(hh, im->icattr, icattr->attr.ic_attribute,
icattr->attr.length_of_ic_attribute, icattr);
}
xcb_im_open_reply_fr_free(&frame);
_xcb_xim_send_query_extension(im);
}
void _xcb_xim_handle_query_extension_reply(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
if (im->open_state != XIM_OPEN_WAIT_EXTENSION_REPLY) {
return;
}
xcb_im_query_extension_reply_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
do {
if (frame.input_method_ID != im->connect_id) {
break;
}
free(im->extensions);
im->extensions = NULL;
im->nExtensions = 0;
// There are some wrong implementation around that use a different wire
// format, thus do not hard fail on this.
if (fail) {
break;
}
im->extensions =
frame.list_of_extensions_supported_by_th.size
? calloc(frame.list_of_extensions_supported_by_th.size,
sizeof(xcb_xim_extension_t))
: NULL;
im->nExtensions = frame.list_of_extensions_supported_by_th.size;
for (uint32_t i = 0; i < frame.list_of_extensions_supported_by_th.size;
i++) {
im->extensions[i].major_code =
frame.list_of_extensions_supported_by_th.items[i]
.extension_major_opcode;
im->extensions[i].minor_code =
frame.list_of_extensions_supported_by_th.items[i]
.extension_minor_opcode;
}
} while (0);
_xcb_xim_send_encoding_negotiation(im);
if (!fail) {
xcb_im_query_extension_reply_fr_free(&frame);
}
}
void _xcb_xim_handle_encoding_negotiation_reply(
xcb_xim_t *im, const xcb_im_packet_header_fr_t *hdr, uint8_t *data) {
if (im->open_state != XIM_OPEN_WAIT_ENCODING_REPLY) {
return;
}
xcb_im_encoding_negotiation_reply_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
xcb_xim_encoding_t encodings[2] = {XCB_XIM_COMPOUND_TEXT,
XCB_XIM_COMPOUND_TEXT};
size_t nEncodings = 0;
if (im->use_compound_text) {
encodings[nEncodings++] = XCB_XIM_COMPOUND_TEXT;
}
if (im->use_utf8_string) {
encodings[nEncodings++] = XCB_XIM_UTF8_STRING;
}
// we only send compound
if (frame.input_method_ID != im->connect_id &&
frame.index_of_the_encoding_determined >= nEncodings) {
break;
}
im->open_state = XIM_OPEN_DONE;
im->encoding = encodings[frame.index_of_the_encoding_determined];
if (im->connect_state.callback) {
im->connect_state.callback(im, im->connect_state.user_data);
}
_xcb_change_event_mask(im->conn, im->accept_win,
XCB_EVENT_MASK_STRUCTURE_NOTIFY, false);
} while (0);
xcb_im_encoding_negotiation_reply_fr_free(&frame);
}
void _xcb_xim_handle_register_triggerkeys(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_register_triggerkeys_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
// we dont check (frame.input_method_ID != im->connect_id);
// here because this is send with open_reply
free(im->onKeys.keys);
free(im->offKeys.keys);
im->onKeys.keys = frame.on_keys_list.size
? calloc(frame.on_keys_list.size,
sizeof(xcb_im_ximtriggerkey_fr_t))
: NULL;
im->offKeys.keys = frame.off_keys_list.size
? calloc(frame.off_keys_list.size,
sizeof(xcb_im_ximtriggerkey_fr_t))
: NULL;
if ((frame.on_keys_list.size && !im->onKeys.keys) ||
(frame.off_keys_list.size && !im->offKeys.keys)) {
free(im->onKeys.keys);
free(im->offKeys.keys);
im->onKeys.keys = im->offKeys.keys = NULL;
im->onKeys.nKeys = im->offKeys.nKeys = 0;
break;
}
im->onKeys.nKeys = frame.on_keys_list.size;
im->offKeys.nKeys = frame.off_keys_list.size;
if (frame.on_keys_list.size) {
memcpy(im->onKeys.keys, frame.on_keys_list.items,
frame.on_keys_list.size * sizeof(xcb_im_ximtriggerkey_fr_t));
}
if (frame.off_keys_list.size) {
memcpy(im->offKeys.keys, frame.off_keys_list.items,
frame.off_keys_list.size *
sizeof(xcb_im_ximtriggerkey_fr_t));
}
} while (0);
xcb_im_register_triggerkeys_fr_free(&frame);
}
void _xcb_xim_handle_create_ic_reply(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_create_ic_reply_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (!im->current) {
break;
}
if (im->current->major_code != XCB_XIM_CREATE_IC &&
im->connect_id != frame.input_method_ID) {
break;
}
xcb_xim_request_queue_t *request = im->current;
im->current = NULL;
if (request->callback.create_ic) {
request->callback.create_ic(im, frame.input_context_ID,
request->user_data);
}
_xcb_xim_request_free(request);
} while (0);
xcb_im_create_ic_reply_fr_free(&frame);
}
void _xcb_xim_handle_destroy_ic_reply(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_destroy_ic_reply_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (!im->current) {
break;
}
if (im->current->major_code != XCB_XIM_DESTROY_IC &&
im->connect_id != frame.input_method_ID &&
im->current->frame.destroy_ic.input_context_ID !=
frame.input_context_ID) {
break;
}
xcb_xim_request_queue_t *request = im->current;
im->current = NULL;
if (request->callback.destroy_ic) {
request->callback.destroy_ic(im, frame.input_context_ID,
request->user_data);
}
_xcb_xim_request_free(request);
} while (0);
xcb_im_destroy_ic_reply_fr_free(&frame);
}
void _xcb_xim_handle_get_im_values_reply(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_get_im_values_reply_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (!im->current) {
break;
}
if (im->current->major_code != XCB_XIM_GET_IM_VALUES &&
im->connect_id != frame.input_method_ID) {
break;
}
xcb_xim_request_queue_t *request = im->current;
im->current = NULL;
if (request->callback.get_im_values) {
request->callback.get_im_values(im, &frame, request->user_data);
}
_xcb_xim_request_free(request);
} while (0);
xcb_im_get_im_values_reply_fr_free(&frame);
}
void _xcb_xim_handle_get_ic_values_reply(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_get_ic_values_reply_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (!im->current) {
break;
}
if (im->current->major_code != XCB_XIM_GET_IC_VALUES &&
im->connect_id != frame.input_method_ID &&
im->current->frame.get_ic_values.input_context_ID !=
frame.input_context_ID) {
break;
}
xcb_xim_request_queue_t *request = im->current;
im->current = NULL;
if (request->callback.get_ic_values) {
request->callback.get_ic_values(im, frame.input_context_ID, &frame,
request->user_data);
}
_xcb_xim_request_free(request);
} while (0);
xcb_im_get_ic_values_reply_fr_free(&frame);
}
void _xcb_xim_handle_set_ic_values_reply(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_set_ic_values_reply_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (!im->current) {
break;
}
if (im->current->major_code != XCB_XIM_SET_IC_VALUES &&
im->connect_id != frame.input_method_ID &&
im->current->frame.set_ic_values.input_context_ID !=
frame.input_context_ID) {
break;
}
xcb_xim_request_queue_t *request = im->current;
im->current = NULL;
if (request->callback.set_ic_values) {
request->callback.set_ic_values(im, frame.input_context_ID,
request->user_data);
}
_xcb_xim_request_free(request);
} while (0);
xcb_im_set_ic_values_reply_fr_free(&frame);
}
void _xcb_xim_handle_reset_ic_reply(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_reset_ic_reply_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (!im->current) {
break;
}
if (im->current->major_code != XCB_XIM_RESET_IC &&
im->connect_id != frame.input_method_ID &&
im->current->frame.reset_ic.input_context_ID !=
frame.input_context_ID) {
break;
}
xcb_xim_request_queue_t *request = im->current;
im->current = NULL;
if (request->callback.reset_ic) {
request->callback.reset_ic(im, frame.input_context_ID, &frame,
request->user_data);
}
_xcb_xim_request_free(request);
} while (0);
xcb_im_reset_ic_reply_fr_free(&frame);
}
void _xcb_xim_handle_forward_event(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_forward_event_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (XIM_MESSAGE_BYTES(hdr) < xcb_im_forward_event_fr_size(&frame) +
sizeof(xcb_key_press_event_t)) {
break;
}
if (im->connect_id != frame.input_method_ID) {
break;
}
xcb_key_press_event_t key_event;
data += xcb_im_forward_event_fr_size(&frame);
memcpy(&key_event, data, sizeof(xcb_key_press_event_t));
if (im->im_callback.forward_event) {
im->im_callback.forward_event(im, frame.input_context_ID,
&key_event, im->user_data);
}
if (frame.flag & XCB_XIM_SYNCHRONOUS) {
_xcb_xim_sync(im, frame.input_context_ID);
}
} while (0);
xcb_im_forward_event_fr_free(&frame);
}
void _xcb_xim_handle_commit(xcb_xim_t *im, const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
if (XIM_MESSAGE_BYTES(hdr) < 6) {
return;
}
uint8_t *pflag = data + 4;
uint16_t flag;
size_t len = XIM_MESSAGE_BYTES(hdr);
uint16_t_read(&flag, &pflag, &len, false);
if (flag & XCB_XIM_LOOKUP_KEYSYM) {
xcb_im_commit_both_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (im->connect_id != frame.input_method_ID) {
break;
}
if (im->im_callback.commit_string) {
im->im_callback.commit_string(
im, frame.input_context_ID, frame.flag,
(char *)frame.committed_string,
frame.byte_length_of_committed_string, &frame.keysym, 1,
im->user_data);
}
if (flag & XCB_XIM_SYNCHRONOUS) {
_xcb_xim_sync(im, frame.input_context_ID);
}
} while (0);
xcb_im_commit_both_fr_free(&frame);
} else if ((flag & XCB_XIM_LOOKUP_BOTH) == XCB_XIM_LOOKUP_CHARS) {
xcb_im_commit_chars_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (im->connect_id != frame.input_method_ID) {
break;
}
if (im->im_callback.commit_string) {
im->im_callback.commit_string(
im, frame.input_context_ID, frame.flag,
(char *)frame.committed_string,
frame.byte_length_of_committed_string, NULL, 0,
im->user_data);
}
if (flag & XCB_XIM_SYNCHRONOUS) {
_xcb_xim_sync(im, frame.input_context_ID);
}
} while (0);
xcb_im_commit_chars_fr_free(&frame);
}
}
void _xcb_xim_handle_close_reply(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
// why we need to wait server :?
}
void _xcb_xim_handle_geometry(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_geometry_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (im->connect_id != frame.input_method_ID) {
break;
}
if (im->im_callback.geometry) {
im->im_callback.geometry(im, frame.input_context_ID, im->user_data);
}
} while (0);
xcb_im_geometry_fr_free(&frame);
}
void _xcb_xim_handle_preedit_start(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_preedit_start_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (im->connect_id != frame.input_method_ID) {
break;
}
if (im->im_callback.preedit_start) {
im->im_callback.preedit_start(im, frame.input_context_ID,
im->user_data);
}
} while (0);
xcb_im_preedit_start_fr_free(&frame);
}
void _xcb_xim_handle_preedit_draw(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_preedit_draw_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (im->connect_id != frame.input_method_ID) {
break;
}
if (im->im_callback.preedit_draw) {
im->im_callback.preedit_draw(im, frame.input_context_ID, &frame,
im->user_data);
}
} while (0);
xcb_im_preedit_draw_fr_free(&frame);
}
void _xcb_xim_handle_preedit_caret(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_preedit_caret_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (im->connect_id != frame.input_method_ID) {
break;
}
if (im->im_callback.preedit_caret) {
im->im_callback.preedit_caret(im, frame.input_context_ID, &frame,
im->user_data);
}
} while (0);
xcb_im_preedit_caret_fr_free(&frame);
}
void _xcb_xim_handle_preedit_done(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_preedit_done_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (im->connect_id != frame.input_method_ID) {
break;
}
if (im->im_callback.preedit_done) {
im->im_callback.preedit_done(im, frame.input_context_ID,
im->user_data);
}
} while (0);
xcb_im_preedit_done_fr_free(&frame);
}
void _xcb_xim_handle_status_start(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_status_start_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (im->connect_id != frame.input_method_ID) {
break;
}
if (im->im_callback.status_start) {
im->im_callback.status_start(im, frame.input_context_ID,
im->user_data);
}
} while (0);
xcb_im_status_start_fr_free(&frame);
}
void _xcb_xim_handle_status_draw(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
if (XIM_MESSAGE_BYTES(hdr) < 8) {
return;
}
uint8_t *ptype = data + 4;
uint32_t type;
size_t len = XIM_MESSAGE_BYTES(hdr);
uint32_t_read(&type, &ptype, &len, false);
if (type == XCB_IM_TextType) {
xcb_im_status_draw_text_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (im->connect_id != frame.input_method_ID) {
break;
}
if (im->im_callback.status_draw_text) {
im->im_callback.status_draw_text(im, frame.input_context_ID,
&frame, im->user_data);
}
} while (0);
xcb_im_status_draw_text_fr_free(&frame);
} else if (type == XCB_IM_BitmapType) {
xcb_im_status_draw_bitmap_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (im->connect_id != frame.input_method_ID) {
break;
}
if (im->im_callback.status_draw_bitmap) {
im->im_callback.status_draw_bitmap(im, frame.input_context_ID,
&frame, im->user_data);
}
} while (0);
xcb_im_status_draw_bitmap_fr_free(&frame);
}
}
void _xcb_xim_handle_status_done(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_status_done_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (im->connect_id != frame.input_method_ID) {
break;
}
if (im->im_callback.status_done) {
im->im_callback.status_done(im, frame.input_context_ID,
im->user_data);
}
} while (0);
xcb_im_status_done_fr_free(&frame);
}
void _xcb_xim_handle_set_event_mask(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_set_event_mask_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (im->connect_id != frame.input_method_ID) {
break;
}
if (im->im_callback.set_event_mask) {
im->im_callback.set_event_mask(
im, frame.input_context_ID, frame.forward_event_mask,
frame.synchronous_event_mask, im->user_data);
}
} while (0);
xcb_im_set_event_mask_fr_free(&frame);
}
void _xcb_xim_handle_sync(xcb_xim_t *im, const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_sync_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (im->connect_id != frame.input_method_ID) {
break;
}
_xcb_xim_sync(im, frame.input_context_ID);
} while (0);
xcb_im_sync_fr_free(&frame);
}
void _xcb_xim_handle_error(xcb_xim_t *im, uint8_t *data) {
if (im->open_state == XIM_OPEN_DONE) {
if (im->current) {
_xcb_xim_process_fail_callback(im, im->current);
_xcb_xim_request_free(im->current);
im->current = NULL;
}
} else {
if (im->open_state != XIM_OPEN_INVALID) {
im->open_state = XIM_OPEN_INVALID;
im->yield_recheck = true;
}
}
}

View File

@ -0,0 +1,81 @@
/*
* SPDX-FileCopyrightText: 2014 Weng Xuetian <wengxt@gmail.com>
*
* SPDX-License-Identifier: LGPL-2.1-only
*
*/
#ifndef CLIENTPROTOCOLHANDLER_H
#define CLIENTPROTOCOLHANDLER_H
#include "imclient.h"
#include "ximproto.h"
#include <stdint.h>
void _xcb_xim_handle_open_reply(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_xim_handle_query_extension_reply(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_xim_handle_encoding_negotiation_reply(
xcb_xim_t *im, const xcb_im_packet_header_fr_t *hdr, uint8_t *data);
void _xcb_xim_handle_create_ic_reply(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_xim_handle_destroy_ic_reply(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_xim_handle_get_im_values_reply(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_xim_handle_register_triggerkeys(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_xim_handle_get_ic_values_reply(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_xim_handle_set_ic_values_reply(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_xim_handle_reset_ic_reply(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_xim_handle_forward_event(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_xim_handle_set_event_mask(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_xim_handle_sync(xcb_xim_t *im, const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_xim_handle_commit(xcb_xim_t *im, const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_xim_handle_geometry(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_xim_handle_preedit_start(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_xim_handle_preedit_draw(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_xim_handle_preedit_caret(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_xim_handle_preedit_done(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_xim_handle_status_start(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_xim_handle_status_draw(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_xim_handle_status_done(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_xim_handle_close_reply(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_xim_handle_error(xcb_xim_t *im, uint8_t *data);
#endif // CLIENTPROTOCOLHANDLER_H

129
xim/xcb-imdkit/src/common.c Normal file
View File

@ -0,0 +1,129 @@
/*
* SPDX-FileCopyrightText: 2014 Weng Xuetian <wengxt@gmail.com>
*
* SPDX-License-Identifier: LGPL-2.1-only
*
*/
#include "common.h"
#include "parser.h"
#include "ximproto.h"
#include <stdlib.h>
#include <string.h>
bool _xcb_im_init_atoms(xcb_connection_t *conn, size_t n,
const char **atom_names, xcb_atom_t *atoms) {
// here we alloc some array on stack, but since we only use this function
// internally and all atom_names size are small (less than 10), so it
// doesn't matter.
xcb_intern_atom_cookie_t atom_cookies[n];
for (size_t i = 0; i < n; i++) {
atom_cookies[i] =
xcb_intern_atom(conn, false, strlen(atom_names[i]), atom_names[i]);
}
size_t i;
for (i = 0; i < n; i++) {
xcb_intern_atom_reply_t *atom_reply =
xcb_intern_atom_reply(conn, atom_cookies[i], NULL);
if (atom_reply) {
atoms[i] = atom_reply->atom;
free(atom_reply);
} else {
break;
}
}
return (i == n);
}
uint32_t _xcb_get_event_mask(xcb_connection_t *conn, xcb_window_t window) {
if (window == XCB_NONE) {
return 0;
}
xcb_get_window_attributes_cookie_t cookie =
xcb_get_window_attributes(conn, window);
xcb_get_window_attributes_reply_t *reply =
xcb_get_window_attributes_reply(conn, cookie, NULL);
if (!reply) {
return 0;
}
uint32_t your_event_mask = reply->your_event_mask;
free(reply);
return your_event_mask;
}
bool _xcb_change_event_mask(xcb_connection_t *conn, xcb_window_t window,
uint32_t mask, bool remove) {
uint32_t your_event_mask = _xcb_get_event_mask(conn, window);
uint32_t masks[1];
if (remove) {
masks[0] = your_event_mask & (~mask);
} else {
masks[0] = your_event_mask | mask;
}
if (masks[0] == your_event_mask) {
return true;
}
xcb_void_cookie_t change_attr_cookie = xcb_change_window_attributes_checked(
conn, window, XCB_CW_EVENT_MASK, masks);
xcb_generic_error_t *error = NULL;
if ((error = xcb_request_check(conn, change_attr_cookie)) != NULL) {
free(error);
return false;
}
return true;
}
size_t _xcb_im_ic_attr_size(uint32_t type) {
switch (type) {
case XimType_CARD32:
case XimType_Window: {
return sizeof(uint32_t);
}
case XimType_XRectangle: {
xcb_im_xrectangle_fr_t fr;
return xcb_im_xrectangle_fr_size(&fr);
}
case XimType_XPoint: {
xcb_im_xpoint_fr_t fr;
return xcb_im_xpoint_fr_size(&fr);
}
}
return 0;
}
uint8_t *_xcb_im_get_ic_value(void *p, uint32_t type, uint8_t *data,
bool swap) {
switch (type) {
case XimType_CARD32:
case XimType_Window: {
uint32_t *result = p;
data = uint32_t_write(result, data, swap);
break;
}
case XimType_XRectangle: {
xcb_rectangle_t *result = p;
xcb_im_xrectangle_fr_t fr;
fr.x = result->x;
fr.y = result->y;
fr.width = result->width;
fr.height = result->height;
data = xcb_im_xrectangle_fr_write(&fr, data, swap);
break;
}
case XimType_XPoint: {
xcb_point_t *result = p;
xcb_im_xpoint_fr_t fr;
fr.x = result->x;
fr.y = result->y;
data = xcb_im_xpoint_fr_write(&fr, data, swap);
break;
}
case XimType_XFontSet: {
break;
}
}
return data;
}

View File

@ -0,0 +1,98 @@
/*
* SPDX-FileCopyrightText: 2014 Weng Xuetian <wengxt@gmail.com>
*
* SPDX-License-Identifier: LGPL-2.1-only
*
*/
#ifndef COMMON_H
#define COMMON_H
#include "ximproto.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <xcb/xcb.h>
#include <xcb/xproto.h>
// some atom name
#define XIM_SERVERS "XIM_SERVERS"
#define XIM_LOCALES "LOCALES"
#define XIM_TRANSPORT "TRANSPORT"
#define _XIM_PROTOCOL "_XIM_PROTOCOL"
#define _XIM_XCONNECT "_XIM_XCONNECT"
#define ARRAY_SIZE(X) (sizeof(X) / sizeof(X[0]))
#define XIM_MESSAGE_BYTES(hdr) ((hdr)->length * 4u)
/*
* categories in XIM_SERVERS
*/
#define XIM_SERVER_CATEGORY "@server="
#define XIM_LOCAL_CATEGORY "@locale="
#define XIM_TRANSPORT_CATEGORY "@transport="
#define DebugLog(S...) \
do { \
if (im->logger) { \
im->logger(S); \
} \
} while (0)
/*
* values for the type of XIMATTR & XICATTR
*/
#define XimType_SeparatorOfNestedList 0
#define XimType_CARD8 1
#define XimType_CARD16 2
#define XimType_CARD32 3
#define XimType_STRING8 4
#define XimType_Window 5
#define XimType_XIMStyles 10
#define XimType_XRectangle 11
#define XimType_XPoint 12
#define XimType_XFontSet 13
#define XimType_XIMOptions 14
#define XimType_XIMHotKeyTriggers 15
#define XimType_XIMHotKeyState 16
#define XimType_XIMStringConversion 17
#define XimType_XIMValuesList 18
#define XimType_NEST 0x7FFF
enum {
XIM_ATOM_SERVER_NAME,
XIM_ATOM_XIM_SERVERS,
XIM_ATOM_LOCALES,
XIM_ATOM_TRANSPORT,
XIM_ATOM_XIM_PROTOCOL,
XIM_ATOM_XIM_CONNECT,
XIM_ATOM_LAST
};
static const xcb_im_ext_list Default_Extension[] = {
// client -> server, by set ic in xlib
{"XIM_EXT_MOVE", XCB_XIM_EXTENSION, XCB_XIM_EXT_MOVE},
#if 0
// not in any imdkit
// server -> client
{"XIM_EXT_SET_EVENT_MASK", XIM_EXTENSION, XIM_EXT_SET_EVENT_MASK},
// server <-> client
// not enabled by xlib
{"XIM_EXT_FORWARD_KEYEVENT", XIM_EXTENSION, XIM_EXT_FORWARD_KEYEVENT},
#endif
};
typedef void (*xcb_xim_callback)();
bool _xcb_im_init_atoms(xcb_connection_t *conn, size_t n,
const char **atom_names, xcb_atom_t *atoms);
uint32_t _xcb_get_event_mask(xcb_connection_t *conn, xcb_window_t window);
bool _xcb_change_event_mask(xcb_connection_t *conn, xcb_window_t window,
uint32_t mask, bool remove);
size_t _xcb_im_ic_attr_size(uint32_t type);
uint8_t *_xcb_im_get_ic_value(void *p, uint32_t type, uint8_t *data, bool swap);
#endif // COMMON_H

View File

@ -0,0 +1,126 @@
/*
* SPDX-FileCopyrightText: 2014 Weng Xuetian <wengxt@gmail.com>
*
* SPDX-License-Identifier: LGPL-2.1-only
*
*/
#include "encoding.h"
#include "xlibi18n/XlcPubI.h"
#define _CONVERT_BUFSIZE 2048
typedef int (*convert_func)();
static size_t get_buf_size(size_t length) {
length *= 3; /* XXX */
length = (length / _CONVERT_BUFSIZE + 1) * _CONVERT_BUFSIZE; /* XXX */
return length;
}
XCBIMDKIT_EXPORT
void xcb_compound_text_init() { _XlcInitCTInfo(); }
int indirect_convert(void **from, size_t *from_left, void **to, size_t *to_left,
convert_func tocs, convert_func csto) {
char buf[_CONVERT_BUFSIZE];
void *cs;
size_t cs_left;
XlcCharSet charset;
int ret;
int unconv_num = 0;
StateRec state;
init_state(&state);
while (*from_left > 0) {
cs = buf;
cs_left = sizeof(buf);
ret = tocs(&state, from, from_left, &cs, &cs_left, &charset);
if (ret < 0) {
break;
}
unconv_num += ret;
size_t length = ((char *)cs) - buf;
if (length > 0) {
cs_left = length;
cs = buf;
ret = csto(&state, &cs, &cs_left, to, to_left, charset);
if (ret < 0) {
unconv_num +=
length / (charset->char_size > 0 ? charset->char_size : 1);
continue;
}
unconv_num += ret;
if (*to_left < 1) {
break;
}
}
}
return unconv_num;
}
XCBIMDKIT_EXPORT
char *xcb_utf8_to_compound_text(const char *utf8, size_t len,
size_t *lenghtOut) {
size_t buf_len = get_buf_size(len) + 1;
void *result;
if ((result = malloc(buf_len)) == NULL) {
return NULL;
}
void *from = (void *)utf8;
void *to = result;
size_t from_left = len;
size_t to_left = buf_len;
int ret =
indirect_convert(&from, &from_left, &to, &to_left, utf8tocs, cstoct);
if (ret || from_left != 0) {
free(result);
return NULL;
}
if (lenghtOut) {
*lenghtOut = to - result;
}
*((char *)to) = '\0';
return result;
}
XCBIMDKIT_EXPORT
char *xcb_compound_text_to_utf8(const char *compound_text, size_t len,
size_t *lenghtOut) {
size_t buf_len = get_buf_size(len) + 1;
void *result;
if ((result = malloc(buf_len)) == NULL) {
return NULL;
}
void *from = (void *)compound_text;
void *to = result;
size_t from_left = len;
size_t to_left = buf_len;
int ret =
indirect_convert(&from, &from_left, &to, &to_left, cttocs, cstoutf8);
if (ret || from_left != 0) {
free(result);
return NULL;
}
if (lenghtOut) {
*lenghtOut = to - result;
}
*((char *)to) = '\0';
return result;
}

View File

@ -0,0 +1,24 @@
/*
* SPDX-FileCopyrightText: 2014 Weng Xuetian <wengxt@gmail.com>
*
* SPDX-License-Identifier: LGPL-2.1-only
*
*/
#ifndef _XCB_IMDKIT_ENCODING_H_
#define _XCB_IMDKIT_ENCODING_H_
#include "ximcommon.h"
#include <stdlib.h>
XCBIMDKIT_DECL_BEGIN
XCBIMDKIT_EXPORT void xcb_compound_text_init();
XCBIMDKIT_EXPORT char *
xcb_utf8_to_compound_text(const char *utf8, size_t length, size_t *lenghtOut);
XCBIMDKIT_EXPORT char *xcb_compound_text_to_utf8(const char *compound_text,
size_t length,
size_t *lenghtOut);
XCBIMDKIT_DECL_END
#endif // _XCB_IMDKIT_ENCODING_H_

View File

@ -0,0 +1,371 @@
#!/usr/bin/env python3
#
# SPDX-FileCopyrightText: 2014 Weng Xuetian <wengxt@gmail.com>
#
# SPDX-License-Identifier: LGPL-2.1-only
#
"""
This is a ugly code generate script, which is intended to be used
against i18nIMProto.c in IMdkit
it will generate all serialization code against xim protocol frame
"""
import fileinput
import collections
import sys
funcs = collections.OrderedDict()
static_size = dict()
funcname = None
for line in fileinput.input(sys.argv[1]):
if "XimFrameRec" in line:
tokens = line.strip().split()
token = None
for token in tokens:
if "[]" in token:
break
if token is not None:
funcname = "xcb_im_" + token[:-2]
funcs[funcname] = []
fieldidx = 0
elif "FRAME(EOL)" in line:
funcname = None
elif funcname is not None:
line = line.strip()
try:
tp = line[:line.rindex("),")+1]
if tp == "_FRAME(POINTER)":
continue
if line.find("/*") != -1:
name = line[line.find("/*")+2:line.find("*/")]
name = name.strip().replace(" ", "_").replace(".", "_").replace("-", "_")
else:
name = "field{0}".format(fieldidx)
fieldidx += 1
funcs[funcname].append((tp,name))
except Exception as e:
pass
def gettypename(attr):
if "BIT8" in attr:
return ("uint8_t")
elif "BIT16" in attr:
return ("uint16_t")
elif "BIT32" in attr:
return ("uint32_t")
elif attr == "_FRAME(BARRAY)":
return ("xcb_im_bytearray_t")
elif "_PTR" in attr:
return "xcb_im_" + attr[attr.find("(") + 1:attr.find(")")]
else:
print(attr)
assert(False)
for funcname, attrs in funcs.items():
size = 0
for attr, name in attrs:
if "BIT8" in attr:
size += 1
elif "BIT16" in attr:
size += 2
elif "BIT32" in attr:
size += 4
elif "PAD" in attr:
pad = int(attr[4])
size += 0 if size % pad == 0 else (pad - size % pad)
elif "PTR" in attr:
if static_size[gettypename(attr)] < 0:
size = -1
break
else:
size += static_size[gettypename(attr)]
else:
size = -1
break
static_size[funcname] = size
def getsize(attr, name):
if "BIT8" in attr:
return "1"
elif "BIT16" in attr:
return "2"
elif "BIT32" in attr:
return "4"
elif "_PTR" in attr:
return "{1}_size(&frame->{0})".format(name, gettypename(attr))
def search_barray_length(attrs, i):
for attr, name in reversed(attrs[0:i]):
if "length" in name:
return (attr, name)
return attrs[i - 1]
if len(sys.argv) > 2:
for funcname, attrs in funcs.items():
print("typedef struct _{0}_t".format(funcname))
print("{")
skip = False
for i, (attr, name) in enumerate(attrs):
if skip:
skip = False
continue
if "_FRAME(B" in attr:
print(" {1} {0};".format(name, gettypename(attr)))
if "_PTR" in attr:
print(" {1}_t {0};".format(name, gettypename(attr)))
elif "_PAD" in attr:
pass
elif "_BYTE_COUNTER" in attr:
pass
elif attr == "_FRAME(ITER)":
(iterattr, itername) = attrs[i + 1]
print(" struct {")
print(" uint32_t size;")
if "_FRAME(B" in iterattr:
print(" {0}* items;".format(gettypename(iterattr)))
if "_PTR" in iterattr:
print(" {0}_t* items;".format(gettypename(iterattr)))
print(" }} {0};".format(name))
skip = True
print("}} {0}_t;".format(funcname))
print("")
def print_generic(cat):
print("#define frame_{0}_func(FRAME) _Generic((FRAME), \\".format(cat))
first = True
for funcname, attrs in funcs.items():
if first:
first=False
else:
print(",\\")
if cat == "size":
if static_size[funcname] >= 0:
print(" {0}_t : {1}".format(funcname, static_size[funcname]), end='')
else:
print(" {0}_t : {0}_{1}(({0}_t*) &(FRAME))".format(funcname, cat), end='')
else:
print(" {0}_t : {0}_{1}".format(funcname, cat), end='')
print(")")
print("")
for cat in ["read", "write", "size", "free"]:
print_generic(cat)
def print_generic_size():
print("#define frame_has_static_size(FRAME) _Generic((FRAME), \\".format(cat))
first = True
for funcname, attrs in funcs.items():
if first:
first=False
else:
print(",\\")
print(" {0}_t : {1}".format(funcname, "true" if static_size[funcname] >= 0 else "false"), end='')
print(")")
print("")
print_generic_size()
for funcname, attrs in funcs.items():
usecounter = any("_BYTE_COUNTER" in attr for attr, name in attrs)
usecounter8 = any("_BYTE_COUNTER(BIT8" in attr for attr, name in attrs)
usecounter16 = any("_BYTE_COUNTER(BIT16" in attr for attr, name in attrs)
usecounter32 = any("_BYTE_COUNTER(BIT32" in attr for attr, name in attrs)
print(("""void {0}_read({0}_t *frame, uint8_t **data, size_t *len, bool swap);\n"""
"""uint8_t* {0}_write({0}_t *frame, uint8_t *data, bool swap);\n"""
"""void {0}_free({0}_t *frame);""").format(funcname))
if static_size[funcname] >= 0:
print("""#define {0}_size(ARG...) (((void)(ARG)), ({1}))""".format(funcname, static_size[funcname]))
else:
print("""size_t {0}_size({0}_t *frame);""".format(funcname))
print("")
else:
print("#include <string.h>")
print("#include \"parser.h\"")
print("#include \"ximproto.h\"")
print("")
for funcname, attrs in funcs.items():
usecounter = any("_BYTE_COUNTER" in attr for attr, name in attrs)
usecounter8 = any("_BYTE_COUNTER(BIT8" in attr for attr, name in attrs)
usecounter16 = any("_BYTE_COUNTER(BIT16" in attr for attr, name in attrs)
usecounter32 = any("_BYTE_COUNTER(BIT32" in attr for attr, name in attrs)
usepad = any("_PAD" in attr for attr, name in attrs)
print("void {0}_read({0}_t *frame, uint8_t **data, size_t *len, bool swap)".format(funcname))
print("{")
if len(attrs) > 0:
print(" memset(frame, 0, sizeof(*frame));")
if usepad:
print(" uint8_t* start = *data;")
if usecounter:
if usecounter8:
print(" uint8_t counter8 = 0;")
if usecounter16:
print(" uint16_t counter16 = 0;")
if usecounter32:
print(" uint32_t counter32 = 0;")
print(" size_t counter = 0;")
skip = False
for i, (attr, name) in enumerate(attrs):
if skip:
skip = False
continue
if "_FRAME(BIT" in attr or "_PTR" in attr:
print(" {1}_read(&frame->{0}, data, len, swap);".format(name, gettypename(attr)))
print(" if (!*data) { return; }")
elif "_FRAME(BARRAY" in attr:
(lenattr, lenname) = search_barray_length(attrs, i)
print(" {1}_read(&frame->{0}, frame->{2}, data, len, swap);".format(name, gettypename(attr), lenname))
print(" if (!*data) { return; }")
elif "_PAD" in attr:
print(" *data = (uint8_t*) align_to_{0}((uintptr_t) *data, *data - start, len);".format(attr[4]))
print(" if (!*data) { return; }")
elif "_BYTE_COUNTER" in attr:
if "BIT8" in attr:
countername = "counter8"
elif "BIT16" in attr:
countername = "counter16"
elif "BIT32" in attr:
countername = "counter32"
print(" {1}_read(&{0}, data, len, swap);".format(countername, gettypename(attr)))
print(" if (!*data) { return; }")
if countername != "counter":
print(" counter = {0};".format(countername))
elif attr == "_FRAME(ITER)":
(iterattr, itername) = attrs[i + 1]
print(" if (counter > *len) { *data = NULL; return; } else { *len -= counter; } ")
print(" frame->{0}.items = NULL;".format(name, gettypename(iterattr)))
print(" frame->{0}.size = 0;".format(name))
print(" while (counter != 0) {")
if "_PTR" in iterattr:
print(" void* temp = realloc(frame->{0}.items, (frame->{0}.size + 1) * sizeof({1}_t));".format(name, gettypename(iterattr)))
else:
print(" void* temp = realloc(frame->{0}.items, (frame->{0}.size + 1) * sizeof({1}));".format(name, gettypename(iterattr)))
print(" if (!temp) {")
print(" *data = NULL;")
print(" return;")
print(" }")
print(" frame->{0}.items = temp;".format(name))
print(" {1}_read(&frame->{0}.items[frame->{0}.size], data, &counter, swap);".format(name, gettypename(iterattr)))
print(" if (!*data) { return; }")
print(" frame->{0}.size++;".format(name))
print(" }")
skip = True
print("}")
print("")
print("uint8_t* {0}_write({0}_t *frame, uint8_t *data, bool swap)".format(funcname))
print("{")
if usepad:
print(" uint8_t* start = data;")
if usecounter:
if usecounter8:
print(" uint8_t counter8 = 0;")
if usecounter16:
print(" uint16_t counter16 = 0;")
if usecounter32:
print(" uint32_t counter = 0;")
skip = False
for i, (attr, name) in enumerate(attrs):
if skip:
skip = False
continue
if "_FRAME(BIT" in attr or "_PTR" in attr:
print(" data = {1}_write(&frame->{0}, data, swap);".format(name, gettypename(attr)))
elif "_FRAME(BARRAY" in attr:
(lenattr, lenname) = search_barray_length(attrs, i)
print(" data = {1}_write(&frame->{0}, frame->{2}, data, swap);".format(name, gettypename(attr), lenname))
elif "_PAD" in attr:
print(" data = (uint8_t*) align_to_{0}((uintptr_t) data, data - start, NULL);".format(attr[4]))
elif "_BYTE_COUNTER" in attr:
for j, (targetattr, targetname) in enumerate(attrs):
if j < i + 1:
continue
if targetattr == "_FRAME(ITER)":
(iterattr, itername) = attrs[j + 1]
break
if "BIT8" in attr:
countername = "counter8"
elif "BIT16" in attr:
countername = "counter16"
elif "BIT32" in attr:
countername = "counter"
if "_PTR" in iterattr:
print(" {0} = 0;".format(countername));
print(" for (uint32_t i = 0; i < frame->{0}.size; i++) {{".format(targetname))
print(" {2} += {1}_size(&frame->{0}.items[i]);".format(targetname, gettypename(iterattr), countername))
print(" }")
else:
print(" {0} = frame->{1}.size * {2};".format(countername, targetname, getsize(iterattr, itername)))
print(" data = {1}_write(&{0}, data, swap);".format(countername, gettypename(attr)))
elif attr == "_FRAME(ITER)":
(iterattr, itername) = attrs[i + 1]
print(" for (uint32_t i = 0; i < frame->{0}.size; i++) {{".format(name))
print(" data = {1}_write(&frame->{0}.items[i], data, swap);".format(name, gettypename(iterattr)))
print(" }")
skip = True
print(" return data;");
print("}")
print("")
if static_size[funcname] < 0:
print("size_t {0}_size({0}_t *frame)".format(funcname))
print("{")
print(" size_t size = 0;")
skip = False
for i, (attr, name) in enumerate(attrs):
if skip:
skip = False
continue
if "_FRAME(BIT" in attr or "_BYTE_COUNTER" in attr:
print(" size += {0};".format(getsize(attr, name)))
elif "_PTR" in attr:
print(" size += {1}_size(&frame->{0});".format(name, gettypename(attr)))
elif "_FRAME(BARRAY" in attr:
(lenattr, lenname) = search_barray_length(attrs, i)
print(" size += frame->{0};".format(lenname))
elif "_PAD" in attr:
print(" size = align_to_{0}(size, size, NULL);".format(attr[4]))
elif attr == "_FRAME(ITER)":
(iterattr, itername) = attrs[i + 1]
if "_PTR" in iterattr:
print(" for (uint32_t i = 0; i < frame->{0}.size; i++) {{".format(name))
print(" size += {1}_size(&frame->{0}.items[i]);".format(name, gettypename(iterattr)))
print(" }")
else:
print(" size += frame->{0}.size * {1};".format(name, getsize(iterattr, itername)))
skip = True
print(" return size;")
print("}")
print("")
print("void {0}_free({0}_t *frame)".format(funcname))
print("{")
for i, (attr, name) in enumerate(attrs):
if skip:
skip = False
continue
if "_PTR" in attr:
print(" {1}_free(&frame->{0});".format(name, gettypename(attr)))
elif "_FRAME(BARRAY" in attr:
pass
elif attr == "_FRAME(ITER)":
(iterattr, itername) = attrs[i + 1]
if "_PTR" in iterattr:
print(" if (frame->{0}.items) {{".format(name))
print(" for (uint32_t i = 0; i < frame->{0}.size; i++) {{".format(name))
print(" {1}_free(&frame->{0}.items[i]);".format(name, gettypename(iterattr)))
print(" }")
print(" }")
print(" free(frame->{0}.items);".format(name))
skip = True
print("}")
print("")

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,183 @@
/*
* SPDX-FileCopyrightText: 2014 Weng Xuetian <wengxt@gmail.com>
*
* SPDX-License-Identifier: LGPL-2.1-only
*
*/
#ifndef _XCB_IMDKIT_IMCLIENT_H_
#define _XCB_IMDKIT_IMCLIENT_H_
#include "ximcommon.h"
#include "ximproto.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <xcb/xcb.h>
#include <xcb/xproto.h>
XCBIMDKIT_DECL_BEGIN
typedef struct _xcb_xim_t xcb_xim_t;
typedef uint16_t xcb_xic_t;
typedef struct _xcb_xim_nested_list {
uint8_t *data;
size_t length;
} xcb_xim_nested_list;
typedef void (*xcb_xim_set_event_mask_callback)(xcb_xim_t *im, xcb_xic_t ic,
uint32_t forward_event_mask,
uint32_t synchronous_event_mask,
void *user_data);
typedef void (*xcb_xim_forward_event_callback)(xcb_xim_t *im, xcb_xic_t ic,
xcb_key_press_event_t *event,
void *user_data);
typedef void (*xcb_xim_commit_string_callback)(xcb_xim_t *im, xcb_xic_t ic,
uint32_t flag, char *str,
uint32_t length,
uint32_t *keysym, size_t nKeySym,
void *user_data);
typedef void (*xcb_xim_geometry_callback)(xcb_xim_t *im, xcb_xic_t ic,
void *user_data);
typedef void (*xcb_xim_preedit_start_callback)(xcb_xim_t *im, xcb_xic_t ic,
void *user_data);
typedef void (*xcb_xim_preedit_draw_callback)(xcb_xim_t *im, xcb_xic_t ic,
xcb_im_preedit_draw_fr_t *frame,
void *user_data);
typedef void (*xcb_xim_preedit_caret_callback)(xcb_xim_t *im, xcb_xic_t ic,
xcb_im_preedit_caret_fr_t *frame,
void *user_data);
typedef void (*xcb_xim_preedit_done_callback)(xcb_xim_t *im, xcb_xic_t ic,
void *user_data);
typedef void (*xcb_xim_status_start_callback)(xcb_xim_t *im, xcb_xic_t ic,
void *user_data);
typedef void (*xcb_xim_status_draw_text_callback)(
xcb_xim_t *im, xcb_xic_t ic, xcb_im_status_draw_text_fr_t *frame,
void *user_data);
typedef void (*xcb_xim_status_draw_bitmap_callback)(
xcb_xim_t *im, xcb_xic_t ic, xcb_im_status_draw_bitmap_fr_t *frame,
void *user_data);
typedef void (*xcb_xim_status_done_callback)(xcb_xim_t *im, xcb_xic_t ic,
void *user_data);
typedef void (*xcb_xim_sync_callback)(xcb_xim_t *im, xcb_xic_t ic,
void *user_data);
typedef void (*xcb_xim_disconnected_callback)(xcb_xim_t *im, void *user_data);
typedef struct _xcb_xim_im_callback {
xcb_xim_set_event_mask_callback set_event_mask;
xcb_xim_forward_event_callback forward_event;
xcb_xim_commit_string_callback commit_string;
xcb_xim_geometry_callback geometry;
xcb_xim_preedit_start_callback preedit_start;
xcb_xim_preedit_draw_callback preedit_draw;
xcb_xim_preedit_caret_callback preedit_caret;
xcb_xim_preedit_done_callback preedit_done;
xcb_xim_status_start_callback status_start;
xcb_xim_status_draw_text_callback status_draw_text;
xcb_xim_status_draw_bitmap_callback status_draw_bitmap;
xcb_xim_status_done_callback status_done;
xcb_xim_sync_callback sync;
xcb_xim_disconnected_callback disconnected;
} xcb_xim_im_callback;
typedef enum _xcb_xim_trigger_key_type_t {
XCB_XIM_IS_NOT_TRIGGER,
XCB_XIM_TRIGGER_ON_KEY,
XCB_XIM_TRIGGER_OFF_KEY,
} xcb_xim_trigger_key_type_t;
typedef enum _xcb_xim_encoding_t {
XCB_XIM_COMPOUND_TEXT,
XCB_XIM_UTF8_STRING,
} xcb_xim_encoding_t;
typedef void (*xcb_xim_open_callback)(xcb_xim_t *im, void *user_data);
typedef void (*xcb_xim_create_ic_callback)(xcb_xim_t *im, xcb_xic_t ic,
void *user_data);
typedef void (*xcb_xim_get_im_values_callback)(
xcb_xim_t *im, xcb_im_get_im_values_reply_fr_t *reply, void *user_data);
typedef void (*xcb_xim_get_ic_values_callback)(
xcb_xim_t *im, xcb_xic_t ic, xcb_im_get_ic_values_reply_fr_t *reply,
void *user_data);
typedef void (*xcb_xim_set_ic_values_callback)(xcb_xim_t *im, xcb_xic_t ic,
void *user_data);
typedef void (*xcb_xim_destroy_ic_callback)(xcb_xim_t *im, xcb_xic_t ic,
void *user_data);
typedef void (*xcb_xim_reset_ic_callback)(xcb_xim_t *im, xcb_xic_t ic,
xcb_im_reset_ic_reply_fr_t *reply,
void *user_data);
XCBIMDKIT_EXPORT xcb_xim_t *xcb_xim_create(xcb_connection_t *conn,
int screen_id, const char *imname);
XCBIMDKIT_EXPORT void
xcb_xim_set_log_handler(xcb_xim_t *im, void (*logger)(const char *, ...));
XCBIMDKIT_EXPORT void xcb_xim_set_use_compound_text(xcb_xim_t *im, bool enable);
XCBIMDKIT_EXPORT void xcb_xim_set_use_utf8_string(xcb_xim_t *im, bool enable);
XCBIMDKIT_EXPORT
xcb_xim_encoding_t xcb_xim_get_encoding(xcb_xim_t *im);
XCBIMDKIT_EXPORT void xcb_xim_destroy(xcb_xim_t *im);
XCBIMDKIT_EXPORT bool xcb_xim_open(xcb_xim_t *im,
xcb_xim_open_callback callback,
bool auto_connect, void *user_data);
XCBIMDKIT_EXPORT void
xcb_xim_set_im_callback(xcb_xim_t *im, const xcb_xim_im_callback *callbacks,
void *user_data);
XCBIMDKIT_EXPORT void
xcb_xim_set_im_callback(xcb_xim_t *im, const xcb_xim_im_callback *callbacks,
void *user_data);
XCBIMDKIT_EXPORT bool xcb_xim_filter_event(xcb_xim_t *im,
xcb_generic_event_t *event);
XCBIMDKIT_DEPRECATED_EXPORT xcb_xim_trigger_key_type_t
xcb_xim_check_trigger_key(xcb_xim_t *im, xcb_keysym_t keysym, uint32_t modifier,
uint32_t *idx);
XCBIMDKIT_EXPORT bool xcb_xim_check_trigger_on_key(xcb_xim_t *im,
xcb_keysym_t keysym,
uint32_t modifier,
uint32_t *idx);
XCBIMDKIT_EXPORT bool xcb_xim_check_trigger_off_key(xcb_xim_t *im,
xcb_keysym_t keysym,
uint32_t modifier,
uint32_t *idx);
XCBIMDKIT_EXPORT bool xcb_xim_trigger_notify(xcb_xim_t *im, xcb_xic_t ic,
uint32_t idx, bool off);
XCBIMDKIT_EXPORT bool
xcb_xim_get_im_values(xcb_xim_t *im, xcb_xim_get_im_values_callback callback,
void *user_data, ...);
XCBIMDKIT_EXPORT xcb_xim_nested_list xcb_xim_create_nested_list(xcb_xim_t *im,
...);
XCBIMDKIT_EXPORT bool xcb_xim_create_ic(xcb_xim_t *im,
xcb_xim_create_ic_callback callback,
void *user_data, ...);
XCBIMDKIT_EXPORT bool
xcb_xim_get_ic_values(xcb_xim_t *im, xcb_xic_t ic,
xcb_xim_get_ic_values_callback callback, void *user_data,
...);
XCBIMDKIT_EXPORT bool
xcb_xim_set_ic_values(xcb_xim_t *im, xcb_xic_t ic,
xcb_xim_set_ic_values_callback callback, void *user_data,
...);
XCBIMDKIT_EXPORT bool xcb_xim_set_ic_focus(xcb_xim_t *im, xcb_xic_t ic);
XCBIMDKIT_EXPORT bool xcb_xim_unset_ic_focus(xcb_xim_t *im, xcb_xic_t ic);
XCBIMDKIT_EXPORT bool xcb_xim_forward_event(xcb_xim_t *im, xcb_xic_t ic,
xcb_key_press_event_t *event);
XCBIMDKIT_EXPORT bool xcb_xim_forward_event_full(xcb_xim_t *im, xcb_xic_t ic,
uint16_t sequence,
xcb_key_press_event_t *event);
XCBIMDKIT_EXPORT bool xcb_xim_reset_ic(xcb_xim_t *im, xcb_xic_t ic,
xcb_xim_reset_ic_callback callback,
void *user_data);
XCBIMDKIT_EXPORT bool xcb_xim_destroy_ic(xcb_xim_t *im, xcb_xic_t ic,
xcb_xim_destroy_ic_callback callback,
void *user_data);
XCBIMDKIT_EXPORT void xcb_xim_close(xcb_xim_t *im);
XCBIMDKIT_EXPORT bool xcb_xim_support_extension(xcb_xim_t *im,
uint16_t major_code,
uint16_t minor_code);
XCBIMDKIT_EXPORT bool xcb_xim_ext_move(xcb_xim_t *im, xcb_xic_t ic, int16_t x,
int16_t y);
XCBIMDKIT_DECL_END
#endif // _XCB_IMDKIT_IMCLIENT_H_

View File

@ -0,0 +1,229 @@
/*
* SPDX-FileCopyrightText: 2014 Weng Xuetian <wengxt@gmail.com>
*
* SPDX-License-Identifier: LGPL-2.1-only
*
*/
#ifndef _XCB_IMDKIT_IMCLIENT_P_H_
#define _XCB_IMDKIT_IMCLIENT_P_H_
#include "common.h"
#include "imclient.h"
#include "list.h"
#include "message.h"
#include "uthash.h"
#include "ximproto.h"
#include "ximproto_p.h"
// this phase is basically a directly mapping from _XimSOMETHING function in
// Xlib state machine is more suitable for xcb asynchronous nature.
typedef enum _xcb_xim_connect_phase_t {
XIM_CONNECT_DONE,
XIM_CONNECT_FAIL,
XIM_CONNECT_CHECK_SERVER,
XIM_CONNECT_CONNECT,
} xcb_xim_connect_phase_t;
typedef enum _xcb_xim_connect_check_server_phase_t {
XIM_CONNECT_CHECK_SERVER_PREPARE,
XIM_CONNECT_CHECK_SERVER_LOCALE,
XIM_CONNECT_CHECK_SERVER_LOCALE_WAIT,
XIM_CONNECT_CHECK_SERVER_TRANSPORT,
XIM_CONNECT_CHECK_SERVER_TRANSPORT_WAIT,
} xcb_xim_connect_check_server_phase_t;
typedef enum _xcb_xim_connect_connect_phase_t {
XIM_CONNECT_CONNECT_PREPARE,
XIM_CONNECT_CONNECT_WAIT,
XIM_CONNECT_CONNECT_WAIT_REPLY,
} xcb_xim_connect_connect_phase_t;
typedef enum _xcb_xim_open_phase_t {
XIM_OPEN_INVALID,
XIM_OPEN_WAIT_OPEN_REPLY,
XIM_OPEN_WAIT_EXTENSION_REPLY,
XIM_OPEN_WAIT_ENCODING_REPLY,
XIM_OPEN_DONE
} xcb_xim_open_phase_t;
typedef struct _xcb_xim_connect_state_t {
xcb_xim_connect_phase_t phase;
xcb_xim_open_callback callback;
void *user_data;
union {
struct {
int index;
xcb_xim_connect_check_server_phase_t subphase;
xcb_window_t window;
xcb_window_t requestor_window;
} check_server;
struct {
xcb_xim_connect_connect_phase_t subphase;
} connect;
};
} xcb_xim_connect_state_t;
typedef struct _xcb_xim_imattr_table_t {
xcb_im_ximattr_fr_t attr;
UT_hash_handle hh;
} xcb_xim_imattr_table_t;
typedef struct _xcb_xim_icattr_table_t {
xcb_im_xicattr_fr_t attr;
UT_hash_handle hh;
} xcb_xim_icattr_table_t;
typedef struct _xcb_xim_extensionx_t {
uint16_t major_code;
uint16_t minor_code;
} xcb_xim_extension_t;
typedef struct _xcb_xim_request_queue_t {
uint8_t major_code;
uint8_t minor_code;
void *user_data;
union {
xcb_im_create_ic_fr_t create_ic;
xcb_im_destroy_ic_fr_t destroy_ic;
xcb_im_get_im_values_fr_t get_im_values;
xcb_im_get_ic_values_fr_t get_ic_values;
xcb_im_set_ic_values_fr_t set_ic_values;
uint8_t forward_event[8 + sizeof(xcb_key_press_event_t)];
xcb_im_reset_ic_fr_t reset_ic;
} frame;
union {
void (*generic)();
xcb_xim_create_ic_callback create_ic;
xcb_xim_destroy_ic_callback destroy_ic;
xcb_xim_get_im_values_callback get_im_values;
xcb_xim_get_ic_values_callback get_ic_values;
xcb_xim_set_ic_values_callback set_ic_values;
xcb_xim_reset_ic_callback reset_ic;
} callback;
list_head list;
} xcb_xim_request_queue_t;
struct _xcb_xim_t {
// basic data which should always be valid
xcb_connection_t *conn;
char *server_name;
int screen_id;
xcb_xim_im_callback im_callback;
void *user_data;
// some global data
uint32_t sequence;
uint8_t byte_order;
// set by _xcb_xim_init
xcb_screen_t *screen;
xcb_screen_t *default_screen;
xcb_atom_t atoms[XIM_ATOM_LAST]; // add one for SERVER_NAME
bool init;
// set by _xcb_xim_get_servers
xcb_atom_t *server_atoms;
int n_server_atoms;
// used by _xcb_xim_check_server / _xcb_xim_connect
xcb_xim_connect_state_t connect_state;
// _xcb_xim_check_server
char *trans_addr;
xcb_window_t im_window;
// and also server_atom
xcb_window_t im_client_window;
xcb_im_property_offset_t *offsets;
// _xcb_xim_connect_wait
int major_code;
int minor_code;
uint32_t accept_win;
// xim open
xcb_xim_open_phase_t open_state;
uint16_t connect_id;
xcb_xim_imattr_table_t *imattr;
xcb_xim_icattr_table_t *icattr;
xcb_xim_extension_t *extensions;
xcb_im_trigger_keys_t onKeys;
xcb_im_trigger_keys_t offKeys;
// request
xcb_xim_request_queue_t *current;
list_head queue;
size_t nExtensions;
bool auto_connect;
// Indicate whether we need a recheck on the new server.
bool recheck;
bool yield_recheck;
// some ic values
xcb_window_t client_window;
xcb_window_t focus_window;
void (*logger)(const char *, ...);
bool use_compound_text;
bool use_utf8_string;
xcb_xim_encoding_t encoding;
uint32_t event_sequence;
};
#define _xcb_xim_read_frame(FRAME, DATA, LEN, FAIL) \
do { \
FAIL = false; \
uint8_t *_data = DATA; \
size_t len = (size_t)(LEN); \
frame_read_func(FRAME)(&FRAME, &_data, &len, false); \
if (!_data) { \
frame_free_func(FRAME)(&FRAME); \
FAIL = true; \
} \
} while (0)
#define _xcb_xim_send_frame(IM, FRAME, FAIL) \
do { \
FAIL = true; \
size_t length = frame_size_func(FRAME); \
uint8_t *reply = NULL; \
uint8_t *alloc_reply = NULL; \
uint8_t \
static_reply[XCB_IM_HEADER_SIZE + (frame_has_static_size(FRAME) \
? frame_size_func(FRAME) \
: 1)]; \
if (frame_has_static_size(FRAME)) { \
reply = static_reply; \
_xcb_write_xim_message_header( \
reply, XIM_PROTO_FRAME_OPCODE(FRAME), 0, length, false); \
} else { \
reply = _xcb_new_xim_message(XIM_PROTO_FRAME_OPCODE(FRAME), 0, \
length, false); \
alloc_reply = reply; \
} \
do { \
if (!reply) { \
break; \
} \
frame_write_func(FRAME)(&(FRAME), reply + XCB_IM_HEADER_SIZE, \
false); \
if (!_xcb_xim_send_message((IM), reply, length)) { \
break; \
} \
FAIL = false; \
} while (0); \
free(alloc_reply); \
} while (0)
bool _xcb_xim_send_message(xcb_xim_t *im, uint8_t *data, size_t length);
void _xcb_xim_request_free(xcb_xim_request_queue_t *request);
bool _xcb_xim_sync(xcb_xim_t *im, xcb_xic_t ic);
void _xcb_xim_process_fail_callback(xcb_xim_t *im,
xcb_xim_request_queue_t *request);
#endif // _XCB_IMDKIT_IMCLIENT_P_H_

1235
xim/xcb-imdkit/src/imdkit.c Normal file

File diff suppressed because it is too large Load Diff

360
xim/xcb-imdkit/src/imdkit.h Normal file
View File

@ -0,0 +1,360 @@
/*
* SPDX-FileCopyrightText: 2014 Weng Xuetian <wengxt@gmail.com>
*
* SPDX-License-Identifier: LGPL-2.1-only
*
*/
#ifndef _XCB_IMDKIT_IMDKIT_H_
#define _XCB_IMDKIT_IMDKIT_H_
#include "xcbimdkit_export.h"
#include "ximcommon.h"
#include "ximproto.h"
#include <stdbool.h>
#include <stdint.h>
#include <xcb/xcb.h>
#include <xcb/xproto.h>
XCBIMDKIT_DECL_BEGIN
/*
* `C' and `no' are additional one which cannot be obtained from modern
* locale.gen. `no' is obsolete, but we keep it here for compatible reason.
*/
#define XCB_IM_ALL_LOCALES \
"aa,af,am,an,ar,as,ast,az,be,bem,ber,bg,bho,bn,bo,br,brx,bs,byn," \
"C,ca,crh,cs,csb,cv,cy,da,de,dv,dz,el,en,es,et,eu,fa,ff,fi,fil,fo," \
"fr,fur,fy,ga,gd,gez,gl,gu,gv,ha,he,hi,hne,hr,hsb,ht,hu,hy,id,ig," \
"ik,is,it,iu,iw,ja,ka,kk,kl,km,kn,ko,kok,ks,ku,kw,ky,lb,lg,li,lij," \
"lo,lt,lv,mag,mai,mg,mhr,mi,mk,ml,mn,mr,ms,mt,my,nan,nb,nds,ne,nl," \
"nn,no,nr,nso,oc,om,or,os,pa,pap,pl,ps,pt,ro,ru,rw,sa,sc,sd,se,shs," \
"si,sid,sk,sl,so,sq,sr,ss,st,sv,sw,ta,te,tg,th,ti,tig,tk,tl,tn,tr," \
"ts,tt,ug,uk,unm,ur,uz,ve,vi,wa,wae,wal,wo,xh,yi,yo,yue,zh,zu"
typedef struct _xcb_im_styles_t {
uint32_t nStyles;
uint32_t *styles;
} xcb_im_styles_t;
typedef char *xcb_im_encoding_t;
typedef struct _xcb_im_encodings_t {
unsigned short nEncodings;
xcb_im_encoding_t *encodings;
} xcb_im_encodings_t;
typedef struct _xcb_im_t xcb_im_t;
typedef struct _xcb_im_input_context_t xcb_im_input_context_t;
typedef struct _xcb_im_client_t xcb_im_client_t;
// Mask to check if the attribute is set.
typedef enum _xcb_im_attr_mask_t {
XCB_XIM_XNArea_MASK = (1 << 0),
XCB_XIM_XNAreaNeeded_MASK = (1 << 1),
XCB_XIM_XNSpotLocation_MASK = (1 << 2),
XCB_XIM_XNColormap_MASK = (1 << 3),
XCB_XIM_XNForeground_MASK = (1 << 4),
XCB_XIM_XNBackground_MASK = (1 << 5),
XCB_XIM_XNBackgroundPixmap_MASK = (1 << 7),
XCB_XIM_XNLineSpace_MASK = (1 << 8),
} xcb_im_attr_mask_t;
typedef struct _xcb_im_preedit_attr_t {
xcb_rectangle_t area;
xcb_rectangle_t area_needed;
xcb_point_t spot_location;
xcb_colormap_t colormap;
uint32_t foreground;
uint32_t background;
xcb_window_t bg_pixmap;
uint32_t line_space;
} xcb_im_preedit_attr_t;
typedef struct _xcb_im_status_attr_t {
xcb_rectangle_t area;
xcb_rectangle_t area_needed;
xcb_point_t spot_location;
xcb_colormap_t colormap;
uint32_t foreground;
uint32_t background;
xcb_window_t bg_pixmap;
uint32_t line_space;
} xcb_im_status_attr_t;
typedef void (*xcb_im_callback)(xcb_im_t *im, xcb_im_client_t *client,
xcb_im_input_context_t *ic,
const xcb_im_packet_header_fr_t *hdr,
void *frame, void *arg, void *user_data);
typedef void (*xcb_im_free_function)(void *memory);
/**
* Create a XIM server.
*
* @param conn xcb connection to be used.
* @param screen xcb screen to be used.
* @param serverWindow A server window.
* @param serverName server name, need to be consistent with XMODIFIERS
* @param locale locale supported. You may want to use XCB_IM_ALL_LOCALES.
* @param inputStyles XIM Styles supported by XIM server.
* @param onKeysList Trigger on key to send to client.
* @param offKeysList Trigger off key to send to cilent.
* @param encodingList XIM encoding list.
* @param event_mask if 0, XCB_EVENT_MASK_KEY_PRESS will be used.
* @param callback Callback function
* @param user_data user data to callback function.
* @return xcb_im_t*
*/
XCBIMDKIT_EXPORT xcb_im_t *
xcb_im_create(xcb_connection_t *conn, int screen, xcb_window_t serverWindow,
const char *serverName, const char *locale,
const xcb_im_styles_t *inputStyles,
const xcb_im_trigger_keys_t *onKeysList,
const xcb_im_trigger_keys_t *offKeysList,
const xcb_im_encodings_t *encodingList, uint32_t event_mask,
xcb_im_callback callback, void *user_data);
/**
* @brief Set a logger handler.
*
* @param im XIM server.
* @param logger logger function.
*/
XCBIMDKIT_EXPORT void xcb_im_set_log_handler(xcb_im_t *im,
void (*logger)(const char *, ...));
/**
* Whether to use sync mode, it will affect certain behavior of XIM.
*
* Forward event and commit string behavior will be changed. If sync mode is
* true, every request need to be replied with sync_reply. The library is still
* working under async mode, just no more request will be send to client.
*
* @param im XIM server
* @param sync sync mode or not.
*/
XCBIMDKIT_EXPORT void xcb_im_set_use_sync_mode(xcb_im_t *im, bool sync);
/**
* Set whether the event defined by event mask is handled in a synchronous way.
*
* @param im XIM server
* @param sync sync on event or not.
*/
XCBIMDKIT_EXPORT void xcb_im_set_use_sync_event(xcb_im_t *im, bool sync);
/**
* Start a XIM server synchronously.
*
* It only does the minimum initialization and try to grab the server name. When
* it fails, it means there might be another server with the same name running.
*
* To finish the initialization, you will need to use xcb_im_filter_event on all
* the event recevied.
*
* You may also call this function again if it fails or after xcb_im_close_im.
*
* @param im XIM server.
* @return whether XIM server is started successfully.
*/
XCBIMDKIT_EXPORT bool xcb_im_open_im(xcb_im_t *im);
/**
* Handle XIM related event, most relevant event will be client message.
*
* @param im XIM server
* @param event X event.
* @return Whether the event is handled by XIM.
*/
XCBIMDKIT_EXPORT bool xcb_im_filter_event(xcb_im_t *im,
xcb_generic_event_t *event);
/**
* Shutdown the XIM server and free all the resources.
*
* @param im XIM server
*
* @see xcb_im_open_im
*/
XCBIMDKIT_EXPORT void xcb_im_close_im(xcb_im_t *im);
/**
* Destroy the XIM server.
*
* xcb_im_close_im need to be called if it is opened successfully.
*
* @param im XIM server.
*/
XCBIMDKIT_EXPORT void xcb_im_destroy(xcb_im_t *im);
/**
* Send a key event to the client.
*
* @param im XIM server
* @param ic Input context.
* @param event key event.
*/
XCBIMDKIT_EXPORT void xcb_im_forward_event(xcb_im_t *im,
xcb_im_input_context_t *ic,
xcb_key_press_event_t *event);
/**
* Send a key event to the client.
*
* @param im XIM server
* @param ic Input context.
* @param sequence sequence number, when re-inject, should be the value from
* forward_event
* @param event key event.
* @see xcb_im_forward_event_fr_t.
*/
XCBIMDKIT_EXPORT void xcb_im_forward_event_full(xcb_im_t *im,
xcb_im_input_context_t *ic,
uint16_t sequence,
xcb_key_press_event_t *event);
/**
* Commit a string to the client.
*
* @param im XIM server
* @param ic Input Context
* @param flag a bit flag of xcb_xim_lookup_flags_t, XCB_XIM_LOOKUP_CHARS is the
* most common value to be used.
* @param str string to be committed, encoding is usually COMPOUND_TEXT.
* @param length byte length of the string
* @param keysym key symbol.
*
* @see xcb_xim_lookup_flags_t
* @see xcb_utf8_to_compound_text
*/
XCBIMDKIT_EXPORT void xcb_im_commit_string(xcb_im_t *im,
xcb_im_input_context_t *ic,
uint32_t flag, const char *str,
uint32_t length, uint32_t keysym);
/**
* Start geometry negotiation, if XIMStyle has XIMPreeditArea or XIMStatusArea
* set.
*
* This is rarely used nowadays. Xlib doesn't have relevant code for it.
*
* @param im XIM server
* @param ic Input context
*/
XCBIMDKIT_EXPORT void xcb_im_geometry_callback(xcb_im_t *im,
xcb_im_input_context_t *ic);
/**
* Sends XIM_PREEDIT_START message to call the XIMPreeditStartCallback function.
*
* @param im XIM server
* @param ic Input context
*/
XCBIMDKIT_EXPORT void xcb_im_preedit_start_callback(xcb_im_t *im,
xcb_im_input_context_t *ic);
/**
* Sends XIM_PREEDIT_DRAW message to call the XIMPreeditDrawCallback function.
*
* @param im XIM server
* @param ic Input context
* @param frame information about preedit string.
*/
XCBIMDKIT_EXPORT void
xcb_im_preedit_draw_callback(xcb_im_t *im, xcb_im_input_context_t *ic,
xcb_im_preedit_draw_fr_t *frame);
/**
* Sends XIM_PREEDIT_CARET message to call the PreeditCaretCallback function.
*
* @param im XIM server
* @param ic Input context
* @param frame information about preedit caret.
*/
XCBIMDKIT_EXPORT void
xcb_im_preedit_caret_callback(xcb_im_t *im, xcb_im_input_context_t *ic,
xcb_im_preedit_caret_fr_t *frame);
/**
* sends XIM_PREEDIT_DONE message to call the XIMPreeditDoneCallback function.
*
* This should only be called after calling xcb_im_preedit_start_callback.
*
* @param im XIM server
* @param ic Input context
*/
XCBIMDKIT_EXPORT void xcb_im_preedit_done_callback(xcb_im_t *im,
xcb_im_input_context_t *ic);
/**
* Sends XIM_STATUS_START message to call the XIMStatusStartCallback function.
*
* @param im XIM server
* @param ic Input context
*/
XCBIMDKIT_EXPORT void xcb_im_status_start_callback(xcb_im_t *im,
xcb_im_input_context_t *ic);
/**
* Sends XIM_STATUS_DRAW message to call the XIMStatusDrawCallback function with
* text.
*
* @param im XIM server
* @param ic Input context
* @param frame text to be drawn by client.
*/
XCBIMDKIT_EXPORT void
xcb_im_status_draw_text_callback(xcb_im_t *im, xcb_im_input_context_t *ic,
xcb_im_status_draw_text_fr_t *frame);
/**
* Sends XIM_STATUS_DRAW message to call the XIMStatusDrawCallback function with
* bitmap.
*
* @param im XIM server
* @param ic Input context
* @param frame bitmap to be drawn by client.
*/
XCBIMDKIT_EXPORT void
xcb_im_status_draw_bitmap_callback(xcb_im_t *im, xcb_im_input_context_t *ic,
xcb_im_status_draw_bitmap_fr_t *frame);
/**
* Sends XIM_STATUS_DONE message to call the XIMStatusDoneCallback function.
*
* @param im XIM server
* @param ic Input context
*/
XCBIMDKIT_EXPORT void xcb_im_status_done_callback(xcb_im_t *im,
xcb_im_input_context_t *ic);
XCBIMDKIT_EXPORT void xcb_im_preedit_start(xcb_im_t *im,
xcb_im_input_context_t *ic);
XCBIMDKIT_EXPORT void xcb_im_preedit_end(xcb_im_t *im,
xcb_im_input_context_t *ic);
XCBIMDKIT_EXPORT void xcb_im_sync_xlib(xcb_im_t *im,
xcb_im_input_context_t *ic);
XCBIMDKIT_EXPORT bool xcb_im_support_extension(xcb_im_t *im,
uint16_t major_code,
uint16_t minor_code);
XCBIMDKIT_EXPORT void
xcb_im_input_context_set_data(xcb_im_input_context_t *ic, void *data,
xcb_im_free_function free_data_function);
XCBIMDKIT_EXPORT void *
xcb_im_input_context_get_data(xcb_im_input_context_t *ic);
XCBIMDKIT_EXPORT uint32_t
xcb_im_input_context_get_input_style(xcb_im_input_context_t *ic);
XCBIMDKIT_EXPORT xcb_window_t
xcb_im_input_context_get_client_window(xcb_im_input_context_t *ic);
XCBIMDKIT_EXPORT xcb_window_t
xcb_im_input_context_get_focus_window(xcb_im_input_context_t *ic);
XCBIMDKIT_EXPORT const xcb_im_preedit_attr_t *
xcb_im_input_context_get_preedit_attr(xcb_im_input_context_t *ic);
XCBIMDKIT_EXPORT const xcb_im_status_attr_t *
xcb_im_input_context_get_status_attr(xcb_im_input_context_t *ic);
XCBIMDKIT_EXPORT uint32_t
xcb_im_input_context_get_preedit_attr_mask(xcb_im_input_context_t *ic);
XCBIMDKIT_EXPORT uint32_t
xcb_im_input_context_get_status_attr_mask(xcb_im_input_context_t *ic);
XCBIMDKIT_DECL_END
#endif // _XCB_IMDKIT_IMDKIT_H_

View File

@ -0,0 +1,292 @@
/*
* SPDX-FileCopyrightText: 2014 Weng Xuetian <wengxt@gmail.com>
*
* SPDX-License-Identifier: LGPL-2.1-only
*
*/
#ifndef _XCB_IMDKIT_IMDKIT_P_H_
#define _XCB_IMDKIT_IMDKIT_P_H_
#include "common.h"
#include "imdkit.h"
#include "list.h"
#include "message.h"
#include "uthash.h"
#include "ximproto_p.h"
#define LOCALES_BUFSIZE (sizeof(XCB_IM_ALL_LOCALES) + 32)
/*
* values for the flag of XIM_ERROR
*/
#define XIM_IMID_VALID 0x0001
#define XIM_ICID_VALID 0x0002
/*
* XIM Error Code
*/
#define XIM_BadAlloc 1
#define XIM_BadStyle 2
#define XIM_BadClientWindow 3
#define XIM_BadFocusWindow 4
#define XIM_BadArea 5
#define XIM_BadSpotLocation 6
#define XIM_BadColormap 7
#define XIM_BadAtom 8
#define XIM_BadPixel 9
#define XIM_BadPixmap 10
#define XIM_BadName 11
#define XIM_BadCursor 12
#define XIM_BadProtocol 13
#define XIM_BadForeground 14
#define XIM_BadBackground 15
#define XIM_LocaleNotSupported 16
#define XIM_BadSomething 999
/*
* byte order
*/
#define BIGENDIAN (CARD8)0x42 /* MSB first */
#define LITTLEENDIAN (CARD8)0x6c /* LSB first */
/*
* values for the category of XIM_ENCODING_NEGOTIATON_REPLY
*/
#define XIM_Encoding_NameCategory 0
#define XIM_Encoding_DetailCategory 1
/*
* value for the index of XIM_ENCODING_NEGOTIATON_REPLY
*/
#define XIM_Default_Encoding_IDX -1
#define _xcb_im_read_frame_with_error(IM, CLIENT, FRAME, DATA, LEN) \
do { \
size_t len = (LEN); \
frame_read_func(FRAME)(&FRAME, &DATA, &len, \
(CLIENT)->byte_order != (IM)->byte_order); \
if (!DATA) { \
frame_free_func(FRAME)(&FRAME); \
_xcb_im_send_error_message((IM), (CLIENT)); \
return; \
} \
} while (0)
#define _xcb_im_read_frame(IM, CLIENT, FRAME, DATA, LEN) \
do { \
size_t len = (LEN); \
frame_read_func(FRAME)(&FRAME, &DATA, &len, \
(CLIENT)->byte_order != (IM)->byte_order); \
if (!DATA) { \
frame_free_func(FRAME)(&FRAME); \
return; \
} \
} while (0)
#define _xcb_im_send_frame(IM, CLIENT, FRAME, SEND_ERROR) \
do { \
bool fail = true; \
bool swap = (CLIENT)->byte_order != (IM)->byte_order; \
size_t length = frame_size_func(FRAME); \
uint8_t *reply; \
uint8_t *alloc_reply = NULL; \
uint8_t \
static_reply[XCB_IM_HEADER_SIZE + (frame_has_static_size(FRAME) \
? frame_size_func(FRAME) \
: 1)]; \
if (frame_has_static_size(FRAME)) { \
reply = static_reply; \
_xcb_write_xim_message_header( \
reply, XIM_PROTO_FRAME_OPCODE(FRAME), 0, length, swap); \
} else { \
reply = _xcb_new_xim_message(XIM_PROTO_FRAME_OPCODE(FRAME), 0, \
length, swap); \
alloc_reply = reply; \
} \
do { \
if (!reply) { \
break; \
} \
frame_write_func(FRAME)(&(FRAME), reply + XCB_IM_HEADER_SIZE, \
swap); \
if (!_xcb_im_send_message((IM), (CLIENT), reply, length)) { \
break; \
} \
fail = false; \
} while (0); \
free(alloc_reply); \
if ((SEND_ERROR) && fail) { \
_xcb_im_send_error_message((IM), (CLIENT)); \
} \
} while (0)
struct _xcb_im_input_context_t {
uint16_t id;
xcb_im_client_t *client;
uint32_t input_style;
xcb_window_t client_win;
xcb_window_t focus_win;
xcb_im_preedit_attr_t preedit;
uint32_t preedit_mask;
xcb_im_status_attr_t status;
uint32_t status_mask;
UT_hash_handle hh;
void *data;
xcb_im_free_function free_data_function;
uint16_t forward_event_sequence;
};
struct _xcb_im_client_t {
xcb_window_t accept_win;
int connect_id;
xcb_window_t client_win;
uint8_t byte_order;
bool sync;
uint16_t icid;
xcb_im_input_context_t *ic_free_list;
xcb_im_input_context_t *input_contexts;
list_head queue;
xcb_im_property_offset_t *offsets;
UT_hash_handle hh1;
UT_hash_handle hh2;
};
typedef struct _xcb_im_default_im_attr_t {
char *name;
uint16_t type;
bool (*get_value)(xcb_im_t *im, xcb_im_client_t *client,
xcb_im_ximattribute_fr_t *attr);
} xcb_im_default_im_attr_t;
bool _xcb_im_get_input_styles_attr(xcb_im_t *im, xcb_im_client_t *client,
xcb_im_ximattribute_fr_t *attr);
static const xcb_im_default_im_attr_t Default_IMattr[] = {
{XCB_XIM_XNQueryInputStyle, XimType_XIMStyles,
_xcb_im_get_input_styles_attr},
/* {XCB_XIM_XNQueryIMValuesList, XimType_XIMValuesList}, */
};
typedef struct _xcb_im_default_ic_attr_t {
char *name;
uint16_t type;
bool read;
} xcb_im_default_ic_attr_t;
static const xcb_im_default_ic_attr_t Default_ICattr[] = {
{XCB_XIM_XNInputStyle, XimType_CARD32, false},
{XCB_XIM_XNClientWindow, XimType_Window, false},
{XCB_XIM_XNFocusWindow, XimType_Window, false},
{XCB_XIM_XNFilterEvents, XimType_CARD32, false},
{XCB_XIM_XNPreeditAttributes, XimType_NEST, false},
{XCB_XIM_XNStatusAttributes, XimType_NEST, false},
{XCB_XIM_XNFontSet, XimType_XFontSet, false},
{XCB_XIM_XNArea, XimType_XRectangle, true},
{XCB_XIM_XNAreaNeeded, XimType_XRectangle, true},
{XCB_XIM_XNColormap, XimType_CARD32, false},
{XCB_XIM_XNStdColormap, XimType_CARD32, false},
{XCB_XIM_XNForeground, XimType_CARD32, true},
{XCB_XIM_XNBackground, XimType_CARD32, true},
{XCB_XIM_XNBackgroundPixmap, XimType_CARD32, false},
{XCB_XIM_XNSpotLocation, XimType_XPoint, true},
{XCB_XIM_XNLineSpace, XimType_CARD32, true},
{XCB_XIM_XNSeparatorofNestedList, XimType_SeparatorOfNestedList, false},
};
struct _xcb_im_t {
xcb_connection_t *conn;
xcb_im_ximattr_fr_t imattr[ARRAY_SIZE(Default_IMattr)];
xcb_im_xicattr_fr_t icattr[ARRAY_SIZE(Default_ICattr)];
xcb_im_ext_fr_t extension[ARRAY_SIZE(Default_Extension)];
uint16_t preeditAttr_id;
uint16_t statusAttr_id;
uint16_t separatorAttr_id;
xcb_im_ximattr_fr_t
*id2attr[ARRAY_SIZE(Default_IMattr) + ARRAY_SIZE(Default_ICattr)];
ssize_t id2preeditoffset[ARRAY_SIZE(Default_IMattr) +
ARRAY_SIZE(Default_ICattr)];
uint32_t
id2preeditmask[ARRAY_SIZE(Default_IMattr) + ARRAY_SIZE(Default_ICattr)];
ssize_t id2statusoffset[ARRAY_SIZE(Default_IMattr) +
ARRAY_SIZE(Default_ICattr)];
uint32_t
id2statusmask[ARRAY_SIZE(Default_IMattr) + ARRAY_SIZE(Default_ICattr)];
ssize_t
id2icoffset[ARRAY_SIZE(Default_IMattr) + ARRAY_SIZE(Default_ICattr)];
uint32_t event_mask;
xcb_im_trigger_keys_t onKeys;
xcb_im_trigger_keys_t offKeys;
xcb_im_styles_t inputStyles;
xcb_im_encodings_t encodings;
char *locale;
char *serverName;
xcb_window_t serverWindow;
int screen_id;
xcb_atom_t atoms[XIM_ATOM_LAST];
xcb_im_client_t *free_list;
xcb_im_client_t *clients_by_id;
xcb_im_client_t *clients_by_win;
uint16_t connect_id;
xcb_screen_t *screen;
xcb_screen_t *default_screen;
uint32_t sequence;
xcb_im_callback callback;
void *user_data;
void (*logger)(const char *, ...);
uint8_t byte_order;
bool init;
bool sync;
bool use_sync_mode;
bool use_sync_event;
};
typedef union _xcb_im_ic_attr_value_t {
xcb_rectangle_t rect;
xcb_point_t point;
uint32_t byte4;
struct {
uint8_t *data;
uint8_t len;
} raw;
} xcb_im_ic_attr_value_t;
typedef struct _xcb_im_queue_t {
uint16_t icid;
xcb_im_packet_header_fr_t hdr;
xcb_im_forward_event_fr_t frame;
xcb_key_press_event_t event;
list_head list;
} xcb_im_queue_t;
xcb_im_input_context_t *_xcb_im_new_input_context(xcb_im_t *im,
xcb_im_client_t *client);
const xcb_im_default_ic_attr_t *_xcb_im_default_ic_attr_entry(xcb_im_t *im,
uint32_t id);
bool _xcb_im_send_message(xcb_im_t *im, xcb_im_client_t *client, uint8_t *data,
size_t length);
void _xcb_im_send_error_message(xcb_im_t *im, xcb_im_client_t *client);
void _xcb_im_destroy_client(xcb_im_t *im, xcb_im_client_t *client);
void _xcb_im_destroy_ic(xcb_im_t *im, xcb_im_input_context_t *ic);
void _xcb_im_send_set_event_mask(xcb_im_t *im, xcb_im_client_t *client,
uint32_t icid, uint32_t forward_event_mask,
uint32_t sync_mask);
void _xcb_im_set_ic_event_mask(xcb_im_t *im, xcb_im_input_context_t *client);
void _xcb_im_set_im_event_mask(xcb_im_t *im, xcb_im_client_t *ic);
void _xcb_im_add_queue(xcb_im_t *im, xcb_im_client_t *client, uint16_t icid,
const xcb_im_packet_header_fr_t *hdr,
xcb_im_forward_event_fr_t *frame, uint8_t *data);
void _xcb_im_process_queue(xcb_im_t *im, xcb_im_client_t *client);
static inline bool _xcb_im_has_trigger_key(xcb_im_t *im) {
return im->onKeys.nKeys || im->offKeys.nKeys;
}
#endif // _XCB_IMDKIT_IMDKIT_P_H_

90
xim/xcb-imdkit/src/list.h Normal file
View File

@ -0,0 +1,90 @@
/*
* SPDX-FileCopyrightText: 2014 Weng Xuetian <wengxt@gmail.com>
*
* SPDX-License-Identifier: LGPL-2.1-only
*
*/
#ifndef _LINK_LIST_H_
#define _LINK_LIST_H_
#include <stdlib.h>
#define list_container_of(ptr, type, member) \
((type *)(((void *)(ptr)) - offsetof(type, member)))
typedef struct _list_head {
struct _list_head *prev;
struct _list_head *next;
} list_head;
static inline void list_init(list_head *pos) {
pos->next = pos;
pos->prev = pos;
}
static inline bool list_is_empty(list_head *pos) { return pos->next == pos; }
static inline void __list_insert_between(list_head *add, list_head *prev,
list_head *next) {
next->prev = add;
prev->next = add;
add->next = next;
add->prev = prev;
}
static inline void list_prepend(list_head *add, list_head *pos) {
__list_insert_between(add, pos, pos->next);
}
static inline void list_append(list_head *add, list_head *pos) {
__list_insert_between(add, pos->prev, pos);
}
static inline void list_remove(list_head *pos) {
list_head *next = pos->next;
list_head *prev = pos->prev;
prev->next = next;
next->prev = prev;
pos->next = NULL;
pos->prev = NULL;
}
#define list_foreach(key, head) \
for (list_head *key = (head)->next; key != (head); key = key->next)
#define list_foreach_safe(key, head) \
for (list_head *key = (head)->next, *__n = key->next; key != (head); \
key = __n, __n = key->next)
#define list_foreach_nl(key, head) \
for (key = (head)->next; key != (head); key = key->next)
#define list_foreach_safe_nl(key, __n, head) \
for (key = (head)->next, __n = key->next; key != (head); \
key = __n, __n = key->next)
#define list_entry_foreach(key, type, head, field) \
for (type *key = list_container_of((head)->next, type, field); \
&key->field != (head); \
key = list_container_of(key->field.next, type, field))
#define list_entry_foreach_nl(key, type, head, field) \
for (key = list_container_of((head)->next, type, field); \
&key->field != (head); \
key = list_container_of(key->field.next, type, field))
#define list_entry_foreach_safe(key, type, head, field) \
for (type *key = list_container_of((head)->next, type, field), \
*__n = list_container_of(key->field.next, type, field); \
&key->field != (head); \
key = __n, __n = list_container_of(key->field.next, type, field))
#define list_entry_foreach_safe_nl(key, __n, type, head, field) \
for (key = list_container_of((head)->next, type, field), \
__n = list_container_of(key->field.next, type, field); \
&key->field != (head); \
key = __n, __n = list_container_of(key->field.next, type, field))
#endif

View File

@ -0,0 +1,221 @@
/*
* SPDX-FileCopyrightText: 2014 Weng Xuetian <wengxt@gmail.com>
*
* SPDX-License-Identifier: LGPL-2.1-only
*
*/
#include "message.h"
#include "common.h"
#include "parser.h"
#include "ximproto.h"
#include <stdlib.h>
#include <string.h>
static uint32_t lookup_offset(xcb_im_property_offset_t **offsets,
xcb_atom_t atom) {
if (!offsets) {
return 0;
}
xcb_im_property_offset_t *result = NULL;
HASH_FIND(hh, *offsets, &atom, sizeof(xcb_atom_t), result);
if (!result) {
return 0;
}
return result->offset;
}
static void set_offset(xcb_im_property_offset_t **offsets, xcb_atom_t atom,
uint32_t offset) {
if (!offsets) {
return;
}
xcb_im_property_offset_t *result = NULL;
HASH_FIND(hh, *offsets, &atom, sizeof(xcb_atom_t), result);
if (!result) {
if (offset != 0) {
result = calloc(1, sizeof(xcb_im_property_offset_t));
result->atom = atom;
result->offset = offset;
HASH_ADD(hh, *offsets, atom, sizeof(xcb_atom_t), result);
}
} else {
if (offset == 0) {
HASH_DEL(*offsets, result);
free(result);
} else {
result->offset = offset;
}
}
}
uint8_t *_xcb_new_xim_message(uint8_t major_opcode, uint8_t minor_opcode,
size_t length, bool swap) {
uint8_t *message = calloc(length + XCB_IM_HEADER_SIZE, 1);
if (message) {
_xcb_write_xim_message_header(message, major_opcode, minor_opcode,
length, swap);
}
return message;
}
uint8_t *_xcb_write_xim_message_header(uint8_t *message, uint8_t major_opcode,
uint8_t minor_opcode, size_t length,
bool swap) {
uint16_t p_len = length / 4;
message = uint8_t_write(&major_opcode, message, swap);
message = uint8_t_write(&minor_opcode, message, swap);
message = uint16_t_write(&p_len, message, swap);
return message;
}
// length is the body without header size in byte
bool _xcb_send_xim_message(xcb_connection_t *conn, xcb_atom_t protocol_atom,
xcb_window_t window, uint8_t *data, size_t length,
const char *name, size_t len) {
if (!data) {
return false;
}
// add header size
length += XCB_IM_HEADER_SIZE;
xcb_client_message_event_t event;
memset(&event, 0, sizeof(event));
event.response_type = XCB_CLIENT_MESSAGE;
event.sequence = 0;
event.window = window;
event.type = protocol_atom;
if (length > XCB_XIM_CM_DATA_SIZE) {
xcb_atom_t atom;
xcb_intern_atom_cookie_t atom_cookie =
xcb_intern_atom(conn, false, len, name);
xcb_intern_atom_reply_t *atom_reply =
xcb_intern_atom_reply(conn, atom_cookie, NULL);
if (!atom_reply) {
return false;
}
atom = atom_reply->atom;
free(atom_reply);
xcb_get_property_cookie_t get_property_cookie = xcb_get_property(
conn, false, window, atom, XCB_ATOM_STRING, 0L, 10000L);
xcb_get_property_reply_t *get_property_reply =
xcb_get_property_reply(conn, get_property_cookie, NULL);
if (!get_property_reply) {
return false;
}
free(get_property_reply);
xcb_void_cookie_t cookie =
xcb_change_property_checked(conn, XCB_PROP_MODE_APPEND, window,
atom, XCB_ATOM_STRING, 8, length, data);
xcb_generic_error_t *error = NULL;
if ((error = xcb_request_check(conn, cookie)) != NULL) {
free(error);
}
event.format = 32;
event.data.data32[0] = length;
event.data.data32[1] = atom;
for (size_t i = 2; i < ARRAY_SIZE(event.data.data32); i++) {
event.data.data32[i] = 0;
}
} else {
event.format = 8;
memcpy(event.data.data8, data, length);
/* Clear unused field with NULL */
for (size_t i = length; i < XCB_XIM_CM_DATA_SIZE; i++) {
event.data.data8[i] = 0;
}
}
xcb_void_cookie_t send_event_cookie = xcb_send_event_checked(
conn, false, window, XCB_EVENT_MASK_NO_EVENT, (const char *)&event);
xcb_generic_error_t *error = NULL;
if ((error = xcb_request_check(conn, send_event_cookie)) != NULL) {
free(error);
}
return true;
}
void _xcb_send_xim_error_message(xcb_connection_t *conn,
xcb_atom_t protocol_atom, xcb_window_t window,
bool swap) {
// use stack to avoid alloc fails
uint8_t message[XCB_IM_HEADER_SIZE];
_xcb_write_xim_message_header(message, XCB_XIM_ERROR, 0, 0, swap);
_xcb_send_xim_message(conn, protocol_atom, window, message, 0, NULL, 0);
}
uint8_t *_xcb_read_xim_message(xcb_connection_t *conn, xcb_window_t window,
xcb_im_property_offset_t **offsets,
xcb_client_message_event_t *ev,
xcb_im_packet_header_fr_t *hdr, bool swap) {
uint8_t *p = NULL;
if (ev->format == 8) {
/* ClientMessage only */
uint8_t *rec = ev->data.data8;
size_t len = sizeof(ev->data.data8);
uint8_t_read(&hdr->major_opcode, &rec, &len, false);
uint8_t_read(&hdr->minor_opcode, &rec, &len, false);
uint16_t_read(&hdr->length, &rec, &len, false);
// check message is well formed
if (len >= hdr->length * 4) {
p = malloc(hdr->length * 4);
}
if (p) {
memcpy(p, rec, hdr->length * 4);
}
} else if (ev->format == 32) {
/* ClientMessage and WindowProperty */
size_t length = ev->data.data32[0];
xcb_atom_t atom = ev->data.data32[1];
uint32_t offset = lookup_offset(offsets, atom);
uint32_t end = offset + length;
uint32_t dword_begin = offset / 4;
uint32_t dword_end = (end + 3) / 4;
xcb_get_property_cookie_t cookie =
xcb_get_property(conn, true, window, atom, XCB_ATOM_ANY,
dword_begin, dword_end - dword_begin);
xcb_get_property_reply_t *reply =
xcb_get_property_reply(conn, cookie, NULL);
uint8_t *rec;
if (!reply || reply->format == 0 || reply->length == 0) {
free(reply);
return (unsigned char *)NULL;
}
rec = xcb_get_property_value(reply) + (offset % 4);
if (reply->bytes_after) {
set_offset(offsets, atom, offset + length);
} else {
set_offset(offsets, atom, 0);
}
uint8_t_read(&hdr->major_opcode, &rec, &length, swap);
uint8_t_read(&hdr->minor_opcode, &rec, &length, swap);
uint16_t_read(&hdr->length, &rec, &length, swap);
size_t buffer_size = ((size_t)hdr->length) * 4;
// check message is well formed
if (buffer_size <= length) {
/* if hit, it might be an error */
p = malloc(buffer_size);
}
if (p) {
memcpy(p, rec, buffer_size);
}
free(reply);
}
return p;
}

View File

@ -0,0 +1,48 @@
/*
* SPDX-FileCopyrightText: 2014 Weng Xuetian <wengxt@gmail.com>
*
* SPDX-License-Identifier: LGPL-2.1-only
*
*/
#ifndef MESSAGE_H
#define MESSAGE_H
#include "ximproto.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <uthash.h>
#include <xcb/xcb.h>
#include <xcb/xproto.h>
typedef struct _xcb_im_property_offset_t {
xcb_atom_t atom;
uint32_t offset;
UT_hash_handle hh;
} xcb_im_property_offset_t;
// Return a new alloc xim message. length is the content size without header
// size.
uint8_t *_xcb_new_xim_message(uint8_t major_opcode, uint8_t minor_opcode,
size_t length, bool swap);
// Write xim message header and return the pointer to content.
uint8_t *_xcb_write_xim_message_header(uint8_t *message, uint8_t major_opcode,
uint8_t minor_opcode, size_t length,
bool swap);
// length is the body without header size in byte
bool _xcb_send_xim_message(xcb_connection_t *conn, xcb_atom_t protocol_atom,
xcb_window_t window, uint8_t *data, size_t length,
const char *name, size_t len);
void _xcb_send_xim_error_message(xcb_connection_t *conn,
xcb_atom_t protocol_atom, xcb_window_t window,
bool swap);
uint8_t *_xcb_read_xim_message(xcb_connection_t *conn, xcb_window_t window,
xcb_im_property_offset_t **offsets,
xcb_client_message_event_t *ev,
xcb_im_packet_header_fr_t *hdr, bool swap);
#endif // MESSAGE_H

117
xim/xcb-imdkit/src/parser.c Normal file
View File

@ -0,0 +1,117 @@
/*
* SPDX-FileCopyrightText: 2014 Weng Xuetian <wengxt@gmail.com>
*
* SPDX-License-Identifier: LGPL-2.1-only
*
*/
#include "parser.h"
#include <stdlib.h>
#include <string.h>
/* For byte swapping */
#define Swap8(n) (n)
#define Swap16(n) (swap ? (((n) << 8 & 0xFF00) | ((n) >> 8 & 0xFF)) : n)
#define Swap32(n) \
(swap ? (((n) << 24 & 0xFF000000) | ((n) << 8 & 0xFF0000) | \
((n) >> 8 & 0xFF00) | ((n) >> 24 & 0xFF)) \
: n)
#define Swap64(n) \
(swap ? (((n) << 56 & 0xFF00000000000000) | \
((n) << 40 & 0xFF000000000000) | ((n) << 24 & 0xFF0000000000) | \
((n) << 8 & 0xFF00000000) | ((n) >> 8 & 0xFF000000) | \
((n) >> 24 & 0xFF0000) | ((n) >> 40 & 0xFF00) | \
((n) >> 56 & 0xFF)) \
: n)
void uint8_t_read(uint8_t *p, uint8_t **data, size_t *len, bool swap) {
if (*len < 1) {
*data = NULL;
return;
}
*p = **data;
*data += 1;
*len -= 1;
}
uint8_t *uint8_t_write(uint8_t *p, uint8_t *data, bool swap) {
*data = *p;
data += 1;
return data;
}
void uint16_t_read(uint16_t *p, uint8_t **data, size_t *len, bool swap) {
if (*len < 2) {
*data = NULL;
return;
}
*p = Swap16(*((uint16_t *)*data));
*data += 2;
*len -= 2;
}
uint8_t *uint16_t_write(uint16_t *p, uint8_t *data, bool swap) {
*((uint16_t *)data) = Swap16(*p);
data += 2;
return data;
}
void uint32_t_read(uint32_t *p, uint8_t **data, size_t *len, bool swap) {
if (*len < 4) {
*data = NULL;
return;
}
*p = Swap32(*((uint32_t *)*data));
*data += 4;
*len -= 4;
}
uint8_t *uint32_t_write(uint32_t *p, uint8_t *data, bool swap) {
*((uint32_t *)data) = Swap32(*p);
data += 4;
return data;
}
void xcb_im_bytearray_t_read(xcb_im_bytearray_t *p, uint32_t arraylen,
uint8_t **data, size_t *len, bool swap) {
if (*len < arraylen) {
*data = NULL;
return;
}
*p = *data;
*data += arraylen;
*len -= arraylen;
}
uint8_t *xcb_im_bytearray_t_write(xcb_im_bytearray_t *p, uint32_t arraylen,
uint8_t *data, bool swap) {
memcpy(data, *p, arraylen);
return data + arraylen;
}
uintptr_t align_to_4(uintptr_t ptr, uintptr_t len, size_t *remain) {
uintptr_t diff = (len % 4) ? 4 - (len % 4) : 0;
if (remain) {
if (*remain < diff) {
return 0;
}
*remain -= diff;
}
return ptr + diff;
}
uintptr_t align_to_2(uintptr_t ptr, uintptr_t len, size_t *remain) {
uintptr_t diff = (len % 2) ? 2 - (len % 2) : 0;
if (remain) {
if (*remain < diff) {
return 0;
}
*remain -= diff;
}
return ptr + diff;
}

View File

@ -0,0 +1,32 @@
/*
* SPDX-FileCopyrightText: 2014 Weng Xuetian <wengxt@gmail.com>
*
* SPDX-License-Identifier: LGPL-2.1-only
*
*/
#ifndef _XCB_IMDKIT_PARSER_H_
#define _XCB_IMDKIT_PARSER_H_
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "ximproto.h"
#define READ_FUNC(TYPE) \
void TYPE##_read(TYPE *p, uint8_t **data, size_t *len, bool swap); \
uint8_t *TYPE##_write(TYPE *p, uint8_t *data, bool swap);
READ_FUNC(uint8_t)
READ_FUNC(uint16_t)
READ_FUNC(uint32_t)
void xcb_im_bytearray_t_read(xcb_im_bytearray_t *p, uint32_t arraylen,
uint8_t **data, size_t *len, bool swap);
uint8_t *xcb_im_bytearray_t_write(xcb_im_bytearray_t *p, uint32_t arraylen,
uint8_t *data, bool swap);
uintptr_t align_to_4(uintptr_t ptr, uintptr_t len, size_t *remain);
uintptr_t align_to_2(uintptr_t ptr, uintptr_t len, size_t *remain);
#endif // IMDKIT_PARSE_H

View File

@ -0,0 +1,937 @@
/*
* SPDX-FileCopyrightText: 2014 Weng Xuetian <wengxt@gmail.com>
*
* SPDX-License-Identifier: LGPL-2.1-only
*
*/
#include "protocolhandler.h"
#include "common.h"
#include "imdkit_p.h"
#include "parser.h"
#include "uthash.h"
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <xcb/xproto.h>
void _xcb_im_handle_connect(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_connect_fr_t frame;
_xcb_im_read_frame_with_error(im, client, frame, data,
XIM_MESSAGE_BYTES(hdr));
if (im->callback) {
im->callback(im, client, NULL, hdr, &frame, NULL, im->user_data);
}
xcb_im_connect_fr_free(&frame);
xcb_im_connect_reply_fr_t reply_frame;
reply_frame.server_major_protocol_version =
frame.client_major_protocol_version;
reply_frame.server_minor_protocol_version =
frame.client_minor_protocol_version;
_xcb_im_send_frame(im, client, reply_frame, true);
}
static void _xcb_im_send_trigger_key(xcb_im_t *im, xcb_im_client_t *client) {
xcb_im_register_triggerkeys_fr_t frame;
/* Right now XIM_OPEN_REPLY hasn't been sent to this new client, so
the input-method-id is still invalid, and should be set to zero...
Reter to $(XC)/lib/X11/imDefLkup.c:_XimRegisterTriggerKeysCallback
*/
frame.input_method_ID = 0;
frame.on_keys_list.size = im->onKeys.nKeys;
frame.on_keys_list.items = im->onKeys.keys;
frame.off_keys_list.size = im->offKeys.nKeys;
frame.off_keys_list.items = im->offKeys.keys;
_xcb_im_send_frame(im, client, frame, false);
}
void _xcb_im_handle_open(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr, uint8_t *data) {
xcb_im_open_fr_t frame;
_xcb_im_read_frame_with_error(im, client, frame, data,
XIM_MESSAGE_BYTES(hdr));
if (im->callback) {
im->callback(im, client, NULL, hdr, &frame, NULL, im->user_data);
}
xcb_im_open_fr_free(&frame);
xcb_im_open_reply_fr_t reply_frame;
reply_frame.input_method_ID = client->connect_id;
reply_frame.IM_attribute_supported.size = ARRAY_SIZE(im->imattr);
reply_frame.IC_attribute_supported.size = ARRAY_SIZE(im->icattr);
reply_frame.IM_attribute_supported.items = im->imattr;
reply_frame.IC_attribute_supported.items = im->icattr;
_xcb_im_send_frame(im, client, reply_frame, true);
if (_xcb_im_has_trigger_key(im)) {
_xcb_im_send_trigger_key(im, client);
} else {
_xcb_im_set_im_event_mask(im, client);
}
}
void _xcb_im_handle_close(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr, uint8_t *data) {
xcb_im_close_fr_t frame;
_xcb_im_read_frame_with_error(im, client, frame, data,
XIM_MESSAGE_BYTES(hdr));
if (im->callback) {
im->callback(im, client, NULL, hdr, &frame, NULL, im->user_data);
}
xcb_im_close_fr_free(&frame);
xcb_im_close_reply_fr_t reply_frame;
reply_frame.input_method_ID = frame.input_method_ID;
_xcb_im_send_frame(im, client, reply_frame, true);
}
void _xcb_im_handle_query_extension(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_query_extension_fr_t frame;
_xcb_im_read_frame_with_error(im, client, frame, data,
XIM_MESSAGE_BYTES(hdr));
int nExts = 0;
xcb_im_ext_fr_t ext_list[ARRAY_SIZE(Default_Extension)];
for (size_t i = 0; i < frame.extensions_supported_by_the_IM_library.size;
i++) {
for (size_t j = 0; j < ARRAY_SIZE(Default_Extension); j++) {
if (frame.extensions_supported_by_the_IM_library.items[i]
.length_of_string ==
im->extension[j].length_of_extension_name &&
strncmp((char *)frame.extensions_supported_by_the_IM_library
.items[i]
.string,
(char *)im->extension[j].extension_name,
frame.extensions_supported_by_the_IM_library.items[i]
.length_of_string) == 0) {
ext_list[nExts] = im->extension[j];
nExts++;
break;
}
}
}
xcb_im_query_extension_fr_free(&frame);
xcb_im_query_extension_reply_fr_t reply_frame;
reply_frame.input_method_ID = client->connect_id;
reply_frame.list_of_extensions_supported_by_th.items = ext_list;
reply_frame.list_of_extensions_supported_by_th.size = nExts;
_xcb_im_send_frame(im, client, reply_frame, true);
}
void _xcb_im_handle_encoding_negotiation(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_encoding_negotiation_fr_t frame;
_xcb_im_read_frame_with_error(im, client, frame, data,
XIM_MESSAGE_BYTES(hdr));
size_t i, j;
for (i = 0; i < frame.supported_list_of_encoding_in_IM_library.size; i++) {
for (j = 0; j < im->encodings.nEncodings; j++) {
if (frame.supported_list_of_encoding_in_IM_library.items[i]
.length_of_string ==
strlen(im->encodings.encodings[j]) &&
strncmp((char *)frame.supported_list_of_encoding_in_IM_library
.items[i]
.string,
im->encodings.encodings[j],
frame.supported_list_of_encoding_in_IM_library.items[i]
.length_of_string) == 0) {
break;
}
}
if (j != im->encodings.nEncodings) {
break;
}
}
// no match then we use 0.
if (i == frame.supported_list_of_encoding_in_IM_library.size) {
i = 0;
j = 0;
}
xcb_im_encoding_negotiation_fr_free(&frame);
xcb_im_encoding_negotiation_reply_fr_t reply_frame;
reply_frame.input_method_ID = client->connect_id;
reply_frame.index_of_the_encoding_determined = i;
reply_frame.category_of_the_encoding_determined = 0;
uint16_t index = j;
if (im->callback) {
im->callback(im, client, NULL, hdr, &frame, &index, im->user_data);
}
_xcb_im_send_frame(im, client, reply_frame, true);
}
void _xcb_im_handle_get_im_values(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_get_im_values_fr_t frame;
_xcb_im_read_frame_with_error(im, client, frame, data,
XIM_MESSAGE_BYTES(hdr));
xcb_im_get_im_values_reply_fr_t reply_frame;
size_t nBuffers = 0;
xcb_im_ximattribute_fr_t buffers[ARRAY_SIZE(Default_IMattr)];
bool met[ARRAY_SIZE(Default_IMattr)];
memset(met, 0, sizeof(met));
for (size_t i = 0; i < frame.im_attribute_id.size; i++) {
if (frame.im_attribute_id.items[i] >= ARRAY_SIZE(im->id2attr)) {
continue;
}
xcb_im_ximattr_fr_t *attr = im->id2attr[frame.im_attribute_id.items[i]];
if ((attr < im->imattr) ||
(attr >= im->imattr + ARRAY_SIZE(Default_IMattr))) {
continue;
}
if (met[attr - im->imattr]) {
continue;
}
if (!Default_IMattr[attr - im->imattr].get_value) {
continue;
}
if (!Default_IMattr[attr - im->imattr].get_value(im, client,
&buffers[nBuffers])) {
continue;
}
buffers[nBuffers].attribute_ID = frame.im_attribute_id.items[i];
met[attr - im->imattr] = true;
nBuffers++;
}
reply_frame.input_method_ID = client->connect_id;
reply_frame.im_attribute_returned.items = buffers;
reply_frame.im_attribute_returned.size = nBuffers;
xcb_im_get_im_values_fr_free(&frame);
_xcb_im_send_frame(im, client, reply_frame, true);
for (size_t i = 0; i < nBuffers; i++) {
free(buffers[i].value);
}
}
void _xcb_im_handle_disconnect(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
_xcb_im_destroy_client(im, client);
xcb_im_disconnect_reply_fr_t reply_frame;
_xcb_im_send_frame(im, client, reply_frame, true);
}
void _xcb_im_parse_ic_value(xcb_im_t *im, xcb_im_input_context_t *ic, void *p,
const xcb_im_default_ic_attr_t *icattr,
uint8_t *data, size_t length) {
switch (icattr->type) {
case XimType_CARD32:
case XimType_Window: {
uint32_t *result = p;
uint32_t_read(result, &data, &length,
im->byte_order != ic->client->byte_order);
break;
}
case XimType_XRectangle: {
xcb_rectangle_t *result = p;
xcb_im_xrectangle_fr_t fr;
_xcb_im_read_frame(im, ic->client, fr, data, length);
result->x = fr.x;
result->y = fr.y;
result->height = fr.height;
result->width = fr.width;
break;
}
case XimType_XPoint: {
xcb_point_t *result = p;
xcb_im_xpoint_fr_t fr;
_xcb_im_read_frame(im, ic->client, fr, data, length);
result->x = fr.x;
result->y = fr.y;
break;
}
case XimType_XFontSet: {
break;
}
}
}
void _xcb_im_parse_nested_ic_values(xcb_im_t *im, xcb_im_input_context_t *ic,
void *p, uint32_t *mask, ssize_t *offsets,
uint32_t *masks, uint8_t *data,
size_t length) {
while (length != 0) {
xcb_im_xicattribute_fr_t fr;
xcb_im_xicattribute_fr_read(&fr, &data, &length,
im->byte_order != ic->client->byte_order);
if (!data) {
return;
}
if (fr.attribute_ID >= ARRAY_SIZE(im->id2attr)) {
continue;
}
const xcb_im_default_ic_attr_t *entry =
_xcb_im_default_ic_attr_entry(im, fr.attribute_ID);
if (!entry || offsets[fr.attribute_ID] < 0) {
continue;
}
*mask |= masks[fr.attribute_ID];
_xcb_im_parse_ic_value(im, ic,
(((uint8_t *)p) + offsets[fr.attribute_ID]),
entry, fr.value, fr.value_length);
}
}
void _xcb_im_parse_ic_values(xcb_im_t *im, xcb_im_input_context_t *ic,
uint32_t nAttr,
xcb_im_xicattribute_fr_t *icattrs) {
for (uint32_t i = 0; i < nAttr; i++) {
if (icattrs[i].attribute_ID == im->separatorAttr_id) {
continue;
}
if (icattrs[i].attribute_ID == im->statusAttr_id) {
_xcb_im_parse_nested_ic_values(
im, ic, &ic->status, &ic->status_mask, im->id2statusoffset,
im->id2statusmask, icattrs[i].value, icattrs[i].value_length);
} else if (icattrs[i].attribute_ID == im->preeditAttr_id) {
_xcb_im_parse_nested_ic_values(
im, ic, &ic->preedit, &ic->preedit_mask, im->id2preeditoffset,
im->id2preeditmask, icattrs[i].value, icattrs[i].value_length);
} else {
const xcb_im_default_ic_attr_t *entry =
_xcb_im_default_ic_attr_entry(im, icattrs[i].attribute_ID);
if (!entry || im->id2icoffset[icattrs[i].attribute_ID] < 0) {
continue;
}
_xcb_im_parse_ic_value(
im, ic,
(((uint8_t *)ic) + im->id2icoffset[icattrs[i].attribute_ID]),
entry, icattrs[i].value, icattrs[i].value_length);
}
}
}
void _xcb_im_handle_create_ic(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_create_ic_fr_t frame;
_xcb_im_read_frame_with_error(im, client, frame, data,
XIM_MESSAGE_BYTES(hdr));
do {
if (frame.input_method_ID != client->connect_id) {
break;
}
xcb_im_input_context_t *ic = _xcb_im_new_input_context(im, client);
if (!ic) {
break;
}
_xcb_im_parse_ic_values(im, ic, frame.ic_attributes.size,
frame.ic_attributes.items);
xcb_im_create_ic_reply_fr_t reply_frame;
reply_frame.input_method_ID = client->connect_id;
reply_frame.input_context_ID = ic->id;
if (im->callback) {
im->callback(im, client, ic, hdr, &frame, &reply_frame,
im->user_data);
}
_xcb_im_send_frame(im, client, reply_frame, true);
if (!_xcb_im_has_trigger_key(im)) {
_xcb_im_set_ic_event_mask(im, ic);
}
xcb_im_create_ic_fr_free(&frame);
return;
} while (0);
// error
xcb_im_create_ic_fr_free(&frame);
_xcb_im_send_error_message(im, client);
}
void _xcb_im_handle_destroy_ic(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_destroy_ic_fr_t frame;
_xcb_im_read_frame_with_error(im, client, frame, data,
XIM_MESSAGE_BYTES(hdr));
do {
if (frame.input_method_ID != client->connect_id) {
break;
}
xcb_im_input_context_t *ic = NULL;
HASH_FIND(hh, client->input_contexts, &frame.input_context_ID,
sizeof(uint16_t), ic);
if (!ic) {
break;
}
xcb_im_destroy_ic_reply_fr_t reply_frame;
reply_frame.input_method_ID = client->connect_id;
reply_frame.input_context_ID = frame.input_context_ID;
xcb_im_destroy_ic_fr_free(&frame);
_xcb_im_destroy_ic(im, ic);
_xcb_im_send_frame(im, client, reply_frame, true);
return;
} while (0);
// error
xcb_im_destroy_ic_fr_free(&frame);
_xcb_im_send_error_message(im, client);
}
void _xcb_im_handle_set_ic_values(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_set_ic_values_fr_t frame;
_xcb_im_read_frame_with_error(im, client, frame, data,
XIM_MESSAGE_BYTES(hdr));
do {
if (frame.input_method_ID != client->connect_id) {
break;
}
xcb_im_input_context_t *ic = NULL;
HASH_FIND(hh, client->input_contexts, &frame.input_context_ID,
sizeof(uint16_t), ic);
if (!ic) {
break;
}
_xcb_im_parse_ic_values(im, ic, frame.ic_attribute.size,
frame.ic_attribute.items);
if (im->callback) {
im->callback(im, client, ic, hdr, &frame, NULL, im->user_data);
}
xcb_im_set_ic_values_fr_free(&frame);
xcb_im_set_ic_values_reply_fr_t reply_frame;
reply_frame.input_method_ID = client->connect_id;
reply_frame.input_context_ID = frame.input_context_ID;
_xcb_im_send_frame(im, client, reply_frame, true);
return;
} while (0);
// error
xcb_im_set_ic_values_fr_free(&frame);
_xcb_im_send_error_message(im, client);
}
uint32_t _xcb_im_get_nested_ic_values(xcb_im_t *im, xcb_im_input_context_t *ic,
void *p, ssize_t *offsets,
uint16_t *attrIDs, uint32_t i,
uint32_t size,
xcb_im_xicattribute_fr_t *attr) {
size_t totalSize = 0;
uint8_t *data = NULL;
uint32_t start = i;
for (int round = 0; round < 2; round++) {
i = start;
while (i < size && attrIDs[i] != im->separatorAttr_id) {
uint16_t attrID = attrIDs[i];
i++;
const xcb_im_default_ic_attr_t *entry =
_xcb_im_default_ic_attr_entry(im, attrID);
if (!entry || !entry->read || offsets[attrID] < 0) {
continue;
}
// calculate size
if (round == 0) {
xcb_im_xicattribute_fr_t fr;
fr.value_length = _xcb_im_ic_attr_size(entry->type);
totalSize += xcb_im_xicattribute_fr_size(&fr);
} else {
uint8_t *start = data;
uint16_t value_length = _xcb_im_ic_attr_size(entry->type);
bool swap = im->byte_order != ic->client->byte_order;
data = uint16_t_write(&attrID, data, swap);
data = uint16_t_write(&value_length, data, swap);
data = _xcb_im_get_ic_value((((uint8_t *)p) + offsets[attrID]),
entry->type, data, swap);
data =
(uint8_t *)align_to_4((uintptr_t)data, data - start, NULL);
}
}
if (round == 0) {
data = malloc(totalSize);
if (!data) {
break;
}
attr->value_length = totalSize;
attr->value = data;
}
}
return i;
}
void _xcb_im_handle_get_ic_values(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_get_ic_values_fr_t frame;
_xcb_im_read_frame_with_error(im, client, frame, data,
XIM_MESSAGE_BYTES(hdr));
do {
if (frame.input_method_ID != client->connect_id) {
break;
}
xcb_im_input_context_t *ic = NULL;
HASH_FIND(hh, client->input_contexts, &frame.input_context_ID,
sizeof(uint16_t), ic);
if (!ic) {
break;
}
if (im->callback) {
im->callback(im, client, ic, hdr, &frame, NULL, im->user_data);
}
xcb_im_get_ic_values_reply_fr_t reply_frame;
reply_frame.input_method_ID = client->connect_id;
reply_frame.input_context_ID = frame.input_context_ID;
reply_frame.ic_attribute.size = 0;
uint32_t nBuffers = 0;
xcb_im_xicattribute_fr_t buffers[ARRAY_SIZE(Default_ICattr)];
memset(buffers, 0, sizeof(buffers));
uint32_t i = 0;
while (i < frame.ic_attribute.size) {
buffers[nBuffers].attribute_ID = frame.ic_attribute.items[i];
if (frame.ic_attribute.items[i] == im->statusAttr_id) {
i = _xcb_im_get_nested_ic_values(
im, ic, &ic->status, im->id2statusoffset,
frame.ic_attribute.items, i + 1, frame.ic_attribute.size,
&buffers[nBuffers]);
} else if (frame.ic_attribute.items[i] == im->preeditAttr_id) {
i = _xcb_im_get_nested_ic_values(
im, ic, &ic->preedit, im->id2preeditoffset,
frame.ic_attribute.items, i + 1, frame.ic_attribute.size,
&buffers[nBuffers]);
} else {
const xcb_im_default_ic_attr_t *entry =
_xcb_im_default_ic_attr_entry(im,
frame.ic_attribute.items[i]);
i++;
if (!entry) {
continue;
}
if (strcmp(entry->name, XCB_XIM_XNFilterEvents) == 0) {
uint32_t result =
XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE;
buffers[nBuffers].value = malloc(sizeof(uint32_t));
buffers[nBuffers].value_length = sizeof(uint32_t);
if (data) {
uint32_t_write(&result, buffers[nBuffers].value,
im->byte_order !=
ic->client->byte_order);
}
}
}
if (buffers[nBuffers].value) {
nBuffers++;
}
}
reply_frame.ic_attribute.size = nBuffers;
reply_frame.ic_attribute.items = buffers;
xcb_im_get_ic_values_fr_free(&frame);
_xcb_im_send_frame(im, client, reply_frame, true);
for (uint32_t i = 0; i < nBuffers; i++) {
free(buffers[i].value);
}
return;
} while (0);
// error
xcb_im_get_ic_values_fr_free(&frame);
_xcb_im_send_error_message(im, client);
}
void _xcb_im_handle_set_ic_focus(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_set_ic_focus_fr_t frame;
_xcb_im_read_frame_with_error(im, client, frame, data,
XIM_MESSAGE_BYTES(hdr));
do {
if (client->connect_id != frame.input_method_ID) {
break;
}
xcb_im_input_context_t *ic = NULL;
HASH_FIND(hh, client->input_contexts, &frame.input_context_ID,
sizeof(uint16_t), ic);
if (!ic) {
break;
}
if (!_xcb_im_has_trigger_key(im)) {
_xcb_im_set_ic_event_mask(im, ic);
}
if (im->callback) {
im->callback(im, client, ic, hdr, &frame, NULL, im->user_data);
}
} while (0);
xcb_im_set_ic_focus_fr_free(&frame);
}
void _xcb_im_handle_unset_ic_focus(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_unset_ic_focus_fr_t frame;
_xcb_im_read_frame_with_error(im, client, frame, data,
XIM_MESSAGE_BYTES(hdr));
do {
if (client->connect_id != frame.input_method_ID) {
break;
}
xcb_im_input_context_t *ic = NULL;
HASH_FIND(hh, client->input_contexts, &frame.input_context_ID,
sizeof(uint16_t), ic);
if (!ic) {
break;
}
if (im->callback) {
im->callback(im, client, ic, hdr, &frame, NULL, im->user_data);
}
} while (0);
xcb_im_unset_ic_focus_fr_free(&frame);
}
void _xcb_im_handle_preedit_caret_reply(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_preedit_caret_reply_fr_t frame;
_xcb_im_read_frame_with_error(im, client, frame, data,
XIM_MESSAGE_BYTES(hdr));
do {
if (client->connect_id != frame.input_method_ID) {
break;
}
xcb_im_input_context_t *ic = NULL;
HASH_FIND(hh, client->input_contexts, &frame.input_context_ID,
sizeof(uint16_t), ic);
if (!ic) {
break;
}
if (im->callback) {
im->callback(im, client, ic, hdr, &frame, NULL, im->user_data);
}
} while (0);
xcb_im_preedit_caret_reply_fr_free(&frame);
}
void _xcb_im_handle_reset_ic(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_reset_ic_fr_t frame;
_xcb_im_read_frame_with_error(im, client, frame, data,
XIM_MESSAGE_BYTES(hdr));
do {
if (client->connect_id != frame.input_method_ID) {
break;
}
xcb_im_input_context_t *ic = NULL;
HASH_FIND(hh, client->input_contexts, &frame.input_context_ID,
sizeof(uint16_t), ic);
if (!ic) {
break;
}
xcb_im_reset_ic_reply_fr_t reply_frame;
reply_frame.input_method_ID = frame.input_method_ID;
reply_frame.input_context_ID = frame.input_context_ID;
reply_frame.committed_string = NULL;
reply_frame.byte_length_of_committed_string = 0;
if (im->callback) {
im->callback(im, client, ic, hdr, &frame, &reply_frame,
im->user_data);
}
_xcb_im_send_frame(im, client, reply_frame, true);
free(reply_frame.committed_string);
} while (0);
xcb_im_reset_ic_fr_free(&frame);
}
void _xcb_im_handle_forward_event(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_forward_event_fr_t frame;
_xcb_im_read_frame_with_error(im, client, frame, data,
XIM_MESSAGE_BYTES(hdr));
do {
if (client->connect_id != frame.input_method_ID) {
break;
}
if (XIM_MESSAGE_BYTES(hdr) < xcb_im_forward_event_fr_size(&frame) +
sizeof(xcb_key_press_event_t)) {
break;
}
xcb_im_input_context_t *ic = NULL;
HASH_FIND(hh, client->input_contexts, &frame.input_context_ID,
sizeof(uint16_t), ic);
if (!ic) {
break;
}
ic->forward_event_sequence = frame.sequence_number;
if (client->sync) {
_xcb_im_add_queue(im, client, ic->id, hdr, &frame, data);
} else {
xcb_key_press_event_t key_event;
memcpy(&key_event, data, sizeof(xcb_key_press_event_t));
if (im->callback) {
im->callback(im, client, ic, hdr, &frame, &key_event,
im->user_data);
}
if (im->use_sync_event) {
xcb_im_sync_reply_fr_t reply_frame;
reply_frame.input_method_ID = frame.input_method_ID;
reply_frame.input_context_ID = frame.input_context_ID;
_xcb_im_send_frame(im, client, reply_frame, true);
}
}
} while (0);
xcb_im_forward_event_fr_free(&frame);
}
void _xcb_im_handle_ext_forward_keyevent(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_ext_forward_keyevent_fr_t frame;
_xcb_im_read_frame_with_error(im, client, frame, data,
XIM_MESSAGE_BYTES(hdr));
do {
if (client->connect_id != frame.input_method_ID) {
break;
}
xcb_im_input_context_t *ic = NULL;
HASH_FIND(hh, client->input_contexts, &frame.input_context_ID,
sizeof(uint16_t), ic);
if (!ic) {
break;
}
xcb_key_press_event_t key_event;
memset(&key_event, 0, sizeof(key_event));
key_event.response_type = frame.xEvent_u_u_type;
key_event.sequence = frame.sequence_number;
key_event.root = im->default_screen->root;
key_event.time = frame.time;
key_event.detail = frame.keycode;
key_event.state = frame.state;
key_event.event = frame.window;
if (im->callback) {
im->callback(im, client, ic, hdr, &frame, &key_event,
im->user_data);
}
} while (0);
xcb_im_ext_forward_keyevent_fr_free(&frame);
}
void _xcb_im_handle_ext_move(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_ext_move_fr_t frame;
_xcb_im_read_frame_with_error(im, client, frame, data,
XIM_MESSAGE_BYTES(hdr));
do {
if (client->connect_id != frame.input_method_ID) {
break;
}
xcb_im_input_context_t *ic = NULL;
HASH_FIND(hh, client->input_contexts, &frame.input_context_ID,
sizeof(uint16_t), ic);
if (!ic) {
break;
}
ic->preedit.spot_location.x = frame.X;
ic->preedit.spot_location.y = frame.Y;
} while (0);
xcb_im_ext_move_fr_free(&frame);
}
void _xcb_im_handle_extension(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
switch (hdr->minor_opcode) {
case XCB_XIM_EXT_FORWARD_KEYEVENT:
_xcb_im_handle_ext_forward_keyevent(im, client, hdr, data);
break;
case XCB_XIM_EXT_MOVE:
_xcb_im_handle_ext_move(im, client, hdr, data);
break;
}
}
void _xcb_im_handle_sync_reply(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_sync_reply_fr_t frame;
_xcb_im_read_frame_with_error(im, client, frame, data,
XIM_MESSAGE_BYTES(hdr));
do {
if (client->connect_id != frame.input_method_ID) {
break;
}
xcb_im_input_context_t *ic = NULL;
HASH_FIND(hh, client->input_contexts, &frame.input_context_ID,
sizeof(uint16_t), ic);
if (!ic) {
break;
}
client->sync = false;
if (im->sync) {
im->sync = false;
if (im->callback) {
im->callback(im, client, ic, hdr, &frame, NULL, im->user_data);
}
}
_xcb_im_process_queue(im, client);
} while (0);
xcb_im_sync_reply_fr_free(&frame);
}
void _xcb_im_handle_trigger_notify(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_trigger_notify_fr_t frame;
_xcb_im_read_frame_with_error(im, client, frame, data,
XIM_MESSAGE_BYTES(hdr));
do {
if (client->connect_id != frame.input_method_ID) {
break;
}
xcb_im_input_context_t *ic = NULL;
HASH_FIND(hh, client->input_contexts, &frame.input_context_ID,
sizeof(uint16_t), ic);
if (!ic) {
break;
}
xcb_im_trigger_notify_reply_fr_t reply_frame;
reply_frame.input_method_ID = frame.input_method_ID;
reply_frame.input_context_ID = frame.input_context_ID;
/* NOTE:
* XIM_TRIGGER_NOTIFY_REPLY should be sent before XIM_SET_EVENT_MASK
* in case of XIM_TRIGGER_NOTIFY(flag == ON), while it should be
* sent after XIM_SET_EVENT_MASK in case of
* XIM_TRIGGER_NOTIFY(flag == OFF).
*/
if (frame.flag == 0) {
_xcb_im_send_frame(im, client, reply_frame, false);
xcb_im_preedit_start(im, ic);
}
if (im->callback) {
im->callback(im, client, ic, hdr, &frame, NULL, im->user_data);
}
if (frame.flag == 1) {
xcb_im_preedit_end(im, ic);
_xcb_im_send_frame(im, client, reply_frame, false);
}
} while (0);
xcb_im_trigger_notify_fr_free(&frame);
}
void _xcb_im_handle_preedit_start_reply(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_preedit_start_reply_fr_t frame;
_xcb_im_read_frame_with_error(im, client, frame, data,
XIM_MESSAGE_BYTES(hdr));
do {
if (client->connect_id != frame.input_method_ID) {
break;
}
xcb_im_input_context_t *ic = NULL;
HASH_FIND(hh, client->input_contexts, &frame.input_context_ID,
sizeof(uint16_t), ic);
if (!ic) {
break;
}
if (im->callback) {
im->callback(im, client, ic, hdr, &frame, NULL, im->user_data);
}
} while (0);
xcb_im_preedit_start_reply_fr_free(&frame);
}

View File

@ -0,0 +1,93 @@
/*
* SPDX-FileCopyrightText: 2014 Weng Xuetian <wengxt@gmail.com>
*
* SPDX-License-Identifier: LGPL-2.1-only
*
*/
#ifndef PROTOCOLHANDLER_H
#define PROTOCOLHANDLER_H
#include "imdkit.h"
#include "ximproto.h"
#include <stdint.h>
void _xcb_im_handle_connect(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_im_handle_open(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr, uint8_t *data);
void _xcb_im_handle_close(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr, uint8_t *data);
void _xcb_im_handle_query_extension(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_im_handle_encoding_negotiation(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_im_handle_get_im_values(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_im_handle_disconnect(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_im_handle_create_ic(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_im_handle_destroy_ic(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_im_handle_set_ic_values(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_im_handle_get_ic_values(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_im_handle_set_ic_focus(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_im_handle_unset_ic_focus(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_im_handle_preedit_caret_reply(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_im_handle_reset_ic(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_im_handle_forward_event(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_im_handle_extension(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_im_handle_sync_reply(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_im_handle_trigger_notify(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
void _xcb_im_handle_preedit_start_reply(xcb_im_t *im, xcb_im_client_t *client,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data);
#endif // PROTOCOLHANDLER_H

View File

@ -0,0 +1,10 @@
prefix=@CMAKE_INSTALL_PREFIX@
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
Name: xcb-imdkit
Description: X input method support for XCB
Version: @XCB_IMDKIT_VERSION@
Requires: xcb xcb-util
Cflags: -I${includedir}
Libs: -L${libdir} -lxcb-imdkit

View File

@ -0,0 +1,7 @@
#ifndef XCBIMDKIT_EXPORT_H
#define XCBIMDKIT_EXPORT_H
#define XCBIMDKIT_EXPORT
#define XCBIMDKIT_DEPRECATED
#endif

View File

@ -0,0 +1,29 @@
/*
* SPDX-FileCopyrightText: 2016 Weng Xuetian <wengxt@gmail.com>
*
* SPDX-License-Identifier: LGPL-2.1-only
*
*/
#ifndef XIMCOMMON_H
#define XIMCOMMON_H
#include "xcbimdkit_export.h"
#ifndef XCBIMDKIT_DECL_BEGIN
#ifdef __cplusplus
#define XCBIMDKIT_DECL_BEGIN extern "C" {
#else
#define XCBIMDKIT_DECL_BEGIN
#endif
#endif
#ifndef XCBIMDKIT_DECL_END
#ifdef __cplusplus
#define XCBIMDKIT_DECL_END }
#else
#define XCBIMDKIT_DECL_END
#endif
#endif
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,166 @@
/*
* SPDX-FileCopyrightText: 2014 Weng Xuetian <wengxt@gmail.com>
*
* SPDX-License-Identifier: LGPL-2.1-only
*
*/
#ifndef XIMPROTO_H
#define XIMPROTO_H
#include "ximcommon.h"
#include "ximproto-gen.h" // IWYU pragma: export
#include <stdint.h>
XCBIMDKIT_DECL_BEGIN
#define XCB_IM_HEADER_SIZE 4
/*
* Client Message data size
*/
#define XCB_XIM_CM_DATA_SIZE 20
/*
* Xim implementation revision
*/
#define XCB_XIM_PROTOCOLMAJORVERSION 0
#define XCB_XIM_PROTOCOLMINORVERSION 0
/*
* Major Protocol number
*/
#define XCB_XIM_CONNECT 1
#define XCB_XIM_CONNECT_REPLY 2
#define XCB_XIM_DISCONNECT 3
#define XCB_XIM_DISCONNECT_REPLY 4
#define XCB_XIM_AUTH_REQUIRED 10
#define XCB_XIM_AUTH_REPLY 11
#define XCB_XIM_AUTH_NEXT 12
#define XCB_XIM_AUTH_SETUP 13
#define XCB_XIM_AUTH_NG 14
#define XCB_XIM_ERROR 20
#define XCB_XIM_OPEN 30
#define XCB_XIM_OPEN_REPLY 31
#define XCB_XIM_CLOSE 32
#define XCB_XIM_CLOSE_REPLY 33
#define XCB_XIM_REGISTER_TRIGGERKEYS 34
#define XCB_XIM_TRIGGER_NOTIFY 35
#define XCB_XIM_TRIGGER_NOTIFY_REPLY 36
#define XCB_XIM_SET_EVENT_MASK 37
#define XCB_XIM_ENCODING_NEGOTIATION 38
#define XCB_XIM_ENCODING_NEGOTIATION_REPLY 39
#define XCB_XIM_QUERY_EXTENSION 40
#define XCB_XIM_QUERY_EXTENSION_REPLY 41
#define XCB_XIM_SET_IM_VALUES 42
#define XCB_XIM_SET_IM_VALUES_REPLY 43
#define XCB_XIM_GET_IM_VALUES 44
#define XCB_XIM_GET_IM_VALUES_REPLY 45
#define XCB_XIM_CREATE_IC 50
#define XCB_XIM_CREATE_IC_REPLY 51
#define XCB_XIM_DESTROY_IC 52
#define XCB_XIM_DESTROY_IC_REPLY 53
#define XCB_XIM_SET_IC_VALUES 54
#define XCB_XIM_SET_IC_VALUES_REPLY 55
#define XCB_XIM_GET_IC_VALUES 56
#define XCB_XIM_GET_IC_VALUES_REPLY 57
#define XCB_XIM_SET_IC_FOCUS 58
#define XCB_XIM_UNSET_IC_FOCUS 59
#define XCB_XIM_FORWARD_EVENT 60
#define XCB_XIM_SYNC 61
#define XCB_XIM_SYNC_REPLY 62
#define XCB_XIM_COMMIT 63
#define XCB_XIM_RESET_IC 64
#define XCB_XIM_RESET_IC_REPLY 65
#define XCB_XIM_GEOMETRY 70
#define XCB_XIM_STR_CONVERSION 71
#define XCB_XIM_STR_CONVERSION_REPLY 72
#define XCB_XIM_PREEDIT_START 73
#define XCB_XIM_PREEDIT_START_REPLY 74
#define XCB_XIM_PREEDIT_DRAW 75
#define XCB_XIM_PREEDIT_CARET 76
#define XCB_XIM_PREEDIT_CARET_REPLY 77
#define XCB_XIM_PREEDIT_DONE 78
#define XCB_XIM_STATUS_START 79
#define XCB_XIM_STATUS_DRAW 80
#define XCB_XIM_STATUS_DONE 81
typedef enum {
XCB_XIM_SYNCHRONOUS = (1 << 0),
XCB_XIM_LOOKUP_CHARS = (1 << 1),
XCB_XIM_LOOKUP_KEYSYM = (1 << 2),
XCB_XIM_LOOKUP_BOTH = XCB_XIM_LOOKUP_CHARS | XCB_XIM_LOOKUP_KEYSYM,
} xcb_xim_lookup_flags_t;
typedef struct _xcb_im_ext_list {
char *name;
uint8_t major_opcode;
uint8_t minor_opcode;
} xcb_im_ext_list;
/*
* Minor Protocol Number for Extension Protocol
*/
#define XCB_XIM_EXTENSION 128
#define XCB_XIM_EXT_SET_EVENT_MASK (0x30)
#define XCB_XIM_EXT_FORWARD_KEYEVENT (0x32)
#define XCB_XIM_EXT_MOVE (0x33)
#define XCB_XIM_XNQueryInputStyle "queryInputStyle"
#define XCB_XIM_XNClientWindow "clientWindow"
#define XCB_XIM_XNInputStyle "inputStyle"
#define XCB_XIM_XNFocusWindow "focusWindow"
#define XCB_XIM_XNFilterEvents "filterEvents"
#define XCB_XIM_XNPreeditAttributes "preeditAttributes"
#define XCB_XIM_XNStatusAttributes "statusAttributes"
#define XCB_XIM_XNArea "area"
#define XCB_XIM_XNAreaNeeded "areaNeeded"
#define XCB_XIM_XNSpotLocation "spotLocation"
#define XCB_XIM_XNColormap "colorMap"
#define XCB_XIM_XNStdColormap "stdColorMap"
#define XCB_XIM_XNForeground "foreground"
#define XCB_XIM_XNBackground "background"
#define XCB_XIM_XNBackgroundPixmap "backgroundPixmap"
#define XCB_XIM_XNFontSet "fontSet"
#define XCB_XIM_XNLineSpace "lineSpace"
#define XCB_XIM_XNSeparatorofNestedList "separatorofNestedList"
typedef enum _xcb_im_style_t {
XCB_IM_PreeditArea = 0x0001,
XCB_IM_PreeditCallbacks = 0x0002,
XCB_IM_PreeditPosition = 0x0004,
XCB_IM_PreeditNothing = 0x0008,
XCB_IM_PreeditNone = 0x0010,
XCB_IM_StatusArea = 0x0100,
XCB_IM_StatusCallbacks = 0x0200,
XCB_IM_StatusNothing = 0x0400,
XCB_IM_StatusNone = 0x0800,
} xcb_im_style_t;
enum { XCB_IM_TextType = 0, XCB_IM_BitmapType = 1 };
typedef enum {
XCB_XIM_REVERSE = (1 << 0),
XCB_XIM_UNDERLINE = (1 << 1),
XCB_XIM_HIGHLIGHT = (1 << 2),
XCB_XIM_PRIMARY = (1 << 5),
XCB_XIM_SECONDARY = (1 << 6),
XCB_XIM_TERTIARY = (1 << 7),
XCB_XIM_VISIBLE_TO_FORWARD = (1 << 8),
XCB_XIM_VISIBLE_TO_BACKWORD = (1 << 9),
XCB_XIM_VISIBLE_TO_CENTER = (1 << 10),
} xcb_im_feedback_t;
typedef struct _xcb_im_trigger_keys_t {
uint16_t nKeys;
xcb_im_ximtriggerkey_fr_t *keys;
} xcb_im_trigger_keys_t;
XCBIMDKIT_DECL_END
#endif // XIMPROTO_H

View File

@ -0,0 +1,58 @@
/*
* SPDX-FileCopyrightText: 2017 Weng Xuetian <wengxt@gmail.com>
*
* SPDX-License-Identifier: LGPL-2.1-only
*
*/
#ifndef _XCB_IMDKIT_XIMPROTO_P_H_
#define _XCB_IMDKIT_XIMPROTO_P_H_
#define XIM_PROTO_FRAME_OPCODE(FRAME) \
_Generic((FRAME), \
xcb_im_connect_reply_fr_t: XCB_XIM_CONNECT_REPLY, \
xcb_im_open_fr_t: XCB_XIM_OPEN, \
xcb_im_open_reply_fr_t: XCB_XIM_OPEN_REPLY, \
xcb_im_close_fr_t: XCB_XIM_CLOSE, \
xcb_im_close_reply_fr_t: XCB_XIM_CLOSE_REPLY, \
xcb_im_query_extension_fr_t: XCB_XIM_QUERY_EXTENSION, \
xcb_im_query_extension_reply_fr_t: XCB_XIM_QUERY_EXTENSION_REPLY, \
xcb_im_encoding_negotiation_fr_t: XCB_XIM_ENCODING_NEGOTIATION, \
xcb_im_encoding_negotiation_reply_fr_t: XCB_XIM_ENCODING_NEGOTIATION_REPLY, \
xcb_im_get_im_values_fr_t: XCB_XIM_GET_IM_VALUES, \
xcb_im_get_im_values_reply_fr_t: XCB_XIM_GET_IM_VALUES_REPLY, \
xcb_im_set_event_mask_fr_t: XCB_XIM_SET_EVENT_MASK, \
xcb_im_create_ic_fr_t: XCB_XIM_CREATE_IC, \
xcb_im_create_ic_reply_fr_t: XCB_XIM_CREATE_IC_REPLY, \
xcb_im_set_ic_values_fr_t: XCB_XIM_SET_IC_VALUES, \
xcb_im_set_ic_values_reply_fr_t: XCB_XIM_SET_IC_VALUES_REPLY, \
xcb_im_get_ic_values_fr_t: XCB_XIM_GET_IC_VALUES, \
xcb_im_get_ic_values_reply_fr_t: XCB_XIM_GET_IC_VALUES_REPLY, \
xcb_im_register_triggerkeys_fr_t: XCB_XIM_REGISTER_TRIGGERKEYS, \
xcb_im_destroy_ic_fr_t: XCB_XIM_DESTROY_IC, \
xcb_im_destroy_ic_reply_fr_t: XCB_XIM_DESTROY_IC_REPLY, \
xcb_im_reset_ic_fr_t: XCB_XIM_RESET_IC, \
xcb_im_reset_ic_reply_fr_t: XCB_XIM_RESET_IC_REPLY, \
xcb_im_trigger_notify_fr_t: XCB_XIM_TRIGGER_NOTIFY, \
xcb_im_trigger_notify_reply_fr_t: XCB_XIM_TRIGGER_NOTIFY_REPLY, \
xcb_im_preedit_start_fr_t: XCB_XIM_PREEDIT_START, \
xcb_im_preedit_draw_fr_t: XCB_XIM_PREEDIT_DRAW, \
xcb_im_preedit_caret_fr_t: XCB_XIM_PREEDIT_CARET, \
xcb_im_preedit_done_fr_t: XCB_XIM_PREEDIT_DONE, \
xcb_im_status_start_fr_t: XCB_XIM_STATUS_START, \
xcb_im_status_draw_text_fr_t: XCB_XIM_STATUS_DRAW, \
xcb_im_status_draw_bitmap_fr_t: XCB_XIM_STATUS_DRAW, \
xcb_im_status_done_fr_t: XCB_XIM_STATUS_DONE, \
xcb_im_commit_chars_fr_t: XCB_XIM_COMMIT, \
xcb_im_commit_both_fr_t: XCB_XIM_COMMIT, \
xcb_im_connect_fr_t: XCB_XIM_CONNECT, \
xcb_im_disconnect_fr_t: XCB_XIM_DISCONNECT, \
xcb_im_disconnect_reply_fr_t: XCB_XIM_DISCONNECT_REPLY, \
xcb_im_set_ic_focus_fr_t: XCB_XIM_SET_IC_FOCUS, \
xcb_im_unset_ic_focus_fr_t: XCB_XIM_UNSET_IC_FOCUS, \
xcb_im_sync_fr_t: XCB_XIM_SYNC, \
xcb_im_sync_reply_fr_t: XCB_XIM_SYNC_REPLY, \
xcb_im_geometry_fr_t: XCB_XIM_GEOMETRY)
#define XCB_XIM_ATOM_ROTATION_SIZE 1024
#endif // _XCB_IMDKIT_XIMPROTO_P_H_

View File

@ -0,0 +1,91 @@
/*
* Copyright 1992, 1993 by TOSHIBA Corp.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of TOSHIBA not be used in advertising
* or publicity pertaining to distribution of the software without specific,
* written prior permission. TOSHIBA make no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* TOSHIBA DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
* TOSHIBA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
* ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
* WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*
* Author: Katsuhisa Yano TOSHIBA Corp.
* mopi@osa.ilab.toshiba.co.jp
*/
#ifndef _XLCPUBLICI_H_
#define _XLCPUBLICI_H_
#include "XlcPublic.h" // IWYU pragma: export
/* Fills into a freshly created XlcCharSet the fields that can be inferred
from the ESC sequence. These are side, char_size, set_size. */
extern bool _XlcParseCharSet(
XlcCharSet charset
);
/* Creates a new XlcCharSet, given its name (including side suffix) and
Compound Text ESC sequence (normally at most 4 bytes). */
extern XlcCharSet _XlcCreateDefaultCharSet(
const char* name,
const char* ct_sequence
);
extern XlcCharSet _XlcAddCT(
const char* name,
const char* ct_sequence
);
extern bool _XlcInitCTInfo (void);
extern void
init_state(State state);
extern int
utf8tocs(
State state,
void **from,
size_t *from_left,
void **to,
size_t *to_left,
XlcCharSet* p_charset);
extern int
cstoct(
State state,
void * *from,
size_t *from_left,
void * *to,
size_t *to_left,
XlcCharSet charset);
extern int
cttocs(
State state,
void * *from,
size_t *from_left,
void * *to,
size_t *to_left,
XlcCharSet *p_charset);
extern int
cstoutf8(
State state,
void * *from,
size_t *from_left,
void * *to,
size_t *to_left,
XlcCharSet charset);
#endif /* _XLCPUBLICI_H_ */

View File

@ -0,0 +1,124 @@
/*
* Copyright 1992, 1993 by TOSHIBA Corp.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of TOSHIBA not be used in advertising
* or publicity pertaining to distribution of the software without specific,
* written prior permission. TOSHIBA make no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* TOSHIBA DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
* TOSHIBA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
* ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
* WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*
* Author: Katsuhisa Yano TOSHIBA Corp.
* mopi@osa.ilab.toshiba.co.jp
*/
/*
* Copyright 1995 by FUJITSU LIMITED
* This is source code modified by FUJITSU LIMITED under the Joint
* Development Agreement for the CDE/Motif PST.
*
* Modifier: Takanori Tateno FUJITSU LIMITED
*
*/
/*
* Most of this API is documented in i18n/Framework.PS
*/
#ifndef _XLCPUBLIC_H_
#define _XLCPUBLIC_H_
#include <stdbool.h>
/*
* Character sets.
*/
/* Every character set has a "side". It denotes the range of byte values for
which the character set is responsible. This means that the character
set's encoded characters will only assumes bytes within the range, and
that the character set can be used simultaneously with another character
set responsible for a disjoint range. */
typedef enum {
XlcUnknown,
XlcC0, /* responsible for values 0x00..0x1F */
XlcGL, /* responsible for values 0x00..0x7F or 0x20..0x7F */
XlcC1, /* responsible for values 0x80..0x9F */
XlcGR, /* responsible for values 0x80..0xFF or 0xA0..0xFF */
XlcGLGR, /* responsible for values 0x00..0xFF */
XlcOther, /* unused */
XlcNONE
} XlcSide;
/* Where the character set comes from. */
typedef enum {
CSsrcUndef, /* unused */
CSsrcStd, /* defined in libX11 */
CSsrcXLC /* defined in an XLC_LOCALE file */
} CSSrc;
/* This is the structure of an XlcCharSet.
Once allocated, they are never freed. */
typedef struct _XlcCharSetRec {
/* Character set name, including side suffix */
const char *name;
/* XLFD encoding name, no side suffix */
const char *encoding_name;
/* Range for which the charset is responsible: XlcGL, XlcGR or XlcGLGR */
XlcSide side;
/* Number of bytes per character. 0 means a varying number (e.g. UTF-8) */
int char_size;
/* Classification of the character set according to ISO-2022 */
int set_size; /* e.g. 94 or 96 */
const char *ct_sequence; /* control sequence of CT */
/* (normally at most 4 bytes) */
/* Description source */
CSSrc source;
} XlcCharSetRec, *XlcCharSet;
/* Returns the charset with the given name (including side suffix).
Returns NULL if not found. */
extern XlcCharSet _XlcGetCharSet(
const char* name
);
/* Returns the charset with the given encoding (no side suffix) and
responsible for at least the given side (XlcGL or XlcGR).
Returns NULL if not found. */
extern XlcCharSet _XlcGetCharSetWithSide(
const char* encoding_name,
XlcSide side
);
/* Registers an XlcCharSet in the list of character sets.
Returns True if successful. */
extern bool _XlcAddCharSet(
XlcCharSet charset
);
/*
* Structure representing the parse state of a Compound Text string.
*/
typedef struct _StateRec {
XlcCharSet charset; /* The charset of the current segment */
XlcCharSet GL_charset; /* The charset responsible for 0x00..0x7F */
XlcCharSet GR_charset; /* The charset responsible for 0x80..0xFF */
XlcCharSet Other_charset; /* != NULL if currently in an other segment */
int ext_seg_left; /* > 0 if currently in an extended segment */
} StateRec, *State;
#endif /* _XLCPUBLIC_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,153 @@
/*
* Copyright 1992, 1993 by TOSHIBA Corp.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of TOSHIBA not be used in advertising
* or publicity pertaining to distribution of the software without specific,
* written prior permission. TOSHIBA make no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* TOSHIBA DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
* TOSHIBA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
* ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
* WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*
* Author: Katsuhisa Yano TOSHIBA Corp.
* mopi@osa.ilab.toshiba.co.jp
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "XlcPublic.h"
#include "XlcPubI.h"
/* The list of all known XlcCharSets. They are identified by their name. */
typedef struct _XlcCharSetListRec {
XlcCharSet charset;
struct _XlcCharSetListRec *next;
} XlcCharSetListRec, *XlcCharSetList;
static XlcCharSetList charset_list = NULL;
/* Returns the charset with the given name (including side suffix).
Returns NULL if not found. */
XlcCharSet
_XlcGetCharSet(
const char *name)
{
XlcCharSetList list;
for (list = charset_list; list; list = list->next) {
if (strcmp(name, list->charset->name) == 0)
return (XlcCharSet) list->charset;
}
return (XlcCharSet) NULL;
}
/* Returns the charset with the given encoding (no side suffix) and
responsible for at least the given side (XlcGL or XlcGR).
Returns NULL if not found. */
XlcCharSet
_XlcGetCharSetWithSide(
const char *encoding_name,
XlcSide side)
{
XlcCharSetList list;
for (list = charset_list; list; list = list->next) {
if (strcmp(list->charset->encoding_name, encoding_name) == 0
&& (list->charset->side == XlcGLGR || list->charset->side == side))
return (XlcCharSet) list->charset;
}
return (XlcCharSet) NULL;
}
/* Registers an XlcCharSet in the list of character sets.
Returns true if successful. */
bool
_XlcAddCharSet(
XlcCharSet charset)
{
XlcCharSetList list;
if (_XlcGetCharSet(charset->name))
return false;
list = malloc(sizeof(XlcCharSetListRec));
if (list == NULL)
return false;
list->charset = charset;
list->next = charset_list;
charset_list = list;
return true;
}
/* Creates a new XlcCharSet, given its name (including side suffix) and
Compound Text ESC sequence (normally at most 4 bytes). */
XlcCharSet
_XlcCreateDefaultCharSet(
const char *name,
const char *ct_sequence)
{
XlcCharSet charset;
int name_len, ct_sequence_len;
const char *colon;
char *tmp;
charset = calloc(1, sizeof(XlcCharSetRec));
if (charset == NULL)
return (XlcCharSet) NULL;
name_len = strlen(name);
ct_sequence_len = strlen(ct_sequence);
/* Fill in name and xrm_name. */
tmp = malloc(name_len + 1 + ct_sequence_len + 1);
if (tmp == NULL) {
free(charset);
return (XlcCharSet) NULL;
}
memcpy(tmp, name, name_len+1);
charset->name = tmp;
/* Fill in encoding_name and xrm_encoding_name. */
if ((colon = strchr(charset->name, ':')) != NULL) {
unsigned int length = colon - charset->name;
char *encoding_tmp = malloc(length + 1);
if (encoding_tmp == NULL) {
free((char *) charset->name);
free(charset);
return (XlcCharSet) NULL;
}
memcpy(encoding_tmp, charset->name, length);
encoding_tmp[length] = '\0';
charset->encoding_name = encoding_tmp;
} else {
charset->encoding_name = charset->name;
}
/* Fill in ct_sequence. */
tmp += name_len + 1;
memcpy(tmp, ct_sequence, ct_sequence_len+1);
charset->ct_sequence = tmp;
/* Fill in side, char_size, set_size. */
if (!_XlcParseCharSet(charset))
/* If ct_sequence is not usable in Compound Text, remove it. */
charset->ct_sequence = "";
return (XlcCharSet) charset;
}

View File

@ -0,0 +1,536 @@
/******************************************************************
Copyright 1993 by SunSoft, Inc.
Copyright 1999-2000 by Bruno Haible
Permission to use, copy, modify, distribute, and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and
that both that copyright notice and this permission notice appear
in supporting documentation, and that the names of SunSoft, Inc. and
Bruno Haible not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission. SunSoft, Inc. and Bruno Haible make no representations
about the suitability of this software for any purpose. It is
provided "as is" without express or implied warranty.
SunSoft Inc. AND Bruno Haible DISCLAIM ALL WARRANTIES WITH REGARD
TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS, IN NO EVENT SHALL SunSoft, Inc. OR Bruno Haible BE LIABLE
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
******************************************************************/
/*
* This file contains:
*
* I. Conversion routines CompoundText/CharSet <--> Unicode/UTF-8.
*
* Used for three purposes:
* 1. The UTF-8 locales, see below.
* 2. Unicode aware applications for which the use of 8-bit character
* sets is an anachronism.
* 3. For conversion from keysym to locale encoding.
*
* II. Conversion files for an UTF-8 locale loader.
* Supports: all locales with codeset UTF-8.
* How: Provides converters for UTF-8.
* Platforms: all systems.
*
* The loader itself is located in lcUTF8.c.
*/
/*
* The conversion from UTF-8 to CompoundText is realized in a very
* conservative way. Recall that CompoundText data is used for inter-client
* communication purposes. We distinguish three classes of clients:
* - Clients which accept only those pieces of CompoundText which belong to
* the character set understood by the current locale.
* (Example: clients which are linked to an older X11 library.)
* - Clients which accept CompoundText with multiple character sets and parse
* it themselves.
* (Example: emacs, xemacs.)
* - Clients which rely entirely on the X{mb,wc}TextPropertyToTextList
* functions for the conversion of CompoundText to their current locale's
* multi-byte/wide-character format.
* For best interoperation, the UTF-8 to CompoundText conversion proceeds as
* follows. For every character, it first tests whether the character is
* representable in the current locale's original (non-UTF-8) character set.
* If not, it goes through the list of predefined character sets for
* CompoundText and tests if the character is representable in that character
* set. If so, it encodes the character using its code within that character
* set. If not, it uses an UTF-8-in-CompoundText encapsulation. Since
* clients of the first and second kind ignore such encapsulated text,
* this encapsulation is kept to a minimum and terminated as early as possible.
*
* In a distant future, when clients of the first and second kind will have
* disappeared, we will be able to stuff UTF-8 data directly in CompoundText
* without first going through the list of predefined character sets.
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "XlcPubI.h"
/* Replacement character for invalid multibyte sequence or wide character. */
#define BAD_WCHAR ((ucs4_t) 0xfffd)
#define BAD_CHAR '?'
/***************************************************************************/
/* Part I: Conversion routines CompoundText/CharSet <--> Unicode/UTF-8.
*
* Note that this code works in any locale. We store Unicode values in
* `ucs4_t' variables, but don't pass them to the user.
*
* This code has to support all character sets that are used for CompoundText,
* nothing more, nothing less. See the table in lcCT.c.
* Since the conversion _to_ CompoundText is likely to need the tables for all
* character sets at once, we don't use dynamic loading (of tables or shared
* libraries through iconv()). Use a fixed set of tables instead.
*
* We use statically computed tables, not dynamically allocated arrays,
* because it's more memory efficient: Different processes using the same
* libX11 shared library share the "text" and read-only "data" sections.
*/
typedef unsigned int ucs4_t;
#define conv_t XlcConv
typedef struct _Utf8ConvRec {
const char *name;
int (* cstowc) (ucs4_t *, unsigned char const *, int);
int (* wctocs) (unsigned char *, ucs4_t, int);
} Utf8ConvRec, *Utf8Conv;
/*
* int xxx_cstowc (XlcConv conv, ucs4_t *pwc, unsigned char const *s, int n)
* converts the byte sequence starting at s to a wide character. Up to n bytes
* are available at s. n is >= 1.
* Result is number of bytes consumed (if a wide character was read),
* or 0 if invalid, or -1 if n too small.
*
* int xxx_wctocs (XlcConv conv, unsigned char *r, ucs4_t wc, int n)
* converts the wide character wc to the character set xxx, and stores the
* result beginning at r. Up to n bytes may be written at r. n is >= 1.
* Result is number of bytes written, or 0 if invalid, or -1 if n too small.
*/
/* Return code if invalid. (xxx_mbtowc, xxx_wctomb) */
#define RET_ILSEQ 0
/* Return code if only a shift sequence of n bytes was read. (xxx_mbtowc) */
#define RET_TOOFEW(n) (-1-(n))
/* Return code if output buffer is too small. (xxx_wctomb, xxx_reset) */
#define RET_TOOSMALL -1
/*
* The tables below are bijective. It would be possible to extend the
* xxx_wctocs tables to do some transliteration (e.g. U+201C,U+201D -> 0x22)
* but *only* with characters not contained in any other table, and *only*
* when the current locale is not an UTF-8 locale.
*/
#include "lcUniConv/utf8.h"
#include "lcUniConv/ucs2be.h"
#ifdef notused
#include "lcUniConv/ascii.h"
#endif
#include "lcUniConv/iso8859_1.h"
#include "lcUniConv/iso8859_2.h"
#include "lcUniConv/iso8859_3.h"
#include "lcUniConv/iso8859_4.h"
#include "lcUniConv/iso8859_5.h"
#include "lcUniConv/iso8859_6.h"
#include "lcUniConv/iso8859_7.h"
#include "lcUniConv/iso8859_8.h"
#include "lcUniConv/iso8859_9.h"
#include "lcUniConv/iso8859_10.h"
#include "lcUniConv/iso8859_11.h"
#include "lcUniConv/iso8859_13.h"
#include "lcUniConv/iso8859_14.h"
#include "lcUniConv/iso8859_15.h"
#include "lcUniConv/iso8859_16.h"
#include "lcUniConv/iso8859_9e.h"
#include "lcUniConv/jisx0201.h"
#include "lcUniConv/tis620.h"
#include "lcUniConv/koi8_r.h"
#include "lcUniConv/koi8_u.h"
#include "lcUniConv/koi8_c.h"
#include "lcUniConv/armscii_8.h"
#include "lcUniConv/cp1133.h"
#include "lcUniConv/mulelao.h"
#include "lcUniConv/viscii.h"
#include "lcUniConv/tcvn.h"
#include "lcUniConv/georgian_academy.h"
#include "lcUniConv/georgian_ps.h"
#include "lcUniConv/cp1251.h"
#include "lcUniConv/cp1255.h"
#include "lcUniConv/cp1256.h"
#include "lcUniConv/tatar_cyr.h"
typedef struct {
unsigned short indx; /* index into big table */
unsigned short used; /* bitmask of used entries */
} Summary16;
#include "lcUniConv/gb2312.h"
#include "lcUniConv/jisx0208.h"
#include "lcUniConv/jisx0212.h"
#include "lcUniConv/ksc5601.h"
#include "lcUniConv/big5.h"
#include "lcUniConv/big5_emacs.h"
#include "lcUniConv/big5hkscs.h"
#include "lcUniConv/gbk.h"
static Utf8ConvRec all_charsets[] = {
/* The ISO10646-1/UTF-8 entry occurs twice, once at the beginning
(for lookup speed), once at the end (as a fallback). */
{ "ISO10646-1",
utf8_mbtowc, utf8_wctomb
},
{ "ISO8859-1",
iso8859_1_mbtowc, iso8859_1_wctomb
},
{ "ISO8859-2",
iso8859_2_mbtowc, iso8859_2_wctomb
},
{ "ISO8859-3",
iso8859_3_mbtowc, iso8859_3_wctomb
},
{ "ISO8859-4",
iso8859_4_mbtowc, iso8859_4_wctomb
},
{ "ISO8859-5",
iso8859_5_mbtowc, iso8859_5_wctomb
},
{ "ISO8859-6",
iso8859_6_mbtowc, iso8859_6_wctomb
},
{ "ISO8859-7",
iso8859_7_mbtowc, iso8859_7_wctomb
},
{ "ISO8859-8",
iso8859_8_mbtowc, iso8859_8_wctomb
},
{ "ISO8859-9",
iso8859_9_mbtowc, iso8859_9_wctomb
},
{ "ISO8859-10",
iso8859_10_mbtowc, iso8859_10_wctomb
},
{ "ISO8859-11",
iso8859_11_mbtowc, iso8859_11_wctomb
},
{ "ISO8859-13",
iso8859_13_mbtowc, iso8859_13_wctomb
},
{ "ISO8859-14",
iso8859_14_mbtowc, iso8859_14_wctomb
},
{ "ISO8859-15",
iso8859_15_mbtowc, iso8859_15_wctomb
},
{ "ISO8859-16",
iso8859_16_mbtowc, iso8859_16_wctomb
},
{ "JISX0201.1976-0",
jisx0201_mbtowc, jisx0201_wctomb
},
{ "TIS620-0",
tis620_mbtowc, tis620_wctomb
},
{ "GB2312.1980-0",
gb2312_mbtowc, gb2312_wctomb
},
{ "JISX0208.1983-0",
jisx0208_mbtowc, jisx0208_wctomb
},
{ "JISX0208.1990-0",
jisx0208_mbtowc, jisx0208_wctomb
},
{ "JISX0212.1990-0",
jisx0212_mbtowc, jisx0212_wctomb
},
{ "KSC5601.1987-0",
ksc5601_mbtowc, ksc5601_wctomb
},
{ "KOI8-R",
koi8_r_mbtowc, koi8_r_wctomb
},
{ "KOI8-U",
koi8_u_mbtowc, koi8_u_wctomb
},
{ "KOI8-C",
koi8_c_mbtowc, koi8_c_wctomb
},
{ "TATAR-CYR",
tatar_cyr_mbtowc, tatar_cyr_wctomb
},
{ "ARMSCII-8",
armscii_8_mbtowc, armscii_8_wctomb
},
{ "IBM-CP1133",
cp1133_mbtowc, cp1133_wctomb
},
{ "MULELAO-1",
mulelao_mbtowc, mulelao_wctomb
},
{ "VISCII1.1-1",
viscii_mbtowc, viscii_wctomb
},
{ "TCVN-5712",
tcvn_mbtowc, tcvn_wctomb
},
{ "GEORGIAN-ACADEMY",
georgian_academy_mbtowc, georgian_academy_wctomb
},
{ "GEORGIAN-PS",
georgian_ps_mbtowc, georgian_ps_wctomb
},
{ "ISO8859-9E",
iso8859_9e_mbtowc, iso8859_9e_wctomb
},
{ "MICROSOFT-CP1251",
cp1251_mbtowc, cp1251_wctomb
},
{ "MICROSOFT-CP1255",
cp1255_mbtowc, cp1255_wctomb
},
{ "MICROSOFT-CP1256",
cp1256_mbtowc, cp1256_wctomb
},
{ "BIG5-0",
big5_mbtowc, big5_wctomb
},
{ "BIG5-E0",
big5_0_mbtowc, big5_0_wctomb
},
{ "BIG5-E1",
big5_1_mbtowc, big5_1_wctomb
},
{ "GBK-0",
gbk_mbtowc, gbk_wctomb
},
{ "BIG5HKSCS-0",
big5hkscs_mbtowc, big5hkscs_wctomb
},
/* The ISO10646-1/UTF-8 entry occurs twice, once at the beginning
(for lookup speed), once at the end (as a fallback). */
{ "ISO10646-1",
utf8_mbtowc, utf8_wctomb
},
/* Encoding ISO10646-1 for fonts means UCS2-like encoding
so for conversion to FontCharSet we need this record */
{ "ISO10646-1",
ucs2be_mbtowc, ucs2be_wctomb
}
};
#define charsets_table_size (sizeof(all_charsets)/sizeof(all_charsets[0]))
#define all_charsets_count (charsets_table_size - 1)
#define ucs2_conv_index (charsets_table_size - 1)
/* from XlcNCharSet to XlcNUtf8String */
int
cstoutf8(
State state,
void * *from,
size_t *from_left,
void * *to,
size_t *to_left,
XlcCharSet charset)
{
const char *name;
Utf8Conv convptr;
int i;
unsigned char const *src;
unsigned char const *srcend;
unsigned char *dst;
unsigned char *dstend;
int unconv_num;
if (from == NULL || *from == NULL)
return 0;
name = charset->encoding_name;
/* not charset->name because the latter has a ":GL"/":GR" suffix */
for (convptr = all_charsets, i = all_charsets_count-1; i > 0; convptr++, i--)
if (!strcmp(convptr->name, name))
break;
if (i == 0)
return -1;
src = (unsigned char const *) *from;
srcend = src + *from_left;
dst = (unsigned char *) *to;
dstend = dst + *to_left;
unconv_num = 0;
while (src < srcend) {
ucs4_t wc;
int consumed;
int count;
consumed = convptr->cstowc(&wc, src, srcend-src);
if (consumed == RET_ILSEQ)
return -1;
if (consumed == RET_TOOFEW(0))
break;
count = utf8_wctomb(dst, wc, dstend-dst);
if (count == RET_TOOSMALL)
break;
if (count == RET_ILSEQ) {
count = utf8_wctomb(dst, BAD_WCHAR, dstend-dst);
if (count == RET_TOOSMALL)
break;
unconv_num++;
}
src += consumed;
dst += count;
}
*from = (void *) src;
*from_left = srcend - src;
*to = (void *) dst;
*to_left = dstend - dst;
return unconv_num;
}
/*
* Converts a Unicode character to an appropriate character set. The NULL
* terminated array of preferred character sets is passed as first argument.
* If successful, *charsetp is set to the character set that was used, and
* *sidep is set to the character set side (XlcGL or XlcGR).
*/
static int
charset_wctocs(
Utf8Conv *charsetp,
XlcSide *sidep,
unsigned char *r,
ucs4_t wc,
int n)
{
int count;
Utf8Conv convptr;
int i;
// First one is utf8. We are not able to fetch XLC_FONTSET like libX11, so
// we just hard code utf8 as our preferred charset.
Utf8Conv preferred_charset[] = {all_charsets, NULL};
Utf8Conv* preferred = preferred_charset;
for (; *preferred != (Utf8Conv) NULL; preferred++) {
convptr = *preferred;
count = convptr->wctocs(r, wc, n);
if (count == RET_TOOSMALL)
return RET_TOOSMALL;
if (count != RET_ILSEQ) {
*charsetp = convptr;
*sidep = (*r < 0x80 ? XlcGL : XlcGR);
return count;
}
}
for (convptr = all_charsets+1, i = all_charsets_count-1; i > 0; convptr++, i--) {
count = convptr->wctocs(r, wc, n);
if (count == RET_TOOSMALL)
return RET_TOOSMALL;
if (count != RET_ILSEQ) {
*charsetp = convptr;
*sidep = (*r < 0x80 ? XlcGL : XlcGR);
return count;
}
}
return RET_ILSEQ;
}
int
utf8tocs(
State state,
void **from,
size_t *from_left,
void **to,
size_t *to_left,
XlcCharSet* p_charset)
{
XlcCharSet last_charset = NULL;
unsigned char const *src;
unsigned char const *srcend;
unsigned char *dst;
unsigned char *dstend;
int unconv_num;
if (from == NULL || *from == NULL)
return 0;
src = (unsigned char const *) *from;
srcend = src + *from_left;
dst = (unsigned char *) *to;
dstend = dst + *to_left;
unconv_num = 0;
while (src < srcend && dst < dstend) {
Utf8Conv chosen_charset = NULL;
XlcSide chosen_side = XlcNONE;
ucs4_t wc;
int consumed;
int count;
consumed = utf8_mbtowc(&wc, src, srcend-src);
if (consumed == RET_TOOFEW(0))
break;
if (consumed == RET_ILSEQ) {
src++;
unconv_num++;
continue;
}
count = charset_wctocs(&chosen_charset, &chosen_side, dst, wc, dstend-dst);
if (count == RET_TOOSMALL)
break;
if (count == RET_ILSEQ) {
src += consumed;
unconv_num++;
continue;
}
if (last_charset == NULL) {
last_charset =
_XlcGetCharSetWithSide(chosen_charset->name, chosen_side);
if (last_charset == NULL) {
src += consumed;
unconv_num++;
continue;
}
} else {
if (!(strcmp(last_charset->encoding_name, chosen_charset->name) == 0
&& (last_charset->side == XlcGLGR
|| last_charset->side == chosen_side)))
break;
}
src += consumed;
dst += count;
}
if (last_charset == NULL)
return -1;
*from = (void *) src;
*from_left = srcend - src;
*to = (void *) dst;
*to_left = dstend - dst;
if (p_charset)
*p_charset = last_charset;
return unconv_num;
}

View File

@ -0,0 +1,535 @@
/*
* Generates an 8-bit character set table from a .TXT table as found on
* ftp.unicode.org or from a table containing the 256 Unicode values as
* hexadecimal integers.
* Examples:
*
* ./8bit_tab_to_h ISO-8859-1 iso8859_1 < tab8859_1
* ./8bit_tab_to_h ISO-8859-2 iso8859_2 < tab8859_2
* ./8bit_tab_to_h ISO-8859-3 iso8859_3 < tab8859_3
* ./8bit_tab_to_h ISO-8859-4 iso8859_4 < tab8859_4
* ./8bit_tab_to_h ISO-8859-5 iso8859_5 < tab8859_5
* ./8bit_tab_to_h ISO-8859-6 iso8859_6 < tab8859_6
* ./8bit_tab_to_h ISO-8859-7 iso8859_7 < tab8859_7
* ./8bit_tab_to_h ISO-8859-8 iso8859_8 < tab8859_8
* ./8bit_tab_to_h ISO-8859-9 iso8859_9 < tab8859_9
* ./8bit_tab_to_h ISO-8859-10 iso8859_10 < tab8859_10
* ./8bit_tab_to_h ISO-8859-14 iso8859_14 < tab8859_14
* ./8bit_tab_to_h ISO-8859-15 iso8859_15 < tab8859_15
* ./8bit_tab_to_h JISX0201.1976-0 jisx0201 < jis0201
* ./8bit_tab_to_h TIS620-0 tis620 < tabtis620
* ./8bit_tab_to_h KOI8-R koi8_r < tabkoi8_r
* ./8bit_tab_to_h KOI8-U koi8_u < tabkoi8_u
* ./8bit_tab_to_h ARMSCII-8 armscii_8 < tabarmscii_8
* ./8bit_tab_to_h CP1133 cp1133 < tabibm_cp1133
* ./8bit_tab_to_h MULELAO-1 mulelao < tabmulelao_1
* ./8bit_tab_to_h VISCII1.1-1 viscii1 < tabviscii
* ./8bit_tab_to_h TCVN-5712 tcvn < tabtcvn
* ./8bit_tab_to_h GEORGIAN-ACADEMY georgian_ac < tabgeorgian_academy
* ./8bit_tab_to_h GEORGIAN-PS georgian_ps < tabgeorgian_ps
*
* ./8bit_tab_to_h ISO-8859-1 iso8859_1 < 8859-1.TXT
* ./8bit_tab_to_h ISO-8859-2 iso8859_2 < 8859-2.TXT
* ./8bit_tab_to_h ISO-8859-3 iso8859_3 < 8859-3.TXT
* ./8bit_tab_to_h ISO-8859-4 iso8859_4 < 8859-4.TXT
* ./8bit_tab_to_h ISO-8859-5 iso8859_5 < 8859-5.TXT
* ./8bit_tab_to_h ISO-8859-6 iso8859_6 < 8859-6.TXT
* ./8bit_tab_to_h ISO-8859-7 iso8859_7 < 8859-7.TXT
* ./8bit_tab_to_h ISO-8859-8 iso8859_8 < 8859-8.TXT
* ./8bit_tab_to_h ISO-8859-9 iso8859_9 < 8859-9.TXT
* ./8bit_tab_to_h ISO-8859-10 iso8859_10 < 8859-10.TXT
* ./8bit_tab_to_h ISO-8859-14 iso8859_14 < 8859-14.TXT
* ./8bit_tab_to_h ISO-8859-15 iso8859_15 < 8859-15.TXT
* ./8bit_tab_to_h JISX0201.1976-0 jisx0201 < JIS0201.TXT
* ./8bit_tab_to_h KOI8-R koi8_r < KOI8-R.TXT
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
int main (int argc, char *argv[])
{
const char* charsetname;
const char* c_charsetname;
const char* filename;
const char* directory;
int charset2uni[0x100];
if (argc != 3 && argc != 4 && argc != 5)
exit(1);
charsetname = argv[1];
c_charsetname = argv[2];
if (argc > 3) {
filename = argv[3];
} else {
char* s = malloc(strlen(c_charsetname)+strlen(".h")+1);
strcpy(s,c_charsetname); strcat(s,".h");
filename = s;
}
directory = (argc > 4 ? argv[4] : "");
fprintf(stderr, "Creating %s%s\n", directory, filename);
{
int i, c;
c = getc(stdin);
ungetc(c,stdin);
if (c == '#') {
/* Read a unicode.org style .TXT file. */
for (i = 0; i < 0x100; i++)
charset2uni[i] = 0xfffd;
for (;;) {
c = getc(stdin);
if (c == EOF)
break;
if (c == '\n' || c == ' ' || c == '\t')
continue;
if (c == '#') {
do { c = getc(stdin); } while (!(c == EOF || c == '\n'));
continue;
}
ungetc(c,stdin);
if (scanf("0x%x", &i) != 1 || !(i >= 0 && i < 0x100))
exit(1);
do { c = getc(stdin); } while (c == ' ' || c == '\t');
if (c != EOF)
ungetc(c,stdin);
if (c == '\n' || c == '#')
continue;
if (scanf("0x%x", &charset2uni[i]) != 1)
exit(1);
}
} else {
/* Read a table of hexadecimal Unicode values. */
for (i = 0; i < 0x100; i++) {
if (scanf("%x", &charset2uni[i]) != 1)
exit(1);
if (charset2uni[i] < 0 || charset2uni[i] == 0xffff)
charset2uni[i] = 0xfffd;
}
if (scanf("%x", &i) != EOF)
exit(1);
}
}
/* Write the output file. */
{
FILE* f;
{
char* fname = malloc(strlen(directory)+strlen(filename)+1);
strcpy(fname,directory); strcat(fname,filename);
f = fopen(fname,"w");
if (f == NULL)
exit(1);
}
fprintf(f, "\n");
fprintf(f, "/*\n");
fprintf(f, " * %s\n", charsetname);
fprintf(f, " */\n");
fprintf(f, "\n");
{
int i, i1, i2, i3;
int line[16];
int tableno;
struct { int minline; int maxline; } tables[16];
bool some_invalid;
bool final_ret_reached;
for (i1 = 0; i1 < 16; i1++) {
bool all_invalid = true;
bool all_identity = true;
for (i2 = 0; i2 < 16; i2++) {
i = 16*i1+i2;
if (charset2uni[i] != 0xfffd)
all_invalid = false;
if (charset2uni[i] != i)
all_identity = false;
}
if (all_invalid)
line[i1] = -2;
else if (all_identity)
line[i1] = -1;
else
line[i1] = 0;
}
tableno = 0;
for (i1 = 0; i1 < 16; i1++) {
if (line[i1] >= 0) {
if (i1 > 0 && tableno > 0 && line[i1-1] == tableno-1) {
line[i1] = tableno-1;
tables[tableno-1].maxline = i1;
} else {
tableno++;
line[i1] = tableno-1;
tables[tableno-1].minline = tables[tableno-1].maxline = i1;
}
}
}
some_invalid = false;
for (i = 0; i < 0x100; i++)
if (charset2uni[i] == 0xfffd)
some_invalid = true;
if (tableno > 0) {
int t;
for (t = 0; t < tableno; t++) {
fprintf(f, "static const unsigned short %s_2uni", c_charsetname);
if (tableno > 1)
fprintf(f, "_%d", t+1);
fprintf(f, "[%d] = {\n", 16*(tables[t].maxline-tables[t].minline+1));
for (i1 = tables[t].minline; i1 <= tables[t].maxline; i1++) {
fprintf(f, " /* 0x%02x */\n", 16*i1);
for (i2 = 0; i2 < 2; i2++) {
fprintf(f, " ");
for (i3 = 0; i3 < 8; i3++) {
i = 16*i1+8*i2+i3;
fprintf(f, " 0x%04x,", charset2uni[i]);
}
fprintf(f, "\n");
}
}
fprintf(f, "};\n");
}
fprintf(f, "\n");
}
final_ret_reached = false;
fprintf(f, "static int\n%s_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n)\n", c_charsetname);
fprintf(f, "{\n");
fprintf(f, " unsigned char c = *s;\n");
if (some_invalid) {
for (i1 = 0; i1 < 16;) {
int t = line[i1];
const char* indent;
for (i2 = i1; i2 < 16 && line[i2] == t; i2++);
indent = (i1 == 0 && i2 == 16 ? " " : " ");
if (i1 == 0) {
if (i2 == 16) {
} else {
fprintf(f, " if (c < 0x%02x) {\n", 16*i2);
}
} else {
if (i2 == 16) {
fprintf(f, " else {\n");
} else {
fprintf(f, " else if (c < 0x%02x) {\n", 16*i2);
}
}
if (t == -2) {
final_ret_reached = true;
} else if (t == -1) {
fprintf(f, "%s*pwc = (ucs4_t) c;\n", indent);
fprintf(f, "%sreturn 1;\n", indent);
} else {
fprintf(f, "%s", indent);
some_invalid = false;
for (i = 16*i1; i < 16*i2; i++)
if (charset2uni[i] == 0xfffd)
some_invalid = true;
if (some_invalid)
fprintf(f, "unsigned short wc = ");
else
fprintf(f, "*pwc = (ucs4_t) ");
fprintf(f, "%s_2uni", c_charsetname);
if (tableno > 1)
fprintf(f, "_%d", t+1);
fprintf(f, "[c");
if (tables[t].minline > 0)
fprintf(f, "-0x%02x", 16*tables[t].minline);
fprintf(f, "];\n");
if (some_invalid) {
fprintf(f, "%sif (wc != 0xfffd) {\n", indent);
fprintf(f, "%s *pwc = (ucs4_t) wc;\n", indent);
fprintf(f, "%s return 1;\n", indent);
fprintf(f, "%s}\n", indent);
final_ret_reached = true;
} else {
fprintf(f, "%sreturn 1;\n", indent);
}
}
if (!(i1 == 0 && i2 == 16))
fprintf(f, " }\n");
i1 = i2;
}
if (final_ret_reached)
fprintf(f, " return RET_ILSEQ;\n");
} else {
for (i1 = 0; i1 < 16;) {
int t = line[i1];
for (i2 = i1; i2 < 16 && line[i2] == t; i2++);
if (i1 == 0) {
if (i2 == 16) {
fprintf(f, " ");
} else {
fprintf(f, " if (c < 0x%02x)\n ", 16*i2);
}
} else {
if (i2 == 16) {
fprintf(f, " else\n ");
} else {
fprintf(f, " else if (c < 0x%02x)\n ", 16*i2);
}
}
if (t == -1)
fprintf(f, "*pwc = (ucs4_t) c;\n");
else {
fprintf(f, "*pwc = (ucs4_t) %s_2uni", c_charsetname);
if (tableno > 1)
fprintf(f, "_%d", t+1);
fprintf(f, "[c");
if (tables[t].minline > 0)
fprintf(f, "-0x%02x", 16*tables[t].minline);
fprintf(f, "];\n");
}
i1 = i2;
}
fprintf(f, " return 1;\n");
}
fprintf(f, "}\n");
}
fprintf(f, "\n");
{
int uni2charset[0x10000];
bool pages[0x100];
int line[0x2000];
int tableno;
struct { int minline; int maxline; int usecount; const char* suffix; } tables[0x2000];
bool need_c;
bool fix_0000;
int i, j, p, j1, j2, t;
for (j = 0; j < 0x10000; j++)
uni2charset[j] = 0;
for (p = 0; p < 0x100; p++)
pages[p] = false;
for (i = 0; i < 0x100; i++) {
j = charset2uni[i];
if (j != 0xfffd) {
uni2charset[j] = i;
pages[j>>8] = true;
}
}
for (j1 = 0; j1 < 0x2000; j1++) {
bool all_invalid = true;
bool all_identity = true;
for (j2 = 0; j2 < 8; j2++) {
j = 8*j1+j2;
if (uni2charset[j] != 0)
all_invalid = false;
if (uni2charset[j] != j)
all_identity = false;
}
if (all_invalid)
line[j1] = -2;
else if (all_identity)
line[j1] = -1;
else
line[j1] = 0;
}
tableno = 0;
for (j1 = 0; j1 < 0x2000; j1++) {
if (line[j1] >= 0) {
if (tableno > 0
&& ((j1 > 0 && line[j1-1] == tableno-1)
|| ((tables[tableno-1].maxline >> 5) == (j1 >> 5)
&& j1 - tables[tableno-1].maxline <= 8))) {
line[j1] = tableno-1;
tables[tableno-1].maxline = j1;
} else {
tableno++;
line[j1] = tableno-1;
tables[tableno-1].minline = tables[tableno-1].maxline = j1;
}
}
}
for (t = 0; t < tableno; t++) {
tables[t].usecount = 0;
j1 = 8*tables[t].minline;
j2 = 8*(tables[t].maxline+1);
for (j = j1; j < j2; j++)
if (uni2charset[j] != 0)
tables[t].usecount++;
}
for (t = 0, p = -1, i = 0; t < tableno; t++) {
if (tables[t].usecount > 1) {
char* s;
if (p == tables[t].minline >> 5) {
s = malloc(5+1);
sprintf(s, "%02x_%d", p, ++i);
} else {
p = tables[t].minline >> 5;
s = malloc(2+1);
sprintf(s, "%02x", p);
}
tables[t].suffix = s;
} else
tables[t].suffix = NULL;
}
{
p = -1;
for (t = 0; t < tableno; t++)
if (tables[t].usecount > 1) {
p = 0;
fprintf(f, "static const unsigned char %s_page%s[%d] = {\n", c_charsetname, tables[t].suffix, 8*(tables[t].maxline-tables[t].minline+1));
for (j1 = tables[t].minline; j1 <= tables[t].maxline; j1++) {
if ((j1 % 0x20) == 0 && j1 > tables[t].minline)
fprintf(f, " /* 0x%04x */\n", 8*j1);
fprintf(f, " ");
for (j2 = 0; j2 < 8; j2++) {
j = 8*j1+j2;
fprintf(f, " 0x%02x,", uni2charset[j]);
}
fprintf(f, " /* 0x%02x-0x%02x */\n", 8*(j1 % 0x20), 8*(j1 % 0x20)+7);
}
fprintf(f, "};\n");
}
if (p >= 0)
fprintf(f, "\n");
}
need_c = false;
for (j1 = 0; j1 < 0x2000;) {
t = line[j1];
for (j2 = j1; j2 < 0x2000 && line[j2] == t; j2++);
if (t >= 0)
j2 = tables[t].maxline+1;
if (!(t == -2 || (t == -1 && j1 == 0)))
need_c = true;
j1 = j2;
}
fix_0000 = false;
fprintf(f, "static int\n%s_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n)\n", c_charsetname);
fprintf(f, "{\n");
if (need_c)
fprintf(f, " unsigned char c = 0;\n");
for (j1 = 0; j1 < 0x2000;) {
t = line[j1];
for (j2 = j1; j2 < 0x2000 && line[j2] == t; j2++);
if (t >= 0) {
if (j1 != tables[t].minline) abort();
if (j2 > tables[t].maxline+1) abort();
j2 = tables[t].maxline+1;
}
if (t == -2) {
} else {
if (j1 == 0)
fprintf(f, " ");
else
fprintf(f, " else ");
if (t >= 0 && tables[t].usecount == 0) abort();
if (t >= 0 && tables[t].usecount == 1) {
if (j2 != j1+1) abort();
for (j = 8*j1; j < 8*j2; j++)
if (uni2charset[j] != 0) {
fprintf(f, "if (wc == 0x%04x)\n c = 0x%02x;\n", j, uni2charset[j]);
break;
}
} else {
if (j1 == 0) {
fprintf(f, "if (wc < 0x%04x)", 8*j2);
} else {
fprintf(f, "if (wc >= 0x%04x && wc < 0x%04x)", 8*j1, 8*j2);
}
if (t == -1) {
if (j1 == 0)
/* If wc == 0, the function must return 1, not -1. */
fprintf(f, " {\n *r = wc;\n return 1;\n }\n");
else
fprintf(f, "\n c = wc;\n");
} else {
fprintf(f, "\n c = %s_page%s[wc", c_charsetname, tables[t].suffix);
if (tables[t].minline > 0)
fprintf(f, "-0x%04x", 8*j1);
fprintf(f, "];\n");
if (j1 == 0 && uni2charset[0] == 0)
/* If wc == 0, the function must return 1, not -1. */
fix_0000 = true;
}
}
}
j1 = j2;
}
if (need_c) {
if (fix_0000)
fprintf(f, " if (c != 0 || wc == 0) {\n");
else
fprintf(f, " if (c != 0) {\n");
fprintf(f, " *r = c;\n");
fprintf(f, " return 1;\n");
fprintf(f, " }\n");
}
fprintf(f, " return RET_ILSEQ;\n");
fprintf(f, "}\n");
}
if (ferror(f) || fclose(f))
exit(1);
}
#if 0
int i1, i2, i3, i1_min, i1_max, j1, j2;
i1_min = 16;
i1_max = -1;
for (i1 = 0; i1 < 16; i1++)
for (i2 = 0; i2 < 16; i2++)
if (charset2uni[16*i1+i2] != 0xfffd) {
if (i1_min > i1) i1_min = i1;
if (i1_max < i1) i1_max = i1;
}
printf("static const unsigned short %s_2uni[%d] = {\n",
name, 16*(i1_max-i1_min+1));
for (i1 = i1_min; i1 <= i1_max; i1++) {
printf(" /""* 0x%02x *""/\n", 16*i1);
for (i2 = 0; i2 < 2; i2++) {
printf(" ");
for (i3 = 0; i3 < 8; i3++) {
if (i3 > 0) printf(" ");
printf("0x%04x,", charset2uni[16*i1+8*i2+i3]);
}
printf("\n");
}
}
printf("};\n");
printf("\n");
for (p = 0; p < 0x100; p++)
pages[p] = 0;
for (i = 0; i < 0x100; i++)
if (charset2uni[i] != 0xfffd)
pages[charset2uni[i]>>8] = 1;
for (p = 0; p < 0x100; p++)
if (pages[p]) {
int j1_min = 32;
int j1_max = -1;
for (j1 = 0; j1 < 32; j1++)
for (j2 = 0; j2 < 8; j2++)
if (uni2charset[256*p+8*j1+j2] != 0) {
if (j1_min > j1) j1_min = j1;
if (j1_max < j1) j1_max = j1;
}
printf("static const unsigned char %s_page%02x[%d] = {\n",
name, p, 8*(j1_max-j1_min+1));
for (j1 = j1_min; j1 <= j1_max; j1++) {
printf(" ");
for (j2 = 0; j2 < 8; j2++)
printf("0x%02x, ", uni2charset[256*p+8*j1+j2]);
printf("/""* 0x%02x-0x%02x *""/\n", 8*j1, 8*j1+7);
}
printf("};\n");
}
printf("\n");
}
#endif
exit(0);
}

View File

@ -0,0 +1,39 @@
This notice applies to the files in this directory. They are taken from
the libiconv-1.1 package, which is covered by the LGPL license. The files
in this directory have been placed under the following copyright, with
permission from the Free Software Foundation.
Copyright (c) 1999-2000 Free Software Foundation, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
FREE SOFTWARE FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of the Free Software Foundation
shall not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization from the
Free Software Foundation.
Notes:
1. This copyright applies only to the files in this directory, and not to
the remaining files in libiconv.
2. The Free Software Foundation does not encourage the use of the above
license for newly written software.

View File

@ -0,0 +1,11 @@
The files in this directory are taken from the libiconv-1.1 package.
The *.h files were generated from tables (mostly from ftp.unicode.org) using
the programs '8bit_tab_to_h.c' and 'cjk_tab_to_h.c'. On some of them, further
optimizations were applied by hand.
If you find a bug in these files, instead of modifying them in XFree86
and let it diverge from libiconv, please notify the libiconv maintainer
(currently <bruno@clisp.org>) so he can fix both in synch.

View File

@ -0,0 +1,97 @@
/*
* ARMSCII-8
*/
static const unsigned short armscii_8_2uni[96] = {
/* 0xa0 */
0x00a0, 0xfffd, 0x0587, 0x0589, 0x0029, 0x0028, 0x00bb, 0x00ab,
0x2014, 0x002e, 0x055d, 0x002c, 0x002d, 0x058a, 0x2026, 0x055c,
/* 0xb0 */
0x055b, 0x055e, 0x0531, 0x0561, 0x0532, 0x0562, 0x0533, 0x0563,
0x0534, 0x0564, 0x0535, 0x0565, 0x0536, 0x0566, 0x0537, 0x0567,
/* 0xc0 */
0x0538, 0x0568, 0x0539, 0x0569, 0x053a, 0x056a, 0x053b, 0x056b,
0x053c, 0x056c, 0x053d, 0x056d, 0x053e, 0x056e, 0x053f, 0x056f,
/* 0xd0 */
0x0540, 0x0570, 0x0541, 0x0571, 0x0542, 0x0572, 0x0543, 0x0573,
0x0544, 0x0574, 0x0545, 0x0575, 0x0546, 0x0576, 0x0547, 0x0577,
/* 0xe0 */
0x0548, 0x0578, 0x0549, 0x0579, 0x054a, 0x057a, 0x054b, 0x057b,
0x054c, 0x057c, 0x054d, 0x057d, 0x054e, 0x057e, 0x054f, 0x057f,
/* 0xf0 */
0x0550, 0x0580, 0x0551, 0x0581, 0x0552, 0x0582, 0x0553, 0x0583,
0x0554, 0x0584, 0x0555, 0x0585, 0x0556, 0x0586, 0x055a, 0xfffd,
};
static int
armscii_8_mbtowc (ucs4_t *pwc, const unsigned char *s, int n)
{
unsigned char c = *s;
if (c < 0xa0) {
*pwc = (ucs4_t) c;
return 1;
}
else {
unsigned short wc = armscii_8_2uni[c-0xa0];
if (wc != 0xfffd) {
*pwc = (ucs4_t) wc;
return 1;
}
}
return RET_ILSEQ;
}
static const unsigned char armscii_8_page00[8] = {
0xa5, 0xa4, 0x2a, 0x2b, 0xab, 0xac, 0xa9, 0x2f, /* 0x28-0x2f */
};
static const unsigned char armscii_8_page00_1[32] = {
0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
0x00, 0x00, 0x00, 0xa6, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
};
static const unsigned char armscii_8_page05[96] = {
0x00, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe, /* 0x30-0x37 */
0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, /* 0x38-0x3f */
0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde, /* 0x40-0x47 */
0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, /* 0x48-0x4f */
0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0x00, /* 0x50-0x57 */
0x00, 0x00, 0xfe, 0xb0, 0xaf, 0xaa, 0xb1, 0x00, /* 0x58-0x5f */
0x00, 0xb3, 0xb5, 0xb7, 0xb9, 0xbb, 0xbd, 0xbf, /* 0x60-0x67 */
0xc1, 0xc3, 0xc5, 0xc7, 0xc9, 0xcb, 0xcd, 0xcf, /* 0x68-0x6f */
0xd1, 0xd3, 0xd5, 0xd7, 0xd9, 0xdb, 0xdd, 0xdf, /* 0x70-0x77 */
0xe1, 0xe3, 0xe5, 0xe7, 0xe9, 0xeb, 0xed, 0xef, /* 0x78-0x7f */
0xf1, 0xf3, 0xf5, 0xf7, 0xf9, 0xfb, 0xfd, 0xa2, /* 0x80-0x87 */
0x00, 0xa3, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
};
static const unsigned char armscii_8_page20[24] = {
0x00, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, /* 0x10-0x17 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0x00, /* 0x20-0x27 */
};
static int
armscii_8_wctomb (unsigned char *r, ucs4_t wc, int n)
{
unsigned char c = 0;
if (wc < 0x0028) {
*r = wc;
return 1;
}
else if (wc >= 0x0028 && wc < 0x0030)
c = armscii_8_page00[wc-0x0028];
else if (wc >= 0x0030 && wc < 0x00a0)
c = wc;
else if (wc >= 0x00a0 && wc < 0x00c0)
c = armscii_8_page00_1[wc-0x00a0];
else if (wc >= 0x0530 && wc < 0x0590)
c = armscii_8_page05[wc-0x0530];
else if (wc >= 0x2010 && wc < 0x2028)
c = armscii_8_page20[wc-0x2010];
if (c != 0) {
*r = c;
return 1;
}
return RET_ILSEQ;
}

View File

@ -0,0 +1,25 @@
/*
* ASCII
*/
static int
ascii_mbtowc (ucs4_t *pwc, const unsigned char *s, int n)
{
unsigned char c = *s;
if (c < 0x80) {
*pwc = (ucs4_t) c;
return 1;
}
return RET_ILSEQ;
}
static int
ascii_wctomb (unsigned char *r, ucs4_t wc, int n)
{
if (wc < 0x0080) {
*r = wc;
return 1;
}
return RET_ILSEQ;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,163 @@
/*
* BIG5-0 and BIG5-1
*/
/*
BIG5 with its 13494 characters doesn't fit in a single 94x94 or 96x96
block. Therefore Emacs/Mule developers, in a typically Japanese way of
thinking, have developed an alternative encoding of BIG5 in two 94x94
planes, very similar to the SHIFT_JIS encoding for JISX0208.
Conversion between BIG5 codes (s1,s2) and BIG5-0 codes (c1,c2):
Example. (s1,s2) = 0xA140, (c1,c2) = 0x2121.
0xA1 <= s1 <= 0xC7, 0x40 <= s2 <= 0x7E || 0xA1 <= s2 <= 0xFE,
0x21 <= c1 <= 0x62, 0x21 <= c2 <= 0x7E.
Invariant:
157*(s1-0xA1) + (s2 < 0x80 ? s2-0x40 : s2-0x62)
= 94*(c1-0x21)+(c2-0x21)
Conversion (s1,s2) -> (c1,c2):
t := 157*(s1-0xA1) + (s2 < 0x80 ? s2-0x40 : s2-0x62)
c1 := (t div 94) + 0x21
c2 := (t mod 94) + 0x21
Conversion (c1,c2) -> (s1,s2):
t := 94*(c1-0x21)+(c2-0x21)
t2 := t mod 157
s1 := (t div 157) + 0xA1
s2 := (t2 < 0x3F ? t2+0x40 : t2+0x62)
Conversion between BIG5 codes (s1,s2) and BIG5-1 codes (c1,c2):
Example. (s1,s2) = 0xC940, (c1,c2) = 0x2121.
0xC9 <= s1 <= 0xF9, 0x40 <= s2 <= 0x7E || 0xA1 <= s2 <= 0xFE,
0x21 <= c1 <= 0x72, 0x21 <= c2 <= 0x7E.
Invariant:
157*(s1-0xC9) + (s2 < 0x80 ? s2-0x40 : s2-0x62)
= 94*(c1-0x21)+(c2-0x21)
Conversion (s1,s2) -> (c1,c2):
t := 157*(s1-0xC9) + (s2 < 0x80 ? s2-0x40 : s2-0x62)
c1 := (t div 94) + 0x21
c2 := (t mod 94) + 0x21
Conversion (c1,c2) -> (s1,s2):
t := 94*(c1-0x21)+(c2-0x21)
t2 := t mod 157
s1 := (t div 157) + 0xC9
s2 := (t2 < 0x3F ? t2+0x40 : t2+0x62)
*/
static int
big5_0_mbtowc (ucs4_t *pwc, const unsigned char *s, int n)
{
unsigned char c1 = s[0];
if (c1 >= 0x21 && c1 <= 0x62) {
if (n >= 2) {
unsigned char c2 = s[1];
if (c2 >= 0x21 && c2 <= 0x7e) {
unsigned int i = 94 * (c1 - 0x21) + (c2 - 0x21);
if (0) {
/* Unoptimized. */
unsigned char buf[2];
buf[0] = (i / 157) + 0xa1;
i = i % 157;
buf[1] = i + (i < 0x3f ? 0x40 : 0x62);
return big5_mbtowc(pwc,buf,2);
} else {
/* Inline the implementation of big5_mbtowc. */
if (i < 6121) {
unsigned short wc = big5_2uni_pagea1[i];
if (wc != 0xfffd) {
*pwc = (ucs4_t) wc;
return 2;
}
}
}
}
return RET_ILSEQ;
}
return RET_TOOFEW(0);
}
return RET_ILSEQ;
}
static int
big5_1_mbtowc (ucs4_t *pwc, const unsigned char *s, int n)
{
unsigned char c1 = s[0];
if (c1 >= 0x21 && c1 <= 0x72) {
if (n >= 2) {
unsigned char c2 = s[1];
if (c2 >= 0x21 && c2 <= 0x7e) {
unsigned int i = 94 * (c1 - 0x21) + (c2 - 0x21);
if (0) {
/* Unoptimized. */
unsigned char buf[2];
buf[0] = (i / 157) + 0xc9;
i = i % 157;
buf[1] = i + (i < 0x3f ? 0x40 : 0x62);
return big5_mbtowc(pwc,buf,2);
} else {
/* Inline the implementation of big5_mbtowc. */
if (i < 7652) {
unsigned short wc = big5_2uni_pagec9[i];
if (wc != 0xfffd) {
*pwc = (ucs4_t) wc;
return 2;
}
}
}
}
return RET_ILSEQ;
}
return RET_TOOFEW(0);
}
return RET_ILSEQ;
}
static int
big5_0_wctomb (unsigned char *r, ucs4_t wc, int n)
{
if (n >= 2) {
unsigned char buf[2];
int ret = big5_wctomb(buf,wc,2);
if (ret != RET_ILSEQ) {
unsigned char s1, s2;
if (ret != 2) abort();
s1 = buf[0];
s2 = buf[1];
if (!(s1 >= 0xa1)) abort();
if (!((s2 >= 0x40 && s2 <= 0x7e) || (s2 >= 0xa1 && s2 <= 0xfe))) abort();
if (s1 < 0xc9) {
unsigned int t = 157 * (s1 - 0xa1) + s2 - (s2 < 0x80 ? 0x40 : 0x62);
r[0] = (t / 94) + 0x21;
r[1] = (t % 94) + 0x21;
return 2;
}
}
return RET_ILSEQ;
}
return RET_TOOSMALL;
}
static int
big5_1_wctomb (unsigned char *r, ucs4_t wc, int n)
{
if (n >= 2) {
unsigned char buf[2];
int ret = big5_wctomb(buf,wc,2);
if (ret != RET_ILSEQ) {
unsigned char s1, s2;
if (ret != 2) abort();
s1 = buf[0];
s2 = buf[1];
if (!(s1 <= 0xf9)) abort();
if (!((s2 >= 0x40 && s2 <= 0x7e) || (s2 >= 0xa1 && s2 <= 0xfe))) abort();
if (s1 >= 0xc9) {
unsigned int t = 157 * (s1 - 0xc9) + s2 - (s2 < 0x80 ? 0x40 : 0x62);
r[0] = (t / 94) + 0x21;
r[1] = (t % 94) + 0x21;
return 2;
}
}
return RET_ILSEQ;
}
return RET_TOOSMALL;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,91 @@
/*
* IBM-CP1133
*/
static const unsigned short cp1133_2uni_1[64] = {
/* 0xa0 */
0x00a0, 0x0e81, 0x0e82, 0x0e84, 0x0e87, 0x0e88, 0x0eaa, 0x0e8a,
0x0e8d, 0x0e94, 0x0e95, 0x0e96, 0x0e97, 0x0e99, 0x0e9a, 0x0e9b,
/* 0xb0 */
0x0e9c, 0x0e9d, 0x0e9e, 0x0e9f, 0x0ea1, 0x0ea2, 0x0ea3, 0x0ea5,
0x0ea7, 0x0eab, 0x0ead, 0x0eae, 0xfffd, 0xfffd, 0xfffd, 0x0eaf,
/* 0xc0 */
0x0eb0, 0x0eb2, 0x0eb3, 0x0eb4, 0x0eb5, 0x0eb6, 0x0eb7, 0x0eb8,
0x0eb9, 0x0ebc, 0x0eb1, 0x0ebb, 0x0ebd, 0xfffd, 0xfffd, 0xfffd,
/* 0xd0 */
0x0ec0, 0x0ec1, 0x0ec2, 0x0ec3, 0x0ec4, 0x0ec8, 0x0ec9, 0x0eca,
0x0ecb, 0x0ecc, 0x0ecd, 0x0ec6, 0xfffd, 0x0edc, 0x0edd, 0x20ad,
};
static const unsigned short cp1133_2uni_2[16] = {
/* 0xf0 */
0x0ed0, 0x0ed1, 0x0ed2, 0x0ed3, 0x0ed4, 0x0ed5, 0x0ed6, 0x0ed7,
0x0ed8, 0x0ed9, 0xfffd, 0xfffd, 0x00a2, 0x00ac, 0x00a6, 0xfffd,
};
static int
cp1133_mbtowc (ucs4_t *pwc, const unsigned char *s, int n)
{
unsigned char c = *s;
if (c < 0xa0) {
*pwc = (ucs4_t) c;
return 1;
}
else if (c < 0xe0) {
unsigned short wc = cp1133_2uni_1[c-0xa0];
if (wc != 0xfffd) {
*pwc = (ucs4_t) wc;
return 1;
}
}
else if (c < 0xf0) {
}
else {
unsigned short wc = cp1133_2uni_2[c-0xf0];
if (wc != 0xfffd) {
*pwc = (ucs4_t) wc;
return 1;
}
}
return RET_ILSEQ;
}
static const unsigned char cp1133_page00[16] = {
0xa0, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfe, 0x00, /* 0xa0-0xa7 */
0x00, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
};
static const unsigned char cp1133_page0e[96] = {
0x00, 0xa1, 0xa2, 0x00, 0xa3, 0x00, 0x00, 0xa4, /* 0x80-0x87 */
0xa5, 0x00, 0xa7, 0x00, 0x00, 0xa8, 0x00, 0x00, /* 0x88-0x8f */
0x00, 0x00, 0x00, 0x00, 0xa9, 0xaa, 0xab, 0xac, /* 0x90-0x97 */
0x00, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, /* 0x98-0x9f */
0x00, 0xb4, 0xb5, 0xb6, 0x00, 0xb7, 0x00, 0xb8, /* 0xa0-0xa7 */
0x00, 0x00, 0xa6, 0xb9, 0x00, 0xba, 0xbb, 0xbf, /* 0xa8-0xaf */
0xc0, 0xca, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, /* 0xb0-0xb7 */
0xc7, 0xc8, 0x00, 0xcb, 0xc9, 0xcc, 0x00, 0x00, /* 0xb8-0xbf */
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0x00, 0xdb, 0x00, /* 0xc0-0xc7 */
0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0x00, 0x00, /* 0xc8-0xcf */
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xd0-0xd7 */
0xf8, 0xf9, 0x00, 0x00, 0xdd, 0xde, 0x00, 0x00, /* 0xd8-0xdf */
};
static int
cp1133_wctomb (unsigned char *r, ucs4_t wc, int n)
{
unsigned char c = 0;
if (wc < 0x00a0) {
*r = wc;
return 1;
}
else if (wc >= 0x00a0 && wc < 0x00b0)
c = cp1133_page00[wc-0x00a0];
else if (wc >= 0x0e80 && wc < 0x0ee0)
c = cp1133_page0e[wc-0x0e80];
else if (wc == 0x20ad)
c = 0xdf;
if (c != 0) {
*r = c;
return 1;
}
return RET_ILSEQ;
}

View File

@ -0,0 +1,112 @@
/*
* CP1251
*/
static const unsigned short cp1251_2uni[128] = {
/* 0x80 */
0x0402, 0x0403, 0x201a, 0x0453, 0x201e, 0x2026, 0x2020, 0x2021,
0x20ac, 0x2030, 0x0409, 0x2039, 0x040a, 0x040c, 0x040b, 0x040f,
/* 0x90 */
0x0452, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
0xfffd, 0x2122, 0x0459, 0x203a, 0x045a, 0x045c, 0x045b, 0x045f,
/* 0xa0 */
0x00a0, 0x040e, 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7,
0x0401, 0x00a9, 0x0404, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407,
/* 0xb0 */
0x00b0, 0x00b1, 0x0406, 0x0456, 0x0491, 0x00b5, 0x00b6, 0x00b7,
0x0451, 0x2116, 0x0454, 0x00bb, 0x0458, 0x0405, 0x0455, 0x0457,
/* 0xc0 */
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
/* 0xd0 */
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
/* 0xe0 */
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f,
/* 0xf0 */
0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f,
};
static int
cp1251_mbtowc (ucs4_t *pwc, const unsigned char *s, int n)
{
unsigned char c = *s;
if (c < 0x80) {
*pwc = (ucs4_t) c;
return 1;
}
else {
unsigned short wc = cp1251_2uni[c-0x80];
if (wc != 0xfffd) {
*pwc = (ucs4_t) wc;
return 1;
}
}
return RET_ILSEQ;
}
static const unsigned char cp1251_page00[32] = {
0xa0, 0x00, 0x00, 0x00, 0xa4, 0x00, 0xa6, 0xa7, /* 0xa0-0xa7 */
0x00, 0xa9, 0x00, 0xab, 0xac, 0xad, 0xae, 0x00, /* 0xa8-0xaf */
0xb0, 0xb1, 0x00, 0x00, 0x00, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
};
static const unsigned char cp1251_page04[152] = {
0x00, 0xa8, 0x80, 0x81, 0xaa, 0xbd, 0xb2, 0xaf, /* 0x00-0x07 */
0xa3, 0x8a, 0x8c, 0x8e, 0x8d, 0x00, 0xa1, 0x8f, /* 0x08-0x0f */
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0x10-0x17 */
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0x18-0x1f */
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0x20-0x27 */
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0x28-0x2f */
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0x30-0x37 */
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0x38-0x3f */
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0x40-0x47 */
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0x48-0x4f */
0x00, 0xb8, 0x90, 0x83, 0xba, 0xbe, 0xb3, 0xbf, /* 0x50-0x57 */
0xbc, 0x9a, 0x9c, 0x9e, 0x9d, 0x00, 0xa2, 0x9f, /* 0x58-0x5f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
0xa5, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
};
static const unsigned char cp1251_page20[48] = {
0x00, 0x00, 0x00, 0x96, 0x97, 0x00, 0x00, 0x00, /* 0x10-0x17 */
0x91, 0x92, 0x82, 0x00, 0x93, 0x94, 0x84, 0x00, /* 0x18-0x1f */
0x86, 0x87, 0x95, 0x00, 0x00, 0x00, 0x85, 0x00, /* 0x20-0x27 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
0x00, 0x8b, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
};
static int
cp1251_wctomb (unsigned char *r, ucs4_t wc, int n)
{
unsigned char c = 0;
if (wc < 0x0080) {
*r = wc;
return 1;
}
else if (wc >= 0x00a0 && wc < 0x00c0)
c = cp1251_page00[wc-0x00a0];
else if (wc >= 0x0400 && wc < 0x0498)
c = cp1251_page04[wc-0x0400];
else if (wc >= 0x2010 && wc < 0x2040)
c = cp1251_page20[wc-0x2010];
else if (wc == 0x20ac)
c = 0x88;
else if (wc == 0x2116)
c = 0xb9;
else if (wc == 0x2122)
c = 0x99;
if (c != 0) {
*r = c;
return 1;
}
return RET_ILSEQ;
}

View File

@ -0,0 +1,120 @@
/*
* CP1255
*/
static const unsigned short cp1255_2uni[128] = {
/* 0x80 */
0x20ac, 0xfffd, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
0x02c6, 0x2030, 0xfffd, 0x2039, 0xfffd, 0xfffd, 0xfffd, 0xfffd,
/* 0x90 */
0xfffd, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
0x02dc, 0x2122, 0xfffd, 0x203a, 0xfffd, 0xfffd, 0xfffd, 0xfffd,
/* 0xa0 */
0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x20aa, 0x00a5, 0x00a6, 0x00a7,
0x00a8, 0x00a9, 0x00d7, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
/* 0xb0 */
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
0x00b8, 0x00b9, 0x00f7, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
/* 0xc0 */
0x05b0, 0x05b1, 0x05b2, 0x05b3, 0x05b4, 0x05b5, 0x05b6, 0x05b7,
0x05b8, 0x05b9, 0xfffd, 0x05bb, 0x05bc, 0x05bd, 0x05be, 0x05bf,
/* 0xd0 */
0x05c0, 0x05c1, 0x05c2, 0x05c3, 0x05f0, 0x05f1, 0x05f2, 0x05f3,
0x05f4, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd,
/* 0xe0 */
0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7,
0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df,
/* 0xf0 */
0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7,
0x05e8, 0x05e9, 0x05ea, 0xfffd, 0xfffd, 0x200e, 0x200f, 0xfffd,
};
static int
cp1255_mbtowc (ucs4_t *pwc, const unsigned char *s, int n)
{
unsigned char c = *s;
if (c < 0x80) {
*pwc = (ucs4_t) c;
return 1;
}
else {
unsigned short wc = cp1255_2uni[c-0x80];
if (wc != 0xfffd) {
*pwc = (ucs4_t) wc;
return 1;
}
}
return RET_ILSEQ;
}
static const unsigned char cp1255_page00[88] = {
0xa0, 0xa1, 0xa2, 0xa3, 0x00, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
0xa8, 0xa9, 0x00, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
0xb8, 0xb9, 0x00, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, /* 0xd0-0xd7 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, /* 0xf0-0xf7 */
};
static const unsigned char cp1255_page02[32] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, /* 0xc0-0xc7 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
};
static const unsigned char cp1255_page05[72] = {
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xb0-0xb7 */
0xc8, 0xc9, 0x00, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xb8-0xbf */
0xd0, 0xd1, 0xd2, 0xd3, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xd0-0xd7 */
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xd8-0xdf */
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xe0-0xe7 */
0xf8, 0xf9, 0xfa, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
};
static const unsigned char cp1255_page20[56] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xfe, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x96, 0x97, 0x00, 0x00, 0x00, /* 0x10-0x17 */
0x91, 0x92, 0x82, 0x00, 0x93, 0x94, 0x84, 0x00, /* 0x18-0x1f */
0x86, 0x87, 0x95, 0x00, 0x00, 0x00, 0x85, 0x00, /* 0x20-0x27 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
0x00, 0x8b, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
};
static int
cp1255_wctomb (unsigned char *r, ucs4_t wc, int n)
{
unsigned char c = 0;
if (wc < 0x0080) {
*r = wc;
return 1;
}
else if (wc >= 0x00a0 && wc < 0x00f8)
c = cp1255_page00[wc-0x00a0];
else if (wc == 0x0192)
c = 0x83;
else if (wc >= 0x02c0 && wc < 0x02e0)
c = cp1255_page02[wc-0x02c0];
else if (wc >= 0x05b0 && wc < 0x05f8)
c = cp1255_page05[wc-0x05b0];
else if (wc >= 0x2008 && wc < 0x2040)
c = cp1255_page20[wc-0x2008];
else if (wc == 0x20aa)
c = 0xa4;
else if (wc == 0x20ac)
c = 0x80;
else if (wc == 0x2122)
c = 0x99;
if (c != 0) {
*r = c;
return 1;
}
return RET_ILSEQ;
}

View File

@ -0,0 +1,134 @@
/*
* CP1256
*/
static const unsigned short cp1256_2uni[128] = {
/* 0x80 */
0x20ac, 0x067e, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
0x02c6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688,
/* 0x90 */
0x06af, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
0x06a9, 0x2122, 0x0691, 0x203a, 0x0153, 0x200c, 0x200d, 0x06ba,
/* 0xa0 */
0x00a0, 0x060c, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
0x00a8, 0x00a9, 0x06be, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
/* 0xb0 */
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
0x00b8, 0x00b9, 0x061b, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x061f,
/* 0xc0 */
0x06c1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627,
0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f,
/* 0xd0 */
0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00d7,
0x0637, 0x0638, 0x0639, 0x063a, 0x0640, 0x0641, 0x0642, 0x0643,
/* 0xe0 */
0x00e0, 0x0644, 0x00e2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00e7,
0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x0649, 0x064a, 0x00ee, 0x00ef,
/* 0xf0 */
0x064b, 0x064c, 0x064d, 0x064e, 0x00f4, 0x064f, 0x0650, 0x00f7,
0x0651, 0x00f9, 0x0652, 0x00fb, 0x00fc, 0x200e, 0x200f, 0x06d2,
};
static int
cp1256_mbtowc (ucs4_t *pwc, const unsigned char *s, int n)
{
unsigned char c = *s;
if (c < 0x80)
*pwc = (ucs4_t) c;
else
*pwc = (ucs4_t) cp1256_2uni[c-0x80];
return 1;
}
static const unsigned char cp1256_page00[96] = {
0xa0, 0x00, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
0xa8, 0xa9, 0x00, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
0xb8, 0xb9, 0x00, 0xbb, 0xbc, 0xbd, 0xbe, 0x00, /* 0xb8-0xbf */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd7, /* 0xd0-0xd7 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
0xe0, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x00, 0xe7, /* 0xe0-0xe7 */
0xe8, 0xe9, 0xea, 0xeb, 0x00, 0x00, 0xee, 0xef, /* 0xe8-0xef */
0x00, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0xf7, /* 0xf0-0xf7 */
0x00, 0xf9, 0x00, 0xfb, 0xfc, 0x00, 0x00, 0x00, /* 0xf8-0xff */
};
static const unsigned char cp1256_page01[72] = {
0x00, 0x00, 0x8c, 0x9c, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
};
static const unsigned char cp1256_page06[208] = {
0x00, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0xbf, /* 0x18-0x1f */
0x00, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0x20-0x27 */
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0x28-0x2f */
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd8, /* 0x30-0x37 */
0xd9, 0xda, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
0xdc, 0xdd, 0xde, 0xdf, 0xe1, 0xe3, 0xe4, 0xe5, /* 0x40-0x47 */
0xe6, 0xec, 0xed, 0xf0, 0xf1, 0xf2, 0xf3, 0xf5, /* 0x48-0x4f */
0xf6, 0xf8, 0xfa, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
0x00, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, /* 0x78-0x7f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x00, /* 0x80-0x87 */
0x8f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
0x00, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
0x8e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
0x00, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, /* 0xa8-0xaf */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0xaa, 0x00, /* 0xb8-0xbf */
0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
};
static const unsigned char cp1256_page20[56] = {
0x00, 0x00, 0x00, 0x00, 0x9d, 0x9e, 0xfd, 0xfe, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x96, 0x97, 0x00, 0x00, 0x00, /* 0x10-0x17 */
0x91, 0x92, 0x82, 0x00, 0x93, 0x94, 0x84, 0x00, /* 0x18-0x1f */
0x86, 0x87, 0x95, 0x00, 0x00, 0x00, 0x85, 0x00, /* 0x20-0x27 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
0x00, 0x8b, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
};
static int
cp1256_wctomb (unsigned char *r, ucs4_t wc, int n)
{
unsigned char c = 0;
if (wc < 0x0080) {
*r = wc;
return 1;
}
else if (wc >= 0x00a0 && wc < 0x0100)
c = cp1256_page00[wc-0x00a0];
else if (wc >= 0x0150 && wc < 0x0198)
c = cp1256_page01[wc-0x0150];
else if (wc == 0x02c6)
c = 0x88;
else if (wc >= 0x0608 && wc < 0x06d8)
c = cp1256_page06[wc-0x0608];
else if (wc >= 0x2008 && wc < 0x2040)
c = cp1256_page20[wc-0x2008];
else if (wc == 0x20ac)
c = 0x80;
else if (wc == 0x2122)
c = 0x99;
if (c != 0) {
*r = c;
return 1;
}
return RET_ILSEQ;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,87 @@
/*
* GEORGIAN-ACADEMY
*/
static const unsigned short georgian_academy_2uni[32] = {
/* 0x80 */
0x0080, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x008e, 0x008f,
/* 0x90 */
0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x009e, 0x0178,
};
static int
georgian_academy_mbtowc (ucs4_t *pwc, const unsigned char *s, int n)
{
unsigned char c = *s;
if (c >= 0x80 && c < 0xa0)
*pwc = (ucs4_t) georgian_academy_2uni[c-0x80];
else if (c >= 0xc0 && c < 0xe7)
*pwc = (ucs4_t) c + 0x1010;
else
*pwc = (ucs4_t) c;
return 1;
}
static const unsigned char georgian_academy_page00[32] = {
0x80, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x9d, 0x9e, 0x00, /* 0x98-0x9f */
};
static const unsigned char georgian_academy_page01[72] = {
0x00, 0x00, 0x8c, 0x9c, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
0x8a, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
};
static const unsigned char georgian_academy_page02[32] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, /* 0xc0-0xc7 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
};
static const unsigned char georgian_academy_page20[48] = {
0x00, 0x00, 0x00, 0x96, 0x97, 0x00, 0x00, 0x00, /* 0x10-0x17 */
0x91, 0x92, 0x82, 0x00, 0x93, 0x94, 0x84, 0x00, /* 0x18-0x1f */
0x86, 0x87, 0x95, 0x00, 0x00, 0x00, 0x85, 0x00, /* 0x20-0x27 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
0x00, 0x8b, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
};
static int
georgian_academy_wctomb (unsigned char *r, ucs4_t wc, int n)
{
unsigned char c = 0;
if (wc < 0x0080) {
*r = wc;
return 1;
}
else if (wc >= 0x0080 && wc < 0x00a0)
c = georgian_academy_page00[wc-0x0080];
else if ((wc >= 0x00a0 && wc < 0x00c0) || (wc >= 0x00e7 && wc < 0x0100))
c = wc;
else if (wc >= 0x0150 && wc < 0x0198)
c = georgian_academy_page01[wc-0x0150];
else if (wc >= 0x02c0 && wc < 0x02e0)
c = georgian_academy_page02[wc-0x02c0];
else if (wc >= 0x10d0 && wc < 0x10f7)
c = wc-0x1010;
else if (wc >= 0x2010 && wc < 0x2040)
c = georgian_academy_page20[wc-0x2010];
else if (wc == 0x2122)
c = 0x99;
if (c != 0) {
*r = c;
return 1;
}
return RET_ILSEQ;
}

View File

@ -0,0 +1,104 @@
/*
* GEORGIAN-PS
*/
static const unsigned short georgian_ps_2uni_1[32] = {
/* 0x80 */
0x0080, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x008e, 0x008f,
/* 0x90 */
0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x009e, 0x0178,
};
static const unsigned short georgian_ps_2uni_2[39] = {
/* 0xc0 */
0x10d0, 0x10d1, 0x10d2, 0x10d3, 0x10d4, 0x10d5, 0x10d6, 0x10f1,
0x10d7, 0x10d8, 0x10d9, 0x10da, 0x10db, 0x10dc, 0x10f2, 0x10dd,
/* 0xd0 */
0x10de, 0x10df, 0x10e0, 0x10e1, 0x10e2, 0x10f3, 0x10e3, 0x10e4,
0x10e5, 0x10e6, 0x10e7, 0x10e8, 0x10e9, 0x10ea, 0x10eb, 0x10ec,
/* 0xe0 */
0x10ed, 0x10ee, 0x10f4, 0x10ef, 0x10f0, 0x10f5,
};
static int
georgian_ps_mbtowc (ucs4_t *pwc, const unsigned char *s, int n)
{
unsigned char c = *s;
if (c >= 0x80 && c < 0xa0)
*pwc = (ucs4_t) georgian_ps_2uni_1[c-0x80];
else if (c >= 0xc0 && c < 0xe6)
*pwc = (ucs4_t) georgian_ps_2uni_2[c-0xc0];
else
*pwc = (ucs4_t) c;
return 1;
}
static const unsigned char georgian_ps_page00[32] = {
0x80, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x9d, 0x9e, 0x00, /* 0x98-0x9f */
};
static const unsigned char georgian_ps_page01[72] = {
0x00, 0x00, 0x8c, 0x9c, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
0x8a, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
};
static const unsigned char georgian_ps_page02[32] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, /* 0xc0-0xc7 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
};
static const unsigned char georgian_ps_page10[40] = {
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc8, /* 0xd0-0xd7 */
0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xcf, 0xd0, 0xd1, /* 0xd8-0xdf */
0xd2, 0xd3, 0xd4, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, /* 0xe0-0xe7 */
0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe3, /* 0xe8-0xef */
0xe4, 0xc7, 0xce, 0xd5, 0xe2, 0xe5, 0x00, 0x00, /* 0xf0-0xf7 */
};
static const unsigned char georgian_ps_page20[48] = {
0x00, 0x00, 0x00, 0x96, 0x97, 0x00, 0x00, 0x00, /* 0x10-0x17 */
0x91, 0x92, 0x82, 0x00, 0x93, 0x94, 0x84, 0x00, /* 0x18-0x1f */
0x86, 0x87, 0x95, 0x00, 0x00, 0x00, 0x85, 0x00, /* 0x20-0x27 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
0x00, 0x8b, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
};
static int
georgian_ps_wctomb (unsigned char *r, ucs4_t wc, int n)
{
unsigned char c = 0;
if (wc < 0x0080) {
*r = wc;
return 1;
}
else if (wc >= 0x0080 && wc < 0x00a0)
c = georgian_ps_page00[wc-0x0080];
else if ((wc >= 0x00a0 && wc < 0x00c0) || (wc >= 0x00e6 && wc < 0x0100))
c = wc;
else if (wc >= 0x0150 && wc < 0x0198)
c = georgian_ps_page01[wc-0x0150];
else if (wc >= 0x02c0 && wc < 0x02e0)
c = georgian_ps_page02[wc-0x02c0];
else if (wc >= 0x10d0 && wc < 0x10f8)
c = georgian_ps_page10[wc-0x10d0];
else if (wc >= 0x2010 && wc < 0x2040)
c = georgian_ps_page20[wc-0x2010];
else if (wc == 0x2122)
c = 0x99;
if (c != 0) {
*r = c;
return 1;
}
return RET_ILSEQ;
}

View File

@ -0,0 +1,22 @@
/*
* ISO-8859-1
*/
static int
iso8859_1_mbtowc (ucs4_t *pwc, const unsigned char *s, int n)
{
unsigned char c = *s;
*pwc = (ucs4_t) c;
return 1;
}
static int
iso8859_1_wctomb (unsigned char *r, ucs4_t wc, int n)
{
if (wc < 0x0100) {
*r = wc;
return 1;
}
return RET_ILSEQ;
}

View File

@ -0,0 +1,87 @@
/*
* ISO-8859-10
*/
static const unsigned short iso8859_10_2uni[96] = {
/* 0xa0 */
0x00a0, 0x0104, 0x0112, 0x0122, 0x012a, 0x0128, 0x0136, 0x00a7,
0x013b, 0x0110, 0x0160, 0x0166, 0x017d, 0x00ad, 0x016a, 0x014a,
/* 0xb0 */
0x00b0, 0x0105, 0x0113, 0x0123, 0x012b, 0x0129, 0x0137, 0x00b7,
0x013c, 0x0111, 0x0161, 0x0167, 0x017e, 0x2015, 0x016b, 0x014b,
/* 0xc0 */
0x0100, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x012e,
0x010c, 0x00c9, 0x0118, 0x00cb, 0x0116, 0x00cd, 0x00ce, 0x00cf,
/* 0xd0 */
0x00d0, 0x0145, 0x014c, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x0168,
0x00d8, 0x0172, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
/* 0xe0 */
0x0101, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x012f,
0x010d, 0x00e9, 0x0119, 0x00eb, 0x0117, 0x00ed, 0x00ee, 0x00ef,
/* 0xf0 */
0x00f0, 0x0146, 0x014d, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x0169,
0x00f8, 0x0173, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x0138,
};
static int
iso8859_10_mbtowc (ucs4_t *pwc, const unsigned char *s, int n)
{
unsigned char c = *s;
if (c < 0xa0)
*pwc = (ucs4_t) c;
else
*pwc = (ucs4_t) iso8859_10_2uni[c-0xa0];
return 1;
}
static const unsigned char iso8859_10_page00[224] = {
0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, /* 0xa0-0xa7 */
0x00, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, /* 0xa8-0xaf */
0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, /* 0xb0-0xb7 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
0x00, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0x00, /* 0xc0-0xc7 */
0x00, 0xc9, 0x00, 0xcb, 0x00, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
0xd0, 0x00, 0x00, 0xd3, 0xd4, 0xd5, 0xd6, 0x00, /* 0xd0-0xd7 */
0xd8, 0x00, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
0x00, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0x00, /* 0xe0-0xe7 */
0x00, 0xe9, 0x00, 0xeb, 0x00, 0xed, 0xee, 0xef, /* 0xe8-0xef */
0xf0, 0x00, 0x00, 0xf3, 0xf4, 0xf5, 0xf6, 0x00, /* 0xf0-0xf7 */
0xf8, 0x00, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0x00, /* 0xf8-0xff */
/* 0x0100 */
0xc0, 0xe0, 0x00, 0x00, 0xa1, 0xb1, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0xc8, 0xe8, 0x00, 0x00, /* 0x08-0x0f */
0xa9, 0xb9, 0xa2, 0xb2, 0x00, 0x00, 0xcc, 0xec, /* 0x10-0x17 */
0xca, 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
0x00, 0x00, 0xa3, 0xb3, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
0xa5, 0xb5, 0xa4, 0xb4, 0x00, 0x00, 0xc7, 0xe7, /* 0x28-0x2f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa6, 0xb6, /* 0x30-0x37 */
0xff, 0x00, 0x00, 0xa8, 0xb8, 0x00, 0x00, 0x00, /* 0x38-0x3f */
0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xf1, 0x00, /* 0x40-0x47 */
0x00, 0x00, 0xaf, 0xbf, 0xd2, 0xf2, 0x00, 0x00, /* 0x48-0x4f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
0xaa, 0xba, 0x00, 0x00, 0x00, 0x00, 0xab, 0xbb, /* 0x60-0x67 */
0xd7, 0xf7, 0xae, 0xbe, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
0x00, 0x00, 0xd9, 0xf9, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0xbc, 0x00, /* 0x78-0x7f */
};
static int
iso8859_10_wctomb (unsigned char *r, ucs4_t wc, int n)
{
unsigned char c = 0;
if (wc < 0x00a0) {
*r = wc;
return 1;
}
else if (wc >= 0x00a0 && wc < 0x0180)
c = iso8859_10_page00[wc-0x00a0];
else if (wc == 0x2015)
c = 0xbd;
if (c != 0) {
*r = c;
return 1;
}
return RET_ILSEQ;
}

View File

@ -0,0 +1,77 @@
/*
* ISO8859-11
*/
static const unsigned short iso8859_11_2uni[96] = {
/* 0xa0 */
0x00a0, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07,
0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f,
/* 0xb0 */
0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17,
0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f,
/* 0xc0 */
0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27,
0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f,
/* 0xd0 */
0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37,
0x0e38, 0x0e39, 0x0e3a, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x0e3f,
/* 0xe0 */
0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47,
0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e4e, 0x0e4f,
/* 0xf0 */
0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57,
0x0e58, 0x0e59, 0x0e5a, 0x0e5b, 0xfffd, 0xfffd, 0xfffd, 0xfffd,
};
static int
iso8859_11_mbtowc (ucs4_t *pwc, const unsigned char *s, int n)
{
unsigned char c = *s;
if (c < 0x80) {
*pwc = (ucs4_t) c;
return 1;
}
else if (c < 0xa0) {
}
else {
unsigned short wc = iso8859_11_2uni[c-0xa0];
if (wc != 0xfffd) {
*pwc = (ucs4_t) wc;
return 1;
}
}
return RET_ILSEQ;
}
static const unsigned char iso8859_11_page0e[96] = {
0x00, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0x00-0x07 */
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0x08-0x0f */
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0x10-0x17 */
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0x18-0x1f */
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0x20-0x27 */
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0x28-0x2f */
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0x30-0x37 */
0xd8, 0xd9, 0xda, 0x00, 0x00, 0x00, 0x00, 0xdf, /* 0x38-0x3f */
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0x40-0x47 */
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0x48-0x4f */
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0x50-0x57 */
0xf8, 0xf9, 0xfa, 0xfb, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
};
static int
iso8859_11_wctomb (unsigned char *r, ucs4_t wc, int n)
{
unsigned char c = 0;
if (wc < 0x0080 || wc == 0x00a0) {
*r = wc;
return 1;
}
else if (wc >= 0x0e00 && wc < 0x0e60)
c = iso8859_11_page0e[wc-0x0e00];
if (c != 0) {
*r = c;
return 1;
}
return RET_ILSEQ;
}

View File

@ -0,0 +1,90 @@
/*
* ISO-8859-13
*/
static const unsigned short iso8859_13_2uni[96] = {
/* 0xa0 */
0x00a0, 0x201d, 0x00a2, 0x00a3, 0x00a4, 0x201e, 0x00a6, 0x00a7,
0x00d8, 0x00a9, 0x0156, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00c6,
/* 0xb0 */
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x201c, 0x00b5, 0x00b6, 0x00b7,
0x00f8, 0x00b9, 0x0157, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00e6,
/* 0xc0 */
0x0104, 0x012e, 0x0100, 0x0106, 0x00c4, 0x00c5, 0x0118, 0x0112,
0x010c, 0x00c9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012a, 0x013b,
/* 0xd0 */
0x0160, 0x0143, 0x0145, 0x00d3, 0x014c, 0x00d5, 0x00d6, 0x00d7,
0x0172, 0x0141, 0x015a, 0x016a, 0x00dc, 0x017b, 0x017d, 0x00df,
/* 0xe0 */
0x0105, 0x012f, 0x0101, 0x0107, 0x00e4, 0x00e5, 0x0119, 0x0113,
0x010d, 0x00e9, 0x017a, 0x0117, 0x0123, 0x0137, 0x012b, 0x013c,
/* 0xf0 */
0x0161, 0x0144, 0x0146, 0x00f3, 0x014d, 0x00f5, 0x00f6, 0x00f7,
0x0173, 0x0142, 0x015b, 0x016b, 0x00fc, 0x017c, 0x017e, 0x2019,
};
static int
iso8859_13_mbtowc (ucs4_t *pwc, const unsigned char *s, int n)
{
unsigned char c = *s;
if (c < 0xa0)
*pwc = (ucs4_t) c;
else
*pwc = (ucs4_t) iso8859_13_2uni[c-0xa0];
return 1;
}
static const unsigned char iso8859_13_page00[224] = {
0xa0, 0x00, 0xa2, 0xa3, 0xa4, 0x00, 0xa6, 0xa7, /* 0xa0-0xa7 */
0x00, 0xa9, 0x00, 0xab, 0xac, 0xad, 0xae, 0x00, /* 0xa8-0xaf */
0xb0, 0xb1, 0xb2, 0xb3, 0x00, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
0x00, 0xb9, 0x00, 0xbb, 0xbc, 0xbd, 0xbe, 0x00, /* 0xb8-0xbf */
0x00, 0x00, 0x00, 0x00, 0xc4, 0xc5, 0xaf, 0x00, /* 0xc0-0xc7 */
0x00, 0xc9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
0x00, 0x00, 0x00, 0xd3, 0x00, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
0xa8, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0xdf, /* 0xd8-0xdf */
0x00, 0x00, 0x00, 0x00, 0xe4, 0xe5, 0xbf, 0x00, /* 0xe0-0xe7 */
0x00, 0xe9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
0x00, 0x00, 0x00, 0xf3, 0x00, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
0xb8, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, /* 0xf8-0xff */
/* 0x0100 */
0xc2, 0xe2, 0x00, 0x00, 0xc0, 0xe0, 0xc3, 0xe3, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0xc8, 0xe8, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0xc7, 0xe7, 0x00, 0x00, 0xcb, 0xeb, /* 0x10-0x17 */
0xc6, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
0x00, 0x00, 0xcc, 0xec, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
0x00, 0x00, 0xce, 0xee, 0x00, 0x00, 0xc1, 0xe1, /* 0x28-0x2f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xed, /* 0x30-0x37 */
0x00, 0x00, 0x00, 0xcf, 0xef, 0x00, 0x00, 0x00, /* 0x38-0x3f */
0x00, 0xd9, 0xf9, 0xd1, 0xf1, 0xd2, 0xf2, 0x00, /* 0x40-0x47 */
0x00, 0x00, 0x00, 0x00, 0xd4, 0xf4, 0x00, 0x00, /* 0x48-0x4f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xba, /* 0x50-0x57 */
0x00, 0x00, 0xda, 0xfa, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
0xd0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
0x00, 0x00, 0xdb, 0xfb, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
0x00, 0x00, 0xd8, 0xf8, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
0x00, 0xca, 0xea, 0xdd, 0xfd, 0xde, 0xfe, 0x00, /* 0x78-0x7f */
};
static const unsigned char iso8859_13_page20[8] = {
0x00, 0xff, 0x00, 0x00, 0xb4, 0xa1, 0xa5, 0x00, /* 0x18-0x1f */
};
static int
iso8859_13_wctomb (unsigned char *r, ucs4_t wc, int n)
{
unsigned char c = 0;
if (wc < 0x00a0) {
*r = wc;
return 1;
}
else if (wc >= 0x00a0 && wc < 0x0180)
c = iso8859_13_page00[wc-0x00a0];
else if (wc >= 0x2018 && wc < 0x2020)
c = iso8859_13_page20[wc-0x2018];
if (c != 0) {
*r = c;
return 1;
}
return RET_ILSEQ;
}

View File

@ -0,0 +1,108 @@
/*
* ISO-8859-14
*/
static const unsigned short iso8859_14_2uni[96] = {
/* 0xa0 */
0x00a0, 0x1e02, 0x1e03, 0x00a3, 0x010a, 0x010b, 0x1e0a, 0x00a7,
0x1e80, 0x00a9, 0x1e82, 0x1e0b, 0x1ef2, 0x00ad, 0x00ae, 0x0178,
/* 0xb0 */
0x1e1e, 0x1e1f, 0x0120, 0x0121, 0x1e40, 0x1e41, 0x00b6, 0x1e56,
0x1e81, 0x1e57, 0x1e83, 0x1e60, 0x1ef3, 0x1e84, 0x1e85, 0x1e61,
/* 0xc0 */
0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
/* 0xd0 */
0x0174, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x1e6a,
0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x0176, 0x00df,
/* 0xe0 */
0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
/* 0xf0 */
0x0175, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x1e6b,
0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x0177, 0x00ff,
};
static int
iso8859_14_mbtowc (ucs4_t *pwc, const unsigned char *s, int n)
{
unsigned char c = *s;
if (c >= 0xa0)
*pwc = (ucs4_t) iso8859_14_2uni[c-0xa0];
else
*pwc = (ucs4_t) c;
return 1;
}
static const unsigned char iso8859_14_page00[96] = {
0xa0, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0xa7, /* 0xa0-0xa7 */
0x00, 0xa9, 0x00, 0x00, 0x00, 0xad, 0xae, 0x00, /* 0xa8-0xaf */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb6, 0x00, /* 0xb0-0xb7 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
0x00, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0x00, /* 0xd0-0xd7 */
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0x00, 0xdf, /* 0xd8-0xdf */
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0x00, /* 0xf0-0xf7 */
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0x00, 0xff, /* 0xf8-0xff */
};
static const unsigned char iso8859_14_page01_0[32] = {
0x00, 0x00, 0xa4, 0xa5, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
0xb2, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
};
static const unsigned char iso8859_14_page01_1[16] = {
0x00, 0x00, 0x00, 0x00, 0xd0, 0xf0, 0xde, 0xfe, /* 0x70-0x77 */
0xaf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
};
static const unsigned char iso8859_14_page1e_0[136] = {
0x00, 0x00, 0xa1, 0xa2, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0xa6, 0xab, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xb1, /* 0x18-0x1f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
0xb4, 0xb5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0xb9, /* 0x50-0x57 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
0xbb, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
0x00, 0x00, 0xd7, 0xf7, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
0xa8, 0xb8, 0xaa, 0xba, 0xbd, 0xbe, 0x00, 0x00, /* 0x80-0x87 */
};
static const unsigned char iso8859_14_page1e_1[8] = {
0x00, 0x00, 0xac, 0xbc, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
};
static int
iso8859_14_wctomb (unsigned char *r, ucs4_t wc, int n)
{
unsigned char c = 0;
if (wc < 0x00a0) {
*r = wc;
return 1;
}
else if (wc >= 0x00a0 && wc < 0x0100)
c = iso8859_14_page00[wc-0x00a0];
else if (wc >= 0x0108 && wc < 0x0128)
c = iso8859_14_page01_0[wc-0x0108];
else if (wc >= 0x0170 && wc < 0x0180)
c = iso8859_14_page01_1[wc-0x0170];
else if (wc >= 0x1e00 && wc < 0x1e88)
c = iso8859_14_page1e_0[wc-0x1e00];
else if (wc >= 0x1ef0 && wc < 0x1ef8)
c = iso8859_14_page1e_1[wc-0x1ef0];
if (c != 0) {
*r = c;
return 1;
}
return RET_ILSEQ;
}

View File

@ -0,0 +1,62 @@
/*
* ISO-8859-15
*/
static const unsigned short iso8859_15_2uni[32] = {
/* 0xa0 */
0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x20ac, 0x00a5, 0x0160, 0x00a7,
0x0161, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
/* 0xb0 */
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x017d, 0x00b5, 0x00b6, 0x00b7,
0x017e, 0x00b9, 0x00ba, 0x00bb, 0x0152, 0x0153, 0x0178, 0x00bf,
};
static int
iso8859_15_mbtowc (ucs4_t *pwc, const unsigned char *s, int n)
{
unsigned char c = *s;
if (c >= 0xa0 && c < 0xc0)
*pwc = (ucs4_t) iso8859_15_2uni[c-0xa0];
else
*pwc = (ucs4_t) c;
return 1;
}
static const unsigned char iso8859_15_page00[32] = {
0xa0, 0xa1, 0xa2, 0xa3, 0x00, 0xa5, 0x00, 0xa7, /* 0xa0-0xa7 */
0x00, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
0xb0, 0xb1, 0xb2, 0xb3, 0x00, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
0x00, 0xb9, 0xba, 0xbb, 0x00, 0x00, 0x00, 0xbf, /* 0xb8-0xbf */
};
static const unsigned char iso8859_15_page01[48] = {
0x00, 0x00, 0xbc, 0xbd, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
0xa6, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
0xbe, 0x00, 0x00, 0x00, 0x00, 0xb4, 0xb8, 0x00, /* 0x78-0x7f */
};
static int
iso8859_15_wctomb (unsigned char *r, ucs4_t wc, int n)
{
unsigned char c = 0;
if (wc < 0x00a0) {
*r = wc;
return 1;
}
else if (wc >= 0x00a0 && wc < 0x00c0)
c = iso8859_15_page00[wc-0x00a0];
else if (wc >= 0x00c0 && wc < 0x0100)
c = wc;
else if (wc >= 0x0150 && wc < 0x0180)
c = iso8859_15_page01[wc-0x0150];
else if (wc == 0x20ac)
c = 0xa4;
if (c != 0) {
*r = c;
return 1;
}
return RET_ILSEQ;
}

View File

@ -0,0 +1,97 @@
/*
* ISO-8859-16
*/
static const unsigned short iso8859_16_2uni[96] = {
/* 0xa0 */
0x00a0, 0x0104, 0x0105, 0x0141, 0x20ac, 0x201e, 0x0160, 0x00a7,
0x0161, 0x00a9, 0x0218, 0x00ab, 0x0179, 0x00ad, 0x017a, 0x017b,
/* 0xb0 */
0x00b0, 0x00b1, 0x010c, 0x0142, 0x017d, 0x201d, 0x00b6, 0x00b7,
0x017e, 0x010d, 0x0219, 0x00bb, 0x0152, 0x0153, 0x0178, 0x017c,
/* 0xc0 */
0x00c0, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0106, 0x00c6, 0x00c7,
0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
/* 0xd0 */
0x0110, 0x0143, 0x00d2, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x015a,
0x0170, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0118, 0x021a, 0x00df,
/* 0xe0 */
0x00e0, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x0107, 0x00e6, 0x00e7,
0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
/* 0xf0 */
0x0111, 0x0144, 0x00f2, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x015b,
0x0171, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0119, 0x021b, 0x00ff,
};
static int
iso8859_16_mbtowc (ucs4_t *pwc, const unsigned char *s, int n)
{
unsigned char c = *s;
if (c < 0xa0)
*pwc = (ucs4_t) c;
else
*pwc = (ucs4_t) iso8859_16_2uni[c-0xa0];
return 1;
}
static const unsigned char iso8859_16_page00[224] = {
0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, /* 0xa0-0xa7 */
0x00, 0xa9, 0x00, 0xab, 0x00, 0xad, 0x00, 0x00, /* 0xa8-0xaf */
0xb0, 0xb1, 0x00, 0x00, 0x00, 0x00, 0xb6, 0xb7, /* 0xb0-0xb7 */
0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
0xc0, 0xc1, 0xc2, 0x00, 0xc4, 0x00, 0xc6, 0xc7, /* 0xc0-0xc7 */
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
0x00, 0x00, 0xd2, 0xd3, 0xd4, 0x00, 0xd6, 0x00, /* 0xd0-0xd7 */
0x00, 0xd9, 0xda, 0xdb, 0xdc, 0x00, 0x00, 0xdf, /* 0xd8-0xdf */
0xe0, 0xe1, 0xe2, 0x00, 0xe4, 0x00, 0xe6, 0xe7, /* 0xe0-0xe7 */
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
0x00, 0x00, 0xf2, 0xf3, 0xf4, 0x00, 0xf6, 0x00, /* 0xf0-0xf7 */
0x00, 0xf9, 0xfa, 0xfb, 0xfc, 0x00, 0x00, 0xff, /* 0xf8-0xff */
/* 0x0100 */
0x00, 0x00, 0xc3, 0xe3, 0xa1, 0xa2, 0xc5, 0xe5, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0xb2, 0xb9, 0x00, 0x00, /* 0x08-0x0f */
0xd0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
0xdd, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
0x00, 0xa3, 0xb3, 0xd1, 0xf1, 0x00, 0x00, 0x00, /* 0x40-0x47 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
0xd5, 0xf5, 0xbc, 0xbd, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
0x00, 0x00, 0xd7, 0xf7, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
0xa6, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
0xd8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
0xbe, 0xac, 0xae, 0xaf, 0xbf, 0xb4, 0xb8, 0x00, /* 0x78-0x7f */
};
static const unsigned char iso8859_16_page02[8] = {
0xaa, 0xba, 0xde, 0xfe, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
};
static const unsigned char iso8859_16_page20[8] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0xb5, 0xa5, 0x00, /* 0x18-0x1f */
};
static int
iso8859_16_wctomb (unsigned char *r, ucs4_t wc, int n)
{
unsigned char c = 0;
if (wc < 0x00a0) {
*r = wc;
return 1;
}
else if (wc >= 0x00a0 && wc < 0x0180)
c = iso8859_16_page00[wc-0x00a0];
else if (wc >= 0x0218 && wc < 0x0220)
c = iso8859_16_page02[wc-0x0218];
else if (wc >= 0x2018 && wc < 0x2020)
c = iso8859_16_page20[wc-0x2018];
else if (wc == 0x20ac)
c = 0xa4;
if (c != 0) {
*r = c;
return 1;
}
return RET_ILSEQ;
}

View File

@ -0,0 +1,93 @@
/*
* ISO-8859-2
*/
static const unsigned short iso8859_2_2uni[96] = {
/* 0xa0 */
0x00a0, 0x0104, 0x02d8, 0x0141, 0x00a4, 0x013d, 0x015a, 0x00a7,
0x00a8, 0x0160, 0x015e, 0x0164, 0x0179, 0x00ad, 0x017d, 0x017b,
/* 0xb0 */
0x00b0, 0x0105, 0x02db, 0x0142, 0x00b4, 0x013e, 0x015b, 0x02c7,
0x00b8, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c,
/* 0xc0 */
0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7,
0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e,
/* 0xd0 */
0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7,
0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df,
/* 0xe0 */
0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7,
0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f,
/* 0xf0 */
0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7,
0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9,
};
static int
iso8859_2_mbtowc (ucs4_t *pwc, const unsigned char *s, int n)
{
unsigned char c = *s;
if (c < 0xa0)
*pwc = (ucs4_t) c;
else
*pwc = (ucs4_t) iso8859_2_2uni[c-0xa0];
return 1;
}
static const unsigned char iso8859_2_page00[224] = {
0xa0, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0xa7, /* 0xa0-0xa7 */
0xa8, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, /* 0xa8-0xaf */
0xb0, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
0x00, 0xc1, 0xc2, 0x00, 0xc4, 0x00, 0x00, 0xc7, /* 0xc0-0xc7 */
0x00, 0xc9, 0x00, 0xcb, 0x00, 0xcd, 0xce, 0x00, /* 0xc8-0xcf */
0x00, 0x00, 0x00, 0xd3, 0xd4, 0x00, 0xd6, 0xd7, /* 0xd0-0xd7 */
0x00, 0x00, 0xda, 0x00, 0xdc, 0xdd, 0x00, 0xdf, /* 0xd8-0xdf */
0x00, 0xe1, 0xe2, 0x00, 0xe4, 0x00, 0x00, 0xe7, /* 0xe0-0xe7 */
0x00, 0xe9, 0x00, 0xeb, 0x00, 0xed, 0xee, 0x00, /* 0xe8-0xef */
0x00, 0x00, 0x00, 0xf3, 0xf4, 0x00, 0xf6, 0xf7, /* 0xf0-0xf7 */
0x00, 0x00, 0xfa, 0x00, 0xfc, 0xfd, 0x00, 0x00, /* 0xf8-0xff */
/* 0x0100 */
0x00, 0x00, 0xc3, 0xe3, 0xa1, 0xb1, 0xc6, 0xe6, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0xc8, 0xe8, 0xcf, 0xef, /* 0x08-0x0f */
0xd0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
0xca, 0xea, 0xcc, 0xec, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
0x00, 0xc5, 0xe5, 0x00, 0x00, 0xa5, 0xb5, 0x00, /* 0x38-0x3f */
0x00, 0xa3, 0xb3, 0xd1, 0xf1, 0x00, 0x00, 0xd2, /* 0x40-0x47 */
0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
0xd5, 0xf5, 0x00, 0x00, 0xc0, 0xe0, 0x00, 0x00, /* 0x50-0x57 */
0xd8, 0xf8, 0xa6, 0xb6, 0x00, 0x00, 0xaa, 0xba, /* 0x58-0x5f */
0xa9, 0xb9, 0xde, 0xfe, 0xab, 0xbb, 0x00, 0x00, /* 0x60-0x67 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9, 0xf9, /* 0x68-0x6f */
0xdb, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
0x00, 0xac, 0xbc, 0xaf, 0xbf, 0xae, 0xbe, 0x00, /* 0x78-0x7f */
};
static const unsigned char iso8859_2_page02[32] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, /* 0xc0-0xc7 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
0xa2, 0xff, 0x00, 0xb2, 0x00, 0xbd, 0x00, 0x00, /* 0xd8-0xdf */
};
static int
iso8859_2_wctomb (unsigned char *r, ucs4_t wc, int n)
{
unsigned char c = 0;
if (wc < 0x00a0) {
*r = wc;
return 1;
}
else if (wc >= 0x00a0 && wc < 0x0180)
c = iso8859_2_page00[wc-0x00a0];
else if (wc >= 0x02c0 && wc < 0x02e0)
c = iso8859_2_page02[wc-0x02c0];
if (c != 0) {
*r = c;
return 1;
}
return RET_ILSEQ;
}

View File

@ -0,0 +1,99 @@
/*
* ISO-8859-3
*/
static const unsigned short iso8859_3_2uni[96] = {
/* 0xa0 */
0x00a0, 0x0126, 0x02d8, 0x00a3, 0x00a4, 0xfffd, 0x0124, 0x00a7,
0x00a8, 0x0130, 0x015e, 0x011e, 0x0134, 0x00ad, 0xfffd, 0x017b,
/* 0xb0 */
0x00b0, 0x0127, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x0125, 0x00b7,
0x00b8, 0x0131, 0x015f, 0x011f, 0x0135, 0x00bd, 0xfffd, 0x017c,
/* 0xc0 */
0x00c0, 0x00c1, 0x00c2, 0xfffd, 0x00c4, 0x010a, 0x0108, 0x00c7,
0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
/* 0xd0 */
0xfffd, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x0120, 0x00d6, 0x00d7,
0x011c, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x016c, 0x015c, 0x00df,
/* 0xe0 */
0x00e0, 0x00e1, 0x00e2, 0xfffd, 0x00e4, 0x010b, 0x0109, 0x00e7,
0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
/* 0xf0 */
0xfffd, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x0121, 0x00f6, 0x00f7,
0x011d, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x016d, 0x015d, 0x02d9,
};
static int
iso8859_3_mbtowc (ucs4_t *pwc, const unsigned char *s, int n)
{
unsigned char c = *s;
if (c < 0xa0) {
*pwc = (ucs4_t) c;
return 1;
}
else {
unsigned short wc = iso8859_3_2uni[c-0xa0];
if (wc != 0xfffd) {
*pwc = (ucs4_t) wc;
return 1;
}
}
return RET_ILSEQ;
}
static const unsigned char iso8859_3_page00[96] = {
0xa0, 0x00, 0x00, 0xa3, 0xa4, 0x00, 0x00, 0xa7, /* 0xa0-0xa7 */
0xa8, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, /* 0xa8-0xaf */
0xb0, 0x00, 0xb2, 0xb3, 0xb4, 0xb5, 0x00, 0xb7, /* 0xb0-0xb7 */
0xb8, 0x00, 0x00, 0x00, 0x00, 0xbd, 0x00, 0x00, /* 0xb8-0xbf */
0xc0, 0xc1, 0xc2, 0x00, 0xc4, 0x00, 0x00, 0xc7, /* 0xc0-0xc7 */
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
0x00, 0xd1, 0xd2, 0xd3, 0xd4, 0x00, 0xd6, 0xd7, /* 0xd0-0xd7 */
0x00, 0xd9, 0xda, 0xdb, 0xdc, 0x00, 0x00, 0xdf, /* 0xd8-0xdf */
0xe0, 0xe1, 0xe2, 0x00, 0xe4, 0x00, 0x00, 0xe7, /* 0xe0-0xe7 */
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0x00, 0xf6, 0xf7, /* 0xf0-0xf7 */
0x00, 0xf9, 0xfa, 0xfb, 0xfc, 0x00, 0x00, 0x00, /* 0xf8-0xff */
};
static const unsigned char iso8859_3_page01[120] = {
0xc6, 0xe6, 0xc5, 0xe5, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
0x00, 0x00, 0x00, 0x00, 0xd8, 0xf8, 0xab, 0xbb, /* 0x18-0x1f */
0xd5, 0xf5, 0x00, 0x00, 0xa6, 0xb6, 0xa1, 0xb1, /* 0x20-0x27 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
0xa9, 0xb9, 0x00, 0x00, 0xac, 0xbc, 0x00, 0x00, /* 0x30-0x37 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
0x00, 0x00, 0x00, 0x00, 0xde, 0xfe, 0xaa, 0xba, /* 0x58-0x5f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
0x00, 0x00, 0x00, 0x00, 0xdd, 0xfd, 0x00, 0x00, /* 0x68-0x6f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
0x00, 0x00, 0x00, 0xaf, 0xbf, 0x00, 0x00, 0x00, /* 0x78-0x7f */
};
static const unsigned char iso8859_3_page02[8] = {
0xa2, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
};
static int
iso8859_3_wctomb (unsigned char *r, ucs4_t wc, int n)
{
unsigned char c = 0;
if (wc < 0x00a0) {
*r = wc;
return 1;
}
else if (wc >= 0x00a0 && wc < 0x0100)
c = iso8859_3_page00[wc-0x00a0];
else if (wc >= 0x0108 && wc < 0x0180)
c = iso8859_3_page01[wc-0x0108];
else if (wc >= 0x02d8 && wc < 0x02e0)
c = iso8859_3_page02[wc-0x02d8];
if (c != 0) {
*r = c;
return 1;
}
return RET_ILSEQ;
}

View File

@ -0,0 +1,93 @@
/*
* ISO-8859-4
*/
static const unsigned short iso8859_4_2uni[96] = {
/* 0xa0 */
0x00a0, 0x0104, 0x0138, 0x0156, 0x00a4, 0x0128, 0x013b, 0x00a7,
0x00a8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00ad, 0x017d, 0x00af,
/* 0xb0 */
0x00b0, 0x0105, 0x02db, 0x0157, 0x00b4, 0x0129, 0x013c, 0x02c7,
0x00b8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014a, 0x017e, 0x014b,
/* 0xc0 */
0x0100, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x012e,
0x010c, 0x00c9, 0x0118, 0x00cb, 0x0116, 0x00cd, 0x00ce, 0x012a,
/* 0xd0 */
0x0110, 0x0145, 0x014c, 0x0136, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
0x00d8, 0x0172, 0x00da, 0x00db, 0x00dc, 0x0168, 0x016a, 0x00df,
/* 0xe0 */
0x0101, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x012f,
0x010d, 0x00e9, 0x0119, 0x00eb, 0x0117, 0x00ed, 0x00ee, 0x012b,
/* 0xf0 */
0x0111, 0x0146, 0x014d, 0x0137, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
0x00f8, 0x0173, 0x00fa, 0x00fb, 0x00fc, 0x0169, 0x016b, 0x02d9,
};
static int
iso8859_4_mbtowc (ucs4_t *pwc, const unsigned char *s, int n)
{
unsigned char c = *s;
if (c < 0xa0)
*pwc = (ucs4_t) c;
else
*pwc = (ucs4_t) iso8859_4_2uni[c-0xa0];
return 1;
}
static const unsigned char iso8859_4_page00[224] = {
0xa0, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0xa7, /* 0xa0-0xa7 */
0xa8, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0xaf, /* 0xa8-0xaf */
0xb0, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
0x00, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0x00, /* 0xc0-0xc7 */
0x00, 0xc9, 0x00, 0xcb, 0x00, 0xcd, 0xce, 0x00, /* 0xc8-0xcf */
0x00, 0x00, 0x00, 0x00, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
0xd8, 0x00, 0xda, 0xdb, 0xdc, 0x00, 0x00, 0xdf, /* 0xd8-0xdf */
0x00, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0x00, /* 0xe0-0xe7 */
0x00, 0xe9, 0x00, 0xeb, 0x00, 0xed, 0xee, 0x00, /* 0xe8-0xef */
0x00, 0x00, 0x00, 0x00, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
0xf8, 0x00, 0xfa, 0xfb, 0xfc, 0x00, 0x00, 0x00, /* 0xf8-0xff */
/* 0x0100 */
0xc0, 0xe0, 0x00, 0x00, 0xa1, 0xb1, 0x00, 0x00, /* 0x00-0x07 */
0x00, 0x00, 0x00, 0x00, 0xc8, 0xe8, 0x00, 0x00, /* 0x08-0x0f */
0xd0, 0xf0, 0xaa, 0xba, 0x00, 0x00, 0xcc, 0xec, /* 0x10-0x17 */
0xca, 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
0x00, 0x00, 0xab, 0xbb, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
0xa5, 0xb5, 0xcf, 0xef, 0x00, 0x00, 0xc7, 0xe7, /* 0x28-0x2f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd3, 0xf3, /* 0x30-0x37 */
0xa2, 0x00, 0x00, 0xa6, 0xb6, 0x00, 0x00, 0x00, /* 0x38-0x3f */
0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xf1, 0x00, /* 0x40-0x47 */
0x00, 0x00, 0xbd, 0xbf, 0xd2, 0xf2, 0x00, 0x00, /* 0x48-0x4f */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa3, 0xb3, /* 0x50-0x57 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
0xa9, 0xb9, 0x00, 0x00, 0x00, 0x00, 0xac, 0xbc, /* 0x60-0x67 */
0xdd, 0xfd, 0xde, 0xfe, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
0x00, 0x00, 0xd9, 0xf9, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0xbe, 0x00, /* 0x78-0x7f */
};
static const unsigned char iso8859_4_page02[32] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, /* 0xc0-0xc7 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
0x00, 0xff, 0x00, 0xb2, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
};
static int
iso8859_4_wctomb (unsigned char *r, ucs4_t wc, int n)
{
unsigned char c = 0;
if (wc < 0x00a0) {
*r = wc;
return 1;
}
else if (wc >= 0x00a0 && wc < 0x0180)
c = iso8859_4_page00[wc-0x00a0];
else if (wc >= 0x02c0 && wc < 0x02e0)
c = iso8859_4_page02[wc-0x02c0];
if (c != 0) {
*r = c;
return 1;
}
return RET_ILSEQ;
}

View File

@ -0,0 +1,76 @@
/*
* ISO-8859-5
*/
static const unsigned short iso8859_5_2uni[96] = {
/* 0xa0 */
0x00a0, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,
0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x00ad, 0x040e, 0x040f,
/* 0xb0 */
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
/* 0xc0 */
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
/* 0xd0 */
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f,
/* 0xe0 */
0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f,
/* 0xf0 */
0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,
0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x00a7, 0x045e, 0x045f,
};
static int
iso8859_5_mbtowc (ucs4_t *pwc, const unsigned char *s, int n)
{
unsigned char c = *s;
if (c < 0xa0)
*pwc = (ucs4_t) c;
else
*pwc = (ucs4_t) iso8859_5_2uni[c-0xa0];
return 1;
}
static const unsigned char iso8859_5_page00[16] = {
0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, /* 0xa0-0xa7 */
0x00, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, /* 0xa8-0xaf */
};
static const unsigned char iso8859_5_page04[96] = {
0x00, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0x00-0x07 */
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0x00, 0xae, 0xaf, /* 0x08-0x0f */
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0x10-0x17 */
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0x18-0x1f */
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0x20-0x27 */
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0x28-0x2f */
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0x30-0x37 */
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0x38-0x3f */
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0x40-0x47 */
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0x48-0x4f */
0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0x50-0x57 */
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0x00, 0xfe, 0xff, /* 0x58-0x5f */
};
static int
iso8859_5_wctomb (unsigned char *r, ucs4_t wc, int n)
{
unsigned char c = 0;
if (wc < 0x00a0) {
*r = wc;
return 1;
}
else if (wc >= 0x00a0 && wc < 0x00b0)
c = iso8859_5_page00[wc-0x00a0];
else if (wc >= 0x0400 && wc < 0x0460)
c = iso8859_5_page04[wc-0x0400];
else if (wc == 0x2116)
c = 0xf0;
if (c != 0) {
*r = c;
return 1;
}
return RET_ILSEQ;
}

Some files were not shown because too many files have changed in this diff Show More