/* esecannaserver --- pseudo canna server that wraps another IME.
* Copyright (C) 1999-2000 Yasuhiro Take
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* ree Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <pwd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "def.h"
#include "misc.h"
#include "vje.h"
#include "vjesocket.h"
typedef struct _vje30_t {
char *dicfile[10]; /* 辞書へのパス */
short dicmode[10]; /* 辞書を開く時の mode */
char *romaji; /* VJE30: ローマ字ファイルのパス */
char *ktable; /* VJE30: 漢字テーブルのパス */
char *restart; /* vjed を再起動するコマンドへのフルパス */
char katakana_gakushu:1; /* カタカナに変換したのを学習する? */
char restart_vjed:1; /* vjed が落ちたとき、再起動する? 終了する? */
} vje30_t;
typedef struct {
char romaji[5];
char yomi[5];
} roma_t;
typedef struct _context_t {
struct _context_t *prev, *next;
short context_num;
short max_bun;
struct {
uchar yomi_pnt;
uchar yomi_len;
ushort koho_num;
ushort *koho;
char *koho_inf;
size_t koho_len;
} bun[MAX_BUNSETU_NUM];
int client_id; /* このコンテキストのオーナーのクライアントの id */
int canna_mode; /* かんなの変換モード */
buff_t yomi_buffer; /* 読みのバッファ. vje 形式 */
char subst_yomi_zero_flag; /* subst_yomi で yomi が null だったか? */
struct {
short id; /* vje library の id. */
char sdic_opened_flag[10];
} vje;
} context_t;
static context_t *cx_top;
static char *vjelibpath;
static client_t *client;
#define VW_ERROR16(_buf) { \
cannaheader_t *he; \
he = (cannaheader_t *)(_buf); \
he->datalen = LSBMSB16(2); \
he->err.e16 = LSBMSB16(-1); \
}
#define VW_ERROR8(_buf) { \
cannaheader_t *he; \
he = (cannaheader_t *)(_buf); \
he->datalen = LSBMSB16(1); \
he->err.e8 = -1; \
}
/*
* wrapper functions から使われる ユーティリティ関数s
*/
/* コンテキスト関連 */
static short vw_new_context(int id)
{
context_t *cx, *new;
short cx_num;
if ((new = (context_t *)calloc(1, sizeof(context_t))) == NULL)
return -1;
cx = cx_top;
if (cx) {
while (cx->next) cx = cx->next;
cx->next = new;
new->prev = cx;
} else {
cx_top = new;
}
cx_num = 1;
for (;;) {
cx = cx_top;
for (;;) {
if (cx == NULL) {
new->context_num = cx_num;
new->client_id = id;
new->vje.id = 0;
return cx_num;
}
if (cx->context_num == cx_num) {
cx_num++;
break;
}
cx = cx->next;
}
}
}
static context_t *vw_get_context(short cx_num)
{
context_t *cx;
if (cx_num == -1)
return NULL;
cx = cx_top;
while (cx) {
if (cx->context_num == cx_num)
return cx;
cx = cx->next;
}
return NULL;
}
static int vw_clear_context(short cx_num)
{
context_t *cx;
int i;
cx = vw_get_context(cx_num);
for (i = 0; i < cx->max_bun; i++) {
if (cx->bun[i].koho)
free(cx->bun[i].koho);
cx->bun[i].koho = NULL;
if (cx->bun[i].koho_inf)
free(cx->bun[i].koho_inf);
cx->bun[i].koho_inf = NULL;
cx->bun[i].yomi_pnt = cx->bun[i].yomi_len = 0;
cx->bun[i].koho_num = cx->bun[i].koho_len = 0;
}
cx->max_bun = 0;
memset(&cx->yomi_buffer, 0, sizeof(buff_t));
return 0;
}
static int vw_free_context(short cx_num)
{
context_t *cx;
cx = vw_get_context(cx_num);
vw_clear_context(cx_num);
if (cx->prev)
cx->prev->next = cx->next;
else
cx_top = cx->next;
if (cx->next)
cx->next->prev = cx->prev;
free(cx);
return 0;
}
/* VJELIB 関係 */
static int vw_open_vje_library(short cx_num)
{
short vje_id;
context_t *cx;
int id, i, mode;
char *dicfname, *dicpath, buf[DIC_NAME_SIZE + 10];
cx = vw_get_context(cx_num);
id = cx->client_id;
if ((vje_id = vje_proto_vjelibopen()) != -1) {
cx->vje.id = vje_id;
vje_proto_loadcoderange();
for (i = 0; i < 10; i++) {
dicfname = client[id].data.vje30->dicfile[i];
mode = client[id].data.vje30->dicmode[i];
dicpath = NULL;
if (dicfname) {
if (i == 9 && client[id].homedir != NULL) {
/* ユーザー辞書の場合で、なおかつ id != VJE_ROOT_CLIENT の場合 */
sprintf(buf, ".vje/%s", dicfname);
dicpath = m_makepath(client[id].homedir, buf);
} else {
sprintf(buf, "dic/%s", dicfname);
dicpath = m_makepath(vjelibpath, buf);
}
m_msg("VJE30.Dic: #%d, [%s] %d\n", i, dicpath, mode);
vje_proto_clear(vje_id);
vje_proto_open_sdic(vje_id, i, dicpath, mode);
cx->vje.sdic_opened_flag[i] = 1;
free(dicpath);
}
}
/* OpenKanjiTable, VRoomajiOpen */
vje_proto_vroomaji_open(vje_id, client[id].data.vje30->romaji, "ROMA");
vje_proto_open_kanji_table(vje_id, client[id].data.vje30->ktable);
mode = 0x5700;
mode |= client[id].data.vje30->katakana_gakushu ? 0x40 : 0;
vje_proto_setmode(vje_id, mode, 0x300, 10, 3);
vje_proto_setmode(vje_id, mode, 0x10b, 10, 3);
return 0;
}
return -1;
}
static int vw_close_vje_library(short cx_num)
{
int i;
context_t *cx;
cx = vw_get_context(cx_num);
if (cx->vje.id) {
for (i = 0; i < 10; i++)
if (cx->vje.sdic_opened_flag[i])
vje_proto_close_sdic(cx->vje.id, i);
vje_proto_vjelibclose(cx->vje.id);
cx->vje.id = 0;
}
return 0;
}
/* ローマ字テーブル関係 */
roma_t romatbl[] = {
{"a", "あ"},
{"i", "い"},
{"ye", "いぇ"},
{"u", "う"},
{"e", "え"},
{"o", "お"},
{"ka", "か"},
{"ki", "き"},
{"ku", "く"},
{"ke", "け"},
{"ko", "こ"},
{"ga", "が"},
{"gi", "ぎ"},
{"gu", "ぐ"},
{"ge", "げ"},
{"go", "ご"},
{"kya", "きゃ"},
{"kyi", "きぃ"},
{"kyu", "きゅ"},
{"kye", "きぇ"},
{"kyo", "きょ"},
{"gya", "ぎゃ"},
{"gyi", "ぎぃ"},
{"gyu", "ぎゅ"},
{"gye", "ぎぇ"},
{"gyo", "ぎょ"},
{"gwa", "ぐぁ"},
{"gwi", "ぐぃ"},
{"gwu", "ぐぅ"},
{"gwe", "ぐぇ"},
{"gwo", "ぐぉ"},
{"sa", "さ"},
{"si", "し"},
{"su", "す"},
{"se", "せ"},
{"so", "そ"},
{"za", "ざ"},
{"zi", "じ"},
{"zu", "ず"},
{"ze", "ぜ"},
{"zo", "ぞ"},
{"sha", "しゃ"},
{"syi", "しぃ"},
{"shu", "しゅ"},
{"she", "しぇ"},
{"sho", "しょ"},
{"ja", "じゃ"},
{"jyi", "じぃ"},
{"ju", "じゅ"},
{"je", "じぇ"},
{"jo", "じょ"},
{"ta", "た"},
{"ti", "ち"},
{"tu", "つ"},
{"te", "て"},
{"to", "と"},
{"da", "だ"},
{"di", "ぢ"},
{"du", "づ"},
{"de", "で"},
{"do", "ど"},
{"cha", "ちゃ"},
{"cyi", "ちぃ"},
{"chu", "ちゅ"},
{"che", "ちぇ"},
{"cho", "ちょ"},
{"tsa", "つぁ"},
{"tsi", "つぃ"},
{"tse", "つぇ"},
{"tso", "つぉ"},
{"tha", "てゃ"},
{"thi", "てぃ"},
{"thu", "てゅ"},
{"the", "てぇ"},
{"tho", "てょ"},
{"dya", "ぢゃ"},
{"dyi", "ぢぃ"},
{"dyu", "ぢゅ"},
{"dye", "ぢぇ"},
{"dyo", "ぢょ"},
{"dha", "でゃ"},
{"dhi", "でぃ"},
{"dhu", "でゅ"},
{"dhe", "でぇ"},
{"dho", "でょ"},
{"na", "な"},
{"ni", "に"},
{"nu", "ぬ"},
{"ne", "ね"},
{"no", "の"},
{"nn", "ん"},
{"nya", "にゃ"},
{"nyi", "にぃ"},
{"nyu", "にゅ"},
{"nye", "にぇ"},
{"nyo", "にょ"},
{"ha", "は"},
{"hi", "ひ"},
{"fu", "ふ"},
{"he", "へ"},
{"ho", "ほ"},
{"ba", "ば"},
{"bi", "び"},
{"bu", "ぶ"},
{"be", "べ"},
{"bo", "ぼ"},
{"pa", "ぱ"},
{"pi", "ぴ"},
{"pu", "ぷ"},
{"pe", "ぺ"},
{"po", "ぽ"},
{"hya", "ひゃ"},
{"hyi", "ひぃ"},
{"hyu", "ひゅ"},
{"hye", "ひぇ"},
{"hyo", "ひょ"},
{"fa", "ふぁ"},
{"fi", "ふぃ"},
{"fe", "ふぇ"},
{"fo", "ふぉ"},
{"bya", "びゃ"},
{"byi", "びぃ"},
{"byu", "びゅ"},
{"bye", "びぇ"},
{"byo", "びょ"},
{"pya", "ぴゃ"},
{"pyi", "ぴぃ"},
{"pyu", "ぴゅ"},
{"pye", "ぴぇ"},
{"pyo", "ぴょ"},
{"ma", "ま"},
{"mi", "み"},
{"mu", "む"},
{"me", "め"},
{"mo", "も"},
{"mya", "みゃ"},
{"myi", "みぃ"},
{"myu", "みゅ"},
{"mye", "みぇ"},
{"myo", "みょ"},
{"ya", "や"},
{"yu", "ゆ"},
{"yo", "よ"},
{"ra", "ら"},
{"ri", "り"},
{"ru", "る"},
{"re", "れ"},
{"ro", "ろ"},
{"rya", "りゃ"},
{"ryi", "りぃ"},
{"ryu", "りゅ"},
{"rye", "りぇ"},
{"ryo", "りょ"},
{"wa", "わ"},
{"wi", "ゐ"},
{"we", "ゑ"},
{"wo", "を"},
{"vu", "ヴ"},
{"va", "ヴァ"},
{"vi", "ヴィ"},
{"ve", "ヴェ"},
{"vo", "ヴォ"},
{"xa", "ぁ"},
{"xi", "ぃ"},
{"xu", "ぅ"},
{"xe", "ぇ"},
{"xo", "ぉ"},
{"xwa", "ゎ"},
{"xtu", "っ"},
{"xya", "ゃ"},
{"xyu", "ゅ"},
{"xyo", "ょ"}
};
#define ROMATBL_SIZE (sizeof(romatbl) / sizeof(roma_t))
static int vw_create_romaji_table()
{
/* romatbl[] の各読みデータを SJIS に変換する */
int i;
char buf[20];
for (i = 0; i < ROMATBL_SIZE; i++) {
euc2sjis(romatbl[i].yomi, strlen(romatbl[i].yomi), buf, 20);
strcpy(romatbl[i].yomi, buf);
}
return 0;
}
static int vw_lookup_romaji_table(uchar *sjisyomi, int slen)
{
int i;
char buf[5];
strncpy(buf, sjisyomi, slen);
buf[slen] = '\0';
for (i = 0; i < ROMATBL_SIZE; i++)
if (strcmp(romatbl[i].yomi, buf) == 0)
return i;
return -1;
}
/* コンフィギュレーションファイル関係 */
static int vw_read_conf_file(int id, char *conffilepath)
{
FILE *fp;
char buf[1024];
char *ope, *val;
int i, ret = 0;
vje30_t *vje30 = client[id].data.vje30;
if ((fp = fopen(conffilepath, "r")) == NULL) {
m_msg("Cannot open Conffile %s.\n", conffilepath);
return -1;
}
while (fgets(buf, 1024, fp)) {
if (buf[0] != '#' && m_conf1_parse(buf, &ope, &val) == 0) {
i = M_CONF_ONOFF(ope, "VJE30.KatakanaGaku", val);
if (i) vje30->katakana_gakushu = i - 1;
if (id == VJE_ROOT_CLIENT) {
m_conf_string(ope, "VJE30.RestartComm", val, &(vje30->restart));
i = M_CONF_ONOFF(ope, "VJE30.RestartVjed", val);
if (i) vje30->restart_vjed = i - 1;
}
}
}
fclose(fp);
return ret;
}
/* general.sty を読む */
static int vw_read_general_style(int id, char *styfilepath)
{
FILE *fp;
char *ope, *val, buf[1024], dicbuf[10];
int roma, ktbl, dic, i, dicmode;
vje30_t *vje30 = client[id].data.vje30;
roma = ktbl = dic = dicmode = 0;
if ((fp = fopen(styfilepath, "r")) == NULL) {
m_msg("Cannot open system conf file %s.\n", styfilepath);
return -1;
}
while (fgets(buf, 1024, fp)) {
if (buf[0] == '[') {
roma = ktbl = dic = dicmode = 0;
if (strstr(buf, "[Roma]"))
roma = 1;
if (strstr(buf, "[DicInfo]"))
ktbl = 1;
for (i = 1; i <= 10; i++) {
sprintf(dicbuf, "[DIC%d]", i);
if (strstr(buf, dicbuf))
dic = i;
}
} else if ((roma || ktbl || dic) && m_conf1_parse(buf, &ope, &val) == 0) {
if (roma)
m_conf_string(ope, "RomFile", val, &(vje30->romaji));
if (ktbl)
m_conf_string(ope, "DicDat", val, &(vje30->ktable));
if (dic) {
m_conf_string(ope, "DicFile", val, &(vje30->dicfile[dic - 1]));
if (m_conf_isequal(ope, "LearnMode", val, "YES") == 2)
dicmode |= 0x06;
if (m_conf_isequal(ope, "LearnMode", val, "DON") == 2)
dicmode |= 0x02;
if (m_conf_isequal(ope, "LearnType", val, "MYSELF") == 2)
dicmode |= 0x10;
if (m_conf_isequal(ope, "Parallel", val, "YES") == 2)
dicmode |= 0x20;
if (dic == 10)
dicmode |= 0x01;
vje30->dicmode[dic - 1] = dicmode;
}
}
}
fclose(fp);
if (vje30->romaji == NULL || vje30->ktable == NULL)
return -1;
return 0;
}
/* vje.cfg を読む */
static int vw_read_vje_cfg()
{
FILE *fp;
char *ope, *val, buf[1024];
if ((fp = fopen(VJECFGFILE, "r")) == NULL) {
m_msg("Cannot open %s\n", VJECFGFILE);
return -1;
}
while (fgets(buf, 1024, fp)) {
if (buf[0] != '[' && m_conf1_parse(buf, &ope, &val) == 0)
m_conf_string(ope, "Path", val, &vjelibpath);
}
fclose(fp);
if (vjelibpath == NULL)
return -1;
/* パスの最後が / で終わってるなら やめさせる */
if (vjelibpath[strlen(vjelibpath) - 1] == '/')
vjelibpath[strlen(vjelibpath) - 1] = 0;
m_msg_dbg("VJE Library Path = %s\n", vjelibpath);
return 0;
}
static int vw_config_client(int id, char *conffile)
{
char *stypath = NULL;
FILE *src1, *src2, *dst1, *dst2;
int len;
vje30_t *vje30;
if ((vje30 = client[id].data.vje30 = calloc(1, sizeof(vje30_t))) == NULL) {
m_msg("Out of Memory.\n");
return -1;
}
if (client[id].homedir && (len = strlen(client[id].homedir)) > 0) {
if (client[id].homedir[len - 1] == '/')
client[id].homedir[len - 1] = 0;
} else {
client[id].homedir = NULL;
}
/* /etc/esecannarc か ~/.esecannarc を読む */
if (vw_read_conf_file(id, conffile) == -1)
return -1;
if (id != VJE_ROOT_CLIENT && client[id].homedir) {
if (chdir(client[id].homedir) == 0) {
if (chdir(".vje") != 0) {
/* ~/.vje がない場合はここで作成し、ファイルをコピー */
dst1 = dst2 = src1 = src2 = NULL;
if (mkdir(".vje", 755) == 0 && chdir(".vje") == 0) {
dst1 = fopen("general.sty", "w");
dst2 = fopen("vjed95u.dic", "w");
if (dst1 && dst2) {
chdir(vjelibpath);
chdir("com");
src1 = fopen("general.sty", "r");
src2 = fopen("vjed95u.dic", "r");
if (src1 && src2) {
m_copy_file_fp(src1, dst1);
m_copy_file_fp(src2, dst2);
}
}
if (dst1) fclose(dst1);
if (dst2) fclose(dst2);
if (src1) fclose(src1);
if (src2) fclose(src2);
}
}
stypath = "general.sty";
}
} else {
chdir(vjelibpath);
stypath = "com/general.sty";
}
if (stypath == NULL)
return -1;
if (vw_read_general_style(id, stypath) == -1)
return -1;
return 0;
}
/* vjed が落ちたときの処理に関する関数s */
static int vw_check8(buffer_t *cbuf)
{
extern int vjeerror;
if (vjeerror) {
/* vje25 のソースを読め。
*/
VW_ERROR8(cbuf->buf);
return 1;
}
return 0;
}
static int vw_check16(buffer_t *cbuf)
{
extern int vjeerror;
if (vjeerror) {
VW_ERROR16(cbuf->buf);
return 1;
}
return 0;
}
int vjewrapper_restarted()
{
extern int vjeerror;
vjeerror = FALSE;
return 0;
}
int vjewrapper_clear_vjeid()
{
context_t *cx;
cx = cx_top;
while (cx) {
if (cx->vje.id)
cx->vje.id = 0;
cx = cx->next;
}
return 0;
}
/* その他、vje に深く関係する関数s */
static int vw_expr_yomi_start(int start, uchar *yomibuf)
{
int start2 = 0;
int i = 0;
while (yomibuf[i]) {
if (start == start2)
return i;
if (ISSJISKANJI1(yomibuf[i]))
i += 2;
else
i++;
start2++;
}
if (start == start2)
return i;
return -1;
}
static int vw_make_vjebuffers(buff_t *in_buf, ushort *atrbuf, kbuff_t *keybuf)
{
int atr_pnt, key_pnt, in_pnt, d_in_pnt;
int i, romaslen;
int zenkana_flag;
uchar roma[5];
uchar hira[5];
in_pnt = atr_pnt = key_pnt = 1;
d_in_pnt = 0;
while (in_pnt <= LEN_OF_BUFP(in_buf)) {
zenkana_flag = 0;
if (in_pnt + 1 <= LEN_OF_BUFP(in_buf) &&
(ISSJIS_ZENKAKU_HIRAGANA(in_buf->str[in_pnt], in_buf->str[in_pnt + 1])
|| ISSJIS_ZENKAKU_VU(in_buf->str[in_pnt], in_buf->str[in_pnt + 1]))) {
/* ひらがな,または「ヴ」の場合 */
if (in_pnt + 3 <= LEN_OF_BUFP(in_buf) &&
(i = vw_lookup_romaji_table(&(in_buf->str[in_pnt]), 4)) != -1) {
/* "にゃ" のような読みの場合 */
strcpy(roma, romatbl[i].romaji);
d_in_pnt = 4;
} else if ((i=vw_lookup_romaji_table(&(in_buf->str[in_pnt]), 2)) != -1) {
/* "に" のような読みの場合 */
strcpy(roma, romatbl[i].romaji);
d_in_pnt = 2;
}
} else if (in_pnt + 1 <= LEN_OF_BUFP(in_buf) &&
ISSJIS_ZENKAKU_KATAKANA(in_buf->str[in_pnt],
in_buf->str[in_pnt + 1])) {
zenkana_flag = 1;
/* カタカナの場合 */
d_in_pnt = -1;
if (in_pnt + 3 <= LEN_OF_BUFP(in_buf) &&
ISSJIS_ZENKAKU_KATAKANA(in_buf->str[in_pnt + 2],
in_buf->str[in_pnt + 3])) {
/* 次の読みもカタカナの場合 */
m_convert_zenkana2zenhira(&(in_buf->str[in_pnt]), hira, 4);
if ((i = vw_lookup_romaji_table(hira, 4)) != -1) {
/* "キャ" のような読みの場合 */
strcpy(roma, romatbl[i].romaji);
d_in_pnt = 4;
}
}
if (d_in_pnt == -1) {
/* 次の読みもカタカナだが "キャ" のような読みではない場合,または
次の読みがカタカナではない場合 */
m_convert_zenkana2zenhira(&(in_buf->str[in_pnt]), hira, 2);
if ((i = vw_lookup_romaji_table(hira, 2)) != -1) {
/* "ニ" のような読みの場合 */
strcpy(roma, romatbl[i].romaji);
d_in_pnt = 2;
}
}
if (d_in_pnt == -1) {
m_msg("vw_make_vjebuffer(): unexpected error01 %d\n", in_pnt);
return -1;
}
} else if (ISSJISKANJI1(in_buf->str[in_pnt])) {
/* "a" "@" "「" などの全角非ひらがな */
if ((roma[0] = m_convert_zen2han(&(in_buf->str[in_pnt]))) == 0) {
m_msg("make_vjebuffer(): unexpected error02 %d\n", in_pnt);
return -1;
}
roma[1] = '\0';
d_in_pnt = 2;
} else {
/* 半角のアルファベット,数字 */
roma[0] = in_buf->str[in_pnt];
roma[1] = '\0';
d_in_pnt = 1;
}
romaslen = strlen(roma);
switch (romaslen) {
case 3:
if (zenkana_flag == 0) {
atrbuf[atr_pnt++] = 0x83; atrbuf[atr_pnt++] = 0x40;
if (d_in_pnt == 4) {
atrbuf[atr_pnt++] = 0x80; atrbuf[atr_pnt++] = 0x40;
}
} else {
atrbuf[atr_pnt++] = 0xab; atrbuf[atr_pnt++] = 0x68;
atrbuf[atr_pnt++] = 0xa8; atrbuf[atr_pnt++] = 0x68;
}
break;
case 2:
if (zenkana_flag == 0) {
atrbuf[atr_pnt++] = 0x82; atrbuf[atr_pnt++] = 0x40;
if (d_in_pnt == 4) {
atrbuf[atr_pnt++] = 0x80; atrbuf[atr_pnt++] = 0x40;
}
} else {
atrbuf[atr_pnt++] = 0xaa; atrbuf[atr_pnt++] = 0x68;
if (d_in_pnt == 4) {
atrbuf[atr_pnt++] = 0xa8; atrbuf[atr_pnt++] = 0x68;
}
}
break;
case 1:
if (d_in_pnt == 2) {
if (zenkana_flag) {
atrbuf[atr_pnt++] = 0xa9; atrbuf[atr_pnt++] = 0x68;
} else if (roma[0] >= 0xa1 && roma[0] <= 0xdf) {
atrbuf[atr_pnt++] = 0x8081; atrbuf[atr_pnt++] = 0x8040;
} else {
atrbuf[atr_pnt++] = 0x81; atrbuf[atr_pnt++] = 0x40;
}
} else
atrbuf[atr_pnt++] = 0x01;
break;
}
memcpy(&(keybuf->str[key_pnt]), roma, romaslen);
key_pnt += romaslen;
in_pnt += d_in_pnt;
}
LEN_OF_OLDBUF(atrbuf) = atr_pnt - 1;
LEN_OF_BUFP(keybuf) = key_pnt - 1;
return 0;
}
static int vw_move_bunsetu(context_t *cx, int n)
{
buninf_t bi;
doubufx_t douon;
buff_t tmpbuf;
uchar euc[IN_BUF_SIZE];
#if 0
while (cx->cur_bun_no < n) {
vje_proto_ji_bunsetu(cx->vje.id);
cx->cur_bun_no++;
vje_proto_get_koho_all(cx->vje.id, &bi, &tmpbuf);
vje_proto_get_douon(cx->vje.id, &douon);
vje_proto_set_koho(cx->vje.id, 1);
}
while (cx->cur_bun_no > n) {
vje_proto_zen_bunsetu(cx->vje.id);
cx->cur_bun_no--;
}
#endif
vje_proto_set_koho_bno(cx->vje.id, n);
return 0;
}
static int vw_convert_yomi_canna2vje(uchar *euc, int slen)
{
euc[slen] = 0;
m_replace_string(euc, "″", "”");
slen = m_replace_string(euc, "う゛", "ヴ");
return slen;
}
static int vw_convert_yomi_vje2canna(uchar *euc, int slen)
{
euc[slen] = 0;
m_replace_string(euc, "”", "″");
slen = m_replace_string(euc, "ヴ", "う゛");
return slen;
}
static int vw_get_yomi(context_t *cx, int bun_no, uchar *euc)
{
uchar tmpbuf[IN_BUF_SIZE];
int slen;
slen = cx->bun[bun_no].yomi_len;
memcpy(tmpbuf, &(cx->yomi_buffer.str[cx->bun[bun_no].yomi_pnt]), slen);
tmpbuf[slen] = 0;
slen = sjis2euc(tmpbuf, slen, euc, IN_BUF_SIZE);
slen = vw_convert_yomi_vje2canna(euc, slen);
euc[slen] = 0;
return slen;
}
static ushort *vw_get_koho_list(context_t *cx, int bun_no, int *koho_num_r,
int *size_r, char **koho_inf_r)
{
int block, i, j, k, pnt, buf_pnt, slen, slen2, koho_num, jiblock_ret, end;
uchar sjis[IN_BUF_SIZE], euc[IN_BUF_SIZE], tmpbuf[IN_BUF_SIZE];
ushort wcs[IN_BUF_SIZE];
buff_t in_buf;
kbuff_t keybuf;
ushort atrbuf[IN_BUF_SIZE * 2];
short size, mode = 1;
char *koho_inf;
uchar yomi_len;
int hira_koho, kata_koho;
extern int vjeerror;
buffer_t zbuf, zbuf2;
doubufx_t douon;
buninf_t bi;
zbuf.size = zbuf2.size = 0;
zbuf.buf = zbuf2.buf = NULL;
hira_koho = kata_koho = -1;
vw_move_bunsetu(cx, bun_no);
vje_proto_get_koho_all(cx->vje.id, &bi, &in_buf);
yomi_len = bi.kouho[bun_no].yomi_len;
koho_num = size = buf_pnt = 0;
vje_proto_get_douon(cx->vje.id, &douon);
/* 候補数が 1 なら無視 */
if (douon.cnt == 1) {
vje_proto_ji_block(cx->vje.id);
vje_proto_get_douon(cx->vje.id, &douon);
/* 「だろう」を変換すると候補は「だろう」だけだから問題あり */
vje_proto_get_koho_all(cx->vje.id, &bi, &in_buf);
if (yomi_len != bi.kouho[bun_no].yomi_len) {
vje_proto_zen_block(cx->vje.id);
vje_proto_get_douon(cx->vje.id, &douon);
}
}
if (vjeerror) {
if (zbuf.buf)
free(zbuf.buf);
if (zbuf2.buf)
free(zbuf2.buf);
*koho_num_r = 0;
*size_r = 0;
*koho_inf_r = NULL;
return NULL;
}
pnt = 0;
for (i = 0; i < douon.cnt; i++) {
slen = douon.buf[pnt++];
memcpy(sjis, &(douon.buf[pnt]), slen);
sjis[slen] = 0;
pnt += slen;
slen = sjis2euc(sjis, slen, euc, IN_BUF_SIZE);
if (m_exist_hankata(euc) == 0) {
if (m_is_zenkata_string(euc))
kata_koho = i;
else if (m_is_hiragana_string(euc))
hira_koho = i;
m_msg_dbg("kouho[%d]=[%s]\n", koho_num, euc);
slen = euc2cannawc(euc, slen, wcs, IN_BUF_SIZE);
slen *= 2;
size += slen + 2;
buffer_check(&zbuf, size);
memcpy(&(zbuf.buf[buf_pnt]), wcs, slen);
buf_pnt += slen;
zbuf.buf[buf_pnt++] = 0; zbuf.buf[buf_pnt++] = 0;
koho_num++;
buffer_check(&zbuf2, koho_num);
koho_inf = (uchar *)zbuf2.buf;
koho_inf[koho_num - 1] = i;
}
}
slen = vw_get_yomi(cx, bun_no, euc);
/* cx->canna_mode に従い、候補を付け足す */
j = m_count_canna_mode(cx->canna_mode);
for (i = 0; i < j; i++) {
k = m_get_canna_mode(cx->canna_mode, i);
if (k == 3) {
/* カタカナ候補 */
koho_num++;
slen2 = m_convert_zenhira2zenkata(euc, slen, tmpbuf);
slen2 = euc2cannawc(tmpbuf, slen2, wcs, IN_BUF_SIZE);
slen2 *= 2;
size += slen2 + 2;
buffer_check(&zbuf, size);
memcpy(&(zbuf.buf[buf_pnt]), wcs, slen2);
buf_pnt += slen2;
zbuf.buf[buf_pnt++] = 0; zbuf.buf[buf_pnt++] = 0;
buffer_check(&zbuf2, koho_num);
koho_inf = (uchar *)zbuf2.buf;
koho_inf[koho_num - 1] = kata_koho;
} else if (k == 1) {
/* ひらがな候補 */
koho_num++;
slen2 = euc2cannawc(euc, slen, wcs, IN_BUF_SIZE);
slen2 *= 2;
size += slen2 + 2;
buffer_check(&zbuf, size);
memcpy(&(zbuf.buf[buf_pnt]), wcs, slen2);
buf_pnt += slen2;
zbuf.buf[buf_pnt++] = 0; zbuf.buf[buf_pnt++] = 0;
buffer_check(&zbuf2, koho_num);
koho_inf = (char *)zbuf2.buf;
koho_inf[koho_num - 1] = hira_koho;
}
}
size += 2;
buffer_check(&zbuf, size);
zbuf.buf[buf_pnt++] = 0; zbuf.buf[buf_pnt++] = 0;
koho_inf = (char *)zbuf2.buf;
*koho_num_r = koho_num;
*size_r = size;
*koho_inf_r = koho_inf;
return (ushort *)zbuf.buf;
}
static ushort *vw_retrieve_koho(short cx_num, int bun_no, int koho_no)
{
context_t *cx;
ushort *p, *ret;
buff_t sjis;
uchar euc[IN_BUF_SIZE];
static ushort wcs[IN_BUF_SIZE];
int i, j, slen, koho_num, koholen;
char *koho_inf;
buninf_t bi;
cx = vw_get_context(cx_num);
p = cx->bun[bun_no].koho;
if (p == NULL && koho_no > 0) {
/* まだ候補を取得してないなら取得する */
cx->bun[bun_no].koho = vw_get_koho_list(cx, bun_no, &koho_num, &koholen,
&koho_inf);
cx->bun[bun_no].koho_inf = koho_inf;
cx->bun[bun_no].koho_num = koho_num;
cx->bun[bun_no].koho_len = koholen;
p = cx->bun[bun_no].koho;
}
if (p) {
i = 0; j = 0;
while (i < koho_no) {
while (p[j]) j++;
j++;
i++;
}
ret = &p[j];
} else {
vje_proto_get_koho_all(cx->vje.id, &bi, &sjis);
slen = sjis2euc(&(sjis.str[bi.kouho[bun_no].hyk_pnt]),
bi.kouho[bun_no].hyk_len, euc, IN_BUF_SIZE);
euc2cannawc(euc, slen, wcs, IN_BUF_SIZE);
ret = wcs;
}
return ret;
}
static int vw_set_koho(short cx_num, int bun_no, int koho_no)
{
int koho, i, len, pnt, n;
context_t *cx;
uchar hira[IN_BUF_SIZE], kata[IN_BUF_SIZE], sjis[IN_BUF_SIZE];
uchar tmpbuf[IN_BUF_SIZE];
ushort atrbuf[IN_BUF_SIZE * 2], *sp;
buff_t in_buf;
kbuff_t keybuf;
doubufx_t douon;
buninf_t bi;
cx = vw_get_context(cx_num);
if (koho_no > 0 && cx->bun[bun_no].koho == NULL) {
int koho_num, koholen;
char *koho_inf;
cx->bun[bun_no].koho = vw_get_koho_list(cx, bun_no, &koho_num, &koholen,
&koho_inf);
cx->bun[bun_no].koho_inf = koho_inf;
cx->bun[bun_no].koho_num = koho_num;
cx->bun[bun_no].koho_len = koholen;
}
if (koho_no > 0) {
koho = cx->bun[bun_no].koho_inf[koho_no];
if (koho != -1) {
vje_proto_get_douon(cx->vje.id, &douon);
vje_proto_set_koho(cx->vje.id, 1 + koho);
vje_proto_get_koho_all(cx->vje.id, &bi, &in_buf);
sjis2euc(&in_buf.str[1], in_buf.len, tmpbuf, IN_BUF_SIZE);
m_msg_dbg("get_koho = [%s]\n", tmpbuf);
return 0;
} else {
/* koho == -1 の時は、カタカナ候補 */
len = vw_get_yomi(cx, bun_no, hira);
m_convert_zenhira2zenkata(hira, len, kata);
m_msg_dbg("KATAKANA gakushu[%s]\n", kata);
len = euc2sjis(kata, len, sjis, IN_BUF_SIZE);
memcpy(&in_buf, &cx->yomi_buffer, sizeof(buff_t));
memcpy(&(in_buf.str[cx->bun[bun_no].yomi_pnt]), sjis, len);
vw_make_vjebuffers(&in_buf, atrbuf, &keybuf);
vje_proto_set_kihonbuff(cx->vje.id, &in_buf, atrbuf, &keybuf);
vje_proto_saihenkan(cx->vje.id, &in_buf, 1, len, len, 8);
memcpy(&cx->yomi_buffer, &in_buf, sizeof(buff_t));
}
} else {
vje_proto_set_koho(cx->vje.id, 1);
}
return 0;
}
/*
* vw_after_henkan() : 変換後呼ぶ関数
* - in_buf : 読み
* - bun_no : 各文節の最優先候補のうち、bun_no で指定された
* : 文節からの候補s を wcs_r にいれる。
* - 帰り値 : wcs_r の長さ
*/
static int vw_after_henkan(short cx_num, buff_t *in_buf, ushort *wcs_r,
int bun_no)
{
int i, pnt, len;
uchar bufeuc[IN_BUF_SIZE];
buff_t bufsjis;
buninf_t bi;
context_t *cx;
doubufx_t douon;
cx = vw_get_context(cx_num);
vje_proto_get_koho_all(cx->vje.id, &bi, &bufsjis);
vje_proto_get_douon(cx->vje.id, &douon);
m_msg_dbg("kouho = ");
pnt = 0;
for (i = bun_no; i < bi.max_bun; i++) {
len = sjis2euc(&(bufsjis.str[bi.kouho[i].hyk_pnt]),bi.kouho[i].hyk_len,
bufeuc, IN_BUF_SIZE);
m_msg_dbg("%d:[%s] ", i, bufeuc);
len = m_convert_hankana2zenkana(bufeuc, len);
len = euc2cannawc(bufeuc, len, &(wcs_r[pnt]), IN_BUF_SIZE - pnt);
pnt += len;
wcs_r[pnt++] = 0;
}
m_msg_dbg("\n");
wcs_r[pnt++] = 0;
vw_clear_context(cx_num);
memcpy(&cx->yomi_buffer, in_buf, sizeof(buff_t));
cx->max_bun = bi.max_bun;
for (i = cx->max_bun - 1; i >= 0; i--) { /* ???: 意味不明。
i = 0 -> cx->max_bun - 1 では
(文節縮めで)増えた文節の候補を
取得できない
*/
cx->bun[i].yomi_pnt = bi.kouho[i].yomi_pnt;
cx->bun[i].yomi_len = bi.kouho[i].yomi_len;
}
return pnt * 2;
}
/*
* 外に公開する関数s 初期化終了関係
*/
/* dlopen() されたあと、client[] を vjewrapper.c に渡すために呼ばれる */
int vjewrapper_dl_started(client_t *cl)
{
client = cl;
m_msg("Module: %s\n", ESECANNA_MODULE_VERSION);
return 0;
}
int vjewrapper_init_rootclient()
{
char buf[128];
short cx_num;
m_msg("Initializing root client for VJE30.\n");
if (vw_read_vje_cfg() == -1) {
m_msg("failed to determine vje library path.\n");
return -1;
}
if (vw_config_client(VJE_ROOT_CLIENT, ESECANNA_RC_PATH) == -1) {
m_msg("No conffile found. Aborting.\n");
return -1;
}
vw_create_romaji_table();
if (gethostname(buf, 128))
strcpy(buf, "localhost");
if (vje_proto_set_clienthostname(buf) == -1) {
m_msg("set_clienthostname failed. Aborting.\n");
return -1;
}
if ((cx_num = vw_new_context(VJE_ROOT_CLIENT)) == -1) {
m_msg("Out of memory. Cannot allocate context. Aborting.\n");
return -1;
}
if (vw_open_vje_library(cx_num) == -1) {
m_msg("vjelibopen failed. Aborting.\n");
return -1;
}
/* OpenKanjiTable, VRoomajiOpen */
m_msg("Initialize succeeded.\n");
return 0;
}
int vjewrapper_end_client(int id)
{
context_t *cx, *cx2;
cx = cx_top;
while (cx) {
if (cx->client_id == id) {
cx2 = cx->next;
vw_close_vje_library(cx->context_num);
vw_free_context(cx->context_num);
cx = cx2;
} else
cx = cx->next;
}
return 0;
}
int vjewrapper_end_rootclient()
{
vjewrapper_end_client(VJE_ROOT_CLIENT);
vje_proto_finish_session();
vje_socket_close_connection();
return 0;
}
int vjewrapper_clear_client_data(int id)
{
int i;
vje30_t *vje30 = client[id].data.vje30;
for (i = 0; i < 10; i++)
MYFREE(vje30->dicfile[i]);
MYFREE(vje30->romaji);
MYFREE(vje30->ktable);
MYFREE(vje30->restart);
MYFREE(client[id].data.vje30);
return 0;
}
/*
* 「かんな」を vje で wrapping する関数s
*/
int vjewrapper_initialize(int id, char *conffile)
{
if (vw_config_client(id, conffile) == 0)
return vw_new_context(id);
return -1;
}
int vjewrapper_finalize(int id, buffer_t *cbuf)
{
cannaheader_t *header;
client[id].need_terminate = TRUE; /* main.c で終了処理をしてもらう */
header = (cannaheader_t *)cbuf->buf;
header->type = 0x02;
header->extra = 0;
header->datalen = LSBMSB16(1);
header->err.e8 = 0;
return 1;
}
int vjewrapper_create_context(int id, buffer_t *cbuf)
{
cannaheader_t *header = (cannaheader_t *)cbuf->buf;
short *sp = (short *)cbuf->buf;
short cx_num;
cx_num = vw_new_context(id);
header->type = 0x03;
header->extra = 0;
header->datalen = LSBMSB16(2);
sp[2] = LSBMSB16(cx_num);
return 1;
}
int vjewrapper_duplicate_context(int id, buffer_t *cbuf)
{
cannaheader_t *header = (cannaheader_t *)cbuf->buf;
short *sp = (short *)cbuf->buf;
short cx_n_new, cx_n_orig;
context_t *cx_orig, *cx_new;
cx_n_orig = LSBMSB16(sp[2]);
cx_n_new = vw_new_context(id);
cx_orig = vw_get_context(cx_n_orig);
cx_new = vw_get_context(cx_n_new);
header->type = 0x04;
header->extra = 0;
header->datalen = LSBMSB16(2);
sp[2] = LSBMSB16(cx_n_new);
return 1;
}
int vjewrapper_close_context(int id, buffer_t *cbuf)
{
cannaheader_t *header = (cannaheader_t *)cbuf->buf;
short *sp = (short *)cbuf->buf;
short cx_num;
uchar err;
cx_num = LSBMSB16(sp[2]);
vw_close_vje_library(cx_num);
err = vw_free_context(cx_num);
header->type = 0x05;
header->extra = 0;
header->datalen = LSBMSB16(1);
header->err.e8 = err;
return 1;
}
int vjewrapper_define_word(int id, buffer_t *cbuf)
{
VW_ERROR8(cbuf->buf);
return 0;
}
int vjewrapper_delete_word(int id, buffer_t *cbuf)
{
VW_ERROR8(cbuf->buf);
return 0;
}
int vjewrapper_begin_convert(int id, buffer_t *cbuf)
{
cannaheader_t *header = (cannaheader_t *)cbuf->buf;
ushort *sp = (ushort *)cbuf->buf;
int *ip = (int *)cbuf->buf;
int len, datalen, koho_len, cmode, i;
short cx_num;
context_t *cx;
short vje_id, mode = 1;
uchar bufeuc[IN_BUF_SIZE];
buff_t in_buf;
kbuff_t keybuf;
ushort atrbuf[IN_BUF_SIZE * 2], wcs[IN_BUF_SIZE * 2];
cx_num = LSBMSB16(sp[4]);
cmode = LSBMSB32(ip[1]);
for (i = 0; i < m_count_canna_mode(cmode); i++) {
m_msg_dbg("Mode #%d = %d\n", i, m_get_canna_mode(cmode, i));
}
cx = vw_get_context(cx_num);
if (cx->vje.id == 0)
vw_open_vje_library(cx_num); /* 失敗したら cx->vje.id は 0 のまま */
len = cannawcstrlen((ushort *)&(cbuf->buf[10]));
len = cannawc2euc((ushort *)&(cbuf->buf[10]), len, bufeuc, IN_BUF_SIZE);
len = vw_convert_yomi_canna2vje(bufeuc, len);
len = euc2sjis(bufeuc, len, in_buf.str + 1, IN_BUF_SIZE - 1);
LEN_OF_BUF(in_buf) = len;
if (cx->vje.id != 0 && vw_make_vjebuffers(&in_buf, atrbuf, &keybuf) == 0) {
vje_id = cx->vje.id;
vje_proto_clear(vje_id);
vje_proto_chg_sdic(vje_id, -1);
/*
vje_proto_set_koho_bno(fd, vje_id, 0);
*/
vje_proto_set_kihonbuff(vje_id, &in_buf, atrbuf, &keybuf);
vje_proto_henkanb(vje_id, &in_buf, atrbuf, &keybuf, &mode, 0);
if (vw_check16(cbuf)) return -1;
koho_len = vw_after_henkan(cx_num, &in_buf, wcs, 0);
if (vw_check16(cbuf)) return -1;
cx->canna_mode = cmode;
datalen = koho_len + 2;
buffer_check(cbuf, 4 + datalen);
header = (cannaheader_t *)cbuf->buf;
sp = (ushort *)cbuf->buf;
header->type = 0x0f;
header->extra = 0;
header->datalen = LSBMSB16(datalen);
sp[2] = LSBMSB16(cx->max_bun);
memcpy(&(sp[3]), wcs, koho_len);
} else {
header->type = 0x0f;
header->extra = 0;
header->datalen = LSBMSB16(2);
header->err.e16 = LSBMSB16(-1);
}
return 1;
}
int vjewrapper_end_convert(int id, buffer_t *cbuf)
{
cannaheader_t *header = (cannaheader_t *)cbuf->buf;
short *sp = (short *)cbuf->buf;
int *ip = (int *)cbuf->buf;
int i, koho_no;
short cx_num;
char err;
context_t *cx;
char eucbuf[IN_BUF_SIZE];
buff_t tmpbuf;
cx_num = LSBMSB16(sp[2]);
cx = vw_get_context(cx_num);
err = (cx->vje.id) ? 0 : -1;
if (ip[2] != 0 && err == 0) {
for (i = 0; i < cx->max_bun; i++) {
vw_move_bunsetu(cx, i);
koho_no = LSBMSB16(sp[6 + i]);
m_msg_dbg("KOUHO(%d) = %d\n", i, koho_no);
vw_set_koho(cx_num, i, koho_no);
}
if (vw_check8(cbuf)) return -1;
i = vje_proto_kakutei1(cx->vje.id, &cx->yomi_buffer, &tmpbuf);
i = sjis2euc(tmpbuf.str + 1, tmpbuf.len, eucbuf, IN_BUF_SIZE);
m_msg_dbg("kakutei = [%s]/%d\n", eucbuf, i);
if (vw_check8(cbuf)) return -1;
}
vw_clear_context(cx_num);
header->type = 0x10;
header->extra = 0;
header->datalen = LSBMSB16(1);
header->err.e8 = err;
return 1;
}
int vjewrapper_get_candidacy_list(int id, buffer_t *cbuf)
{
context_t *cx;
cannaheader_t *header;
short *sp = (short *)cbuf->buf;
int bun_no, koho_num, koholen;
char *koho_inf;
short size, cx_num;
cx_num = LSBMSB16(sp[2]);
bun_no = LSBMSB16(sp[3]);
cx = vw_get_context(cx_num);
if (cx->vje.id == 0) {
VW_ERROR16(cbuf->buf);
return 1;
}
/* KOHO */
if (cx->bun[bun_no].koho == NULL) {
cx->bun[bun_no].koho = vw_get_koho_list(cx, bun_no, &koho_num, &koholen,
&koho_inf);
cx->bun[bun_no].koho_inf = koho_inf;
cx->bun[bun_no].koho_num = koho_num;
cx->bun[bun_no].koho_len = koholen;
} else {
koho_num = cx->bun[bun_no].koho_num;
koholen = cx->bun[bun_no].koho_len;
}
size = koholen;
if (vw_check16(cbuf)) return -1;
buffer_check(cbuf, size + 6);
sp = (short *)cbuf->buf;
header = (cannaheader_t *)cbuf->buf;
memcpy(&(cbuf->buf[6]), cx->bun[bun_no].koho, size);
sp[2] = LSBMSB16(koho_num);
size += 2; /* FIXME: IS THIS RIGHT? */
header->type = 0x11;
header->extra = 0;
header->datalen = LSBMSB16(size);
return 1;
}
int vjewrapper_get_yomi(int id, buffer_t *cbuf)
{
cannaheader_t *header;
short *sp = (short *)cbuf->buf;
int size, bun_no, slen;
uchar euc[YOMI_BUF_SIZE];
ushort wcs[YOMI_BUF_SIZE];
short cx_num, si;
context_t *cx;
cx_num = LSBMSB16(sp[2]);
bun_no = LSBMSB16(sp[3]);
cx = vw_get_context(cx_num);
slen = vw_get_yomi(cx, bun_no, euc);
slen = euc2cannawc(euc, slen, wcs, YOMI_BUF_SIZE);
slen *= 2;
size = 2 + slen + 2;
buffer_check(cbuf, size + 4);
sp = (short *)cbuf->buf;
header = (cannaheader_t *)cbuf->buf;
memcpy(&(cbuf->buf[6]), wcs, slen);
cbuf->buf[6 + slen] = 0; cbuf->buf[6 + slen + 1] = 0;
header->type = 0x12;
header->extra = 0;
header->datalen = LSBMSB16(size);
si = slen;
sp[2] = LSBMSB16(si);
return 1;
}
int vjewrapper_subst_yomi(int id, buffer_t *cbuf)
{
cannaheader_t *header = (cannaheader_t *)cbuf->buf;
ushort *sp = (ushort *)cbuf->buf;
short cx_num, start, end, yomilen, mode = 0;
int newyomipnt, size, len, errflag = 0, koho_len, datalen, cvt, i;
ushort *yomi;
uchar euc[IN_BUF_SIZE], sjis[IN_BUF_SIZE];
buff_t in_buf;
kbuff_t keybuf;
ushort atrbuf[IN_BUF_SIZE * 2], wcs[IN_BUF_SIZE * 2];
context_t *cx;
cx_num = LSBMSB16(sp[2]);
start = LSBMSB16(sp[3]);
end = LSBMSB16(sp[4]);
yomilen = LSBMSB16(sp[5]);
yomi = (ushort *)&(sp[6]);
cx = vw_get_context(cx_num);
memcpy(&in_buf, &cx->yomi_buffer, sizeof(buff_t));
/* 変換されている読みの長さを取得 */
for (i = cvt = 0; i < cx->max_bun; i++)
cvt += cx->bun[i].yomi_len;
if ((newyomipnt = vw_expr_yomi_start(start, &in_buf.str[1 + cvt])) < 0)
errflag = 1;
if (errflag == 0) {
if (yomilen > 0) {
cx->subst_yomi_zero_flag = 0;
if (in_buf.str[1 + cvt + newyomipnt]) {
in_buf.str[1 + cvt + newyomipnt] = 0;
LEN_OF_BUF(in_buf) = strlen(&in_buf.str[1]);
vw_make_vjebuffers(&in_buf, atrbuf, &keybuf);
vje_proto_set_kihonbuff(cx->vje.id, &in_buf, atrbuf, &keybuf);
/* バックスペースされたときは mode = 2 になるみたい */
mode = 2;
}
cannawc2euc(yomi, yomilen, euc, IN_BUF_SIZE);
m_msg_dbg("newyomi = %s/%d\n", euc, yomilen);
len = euc2sjis(euc, strlen(euc), sjis, IN_BUF_SIZE) + 1;
if (newyomipnt + cvt + 1 + len > IN_BUF_SIZE)
size = IN_BUF_SIZE - 1 - (newyomipnt + cvt + 1);
else
size = len;
strncpy(&(in_buf.str[newyomipnt + cvt + 1]), sjis, size);
in_buf.str[IN_BUF_SIZE - 1] = 0;
LEN_OF_BUF(in_buf) = strlen(&in_buf.str[1]);
} else {
cx->subst_yomi_zero_flag = 1;
in_buf.str[newyomipnt + cvt + 1] = 0;
LEN_OF_BUF(in_buf) = strlen(&in_buf.str[1]);
}
sjis2euc(in_buf.str + 1, LEN_OF_BUF(in_buf), euc, IN_BUF_SIZE);
m_msg_dbg("yomi = [%s]/%d\n", euc, LEN_OF_BUF(in_buf));
vw_make_vjebuffers(&in_buf, atrbuf, &keybuf);
vje_proto_set_kihonbuff(cx->vje.id, &in_buf, atrbuf, &keybuf);
if (cx->subst_yomi_zero_flag == 0) {
/* ただ単にバックスペースされた場合は, henkanb を呼ばないっぽい。*/
vje_proto_henkanb(cx->vje.id, &in_buf, atrbuf, &keybuf, &mode, cvt);
}
if (vw_check16(cbuf)) return -1;
koho_len = vw_after_henkan(cx_num, &in_buf, wcs, 0);
if (vw_check16(cbuf)) return -1;
datalen = koho_len + 2;
buffer_check(cbuf, 4 + datalen);
header = (cannaheader_t *)cbuf->buf;
sp =(ushort *)cbuf->buf;
header->type = 0x13;
header->extra = 0;
header->datalen = LSBMSB16(datalen);
sp[2] = LSBMSB16(cx->max_bun);
memcpy(&sp[3], wcs, koho_len);
} else {
header->type = 0x13;
header->extra = 0;
header->datalen = LSBMSB16(2);
header->err.e16 = LSBMSB16(-1);
}
return 1;
}
int vjewrapper_store_yomi(int id, buffer_t *cbuf)
{
cannaheader_t *header;
ushort *sp = (ushort *)cbuf->buf;
short cx_num, bun_no, datalen;
ushort *yomi;
int len, koho_len, pnt, i;
context_t *cx;
#if 0
buninf_t bi;
#endif
uchar euc[IN_BUF_SIZE], sjis[IN_BUF_SIZE];
ushort atrbuf[IN_BUF_SIZE * 2], wcs[IN_BUF_SIZE * 2];
buff_t in_buf;
kbuff_t keybuf;
datalen = LSBMSB16(sp[1]);
cx_num = LSBMSB16(sp[2]);
bun_no = LSBMSB16(sp[3]);
/* かんなライブラリのバグ? 変更後の読みをパケットに含めなあかんのに、
変更後の読みがヌルならなにも含まれない。
(Terminate Char である 0x0000 すら渡さない。) その対応策 */
if (datalen > 4)
yomi = &sp[4];
else
yomi = NULL;
cx = vw_get_context(cx_num);
if (yomi) {
len = cannawc2euc(yomi, cannawcstrlen(yomi), euc, IN_BUF_SIZE);
len = euc2sjis(euc, len, sjis, IN_BUF_SIZE);
} else {
len = 0;
}
#if 0
/* FIXME IF NECESSARY: OBSOLETE CODE!!! ONLY WORKS ON VJE 2.5 */
/* 厳密にはこのコードが必要かも知れないが、なくてもまともに動く? */
memset(&in_buf, 0, sizeof(buff_t));
pnt = 1;
for (i = 0; i < cx->max_bun; i++) {
memcpy(&in_buf[pnt], &cx->yomi_buffer[cx->bun[i].yomi_pnt],
cx->bun[i].yomi_len);
pnt += cx->bun[i].yomi_len;
}
in_buf[pnt] = 0;
LEN_OF_BUF(in_buf) = strlen(&in_buf[1]);
vw_make_vjebuffers(in_buf, atrbuf, keybuf);
vje_proto_set_kihonbuff(cx->vje.id, in_buf, atrbuf, keybuf);
vje_proto_get_koho_all(cx->vje.id, &bi, sjis);
vje_proto_set_koho_bno(cx->vje.id, bi.max_bun - 1);
vje_proto_chg_sdic(cx->vje.id, -1);
vje_proto_get_koho_all(cx->vje.id, &bi, sjis);
#endif
vw_move_bunsetu(cx, bun_no);
memset(&in_buf, 0, sizeof(buff_t));
pnt = 1;
for (i = 0; i < cx->max_bun; i++) {
if (i == bun_no) {
if (len > 0) {
memcpy(&in_buf.str[pnt], sjis, len);
pnt += len;
}
} else {
memcpy(&in_buf.str[pnt], &cx->yomi_buffer.str[cx->bun[i].yomi_pnt],
cx->bun[i].yomi_len);
pnt += cx->bun[i].yomi_len;
}
}
in_buf.str[pnt] = 0;
LEN_OF_BUF(in_buf) = strlen(&in_buf.str[1]);
vw_make_vjebuffers(&in_buf, atrbuf, &keybuf);
vje_proto_set_kihonbuff(cx->vje.id, &in_buf, atrbuf, &keybuf);
if (len > 0)
vje_proto_saihenkan(cx->vje.id, &in_buf, 1, len, len, 5);
else
vje_proto_saihenkan(cx->vje.id, &in_buf, 1, 0, 0, 0);
if (vw_check16(cbuf)) return -1;
koho_len = vw_after_henkan(cx_num, &in_buf, wcs, 0);
if (vw_check16(cbuf)) return -1;
datalen = koho_len + 2;
buffer_check(cbuf, 4 + datalen);
header = (cannaheader_t *)cbuf->buf;
sp = (ushort *)cbuf->buf;
header->type = 0x14;
header->extra = 0;
header->datalen = LSBMSB16(datalen);
sp[2] = LSBMSB16(cx->max_bun);
memcpy(&sp[3], wcs, koho_len);
return 1;
}
int vjewrapper_store_range(int id, buffer_t *cbuf)
{
VW_ERROR8(cbuf->buf);
return 0;
}
int vjewrapper_get_lastyomi(int id, buffer_t *cbuf)
{
cannaheader_t *header;
ushort *sp = (ushort *)cbuf->buf;
short cx_num, maxbun, datalen;
int len, cvt, i;
uchar *yomi, euc[IN_BUF_SIZE];
ushort wcs[IN_BUF_SIZE];
context_t *cx;
cx_num = LSBMSB16(sp[2]);
cx = vw_get_context(cx_num);
maxbun = cx->max_bun - 1;
for (i = cvt = 0; i < cx->max_bun; i++)
cvt += cx->bun[i].yomi_len;
i = cx->bun[maxbun].yomi_pnt + cx->bun[maxbun].yomi_len;
yomi = &cx->yomi_buffer.str[i];
len = sjis2euc(yomi, strlen(yomi), euc, IN_BUF_SIZE);
m_msg_dbg("lastyomi = [%s]\n", euc);
len = euc2cannawc(euc, len, wcs, IN_BUF_SIZE);
datalen = 2 + len * 2 + 2;
buffer_check(cbuf, datalen + 4);
header = (cannaheader_t *)cbuf->buf;
sp = (ushort *)cbuf->buf;
header->type = 0x16;
header->extra = 0;
header->datalen = LSBMSB16(datalen);
sp[2] = LSBMSB16(len);
memcpy(&sp[3], wcs, len * 2 + 2);
return 1;
}
int vjewrapper_flush_yomi(int id, buffer_t *cbuf)
{
cannaheader_t *header = (cannaheader_t *)cbuf->buf;
ushort *sp = (ushort *)cbuf->buf;
short cx_num, mode = 1, datalen;
int i, cvt, koho_len;
context_t *cx;
buff_t in_buf;
kbuff_t keybuf;
ushort atrbuf[IN_BUF_SIZE * 2], wcs[IN_BUF_SIZE * 2];
cx_num = LSBMSB16(sp[2]);
cx = vw_get_context(cx_num);
if (cx->subst_yomi_zero_flag)
mode = 3;
memcpy(&in_buf, &cx->yomi_buffer, sizeof(buff_t));
vw_make_vjebuffers(&in_buf, atrbuf, &keybuf);
/* どうやら bno には変換されている文節数を渡すらしい(自動変換のときのみ) */
vje_proto_set_koho_bno(cx->vje.id, cx->max_bun);
/* 変換されている読みの長さを取得 */
for (i = cvt = 0; i < cx->max_bun; i++)
cvt += cx->bun[i].yomi_len;
vje_proto_chg_sdic(cx->vje.id, -1);
vje_proto_set_kihonbuff(cx->vje.id, &in_buf, atrbuf, &keybuf);
vje_proto_henkanb(cx->vje.id, &in_buf, atrbuf, &keybuf, &mode, cvt);
if (vw_check16(cbuf)) return -1;
koho_len = vw_after_henkan(cx_num, &in_buf, wcs, 0);
if (vw_check16(cbuf)) return -1;
datalen = koho_len + 2;
buffer_check(cbuf, 4 + datalen);
header = (cannaheader_t *)cbuf->buf;
sp = (ushort *)cbuf->buf;
header->type = 0x17;
header->extra = 0;
header->datalen = LSBMSB16(datalen);
sp[2] = LSBMSB16(cx->max_bun);
memcpy(&sp[3], wcs, koho_len);
return 1;
}
int vjewrapper_remove_yomi(int id, buffer_t *cbuf)
{
cannaheader_t *header = (cannaheader_t *)cbuf->buf;
short *sp = (short *)cbuf->buf;
int *ip = (int *)cbuf->buf;
int i, koho_no, bun_no, len, pnt;
short cx_num, datalen;
char err;
context_t *cx;
char euc[IN_BUF_SIZE];
ushort wcs[IN_BUF_SIZE * 2];
buff_t in_buf;
buff_t tmpbuf;
datalen = LSBMSB16(sp[1]);
cx_num = LSBMSB16(sp[2]);
bun_no = LSBMSB16(sp[3]);
cx = vw_get_context(cx_num);
err = (cx->vje.id) ? 0 : -1;
if (err == 0) {
vje_proto_set_koho_bno(cx->vje.id, cx->max_bun - 1);
if (ip[2] != 0) {
for (i = 0; i <= bun_no; i++) {
if (datalen >= 8 + (i + 1) * 2) {
vw_move_bunsetu(cx, i);
koho_no = LSBMSB16(sp[6 + i]);
vw_set_koho(cx_num, i, koho_no);
}
}
if (vw_check8(cbuf)) return -1;
}
vw_move_bunsetu(cx, bun_no);
memcpy(&in_buf, &cx->yomi_buffer, sizeof(buff_t));
i = vje_proto_kakutei2(cx->vje.id, &in_buf, &tmpbuf);
if (vw_check8(cbuf)) return -1;
pnt = cx->bun[bun_no].yomi_pnt + cx->bun[bun_no].yomi_len;
len = LEN_OF_BUF(in_buf) - pnt + 1 + 1;
memmove(&in_buf.str[1], &in_buf.str[pnt], len);
LEN_OF_BUF(in_buf) = strlen(&in_buf.str[1]);
sjis2euc(in_buf.str + 1, LEN_OF_BUF(in_buf), euc, IN_BUF_SIZE);
vw_after_henkan(cx_num, &in_buf, wcs, 0);
}
header->type = 0x18;
header->extra = 0;
header->datalen = LSBMSB16(1);
header->err.e8 = cx->max_bun;
return 1;
}
int vjewrapper_get_simplekanji(int id, buffer_t *cbuf)
{
VW_ERROR16(cbuf->buf);
return 0;
}
int vjewrapper_resize_pause(int id, buffer_t *cbuf)
{
int i, j, vjeyomilen = 0, bun_no, cx_num, koho_len, datalen;
short cannayomilen;
int nbun, len, len2;
short *sp = (short *)cbuf->buf;
cannaheader_t *header;
context_t *cx;
buff_t in_buf;
ushort wcs[IN_BUF_SIZE * 2];
buninf_t bi;
doubufx_t douon;
cx_num = LSBMSB16(sp[2]);
bun_no = LSBMSB16(sp[3]);
cannayomilen = LSBMSB16(sp[4]);
cx = vw_get_context(cx_num);
if (cx->vje.id == 0) {
VW_ERROR16(cbuf->buf);
return 1;
}
vje_proto_get_koho_all(cx->vje.id, &bi, &in_buf);
if (cannayomilen == -1) { /* 文節伸ばし */
if (bun_no + 1 >= cx->max_bun)
vjeyomilen = cx->bun[bun_no].yomi_len;
else {
vjeyomilen = cx->bun[bun_no].yomi_len;
if (ISSJISKANJI1(cx->yomi_buffer.str[cx->bun[bun_no + 1].yomi_pnt]))
vjeyomilen += 2;
else
vjeyomilen++;
}
} else if (cannayomilen == -2) { /* 文節縮め */
for (i = j = 0; i < cx->bun[bun_no].yomi_len;) {
if (ISSJISKANJI1(cx->yomi_buffer.str[cx->bun[bun_no].yomi_pnt + i]))
j = 2;
else
j = 1;
i += j;
}
vjeyomilen = cx->bun[bun_no].yomi_len - j;
if (vjeyomilen <= 0)
vjeyomilen = cx->bun[bun_no].yomi_len;
} else if (cannayomilen > 0) {
j = vjeyomilen = 0;
while (j != cannayomilen) {
if (ISSJISKANJI1(cx->yomi_buffer.str[cx->bun[bun_no].yomi_pnt +
vjeyomilen]))
vjeyomilen += 2;
else
vjeyomilen++;
j++;
}
}
if (vjeyomilen > 0) {
i = bun_no; len2 = 0;
for (;;) {
len2 += cx->bun[i].yomi_len;
if (vjeyomilen <= len2)
break;
i++;
}
nbun = 1 + i - bun_no;
len = vjeyomilen;
memcpy(&in_buf, &cx->yomi_buffer, sizeof(buff_t));
vw_move_bunsetu(cx, bun_no);
vje_proto_saihenkan(cx->vje.id, &in_buf, nbun, len2, len, 5);
if (vw_check16(cbuf)) return -1;
/* 注目分節の候補数が1の場合、vje の仕様で次のブロックに
ひらがな、カタカナ,半角候補が現れる。さらに ji_block したときに
別の分節の候補が変わることがある。その対策。
*/
vje_proto_get_douon(cx->vje.id, &douon);
if (douon.cnt == 1)
vje_proto_ji_block(cx->vje.id);
vje_proto_saihenkan(cx->vje.id, &in_buf, 1, len, len, 5);
koho_len = vw_after_henkan(cx_num, &in_buf, wcs, bun_no);
if (vw_check16(cbuf)) return -1;
datalen = koho_len + 2;
buffer_check(cbuf, datalen + 4);
header = (cannaheader_t *)cbuf->buf;
sp = (short *)cbuf->buf;
header->type = 0x1a;
header->extra = 0;
header->datalen = LSBMSB16(datalen);
sp[2] = LSBMSB16(cx->max_bun);
memcpy(&(sp[3]), wcs, koho_len);
} else {
VW_ERROR16(cbuf->buf);
}
return 1;
}
int vjewrapper_get_hinshi(int id, buffer_t *cbuf)
{
cannaheader_t *header = (cannaheader_t *)cbuf->buf;
header->type = 0x1b;
header->extra = 0;
header->datalen = LSBMSB16(1);
header->err.e8 = 0;
return 1;
}
int vjewrapper_get_lex(int id, buffer_t *cbuf)
{
VW_ERROR16(cbuf->buf);
return 0;
}
int vjewrapper_get_status(int id, buffer_t *cbuf)
{
struct {
int bunnum;
int candnum;
int maxcand;
int diccand;
int ylen;
int klen;
int tlen;
} stat;
short bun_no, koho_no, cx_num;
short *sp = (short *)cbuf->buf;
int i, koho_num, koholen;
cannaheader_t *header;
context_t *cx;
uchar euc[IN_BUF_SIZE];
ushort wcs[IN_BUF_SIZE];
char *koho_inf;
cx_num = LSBMSB16(sp[2]);
bun_no = LSBMSB16(sp[3]);
koho_no = LSBMSB16(sp[4]);
cx = vw_get_context(cx_num);
if (cx->vje.id == 0) {
VW_ERROR8(cbuf->buf);
return 1;
}
i = vw_get_yomi(cx, bun_no, euc);
i = euc2cannawc(euc, i, wcs, IN_BUF_SIZE);
stat.ylen = LSBMSB32(i); /* カレント候補の読みがなのバイト数 */
if (cx->bun[bun_no].koho == NULL) {
/* まだ候補を取得してないなら取得する */
cx->bun[bun_no].koho = vw_get_koho_list(cx, bun_no, &koho_num, &koholen,
&koho_inf);
cx->bun[bun_no].koho_inf = koho_inf;
cx->bun[bun_no].koho_num = koho_num;
cx->bun[bun_no].koho_len = koholen;
}
i = cannawcstrlen(vw_retrieve_koho(cx_num, bun_no, koho_no));
stat.klen = LSBMSB32(i); /* カレント候補の漢字候補のバイト数 */
stat.tlen = LSBMSB32(1); /* カレント候補の構成単語数 */
i = cx->bun[bun_no].koho_num;
stat.maxcand = LSBMSB32(i); /* カレント文節の候補数 */
i -= m_count_canna_mode(cx->canna_mode);
stat.diccand = LSBMSB32(i); /* maxcand - モード指定分 */
stat.bunnum = LSBMSB32(bun_no); /* カレント文節番号 */
stat.candnum = LSBMSB32(koho_no); /* カレント候補番号 */
if (vw_check8(cbuf)) return -1;
buffer_check(cbuf, 33);
header = (cannaheader_t *)cbuf->buf;
header->type = 0x1d;
header->extra = 0;
header->datalen = LSBMSB16(29);
cbuf->buf[4] = 0;
memcpy(&(cbuf->buf[5]), (char *)&stat, 28);
return 1;
}
int vjewrapper_set_locale(int id, buffer_t *cbuf)
{
VW_ERROR8(cbuf->buf);
return 0;
}
int vjewrapper_auto_convert(int id, buffer_t *cbuf)
{
cannaheader_t *header = (cannaheader_t *)cbuf->buf;
short *sp = (short *)cbuf->buf;
int *ip = (int *)cbuf->buf;
int cmode;
short cx_num;
context_t *cx;
cx_num = LSBMSB16(sp[2]);
cmode = LSBMSB32(ip[2]);
cx = vw_get_context(cx_num);
if (cx->vje.id == 0)
vw_open_vje_library(cx_num); /* 失敗したら cx->vje.id は 0 のまま */
if (cx->vje.id) {
vje_proto_clear(cx->vje.id);
vw_clear_context(cx_num);
cx->subst_yomi_zero_flag = 0;
cx->canna_mode = cmode;
/* 必要ならここでコンテキストにフラグをたてる */
header->datalen = LSBMSB16(1);
header->err.e8 = 0;
} else {
header->datalen = LSBMSB16(1);
header->err.e8 = -1;
}
return 1;
}
syntax highlighted by Code2HTML, v. 0.9.1