Fix documentation.
[m17n/m17n-lib.git] / example / mimx-ispell.c
1 /* imx-ispell.c -- Ispell input method external module. -*- coding: euc-jp; -*-
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 int face_available;
95 static MFace *mface_overstrike = NULL;
96
97 static MPlist *
98 add_action (MPlist *actions, MSymbol name, MSymbol key, void *val)
99 {
100   MPlist *action = mplist ();
101
102   mplist_add (action, Msymbol, name);
103   if (key != Mnil)
104     mplist_add (action, key, val);
105   mplist_add (actions, Mplist, action);
106   m17n_object_unref (action);
107   return actions;
108 }
109
110 MPlist *
111 init (MPlist *args)
112 {
113   if (! initialized++)
114     {
115       MFaceHLineProp hline;
116
117       face_available = 0;
118       if (m17n_status () == M17N_GUI_INITIALIZED)
119         {
120           face_available = 1;
121           hline.type = MFACE_HLINE_STRIKE_THROUGH;
122           hline.width = 1;
123           hline.color = msymbol ("black");
124           mface_overstrike = mface ();
125           mface_put_prop (mface_overstrike, Mhline, &hline);
126         }
127     }
128   return NULL;
129 }
130
131 MPlist *
132 fini (MPlist *args)
133 {
134   if (initialized != 0
135       && --initialized == 0
136       && face_available)
137     m17n_object_unref (mface_overstrike);
138   return NULL;
139 }
140
141 MPlist *
142 ispell_word (MPlist *args)
143 {
144   MInputContext *ic;
145   unsigned char buf[256];
146   int nbytes;
147   MPlist *actions, *candidates, *plist;
148   char command[256];
149   char **words;
150   FILE *ispell;
151   char *p = (char *) buf;
152   int i, n;
153   MSymbol init_state;
154   MSymbol select_state;
155   MText *mt;
156
157   ic = mplist_value (args);
158   args = mplist_next (args);
159   init_state = (MSymbol) mplist_value (args);
160   args = mplist_next (args);
161   select_state = (MSymbol) mplist_value (args);
162   nbytes = mconv_encode_buffer (Mcoding_us_ascii, ic->preedit, buf, 256);
163
164   actions = mplist ();
165
166   if (nbytes < 3)
167     return add_action (actions, msymbol ("shift"), Msymbol, init_state);
168
169   buf[nbytes] = '\0';
170   sprintf (command, "echo %s | ispell -a -m", (char *) buf);
171   ispell = popen (command, "r");
172   if (! ispell)
173     return add_action (actions, msymbol ("shift"), Msymbol, init_state);
174
175   /* Skip the heading line.  */
176   fgets (p, 256, ispell);
177   /* Read just 256 bytes, thus candidates listed after the first 256
178      bytes are just ignored.  */
179   fgets (p, 256, ispell);
180   pclose (ispell);
181   p[strlen (p) - 1] = '\0';
182   if (*p != '&' && *p != '#')
183     return add_action (actions, msymbol ("shift"), Msymbol, init_state);
184
185   add_action (actions, msymbol ("delete"), Msymbol,  msymbol ("@<"));
186   if (*p == '#')
187     {
188       mt = mtext_dup (ic->preedit);
189       if (face_available)
190         mtext_push_prop (mt, 0, mtext_len (mt), Mface, mface_overstrike);
191       mplist_add (actions, Mtext, mt);
192       add_action (actions, msymbol ("shift"), Msymbol, init_state);
193       m17n_object_unref (mt);
194       return actions;
195     }
196
197   p = strchr (p + 2, ' ');
198   if (sscanf (p, "%d", &n) != 1)
199     return add_action (actions, msymbol ("shift"), Msymbol, init_state);
200   words = alloca (sizeof (char *) * n);
201   p = strchr (p + 1, ' ');
202   p = strchr (p + 1, ' ');
203   for (i = 0; i < n - 1; i++)
204     {
205       words[i] = ++p;
206       p = strchr (p, ',');
207       if (! p)
208         {
209           n = i - 1;
210           break;
211         }
212       *p++ = '\0';
213     }
214   words[i] = ++p;
215   candidates = mplist ();
216   for (i = 0; i < n; i++)
217     {
218       mt = mconv_decode_buffer (Mcoding_us_ascii, (unsigned char *) words[i],
219                                 strlen (words[i]));
220       mplist_add (candidates, Mtext, mt);
221       m17n_object_unref (mt);
222     }
223   mt = mtext_dup (ic->preedit);
224   if (face_available)
225     mtext_push_prop (mt, 0, mtext_len (mt), Mface, mface_overstrike);
226   mplist_add (candidates, Mtext, mt);
227   m17n_object_unref (mt);
228   plist = mplist_add (mplist (), Mplist, candidates);
229   m17n_object_unref (candidates);
230   mplist_add (actions, Mplist, plist);
231   m17n_object_unref (plist);
232   add_action (actions, msymbol ("show"), Mnil, NULL);
233   add_action (actions, msymbol ("shift"), Msymbol, select_state);
234   return actions;
235 }
236
237 #else  /* not HAVE_ISPELL */
238
239 MPlist *ispell_word (MPlist *args) { return NULL; }
240
241 #endif /* not HAVE_ISPELL */
242 #endif /* not FOR_DOXYGEN */