#include #include #include #include #include #include #include #include struct sj4ime { Sj4Lib* lib; int charset; Sj4ImePacket packet; Sj4Kouho kouho; unsigned int length; char romabuf[7]; u_char kanabuf[SJ4BUFSZ]; u_char convbuf[SJ4BUFSZ]; }; static struct sj4table { const char* roma; u_char* kana; const char* roma2; } kanatbl[] = { #include "KanaTable" }; #define DISPATCH(x, y) \ if(ime->packet != NULL) { \ ime->packet(ime, (x), (y)); \ } Sj4Ime* sj4_ime(int charset, const char* dict, Sj4ImePacket packet) { Sj4Ime* ime; if((ime = calloc(1, sizeof(*ime))) == NULL) return NULL; if((ime->lib = sj4_open(charset, dict)) == NULL) { free(ime); return NULL; } ime->charset = charset; ime->packet = packet; } static int w_len(wchar_t* wc) { int i; for(i = 0; wc[i] != 0; i++); return i; } static int b_len(int charset, u_char* buffer) { if(charset == SJ4UTF16) { return w_len((wchar_t*)buffer); } else { return strlen(buffer); } } static void concat(int charset, u_char* out, u_char* in) { int i; #ifdef UCS if(charset == SJ4UTF16) { wchar_t* w_out = (wchar_t*)out; i = w_len(w_out); w_out[i + sj4_charset_to(charset, (u_char*)(w_out + i), in, strlen(in))] = 0; } else #else { i = strlen(out); out[i + sj4_charset_to(charset, out + i, in, strlen(in))] = 0; } #endif } static void concat_nc(int charset, u_char* out, u_char* in) { int i, j; #ifdef UCS if(charset == SJ4UTF16) { wchar_t* w_out = (wchar_t*)out; i = w_len(w_out); j = w_len((wchar_t*)in); memcpy(w_out + i, in, j * sizeof(wchar_t)); w_out[i + j] = 0; } else #else { i = strlen(out); j = strlen(in); memcpy(out + i, in, j); out[i + j] = 0; } #endif } #define ZEROBUF memset(&ime->kouho.buffer, 0, sizeof(ime->kouho.buffer)) static void comp(Sj4Ime* ime) { #if 0 do { #endif if(ime->length == 0) { concat_nc(ime->charset, ime->convbuf, ime->kanabuf); #ifdef UCS memset(ime->kanabuf, 0, sizeof(wchar_t)); #else ime->kanabuf[0] = 0; #endif } else { int sc = ime->charset == SJ4UTF16 ? sizeof(wchar_t) : 1; concat_nc(ime->charset, ime->convbuf, ime->kouho.buffer.raw); memmove(ime->kanabuf, ime->kanabuf + ime->length * sc, SJ4BUFSZ - ime->length * sc); memset(ime->kanabuf + SJ4BUFSZ - ime->length * sc, 0, ime->length * sc); } ime->length = 0; ZEROBUF; #if 0 } while(b_len(ime->charset, ime->kanabuf) > 0); #endif } void sj4_ime_key(Sj4Ime* ime, int key) { if(key == '\n') { comp(ime); } else if(key == ' ') { reconvert:; if(b_len(ime->charset, ime->kouho.buffer.raw) == 0) { ime->length = sj4_getkan(ime->lib, ime->kanabuf, strlen(ime->kanabuf), &ime->kouho); DISPATCH(Sj4ImeBeginKanList, NULL); do { DISPATCH(Sj4ImeKanEntry, &ime->kouho); } while(sj4_nextkan(ime->lib) != 0); DISPATCH(Sj4ImeEndKanList, NULL); ime->length = sj4_getkan(ime->lib, ime->kanabuf, strlen(ime->kanabuf), &ime->kouho); } else { if((ime->length = sj4_nextkan(ime->lib)) == 0) { ZEROBUF; goto reconvert; } } } else if(('a' <= tolower(key) && tolower(key) <= 'z') || key == '~' || key == ',' || key == '.' || key == '[' || key == ']') { int i; if(ime->length != 0) comp(ime); key = toupper(key); if(ime->romabuf[strlen(ime->romabuf) - 1] == 'N' && !(key == 'A' || key == 'I' || key == 'U' || key == 'E' || key == 'O' || key == 'Y' || key == 'N')) { ime->romabuf[strlen(ime->romabuf) + 1] = 0; ime->romabuf[strlen(ime->romabuf)] = 'N'; } ime->romabuf[strlen(ime->romabuf) + 1] = 0; ime->romabuf[strlen(ime->romabuf)] = key; reduce: for(i = 0; i < sizeof(kanatbl) / sizeof(kanatbl[0]); i++) { int n = strlen(kanatbl[i].roma); if(n > strlen(ime->romabuf)) continue; if(memcmp(ime->romabuf, kanatbl[i].roma, n) == 0) { int j; n = strlen(kanatbl[i].roma) - strlen(kanatbl[i].roma2); memmove(ime->romabuf - (n < 0 ? n : 0), ime->romabuf + (n > 0 ? n : 0), sizeof(ime->romabuf) - n); if(n > 0) { for(j = sizeof(ime->romabuf) - n; j < sizeof(ime->romabuf); j++) ime->romabuf[j] = 0; } else { for(j = 0; j < -n; j++) ime->romabuf[j] = 0; } memcpy(ime->romabuf, kanatbl[i].roma2, strlen(kanatbl[i].roma2)); concat(ime->charset, ime->kanabuf, kanatbl[i].kana); goto reduce; } } if(strlen(ime->romabuf) >= 4) { ime->romabuf[0] = 0; } } else { char keys[2]; keys[0] = key; keys[1] = 0; concat(ime->charset, ime->kanabuf, keys); } } int sj4_ime_length(Sj4Ime* ime) { return ime->length; } void* sj4_ime_kouho(Sj4Ime* ime) { return ime->kouho.buffer.raw; } void* sj4_ime_kanabuf(Sj4Ime* ime) { return ime->kanabuf; } void* sj4_ime_convbuf(Sj4Ime* ime) { return ime->convbuf; }