1 /*
2  * Copyright (C) 2020 The HIME team, Taiwan
3  * Copyright (C) 2011 Edward Der-Hua Liu, Hsin-Chu, Taiwan
4  * Copyright (C) 2012 Favonia <favonia@gmail.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation version 2.1
9  * of the License.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20 
21 #include "hime.h"
22 
23 #include "pho-kbm-name.h"
24 #include "pho.h"
25 
26 /* "5849302-67" is Dvorak Simplified Keyboard remapped under QWERTY keyboard
27  * Please see: http://en.wikipedia.org/wiki/Dvorak_Simplified_Keyboard
28  *             https://github.com/hime-ime/hime/issues/62
29  */
30 struct {
31     char *kstr;
32     int RL;
33 } selkeys[] = {
34     {"123456789", 0}, {"asdfghjkl;", 0}, {"asdfzxcv", 0}, {"fdsavcxz", 1}, {"rewfdsvcx", 1}, {"fdsvcxrew", 1}, {"3825416790", 1}, {"5849302-67", 1}, {NULL}};
35 
36 /* XXX UI states hold uncommited preference.
37  * That's why we need these global variables. */
38 static GtkWidget *check_button_tsin_phrase_pre_select,
39     *check_button_phonetic_char_dynamic_sequence,
40     *check_button_pho_hide_row2,
41     *check_button_pho_in_row1,
42     *check_button_phonetic_huge_tab,
43     *check_button_tsin_tone_char_input,
44     *check_button_tsin_tab_phrase_end,
45     *check_button_tsin_tail_select_key,
46     *check_button_tsin_buffer_editing_mode,
47     *check_button_tsin_use_pho_near,
48     *spinner_tsin_buffer_size,
49     *spinner_pho_candidate_col_N;
50 
51 GtkWidget *check_button_hime_capslock_lower;
52 
53 static GtkWidget *opt_kbm_opts, *opt_selkeys, *opt_eng_ch_opts[2];
54 extern gboolean button_order;
55 
56 static struct {
57     unich_t *name;
58     int key;
59 } tsin_eng_ch_sw[] = {
60     {N_ ("(Disable)"), TSIN_CHINESE_ENGLISH_TOGGLE_KEY_None},
61     {N_ ("CapsLock"), TSIN_CHINESE_ENGLISH_TOGGLE_KEY_CapsLock},
62     //  {N_("Tab"), TSIN_CHINESE_ENGLISH_TOGGLE_KEY_Tab},
63     {N_ ("Shift"), TSIN_CHINESE_ENGLISH_TOGGLE_KEY_Shift},
64     {N_ ("Left Shift"), TSIN_CHINESE_ENGLISH_TOGGLE_KEY_ShiftL},
65     {N_ ("Right Shift"), TSIN_CHINESE_ENGLISH_TOGGLE_KEY_ShiftR},
66 };
67 int tsin_eng_ch_swN = sizeof (tsin_eng_ch_sw) / sizeof (tsin_eng_ch_sw[0]);
68 
69 static struct {
70     unich_t *name;
71     int key;
72 } tsin_space_options[] = {
73     {N_ ("Select other same phonetic characters"), TSIN_SPACE_OPT_SELECT_CHAR},
74     {N_ ("Send space to Tsin buffer"), TSIN_SPACE_OPT_INPUT}};
75 int tsin_space_optionsN = sizeof (tsin_space_options) / sizeof (tsin_space_options[0]);
76 
77 extern char *pho_speaker[16];
78 extern int pho_speakerN;
79 
get_current_speaker_idx()80 int get_current_speaker_idx () {
81     int i;
82 
83     for (i = 0; i < pho_speakerN; i++)
84         if (!strcmp (pho_speaker[i], phonetic_speak_sel))
85             return i;
86 
87     return 0;
88 }
89 
save_tsin_eng_pho_key()90 void save_tsin_eng_pho_key () {
91     int idx;
92     idx = gtk_combo_box_get_active (GTK_COMBO_BOX (opt_eng_ch_opts[0]));
93     save_hime_conf_int (TSIN_CHINESE_ENGLISH_TOGGLE_KEY,
94                         tsin_eng_ch_sw[idx].key);
95 
96     save_hime_conf_int (HIME_CAPSLOCK_LOWER,
97                         gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_button_hime_capslock_lower)));
98 }
99 
100 static GtkWidget *kbm_widget = NULL;
101 
102 static int new_select_idx_tsin_space_opt;
103 //static GdkColor tsin_phrase_line_gcolor;
104 
save_kbm_conf()105 void save_kbm_conf () {
106     if (kbm_widget == NULL) {
107         fprintf (stderr, "save_kbm_conf: kbm_widget is NULL!\n");
108         return;
109     }
110 
111     int idx = gtk_combo_box_get_active (GTK_COMBO_BOX (opt_kbm_opts));
112 
113     int idx_selkeys = gtk_combo_box_get_active (GTK_COMBO_BOX (opt_selkeys));
114 
115     pho_candidate_col_N = (int) gtk_spin_button_get_value (GTK_SPIN_BUTTON (spinner_pho_candidate_col_N));
116 
117     if (pho_candidate_col_N > strlen (selkeys[idx_selkeys].kstr))
118         pho_candidate_col_N = strlen (selkeys[idx_selkeys].kstr);
119 
120     dbg ("pho_candidate_col_N %d\n", pho_candidate_col_N);
121 
122     char tt[128];
123     snprintf (tt, sizeof (tt), "%s %s %d %d", kbm_sel[idx].kbm, selkeys[idx_selkeys].kstr, pho_candidate_col_N, selkeys[idx_selkeys].RL);
124 
125     char phokbm_name[128];
126     get_hime_conf_fstr (PHONETIC_KEYBOARD, phokbm_name, "");
127 
128     if (strcmp (phokbm_name, tt)) {
129         save_hime_conf_str (PHONETIC_KEYBOARD_BAK, phokbm_name);
130     }
131     save_hime_conf_str (PHONETIC_KEYBOARD, tt);
132 
133     save_tsin_eng_pho_key ();
134 
135     save_hime_conf_int (TSIN_SPACE_OPT,
136                         tsin_space_options[new_select_idx_tsin_space_opt].key);
137 
138     save_hime_conf_int (TSIN_PHRASE_PRE_SELECT,
139                         gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_button_tsin_phrase_pre_select)));
140 
141     save_hime_conf_int (PHONETIC_CHAR_DYNAMIC_SEQUENCE,
142                         gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_button_phonetic_char_dynamic_sequence)));
143     save_hime_conf_int (PHO_HIDE_ROW2,
144                         gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_button_pho_hide_row2)));
145 
146     save_hime_conf_int (PHO_IN_ROW1,
147                         gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_button_pho_in_row1)));
148 
149     save_hime_conf_int (PHONETIC_HUGE_TAB,
150                         gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_button_phonetic_huge_tab)));
151 
152     save_hime_conf_int (TSIN_TONE_CHAR_INPUT,
153                         gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_button_tsin_tone_char_input)));
154 
155     save_hime_conf_int (TSIN_USE_PHO_NEAR,
156                         gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_button_tsin_use_pho_near)));
157 
158     save_hime_conf_int (TSIN_TAB_PHRASE_END,
159                         gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_button_tsin_tab_phrase_end)));
160 
161     save_hime_conf_int (TSIN_TAIL_SELECT_KEY,
162                         gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_button_tsin_tail_select_key)));
163 
164     save_hime_conf_int (TSIN_BUFFER_EDITING_MODE,
165                         gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_button_tsin_buffer_editing_mode)));
166 
167     tsin_buffer_size = (int) gtk_spin_button_get_value (GTK_SPIN_BUTTON (spinner_tsin_buffer_size));
168     save_hime_conf_int (TSIN_BUFFER_SIZE, tsin_buffer_size);
169 
170 #if 0
171   gchar *cstr;
172   cstr = gtk_color_selection_palette_to_string(&tsin_phrase_line_gcolor, 1);
173   dbg("color %s\n", cstr);
174   save_hime_conf_str(TSIN_PHRASE_LINE_COLOR, cstr);
175   g_free(cstr);
176 #endif
177 
178     save_omni_config ();
179     /* caleb- does found where "reload kbm" is used.
180    * caleb- think the send_hime_message() here does nothing.
181    */
182     send_hime_message (GDK_DISPLAY (), "reload kbm");
183 }
184 
destroy_kbm_widget()185 void destroy_kbm_widget () {
186     gtk_widget_destroy (kbm_widget);
187     kbm_widget = NULL;
188 }
189 
190 #if 0
191 static void callback_button_clicked_tsin_sw( GtkWidget *widget, gpointer data)
192 {
193   new_select_idx_tsin_sw = (int) data;
194 }
195 #endif
196 
callback_button_clicked_tsin_space_opt(GtkWidget * widget,gpointer data)197 static void callback_button_clicked_tsin_space_opt (GtkWidget *widget, gpointer data) {
198     new_select_idx_tsin_space_opt = (gsize) data;
199 }
200 
get_current_kbm_idx()201 static int get_current_kbm_idx () {
202     int i;
203     for (i = 0; kbm_sel[i].kbm; i++)
204         if (!strcmp (kbm_sel[i].kbm, pho_kbm_name)) {
205             return i;
206         }
207 
208     p_err ("phonetic-keyboard->%s is not valid", pho_kbm_name);
209     return 0;
210 }
211 
get_currnet_eng_ch_sw_idx()212 static int get_currnet_eng_ch_sw_idx () {
213     int i;
214     for (i = 0; i < tsin_eng_ch_swN; i++)
215         if (tsin_eng_ch_sw[i].key == tsin_chinese_english_toggle_key)
216             return i;
217 
218     p_err ("tsin-chinese-english-switch->%d is not valid", tsin_chinese_english_toggle_key);
219     return -1;
220 }
221 
get_currnet_tsin_space_option_idx()222 static int get_currnet_tsin_space_option_idx () {
223     int i;
224     for (i = 0; i < tsin_space_optionsN; i++)
225         if (tsin_space_options[i].key == tsin_space_opt)
226             return i;
227 
228     p_err ("tsin-space-opt->%d is not valid", tsin_space_opt);
229     return -1;
230 }
231 
232 //static GtkWidget *da_phrase_line;
233 
234 #if 0
235 static void cb_save_tsin_phrase_line_color(GtkWidget *widget, gpointer user_data)
236 {
237   GtkColorSelectionDialog *color_selector = (GtkColorSelectionDialog *)user_data;
238   gtk_color_selection_get_current_color(GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(color_selector)), &tsin_phrase_line_gcolor);
239 
240 #if !GTK_CHECK_VERSION(2, 91, 6)
241   gtk_widget_modify_bg(da_phrase_line, GTK_STATE_NORMAL, &tsin_phrase_line_gcolor);
242 #else
243   GdkRGBA rgbbg;
244   gdk_rgba_parse(&rgbbg, gdk_color_to_string(&tsin_phrase_line_gcolor));
245   gtk_widget_override_background_color(da_phrase_line, GTK_STATE_FLAG_NORMAL, &rgbbg);
246 #endif
247 }
248 #endif
249 
create_kbm_opts()250 static GtkWidget *create_kbm_opts () {
251 
252     GtkWidget *hbox = gtk_hbox_new (FALSE, 1);
253 
254     opt_kbm_opts = gtk_combo_box_text_new ();
255     gtk_box_pack_start (GTK_BOX (hbox), opt_kbm_opts, FALSE, FALSE, 0);
256 
257     int i;
258     int current_idx = get_current_kbm_idx ();
259 
260     for (i = 0; kbm_sel[i].name; i++) {
261         gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (opt_kbm_opts), _ (kbm_sel[i].name));
262     }
263 
264     gtk_combo_box_set_active (GTK_COMBO_BOX (opt_kbm_opts), current_idx);
265 
266     opt_selkeys = gtk_combo_box_text_new ();
267     gtk_box_pack_start (GTK_BOX (hbox), opt_selkeys, FALSE, FALSE, 0);
268 
269     current_idx = 0;
270     for (i = 0; selkeys[i].kstr; i++) {
271         gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (opt_selkeys), selkeys[i].kstr);
272         if (!strcmp (selkeys[i].kstr, pho_selkey))
273             current_idx = i;
274     }
275 
276     gtk_combo_box_set_active (GTK_COMBO_BOX (opt_selkeys), current_idx);
277 
278     GtkAdjustment *adj =
279         (GtkAdjustment *) gtk_adjustment_new (pho_candidate_col_N, 1, 10, 1.0, 1.0, 0.0);
280     spinner_pho_candidate_col_N = gtk_spin_button_new (adj, 0, 0);
281     gtk_box_pack_start (GTK_BOX (hbox), spinner_pho_candidate_col_N, FALSE, FALSE, 0);
282 
283     return hbox;
284 }
285 
update_eng_ch_opts(GtkComboBox * widget,gpointer user_data)286 static void update_eng_ch_opts (GtkComboBox *widget, gpointer user_data) {
287     gint i;
288     gint idx = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
289     for (i = 0; i < 2; i++) {
290         if ((opt_eng_ch_opts[i]) && (opt_eng_ch_opts[i] != (GtkWidget *) widget))
291             gtk_combo_box_set_active (GTK_COMBO_BOX (opt_eng_ch_opts[i]), idx);
292     }
293 }
294 
create_eng_ch_opts(gint index)295 static GtkWidget *create_eng_ch_opts (gint index) {
296 
297     GtkWidget *hbox = gtk_hbox_new (FALSE, 1);
298 
299     opt_eng_ch_opts[index] = gtk_combo_box_text_new ();
300     g_signal_connect (G_OBJECT (opt_eng_ch_opts[index]), "changed", G_CALLBACK (update_eng_ch_opts), NULL);
301     gtk_box_pack_start (GTK_BOX (hbox), opt_eng_ch_opts[index], FALSE, FALSE, 0);
302 
303     int i;
304     int current_idx = get_currnet_eng_ch_sw_idx ();
305 
306     for (i = 0; i < tsin_eng_ch_swN; i++) {
307         gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (opt_eng_ch_opts[index]), _ (tsin_eng_ch_sw[i].name));
308     }
309 
310     dbg ("current_idx:%d\n", current_idx);
311 
312     gtk_combo_box_set_active (GTK_COMBO_BOX (opt_eng_ch_opts[index]), current_idx);
313 
314     return hbox;
315 }
316 
create_en_pho_key_sel(char * s,gint index)317 GtkWidget *create_en_pho_key_sel (char *s, gint index) {
318     GtkWidget *frame_tsin_sw = gtk_frame_new (s);
319     GtkWidget *vbox_tsin_sw = gtk_vbox_new (FALSE, 0);
320     gtk_orientable_set_orientation (GTK_ORIENTABLE (vbox_tsin_sw), GTK_ORIENTATION_VERTICAL);
321     gtk_container_add (GTK_CONTAINER (frame_tsin_sw), vbox_tsin_sw);
322     gtk_container_set_border_width (GTK_CONTAINER (frame_tsin_sw), 1);
323     gtk_container_add (GTK_CONTAINER (vbox_tsin_sw), create_eng_ch_opts (index));
324     GtkWidget *hbox_hime_capslock_lower = gtk_hbox_new (FALSE, 0);
325     gtk_box_pack_start (GTK_BOX (vbox_tsin_sw), hbox_hime_capslock_lower, FALSE, FALSE, 0);
326     check_button_hime_capslock_lower = gtk_check_button_new_with_label (_ ("Lower case when CapsLock is on"));
327     gtk_box_pack_start (GTK_BOX (hbox_hime_capslock_lower), check_button_hime_capslock_lower, FALSE, FALSE, 0);
328     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button_hime_capslock_lower), hime_capslock_lower);
329 
330     return frame_tsin_sw;
331 }
332 
333 void load_settings ();
334 
create_kbm_widget()335 GtkWidget *create_kbm_widget () {
336     if (kbm_widget != NULL)
337         fprintf (stderr, "create_kbm_widget: kbm_widget was not NULL!\n");
338 
339     load_settings ();
340 
341     GtkWidget *vbox_top = gtk_vbox_new (FALSE, 3);
342     gtk_orientable_set_orientation (GTK_ORIENTABLE (vbox_top), GTK_ORIENTATION_VERTICAL);
343     kbm_widget = vbox_top;
344 
345     GtkWidget *hbox_lr = gtk_hbox_new (FALSE, 0);
346     gtk_box_pack_start (GTK_BOX (vbox_top), hbox_lr, FALSE, FALSE, 0);
347 
348     GtkWidget *vbox_l = gtk_vbox_new (FALSE, 0);
349     gtk_orientable_set_orientation (GTK_ORIENTABLE (vbox_l), GTK_ORIENTATION_VERTICAL);
350     gtk_container_set_border_width (GTK_CONTAINER (vbox_l), 10);
351     gtk_box_pack_start (GTK_BOX (hbox_lr), vbox_l, TRUE, TRUE, 10);
352 
353     GtkWidget *vbox_r = gtk_vbox_new (FALSE, 0);
354     gtk_orientable_set_orientation (GTK_ORIENTABLE (vbox_r), GTK_ORIENTATION_VERTICAL);
355     gtk_container_set_border_width (GTK_CONTAINER (vbox_r), 10);
356     gtk_box_pack_start (GTK_BOX (hbox_lr), vbox_r, TRUE, TRUE, 10);
357 
358     GtkWidget *frame_kbm = gtk_frame_new (_ ("Keymap/Selection keys/Candidates per line"));
359     gtk_box_pack_start (GTK_BOX (vbox_l), frame_kbm, FALSE, FALSE, 0);
360     gtk_container_set_border_width (GTK_CONTAINER (frame_kbm), 1);
361     gtk_container_add (GTK_CONTAINER (frame_kbm), create_kbm_opts ());
362 
363     gtk_box_pack_start (GTK_BOX (vbox_l), create_en_pho_key_sel (_ ("(Tsin) Toggle [中/英] input"), 0), FALSE, FALSE, 0);
364 
365     GtkWidget *frame_tsin_space_opt = gtk_frame_new (_ ("(Tsin) When pressing spacebar..."));
366     gtk_box_pack_start (GTK_BOX (vbox_l), frame_tsin_space_opt, FALSE, FALSE, 0);
367     gtk_container_set_border_width (GTK_CONTAINER (frame_tsin_space_opt), 1);
368 
369     GtkWidget *box_tsin_space_opt = gtk_vbox_new (FALSE, 0);
370     gtk_orientable_set_orientation (GTK_ORIENTABLE (box_tsin_space_opt), GTK_ORIENTATION_VERTICAL);
371     gtk_container_add (GTK_CONTAINER (frame_tsin_space_opt), box_tsin_space_opt);
372     gtk_container_set_border_width (GTK_CONTAINER (box_tsin_space_opt), 1);
373 
374     GSList *group_tsin_space_opt = NULL;
375     int current_idx = get_currnet_tsin_space_option_idx ();
376     new_select_idx_tsin_space_opt = current_idx;
377 
378     gsize i;
379     for (i = 0; i < tsin_space_optionsN; i++) {
380         GtkWidget *button = gtk_radio_button_new_with_label (group_tsin_space_opt, _ (tsin_space_options[i].name));
381         gtk_box_pack_start (GTK_BOX (box_tsin_space_opt), button, FALSE, FALSE, 0);
382 
383         group_tsin_space_opt = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
384 
385         g_signal_connect (G_OBJECT (button), "clicked",
386                           G_CALLBACK (callback_button_clicked_tsin_space_opt), (gpointer) i);
387 
388         if (i == current_idx)
389             gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
390     }
391 
392     GtkWidget *hbox_tsin_phrase_pre_select = gtk_hbox_new (FALSE, 0);
393     gtk_box_pack_start (GTK_BOX (vbox_l), hbox_tsin_phrase_pre_select, FALSE, FALSE, 1);
394     check_button_tsin_phrase_pre_select = gtk_check_button_new_with_label (_ ("Enable preselection window in Tsin"));
395     gtk_box_pack_start (GTK_BOX (hbox_tsin_phrase_pre_select), check_button_tsin_phrase_pre_select, FALSE, FALSE, 0);
396     gtk_toggle_button_set_active (
397         GTK_TOGGLE_BUTTON (check_button_tsin_phrase_pre_select), tsin_phrase_pre_select);
398 
399     GtkWidget *hbox_phonetic_char_dynamic_sequence = gtk_hbox_new (FALSE, 0);
400     gtk_box_pack_start (GTK_BOX (vbox_l), hbox_phonetic_char_dynamic_sequence, FALSE, FALSE, 1);
401     check_button_phonetic_char_dynamic_sequence = gtk_check_button_new_with_label (_ ("Resorting choices by user's usage frequency"));
402     gtk_box_pack_start (GTK_BOX (hbox_phonetic_char_dynamic_sequence), check_button_phonetic_char_dynamic_sequence, FALSE, FALSE, 0);
403     gtk_toggle_button_set_active (
404         GTK_TOGGLE_BUTTON (check_button_phonetic_char_dynamic_sequence), phonetic_char_dynamic_sequence);
405 
406     GtkWidget *hbox_pho_hide_row2 = gtk_hbox_new (FALSE, 0);
407     gtk_box_pack_start (GTK_BOX (vbox_r), hbox_pho_hide_row2, FALSE, FALSE, 1);
408     check_button_pho_hide_row2 = gtk_check_button_new_with_label (_ ("Hide second row of Bopomofo's window"));
409     gtk_box_pack_start (GTK_BOX (hbox_pho_hide_row2), check_button_pho_hide_row2, FALSE, FALSE, 0);
410     gtk_toggle_button_set_active (
411         GTK_TOGGLE_BUTTON (check_button_pho_hide_row2), pho_hide_row2);
412 
413     GtkWidget *hbox_pho_in_row1 = gtk_hbox_new (FALSE, 0);
414     gtk_box_pack_start (GTK_BOX (vbox_r), hbox_pho_in_row1, FALSE, FALSE, 1);
415     check_button_pho_in_row1 = gtk_check_button_new_with_label (_ ("Move keycodes to first row of Bopomofo's window"));
416     gtk_box_pack_start (GTK_BOX (hbox_pho_in_row1), check_button_pho_in_row1, FALSE, FALSE, 0);
417     gtk_toggle_button_set_active (
418         GTK_TOGGLE_BUTTON (check_button_pho_in_row1), pho_in_row1);
419 
420     GtkWidget *hbox_phonetic_huge_tab = gtk_hbox_new (FALSE, 0);
421     gtk_box_pack_start (GTK_BOX (vbox_r), hbox_phonetic_huge_tab, FALSE, FALSE, 1);
422     check_button_phonetic_huge_tab = gtk_check_button_new_with_label (_ ("Enable more UTF-8 characters"));
423     gtk_box_pack_start (GTK_BOX (hbox_phonetic_huge_tab), check_button_phonetic_huge_tab, FALSE, FALSE, 0);
424     gtk_toggle_button_set_active (
425         GTK_TOGGLE_BUTTON (check_button_phonetic_huge_tab), phonetic_huge_tab);
426 
427     GtkWidget *hbox_tsin_tone_char_input = gtk_hbox_new (FALSE, 0);
428     gtk_box_pack_start (GTK_BOX (vbox_r), hbox_tsin_tone_char_input, FALSE, FALSE, 1);
429     check_button_tsin_tone_char_input = gtk_check_button_new_with_label (_ ("Enable tone symbols in Tsin"));
430     gtk_box_pack_start (GTK_BOX (hbox_tsin_tone_char_input), check_button_tsin_tone_char_input, FALSE, FALSE, 0);
431     gtk_toggle_button_set_active (
432         GTK_TOGGLE_BUTTON (check_button_tsin_tone_char_input), tsin_tone_char_input);
433 
434     GtkWidget *hbox_tsin_tab_phrase_end = gtk_hbox_new (FALSE, 1);
435     gtk_box_pack_start (GTK_BOX (vbox_r), hbox_tsin_tab_phrase_end, FALSE, FALSE, 1);
436     check_button_tsin_tab_phrase_end = gtk_check_button_new_with_label (_ ("Break sentence with Escape/Tab key"));
437     gtk_box_pack_start (GTK_BOX (hbox_tsin_tab_phrase_end), check_button_tsin_tab_phrase_end, FALSE, FALSE, 0);
438     gtk_toggle_button_set_active (
439         GTK_TOGGLE_BUTTON (check_button_tsin_tab_phrase_end), tsin_tab_phrase_end);
440 
441     GtkWidget *hbox_tsin_tail_select_key = gtk_hbox_new (FALSE, 0);
442     gtk_box_pack_start (GTK_BOX (vbox_r), hbox_tsin_tail_select_key, FALSE, FALSE, 1);
443     check_button_tsin_tail_select_key = gtk_check_button_new_with_label (_ ("Show selection key behind choices"));
444     gtk_box_pack_start (GTK_BOX (hbox_tsin_tail_select_key), check_button_tsin_tail_select_key, FALSE, FALSE, 0);
445     gtk_toggle_button_set_active (
446         GTK_TOGGLE_BUTTON (check_button_tsin_tail_select_key), tsin_tail_select_key);
447 
448     GtkWidget *hbox_tsin_buffer_editing_mode = gtk_hbox_new (FALSE, 0);
449     gtk_box_pack_start (GTK_BOX (vbox_r), hbox_tsin_buffer_editing_mode, FALSE, FALSE, 1);
450     check_button_tsin_buffer_editing_mode = gtk_check_button_new_with_label (_ ("\\ key to toggle jkx keys editing mode"));
451     gtk_box_pack_start (GTK_BOX (hbox_tsin_buffer_editing_mode), check_button_tsin_buffer_editing_mode, FALSE, FALSE, 0);
452     gtk_toggle_button_set_active (
453         GTK_TOGGLE_BUTTON (check_button_tsin_buffer_editing_mode), tsin_buffer_editing_mode);
454 
455     GtkWidget *hbox_tsin_use_pho_near = gtk_hbox_new (FALSE, 0);
456     gtk_box_pack_start (GTK_BOX (vbox_r), hbox_tsin_use_pho_near, FALSE, FALSE, 1);
457     check_button_tsin_use_pho_near = gtk_check_button_new_with_label (_ ("Press up-arrow to query similar pronunciation words"));
458     gtk_box_pack_start (GTK_BOX (hbox_tsin_use_pho_near), check_button_tsin_use_pho_near, FALSE, FALSE, 0);
459     gtk_toggle_button_set_active (
460         GTK_TOGGLE_BUTTON (check_button_tsin_use_pho_near), tsin_use_pho_near);
461 
462     GtkWidget *frame_tsin_buffer_size = gtk_frame_new (_ ("Tsin's buffer size"));
463     gtk_box_pack_start (GTK_BOX (vbox_r), frame_tsin_buffer_size, FALSE, FALSE, 0);
464     gtk_container_set_border_width (GTK_CONTAINER (frame_tsin_buffer_size), 1);
465     GtkAdjustment *adj_gtab_in =
466         (GtkAdjustment *) gtk_adjustment_new (tsin_buffer_size, 10.0, MAX_PH_BF, 1.0, 1.0, 0.0);
467     spinner_tsin_buffer_size = gtk_spin_button_new (adj_gtab_in, 0, 0);
468     gtk_container_add (GTK_CONTAINER (frame_tsin_buffer_size), spinner_tsin_buffer_size);
469 
470     return kbm_widget;
471 }
472