/* imx-ispell.c -- Ispell input method external module. -*- coding: euc-jp; -*-
Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
National Institute of Advanced Industrial Science and Technology (AIST)
Registration Number H15PRO112
This file is part of the m17n library.
The m17n 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.
The m17n 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 the m17n library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA. */
/***en
@enpage mimx-ispell external module for the input method <en, ispell>
@section mimx-ispell-description DESCRIPTION
The shared library mimx-ispell.so is an external module used by the
input method <en, ispell>. It exports these functions.
<ul>
<li> init
Initialize this library.
<li> fini
Finalize this library.
<li> ispell_word
Check the spell of the current preedit text (English) and, if the
spell is incorrect, return a list of candidates.
</ul>
This program is just for demonstrating how to write an external
module for an m17n input method, not for an actual use.
@section mimx-ispell-seealso See also
@ref mdbIM
*/
/***ja
@japage mimx-ispell 入力メソッド <en, ispell> 用外部モジュール
@section mimx-ispell-description DESCRIPTION
共有ライブラリ mimx-ispell.so は入力メソッド <en, ispell> に用いら
れる外部モジュールであり、以下の関数を export している。
<ul>
<li> init
ライブラリの初期化。
<li> fini
ライブラリの終了。
<li> ispell_word
現在の preedit テキスト (英文) の綴を調べ、間違っていれば候補のリ
ストを返す。
</ul>
このプログラムはm17n 入力メソッド用外部モジュールの書き方を示すた
めのものであり、実際の利用を意図したものではない。
@section mimx-ispell-seealso 参照
@ref mdbIM
*/
#ifndef FOR_DOXYGEN
#include <stdio.h>
#include <string.h>
#include <m17n-gui.h>
#ifdef HAVE_ISPELL
static int initialized = 0;
static int face_available;
static MFace *mface_overstrike = NULL;
static MPlist *
add_action (MPlist *actions, MSymbol name, MSymbol key, void *val)
{
MPlist *action = mplist ();
mplist_add (action, Msymbol, name);
if (key != Mnil)
mplist_add (action, key, val);
mplist_add (actions, Mplist, action);
m17n_object_unref (action);
return actions;
}
MPlist *
init (MPlist *args)
{
if (! initialized++)
{
MFaceHLineProp hline;
face_available = 0;
if (m17n_status () == M17N_GUI_INITIALIZED)
{
face_available = 1;
hline.type = MFACE_HLINE_STRIKE_THROUGH;
hline.width = 1;
hline.color = msymbol ("black");
mface_overstrike = mface ();
mface_put_prop (mface_overstrike, Mhline, &hline);
}
}
return NULL;
}
MPlist *
fini (MPlist *args)
{
if (initialized != 0
&& --initialized == 0
&& face_available)
m17n_object_unref (mface_overstrike);
return NULL;
}
MPlist *
ispell_word (MPlist *args)
{
MInputContext *ic;
unsigned char buf[256];
int nbytes;
MPlist *actions, *candidates, *plist;
char command[256];
char **words;
FILE *ispell;
char *p = (char *) buf;
int i, n;
MSymbol init_state;
MSymbol select_state;
MText *mt;
ic = mplist_value (args);
args = mplist_next (args);
init_state = (MSymbol) mplist_value (args);
args = mplist_next (args);
select_state = (MSymbol) mplist_value (args);
nbytes = mconv_encode_buffer (Mcoding_us_ascii, ic->preedit, buf, 256);
actions = mplist ();
if (nbytes < 3)
return add_action (actions, msymbol ("shift"), Msymbol, init_state);
buf[nbytes] = '\0';
sprintf (command, "echo %s | ispell -a -m", (char *) buf);
ispell = popen (command, "r");
if (! ispell)
return add_action (actions, msymbol ("shift"), Msymbol, init_state);
/* Skip the heading line. */
fgets (p, 256, ispell);
/* Read just 256 bytes, thus candidates listed after the first 256
bytes are just ignored. */
fgets (p, 256, ispell);
pclose (ispell);
p[strlen (p) - 1] = '\0';
if (*p != '&' && *p != '#')
return add_action (actions, msymbol ("shift"), Msymbol, init_state);
add_action (actions, msymbol ("delete"), Msymbol, msymbol ("@<"));
if (*p == '#')
{
mt = mtext_dup (ic->preedit);
if (face_available)
mtext_push_prop (mt, 0, mtext_len (mt), Mface, mface_overstrike);
mplist_add (actions, Mtext, mt);
add_action (actions, msymbol ("shift"), Msymbol, init_state);
m17n_object_unref (mt);
return actions;
}
p = strchr (p + 2, ' ');
if (sscanf (p, "%d", &n) != 1)
return add_action (actions, msymbol ("shift"), Msymbol, init_state);
words = alloca (sizeof (char *) * n);
p = strchr (p + 1, ' ');
p = strchr (p + 1, ' ');
for (i = 0; i < n - 1; i++)
{
words[i] = ++p;
p = strchr (p, ',');
if (! p)
{
n = i - 1;
break;
}
*p++ = '\0';
}
words[i] = ++p;
candidates = mplist ();
for (i = 0; i < n; i++)
{
mt = mconv_decode_buffer (Mcoding_us_ascii, (unsigned char *) words[i],
strlen (words[i]));
mplist_add (candidates, Mtext, mt);
m17n_object_unref (mt);
}
mt = mtext_dup (ic->preedit);
if (face_available)
mtext_push_prop (mt, 0, mtext_len (mt), Mface, mface_overstrike);
mplist_add (candidates, Mtext, mt);
m17n_object_unref (mt);
plist = mplist_add (mplist (), Mplist, candidates);
m17n_object_unref (candidates);
mplist_add (actions, Mplist, plist);
m17n_object_unref (plist);
add_action (actions, msymbol ("show"), Mnil, NULL);
add_action (actions, msymbol ("shift"), Msymbol, select_state);
return actions;
}
#else /* not HAVE_ISPELL */
MPlist *ispell_word (MPlist *args) { return NULL; }
#endif /* not HAVE_ISPELL */
#endif /* not FOR_DOXYGEN */