(mtext__adjust_foramt): Extern it.
[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     @page 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
54 #ifndef FOR_DOXYGEN
55
56 #include <stdio.h>
57 #include <string.h>
58 #include <config.h>
59 #include <m17n-gui.h>
60
61 #ifdef HAVE_ISPELL
62
63 static int initialized = 0;
64 static MFace *mface_overstrike = NULL;
65
66 static MPlist *
67 add_action (MPlist *actions, MSymbol name, MSymbol key, void *val)
68 {
69   MPlist *action = mplist ();
70
71   mplist_add (action, Msymbol, name);
72   if (key != Mnil)
73     mplist_add (action, key, val);
74   mplist_add (actions, Mplist, action);
75   m17n_object_unref (action);
76   return actions;
77 }
78
79 MPlist *
80 init (MPlist *args)
81 {
82   if (! initialized++)
83     {
84       MFaceHLineProp hline;
85
86       hline.type = MFACE_HLINE_STRIKE_THROUGH;
87       hline.width = 1;
88       hline.color = msymbol ("black");
89       mface_overstrike = mface ();
90       mface_put_prop (mface_overstrike, Mhline, &hline);
91     }
92   return NULL;
93 }
94
95 MPlist *
96 fini (MPlist *args)
97 {
98   if (! --initialized)
99     m17n_object_unref (mface_overstrike);
100   return NULL;
101 }
102
103 MPlist *
104 ispell_word (MPlist *args)
105 {
106   MInputContext *ic;
107   unsigned char buf[256];
108   int nbytes;
109   MPlist *actions, *candidates, *plist;
110   char command[256];
111   char **words;
112   FILE *ispell;
113   char *p = (char *) buf;
114   int i, n;
115   MSymbol init_state;
116   MSymbol select_state;
117   MText *mt;
118
119   ic = mplist_value (args);
120   args = mplist_next (args);
121   init_state = (MSymbol) mplist_value (args);
122   args = mplist_next (args);
123   select_state = (MSymbol) mplist_value (args);
124   nbytes = mconv_encode_buffer (Mcoding_us_ascii, ic->preedit, buf, 256);
125
126   actions = mplist ();
127
128   if (nbytes < 3)
129     return add_action (actions, msymbol ("shift"), Msymbol, init_state);
130
131   buf[nbytes] = '\0';
132   sprintf (command, "echo %s | ispell -a -m", (char *) buf);
133   ispell = popen (command, "r");
134   if (! ispell)
135     return add_action (actions, msymbol ("shift"), Msymbol, init_state);
136
137   /* Skip the heading line.  */
138   fgets (p, 256, ispell);
139   /* Read just 256 bytes, thus candidates listed after the first 256
140      bytes are just ignored.  */
141   fgets (p, 256, ispell);
142   pclose (ispell);
143   p[strlen (p) - 1] = '\0';
144   if (*p != '&' && *p != '#')
145     return add_action (actions, msymbol ("shift"), Msymbol, init_state);
146
147   add_action (actions, msymbol ("delete"), Msymbol,  msymbol ("@<"));
148   if (*p == '#')
149     {
150       mt = mtext_dup (ic->preedit);
151       mtext_push_prop (mt, 0, mtext_len (mt), Mface, mface_overstrike);
152       mplist_add (actions, Mtext, mt);
153       add_action (actions, msymbol ("shift"), Msymbol, init_state);
154       m17n_object_unref (mt);
155       return actions;
156     }
157
158   p = strchr (p + 2, ' ');
159   if (sscanf (p, "%d", &n) != 1)
160     return add_action (actions, msymbol ("shift"), Msymbol, init_state);
161   words = alloca (sizeof (char *) * n);
162   p = strchr (p + 1, ' ');
163   p = strchr (p + 1, ' ');
164   for (i = 0; i < n - 1; i++)
165     {
166       words[i] = ++p;
167       p = strchr (p, ',');
168       if (! p)
169         {
170           n = i - 1;
171           break;
172         }
173       *p++ = '\0';
174     }
175   words[i] = ++p;
176   candidates = mplist ();
177   for (i = 0; i < n; i++)
178     {
179       mt = mconv_decode_buffer (Mcoding_us_ascii, (unsigned char *) words[i],
180                                 strlen (words[i]));
181       mplist_add (candidates, Mtext, mt);
182       m17n_object_unref (mt);
183     }
184   mt = mtext_dup (ic->preedit);
185   mtext_push_prop (mt, 0, mtext_len (mt), Mface, mface_overstrike);
186   mplist_add (candidates, Mtext, mt);
187   m17n_object_unref (mt);
188   plist = mplist_add (mplist (), Mplist, candidates);
189   m17n_object_unref (candidates);
190   mplist_add (actions, Mplist, plist);
191   m17n_object_unref (plist);
192   add_action (actions, msymbol ("show"), Mnil, NULL);
193   add_action (actions, msymbol ("shift"), Msymbol, select_state);
194   return actions;
195 }
196
197 #else  /* not HAVE_ISPELL */
198
199 MPlist *ispell_word (MPlist *args) { return NULL; }
200
201 #endif /* not HAVE_ISPELL */
202 #endif /* not FOR_DOXYGEN */