1 /***************************************************************************
2 * Copyright (C) 2004 by TAM(Teppei Tamra) *
3 * tam-t@par.odn.ne.jp *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20 #include "wnnconversion.h"
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #ifdef HAVE_GETTEXT
27 #include <libintl.h>
28 #define _(String) dgettext(GETTEXT_PACKAGE,String)
29 #define N_(String) (String)
30 #else
31 #define _(String) (String)
32 #define N_(String) (String)
33 #define bindtextdomain(Package,Directory)
34 #define textdomain(domain)
35 #define bind_textdomain_codeset(domain,codeset)
36 #endif
37
38 // プライグイン化のおまじないです。
39 //HonokaPluginRegister(WnnConversion);
40
WnnConversion(ConfigPointer cfg)41 WnnConversion::WnnConversion(ConfigPointer cfg) : Convertor(cfg)
42 {
43 // とりあえず決めうちでいきます。
44 m_iconv.set_encoding ("EUC-JP");
45 pos = 0;
46 bunsetu = 0;
47 wnn = 0;
48 sType = Wnn4;
49 }
50
51
~WnnConversion()52 WnnConversion::~WnnConversion()
53 {
54 wnnDisconnect();
55 }
56
57
58 /* w_charからEUCに変換するアレ */
wstostr(unsigned char * e,w_char * u)59 void WnnConversion::wstostr(unsigned char *e,w_char *u) {
60 w_char x;
61 for(;*u;) {
62 x = *u ++;
63 if (x & 0x8000) {
64 *e ++ = x >> 8;
65 *e ++ = x;
66 } else
67 if (x & 0x80) {
68 *e ++ = 0x8e;
69 *e ++ = x & 0xff;
70 } else
71 *e++ = x;
72 }
73 *e ++ = 0;
74 }
75
76 /* EUCからw_charに変換するナニ */
strtows(w_char * u,unsigned char * e)77 void WnnConversion::strtows(w_char *u,unsigned char *e) {
78 w_char x;
79 for(;*e;) {
80 x = *e ++;
81 // これいらない↓
82 //if (x == 0x8e) x = 0x80 | *e ++;
83 if (x & 0x80)
84 x = ((x << 8) & 0xff00) | *e ++;
85 *u ++ = x;
86 }
87 *u = 0;
88 }
89
90 /*!
91 \fn WnnConversion::connect()
92 */
connect()93 bool WnnConversion::connect()
94 {
95 String host = config->read(String(HONOKA_CONFIG_JSERVER),String(HONOKA_DEFAULT_JSERVER));
96 String rc = config->read(String(HONOKA_CONFIG_WNNENVRC),String(HONOKA_DEFAULT_WNNENVRC));
97 String t = config->read(String(HONOKA_CONFIG_JSERVERTYPE),String(HONOKA_DEFAULT_JSERVERTYPE));
98
99 if (t == "Wnn6") {
100 sType = Wnn6;
101 } else if (t == "Wnn7") {
102 sType = Wnn7;
103 } else if (t == "Wnn8") {
104 sType = Wnn8;
105 } else {
106 sType = Wnn4;
107 }
108
109 return wnnConnect(String("scim-wnn"),host,rc,sType,0);
110 }
111
112 /*!
113 \fn WnnConversion::disconnect()
114 */
disconnect()115 void WnnConversion::disconnect()
116 {
117 wnnDisconnect();
118 }
119
120
121 /*!
122 \fn WnnConversion::wnnConnect(String name,String host,String rc,JServerType type,int timeout)
123 */
wnnConnect(String name,String host,String rc,JServerType type,int timeout)124 bool WnnConversion::wnnConnect(String name,String host,String rc,JServerType type,int timeout)
125 {
126 wnn = jl_open((char *)name.c_str(),(char *)host.c_str(),(char *)rc.c_str(),wnn_error,wnn_message,timeout);
127 //wnn = jl_open_lang("test","localhost","jp_JP","/usr/lib/wnn7/ja_JP/wnnenvrc",wnn_error,wnn_message,10);
128 if (wnn == NULL) return false;
129 #ifdef HAVE_LIBWNN7
130 // 予測入力を初期化しておく。
131 jl_yosoku_init(wnn);
132 #endif
133 sType = type;
134 return true;
135 }
136
137 /*!
138 \fn WnnConversion::wnnDisconnect()
139 */
wnnDisconnect()140 void WnnConversion::wnnDisconnect()
141 {
142 if (wnn != NULL) {
143 jl_dic_save_all(wnn);
144 #ifdef HAVE_LIBWNN7
145 jl_yosoku_free(wnn);
146 #endif
147 jl_close(wnn);
148 wnn = NULL;
149 }
150 }
151
152
153
154
155 /*!
156 \fn WnnConversion::isConnected()
157 */
isConnected()158 bool WnnConversion::isConnected()
159 {
160 if (wnn) return true;
161 else return false;
162 }
163
164
165
166
167 /*!
168 \fn WnnConversion::wnn_message (char *s)
169 */
wnn_message(char * s)170 int WnnConversion::wnn_message (char *s)
171 {
172
173 SCIM_DEBUG_IMENGINE(1) << s << "\n";
174 }
175
176 /*!
177 \fn WnnConversion::wnn_error (char *s)
178 */
wnn_error(char * s)179 int WnnConversion::wnn_error (char *s)
180 {
181
182 SCIM_DEBUG_IMENGINE(1) << s << "\n";
183 }
184
185
186
187
188 /*!
189 \fn WnnConversion::reset()
190 */
reset()191 void WnnConversion::reset()
192 {
193 yomiText.clear();
194 bunList.clear();
195 yomiList.clear();
196 text.clear();
197 attr.clear();
198 pos = 0;
199 jl_kill(wnn,0,-1);
200 }
201
202
203 /*!
204 \fn WnnConversion::setYomiText(WideString yomi)
205 */
setYomiText(WideString yomi)206 void WnnConversion::setYomiText(WideString yomi)
207 {
208 yomiText = yomi;
209 }
210
211
212
213 /*!
214 \fn WnnConversion::ren_conversion()
215 */
ren_conversion()216 int WnnConversion::ren_conversion()
217 {
218 if ((yomiText.length() > 500) || (!yomiText.length())) return -1;
219 convList.Yomi.clear();
220 convList.kouho.clear();
221 bunList.clear();
222 yomiList.clear();
223 pos = 0;
224 w_char ws[1024];
225 char c[2048];
226 String y;
227 m_iconv.convert(y,yomiText);
228 strtows(ws,(unsigned char*)y.c_str());
229 bunsetu = jl_fi_ren_conv(wnn,ws,0,-1,WNN_USE_ZENGO);
230 if (bunsetu == -1) return -1;
231 for(unsigned int i = 0;i < bunsetu;i ++) {
232 WideString w;
233 jl_get_kanji(wnn,i,i + 1,ws);
234 wstostr((unsigned char*)c,ws);
235 m_iconv.convert(w,c,strlen(c));
236 bunList.push_back(w);
237 jl_get_yomi(wnn,i,i + 1,ws);
238 wstostr((unsigned char*)c,ws);
239 m_iconv.convert(w,c,strlen(c));
240 yomiList.push_back(w);
241 }
242 createText();
243 return bunsetu;
244 }
245
246
247 /*!
248 \fn WnnConversion::resizeRegion(int w)
249 */
resizeRegion(int w)250 bool WnnConversion::resizeRegion(int w)
251 {
252 if (w == 0) return false;
253 if ((yomiList[pos].length() + w) <= 0) return false;
254 if (((pos + 1) >= yomiList.size()) && (w > 0)) return false;
255
256 w_char ws[1024];
257 char c[2048];
258 int s;
259 int h = WNN_NO_USE;
260 if (pos > 0) h = WNN_USE_MAE;
261 else if (pos < bunsetu - 1) h = WNN_USE_ATO;
262 bunsetu = jl_fi_nobi_conv(wnn,pos,yomiList[pos].length() + w,-1,h,WNN_SHO);
263 convList.kouho.clear();
264 bunList.clear();
265 yomiList.clear();
266 for(unsigned int i = 0;i < bunsetu;i ++) {
267 WideString w;
268 jl_get_kanji(wnn,i,i + 1,ws);
269 wstostr((unsigned char*)c,ws);
270 m_iconv.convert(w,c,strlen(c));
271 bunList.push_back(w);
272 jl_get_yomi(wnn,i,i + 1,ws);
273 wstostr((unsigned char*)c,ws);
274 m_iconv.convert(w,c,strlen(c));
275 yomiList.push_back(w);
276 }
277 createText();
278 return true;
279 }
280
281
282 /*!
283 \fn WnnConversion::createText()
284 */
createText()285 void WnnConversion::createText()
286 {
287 WideString w;
288 caretPos = 0;
289 for(unsigned int i = 0;i < bunsetu;i ++) {
290 if (pos == i) {
291 caretPos = w.length();
292 attr.clear();
293 Attribute a(w.length(),bunList[i].length(),SCIM_ATTR_DECORATE,SCIM_ATTR_DECORATE_REVERSE);
294 attr.push_back(a);
295 }
296 w = w + bunList[i];
297 }
298 text = w;
299 }
300
301
302 /*!
303 \fn WnnConversion::getSegmentList()
304 */
getSegmentList()305 const vector<Segment> WnnConversion::getSegmentList()
306 {
307 // getTextにかわるもの。
308 vector<Segment> result;
309 for(unsigned int i = 0;i < bunsetu;i ++) result.push_back(Segment(bunList[i],yomiList[i]));
310 return result;
311 }
312
313
314 /*!
315 \fn WnnConversion::setPos(int p)
316 */
setPos(int p)317 int WnnConversion::setPos(int p)
318 {
319 /*if (p >= bunsetu) p = (p % bunsetu);
320 else if (p < 0) p = bunsetu - (abs(p) % bunsetu);*/
321 if ((p < bunsetu) && (p >= 0)) pos = p;
322
323 //pos = p;
324 createText();
325 return pos;
326 }
327
328
329 /*!
330 \fn WnnConversion::getPos()
331 */
getPos()332 int WnnConversion::getPos()
333 {
334 return pos;
335 }
336
337
338 /*!
339 \fn WnnConversion::getYosokuList(const WideString &str)
340 */
getYosokuList(const WideString & str)341 ResultList WnnConversion::getYosokuList(const WideString &str)
342 {
343 convList.Yomi = str;
344 convList.kouho.clear();
345 //convList.count = 0;
346 convList.pos = 0;
347 convList.kType = PREDICTION;
348 convList.Title = utf8_mbstowcs(String(_("yosoku lookup result")));
349 #ifdef HAVE_LIBWNN7
350 String s;
351 m_iconv.convert(s,convList.Yomi);
352 // @todo ここもmbstowcsしたほうが良いんか?
353 char c[1024];
354 strcpy(c,s.c_str());
355 if (jl_yosoku_yosoku(wnn,c) != 0) return convList;
356 //convList.count = ykYosokuKouhoNum;
357 for(unsigned int i = 0;i < ykYosokuKouhoNum;i ++) {
358 WideString w;
359 m_iconv.convert(w,ykYosokuKouho[i],strlen(ykYosokuKouho[i]));
360 convList.kouho.push_back(ResultEntry(w));
361 }
362 //jl_yosoku_free(wnn);
363 #endif
364 return convList;
365 }
366
367
368 /*!
369 \fn WnnConversion::getResultList(int p,ResultType kt)
370 */
getResultList(int p,ResultType kt)371 ResultList WnnConversion::getResultList(int p,ResultType kt)
372 {
373 w_char k[1024];
374 char buf[2048];
375 WideString u;
376 convList.kouho.clear();
377 convList.Yomi.clear();
378 convList.pos = 0;
379 //convList.count = 0;
380 if ((sType != Wnn8) && (sType != Wnn7) && (kt != DEFAULT)) return convList;
381
382 if (p == -1) p = pos;
383 //if ((p >= bunsetu) || (p < 0)) p = p % bunsetu;
384 if (p >= bunsetu) return convList;
385 pos = p;
386 jl_get_yomi(wnn,pos,pos + 1,k);
387 wstostr((unsigned char*)buf,k);
388 m_iconv.convert(u,buf,strlen(buf));
389 convList.Yomi = u;
390
391 // bunsetu connection control
392 int conn = WNN_USE_ZENGO;
393 if (bunsetu == 1) conn = WNN_NO_USE;
394 else if (pos == 0) conn = WNN_USE_ATO;
395 else if (pos == (bunsetu - 1)) conn = WNN_USE_MAE;
396 switch (kt) {
397 #ifdef HAVE_LIBWNN7
398 case SPECIAL2: {
399 convList.pos = jl_zenikeiji_dai(wnn,pos,pos + 1,conn,WNN_UNIQ);
400 convList.kType = SPECIAL2;
401 convList.Title = utf8_mbstowcs(String(_("Ikeiji lookup result")));
402 break;
403 }
404 case SPECIAL1: {
405 convList.pos = jl_zenassoc_dai(wnn,pos,pos + 1,conn,WNN_UNIQ);
406 convList.kType = SPECIAL1;
407 convList.Title = utf8_mbstowcs(String(_("association lookup result")));
408 break;
409 }
410 #endif
411 default: {
412 convList.pos = jl_zenkouho_dai(wnn,pos,pos + 1,conn,WNN_UNIQ);
413 convList.kType = DEFAULT;
414 convList.Title = utf8_mbstowcs(String(_("lookup result")));
415 break;
416 }
417 }
418
419 // @todo be implement to ikeiji conversion using "jl_zenikeiji_dai()".
420 // @todo be implement to rensou conversion using "jl_zenassoc_dai()".
421 // @todo jl_zenkouho should change to jl_zenkouho_dai.
422 //convList.pos = jl_zenassoc_dai(wnn,pos,pos + 1,WNN_USE_ZENGO,WNN_UNIQ);
423 //convList.pos = jl_zenkouho(wnn,pos,conn,WNN_UNIQ);
424 if (convList.pos == -1) return convList;
425 int count = jl_zenkouho_suu(wnn);
426
427 for (unsigned int i = 0;i < count; i ++) {
428 jl_get_zenkouho_kanji(wnn,i,k);
429 wstostr((unsigned char*)buf,k);
430 m_iconv.convert(u,buf,strlen(buf));
431 convList.kouho.push_back(u);
432 }
433 select(convList.pos);
434 createText();
435 return convList;
436
437 }
438
439
440 /*!
441 \fn WnnConversion::select(int p)
442 */
select(int p)443 bool WnnConversion::select(int p)
444 {
445 if (p > convList.count()) p = 0;
446 convList.pos = p;
447 switch(convList.kType) {
448 case DEFAULT: {
449 jl_set_jikouho_dai(wnn,p);
450 break;
451 }
452 case PREDICTION: {
453 #ifdef HAVE_LIBWNN7
454 jl_yosoku_selected_cand(wnn,p);
455 #endif
456 return true;
457 }
458 default: {
459 break;
460 }
461 }
462
463 bunList.at(pos) = convList.kouho.at(p).kanji;
464 createText();
465
466 return true;
467
468 }
469
470
471
472
473
474
475 /*!
476 \fn WnnConversion::updateFrequency()
477 */
updateFrequency()478 void WnnConversion::updateFrequency()
479 {
480 if (bunsetu) {
481 #ifdef HAVE_LIBWNN7
482 w_char ws[1024];
483 int c = jl_get_kanji(wnn,0,bunsetu,ws);
484 jl_yosoku_toroku(wnn,ws,c);
485 #endif
486 jl_optimize_fi(wnn,0,-1);
487 pretext = text;
488 }
489 }
490
491
492
493
getName()494 String WnnConversion::getName()
495 {
496 return String("Wnn");
497 }
498
getPropertyName()499 String WnnConversion::getPropertyName()
500 {
501 return String(_("WnnConversion"));
502 }
503
504
505
506 /*!
507 \fn WnnConversion::updateYosoku(WideString text,const WideString yomi)
508 */
updateYosoku(WideString text,const WideString yomi)509 void WnnConversion::updateYosoku(WideString text,const WideString yomi)
510 {
511 #ifdef HAVE_LIBWNN7
512 if (text == pretext) return;
513 reset();
514 setYomiText(yomi);
515 ren_conversion();
516 w_char ws[1024];
517 char c[2048];
518 String y;
519 m_iconv.convert(y,text);
520 strtows(ws,(unsigned char*)y.c_str());
521 jl_yosoku_toroku(wnn,ws,text.length());
522 reset();
523 #endif
524 return;
525
526 }
527