summaryrefslogtreecommitdiff
path: root/src-main/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src-main/main.c')
-rw-r--r--src-main/main.c545
1 files changed, 545 insertions, 0 deletions
diff --git a/src-main/main.c b/src-main/main.c
new file mode 100644
index 0000000..024cb6e
--- /dev/null
+++ b/src-main/main.c
@@ -0,0 +1,545 @@
+/*
+ * Comments in this program are written in Japanese,
+ * because this program is a Japanese input method.
+ * (many Japanese gramatical terms will appear.)
+ *
+ * Kana-Kanji conversion engine Anthy.
+ * 仮名漢字変換エンジンAnthy(アンシー)
+ *
+ * Funded by IPA未踏ソフトウェア創造事業 2001 9/22
+ * Funded by IPA未踏ソフトウェア創造事業 2005
+ * Copyright (C) 2000-2007 TABATA Yusuke, UGAWA Tomoharu
+ * Copyright (C) 2004-2006 YOSHIDA Yuichi
+ * Copyright (C) 2000-2007 KMC(Kyoto University Micro Computer Club)
+ * Copyright (C) 2001-2002 TAKAI Kosuke, Nobuoka Takahiro
+ *
+ */
+/*
+ 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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/*
+ * Anthyの変換機能はライブラリとして構成されており、この
+ * ファイルにはライブラリの提供する関数(API)が記述されています。
+ *
+ * ライブラリの提供する関数は下記のようなものがあります
+ * (1)ライブラリ全体の初期化、終了、設定
+ * (2)変換コンテキストの作成、解放
+ * (3)変換コンテキストに対する文字列の設定、文節長の変更、候補の取得等
+ *
+ * インターフェイスに関しては doc/LIBを参照してください
+ * Anthyのコードを理解しようとする場合は
+ * doc/GLOSSARY で用語を把握することを勧めます
+ */
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <anthy/dic.h>
+#include <anthy/splitter.h>
+#include <anthy/conf.h>
+#include <anthy/ordering.h>
+#include <anthy/logger.h>
+#include <anthy/record.h>
+#include <anthy/anthy.h>
+#include <anthy/record.h>
+#include <anthy/xchar.h> /* for KK_VU */
+#include "main.h"
+#include "config.h"
+
+
+/** Anthyの初期化が完了したかどうかのフラグ */
+static int is_init_ok;
+/** コンテキスト生成時のエンコーディング */
+static int default_encoding;
+/***/
+static char *history_file;
+
+/** (API) 全体の初期化 */
+int
+anthy_init(void)
+{
+ char *hfn;
+ if (is_init_ok) {
+ /* 2度初期化しないように */
+ return 0;
+ }
+
+ /* 各サブシステムを順に初期化する */
+ if (anthy_init_dic()) {
+ anthy_log(0, "Failed to initialize dictionary.\n");
+ return -1;
+ }
+
+ if (anthy_init_splitter()) {
+ anthy_log(0, "Failed to init splitter.\n");
+ return -1;
+ }
+ anthy_init_contexts();
+ anthy_init_personality();
+ anthy_infosort_init();
+ anthy_relation_init();
+
+ /**/
+ default_encoding = ANTHY_EUC_JP_ENCODING;
+ is_init_ok = 1;
+ history_file = NULL;
+ hfn = getenv("ANTHY_HISTORY_FILE");
+ if (hfn) {
+ history_file = strdup(hfn);
+ }
+
+ /**/
+ return 0;
+}
+
+/** (API) 全データの解放 */
+void
+anthy_quit(void)
+{
+ if (!is_init_ok) {
+ return ;
+ }
+ anthy_quit_contexts();
+ anthy_quit_personality();
+ anthy_quit_splitter();
+ /* 多くのデータ構造はここでallocatorによって解放される */
+ anthy_quit_dic();
+
+ is_init_ok = 0;
+ /**/
+ if (history_file) {
+ free(history_file);
+ }
+ history_file = NULL;
+}
+
+/** (API) 設定項目の上書き */
+void
+anthy_conf_override(const char *var, const char *val)
+{
+ anthy_do_conf_override(var, val);
+}
+
+/** (API) personalityの設定 */
+int
+anthy_set_personality(const char *id)
+{
+ return anthy_do_set_personality(id);
+}
+
+/** (API) 変換contextの作成 */
+struct anthy_context *
+anthy_create_context(void)
+{
+ if (!is_init_ok) {
+ return 0;
+ }
+ return anthy_do_create_context(default_encoding);
+}
+
+/** (API) 変換contextのリセット */
+void
+anthy_reset_context(struct anthy_context *ac)
+{
+ anthy_do_reset_context(ac);
+}
+
+/** (API) 変換contextの解放 */
+void
+anthy_release_context(struct anthy_context *ac)
+{
+ anthy_do_release_context(ac);
+}
+
+/**
+ * 再変換が必要かどうかの判定
+ */
+static int
+need_reconvert(struct anthy_context *ac, xstr *xs)
+{
+ int i;
+
+ if (ac->reconversion_mode == ANTHY_RECONVERT_ALWAYS) {
+ return 1;
+ }
+ if (ac->reconversion_mode == ANTHY_RECONVERT_DISABLE) {
+ return 0;
+ }
+
+ for (i = 0; i < xs->len; ++i) {
+ xchar xc = xs->str[i];
+ int type = anthy_get_xchar_type(xc);
+
+ /* これらの文字種の場合は逆変換する
+ * 「ヴ」はフロントエンドが平仮名モードの文字列として送ってくるので、
+ * 逆変換の対象とはしない
+ */
+ if (!(type & (XCT_HIRA | XCT_SYMBOL | XCT_NUM |
+ XCT_WIDENUM | XCT_OPEN | XCT_CLOSE |
+ XCT_ASCII)) &&
+ xc != KK_VU) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+/** (API) 変換文字列の設定 */
+int
+anthy_set_string(struct anthy_context *ac, const char *s)
+{
+ xstr *xs;
+ int retval;
+
+ if (!ac) {
+ return -1;
+ }
+
+ /*初期化*/
+ anthy_do_reset_context(ac);
+
+ /* 辞書セッションの開始 */
+ if (!ac->dic_session) {
+ ac->dic_session = anthy_dic_create_session();
+ if (!ac->dic_session) {
+ return -1;
+ }
+ }
+
+ anthy_dic_activate_session(ac->dic_session);
+ /* 変換を開始する前に個人辞書をreloadする */
+ anthy_reload_record();
+
+ xs = anthy_cstr_to_xstr(s, ac->encoding);
+ /**/
+ if (!need_reconvert(ac, xs)) {
+ /* 普通に変換する */
+ retval = anthy_do_context_set_str(ac, xs, 0);
+ } else {
+ /* 漢字やカタカナが混じっていたら再変換してみる */
+ struct anthy_conv_stat stat;
+ struct seg_ent *seg;
+ int i;
+ xstr* hira_xs;
+ /* 与えられた文字列に変換をかける */
+ retval = anthy_do_context_set_str(ac, xs, 1);
+
+ /* 各文節の第一候補を取得して平仮名列を得る */
+ anthy_get_stat(ac, &stat);
+ hira_xs = NULL;
+ for (i = 0; i < stat.nr_segment; ++i) {
+ seg = anthy_get_nth_segment(&ac->seg_list, i);
+ hira_xs = anthy_xstrcat(hira_xs, &seg->cands[0]->str);
+ }
+ /* 改めて変換を行なう */
+ anthy_release_segment_list(ac);
+ retval = anthy_do_context_set_str(ac, hira_xs, 0);
+ anthy_free_xstr(hira_xs);
+ }
+
+ anthy_free_xstr(xs);
+ return retval;
+}
+
+/** (API) 文節長の変更 */
+void
+anthy_resize_segment(struct anthy_context *ac, int nth, int resize)
+{
+ anthy_dic_activate_session(ac->dic_session);
+ anthy_do_resize_segment(ac, nth, resize);
+}
+
+/** (API) 変換の状態の取得 */
+int
+anthy_get_stat(struct anthy_context *ac, struct anthy_conv_stat *s)
+{
+ s->nr_segment = ac->seg_list.nr_segments;
+ return 0;
+}
+
+/** (API) 文節の状態の取得 */
+int
+anthy_get_segment_stat(struct anthy_context *ac, int n,
+ struct anthy_segment_stat *s)
+{
+ struct seg_ent *seg;
+ seg = anthy_get_nth_segment(&ac->seg_list, n);
+ if (seg) {
+ s->nr_candidate = seg->nr_cands;
+ s->seg_len = seg->str.len;
+ return 0;
+ }
+ return -1;
+}
+
+static int
+get_special_candidate_index(int nth, struct seg_ent *seg)
+{
+ int i;
+ int mask = XCT_NONE;
+ if (nth >= 0) {
+ return nth;
+ }
+ if (nth == NTH_UNCONVERTED_CANDIDATE ||
+ nth == NTH_HALFKANA_CANDIDATE) {
+ return nth;
+ }
+ if (nth == NTH_KATAKANA_CANDIDATE) {
+ mask = XCT_KATA;
+ } else if (nth == NTH_HIRAGANA_CANDIDATE) {
+ mask = XCT_HIRA;
+ }
+ for (i = 0; i < seg->nr_cands; i++) {
+ if (anthy_get_xstr_type(&seg->cands[i]->str) & mask) {
+ return i;
+ }
+ }
+ return NTH_UNCONVERTED_CANDIDATE;
+}
+
+/** (API) 文節の取得 */
+int
+anthy_get_segment(struct anthy_context *ac, int nth_seg,
+ int nth_cand, char *buf, int buflen)
+{
+ struct seg_ent *seg;
+ char *p;
+ int len;
+
+ /* 文節を取り出す */
+ if (nth_seg < 0 || nth_seg >= ac->seg_list.nr_segments) {
+ return -1;
+ }
+ seg = anthy_get_nth_segment(&ac->seg_list, nth_seg);
+
+ /* 文節から候補を取り出す */
+ p = NULL;
+ if (nth_cand < 0) {
+ nth_cand = get_special_candidate_index(nth_cand, seg);
+ }
+ if (nth_cand == NTH_HALFKANA_CANDIDATE) {
+ xstr *xs = anthy_xstr_hira_to_half_kata(&seg->str);
+ p = anthy_xstr_to_cstr(xs, ac->encoding);
+ anthy_free_xstr(xs);
+ } else if (nth_cand == NTH_UNCONVERTED_CANDIDATE) {
+ /* 変換前の文字列を取得する */
+ p = anthy_xstr_to_cstr(&seg->str, ac->encoding);
+ } else if (nth_cand >= 0 && nth_cand < seg->nr_cands) {
+ p = anthy_xstr_to_cstr(&seg->cands[nth_cand]->str, ac->encoding);
+ }
+ if (!p) {
+ return -1;
+ }
+
+ /* バッファに書き込む */
+ len = strlen(p);
+ if (!buf) {
+ free(p);
+ return len;
+ }
+ if (len + 1 > buflen) {
+ /* バッファが足りません */
+ free(p);
+ return -1;
+ }
+ strcpy(buf, p);
+ free(p);
+ return len;
+}
+
+/* すべての文節がコミットされたかcheckする */
+static int
+commit_all_segment_p(struct anthy_context *ac)
+{
+ int i;
+ struct seg_ent *se;
+ for (i = 0; i < ac->seg_list.nr_segments; i++) {
+ se = anthy_get_nth_segment(&ac->seg_list, i);
+ if (se->committed < 0) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/** (API) 文節の確定 */
+int
+anthy_commit_segment(struct anthy_context *ac, int s, int c)
+{
+ struct seg_ent *seg;
+ if (!ac->str.str) {
+ return -1;
+ }
+ if (s < 0 || s >= ac->seg_list.nr_segments) {
+ return -1;
+ }
+ if (commit_all_segment_p(ac)) {
+ /* すでに全てのセグメントがコミットされている */
+ return -1;
+ }
+
+ anthy_dic_activate_session(ac->dic_session);
+ seg = anthy_get_nth_segment(&ac->seg_list, s);
+ if (c < 0) {
+ c = get_special_candidate_index(c, seg);
+ }
+ if (c == NTH_UNCONVERTED_CANDIDATE) {
+ /*
+ * 変換前の文字列がコミットされたので,それに対応する候補の番号を探す
+ */
+ int i;
+ for (i = 0; i < seg->nr_cands; i++) {
+ if (!anthy_xstrcmp(&seg->str, &seg->cands[i]->str)) {
+ c = i;
+ }
+ }
+ }
+ if (c < 0 || c >= seg->nr_cands) {
+ return -1;
+ }
+ seg->committed = c;
+
+ if (commit_all_segment_p(ac)) {
+ /* 今、すべてのセグメントがコミットされた */
+ anthy_proc_commit(&ac->seg_list, &ac->split_info);
+ /**/
+ anthy_save_history(history_file, ac);
+ }
+ return 0;
+}
+
+/** (API) 予測してほしい文字列の設定 */
+int
+anthy_set_prediction_string(struct anthy_context *ac, const char* s)
+{
+ int retval;
+ xstr *xs;
+
+ anthy_dic_activate_session(ac->dic_session);
+ /* 予測を開始する前に個人辞書をreloadする */
+ anthy_reload_record();
+
+
+ xs = anthy_cstr_to_xstr(s, ac->encoding);
+
+ retval = anthy_do_set_prediction_str(ac, xs);
+
+ anthy_free_xstr(xs);
+
+ return retval;
+}
+
+/** (API) 予測変換の状態の取得 */
+int
+anthy_get_prediction_stat(struct anthy_context *ac, struct anthy_prediction_stat * ps)
+{
+ ps->nr_prediction = ac->prediction.nr_prediction;
+ return 0;
+}
+
+/** (API) 予測変換の候補の取得 */
+int
+anthy_get_prediction(struct anthy_context *ac, int nth, char* buf, int buflen)
+{
+ struct prediction_cache* prediction = &ac->prediction;
+ int nr_prediction = prediction->nr_prediction;
+ char* p;
+ int len;
+
+ if (nth < 0 || nr_prediction <= nth) {
+ return -1;
+ }
+
+ p = anthy_xstr_to_cstr(prediction->predictions[nth].str, ac->encoding);
+
+ /* バッファに書き込む */
+ len = strlen(p);
+ if (!buf) {
+ free(p);
+ return len;
+ }
+ if (len + 1 > buflen) {
+ free(p);
+ return -1;
+ } else {
+ strcpy(buf, p);
+ free(p);
+ return len;
+ }
+}
+
+/** (API) 予測の結果を確定する
+ */
+int
+anthy_commit_prediction(struct anthy_context *ac, int nth)
+{
+ struct prediction_cache* pc = &ac->prediction;
+ if (nth < 0 || nth >= pc->nr_prediction) {
+ return -1;
+ }
+ anthy_do_commit_prediction(pc->predictions[nth].src_str,
+ pc->predictions[nth].str);
+ return 0;
+}
+
+/** (API) 開発用 */
+void
+anthy_print_context(struct anthy_context *ac)
+{
+ anthy_do_print_context(ac, default_encoding);
+}
+
+/** (API) Anthy ライブラリのバージョンを表す文字列を返す
+ * 共有ライブラリでは外部変数のエクスポートは好ましくないので関数にしてある
+ */
+const char *
+anthy_get_version_string (void)
+{
+#ifdef VERSION
+ return VERSION;
+#else /* just in case */
+ return "(unknown)";
+#endif
+}
+
+/** (API) */
+int
+anthy_context_set_encoding(struct anthy_context *ac, int encoding)
+{
+ if (!ac) {
+ return ANTHY_EUC_JP_ENCODING;
+ }
+ if (encoding == ANTHY_UTF8_ENCODING ||
+ encoding == ANTHY_EUC_JP_ENCODING) {
+ ac->encoding = encoding;
+ }
+ return ac->encoding;
+}
+
+/** (API) */
+int
+anthy_set_reconversion_mode(anthy_context_t ac, int mode)
+{
+ if (!ac) {
+ return ANTHY_RECONVERT_AUTO;
+ }
+ if (mode == ANTHY_RECONVERT_AUTO ||
+ mode == ANTHY_RECONVERT_DISABLE ||
+ mode == ANTHY_RECONVERT_ALWAYS) {
+ ac->reconversion_mode = mode;
+ }
+ return ac->reconversion_mode;
+}