1 /* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */
2
3 #include "mc_im.h"
4
5 #include <pobl/bl_mem.h> /* free */
6 #include <pobl/bl_debug.h>
7 #include <pobl/bl_file.h>
8 #include <pobl/bl_conf_io.h>
9 #include <pobl/bl_dlfcn.h>
10 #include <pobl/bl_map.h>
11 #include <pobl/bl_str.h> /* strdup */
12 #include <pobl/bl_def.h> /* USE_WIN32API */
13 #include <glib.h>
14 #include <c_intl.h>
15 #include <dirent.h>
16 #include <im_info.h>
17
18 #include "mc_combo.h"
19 #include "mc_io.h"
20
21 #if 0
22 #define __DEBUG
23 #endif
24
25 #if defined(USE_WIN32API)
26 #define CONFIG_PATH "."
27 #elif defined(SYSCONFDIR)
28 #define CONFIG_PATH SYSCONFDIR
29 #else
30 #define CONFIG_PATH "/etc"
31 #endif
32
33 #ifndef LIBDIR
34 #define IM_DIR "/usr/local/lib/mlterm/"
35 #else
36 #define IM_DIR LIBDIR "/mlterm/"
37 #endif
38
39 #define STR_LEN 256
40
41 BL_MAP_TYPEDEF(xim_locale, char *, char *);
42
43 #define IM_MAX 20
44
45 typedef enum im_type {
46 IM_NONE = 0,
47 IM_XIM = 1,
48 IM_OTHER = 2,
49
50 IM_TYPE_MAX = IM_MAX
51
52 } im_type_t;
53
54 typedef im_info_t *(*im_get_info_func_t)(char *, char *);
55
56 /* --- static variables --- */
57
58 static char *cur_locale;
59
60 static im_type_t im_type;
61 static im_type_t cur_im_type;
62
63 static char **xims;
64 static char **locales;
65 static u_int num_xims;
66
67 static int is_changed = 0;
68
69 static char xim_auto_str[STR_LEN] = "";
70 static char current_locale_str[STR_LEN] = "";
71 static char selected_xim_name[STR_LEN] = "";
72 static char selected_xim_locale[STR_LEN] = "";
73
74 static im_info_t *im_info_table[IM_MAX];
75 static u_int num_info = 0;
76 static im_info_t *selected_im = NULL;
77 static int selected_im_arg = -1;
78
79 static GtkWidget **im_opt_widget;
80
81 static GtkWidget *skk_dict_entry;
82 static GtkWidget *skk_sskey_entry;
83 static GtkWidget *wnn_serv_entry;
84
85 /* --- static functions --- */
86
is_im_plugin(char * file_name)87 static int is_im_plugin(char *file_name) {
88 if (bl_dl_is_module(file_name) && strstr(file_name, "im-")) {
89 return 1;
90 }
91
92 return 0;
93 }
94
95 #ifdef USE_WIN32API
get_kbd_info(char * locale,char * encoding)96 static im_info_t *get_kbd_info(char *locale, char *encoding) {
97 im_info_t *result;
98
99 if (!(result = malloc(sizeof(im_info_t)))) {
100 return NULL;
101 }
102
103 result->num_args = 13;
104
105 if (!(result->args = malloc(sizeof(char *) * result->num_args))) {
106 free(result);
107 return NULL;
108 }
109
110 if (!(result->readable_args = malloc(sizeof(char *) * result->num_args))) {
111 free(result->args);
112 free(result);
113 return NULL;
114 }
115
116 result->readable_args[0] = strdup("Unknown");
117 result->readable_args[1] = strdup("Arabic");
118 result->readable_args[2] = strdup("Hebrew");
119 result->readable_args[3] = strdup("Indic (ASSAMESE)");
120 result->readable_args[4] = strdup("Indic (BENGALI)");
121 result->readable_args[5] = strdup("Indic (GUJARATI)");
122 result->readable_args[6] = strdup("Indic (HINDI)");
123 result->readable_args[7] = strdup("Indic (KANNADA)");
124 result->readable_args[8] = strdup("Indic (MALAYALAM)");
125 result->readable_args[9] = strdup("Indic (ORIYA)");
126 result->readable_args[10] = strdup("Indic (PUNJABI)");
127 result->readable_args[11] = strdup("Indic (TAMIL)");
128 result->readable_args[12] = strdup("Indic (TELUGU)");
129
130 result->args[0] = strdup("");
131 result->args[1] = strdup("arabic");
132 result->args[2] = strdup("hebrew");
133 result->args[3] = strdup("isciiassamese");
134 result->args[4] = strdup("isciibengali");
135 result->args[5] = strdup("isciigujarati");
136 result->args[6] = strdup("isciihindi");
137 result->args[7] = strdup("isciikannada");
138 result->args[8] = strdup("isciimalayalam");
139 result->args[9] = strdup("isciioriya");
140 result->args[10] = strdup("isciipunjabi");
141 result->args[11] = strdup("isciitamil");
142 result->args[12] = strdup("isciitelugu");
143
144 result->id = strdup("kbd");
145 result->name = strdup("keyboard");
146
147 return result;
148 }
149 #endif
150
get_im_info(char * locale,char * encoding)151 static int get_im_info(char *locale, char *encoding) {
152 char *im_dir_path;
153 DIR *dir;
154 struct dirent *d;
155 const char *gui;
156
157 if ((dir = opendir(IM_DIR))) {
158 im_dir_path = IM_DIR;
159 #if 0
160 } else if ((dir = opendir("."))) {
161 im_dir_path = "";
162 #endif
163 } else {
164 #ifdef USE_WIN32API
165 if ((im_info_table[num_info] = get_kbd_info(locale, encoding))) {
166 num_info++;
167 return 1;
168 }
169 #endif
170 return 0;
171 }
172
173 gui = mc_get_gui();
174
175 while ((d = readdir(dir))) {
176 im_info_t *info;
177 char symname[100];
178 char *p;
179 char *end;
180 bl_dl_handle_t handle;
181
182 if (d->d_name[0] == '.' || !is_im_plugin(d->d_name)) continue;
183
184 /* libim-foo.so -> libim-foo */
185 if (!(p = strchr(d->d_name, '.'))) continue;
186 *p = '\0';
187
188 /* libim-foo -> im-foo */
189 if (!(p = strstr(d->d_name, "im-"))) continue;
190
191 end = p + strlen(p);
192 if (strcmp(gui, "sdl2") == 0) {
193 end -= 5;
194 if (strcmp(end, "-sdl2") != 0) {
195 continue;
196 }
197 } else if (strcmp(gui, "fb") == 0 || strcmp(gui, "console") == 0 ||
198 strcmp(gui, "wayland") == 0) {
199 end -= 3;
200 if (strcmp(end, *gui == 'w' ? "-wl" : "-fb") != 0) {
201 continue;
202 }
203 }
204
205 if ((handle = bl_dl_open(im_dir_path, p))) {
206 im_get_info_func_t func;
207
208 *end = '\0';
209 snprintf(symname, 100, "im_%s_get_info", &p[3]);
210
211 if ((func = (im_get_info_func_t)bl_dl_func_symbol(handle, symname))) {
212 if ((info = (*func)(locale, encoding))) {
213 im_info_table[num_info] = info;
214 num_info++;
215 }
216 }
217
218 bl_dl_close(handle);
219 }
220 }
221
222 return 0;
223 }
224
225 /*
226 * XIM
227 */
228
get_xim_locale(char * xim)229 static char *get_xim_locale(char *xim) {
230 int count;
231
232 for (count = 0; count < num_xims; count++) {
233 if (strcmp(xims[count], xim) == 0) {
234 return locales[count];
235 }
236 }
237
238 return NULL;
239 }
240
xim_selected(GtkWidget * widget,gpointer data)241 static gint xim_selected(GtkWidget *widget, gpointer data) {
242 char *locale;
243
244 snprintf(selected_xim_name, STR_LEN, "%s", gtk_entry_get_text(GTK_ENTRY(widget)));
245
246 if ((locale = get_xim_locale(selected_xim_name))) {
247 gtk_entry_set_text(GTK_ENTRY(data), locale);
248 } else {
249 gtk_entry_set_text(GTK_ENTRY(data), current_locale_str);
250 }
251
252 snprintf(selected_xim_locale, STR_LEN, "%s", gtk_entry_get_text(GTK_ENTRY(data)));
253
254 is_changed = 1;
255
256 return 1;
257 }
258
read_xim_conf(BL_MAP (xim_locale)xim_locale_table,char * filename)259 static int read_xim_conf(BL_MAP(xim_locale) xim_locale_table, char *filename) {
260 bl_file_t *from;
261 char *key;
262 char *value;
263 BL_PAIR(xim_locale) pair;
264 int result;
265
266 if (!(from = bl_file_open(filename, "r"))) {
267 #ifdef DEBUG
268 bl_warn_printf(BL_DEBUG_TAG " %s couldn't be opened.\n", filename);
269 #endif
270
271 return 0;
272 }
273
274 while (bl_conf_io_read(from, &key, &value)) {
275 bl_map_get(xim_locale_table, key, pair);
276
277 if (pair) {
278 free(pair->value);
279 pair->value = strdup(value);
280 } else {
281 key = strdup(key);
282 value = strdup(value);
283
284 bl_map_set(result, xim_locale_table, key, value);
285 }
286 }
287
288 bl_file_close(from);
289
290 return 1;
291 }
292
xim_widget_new(const char * xim_name,const char * xim_locale,const char * cur_locale)293 static GtkWidget *xim_widget_new(const char *xim_name, const char *xim_locale,
294 const char *cur_locale) {
295 BL_MAP(xim_locale) xim_locale_table;
296 BL_PAIR(xim_locale) * array;
297 u_int size;
298 char *rcpath;
299 char *default_xim_name;
300 GtkWidget *vbox;
301 GtkWidget *hbox;
302 GtkWidget *label;
303 GtkWidget *entry;
304 GtkWidget *combo;
305 GtkWidget *combo_entry;
306 int count;
307
308 default_xim_name = mc_get_str_value("default_xim_name");
309 snprintf(xim_auto_str, STR_LEN, _("auto (currently %s)"), default_xim_name);
310 free(default_xim_name);
311
312 /*
313 * create known xim list from <prefix>/etc/mlterm/xim and/or
314 * ~/.mlterm/xim.
315 */
316
317 bl_map_new_with_size(char *, char *, xim_locale_table, bl_map_hash_str, bl_map_compare_str, 16);
318
319 bl_set_sys_conf_dir(CONFIG_PATH);
320
321 if ((rcpath = bl_get_sys_rc_path("mlterm/xim"))) {
322 read_xim_conf(xim_locale_table, rcpath);
323 free(rcpath);
324 }
325
326 if ((rcpath = bl_get_user_rc_path("mlterm/xim"))) {
327 read_xim_conf(xim_locale_table, rcpath);
328 free(rcpath);
329 }
330
331 bl_map_get_pairs_array(xim_locale_table, array, size);
332
333 if ((xims = malloc(sizeof(char *) * (size + 1))) == NULL ||
334 (locales = malloc(sizeof(char *) * (size + 1))) == NULL) {
335 free(xims);
336 bl_map_destroy(xim_locale_table);
337
338 return NULL;
339 }
340
341 for (count = 0; count < size; count++) {
342 xims[count] = array[count]->key;
343 locales[count] = array[count]->value;
344 }
345
346 xims[count] = xim_auto_str;
347 locales[count] = NULL;
348
349 num_xims = size + 1;
350
351 bl_map_destroy(xim_locale_table);
352
353 /*
354 * create widgets
355 */
356
357 vbox = gtk_vbox_new(FALSE, 5);
358
359 snprintf(current_locale_str, STR_LEN, _("auto (currently %s)"), cur_locale);
360 entry = gtk_entry_new();
361 snprintf(selected_xim_locale, STR_LEN, "%s", xim_locale ? xim_locale : current_locale_str);
362 gtk_entry_set_text(GTK_ENTRY(entry), selected_xim_locale);
363
364 snprintf(selected_xim_name, STR_LEN, "%s", xim_name ? xim_name : xim_auto_str);
365 combo = mc_combo_new(_("XIM Server"), xims, num_xims, selected_xim_name, 0, &combo_entry);
366 g_signal_connect(combo_entry, "changed", G_CALLBACK(xim_selected), entry);
367
368 label = gtk_label_new(_("XIM locale"));
369
370 hbox = gtk_hbox_new(FALSE, 5);
371
372 gtk_box_pack_start(GTK_BOX(vbox), combo, TRUE, TRUE, 0);
373 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
374 gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
375 gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
376
377 gtk_widget_show(combo);
378 gtk_widget_show(entry);
379 gtk_widget_show(label);
380 gtk_widget_show(hbox);
381
382 return vbox;
383 }
384
385 /*
386 * pluggable ims
387 */
388
im_selected(GtkWidget * widget,gpointer data)389 static gint im_selected(GtkWidget *widget, gpointer data) {
390 const char *str;
391 int i;
392
393 if (selected_im == NULL) return 1;
394
395 str = (const char *)gtk_entry_get_text(GTK_ENTRY(widget));
396
397 for (i = 0; i < selected_im->num_args; i++)
398 if (strcmp(selected_im->readable_args[i], str) == 0) selected_im_arg = i;
399
400 is_changed = 1;
401
402 return 1;
403 }
404
im_widget_new(int nth_im,const char * value,char * locale)405 static GtkWidget *im_widget_new(int nth_im, const char *value, char *locale) {
406 GtkWidget *combo;
407 GtkWidget *entry;
408 im_info_t *info;
409 int i;
410 int selected = 0;
411 size_t len;
412
413 info = im_info_table[nth_im];
414
415 if (value) {
416 for (i = 1; i < info->num_args; i++) {
417 if (strcmp(info->args[i], value) == 0) {
418 selected = i;
419 }
420 }
421 }
422
423 if (!info->num_args) return NULL;
424
425 if (!value || (value && selected)) {
426 char *auto_str;
427
428 /*
429 * replace gettextized string
430 */
431 len = strlen(_("auto (currently %s)")) + strlen(info->readable_args[0]) + 1;
432
433 if ((auto_str = malloc(len))) {
434 snprintf(auto_str, len, _("auto (currently %s)"), info->readable_args[0]);
435 free(info->readable_args[0]);
436 info->readable_args[0] = auto_str;
437 }
438 } else {
439 free(info->readable_args[0]);
440 info->readable_args[0] = strdup(value);
441 }
442
443 combo = mc_combo_new(_("Option"), info->readable_args, info->num_args,
444 info->readable_args[selected], 1, &entry);
445 g_signal_connect(entry, "changed", G_CALLBACK(im_selected), NULL);
446
447 return combo;
448 }
449
entry_selected(GtkWidget * widget,gpointer data)450 static gint entry_selected(GtkWidget *widget, gpointer data) {
451 is_changed = 1;
452
453 return 1;
454 }
455
entry_with_label_new(GtkWidget * parent,const char * text,const char * value)456 static GtkWidget *entry_with_label_new(GtkWidget *parent, const char *text, const char *value) {
457 GtkWidget *hbox;
458 GtkWidget *label;
459 GtkWidget *entry;
460
461 hbox = gtk_hbox_new(FALSE, 5);
462 gtk_box_pack_start(GTK_BOX(parent), hbox, TRUE, TRUE, 0);
463 gtk_widget_show(hbox);
464
465 label = gtk_label_new(text);
466 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
467 gtk_widget_show(label);
468
469 entry = gtk_entry_new();
470 gtk_entry_set_text(GTK_ENTRY(entry), value);
471 g_signal_connect(entry, "changed", G_CALLBACK(entry_selected), entry);
472 gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
473 gtk_widget_show(entry);
474
475 return entry;
476 }
477
combo_with_label_new(GtkWidget * parent,const char * label_name,char ** item_names,u_int item_num,const char * value)478 static GtkWidget *combo_with_label_new(GtkWidget *parent, const char *label_name,
479 char **item_names, u_int item_num, const char *value) {
480 GtkWidget *hbox;
481 GtkWidget *combo;
482 GtkWidget *entry;
483
484 hbox = gtk_hbox_new(FALSE, 5);
485 gtk_box_pack_start(GTK_BOX(parent), hbox, TRUE, TRUE, 0);
486 gtk_widget_show(hbox);
487
488 combo = mc_combo_new(label_name, item_names, item_num, value, 0, &entry);
489 gtk_box_pack_start(GTK_BOX(hbox), combo, TRUE, TRUE, 0);
490 gtk_widget_show(combo);
491 g_signal_connect(entry, "changed", G_CALLBACK(entry_selected), entry);
492
493 return entry;
494 }
495
skk_widget_new(char * value)496 static GtkWidget *skk_widget_new(char *value) {
497 GtkWidget *vbox;
498 char *dict = NULL;
499 char *sskey = NULL;
500 char buf[2];
501 char *cands[] = { ";", ":", "Muhenkan", "Henkan", };
502
503 /* Same processing as im_skk_new() in im_skk.c */
504 if (value) {
505 #if 1
506 /* XXX Compat with 3.8.3 or before. */
507 if (!strchr(value, '=')) {
508 dict = value;
509 } else
510 #endif
511 {
512 char *next;
513
514 do {
515 if ((next = strchr(value, ','))) {
516 *(next++) = '\0';
517 }
518
519 if (strncmp(value, "sskey=", 6) == 0) {
520 int digit;
521 sskey = value + 6;
522 if (sscanf(sskey, "\\x%x", &digit) == 1) {
523 buf[0] = digit;
524 buf[1] = '\0';
525 sskey = buf;
526 }
527 } else if (strncmp(value, "dict=", 5) == 0) {
528 dict = value + 5;
529 }
530 } while ((value = next));
531 }
532 }
533
534 vbox = gtk_vbox_new(FALSE, 5);
535 skk_dict_entry = entry_with_label_new(vbox, _("Dictionary"), dict ? dict : "");
536 skk_sskey_entry = combo_with_label_new(vbox, _("Sticky shift key"), cands,
537 sizeof(cands) / sizeof(cands[0]),
538 sskey ? sskey : "");
539
540 return vbox;
541 }
542
skk_current_value(void)543 static char *skk_current_value(void) {
544 const char *dict;
545 const char *sskey;
546 size_t len = 4;
547 char *value;
548 char *p;
549
550 dict = gtk_entry_get_text(GTK_ENTRY(skk_dict_entry));
551 if (*dict) {
552 len += (strlen(dict) + 5 + 1);
553 }
554 sskey = gtk_entry_get_text(GTK_ENTRY(skk_sskey_entry));
555 if (*sskey) {
556 len += (strlen(sskey) + 6 + 1);
557 }
558
559 value = p = malloc(len);
560
561 strcpy(p, "skk");
562 p += 3;
563
564 if (*dict) {
565 sprintf(p, ":dict=%s", dict);
566 p += strlen(p);
567 }
568 if (*sskey) {
569 char sep = *dict ? ',' : ':';
570
571 if (strlen(sskey) == 1) {
572 sprintf(p, "%csskey=\\x%.2x", sep, *sskey);
573 } else {
574 sprintf(p, "%csskey=%s", sep, sskey);
575 }
576 }
577
578 return value;
579 }
580
wnn_widget_new(char * value)581 static GtkWidget *wnn_widget_new(char *value) {
582 GtkWidget *vbox;
583
584 vbox = gtk_vbox_new(FALSE, 5);
585 wnn_serv_entry = entry_with_label_new(vbox, _("Server"), value);
586
587 return vbox;
588 }
589
wnn_current_value(void)590 static char *wnn_current_value(void) {
591 const char *serv;
592 size_t len = 4;
593 char *value;
594
595 serv = gtk_entry_get_text(GTK_ENTRY(wnn_serv_entry));
596 if (*serv) {
597 len += (strlen(serv) + 1);
598 }
599
600 value = malloc(len);
601
602 if (*serv) {
603 sprintf(value, "wnn:%s", serv);
604 } else {
605 strcpy(value, "wnn");
606 }
607
608 return value;
609 }
610
611 /*
612 * callbacks for radio buttons of im type.
613 */
button_xim_checked(GtkWidget * widget,gpointer data)614 static gint button_xim_checked(GtkWidget *widget, gpointer data) {
615 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
616 if (data) gtk_widget_show(GTK_WIDGET(data));
617 im_type = IM_XIM;
618 } else {
619 if (data) gtk_widget_hide(GTK_WIDGET(data));
620 }
621
622 is_changed = 1;
623
624 return 1;
625 }
626
button_im_checked(GtkWidget * widget,gpointer data)627 static gint button_im_checked(GtkWidget *widget, gpointer data) {
628 int i;
629 int idx = 0;
630
631 if (data == NULL || num_info == 0) {
632 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
633 im_type = IM_NONE;
634 }
635 } else {
636 for (i = 0; i < num_info; i++)
637 if (im_info_table[i] == data) idx = i;
638
639 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
640 im_type = IM_OTHER + idx;
641 selected_im = data;
642 if (im_opt_widget[idx]) gtk_widget_show(GTK_WIDGET(im_opt_widget[idx]));
643 } else {
644 if (im_opt_widget[idx]) gtk_widget_hide(GTK_WIDGET(im_opt_widget[idx]));
645 }
646 }
647
648 is_changed = 1;
649
650 return 1;
651 }
652
653 /* --- global functions --- */
654
mc_im_init(void)655 void mc_im_init(void) {
656 char *encoding = mc_get_str_value("encoding");
657
658 cur_locale = mc_get_str_value("locale"); /* XXX leaked */
659
660 get_im_info(cur_locale, encoding);
661
662 free(encoding);
663 }
664
mc_im_config_widget_new(void)665 GtkWidget *mc_im_config_widget_new(void) {
666 char *xim_name = NULL;
667 char *xim_locale = NULL;
668 char *value;
669 char *im_name;
670 int i;
671 int index = -1;
672 GtkWidget *xim;
673 GtkWidget *frame;
674 GtkWidget *vbox;
675 GtkWidget *hbox;
676 GtkWidget *radio;
677 GSList *group;
678
679 value = mc_get_str_value("input_method");
680
681 im_name = bl_str_sep(&value, ":");
682
683 im_type = IM_NONE;
684 if (strncmp(im_name, "xim", 3) == 0) {
685 im_type = IM_XIM;
686 xim_name = bl_str_sep(&value, ":");
687 xim_locale = bl_str_sep(&value, ":");
688 } else if (strncmp(im_name, "none", 4) == 0) {
689 /* do nothing */
690 } else {
691 for (i = 0; i < num_info; i++) {
692 if (strcmp(im_name, im_info_table[i]->id) == 0) {
693 index = i;
694 im_type = IM_OTHER + i;
695 break;
696 }
697 }
698 }
699 cur_im_type = im_type;
700
701 if (strcmp(mc_get_gui(), "xlib") != 0) {
702 xim = NULL;
703 } else {
704 xim = xim_widget_new(xim_name, xim_locale, cur_locale);
705 }
706
707 im_opt_widget = malloc(sizeof(GtkWidget*) * num_info);
708
709 for (i = 0; i < num_info; i++) {
710 if (strcmp(im_info_table[i]->id, "skk") == 0)
711 im_opt_widget[i] = skk_widget_new(index == i ? value : "");
712 else if (strcmp(im_info_table[i]->id, "wnn") == 0)
713 im_opt_widget[i] = wnn_widget_new(index == i ? value : "");
714 else
715 im_opt_widget[i] = im_widget_new(i, index == i ? value : NULL, cur_locale);
716 }
717
718 free(im_name);
719
720 frame = gtk_frame_new(_("Input Method"));
721
722 vbox = gtk_vbox_new(FALSE, 5);
723 gtk_widget_show(vbox);
724
725 hbox = gtk_hbox_new(FALSE, 5);
726 radio = gtk_radio_button_new_with_label(NULL, xim ? "XIM" : "Default");
727 g_signal_connect(radio, "toggled", G_CALLBACK(button_xim_checked), xim);
728 gtk_widget_show(GTK_WIDGET(radio));
729 gtk_box_pack_start(GTK_BOX(hbox), radio, FALSE, FALSE, 0);
730 if (im_type == IM_XIM) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE);
731
732 for (i = 0; i < num_info; i++) {
733 group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio));
734 radio = gtk_radio_button_new_with_label(group, im_info_table[i]->name);
735 g_signal_connect(radio, "toggled", G_CALLBACK(button_im_checked), im_info_table[i]);
736 gtk_widget_show(GTK_WIDGET(radio));
737 gtk_box_pack_start(GTK_BOX(hbox), radio, FALSE, FALSE, 0);
738 if (index == i)
739 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE);
740 }
741
742 if (strcmp(mc_get_gui(), "xlib") == 0) {
743 group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio));
744 radio = gtk_radio_button_new_with_label(group, _("None"));
745 g_signal_connect(radio, "toggled", G_CALLBACK(button_im_checked), NULL);
746 gtk_widget_show(GTK_WIDGET(radio));
747 gtk_box_pack_start(GTK_BOX(hbox), radio, FALSE, FALSE, 0);
748 if (im_type == IM_NONE) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE);
749 }
750
751 gtk_widget_show(GTK_WIDGET(hbox));
752 gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
753
754 switch (im_type) {
755 case IM_XIM:
756 if (xim) gtk_widget_show(xim);
757 for (i = 0; i < num_info; i++)
758 if (im_opt_widget[i]) gtk_widget_hide(im_opt_widget[i]);
759 break;
760 case IM_NONE:
761 if (xim) gtk_widget_hide(xim);
762 for (i = 0; i < num_info; i++)
763 if (im_opt_widget[i]) gtk_widget_hide(im_opt_widget[i]);
764 break;
765 default: /* OTHER */
766 if (xim) gtk_widget_hide(xim);
767 for (i = 0; i < num_info; i++) {
768 if (!im_opt_widget[i]) continue;
769
770 if (i == index)
771 gtk_widget_show(im_opt_widget[i]);
772 else
773 gtk_widget_hide(im_opt_widget[i]);
774 }
775 break;
776 }
777
778 if (xim) gtk_box_pack_start(GTK_BOX(vbox), xim, TRUE, TRUE, 0);
779 for (i = 0; i < num_info; i++)
780 if (im_opt_widget[i]) gtk_box_pack_start(GTK_BOX(vbox), im_opt_widget[i], TRUE, TRUE, 0);
781
782 gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
783 gtk_container_add(GTK_CONTAINER(frame), vbox);
784
785 is_changed = 0;
786
787 return frame;
788 }
789
mc_update_im(void)790 void mc_update_im(void) {
791 char *p;
792 size_t len;
793
794 if (!is_changed) return;
795
796 if (strcmp(selected_im->id, "skk") == 0) {
797 p = skk_current_value();
798 goto end;
799 } else if (strcmp(selected_im->id, "wnn") == 0) {
800 p = wnn_current_value();
801 goto end;
802 }
803
804 if (im_type == cur_im_type && selected_im_arg == -1) {
805 is_changed = 0;
806 return;
807 }
808
809 if (selected_im_arg == -1) {
810 is_changed = 0;
811 selected_im_arg = 0;
812 }
813
814 switch (im_type) {
815 case IM_XIM:
816 if (strcmp(selected_xim_name, xim_auto_str) == 0) {
817 p = strdup("xim");
818 } else if (strcmp(selected_xim_locale, current_locale_str) == 0) {
819 len = 3 + 1 + strlen(selected_xim_name) + 1;
820 if (!(p = malloc(sizeof(char) * len))) return;
821 sprintf(p, "xim:%s", selected_xim_name);
822 } else {
823 len = 3 + 1 + strlen(selected_xim_name) + 1 + strlen(selected_xim_locale) + 1;
824 if (!(p = malloc(sizeof(char) * len))) return;
825 sprintf(p, "xim:%s:%s", selected_xim_name, selected_xim_locale);
826 }
827 break;
828 case IM_NONE:
829 p = strdup("none");
830 break;
831 /* case IM_OTHER: */
832 default:
833 if (selected_im == NULL) return;
834 if (selected_im_arg == 0) { /* auto */
835 p = strdup(selected_im->id);
836 } else {
837 len = strlen(selected_im->id) + strlen(selected_im->args[selected_im_arg]) + 2;
838 if (!(p = malloc(len))) return;
839 sprintf(p, "%s:%s", selected_im->id, selected_im->args[selected_im_arg]);
840 }
841 break;
842 }
843
844 end:
845 mc_set_str_value("input_method", p);
846
847 selected_im_arg = -1;
848 cur_im_type = im_type;
849 is_changed = 0;
850
851 free(p);
852 }
853