1 /*
2 
3   Copyright (c) 2005-2013 uim Project https://github.com/uim/uim
4 
5   All rights reserved.
6 
7   Redistribution and use in source and binary forms, with or without
8   modification, are permitted provided that the following conditions
9   are met:
10 
11   1. Redistributions of source code must retain the above copyright
12      notice, this list of conditions and the following disclaimer.
13   2. Redistributions in binary form must reproduce the above copyright
14      notice, this list of conditions and the following disclaimer in the
15      documentation and/or other materials provided with the distribution.
16   3. Neither the name of authors nor the names of its contributors
17      may be used to endorse or promote products derived from this software
18      without specific prior written permission.
19 
20   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
21   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
24   FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26   OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29   OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30   SUCH DAMAGE.
31 
32 */
33 
34 #include <config.h>
35 
36 #include <glib.h>
37 #include <gtk/gtk.h>
38 #if GTK_CHECK_VERSION(2, 90, 0)
39 # include <gdk/gdkkeysyms-compat.h>
40 #else
41 # include <gdk/gdkkeysyms.h>
42 #endif
43 
44 #include <string.h>
45 #include <stdlib.h>
46 #include <stdio.h>
47 #include <locale.h>
48 
49 #include "uim/uim.h"
50 #include "uim/uim-custom.h"
51 #include "uim/uim-scm.h"
52 #include "uim/gettext.h"
53 #include "gtk-custom-widgets.h"
54 #include "../immodule/key-util-gtk.h"
55 
56 #define DEFAULT_WINDOW_WIDTH_MAX 800
57 #define DEFAULT_WINDOW_HEIGHT_MAX 600
58 #define USE_CHANGES_SENSITIVE_OK_BUTTON 0
59 
60 static GtkWidget *pref_window = NULL;
61 static GtkWidget *pref_tree_view = NULL;
62 static GtkWidget *pref_hbox = NULL;
63 static GtkWidget *current_group_widget = NULL;
64 
65 gboolean uim_pref_gtk_value_changed = FALSE;
66 static GtkWidget *pref_apply_button = NULL;
67 static GtkWidget *pref_ok_button = NULL;
68 
69 enum
70 {
71   GROUP_COLUMN = 0,
72   GROUP_WIDGET = 1,
73   GROUP_SYM = 2,
74   NUM_COLUMNS
75 };
76 
77 void uim_pref_gtk_mark_value_changed(void);
78 void uim_pref_gtk_unmark_value_changed(void);
79 
80 static gboolean	pref_tree_selection_changed(GtkTreeSelection *selection,
81 					     gpointer data);
82 static GtkWidget *create_pref_treeview(void);
83 static GtkWidget *create_group_widget(const char *group_name);
84 static void create_sub_group_widgets(GtkWidget *parent_widget,
85 				     const char *parent_group);
86 
87 void
uim_pref_gtk_mark_value_changed(void)88 uim_pref_gtk_mark_value_changed(void)
89 {
90   uim_pref_gtk_value_changed = TRUE;
91   gtk_widget_set_sensitive(pref_apply_button, TRUE);
92 #if USE_CHANGES_SENSITIVE_OK_BUTTON
93   gtk_widget_set_sensitive(pref_ok_button, TRUE);
94 #endif
95 }
96 
97 void
uim_pref_gtk_unmark_value_changed(void)98 uim_pref_gtk_unmark_value_changed(void)
99 {
100   uim_pref_gtk_value_changed = FALSE;
101   gtk_widget_set_sensitive(pref_apply_button, FALSE);
102 #if USE_CHANGES_SENSITIVE_OK_BUTTON
103   gtk_widget_set_sensitive(pref_ok_button, FALSE);
104 #endif
105 }
106 
107 /*
108  *  2005-02-10 Takuro Ashie <ashie@homa.ne.jp>
109  *    This feature is disabled according to [Anthy-dev 1795].
110  */
111 #if 0
112 static void
113 save_confirm_dialog_response_cb(GtkDialog *dialog, gint arg, gpointer user_data)
114 {
115   switch (arg)
116   {
117   case GTK_RESPONSE_YES:
118     uim_custom_save();
119     uim_custom_broadcast();
120     uim_pref_gtk_value_changed = FALSE;
121     break;
122   case GTK_RESPONSE_NO:
123     uim_pref_gtk_value_changed = FALSE;
124     break;
125   default:
126     break;
127   }
128 }
129 #endif
130 
131 static gboolean
pref_tree_selection_changed(GtkTreeSelection * selection,gpointer data)132 pref_tree_selection_changed(GtkTreeSelection *selection,
133 			     gpointer data)
134 {
135   GtkTreeStore *store;
136   GtkTreeIter iter;
137   GtkTreeModel *model;
138   char *group_name, *group_sym;
139   GtkWidget *group_widget;
140 
141 /*
142  *  2005-02-10 Takuro Ashie <ashie@homa.ne.jp>
143  *    This feature is disabled according to [Anthy-dev 1795].
144  */
145 #if 0
146   /* Preference save check should be here. */
147   if (uim_pref_gtk_value_changed) {
148     GtkWidget *dialog;
149     dialog = gtk_message_dialog_new(NULL,
150 				    GTK_DIALOG_MODAL,
151 				    GTK_MESSAGE_QUESTION,
152 				    GTK_BUTTONS_YES_NO,
153 				    _("Some value(s) have been changed.\n"
154 				      "Save?"));
155     gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(pref_window));
156     gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER_ON_PARENT);
157     g_signal_connect(G_OBJECT(dialog), "response",
158 		     G_CALLBACK(save_confirm_dialog_response_cb), NULL);
159     gtk_dialog_run(GTK_DIALOG(dialog));
160     gtk_widget_destroy(dialog);
161   }
162 #endif
163 
164   if (gtk_tree_selection_get_selected(selection, &model, &iter) == FALSE)
165     return TRUE;
166 
167   store = GTK_TREE_STORE(model);
168   gtk_tree_model_get(model, &iter,
169 		     GROUP_COLUMN, &group_name,
170 		     GROUP_WIDGET, &group_widget,
171 		     GROUP_SYM, &group_sym,
172 		     -1);
173 
174   if (group_name == NULL)
175     return TRUE;
176 
177   if (group_widget == NULL) {
178     group_widget = create_group_widget(group_sym);
179     gtk_tree_store_set(store, &iter, GROUP_WIDGET, group_widget, -1);
180   }
181 
182   /* hide current selected group's widget */
183   if (current_group_widget)
184     gtk_widget_hide(current_group_widget);
185 
186   /* whether group_widget is already packed or not */
187   if (!gtk_widget_get_parent(group_widget))
188     gtk_box_pack_start (GTK_BOX (pref_hbox), group_widget, TRUE, TRUE, 0);
189 
190   /* show selected group's widget */
191   gtk_widget_show_all(group_widget);
192 
193   current_group_widget = group_widget;
194 
195   free(group_name);
196   free(group_sym);
197   return TRUE;
198 }
199 
200 
201 static void
quit_confirm_dialog_response_cb(GtkDialog * dialog,gint arg,gpointer user_data)202 quit_confirm_dialog_response_cb(GtkDialog *dialog, gint arg, gpointer user_data)
203 {
204   gboolean *quit = user_data;
205 
206   switch (arg)
207   {
208   case GTK_RESPONSE_YES:
209   case GTK_RESPONSE_OK:
210     *quit = TRUE;
211     break;
212   case GTK_RESPONSE_CANCEL:
213   case GTK_RESPONSE_NO:
214     *quit = FALSE;
215     break;
216   default:
217     break;
218   }
219 }
220 
221 static void
quit_confirm(void)222 quit_confirm(void)
223 {
224   if (uim_pref_gtk_value_changed) {
225     GtkWidget *dialog;
226     gboolean quit = FALSE;
227 
228     dialog = gtk_message_dialog_new(NULL,
229 				    GTK_DIALOG_MODAL,
230 				    GTK_MESSAGE_QUESTION,
231 				    GTK_BUTTONS_YES_NO,
232 				    "%s", _("Some value(s) have been changed.\n"
233 				      "Do you really quit this program?"));
234     gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(pref_window));
235     gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER_ON_PARENT);
236     g_signal_connect(G_OBJECT(dialog), "response",
237 		     G_CALLBACK(quit_confirm_dialog_response_cb), &quit);
238     gtk_dialog_run(GTK_DIALOG(dialog));
239     gtk_widget_destroy(dialog);
240 
241     if (quit)
242       gtk_main_quit();
243   } else {
244     gtk_main_quit();
245   }
246 }
247 
248 static gboolean
key_press_cb(GtkWidget * widget,GdkEventKey * event)249 key_press_cb(GtkWidget *widget, GdkEventKey *event)
250 {
251   if (event->keyval == GDK_Escape) {
252     quit_confirm();
253     return TRUE;
254   }
255 
256   return FALSE;
257 }
258 
259 static gint
delete_event_cb(GtkWidget * widget,gpointer data)260 delete_event_cb(GtkWidget *widget, gpointer data)
261 {
262   quit_confirm();
263   return TRUE;
264 }
265 
266 static GtkWidget *
create_pref_treeview(void)267 create_pref_treeview(void)
268 {
269   GtkTreeStore *tree_store;
270   GtkCellRenderer *renderer;
271   GtkTreeViewColumn *column;
272   GtkTreeIter iter;
273   char **primary_groups, **grp;
274   GtkTreeSelection *selection;
275   GtkTreePath *first_path;
276   tree_store = gtk_tree_store_new (NUM_COLUMNS,
277 				   G_TYPE_STRING,
278 				   GTK_TYPE_WIDGET,
279 				   G_TYPE_STRING);
280 
281   pref_tree_view = gtk_tree_view_new();
282 
283   renderer = gtk_cell_renderer_text_new();
284   column = gtk_tree_view_column_new_with_attributes(_("Group"),
285 						    renderer,
286 						    "text", GROUP_COLUMN,
287 						    (const gchar *)NULL);
288   gtk_tree_view_column_set_sort_column_id(column, 0);
289   gtk_tree_view_append_column(GTK_TREE_VIEW(pref_tree_view), column);
290 
291   primary_groups = uim_custom_primary_groups();
292   for (grp = primary_groups; *grp; grp++) {
293     struct uim_custom_group *group = uim_custom_group_get(*grp);
294     gtk_tree_store_append (tree_store, &iter, NULL/* parent iter */);
295     /* only set the widget of the first row for now */
296     if (grp == primary_groups) {
297       gtk_tree_store_set (tree_store, &iter,
298 			  GROUP_COLUMN, group->label,
299 			  GROUP_WIDGET, create_group_widget(*grp),
300 			  GROUP_SYM, *grp,
301 			  -1);
302     } else {
303       gtk_tree_store_set (tree_store, &iter,
304 			  GROUP_COLUMN, group->label,
305 			  GROUP_WIDGET, NULL,
306 			  GROUP_SYM, *grp,
307 			  -1);
308     }
309     uim_custom_group_free(group);
310   }
311   uim_custom_symbol_list_free( primary_groups );
312 
313   gtk_tree_view_set_model (GTK_TREE_VIEW(pref_tree_view),
314 			   GTK_TREE_MODEL(tree_store));
315   g_object_unref (tree_store);
316   gtk_tree_view_set_rules_hint (GTK_TREE_VIEW(pref_tree_view), TRUE);
317   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (pref_tree_view));
318   gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
319   g_signal_connect (G_OBJECT(selection), "changed",
320 		    G_CALLBACK(pref_tree_selection_changed), NULL);
321 
322   first_path = gtk_tree_path_new_from_indices (0, -1);
323 
324   gtk_tree_view_set_cursor(GTK_TREE_VIEW(pref_tree_view),
325 			   first_path, NULL, FALSE);
326 
327   return pref_tree_view;
328 }
329 
330 static void
ok_button_clicked(GtkButton * button,gpointer user_data)331 ok_button_clicked(GtkButton *button, gpointer user_data)
332 {
333   /*const char *group_name = user_data;*/
334 
335   if (uim_pref_gtk_value_changed) {
336     uim_custom_save();
337     uim_custom_broadcast_reload_request();
338     uim_pref_gtk_unmark_value_changed();
339   }
340 
341   gtk_main_quit();
342 }
343 
344 static void
apply_button_clicked(GtkButton * button,gpointer user_data)345 apply_button_clicked(GtkButton *button, gpointer user_data)
346 {
347   /*const char *group_name = user_data;*/
348 
349   if (uim_pref_gtk_value_changed) {
350     uim_custom_save();
351     uim_custom_broadcast_reload_request();
352     uim_pref_gtk_unmark_value_changed();
353   }
354 }
355 
356 static void
set_to_default_cb(GtkWidget * widget,gpointer data)357 set_to_default_cb(GtkWidget *widget, gpointer data)
358 {
359   uim_pref_gtk_set_default_value(widget);
360 
361   if (GTK_IS_CONTAINER(widget))
362     gtk_container_foreach(GTK_CONTAINER(widget),
363 			  (GtkCallback) (set_to_default_cb), NULL);
364   uim_pref_gtk_mark_value_changed();
365 }
366 
367 static void
defaults_button_clicked(GtkButton * button,gpointer user_data)368 defaults_button_clicked(GtkButton *button, gpointer user_data)
369 {
370   gtk_container_foreach(GTK_CONTAINER(current_group_widget),
371 			(GtkCallback) (set_to_default_cb), NULL);
372 }
373 
374 static GtkWidget *
create_setting_button_box(const char * group_name)375 create_setting_button_box(const char *group_name)
376 {
377   GtkWidget *setting_button_box;
378   GtkWidget *button;
379 
380 #if GTK_CHECK_VERSION(3, 2, 0)
381   setting_button_box = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
382 #else
383   setting_button_box = gtk_hbutton_box_new();
384 #endif
385   gtk_button_box_set_layout(GTK_BUTTON_BOX(setting_button_box), GTK_BUTTONBOX_END);
386   gtk_box_set_spacing(GTK_BOX(setting_button_box), 8);
387 
388   /* Defaults button */
389   button = gtk_button_new_with_mnemonic(_("_Defaults"));
390   g_signal_connect(G_OBJECT(button), "clicked",
391 		   G_CALLBACK(defaults_button_clicked), (gpointer) group_name);
392   gtk_box_pack_start(GTK_BOX(setting_button_box), button, TRUE, TRUE, 8);
393   gtk_widget_set_tooltip_text(button, _("Revert all changes to default"));
394 
395 
396   /* Apply button */
397   pref_apply_button = gtk_button_new_from_stock(GTK_STOCK_APPLY);
398   g_signal_connect(G_OBJECT(pref_apply_button), "clicked",
399 		   G_CALLBACK(apply_button_clicked), (gpointer) group_name);
400   gtk_widget_set_sensitive(pref_apply_button, FALSE);
401   gtk_box_pack_start(GTK_BOX(setting_button_box), pref_apply_button, TRUE, TRUE, 8);
402   gtk_widget_set_tooltip_text(pref_apply_button, _("Apply all changes"));
403 
404   /* Cancel button */
405   button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
406   g_signal_connect(G_OBJECT(button), "clicked",
407 		   G_CALLBACK(quit_confirm), NULL);
408   gtk_box_pack_start(GTK_BOX(setting_button_box), button, TRUE, TRUE, 8);
409   gtk_widget_set_tooltip_text(button, _("Quit this application without applying changes"));
410 
411   /* OK button */
412   pref_ok_button = gtk_button_new_from_stock(GTK_STOCK_OK);
413   g_signal_connect(G_OBJECT(pref_ok_button), "clicked",
414 		   G_CALLBACK(ok_button_clicked), (gpointer) group_name);
415   gtk_box_pack_start(GTK_BOX(setting_button_box), pref_ok_button, TRUE, TRUE, 8);
416 #if USE_CHANGES_SENSITIVE_OK_BUTTON
417   gtk_widget_set_sensitive(pref_ok_button, FALSE);
418 #endif
419   gtk_widget_set_tooltip_text(pref_ok_button, _("Quit this application with applying changes"));
420 
421   return setting_button_box;
422 }
423 
424 static GtkWidget *
create_group_widget(const char * group_name)425 create_group_widget(const char *group_name)
426 {
427   GtkWidget *scrolled_win;
428   GtkWidget *vbox;
429   GtkWidget *group_label;
430   struct uim_custom_group *group;
431   char *label_text;
432 
433   scrolled_win = gtk_scrolled_window_new(NULL, NULL);
434   gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_win),
435 				 GTK_POLICY_NEVER,
436 				 GTK_POLICY_AUTOMATIC);
437 #if GTK_CHECK_VERSION(3, 2, 0)
438   vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8);
439 #else
440   vbox = gtk_vbox_new(FALSE, 8);
441 #endif
442 #if GTK_CHECK_VERSION(3, 8, 0)
443   gtk_container_add(GTK_CONTAINER(scrolled_win), vbox);
444 #else
445   gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_win),
446 					vbox);
447 #endif
448 
449   gtk_container_set_border_width(GTK_CONTAINER(vbox), 4);
450 
451   group = uim_custom_group_get(group_name);
452 
453   if (group == NULL)
454     return NULL;
455 
456   group_label = gtk_label_new("");
457   label_text  = g_markup_printf_escaped("<span size=\"xx-large\">%s</span>",
458 					group->label);
459   gtk_label_set_markup(GTK_LABEL(group_label), label_text);
460   g_free(label_text);
461 
462   gtk_box_pack_start (GTK_BOX(vbox), group_label, FALSE, TRUE, 8);
463 
464   create_sub_group_widgets(vbox, group_name);
465 
466   uim_custom_group_free(group);
467 
468   return scrolled_win;
469 }
470 
create_sub_group_widgets(GtkWidget * parent_widget,const char * parent_group)471 static void create_sub_group_widgets(GtkWidget *parent_widget, const char *parent_group)
472 {
473     char **sgrp_syms = uim_custom_group_subgroups(parent_group);
474     char **sgrp_sym;
475 
476     for (sgrp_sym = sgrp_syms; *sgrp_sym; sgrp_sym++)
477     {
478         struct uim_custom_group *sgrp =  uim_custom_group_get(*sgrp_sym);
479 	char **custom_syms, **custom_sym;
480 	GString *sgrp_str;
481 	GtkWidget *frame;
482 	GtkWidget *vbox;
483 
484 	if (!sgrp)
485 	  continue;
486 
487 	/* XXX quick hack to use AND expression of groups */
488 	sgrp_str = g_string_new("");
489 	g_string_printf(sgrp_str, "%s '%s", parent_group, *sgrp_sym);
490 	custom_syms = uim_custom_collect_by_group(sgrp_str->str);
491 	g_string_free(sgrp_str, TRUE);
492 
493 	if (!custom_syms)
494 	  continue;
495 	if (!*custom_syms) {
496 	  uim_custom_symbol_list_free(custom_syms);
497 	  continue;
498 	}
499 
500 #if GTK_CHECK_VERSION(3, 2, 0)
501 	vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8);
502 #else
503 	vbox = gtk_vbox_new(FALSE, 8);
504 #endif
505 	if (strcmp(*sgrp_sym, "main")) {
506 	  frame = gtk_frame_new(sgrp->label);
507 	  gtk_frame_set_label_align(GTK_FRAME(frame), 0.02, 0.5);
508 	  gtk_box_pack_start(GTK_BOX(parent_widget), frame, FALSE, FALSE, 0);
509 
510 	  gtk_container_add(GTK_CONTAINER(frame), vbox);
511 	} else {
512 
513 	  /*
514 	   * Removing frame for 'main' subgroup. If you feel it
515 	   * strange, Replace it as you favor.  -- YamaKen 2005-02-06
516 	   */
517 	  gtk_box_pack_start(GTK_BOX(parent_widget), vbox, FALSE, FALSE, 0);
518 	}
519 
520 	gtk_container_set_border_width(GTK_CONTAINER(vbox), 6);
521 
522 	for (custom_sym = custom_syms; *custom_sym; custom_sym++) {
523 	  uim_pref_gtk_add_custom(vbox, *custom_sym);
524 	}
525 	uim_custom_symbol_list_free(custom_syms);
526 
527 	uim_custom_group_free(sgrp);
528     }
529 
530     uim_custom_symbol_list_free(sgrp_syms);
531 }
532 
533 static GtkWidget *
create_pref_window(void)534 create_pref_window(void)
535 {
536   GtkWidget *window;
537   GtkWidget *scrolled_win; /* treeview container */
538   GtkWidget *vbox;
539   GdkPixbuf *icon;
540 
541   pref_window = window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
542 
543   icon = gdk_pixbuf_new_from_file(UIM_PIXMAPSDIR"/uim-icon.png", NULL);
544   gtk_window_set_icon(GTK_WINDOW(pref_window), icon);
545 
546   g_signal_connect(G_OBJECT (window), "delete_event",
547 		   G_CALLBACK (delete_event_cb), NULL);
548   g_signal_connect(G_OBJECT (window), "key_press_event",
549 		   G_CALLBACK (key_press_cb), NULL);
550 
551 
552 #if GTK_CHECK_VERSION(3, 2, 0)
553   pref_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
554 #else
555   pref_hbox = gtk_hbox_new(FALSE, 8);
556 #endif
557 
558   scrolled_win = gtk_scrolled_window_new(NULL, NULL);
559   gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_win),
560 				      GTK_SHADOW_ETCHED_IN);
561   gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_win),
562 				 GTK_POLICY_NEVER,
563 				 GTK_POLICY_AUTOMATIC);
564   gtk_box_pack_start(GTK_BOX(pref_hbox), scrolled_win, FALSE, TRUE, 0);
565 
566   gtk_container_add(GTK_CONTAINER(scrolled_win), create_pref_treeview());
567 
568 #if GTK_CHECK_VERSION(3, 2, 0)
569   vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8);
570 #else
571   vbox = gtk_vbox_new(FALSE, 8);
572 #endif
573   gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
574   gtk_box_pack_start(GTK_BOX(vbox), pref_hbox, TRUE, TRUE, 0);
575   gtk_box_pack_start(GTK_BOX(vbox), create_setting_button_box("dummy-group-name"), FALSE, TRUE, 0);
576   gtk_container_add(GTK_CONTAINER(window), vbox);
577 
578   {
579     GdkScreen *scr;
580     gint w, h;
581 
582     scr = gtk_window_get_screen(GTK_WINDOW(window));
583     w = CLAMP(gdk_screen_get_width(scr)  * 0.95, 0, DEFAULT_WINDOW_WIDTH_MAX);
584     h = CLAMP(gdk_screen_get_height(scr) * 0.95, 0, DEFAULT_WINDOW_HEIGHT_MAX);
585     gtk_window_set_default_size(GTK_WINDOW(window), w, h);
586     gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER_ALWAYS);
587   }
588 
589   return window;
590 }
591 
592 static gboolean
check_dot_uim_file(void)593 check_dot_uim_file(void)
594 {
595   GString *dot_uim;
596   GtkWidget *dialog;
597   const gchar *message =
598     N_("The user customize file \"~/.uim\" is found.\n"
599        "This file will override all conflicted settings set by\n"
600        "this tool (stored in ~/.uim.d/customs/*.scm).\n"
601        "Please check the file if you find your settings aren't applied.\n\n"
602        "(To suppress this dialog, add following line to ~/.uim)\n"
603        "(define uim-pref-suppress-dot-uim-warning-dialog? #t)");
604   uim_bool suppress_dialog;
605 
606   suppress_dialog = uim_scm_symbol_value_bool("uim-pref-suppress-dot-uim-warning-dialog?");
607   if (suppress_dialog) {
608     return FALSE;
609   }
610 
611   dot_uim = g_string_new(g_get_home_dir());
612   g_string_append(dot_uim, "/.uim");
613 
614   if (!g_file_test(dot_uim->str, G_FILE_TEST_EXISTS)) {
615     g_string_free(dot_uim, TRUE);
616     return FALSE;
617   }
618   g_string_free(dot_uim, TRUE);
619 
620   dialog = gtk_message_dialog_new(NULL,
621 				  GTK_DIALOG_MODAL,
622 				  GTK_MESSAGE_WARNING,
623 				  GTK_BUTTONS_OK,
624 				  "%s", _(message));
625   if (pref_window) {
626     gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(pref_window));
627     gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER_ON_PARENT);
628   }
629 
630   gtk_dialog_run(GTK_DIALOG(dialog));
631   gtk_widget_destroy(GTK_WIDGET(dialog));
632 
633   return FALSE;
634 }
635 
636 int
main(int argc,char * argv[])637 main(int argc, char *argv[])
638 {
639   setlocale(LC_ALL, "");
640   bindtextdomain(PACKAGE, LOCALEDIR);
641   textdomain(PACKAGE);
642   bind_textdomain_codeset(PACKAGE, "UTF-8");
643 
644   gtk_init(&argc, &argv);
645 
646   if (uim_init() < 0) {
647     fprintf(stderr, "uim_init() failed.\n");
648     return -1;
649   }
650 
651   if (uim_custom_enable()) {
652     GtkWidget *pref;
653 
654     im_uim_init_modifier_keys();
655     g_idle_add((GSourceFunc) check_dot_uim_file, NULL);
656     pref = create_pref_window();
657     gtk_widget_show_all(pref);
658 
659     gtk_main();
660   } else {
661     fprintf(stderr, "uim_custom_enable() failed.\n");
662     uim_quit();
663     return -1;
664   }
665 
666   uim_quit();
667   return 0;
668 }
669