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