1 /*
2 * Copyright (C) 2020 The HIME team, Taiwan
3 * Copyright (C) 2011 Edward Der-Hua Liu, Hsin-Chu, Taiwan
4 * Copyright (C) 2012 tytsim <https://github.com/tytsim>
5 * Copyright (C) 2012 Favonia <favonia@gmail.com>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation version 2.1
10 * of the License.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include <signal.h>
23
24 #include "hime.h"
25
26 #include "gtab.h"
27 #include "lang.h"
28
29 GtkWidget *main_window;
30 extern gboolean button_order;
31 char utf8_edit[] = HIME_SCRIPT_DIR "/utf8-edit";
32
cb_alt_shift()33 static void cb_alt_shift () {
34 char tt[512];
35 snprintf (tt, sizeof (tt), "( cd ~/.config/hime && %s phrase.table ) &", utf8_edit);
36 system (tt);
37 }
38
cb_symbol_table()39 static void cb_symbol_table () {
40 char tt[512];
41 snprintf (tt, sizeof (tt), "( cd ~/.config/hime && %s symbol-table ) &", utf8_edit);
42 system (tt);
43 }
44
cb_gb_output_toggle()45 static void cb_gb_output_toggle () {
46 send_hime_message (GDK_DISPLAY (), GB_OUTPUT_TOGGLE);
47 exit (0);
48 }
49
cb_win_kbm_toggle()50 static void cb_win_kbm_toggle () {
51 send_hime_message (GDK_DISPLAY (), KBM_TOGGLE);
52 exit (0);
53 }
54
cb_gb_translate_toggle()55 static void cb_gb_translate_toggle () {
56 system (HIME_BIN_DIR "/hime-sim2trad &");
57 exit (0);
58 }
59
cb_juying_learn()60 static void cb_juying_learn () {
61 system (HIME_BIN_DIR "/hime-juyin-learn &");
62 exit (0);
63 }
64
create_result_win(const int res,const char * cmd)65 static void create_result_win (const int res, const char *cmd) {
66 GtkWidget *dialog = NULL;
67 if (res) {
68 dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
69 "%s code:%d '%s'\n%s", _ ("Failed"), res, strerror (res), cmd);
70 } else {
71 dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_OK,
72 _ ("Success"));
73 }
74 if (dialog == NULL)
75 exit (-1);
76
77 gtk_dialog_run (GTK_DIALOG (dialog));
78 gtk_widget_destroy (dialog);
79 }
80
cb_ts_export()81 static void cb_ts_export () {
82 GtkWidget *file_selector =
83 gtk_file_chooser_dialog_new (
84 _ ("Please input filename for exporting data"),
85 GTK_WINDOW (main_window),
86 GTK_FILE_CHOOSER_ACTION_SAVE,
87 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
88 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
89 NULL);
90
91 gtk_dialog_set_alternative_button_order (
92 GTK_DIALOG (file_selector),
93 GTK_RESPONSE_ACCEPT,
94 GTK_RESPONSE_CANCEL,
95 -1);
96
97 char hime_dir[512];
98 get_hime_dir (hime_dir);
99 char cmd[512];
100 char fname[256];
101 char *filename = inmd[default_input_method].filename;
102 char tt[256];
103 if (inmd[default_input_method].method_type == method_type_TSIN) {
104 get_hime_user_fname (tsin32_f, fname);
105 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (file_selector), tsin32_f);
106 } else if (filename) {
107 strcat (strcpy (tt, filename), ".append.gtab.tsin-db");
108 if (!get_hime_user_fname (tt, fname)) {
109 strcat (strcpy (tt, filename), ".tsin-db");
110 if (!get_hime_user_fname (tt, fname))
111 p_err ("cannot find %s", fname);
112 }
113 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (file_selector), tt);
114 }
115
116 gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (file_selector), TRUE);
117 if (gtk_dialog_run (GTK_DIALOG (file_selector)) == GTK_RESPONSE_ACCEPT) {
118 gchar *selected_filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (file_selector));
119 snprintf (cmd, sizeof (cmd), HIME_BIN_DIR "/hime-tsd2a32 %s -o %s", fname, selected_filename);
120 dbg ("exec %s\n", cmd);
121 int res = system (cmd);
122 res = 0; // some problem in system(), the exit code is not reliable
123 create_result_win (res, cmd);
124 }
125 gtk_widget_destroy (file_selector);
126 }
127
ts_import(const gchar * selected_filename)128 static void ts_import (const gchar *selected_filename) {
129 char cmd[256];
130 char *home = getenv ("HOME");
131 if (!home)
132 home = "";
133 if (inmd[default_input_method].method_type == method_type_TSIN) {
134 snprintf (cmd, sizeof (cmd),
135 "cd %s/.config/hime && " HIME_BIN_DIR "/hime-tsd2a32 %s > tmpfile && cat %s >> tmpfile && " HIME_BIN_DIR "/hime-tsa2d32 tmpfile %s",
136 home, tsin32_f, selected_filename, tsin32_f);
137 int res = system (cmd);
138 res = 0;
139 create_result_win (res, cmd);
140 } else {
141 char tt[512];
142 snprintf (tt, sizeof (tt), HIME_SCRIPT_DIR "/tsin-gtab-import %s '%s'", inmd[default_input_method].filename,
143 selected_filename);
144 system (tt);
145 }
146 }
147
cb_ts_import()148 static void cb_ts_import () {
149 /* Create the selector */
150
151 GtkWidget *file_selector =
152 gtk_file_chooser_dialog_new (
153 _ ("Please input filename for importing data"),
154 GTK_WINDOW (main_window),
155 GTK_FILE_CHOOSER_ACTION_OPEN,
156 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
157 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
158 NULL);
159
160 gtk_dialog_set_alternative_button_order (
161 GTK_DIALOG (file_selector),
162 GTK_RESPONSE_ACCEPT,
163 GTK_RESPONSE_CANCEL,
164 -1);
165
166 if (gtk_dialog_run (GTK_DIALOG (file_selector)) == GTK_RESPONSE_ACCEPT) {
167 gchar *selected_filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (file_selector));
168
169 ts_import (selected_filename);
170 }
171 gtk_widget_destroy (file_selector);
172 }
173
cb_ts_edit()174 static void cb_ts_edit () {
175 system (HIME_BIN_DIR "/hime-ts-edit");
176 }
177
cb_tslearn()178 static void cb_tslearn () {
179 system ("hime-tslearn &");
180 exit (0);
181 }
182
cb_ts_import_sys()183 static void cb_ts_import_sys () {
184 char tt[512];
185 snprintf (tt, sizeof (tt), "cd ~/.config/hime && " HIME_BIN_DIR "/hime-tsd2a32 %s > tmpfile && " HIME_BIN_DIR "/hime-tsd2a32 %s/%s >> tmpfile && " HIME_BIN_DIR "/hime-tsa2d32 tmpfile",
186 tsin32_f, HIME_TABLE_DIR, tsin32_f);
187 dbg ("exec %s\n", tt);
188 system (tt);
189 }
190
191 /* XXX */
192 #include "gst.h"
193 #include "hime-module-cb.h"
194 #include "hime-module.h"
195 #include "im-client/hime-im-client-attr.h"
196 #include "pho.h"
197 #include "tsin.h"
198 HIME_module_callback_functions *init_HIME_module_callback_functions (char *sofile);
199
200 /* The type of the entries in the table.
201 * XXX XXX XXX XXX XXX XXX XXX XXX XXX */
202 typedef struct {
203 const char *name;
204 GtkWidget *(*create) ();
205 void (*save) ();
206 void (*destroy) ();
207 } TAB_ENTRY;
208
209 /* XXX hime-setup-gtab.c */
210 GtkWidget *create_gtab_widget ();
211 void save_gtab_conf ();
212 void destroy_gtab_widget ();
213
214 /* XXX hime-setup-appearance.c */
215 GtkWidget *create_appearance_widget ();
216 void save_appearance_conf ();
217 void destroy_appearance_widget ();
218
219 /* XXX hime-setup-pho.c */
220 GtkWidget *create_kbm_widget ();
221 void save_kbm_conf ();
222 void destroy_kbm_widget ();
223
224 /* XXX hime-setup-list.c */
225 GtkWidget *create_gtablist_widget ();
226 void save_gtablist_conf ();
227 void destroy_gtablist_widget ();
228
229 GtkWidget *misc_widget = NULL;
230
pack_start_new_button_with_callback(GtkBox * box,const gchar * label,GCallback cb,gpointer * user_data)231 static void pack_start_new_button_with_callback (
232 GtkBox *box,
233 const gchar *label,
234 GCallback cb,
235 gpointer *user_data) {
236 GtkWidget *button = gtk_button_new_with_label (label);
237 if (button == NULL)
238 exit (-1);
239 gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 5);
240 g_signal_connect (G_OBJECT (button), "clicked", cb, user_data);
241 }
242
create_misc_widget(void)243 static GtkWidget *create_misc_widget (void) {
244 GtkWidget *top_widget = gtk_vbox_new (FALSE, 5);
245 gtk_orientable_set_orientation (GTK_ORIENTABLE (top_widget), GTK_ORIENTATION_VERTICAL);
246
247 pack_start_new_button_with_callback (GTK_BOX (top_widget),
248 _ ("Edit Alt-Shift phrases"), G_CALLBACK (cb_alt_shift), NULL);
249
250 pack_start_new_button_with_callback (GTK_BOX (top_widget),
251 _ ("Edit symbols"), G_CALLBACK (cb_symbol_table), NULL);
252
253 if (!hime_status_tray) {
254 pack_start_new_button_with_callback (GTK_BOX (top_widget),
255 _ ("Toggle Simplified Chinese output"), G_CALLBACK (cb_gb_output_toggle), NULL);
256
257 pack_start_new_button_with_callback (GTK_BOX (top_widget),
258 _ ("Toggle virtual keyboard"), G_CALLBACK (cb_win_kbm_toggle), NULL);
259 }
260
261 pack_start_new_button_with_callback (GTK_BOX (top_widget),
262 _ ("Convert clipboard's Simplified Chinese to Traditional Chinese"), G_CALLBACK (cb_gb_translate_toggle), NULL);
263
264 pack_start_new_button_with_callback (GTK_BOX (top_widget),
265 _ ("Lookup phonations of words in clipboard"), G_CALLBACK (cb_juying_learn), NULL);
266
267 GtkWidget *frame_ts = gtk_frame_new (_ ("Options for Tsin's database"));
268 gtk_box_pack_start (GTK_BOX (top_widget), frame_ts, FALSE, FALSE, 5);
269 GtkWidget *vbox_ts = gtk_vbox_new (FALSE, 5);
270 gtk_orientable_set_orientation (GTK_ORIENTABLE (vbox_ts), GTK_ORIENTATION_VERTICAL);
271 gtk_container_add (GTK_CONTAINER (frame_ts), vbox_ts);
272
273 pack_start_new_button_with_callback (GTK_BOX (vbox_ts),
274 _ ("Export phrase database"), G_CALLBACK (cb_ts_export), NULL);
275
276 pack_start_new_button_with_callback (GTK_BOX (vbox_ts),
277 _ ("Import phrase database"), G_CALLBACK (cb_ts_import), NULL);
278
279 pack_start_new_button_with_callback (GTK_BOX (vbox_ts),
280 _ ("Edit phrase database"), G_CALLBACK (cb_ts_edit), NULL);
281
282 pack_start_new_button_with_callback (GTK_BOX (vbox_ts),
283 _ ("Learn phrases in articles"), G_CALLBACK (cb_tslearn), NULL);
284
285 pack_start_new_button_with_callback (GTK_BOX (vbox_ts),
286 _ ("Import global database"), G_CALLBACK (cb_ts_import_sys), NULL);
287
288 int i;
289 for (i = 0; i < inmdN; i++) {
290 INMD *pinmd = &inmd[i];
291 if (pinmd->method_type != method_type_MODULE || pinmd->disabled)
292 continue;
293
294 HIME_module_callback_functions *f = init_HIME_module_callback_functions (pinmd->filename);
295 if (!f)
296 continue;
297
298 if (!f->module_setup_window_create) {
299 free (f);
300 continue;
301 }
302
303 char tt[128];
304 strcpy (tt, pinmd->cname);
305 strcat (tt, _ ("Configuration"));
306 pack_start_new_button_with_callback (GTK_BOX (top_widget),
307 tt, G_CALLBACK (f->module_setup_window_create), GINT_TO_POINTER (hime_setup_window_type_utility));
308 }
309
310 return top_widget;
311 }
312
dummy()313 static void dummy () {}
314
315 /* The table defining all tabs */
316 #define TAB_TABLE_SIZE 5
317 static TAB_ENTRY tab_table[TAB_TABLE_SIZE] =
318 {{N_ ("開啟/關閉/預設輸入法"), create_gtablist_widget, save_gtablist_conf, destroy_gtablist_widget}, {N_ ("Appearance Settings"), create_appearance_widget, save_appearance_conf, destroy_appearance_widget}, {N_ ("Settings for Bopomofo, Tsin, and Pinyin"), create_kbm_widget, save_kbm_conf, destroy_kbm_widget}, {N_ ("Settings for gtab input methods"), create_gtab_widget, save_gtab_conf, destroy_gtab_widget}, {N_ ("雜項"), create_misc_widget, dummy, dummy}};
319
save_all_tabs(void)320 static void save_all_tabs (void) {
321 int i = 0; /* non-C99 */
322 for (i = 0; i < TAB_TABLE_SIZE; i++)
323 tab_table[i].save ();
324 }
325
destroy_all_tabs(void)326 static void destroy_all_tabs (void) {
327 int i = 0; /* non-C99 */
328 for (i = 0; i < TAB_TABLE_SIZE; i++)
329 tab_table[i].destroy ();
330 }
331
dialog_response_handler(GtkDialog * dialog,gint response,gpointer user_data)332 static void dialog_response_handler (GtkDialog *dialog,
333 gint response,
334 gpointer user_data) {
335 switch (response) {
336 case GTK_RESPONSE_OK:
337 save_all_tabs ();
338 break;
339 default:
340 break;
341 }
342
343 /* Clean up */
344 destroy_all_tabs ();
345 gtk_main_quit ();
346 }
347
run_dialog(void)348 static void run_dialog (void) {
349 /* Create the notebook. */
350 GtkWidget *notebook = gtk_notebook_new ();
351 if (notebook == NULL) {
352 fprintf (stderr, "notebook == NULL?!\n");
353 exit (-1);
354 }
355
356 /* Put tabs into the notebook. */
357 int i = 0; /* non-C99 */
358 for (i = 0; i < TAB_TABLE_SIZE; i++) {
359 GtkWidget *child = tab_table[i].create ();
360 if (child == NULL) {
361 fprintf (stderr, "[%d] child == NULL?!\n", i);
362 exit (-1);
363 }
364
365 GtkWidget *label = gtk_label_new (_ (tab_table[i].name));
366 if (label == NULL) {
367 fprintf (stderr, "[%d] label == NULL?! (%s translated to %s)\n", i, tab_table[i].name, _ (tab_table[i].name));
368 exit (-1);
369 }
370
371 if (gtk_notebook_append_page (GTK_NOTEBOOK (notebook), child, label) == -1) {
372 fprintf (stderr, "[%d] append_page\n", i);
373 exit (-1);
374 }
375 }
376
377 /* Create the dialog */
378 GtkWidget *dialog = gtk_dialog_new_with_buttons (
379 _ ("hime setup"),
380 NULL,
381 GTK_DIALOG_DESTROY_WITH_PARENT,
382 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
383 GTK_STOCK_OK, GTK_RESPONSE_OK,
384 NULL);
385 if (dialog == NULL) {
386 fprintf (stderr, "dialog == NULL?!\n");
387 exit (-1);
388 }
389
390 /* Alternative button order when button-orde = 1 */
391 gtk_dialog_set_alternative_button_order (
392 GTK_DIALOG (dialog),
393 GTK_RESPONSE_OK,
394 GTK_RESPONSE_CANCEL,
395 -1);
396
397 /* Put the notebook into the dialog. */
398 GtkWidget *content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
399 gtk_container_add (GTK_CONTAINER (content_area), notebook);
400
401 /* Run the dialog and save the setting when 'OK' is clicked. */
402 g_signal_connect_swapped (
403 dialog,
404 "response",
405 G_CALLBACK (dialog_response_handler),
406 NULL);
407
408 gtk_widget_show_all (dialog);
409 }
410
411 void exec_setup_scripts ();
412
main(int argc,char ** argv)413 int main (int argc, char **argv) {
414 set_is_chs ();
415
416 exec_setup_scripts ();
417
418 init_TableDir ();
419
420 load_settings ();
421
422 load_gtab_list (FALSE);
423
424 gtk_init (&argc, &argv);
425
426 #if HIME_I18N_MESSAGE
427 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
428 textdomain (GETTEXT_PACKAGE);
429 #endif
430
431 g_object_get (gtk_settings_get_default (), "gtk-alternative-button-order", &button_order, NULL);
432
433 #if 0
434 // once you invoke hime-setup, the left-right buton tips is disabled
435 save_hime_conf_int(LEFT_RIGHT_BUTTON_TIPS, 0);
436 #endif
437
438 run_dialog ();
439 gtk_main ();
440 return 0;
441 }
442