e494785be9dcd4efdf1e3bf21efa330f5b7cfa85
[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           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                                  this);
153           if (pos >= last && pos < from + wordcut_result.start[i])
154             prop = this;
155           M17N_OBJECT_UNREF (this);
156         }
157
158       this = mtext_property (Mthai_wordseg, Mt,
159                              MTEXTPROP_VOLATILE_WEAK | MTEXTPROP_NO_MERGE);
160       last = from + wordcut_result.start[i];
161       mtext_attach_property (mt, last, last + wordcut_result.offset[i], this);
162       if (pos >= last && pos < last + wordcut_result.offset[i])
163         prop = this;
164       m17n_object_unref (this);
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 static MTextProperty *
185 wordseg_propertize (MText *mt, int pos, int from, int to, unsigned char *tis)
186 {
187   return NULL;
188 }
189
190
191 #endif  /* not HAVE_WORDCUT nor HAVE_WORDCUT_OLD */
192
193 int
194 thai_wordseg (MText *mt, int pos, int *from, int *to)
195 {
196   /* TIS620 code sequence.  */
197   unsigned char *tis;
198   MTextProperty *prop;
199   int in_word;
200
201   if (pos >= mtext_nchars (mt))
202     {
203       *from = *to = pos;
204       return 0;
205     }
206
207   prop = mtext_get_property (mt, pos, Mthai_wordseg);
208
209   if (! prop)
210     {
211       int beg, end;
212       int c;
213
214       /* Extra 1-byte is for 0 terminating.  */
215       tis = alloca ((*to - *from) + 1);
216
217       for (beg = pos; beg > *from; beg--)
218         {
219           if ((c = mtext_ref_char (mt, beg - 1)) < THAI_BEG || c > THAI_END)
220             break;
221           tis[beg - 1 - *from] = 0xA1 + (c - THAI_BEG);
222         }
223       for (end = pos; end < *to; end++)
224         {
225           if ((c = mtext_ref_char (mt, end)) < THAI_BEG || c > THAI_END)
226             break;
227           tis[end - *from] = 0xA1 + (c - THAI_BEG);
228         }           
229           
230       if (pos == end)
231         {
232           *from = *to = pos;
233           return 0;
234         }
235
236       /* Make it terminate by 0.  */
237       tis[end - *from] = 0;
238       prop = wordseg_propertize (mt, pos, beg, end, tis + (beg - *from));
239     }
240
241   *from = MTEXTPROP_START (prop);
242   *to = MTEXTPROP_END (prop);
243   in_word = MTEXTPROP_VAL (prop) == Mt;
244   return in_word;
245 }
246
247 \f
248 /* Internal API */
249
250 int
251 mtext__word_thai_init ()
252 {
253   if (! wordseg_library_initialized)
254     {
255       if (init_wordseg_library () < 0)
256         return -1;
257       wordseg_library_initialized = 1;
258       Mthai_wordseg = msymbol (" wordcut-wordseg");
259     }
260   mchartable_set_range (wordseg_func_table, THAI_BEG, THAI_END,
261                         (void *) thai_wordseg);
262   return 0;
263 }
264
265 void
266 mtext__word_thai_fini ()
267 {
268   if (wordseg_library_initialized)
269     {
270       fini_wordseg_library ();
271       wordseg_library_initialized = 0;
272     }
273 }