Include <stdio.h>.
[m17n/m17n-lib.git] / src / word-thai.c
1 /* word-thai.c -- Find a word segment in Thai text.
2    Copyright (C) 2005
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 #include <stdio.h>
24
25 #include "config.h"
26 #include "m17n-core.h"
27 #include "m17n-misc.h"
28 #include "internal.h"
29 #include "textprop.h"
30 #include "character.h"
31 #include "mtext.h"
32
33 static int init_wordseg_library (void);
34 static void fini_wordseg_library (void);
35 static MTextProperty *wordseg_propertize (MText *mt, int pos, int from, int to,
36                                           unsigned char *tis);
37
38 #define THAI_BEG 0x0E01
39 #define THAI_END 0x0E6F
40
41 static int wordseg_library_initialized;
42 static MSymbol Mthai_wordseg;
43
44 #ifdef HAVE_WORDCUT
45
46 #include <wordcut/wcwordcut.h>
47
48 static WcWordcut wordcut;
49 static WcWordVector *word_vector;
50
51 static int
52 init_wordseg_library (void)
53 {  
54   wc_wordcut_init (&wordcut);
55   return 0;
56 }
57
58 static void
59 fini_wordseg_library (void)
60 {
61   if (word_vector)
62     wc_word_vector_delete (word_vector);
63   wc_wordcut_destroy (&wordcut);
64   return;
65 }
66
67 static MTextProperty *
68 wordseg_propertize (MText *mt, int pos, int from, int to, unsigned char *tis)
69 {
70   gulong i, count;
71   MTextProperty *prop = NULL;
72
73   if (! word_vector)
74     word_vector = wc_word_vector_new ();
75   else
76     {
77       wc_word_vector_destroy (word_vector);
78       wc_word_vector_init (word_vector);
79     }
80
81   wc_wordcut_cut (&wordcut, (gchar *) tis, (gint) (to - from),
82                   word_vector);
83   count = wc_word_vector_get_count (word_vector);
84   for (i = 0; i < count; i++)
85     {
86       WcWord *word = wc_word_vector_get_word (word_vector, i);
87
88       if (word->type != WC_WORDTYPE_DELETED)
89         {
90           MSymbol val = ((word->type == WC_WORDTYPE_DICTIONARY
91                           || word->type == WC_WORDTYPE_WORDUNIT
92                           || word->type == WC_WORDTYPE_JOINED)
93                          ? Mt : Mnil);
94           MTextProperty *this
95             = mtext_property (Mthai_wordseg, val,
96                               MTEXTPROP_VOLATILE_WEAK | MTEXTPROP_NO_MERGE);
97
98           mtext_attach_property (mt, from, from + word->len, this);
99           if (pos >= from && pos < from + word->len)
100             prop = this;
101           else
102             M17N_OBJECT_UNREF (this);
103           from += word->len;
104         }
105     }
106   return prop;
107 }
108
109 #elif HAVE_WORDCUT_OLD
110
111 #include <wordcut/wordcut.h>
112
113 static Wordcut wordcut;
114 static WordcutResult wordcut_result;
115 static int wordcut_result_used;
116
117 static int
118 init_wordseg_library (void)
119 {  
120   return (wordcut_init (&wordcut, WORDCUT_TDICT) == 0 ? 0 : -1);
121 }
122
123 static void
124 fini_wordseg_library (void)
125 {
126   if (wordcut_result_used)
127     {
128       wordcut_result_close (&wordcut_result);
129       wordcut_result_used = 0;
130     }
131   wordcut_close (&wordcut);
132   return;
133 }
134
135 static MTextProperty *
136 wordseg_propertize (MText *mt, int pos, int from, int to, unsigned char *tis)
137 {
138   int i, last;
139   MTextProperty *prop = NULL;
140
141   wordcut_cut (&wordcut, (char *) tis, &wordcut_result);
142   wordcut_result_used = 1;
143   for (i = 0, last = from; i < wordcut_result.count; i++)
144     {
145       MTextProperty *this;
146
147       if (last < from + wordcut_result.start[i])
148         {
149           this = mtext_property (Mthai_wordseg, Mnil,
150                                  MTEXTPROP_VOLATILE_WEAK | MTEXTPROP_NO_MERGE);
151           mtext_attach_property (mt, last, from + wordcut_result.start[i],
152                                  prop);
153           if (pos >= last && pos < from + wordcut_result.start[i])
154             prop = this;
155           else
156             M17N_OBJECT_UNREF (this);
157         }
158
159       last = from + wordcut_result.start[i];
160       mtext_attach_property (mt, last, last + wordcut_result.offset[i], prop);
161       if (pos >= last && pos < last + wordcut_result.offset[i])
162         prop = this;
163       else
164         m17n_object_unref (prop);
165       last += wordcut_result.offset[i];
166     }
167   return prop;
168 }
169
170 #else  /* not HAVE_WORDCUT nor HAVE_WORDCUT_OLD */
171
172 int
173 init_wordseg_library (void)
174 {  
175   return -1;
176 }
177
178 void
179 fini_wordseg_library (void)
180 {
181   return;
182 }
183
184 #endif  /* not HAVE_WORDCUT nor HAVE_WORDCUT_OLD */
185
186 int
187 thai_wordseg (MText *mt, int pos, int *from, int *to)
188 {
189   /* TIS620 code sequence.  */
190   unsigned char *tis;
191   MTextProperty *prop;
192   int in_word;
193
194   if (pos >= mtext_nchars (mt))
195     {
196       *from = *to = pos;
197       return 0;
198     }
199
200   prop = mtext_get_property (mt, pos, Mthai_wordseg);
201
202   if (! prop)
203     {
204       int beg, end;
205       int c;
206
207       /* Extra 1-byte is for 0 terminating.  */
208       tis = alloca ((*to - *from) + 1);
209
210       for (beg = pos; beg > *from; beg--)
211         {
212           if ((c = mtext_ref_char (mt, beg - 1)) < THAI_BEG || c > THAI_END)
213             break;
214           tis[beg - 1 - *from] = 0xA1 + (c - THAI_BEG);
215         }
216       for (end = pos; end < *to; end++)
217         {
218           if ((c = mtext_ref_char (mt, end)) < THAI_BEG || c > THAI_END)
219             break;
220           tis[end - *from] = 0xA1 + (c - THAI_BEG);
221         }           
222           
223       if (pos == end)
224         {
225           *from = *to = pos;
226           return 0;
227         }
228
229       /* Make it terminate by 0.  */
230       tis[end - *from] = 0;
231       prop = wordseg_propertize (mt, pos, beg, end, tis + (beg - *from));
232     }
233
234   *from = MTEXTPROP_START (prop);
235   *to = MTEXTPROP_END (prop);
236   in_word = MTEXTPROP_VAL (prop) == Mt;
237   M17N_OBJECT_UNREF (prop);
238   return in_word;
239 }
240
241 \f
242 /* Internal API */
243
244 int
245 mtext__word_thai_init ()
246 {
247   if (! wordseg_library_initialized)
248     {
249       if (init_wordseg_library () < 0)
250         return -1;
251       wordseg_library_initialized = 1;
252       Mthai_wordseg = msymbol (" wordcut-wordseg");
253     }
254   mchartable_set_range (wordseg_func_table, THAI_BEG, THAI_END,
255                         (void *) thai_wordseg);
256   return 0;
257 }
258
259 void
260 mtext__word_thai_fini ()
261 {
262   if (wordseg_library_initialized)
263     {
264       fini_wordseg_library ();
265       wordseg_library_initialized = 0;
266     }
267 }