1 /*
2 * Copyright (C) 2020 The HIME team, Taiwan
3 * Copyright (C) 2011-2012 cwlin <https://github.com/cwlin>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library 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 GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 #include "chewing.h"
21
22 // hime-chewing funcs
23 static gboolean select_idx (int c);
24 static void prev_page (void);
25 static void next_page (void);
26 static gboolean chewing_initialize (void);
27 static gboolean is_empty (void);
28 static gboolean hime_label_show (char *pszPho, int nPos);
29 static gboolean hime_label_clear (int nCount);
30 static gboolean hime_label_cand_show (char *pszWord, int nCount);
31 static gboolean gtk_pango_font_pixel_size_get (int *pnFontWidth, int *pnFontHeight);
32
33 static gboolean hime_key_filter (int *pnKeyVal);
34 static gboolean hime_zuin_label_show (void);
35 static gboolean hime_buffer_label_show (void);
36 static gboolean hime_buffer_commit (void);
37
38 static void hime_chewing_cb_register (void);
39 static void hime_chewing_handler_default (ChewingContext *pCtx);
40
41 static int hime_chewing_wrapper_bs (ChewingContext *pCtx);
42 static int hime_chewing_wrapper_enter (ChewingContext *pCtx);
43 static int hime_chewing_wrapper_home (ChewingContext *pCtx);
44 static int hime_chewing_wrapper_left (ChewingContext *pCtx);
45 static int hime_chewing_wrapper_up (ChewingContext *pCtx);
46 static int hime_chewing_wrapper_right (ChewingContext *pCtx);
47 static int hime_chewing_wrapper_down (ChewingContext *pCtx);
48 static int hime_chewing_wrapper_pageup (ChewingContext *pCtx);
49 static int hime_chewing_wrapper_pagedown (ChewingContext *pCtx);
50 static int hime_chewing_wrapper_end (ChewingContext *pCtx);
51 static int hime_chewing_wrapper_del (ChewingContext *pCtx);
52
53 static HIME_module_main_functions g_himeModMainFuncs;
54 static GtkWidget *g_pWinChewing = NULL;
55 static ChewingContext *g_pChewingCtx = NULL;
56 static GtkWidget *g_pEvBoxChewing = NULL;
57 static GtkWidget *g_pHBoxChewing = NULL;
58 static SEG *g_pSeg = NULL;
59 static int g_nCurrentCursorPos = 0;
60
61 static intptr_t (*g_pKeyHandler[HIME_CHEWING_KEY_MAX]) (ChewingContext *pCtx);
62
63 // FIXME: impl
64 static gboolean
select_idx(int c)65 select_idx (int c) {
66 return TRUE;
67 }
68
69 // FIXME: impl
70 static void
prev_page(void)71 prev_page (void) {
72 }
73
74 // FIXME: impl
75 static void
next_page(void)76 next_page (void) {
77 }
78
79 static gboolean
hime_label_show(char * pszPho,int nPos)80 hime_label_show (char *pszPho, int nPos) {
81 char szTmp[128];
82
83 if (!pszPho)
84 return FALSE;
85
86 memset (szTmp, 0x00, 128);
87
88 if (*g_himeModMainFuncs.mf_hime_win_color_use)
89 snprintf (szTmp, sizeof (szTmp), "<span background=\"%s\" foreground=\"white\">%s</span>",
90 *g_himeModMainFuncs.mf_tsin_cursor_color,
91 pszPho);
92 else
93 snprintf (szTmp, sizeof (szTmp), "<span background=\"" TSIN_CURSOR_COLOR_DEFAULT "\">%s</span>",
94 pszPho);
95
96 gtk_label_set_markup (GTK_LABEL (g_pSeg[nPos].label),
97 nPos != g_nCurrentCursorPos ? pszPho : szTmp);
98
99 return TRUE;
100 }
101
102 static gboolean
hime_label_clear(int nCount)103 hime_label_clear (int nCount) {
104 while (nCount--)
105 gtk_label_set_text (GTK_LABEL (g_pSeg[nCount].label), NULL);
106
107 return TRUE;
108 }
109
110 static gboolean
gtk_pango_font_pixel_size_get(int * pnFontWidth,int * pnFontHeight)111 gtk_pango_font_pixel_size_get (int *pnFontWidth, int *pnFontHeight) {
112 PangoLayout *pPangoLayout;
113 PangoContext *pPangoContext;
114 PangoFontDescription *pPangoFontDesc;
115
116 pPangoLayout = gtk_widget_create_pango_layout (g_pWinChewing, "中");
117 //pPangoLayout = gtk_widget_create_pango_layout (
118 // g_pWinChewing,
119 // (char *)gtk_label_get_text (GTK_LABEL (g_pSeg[g_nCurrentCursorPos].label)));
120 pPangoContext = gtk_widget_get_pango_context (g_pWinChewing);
121 pPangoFontDesc = pango_context_get_font_description (pPangoContext);
122
123 pango_layout_set_font_description (pPangoLayout, pPangoFontDesc);
124 pango_layout_get_pixel_size (pPangoLayout, pnFontWidth, pnFontHeight);
125
126 g_object_unref (pPangoLayout);
127 return TRUE;
128 }
129
130 // FIXME: the pos of g_pSeg[].label is not correct
131 static gboolean
hime_label_cand_show(char * pszWord,int nIdx)132 hime_label_cand_show (char *pszWord, int nIdx) {
133 int nX, nY;
134 int nFontWidth, nFontHeight;
135
136 g_himeModMainFuncs.mf_set_sele_text (chewing_cand_TotalChoice (g_pChewingCtx),
137 nIdx,
138 pszWord,
139 -1);
140
141 // find the position of the cand win
142 g_himeModMainFuncs.mf_get_widget_xy (g_pWinChewing,
143 g_pSeg[g_nCurrentCursorPos].label,
144 &nX, &nY);
145
146 gtk_pango_font_pixel_size_get (&nFontWidth, &nFontHeight);
147 nX += g_nCurrentCursorPos * nFontWidth;
148
149 nY = g_himeModMainFuncs.mf_hime_edit_display_ap_only () ? *g_himeModMainFuncs.mf_win_y : *g_himeModMainFuncs.mf_win_y + *g_himeModMainFuncs.mf_win_yl;
150
151 g_himeModMainFuncs.mf_disp_selections (nX, nY);
152
153 return TRUE;
154 }
155
156 static gboolean
chewing_initialize(void)157 chewing_initialize (void) {
158 char *pszChewingHashDir;
159 char *pszHome;
160 gboolean bWriteMode = FALSE;
161 ChewingConfigData dummyConfig;
162
163 pszHome = getenv ("HOME");
164 if (!pszHome)
165 pszHome = "";
166
167 pszChewingHashDir = malloc (strlen (pszHome) + strlen ("/.chewing/") + 1);
168 memset (pszChewingHashDir, 0x00, strlen (pszHome) + strlen ("/.chewing/") + 1);
169 sprintf (pszChewingHashDir, "%s/.chewing", pszHome);
170
171 free (pszChewingHashDir);
172 pszHome = NULL;
173
174 g_pChewingCtx = chewing_new ();
175 if (!g_pChewingCtx)
176 return FALSE;
177
178 memset (&dummyConfig, 0x00, sizeof (ChewingConfigData));
179
180 chewing_config_open (bWriteMode);
181
182 chewing_config_load (&dummyConfig);
183
184 chewing_config_set (g_pChewingCtx);
185
186 chewing_config_close ();
187
188 hime_chewing_cb_register ();
189
190 return TRUE;
191 }
192
193 static gboolean
is_empty(void)194 is_empty (void) {
195 if (!g_pChewingCtx)
196 return FALSE;
197 return !chewing_buffer_Check (g_pChewingCtx) && !chewing_bopomofo_Check (g_pChewingCtx);
198 }
199
200 static gboolean
hime_key_filter(int * pnKeyVal)201 hime_key_filter (int *pnKeyVal) {
202 if ((*pnKeyVal) > HIME_CHEWING_DEFAULT_KEY_MIN &&
203 (*pnKeyVal) < HIME_CHEWING_DEFAULT_KEY_MAX)
204 chewing_handle_Default (g_pChewingCtx, (*pnKeyVal));
205 else if ((*pnKeyVal) >= XK_KP_0 && (*pnKeyVal) <= XK_KP_9)
206 chewing_handle_Numlock (g_pChewingCtx, (*pnKeyVal) - XK_KP_0 + '0');
207 else if ((*pnKeyVal) < HIME_CHEWING_KEY_MAX &&
208 (*pnKeyVal) >= HIME_CHEWING_KEY_MIN)
209 if ((int) (g_pKeyHandler[(*pnKeyVal)](g_pChewingCtx)) == -1)
210 return FALSE;
211
212 g_nCurrentCursorPos = chewing_cursor_Current (g_pChewingCtx);
213
214 if (g_nCurrentCursorPos < 0 || g_nCurrentCursorPos > MAX_SEG_NUM)
215 return FALSE;
216
217 return TRUE;
218 }
219
220 static gboolean
hime_zuin_label_show(void)221 hime_zuin_label_show (void) {
222 const char *pszTmp = NULL;
223 char *pszWord = NULL;
224 int nZuinLen = 0, nIdx = 0, nPhoIdx = 0;
225
226 pszTmp = chewing_bopomofo_String_static (g_pChewingCtx);
227 nZuinLen = strlen (pszTmp) / 3;
228 pszWord = (char *) realloc (pszWord, 4);
229
230 if (!pszWord)
231 return FALSE;
232
233 memset (pszWord, 0x00, 4);
234
235 if (pszTmp) {
236 for (nIdx = 0; nIdx < nZuinLen; nIdx++) {
237 memcpy (pszWord, pszTmp + nIdx * 3, 3);
238 for (nPhoIdx = 0; nPhoIdx < 3; nPhoIdx++)
239 if (strstr (g_himeModMainFuncs.mf_pho_chars[nPhoIdx], pszWord) != NULL)
240 hime_label_show (pszWord, nPhoIdx + chewing_buffer_Len (g_pChewingCtx) + 1);
241 }
242 }
243
244 free (pszWord);
245
246 return TRUE;
247 }
248
249 static gboolean
hime_buffer_label_show(void)250 hime_buffer_label_show (void) {
251 char *pszTmp = NULL;
252 char *pszWord = NULL;
253 char *pszChewingCand = NULL;
254 char *pHead = NULL;
255 int nIdx = 0;
256 int nPos = 0;
257 int nWordSize = 0;
258
259 pszWord = (char *) realloc (pszWord, 8);
260
261 if (!pszWord)
262 return FALSE;
263
264 memset (pszWord, 0x00, 8);
265
266 // check if the composing is valid or not
267 if (chewing_buffer_Check (g_pChewingCtx)) {
268 g_himeModMainFuncs.mf_hide_selections_win ();
269 pszTmp = chewing_buffer_String (g_pChewingCtx);
270
271 // init cand_no
272 chewing_cand_Enumerate (g_pChewingCtx);
273
274 g_himeModMainFuncs.mf_clear_sele ();
275
276 if (chewing_cand_TotalChoice (g_pChewingCtx)) {
277 while (chewing_cand_hasNext (g_pChewingCtx)) {
278 pszChewingCand = chewing_cand_String (g_pChewingCtx);
279
280 if (nIdx > chewing_get_candPerPage (g_pChewingCtx) - 1)
281 break;
282 hime_label_cand_show (pszChewingCand, nIdx++);
283 free (pszChewingCand);
284 }
285 }
286
287 for (nPos = 0, pHead = pszTmp, nIdx = 0; nPos < strlen (pszTmp); nPos += nWordSize, pHead += nWordSize) {
288 if (!((*pHead) & 0x80)) // 1 byte utf-8 data
289 nWordSize = 1;
290 else if (((*pHead) & 0xf0) == 0xc0) // 2 bytes utf-8 data
291 nWordSize = 2;
292 else if (((*pHead) & 0xf0) == 0xe0) // 3 bytes utf-8 data
293 nWordSize = 3;
294 else if (((*pHead) & 0xf0) == 0xf0) // 4 bytes utf-8 data
295 nWordSize = 4;
296
297 memset (pszWord, 0x00, 8);
298 memcpy (pszWord, pHead, nWordSize);
299 hime_label_show (pszWord, nIdx++);
300 }
301
302 // if chewing_buffer_Check is not zero,
303 // it means that the chewing_buffer_String must have val,
304 // so we could free the ptr here
305 free (pszTmp);
306 }
307
308 free (pszWord);
309
310 return TRUE;
311 }
312
313 static gboolean
hime_buffer_commit(void)314 hime_buffer_commit (void) {
315 char *pszTmp = NULL;
316
317 if (chewing_commit_Check (g_pChewingCtx)) {
318 pszTmp = chewing_commit_String (g_pChewingCtx);
319 g_himeModMainFuncs.mf_send_text (pszTmp);
320
321 // FIXME: workaround for repeated commit
322 chewing_handle_Esc (g_pChewingCtx);
323
324 // if chewing_commit_Check is not zero,
325 // it means that the chewing_commit_String must have val,
326 // so we could free the ptr here
327 free (pszTmp);
328 }
329
330 if (*g_himeModMainFuncs.mf_hime_pop_up_win && is_empty ())
331 module_hide_win ();
332
333 return TRUE;
334 }
335
336 static void
hime_chewing_handler_default(ChewingContext * pCtx)337 hime_chewing_handler_default (ChewingContext *pCtx) {
338 return ((void) NULL);
339 }
340
341 static int
hime_chewing_wrapper_bs(ChewingContext * pCtx)342 hime_chewing_wrapper_bs (ChewingContext *pCtx) {
343 // If zuin is present, force libchewing handles Backspace for removing last zuin
344 const char *pszWord = chewing_bopomofo_String_static (pCtx);
345 if (pszWord[0] != '\0')
346 return chewing_handle_Backspace (g_pChewingCtx);
347 HIME_CHEWING_WRAPPER_FUNC (chewing_handle_Backspace);
348 }
349
350 static int
hime_chewing_wrapper_enter(ChewingContext * pCtx)351 hime_chewing_wrapper_enter (ChewingContext *pCtx) {
352 HIME_CHEWING_WRAPPER_FUNC (chewing_handle_Enter);
353 }
354
355 static int
hime_chewing_wrapper_home(ChewingContext * pCtx)356 hime_chewing_wrapper_home (ChewingContext *pCtx) {
357 HIME_CHEWING_WRAPPER_FUNC (chewing_handle_Home);
358 }
359
360 static int
hime_chewing_wrapper_left(ChewingContext * pCtx)361 hime_chewing_wrapper_left (ChewingContext *pCtx) {
362 HIME_CHEWING_WRAPPER_FUNC (chewing_handle_Left);
363 }
364
365 static int
hime_chewing_wrapper_up(ChewingContext * pCtx)366 hime_chewing_wrapper_up (ChewingContext *pCtx) {
367 HIME_CHEWING_WRAPPER_FUNC (chewing_handle_Up);
368 }
369
370 static int
hime_chewing_wrapper_right(ChewingContext * pCtx)371 hime_chewing_wrapper_right (ChewingContext *pCtx) {
372 HIME_CHEWING_WRAPPER_FUNC (chewing_handle_Right);
373 }
374
375 static int
hime_chewing_wrapper_down(ChewingContext * pCtx)376 hime_chewing_wrapper_down (ChewingContext *pCtx) {
377 HIME_CHEWING_WRAPPER_FUNC (chewing_handle_Down);
378 }
379
380 static int
hime_chewing_wrapper_pageup(ChewingContext * pCtx)381 hime_chewing_wrapper_pageup (ChewingContext *pCtx) {
382 HIME_CHEWING_WRAPPER_FUNC (chewing_handle_PageUp);
383 }
384
hime_chewing_wrapper_pagedown(ChewingContext * pCtx)385 static int hime_chewing_wrapper_pagedown (ChewingContext *pCtx) {
386 HIME_CHEWING_WRAPPER_FUNC (chewing_handle_PageDown);
387 }
388
389 static int
hime_chewing_wrapper_end(ChewingContext * pCtx)390 hime_chewing_wrapper_end (ChewingContext *pCtx) {
391 HIME_CHEWING_WRAPPER_FUNC (chewing_handle_End);
392 }
393
394 static int
hime_chewing_wrapper_del(ChewingContext * pCtx)395 hime_chewing_wrapper_del (ChewingContext *pCtx) {
396 HIME_CHEWING_WRAPPER_FUNC (chewing_handle_Del);
397 }
398
399 static void
hime_chewing_cb_register(void)400 hime_chewing_cb_register (void) {
401 int nIdx = HIME_CHEWING_KEY_MIN;
402
403 for (; nIdx < HIME_CHEWING_KEY_MAX; nIdx++)
404 g_pKeyHandler[nIdx] = (void *) hime_chewing_handler_default;
405
406 g_pKeyHandler[XK_space] = (void *) chewing_handle_Space;
407 g_pKeyHandler[XK_BackSpace] = (void *) hime_chewing_wrapper_bs;
408 g_pKeyHandler[XK_Tab] = (void *) chewing_handle_Tab;
409 g_pKeyHandler[XK_Return] = (void *) hime_chewing_wrapper_enter;
410 g_pKeyHandler[XK_Escape] = (void *) chewing_handle_Esc;
411 g_pKeyHandler[XK_Home] = (void *) hime_chewing_wrapper_home;
412 g_pKeyHandler[XK_Left] = (void *) hime_chewing_wrapper_left;
413 g_pKeyHandler[XK_Up] = (void *) hime_chewing_wrapper_up;
414 g_pKeyHandler[XK_Right] = (void *) hime_chewing_wrapper_right;
415 g_pKeyHandler[XK_Down] = (void *) hime_chewing_wrapper_down;
416 g_pKeyHandler[XK_Page_Up] = (void *) hime_chewing_wrapper_pageup;
417 g_pKeyHandler[XK_Page_Down] = (void *) hime_chewing_wrapper_pagedown;
418 g_pKeyHandler[XK_End] = (void *) hime_chewing_wrapper_end;
419 g_pKeyHandler[XK_KP_Enter] = (void *) hime_chewing_wrapper_enter;
420 g_pKeyHandler[XK_KP_Left] = (void *) hime_chewing_wrapper_left;
421 g_pKeyHandler[XK_KP_Up] = (void *) hime_chewing_wrapper_up;
422 g_pKeyHandler[XK_KP_Right] = (void *) hime_chewing_wrapper_right;
423 g_pKeyHandler[XK_KP_Down] = (void *) hime_chewing_wrapper_down;
424 g_pKeyHandler[XK_KP_Delete] = (void *) hime_chewing_wrapper_del;
425 #if 0
426 g_pKeyHandler[XK_Shift_L] = (void *)chewing_handle_ShiftLeft;
427 g_pKeyHandler[XK_Shift_R] = (void *)chewing_handle_ShiftRight;
428 #endif
429 g_pKeyHandler[XK_Delete] = (void *) hime_chewing_wrapper_del;
430 }
431
module_init_win(HIME_module_main_functions * pFuncs)432 int module_init_win (HIME_module_main_functions *pFuncs) {
433 GtkWidget *pErrDialog = NULL;
434 int nIdx;
435 int nSegSize = 0;
436
437 if (!pFuncs)
438 return FALSE;
439
440 g_himeModMainFuncs = *pFuncs;
441
442 g_himeModMainFuncs.mf_set_tsin_pho_mode ();
443 g_himeModMainFuncs.mf_set_win1_cb ((cb_selec_by_idx_t) select_idx,
444 prev_page,
445 next_page);
446
447 if (g_pWinChewing)
448 return TRUE;
449
450 if (!chewing_initialize ()) {
451 pErrDialog = gtk_message_dialog_new (NULL,
452 GTK_DIALOG_MODAL,
453 GTK_MESSAGE_ERROR,
454 GTK_BUTTONS_CLOSE,
455 "chewing init failed");
456 gtk_dialog_run (GTK_DIALOG (pErrDialog));
457 gtk_widget_destroy (pErrDialog);
458 return FALSE;
459 }
460
461 g_pWinChewing = gtk_window_new (GTK_WINDOW_TOPLEVEL);
462 gtk_window_set_has_resize_grip (GTK_WINDOW (g_pWinChewing), FALSE);
463
464 gtk_widget_realize (g_pWinChewing);
465 g_himeModMainFuncs.mf_set_no_focus (g_pWinChewing);
466
467 g_pEvBoxChewing = gtk_event_box_new ();
468 gtk_event_box_set_visible_window (GTK_EVENT_BOX (g_pEvBoxChewing), FALSE);
469
470 if (!g_pEvBoxChewing)
471 return FALSE;
472 gtk_container_add (GTK_CONTAINER (g_pWinChewing), g_pEvBoxChewing);
473
474 g_pHBoxChewing = gtk_hbox_new (FALSE, 0);
475 if (!g_pHBoxChewing)
476 return FALSE;
477 gtk_container_add (GTK_CONTAINER (g_pEvBoxChewing), g_pHBoxChewing);
478
479 // TODO: not sure if we need the mouse CB or not...
480 // if we add the CB here, then it seems that we have to use gdk
481 // it seems not so important...? do it later
482 //g_signal_connect (G_OBJECT (g_pEvBoxChewing), "button-press-event",
483 // G_CALLBACK (mouse_button_callback), NULL);
484
485 if (!g_pSeg) {
486 nSegSize = sizeof (SEG) * MAX_SEG_NUM;
487 g_pSeg = malloc (nSegSize);
488 memset (g_pSeg, 0, nSegSize);
489 }
490
491 for (nIdx = 0; nIdx < MAX_SEG_NUM; nIdx++) {
492 g_pSeg[nIdx].label = gtk_label_new (NULL);
493 gtk_widget_show (g_pSeg[nIdx].label);
494 gtk_box_pack_start (GTK_BOX (g_pHBoxChewing),
495 g_pSeg[nIdx].label,
496 FALSE,
497 FALSE,
498 0);
499 }
500
501 if (!g_himeModMainFuncs.mf_phkbm->selkeyN)
502 g_himeModMainFuncs.mf_load_tab_pho_file ();
503
504 gtk_widget_show_all (g_pWinChewing);
505
506 g_himeModMainFuncs.mf_init_tsin_selection_win ();
507
508 module_change_font_size ();
509
510 module_hide_win ();
511
512 return TRUE;
513 }
514
515 // FIXME: impl
module_get_win_geom(void)516 void module_get_win_geom (void) {
517 return;
518 }
519
520 // FIXME: chk
module_reset(void)521 int module_reset (void) {
522 if (!g_pWinChewing)
523 return 0;
524 return 1;
525 }
526
527 // FIXME: refine and chk
module_get_preedit(char * pszStr,HIME_PREEDIT_ATTR himePreeditAttr[],int * pnCursor,int * pCompFlag)528 int module_get_preedit (char *pszStr, HIME_PREEDIT_ATTR himePreeditAttr[], int *pnCursor, int *pCompFlag) {
529 char *pszTmpStr = NULL;
530 const char *pszZuinStr = NULL;
531 int nIdx;
532 int nLength;
533 int nTotalLen = 0;
534 int nAttr = 0;
535 int nZuinLen = 0;
536
537 pszStr[0] = 0;
538 *pnCursor = 0;
539 himePreeditAttr[0].flag = HIME_PREEDIT_ATTR_FLAG_UNDERLINE;
540 himePreeditAttr[0].ofs0 = 0;
541
542 if (chewing_buffer_Len (g_pChewingCtx))
543 nAttr = 1;
544
545 for (nIdx = 0; nIdx < chewing_buffer_Len (g_pChewingCtx); nIdx++) {
546 pszTmpStr = (char *) gtk_label_get_text (GTK_LABEL (g_pSeg[nIdx].label));
547 nLength = g_himeModMainFuncs.mf_utf8_str_N (pszTmpStr);
548 nTotalLen += nLength;
549
550 if (nIdx < chewing_cursor_Current (g_pChewingCtx))
551 *pnCursor += nLength;
552
553 #if 0
554 if (nIdx == chewing_cursor_Current (g_pChewingCtx))
555 {
556 himePreeditAttr[1].ofs0 = *pnCursor;
557 himePreeditAttr[1].ofs1 = *pnCursor + nLength;
558 himePreeditAttr[1].flag = HIME_PREEDIT_ATTR_FLAG_REVERSE;
559 nAttr++;
560 }
561 #endif
562
563 strcat (pszStr, pszTmpStr);
564 }
565
566 if (g_himeModMainFuncs.mf_hime_display_on_the_spot_key ()) {
567 pszZuinStr = chewing_bopomofo_String_static (g_pChewingCtx);
568 strcat (pszStr, pszZuinStr);
569 nTotalLen += nZuinLen;
570 }
571
572 himePreeditAttr[0].ofs1 = nTotalLen;
573
574 pCompFlag = 0;
575
576 return nAttr;
577 }
578
579 gboolean
module_feedkey(int nKeyVal,int nKeyState)580 module_feedkey (int nKeyVal, int nKeyState) {
581 if (!g_pChewingCtx)
582 return FALSE;
583
584 if (!g_himeModMainFuncs.mf_tsin_pho_mode ())
585 return FALSE;
586
587 hime_label_clear (MAX_SEG_NUM);
588
589 chewing_set_ShapeMode (g_pChewingCtx, g_himeModMainFuncs.mf_current_shape_mode ());
590
591 if (nKeyState & (Mod1Mask | Mod4Mask | Mod5Mask | ControlMask))
592 return FALSE;
593
594 if (!hime_key_filter (&nKeyVal))
595 return FALSE;
596
597 if (!hime_buffer_commit ())
598 return FALSE;
599
600 if (!hime_buffer_label_show ())
601 return FALSE;
602
603 if (!hime_zuin_label_show ())
604 return FALSE;
605
606 module_show_win ();
607
608 return TRUE;
609 }
610
611 // FIXME: impl
module_feedkey_release(KeySym xkey,int nKbState)612 int module_feedkey_release (KeySym xkey, int nKbState) {
613 return 0;
614 }
615
module_move_win(int nX,int nY)616 void module_move_win (int nX, int nY) {
617 gtk_window_get_size (GTK_WINDOW (g_pWinChewing),
618 g_himeModMainFuncs.mf_win_xl,
619 g_himeModMainFuncs.mf_win_yl);
620
621 if (nX + *g_himeModMainFuncs.mf_win_xl > *g_himeModMainFuncs.mf_dpy_xl)
622 nX = *g_himeModMainFuncs.mf_dpy_xl - *g_himeModMainFuncs.mf_win_xl;
623 if (nX < 0)
624 nX = 0;
625
626 if (nY + *g_himeModMainFuncs.mf_win_yl > *g_himeModMainFuncs.mf_dpy_yl)
627 nY = *g_himeModMainFuncs.mf_dpy_yl - *g_himeModMainFuncs.mf_win_yl;
628 if (nY < 0)
629 nY = 0;
630
631 gtk_window_move (GTK_WINDOW (g_pWinChewing), nX, nY);
632
633 *g_himeModMainFuncs.mf_win_x = nX;
634 *g_himeModMainFuncs.mf_win_y = nY;
635
636 g_himeModMainFuncs.mf_move_win_sym ();
637 }
638
module_change_font_size(void)639 void module_change_font_size (void) {
640 GdkColor colorFG;
641
642 gdk_color_parse (*g_himeModMainFuncs.mf_hime_win_color_fg, &colorFG);
643
644 #if GTK_CHECK_VERSION(3, 0, 0)
645 GdkRGBA rgbfg;
646 gdk_rgba_parse (&rgbfg, gdk_color_to_string (&colorFG));
647 #endif
648
649 g_himeModMainFuncs.mf_change_win_bg (g_pWinChewing);
650 g_himeModMainFuncs.mf_change_win_bg (g_pEvBoxChewing);
651
652 for (int i = 0; i < MAX_SEG_NUM; i++) {
653 GtkWidget *pLabel = g_pSeg[i].label;
654 g_himeModMainFuncs.mf_set_label_font_size (
655 pLabel,
656 *g_himeModMainFuncs.mf_hime_font_size);
657
658 if (*g_himeModMainFuncs.mf_hime_win_color_use) {
659 #if !GTK_CHECK_VERSION(3, 0, 0)
660 gtk_widget_modify_fg (pLabel, GTK_STATE_NORMAL, &colorFG);
661 #else
662 gtk_widget_override_color (pLabel, GTK_STATE_FLAG_NORMAL, &rgbfg);
663 #endif
664 }
665 }
666 }
667
module_show_win(void)668 void module_show_win (void) {
669 if (g_himeModMainFuncs.mf_hime_edit_display_ap_only ())
670 return;
671
672 if (*g_himeModMainFuncs.mf_hime_pop_up_win && is_empty ())
673 return;
674
675 gtk_window_resize (GTK_WINDOW (g_pWinChewing),
676 32 * (chewing_buffer_Check (g_pChewingCtx) + 1),
677 12);
678 gtk_widget_show (g_pWinChewing);
679
680 g_himeModMainFuncs.mf_show_win_sym ();
681 }
682
module_hide_win(void)683 void module_hide_win (void) {
684 gtk_widget_hide (g_pWinChewing);
685 g_himeModMainFuncs.mf_hide_selections_win ();
686 g_himeModMainFuncs.mf_hide_win_sym ();
687 }
688
689 // FIXME: chk
module_win_visible(void)690 int module_win_visible (void) {
691 return gtk_widget_get_visible (g_pWinChewing);
692 }
693
module_win_geom(void)694 void module_win_geom (void) {
695 if (!g_pWinChewing)
696 return;
697
698 gtk_window_get_position (GTK_WINDOW (g_pWinChewing),
699 g_himeModMainFuncs.mf_win_x,
700 g_himeModMainFuncs.mf_win_y);
701
702 g_himeModMainFuncs.mf_get_win_size (g_pWinChewing,
703 g_himeModMainFuncs.mf_win_xl,
704 g_himeModMainFuncs.mf_win_yl);
705 }
706
module_flush_input(void)707 int module_flush_input (void) {
708 char *pszTmp;
709
710 if (chewing_buffer_Check (g_pChewingCtx)) {
711 pszTmp = chewing_buffer_String (g_pChewingCtx);
712 g_himeModMainFuncs.mf_send_text (pszTmp);
713 free (pszTmp);
714 }
715
716 chewing_Reset (g_pChewingCtx);
717
718 // FIXME: dirty workaround to reset the libchewing internal data
719 // it may impact the bEscCleanAllBuf setting
720 chewing_handle_Esc (g_pChewingCtx);
721
722 hime_label_clear (MAX_SEG_NUM);
723
724 if (*g_himeModMainFuncs.mf_hime_pop_up_win && is_empty ())
725 module_hide_win ();
726
727 return 0;
728 }
729