*** empty log message ***
[m17n/m17n-lib.git] / example / mimx-ispell.c
1 /* imx-ispell.c -- Input method external module for Ispell.
2    Copyright (C) 2003, 2004
3      National Institute of Advanced Industrial Science and Technology (AIST)
4      Registration Number H15PRO112
5
6    This file is part of the m17n library.
7
8    The m17n library is free software; you can redistribute it and/or
9    modify it under the terms of the GNU Lesser General Public License
10    as published by the Free Software Foundation; either version 2.1 of
11    the License, or (at your option) any later version.
12
13    The m17n library is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Lesser General Public License for more details.
17
18    You should have received a copy of the GNU Lesser General Public
19    License along with the m17n library; if not, write to the Free
20    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21    02111-1307, USA.  */
22
23 /***en
24     @enpage mimx-ispell external module for the input method <en, ispell>
25
26     @section mimx-ispell-description DESCRIPTION
27
28     The shared library mimx-ispell.so is an external module used by the
29     input method <en, ispell>.  It exports these functions.
30
31     <ul>
32     <li> init
33
34     Initialize this library.
35
36     <li> fini
37
38     Finalize this library.
39
40     <li> ispell_word
41
42     Check the spell of the current preedit text (English) and, if the
43     spell is incorrect,  return a list of candidates.
44
45     </ul>
46
47     This program is just for demonstrating how to write an external
48     module for an m17n input method, not for an actual use.
49
50     @section mimx-ispell-seealso See also
51     @ref mdbIM
52 */
53 /***ja
54     @japage mimx-ispell ÆþÎϥ᥽¥Ã¥É <en, ispell> Íѳ°Éô¥â¥¸¥å¡¼¥ë
55
56     @section mimx-ispell-description DESCRIPTION
57
58     ¶¦Í­¥é¥¤¥Ö¥é¥ê mimx-ispell.so ¤ÏÆþÎϥ᥽¥Ã¥É <en, ispell> ¤ËÍѤ¤¤é 
59     ¤ì¤ë³°Éô¥â¥¸¥å¡¼¥ë¤Ç¤¢¤ê¡¢°Ê²¼¤Î´Ø¿ô¤ò export ¤·¤Æ¤¤¤ë¡£
60
61     <ul>
62     <li> init
63
64     ¥é¥¤¥Ö¥é¥ê¤Î½é´ü²½¡£
65
66     <li> fini
67
68     ¥é¥¤¥Ö¥é¥ê¤Î½ªÎ»¡£ 
69
70     <li> ispell_word
71
72     ¸½ºß¤Î preedit ¥Æ¥­¥¹¥È (±Ñʸ) ¤ÎÄÖ¤òÄ´¤Ù¡¢´Ö°ã¤Ã¤Æ¤¤¤ì¤Ð¸õÊä¤Î¥ê 
73     ¥¹¥È¤òÊÖ¤¹¡£
74
75     </ul>
76
77     ¤³¤Î¥×¥í¥°¥é¥à¤Ïm17n ÆþÎϥ᥽¥Ã¥ÉÍѳ°Éô¥â¥¸¥å¡¼¥ë¤Î½ñ¤­Êý¤ò¼¨¤¹¤¿ 
78     ¤á¤Î¤â¤Î¤Ç¤¢¤ê¡¢¼ÂºÝ¤ÎÍøÍѤò°Õ¿Þ¤·¤¿¤â¤Î¤Ç¤Ï¤Ê¤¤¡£
79
80     @section mimx-ispell-seealso »²¾È
81     @ref mdbIM
82 */
83
84 #ifndef FOR_DOXYGEN
85
86 #include <stdio.h>
87 #include <string.h>
88 #include <config.h>
89 #include <m17n-gui.h>
90
91 #ifdef HAVE_ISPELL
92
93 static int initialized = 0;
94 static MFace *mface_overstrike = NULL;
95
96 static MPlist *
97 add_action (MPlist *actions, MSymbol name, MSymbol key, void *val)
98 {
99   MPlist *action = mplist ();
100
101   mplist_add (action, Msymbol, name);
102   if (key != Mnil)
103     mplist_add (action, key, val);
104   mplist_add (actions, Mplist, action);
105   m17n_object_unref (action);
106   return actions;
107 }
108
109 MPlist *
110 init (MPlist *args)
111 {
112   if (! initialized++)
113     {
114       MFaceHLineProp hline;
115
116       hline.type = MFACE_HLINE_STRIKE_THROUGH;
117       hline.width = 1;
118       hline.color = msymbol ("black");
119       mface_overstrike = mface ();
120       mface_put_prop (mface_overstrike, Mhline, &hline);
121     }
122   return NULL;
123 }
124
125 MPlist *
126 fini (MPlist *args)
127 {
128   if (! --initialized)
129     m17n_object_unref (mface_overstrike);
130   return NULL;
131 }
132
133 MPlist *
134 ispell_word (MPlist *args)
135 {
136   MInputContext *ic;
137   unsigned char buf[256];
138   int nbytes;
139   MPlist *actions, *candidates, *plist;
140   char command[256];
141   char **words;
142   FILE *ispell;
143   char *p = (char *) buf;
144   int i, n;
145   MSymbol init_state;
146   MSymbol select_state;
147   MText *mt;
148
149   ic = mplist_value (args);
150   args = mplist_next (args);
151   init_state = (MSymbol) mplist_value (args);
152   args = mplist_next (args);
153   select_state = (MSymbol) mplist_value (args);
154   nbytes = mconv_encode_buffer (Mcoding_us_ascii, ic->preedit, buf, 256);
155
156   actions = mplist ();
157
158   if (nbytes < 3)
159     return add_action (actions, msymbol ("shift"), Msymbol, init_state);
160
161   buf[nbytes] = '\0';
162   sprintf (command, "echo %s | ispell -a -m", (char *) buf);
163   ispell = popen (command, "r");
164   if (! ispell)
165     return add_action (actions, msymbol ("shift"), Msymbol, init_state);
166
167   /* Skip the heading line.  */
168   fgets (p, 256, ispell);
169   /* Read just 256 bytes, thus candidates listed after the first 256
170      bytes are just ignored.  */
171   fgets (p, 256, ispell);
172   pclose (ispell);
173   p[strlen (p) - 1] = '\0';
174   if (*p != '&' && *p != '#')
175     return add_action (actions, msymbol ("shift"), Msymbol, init_state);
176
177   add_action (actions, msymbol ("delete"), Msymbol,  msymbol ("@<"));
178   if (*p == '#')
179     {
180       mt = mtext_dup (ic->preedit);
181       mtext_push_prop (mt, 0, mtext_len (mt), Mface, mface_overstrike);
182       mplist_add (actions, Mtext, mt);
183       add_action (actions, msymbol ("shift"), Msymbol, init_state);
184       m17n_object_unref (mt);
185       return actions;
186     }
187
188   p = strchr (p + 2, ' ');
189   if (sscanf (p, "%d", &n) != 1)
190     return add_action (actions, msymbol ("shift"), Msymbol, init_state);
191   words = alloca (sizeof (char *) * n);
192   p = strchr (p + 1, ' ');
193   p = strchr (p + 1, ' ');
194   for (i = 0; i < n - 1; i++)
195     {
196       words[i] = ++p;
197       p = strchr (p, ',');
198       if (! p)
199         {
200           n = i - 1;
201           break;
202         }
203       *p++ = '\0';
204     }
205   words[i] = ++p;
206   candidates = mplist ();
207   for (i = 0; i < n; i++)
208     {
209       mt = mconv_decode_buffer (Mcoding_us_ascii, (unsigned char *) words[i],
210                                 strlen (words[i]));
211       mplist_add (candidates, Mtext, mt);
212       m17n_object_unref (mt);
213     }
214   mt = mtext_dup (ic->preedit);
215   mtext_push_prop (mt, 0, mtext_len (mt), Mface, mface_overstrike);
216   mplist_add (candidates, Mtext, mt);
217   m17n_object_unref (mt);
218   plist = mplist_add (mplist (), Mplist, candidates);
219   m17n_object_unref (candidates);
220   mplist_add (actions, Mplist, plist);
221   m17n_object_unref (plist);
222   add_action (actions, msymbol ("show"), Mnil, NULL);
223   add_action (actions, msymbol ("shift"), Msymbol, select_state);
224   return actions;
225 }
226
227 #else  /* not HAVE_ISPELL */
228
229 MPlist *ispell_word (MPlist *args) { return NULL; }
230
231 #endif /* not HAVE_ISPELL */
232 #endif /* not FOR_DOXYGEN */