--- a/canna.C +++ b/canna.C @@ -4,10 +4,87 @@ #define FEP_KEY 15 #define ESC_KEY 27 +void Canna::write_utf8(int fd, char *p, int len) +{ + if (eucjp_to_utf8_cd == (iconv_t)-1) + write(fd, p, strlen(p)); + else + { + char *putf8 = iconv_string(eucjp_to_utf8_cd, p, len); + write(fd, putf8, strlen(putf8)); + free(putf8); + } +} + +char * Canna::iconv_string(iconv_t fd, char *str, int slen) +{ + char *from; + size_t fromlen; + char *to; + size_t tolen; + size_t len = 0; + size_t done = 0; + char *result = NULL; + char *p; + int l; + + from = (char *)str; + fromlen = slen; + for (;;) + { + if (len == 0 || errno == E2BIG) + { + /* Allocate enough room for most conversions. When re-allocating + * increase the buffer size. */ + len = len + fromlen * 2 + 40; + p = (char*)malloc((unsigned)len); + if (p != NULL && done > 0) + memcpy(p, result, done); + free(result); + result = p; + if (result == NULL) /* out of memory */ + break; + } + + to = (char *)result + done; + tolen = len - done - 2; + /* Avoid a warning for systems with a wrong iconv() prototype by + * casting the second argument to void *. */ + if (iconv(fd, &from, &fromlen, &to, &tolen) != (size_t)-1) + { + /* Finished, append a NUL. */ + *to = 0; + break; + } + /* Check both ICONV_EILSEQ and EILSEQ, because the dynamically loaded + * iconv library may use one of them. */ + if (errno == EILSEQ || errno == EILSEQ) + { + /* Can't convert: insert a '?' and skip a character. This assumes + * conversion from 'encoding' to something else. In other + * situations we don't know what to skip anyway. */ + *to++ = *from++; + fromlen -= 1; + } + else if (errno != E2BIG) + { + /* conversion failed */ + free(result); + result = NULL; + break; + } + /* Not enough room or skipping illegal sequence. */ + done = to - (char *)result; + } + return result; +} + // コンストラクタだよん Canna::Canna(int ac, char** av, char* amsg, char* emsg): Pty(ac, av, amsg, emsg) { + char *p_lang = getenv("LANG"); + // かんなの初期化 jrKanjiControl(0, KC_INITIALIZE, 0); jrKanjiControl(0, KC_SETAPPNAME, "canfep"); @@ -15,6 +92,9 @@ jrKanjiControl(0, KC_QUERYMODE, (char*) saveMode); jrKanjiControl(0, KC_SETWIDTH, (char*) 72); + if (p_lang == NULL || strstr(p_lang, "-8")) + eucjp_to_utf8_cd = iconv_open("utf-8", "euc-jp"); + mode(saveMode); } @@ -25,6 +105,8 @@ jrKanjiControl(0, KC_KILL, (char*) &ksv); jrKanjiControl(0, KC_FINALIZE, 0); + if (eucjp_to_utf8_cd != (iconv_t)-1) + iconv_close(eucjp_to_utf8_cd); mode(saveMode); } @@ -32,7 +114,7 @@ void Canna::kakutei(unsigned char* p) { - write(wfd, p, strlen((char*) p)); + write_utf8(wfd, (char*)p, strlen((char*) p)); } // 変換中(未確定)の文字列を出力する @@ -42,13 +124,13 @@ write(rfd, sc, strlen(sc)); write(rfd, rc, strlen(rc)); write(rfd, us, strlen(us)); - write(rfd, p, pos); + write_utf8(rfd, (char*)p, pos); write(rfd, ue, strlen(ue)); write(rfd, so, strlen(so)); - write(rfd, p + pos, len); + write_utf8(rfd, (char*)p + pos, len); write(rfd, se, strlen(se)); write(rfd, us, strlen(us)); - write(rfd, p + pos + len, strlen((char*) p + pos + len)); + write_utf8(rfd, (char*)p + pos + len, strlen((char*) p + pos + len)); write(rfd, ue, strlen(ue)); } @@ -73,7 +155,7 @@ write(rfd, sc, strlen(sc)); write(rfd, ts, strlen(ts)); write(rfd, ce, strlen(ce)); - write(rfd, p, strlen((char*) p)); + write_utf8(rfd, (char*)p, strlen((char*) p)); write(rfd, fs, strlen(fs)); } @@ -84,13 +166,13 @@ write(rfd, sc, strlen(sc)); write(rfd, ts, strlen(ts)); write(rfd, ce, strlen(ce)); - write(rfd, p, strlen((char*) p)); + write_utf8(rfd, (char*)p, strlen((char*) p)); write(rfd, " ", 1); - write(rfd, l, pos); + write_utf8(rfd, (char*)l, pos); write(rfd, so, strlen(so)); - write(rfd, l + pos, len); + write_utf8(rfd, (char*)l + pos, len); write(rfd, se, strlen(se)); - write(rfd, l + pos + len, strlen((char*) l + pos +len)); + write_utf8(rfd, (char*)l + pos + len, strlen((char*) l + pos +len)); write(rfd, fs, strlen(fs)); } --- a/canna.H +++ b/canna.H @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include #include "pty.H" @@ -17,6 +19,7 @@ jrKanjiStatus ks; jrKanjiStatusWithValue ksv; private: + iconv_t eucjp_to_utf8_cd; unsigned char currentMode[BUFSIZ]; unsigned char saveMode[BUFSIZ]; private: @@ -25,6 +28,8 @@ void delhenkan(int len); void mode(unsigned char* p); void gline(unsigned char* p, unsigned char* l, int pos, int len); + void write_utf8(int fd, char *p, int len); + char* iconv_string(iconv_t fd, char *str, int slen); public: void loop(); };