"Fossies" - the Fresh Open Source Software Archive

Member "jpilot-2_0_1/jpilot.c" (3 Apr 2021, 74351 Bytes) of package /linux/privat/jpilot-2_0_1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "jpilot.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.8.2_vs_2_0_1.

    1 /*******************************************************************************
    2  * jpilot.c
    3  * A module of J-Pilot http://jpilot.org
    4  *
    5  * Copyright (C) 1999-2014 by Judd Montgomery
    6  *
    7  * This program is free software; you can redistribute it and/or modify
    8  * it under the terms of the GNU General Public License as published by
    9  * the Free Software Foundation; version 2 of the License.
   10  *
   11  * This program 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
   14  * GNU General Public License for more details.
   15  *
   16  * You should have received a copy of the GNU General Public License
   17  * along with this program; if not, write to the Free Software
   18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   19  ******************************************************************************/
   20 
   21 /********************************* Includes ***********************************/
   22 #include "config.h"
   23 #include <time.h>
   24 #include <stdio.h>
   25 #include <stdlib.h>
   26 #include <signal.h>
   27 #include <string.h>
   28 #include <ctype.h>
   29 #include <sys/types.h>
   30 #include <sys/stat.h>
   31 #include <unistd.h>
   32 
   33 #ifdef HAVE_LOCALE_H
   34 
   35 #  include <locale.h>
   36 
   37 #endif
   38 #ifdef HAVE_LANGINFO_H
   39 
   40 #  include <langinfo.h>
   41 
   42 #endif
   43 
   44 #include <gtk/gtk.h>
   45 #include <gdk/gdkkeysyms.h>
   46 
   47 #include "utils.h"
   48 #include "i18n.h"
   49 #include "otherconv.h"
   50 #include "libplugin.h"
   51 #include "datebook.h"
   52 #include "address.h"
   53 #include "install_user.h"
   54 #include "todo.h"
   55 #include "memo.h"
   56 #include "sync.h"
   57 #include "log.h"
   58 #include "prefs_gui.h"
   59 #include "prefs.h"
   60 #include "plugins.h"
   61 #include "alarms.h"
   62 #include "print.h"
   63 #include "restore.h"
   64 #include "password.h"
   65 #include "pidfile.h"
   66 #include "jpilot.h"
   67 
   68 #include "icons/jpilot-icon4.xpm"
   69 #include "icons/datebook.xpm"
   70 #include "icons/address.xpm"
   71 #include "icons/todo.xpm"
   72 #include "icons/memo.xpm"
   73 #include "icons/appl_menu_icons.h"
   74 #include "icons/lock_icons.h"
   75 #include "icons/sync.xpm"
   76 #include "icons/cancel_sync.xpm"
   77 #include "icons/backup.xpm"
   78 
   79 /********************************* Constants **********************************/
   80 #define OUTPUT_MINIMIZE 383
   81 #define OUTPUT_RESIZE   384
   82 #define OUTPUT_SETSIZE  385
   83 #define OUTPUT_CLEAR    386
   84 
   85 #define MASK_WIDTH  0x08
   86 #define MASK_HEIGHT 0x04
   87 #define MASK_X      0x02
   88 #define MASK_Y      0x01
   89 #define PIPE_DEBUG 1
   90 /* #define PIPE_DEBUG */
   91 /******************************* Global vars **********************************/
   92 /* Application-wide globals */
   93 int pipe_from_child, pipe_to_parent;
   94 int pipe_from_parent, pipe_to_child;
   95 /* Main GTK window for application */
   96 GtkWidget *window;
   97 GtkWidget *glob_date_label;
   98 GtkWidget *glob_dialog = NULL;
   99 int glob_app = 0;
  100 unsigned char skip_plugins;
  101 gint glob_date_timer_tag;
  102 pid_t glob_child_pid;
  103 pid_t jpilot_master_pid;
  104 int plugin_number = DATEBOOK + 100;
  105 /* jpilot.c file globals */
  106 static GtkWidget *g_hbox, *g_vbox0;
  107 static GtkWidget *g_hbox2, *g_vbox0_1;
  108 static GtkWidget *g_output_text_scrolled_window;
  109 static GtkTextView *g_output_text;
  110 static GtkTextBuffer *g_output_text_buffer;
  111 static GtkWidget *output_pane;
  112 static GtkWidget *button_locked;
  113 static GtkWidget *button_masklocked;
  114 static GtkWidget *button_unlocked;
  115 static GtkWidget *button_sync;
  116 static GtkWidget *button_cancel_sync;
  117 static GtkWidget *button_backup;
  118 static GtkWidget *menu_hide_privates;
  119 static GtkWidget *menu_show_privates;
  120 static GtkWidget *menu_mask_privates;
  121 
  122 extern GtkWidget *weekview_window;
  123 extern GtkWidget *monthview_window;
  124 
  125 /****************************** Prototypes ************************************/
  126 static void cb_delete_event(GtkWidget *widget, GdkEvent *event, gpointer data);
  127 
  128 static void install_gui_and_size(GtkWidget *main_window);
  129 
  130 static void cb_private(GtkWidget *widget, gpointer data);
  131 
  132 char *getViewMenuXmlString();
  133 #ifdef ENABLE_PLUGINS
  134 
  135 
  136 static void call_plugin_help(int number);
  137 
  138 #endif
  139 
  140 /****************************** Main Code *************************************/
  141 
  142 static int create_main_boxes(void) {
  143     g_hbox2 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
  144     g_vbox0_1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
  145 
  146     gtk_box_pack_start(GTK_BOX(g_hbox), g_hbox2, TRUE, TRUE, 0);
  147     gtk_box_pack_start(GTK_BOX(g_vbox0), g_vbox0_1, FALSE, FALSE, 0);
  148     return EXIT_SUCCESS;
  149 }
  150 
  151 static int gui_cleanup(void) {
  152 #ifdef ENABLE_PLUGINS
  153     struct plugin_s *plugin;
  154     GList *plugin_list, *temp_list;
  155 #endif
  156 
  157 #ifdef ENABLE_PLUGINS
  158     plugin_list = NULL;
  159     plugin_list = get_plugin_list();
  160 
  161     /* Find out which (if any) plugin to call a gui_cleanup on */
  162     for (temp_list = plugin_list; temp_list; temp_list = temp_list->next) {
  163         plugin = (struct plugin_s *) temp_list->data;
  164         if (plugin) {
  165             if (plugin->number == glob_app) {
  166                 if (plugin->plugin_gui_cleanup) {
  167                     plugin->plugin_gui_cleanup();
  168                 }
  169                 break;
  170             }
  171         }
  172     }
  173 #endif
  174 
  175     // if you uncomment this line, changing themes will switch live
  176     // however, there are some side effects that I haven't figured out
  177     // how to overcome. (things overridden in a theme, but not defined in another
  178     // do not revert back to default.)
  179   //   read_gtkrc_file();
  180     switch (glob_app) {
  181         case DATEBOOK:
  182             datebook_gui_cleanup();
  183             break;
  184         case ADDRESS:
  185             address_gui_cleanup();
  186             break;
  187         case TODO:
  188             todo_gui_cleanup();
  189             break;
  190         case MEMO:
  191             memo_gui_cleanup();
  192             break;
  193         default:
  194             break;
  195     }
  196     return EXIT_SUCCESS;
  197 }
  198 
  199 #ifdef ENABLE_PLUGINS
  200 
  201 void call_plugin_gui(int number, int unique_id) {
  202     struct plugin_s *plugin;
  203     GList *plugin_list, *temp_list;
  204 
  205     if (!number) {
  206         return;
  207     }
  208 
  209     gui_cleanup();
  210 
  211     plugin_list = NULL;
  212     plugin_list = get_plugin_list();
  213 
  214     /* Destroy main boxes and recreate them */
  215     gtk_widget_destroy(g_vbox0_1);
  216     gtk_widget_destroy(g_hbox2);
  217     create_main_boxes();
  218     if (glob_date_timer_tag) {
  219         g_source_remove(glob_date_timer_tag);
  220         glob_date_timer_tag = 0;
  221     }
  222 
  223     /* Find out which plugin we are calling */
  224     for (temp_list = plugin_list; temp_list; temp_list = temp_list->next) {
  225         plugin = (struct plugin_s *) temp_list->data;
  226         if (plugin) {
  227             if (plugin->number == number) {
  228                 glob_app = plugin->number;
  229                 if (plugin->plugin_gui) {
  230                     plugin->plugin_gui(g_vbox0_1, g_hbox2, unique_id);
  231                 }
  232                 break;
  233             }
  234         }
  235     }
  236 }
  237 
  238 //static void cb_plugin_setup() {
  239 //    call_plugin_gui(plugin_number++, 0);
  240 //}
  241 
  242 static void cb_plugin_gui(GtkAction *action, int number) {
  243     call_plugin_gui(number, 0);
  244 }
  245 
  246 /* Redraws plugin GUI after structure changing event such as category editing */
  247 void plugin_gui_refresh(int unique_id) {
  248     call_plugin_gui(glob_app, unique_id);
  249 }
  250 static void cb_plugin_help(GtkAction *action,
  251                         gpointer   user_data){
  252    call_plugin_help(GPOINTER_TO_INT(user_data));
  253 }
  254 static void call_plugin_help(int number) {
  255     struct plugin_s *plugin;
  256     GList *plugin_list, *temp_list;
  257     char *button_text[] = {N_("OK")};
  258     char *text;
  259     int width, height;
  260 
  261     if (!number) {
  262         return;
  263     }
  264 
  265     plugin_list = NULL;
  266     plugin_list = get_plugin_list();
  267 
  268     /* Find out which plugin we are calling */
  269     for (temp_list = plugin_list; temp_list; temp_list = temp_list->next) {
  270         plugin = (struct plugin_s *) temp_list->data;
  271         if (plugin) {
  272             if (plugin->number == number) {
  273                 if (plugin->plugin_help) {
  274                     text = NULL;
  275                     plugin->plugin_help(&text, &width, &height);
  276                     if (text) {
  277                         dialog_generic(GTK_WINDOW(window),
  278                                        plugin->help_name, DIALOG_INFO, text, 1, button_text);
  279                         free(text);
  280                     }
  281                 }
  282                 break;
  283             }
  284         }
  285     }
  286 }
  287 
  288 
  289 
  290 #endif
  291 
  292 static void cb_print(GtkWidget *widget, gpointer data) {
  293 #ifdef ENABLE_PLUGINS
  294     struct plugin_s *plugin;
  295     GList *plugin_list, *temp_list;
  296 #endif
  297     char *button_text[] = {N_("OK")};
  298 
  299     switch (glob_app) {
  300         case DATEBOOK:
  301             if (print_gui(window, DATEBOOK, 1, 0x07) == DIALOG_SAID_PRINT) {
  302                 datebook_print(print_day_week_month);
  303             }
  304             return;
  305         case ADDRESS:
  306             if (print_gui(window, ADDRESS, 0, 0x00) == DIALOG_SAID_PRINT) {
  307                 address_print();
  308             }
  309             return;
  310         case TODO:
  311             if (print_gui(window, TODO, 0, 0x00) == DIALOG_SAID_PRINT) {
  312                 todo_print();
  313             }
  314             return;
  315         case MEMO:
  316             if (print_gui(window, MEMO, 0, 0x00) == DIALOG_SAID_PRINT) {
  317                 memo_print();
  318             }
  319             return;
  320     }
  321 #ifdef ENABLE_PLUGINS
  322     plugin_list = NULL;
  323     plugin_list = get_plugin_list();
  324 
  325     for (temp_list = plugin_list; temp_list; temp_list = temp_list->next) {
  326         plugin = (struct plugin_s *) temp_list->data;
  327         if (plugin) {
  328             if (glob_app == plugin->number) {
  329                 if (plugin->plugin_print) {
  330                     plugin->plugin_print();
  331                     return;
  332                 }
  333             }
  334         }
  335     }
  336 #endif
  337     dialog_generic(GTK_WINDOW(window),
  338                    _("Print"), DIALOG_WARNING,
  339                    _("There is no print support for this conduit."),
  340                    1, button_text);
  341 }
  342 
  343 static void cb_restore(GtkWidget *widget, gpointer data) {
  344     int r;
  345     int w, h, x, y;
  346 
  347     jp_logf(JP_LOG_DEBUG, "cb_restore()\n");
  348 
  349     w = gdk_window_get_width(gtk_widget_get_window(window));
  350     h = gdk_window_get_height(gtk_widget_get_window(window));
  351 
  352     gdk_window_get_root_origin(gtk_widget_get_window(window), &x, &y);
  353 
  354     w = w / 2;
  355     x += 40;
  356 
  357     r = restore_gui(window, w, h, x, y);
  358 
  359     /* Fork successful, child sync process started */
  360     if (glob_child_pid && (r == EXIT_SUCCESS)) {
  361         gtk_widget_hide(button_sync);
  362         gtk_widget_show(button_cancel_sync);
  363     }
  364 }
  365 
  366 static void cb_import(GtkWidget *widget, gpointer data) {
  367 #ifdef ENABLE_PLUGINS
  368     struct plugin_s *plugin;
  369     GList *plugin_list, *temp_list;
  370 #endif
  371     char *button_text[] = {N_("OK")};
  372 
  373     switch (glob_app) {
  374         case DATEBOOK:
  375             datebook_import(window);
  376             return;
  377         case ADDRESS:
  378             address_import(window);
  379             return;
  380         case TODO:
  381             todo_import(window);
  382             return;
  383         case MEMO:
  384             memo_import(window);
  385             return;
  386     }
  387 #ifdef ENABLE_PLUGINS
  388     plugin_list = NULL;
  389     plugin_list = get_plugin_list();
  390 
  391     for (temp_list = plugin_list; temp_list; temp_list = temp_list->next) {
  392         plugin = (struct plugin_s *) temp_list->data;
  393         if (plugin) {
  394             if (glob_app == plugin->number) {
  395                 if (plugin->plugin_import) {
  396                     plugin->plugin_import(window);
  397                     return;
  398                 }
  399             }
  400         }
  401     }
  402 #endif
  403     dialog_generic(GTK_WINDOW(window),
  404                    _("Import"), DIALOG_WARNING,
  405                    _("There is no import support for this conduit."),
  406                    1, button_text);
  407 }
  408 
  409 static void cb_export(GtkWidget *widget, gpointer data) {
  410 #ifdef ENABLE_PLUGINS
  411     struct plugin_s *plugin;
  412     GList *plugin_list, *temp_list;
  413 #endif
  414     char *button_text[] = {N_("OK")};
  415 
  416     switch (glob_app) {
  417         case DATEBOOK:
  418             datebook_export(window);
  419             return;
  420         case ADDRESS:
  421             address_export(window);
  422             return;
  423         case TODO:
  424             todo_export(window);
  425             return;
  426         case MEMO:
  427             memo_export(window);
  428             return;
  429     }
  430 #ifdef ENABLE_PLUGINS
  431     plugin_list = NULL;
  432     plugin_list = get_plugin_list();
  433 
  434     for (temp_list = plugin_list; temp_list; temp_list = temp_list->next) {
  435         plugin = (struct plugin_s *) temp_list->data;
  436         if (plugin) {
  437             if (glob_app == plugin->number) {
  438                 if (plugin->plugin_export) {
  439                     plugin->plugin_export(window);
  440                     return;
  441                 }
  442             }
  443         }
  444     }
  445 #endif
  446     dialog_generic(GTK_WINDOW(window),
  447                    _("Export"), DIALOG_WARNING,
  448                    _("There is no export support for this conduit."),
  449                    1, button_text);
  450 }
  451 
  452 //FIX remove
  453 //static void cb_private_from_radio(GtkRadioAction *action) {
  454 //    cb_private(NULL, GINT_TO_POINTER(gtk_radio_action_get_current_value(action)));
  455 //}
  456 
  457 static void cb_private(GtkWidget *widget, gpointer data) {
  458     int privates, was_privates;
  459     int r_dialog = 0;
  460     static int skip_false_call = 0;
  461 #ifdef ENABLE_PRIVATE
  462     char ascii_password[64];
  463     int r_pass;
  464     int retry;
  465 #endif
  466 
  467     if (skip_false_call) {
  468         skip_false_call = 0;
  469         return;
  470     }
  471 
  472     was_privates = show_privates(GET_PRIVATES);
  473     privates = show_privates(GPOINTER_TO_INT(data));
  474 
  475     /* no changes */
  476     if (was_privates == privates)
  477         return;
  478 
  479     switch (privates) {
  480         case MASK_PRIVATES:
  481             gtk_widget_hide(button_locked);
  482             gtk_widget_show(button_masklocked);
  483             gtk_widget_hide(button_unlocked);
  484             if (! gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_mask_privates))) {
  485                 skip_false_call = 1;
  486                 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_mask_privates), TRUE);
  487             }
  488             break;
  489         case HIDE_PRIVATES:
  490             gtk_widget_show(button_locked);
  491             gtk_widget_hide(button_masklocked);
  492             gtk_widget_hide(button_unlocked);
  493             if (! gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_hide_privates))) {
  494                 skip_false_call = 1;
  495                 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_hide_privates), TRUE);
  496             }
  497             break;
  498         case SHOW_PRIVATES:
  499             /* Ask for the password, or don't depending on configure option */
  500 #ifdef ENABLE_PRIVATE
  501             memset(ascii_password, 0, sizeof(ascii_password));
  502             if (was_privates != SHOW_PRIVATES) {
  503                 retry = FALSE;
  504                 do {
  505                     r_dialog = dialog_password(GTK_WINDOW(window),
  506                                                ascii_password, retry);
  507                     r_pass = verify_password(ascii_password);
  508                     retry = TRUE;
  509                 } while ((r_pass == FALSE) && (r_dialog == 2));
  510             }
  511 #else
  512             r_dialog = 2;
  513 #endif
  514             if (r_dialog == 2) {
  515                 gtk_widget_hide(button_locked);
  516                 gtk_widget_hide(button_masklocked);
  517                 gtk_widget_show(button_unlocked);
  518                 if (! gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_show_privates))) {
  519                     skip_false_call = 1;
  520                     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_show_privates), TRUE);
  521                 }
  522             } else {
  523                 /* wrong or canceled password, hide the entries */
  524                 privates = show_privates(HIDE_PRIVATES);
  525                 if (! gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_hide_privates))) {
  526                     skip_false_call = 1;
  527                     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_hide_privates), TRUE);
  528                 }
  529                 cb_app_button(NULL, GINT_TO_POINTER(REDRAW));
  530                 return;
  531             }
  532             break;
  533     }
  534 
  535     if (was_privates != privates)
  536         cb_app_button(NULL, GINT_TO_POINTER(REDRAW));
  537 }
  538 
  539 static void cb_install_user(GtkWidget *widget, gpointer data) {
  540     int r;
  541 
  542     r = install_user_gui(window);
  543 
  544     /* Fork successful, child sync process started */
  545     if (glob_child_pid && (r == EXIT_SUCCESS)) {
  546         gtk_widget_hide(button_sync);
  547         gtk_widget_show(button_cancel_sync);
  548     }
  549 }
  550 
  551 void cb_datebook_app_button() {
  552     cb_app_button(NULL, GINT_TO_POINTER(DATEBOOK));
  553 }
  554 
  555 void cb_address_app_button() {
  556     cb_app_button(NULL, GINT_TO_POINTER(ADDRESS));
  557 }
  558 
  559 void cb_todo_app_button() {
  560     cb_app_button(NULL, GINT_TO_POINTER(TODO));
  561 }
  562 
  563 void cb_memo_app_button() {
  564     cb_app_button(NULL, GINT_TO_POINTER(MEMO));
  565 }
  566 
  567 void cb_app_button(GtkWidget *widget, gpointer data) {
  568     int app;
  569     int refresh;
  570 
  571     app = GPOINTER_TO_INT(data);
  572 
  573     /* If the current and selected apps are the same then just refresh screen */
  574     refresh = (app == glob_app);
  575 
  576     /* Tear down GUI when switching apps or on forced REDRAW */
  577     if ((!refresh) || (app == REDRAW)) {
  578         gui_cleanup();
  579         if (glob_date_timer_tag) {
  580             g_source_remove(glob_date_timer_tag);
  581             glob_date_timer_tag = 0;
  582         }
  583         gtk_widget_destroy(g_vbox0_1);
  584         gtk_widget_destroy(g_hbox2);
  585         create_main_boxes();
  586         if (app == REDRAW) {
  587             app = glob_app;
  588         }
  589     }
  590 
  591     switch (app) {
  592         case DATEBOOK:
  593             if (refresh) {
  594                 datebook_refresh(TRUE, TRUE);
  595             } else {
  596                 glob_app = DATEBOOK;
  597                 datebook_gui(g_vbox0_1, g_hbox2);
  598             }
  599             break;
  600         case ADDRESS:
  601             if (refresh) {
  602                 address_cycle_cat();
  603                 address_refresh();
  604             } else {
  605                 glob_app = ADDRESS;
  606                 address_gui(g_vbox0_1, g_hbox2);
  607             }
  608             break;
  609         case TODO:
  610             if (refresh) {
  611                 todo_cycle_cat();
  612                 todo_refresh();
  613             } else {
  614                 glob_app = TODO;
  615                 todo_gui(g_vbox0_1, g_hbox2);
  616             }
  617             break;
  618         case MEMO:
  619             if (refresh) {
  620                 memo_cycle_cat();
  621                 memo_refresh();
  622             } else {
  623                 glob_app = MEMO;
  624                 memo_gui(g_vbox0_1, g_hbox2);
  625             }
  626             break;
  627         default:
  628             /* recursion */
  629             if ((glob_app == DATEBOOK) ||
  630                 (glob_app == ADDRESS) ||
  631                 (glob_app == TODO) ||
  632                 (glob_app == MEMO))
  633                 cb_app_button(NULL, GINT_TO_POINTER(glob_app));
  634             break;
  635     }
  636 }
  637 
  638 static void sync_sig_handler(int sig) {
  639     unsigned int flags;
  640     int r;
  641 
  642     flags = skip_plugins ? SYNC_NO_PLUGINS : 0;
  643 
  644     r = setup_sync(flags);
  645 
  646     /* Fork successful, child sync process started */
  647     if (glob_child_pid && (r == EXIT_SUCCESS)) {
  648         gtk_widget_hide(button_sync);
  649         gtk_widget_show(button_cancel_sync);
  650     }
  651 }
  652 
  653 static void cb_sync(GtkWidget *widget, unsigned int flags) {
  654     long ivalue;
  655     int r;
  656 
  657     /* confirm file installation */
  658     get_pref(PREF_CONFIRM_FILE_INSTALL, &ivalue, NULL);
  659     if (ivalue) {
  660         char file[FILENAME_MAX];
  661         char home_dir[FILENAME_MAX];
  662         struct stat buf;
  663 
  664         /* If there are files to be installed, ask the user right before sync */
  665         get_home_file_name("", home_dir, sizeof(home_dir));
  666         g_snprintf(file, sizeof(file), "%s/"EPN".install", home_dir);
  667 
  668         if (!stat(file, &buf)) {
  669             if (buf.st_size > 0) {
  670                 install_gui_and_size(window);
  671             }
  672         }
  673     }
  674 
  675     r = setup_sync(flags);
  676 
  677     /* Fork successful, child sync process started */
  678     if (glob_child_pid && (r == EXIT_SUCCESS)) {
  679         gtk_widget_hide(button_sync);
  680         gtk_widget_show(button_cancel_sync);
  681     }
  682 
  683 }
  684 
  685 void cb_cancel_sync(GtkWidget *widget, unsigned int flags);
  686 
  687 char *getFileMenuXmlString();
  688 
  689 void addUiFromString(const GtkUIManager *uiManager, const char *menuXml);
  690 
  691 
  692 #ifdef WEBMENU
  693 static const char *getWebMenuXmlString();
  694 #endif
  695 
  696 
  697 
  698 void cb_cancel_sync(GtkWidget *widget, unsigned int flags) {
  699     if (glob_child_pid) {
  700         jp_logf(JP_LOG_GUI, "****************************************\n");
  701         jp_logf(JP_LOG_GUI, _(" Cancelling HotSync\n"));
  702         jp_logf(JP_LOG_GUI, "****************************************\n");
  703         kill(glob_child_pid, SIGTERM);
  704     }
  705     gtk_widget_hide(button_cancel_sync);
  706     gtk_widget_show(button_sync);
  707 }
  708 
  709 /*
  710  * This is called when the user name from the palm doesn't match
  711  * or the user ID from the palm is 0
  712  */
  713 static int bad_sync_exit_status(int exit_status) {
  714     char text1[] =
  715             /*-------------------------------------------*/
  716             N_("This handheld does not have the same user name or user ID\n"
  717                "as the one that was synced the last time.\n"
  718                "Syncing could have unwanted effects including data loss.\n"
  719                "\n"
  720                "Read the user manual if you are uncertain.");
  721     char text2[] =
  722             /*-------------------------------------------*/
  723             N_("This handheld has a NULL user ID.\n"
  724                "Every handheld must have a unique user ID in order to sync properly.\n"
  725                "If the handheld has been hard reset, \n"
  726                "   use restore from the menu to restore it.\n"
  727                "Otherwise, to add a new user name and ID\n"
  728                "   use install-user from the menu.\n"
  729                "\n"
  730                "Read the user manual if you are uncertain.");
  731     char *button_text[] = {N_("Cancel Sync"), N_("Sync Anyway")
  732     };
  733 
  734     if (!GTK_IS_WINDOW(window)) {
  735         return EXIT_FAILURE;
  736     }
  737     if ((exit_status == SYNC_ERROR_NOT_SAME_USERID) ||
  738         (exit_status == SYNC_ERROR_NOT_SAME_USER)) {
  739         return dialog_generic(GTK_WINDOW(window),
  740                               _("Sync Problem"), DIALOG_WARNING, _(text1), 2, button_text);
  741     }
  742     if (exit_status == SYNC_ERROR_NULL_USERID) {
  743         return dialog_generic(GTK_WINDOW(window),
  744                               _("Sync Problem"), DIALOG_ERROR, _(text2), 1, button_text);
  745     }
  746     return EXIT_FAILURE;
  747 }
  748 
  749 void output_to_pane(const char *str) {
  750     int h, new_y;
  751     long ivalue;
  752     GtkWidget *pane_hbox;
  753     GtkRequisition size_requisition;
  754 
  755     /* Adjust window height to user preference or minimum size */
  756     get_pref(PREF_OUTPUT_HEIGHT, &ivalue, NULL);
  757     /* Make them look at something if output happens */
  758     if (ivalue < 50) {
  759         /* Ask GTK for size which is just large enough to show both buttons */
  760         pane_hbox = gtk_paned_get_child2(GTK_PANED(output_pane));
  761         //gtk2 gtk_widget_size_request(pane_hbox, &size_requisition);
  762         gtk_widget_get_preferred_size(pane_hbox, NULL, &size_requisition);
  763         ivalue = size_requisition.height + 1;
  764         set_pref(PREF_OUTPUT_HEIGHT, ivalue, NULL, TRUE);
  765     }
  766     //w = gdk_window_get_width(gtk_widget_get_window(window));
  767     h = gdk_window_get_height(gtk_widget_get_window(window));
  768     new_y = h - ivalue;
  769     gtk_paned_set_position(GTK_PANED(output_pane), new_y);
  770 
  771     /* Output text to window */
  772     GtkTextIter end_iter;
  773     GtkTextMark *end_mark;
  774     gboolean scroll_to_end = FALSE;
  775     gdouble sbar_value, sbar_page_size, sbar_upper;
  776 
  777     /* The window position scrolls with new input if the user has left
  778      * the scrollbar at the bottom of the window.  Otherwise, if the user
  779      * is scrolling back through the log then jpilot does nothing and defers
  780      * to the user. */
  781 
  782     /* Get position of scrollbar */
  783     //gtk2 GtkAdjustment * vadjustment =  gtk_text_view_get_vadjustment (g_output_text);
  784     GtkAdjustment * vadjustment = gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(g_output_text));
  785     sbar_value = gtk_adjustment_get_value(vadjustment);
  786     sbar_page_size = gtk_adjustment_get_page_size(vadjustment);
  787     sbar_upper = gtk_adjustment_get_upper(vadjustment);
  788     /* Keep scrolling to the end only if we are already near(1 window) of the end
  789      * OR the window has just been created and is blank */
  790     if ((abs((sbar_value + sbar_page_size) - sbar_upper) < sbar_page_size)
  791         || sbar_page_size == 1) {
  792         scroll_to_end = TRUE;
  793     }
  794 
  795     gtk_text_buffer_get_end_iter(g_output_text_buffer, &end_iter);
  796 
  797     if (!g_utf8_validate(str, -1, NULL)) {
  798         gchar *utf8_text;
  799 
  800         utf8_text = g_locale_to_utf8(str, -1, NULL, NULL, NULL);
  801         gtk_text_buffer_insert(g_output_text_buffer, &end_iter, utf8_text, -1);
  802         g_free(utf8_text);
  803     } else
  804         gtk_text_buffer_insert(g_output_text_buffer, &end_iter, str, -1);
  805 
  806     if (scroll_to_end) {
  807         end_mark = gtk_text_buffer_create_mark(g_output_text_buffer, NULL, &end_iter, TRUE);
  808         gtk_text_buffer_move_mark(g_output_text_buffer, end_mark, &end_iter);
  809         gtk_text_view_scroll_to_mark(g_output_text, end_mark, 0, TRUE, 0.0, 0.0);
  810         gtk_text_buffer_delete_mark(g_output_text_buffer, end_mark);
  811     }
  812 }
  813 
  814 
  815 gboolean cb_read_pipe_from_child(GIOChannel *channel, GIOCondition cond, gpointer data) {
  816     int num;
  817     char buf_space[1026];
  818     char *buf;
  819     int buf_len;
  820     fd_set fds;
  821     struct timeval tv;
  822     int ret, done;
  823     char *Pstr1, *Pstr2, *Pstr3;
  824     int user_len;
  825     char password[MAX_PREF_LEN];
  826     int password_len;
  827     unsigned long user_id;
  828     int i, reason;
  829     int command;
  830     char user[MAX_PREF_LEN];
  831     char command_str[80];
  832     long char_set;
  833     const char *svalue;
  834     char title[MAX_PREF_LEN + 256];
  835     char *user_name;
  836     gint in = g_io_channel_unix_get_fd(channel);
  837 
  838     /* This is so we can always look at the previous char in buf */
  839     buf = &buf_space[1];
  840     buf[-1] = 'A'; /* that looks weird */
  841     done = 0;
  842     while (!done) {
  843         buf[0] = '\0';
  844         buf_len = 0;
  845         /* Read until "\0\n", or buffer full */
  846 
  847         for (i = 0; i < 1022; i++) {
  848             buf[i] = '\0';
  849             /* Linux modifies tv in the select call */
  850             tv.tv_sec = 0;
  851             tv.tv_usec = 0;
  852             FD_ZERO(&fds);
  853             FD_SET(in, &fds);
  854             ret = select(in + 1, &fds, NULL, NULL, &tv);
  855             if ((ret < 1) || (!FD_ISSET(in, &fds))) {
  856                 done = 1;
  857                 break;
  858             }
  859             ret = read(in, &(buf[i]), 1);
  860             if (ret <= 0) {
  861                 done = 1;
  862                 break;
  863             }
  864             if ((buf[i - 1] == '\0') && (buf[i] == '\n')) {
  865                 buf_len = buf_len - 1;
  866                 break;
  867             }
  868             buf_len++;
  869             if (buf_len >= 1022) {
  870                 buf[buf_len] = '\0';
  871                 break;
  872             }
  873         }
  874 
  875         if (buf_len < 1) break;
  876 
  877         /* Look for the command */
  878         command = 0;
  879         sscanf(buf, "%d:", &command);
  880 
  881         Pstr1 = strstr(buf, ":");
  882         if (Pstr1 != NULL) {
  883             Pstr1++;
  884         }
  885 #ifdef PIPE_DEBUG
  886         printf("command=%d [%s]\n", command, Pstr1);
  887 #endif
  888         if (Pstr1) {
  889             switch (command) {
  890                 case PIPE_PRINT:
  891                     /* Output the text to the Sync window */
  892                     output_to_pane(Pstr1);
  893                     break;
  894                 case PIPE_USERID:
  895                     /* Save user ID as pref */
  896                     num = sscanf(Pstr1, "%lu", &user_id);
  897                     if (num > 0) {
  898                         jp_logf(JP_LOG_DEBUG, "pipe_read: user id = %lu\n", user_id);
  899                         set_pref(PREF_USER_ID, user_id, NULL, TRUE);
  900                     } else {
  901                         jp_logf(JP_LOG_DEBUG, "pipe_read: trouble reading user id\n");
  902                     }
  903                     break;
  904                 case PIPE_USERNAME:
  905                     /* Save username as pref */
  906                     Pstr2 = strchr(Pstr1, '\"');
  907                     if (Pstr2) {
  908                         Pstr2++;
  909                         Pstr3 = strchr(Pstr2, '\"');
  910                         if (Pstr3) {
  911                             user_len = Pstr3 - Pstr2;
  912                             if (user_len > MAX_PREF_LEN) {
  913                                 user_len = MAX_PREF_LEN;
  914                             }
  915                             g_strlcpy(user, Pstr2, user_len + 1);
  916                             jp_logf(JP_LOG_DEBUG, "pipe_read: user = %s\n", user);
  917                             set_pref(PREF_USER, 0, user, TRUE);
  918                         }
  919                     }
  920                     break;
  921                 case PIPE_PASSWORD:
  922                     /* Save password as pref */
  923                     Pstr2 = strchr(Pstr1, '\"');
  924                     if (Pstr2) {
  925                         Pstr2++;
  926                         Pstr3 = strchr(Pstr2, '\"');
  927                         if (Pstr3) {
  928                             password_len = Pstr3 - Pstr2;
  929                             if (password_len > MAX_PREF_LEN) {
  930                                 password_len = MAX_PREF_LEN;
  931                             }
  932                             g_strlcpy(password, Pstr2, password_len + 1);
  933                             jp_logf(JP_LOG_DEBUG, "pipe_read: password = %s\n", password);
  934                             set_pref(PREF_PASSWORD, 0, password, TRUE);
  935                         }
  936                     }
  937                     break;
  938                 case PIPE_WAITING_ON_USER:
  939 #ifdef PIPE_DEBUG
  940                     printf("waiting on user\n");
  941 #endif
  942                     /* Look for the reason */
  943                     num = sscanf(Pstr1, "%d", &reason);
  944 #ifdef PIPE_DEBUG
  945                     printf("reason %d\n", reason);
  946 #endif
  947                     if (num > 0) {
  948                         jp_logf(JP_LOG_DEBUG, "pipe_read: reason = %d\n", reason);
  949                     } else {
  950                         jp_logf(JP_LOG_DEBUG, "pipe_read: trouble reading reason\n");
  951                     }
  952                     if ((reason == SYNC_ERROR_NOT_SAME_USERID) ||
  953                         (reason == SYNC_ERROR_NOT_SAME_USER) ||
  954                         (reason == SYNC_ERROR_NULL_USERID)) {
  955                         /* Future code */
  956                         /* This is where to add an option for adding user or
  957                          user id to possible ids to sync with. */
  958                         ret = bad_sync_exit_status(reason);
  959 #ifdef PIPE_DEBUG
  960                         printf("ret=%d\n", ret);
  961 #endif
  962                         if (ret == DIALOG_SAID_2) {
  963                             sprintf(command_str, "%d:\n", PIPE_SYNC_CONTINUE);
  964                         } else {
  965                             sprintf(command_str, "%d:\n", PIPE_SYNC_CANCEL);
  966                         }
  967                         if (write(pipe_to_child, command_str, strlen(command_str)) < 0) {
  968                             jp_logf(JP_LOG_WARN, "write failed %s %d\n", __FILE__, __LINE__);
  969                         }
  970                         fsync(pipe_to_child);
  971                     }
  972                     break;
  973                 case PIPE_FINISHED:
  974                     /* Update main window title as user name may have changed */
  975                     get_pref(PREF_CHAR_SET, &char_set, NULL);
  976                     get_pref(PREF_USER, NULL, &svalue);
  977                     strcpy(title, PN" "VERSION);
  978                     if ((svalue) && (svalue[0])) {
  979                         strcat(title, _(" User: "));
  980                         user_name = charset_p2newj(svalue, -1, char_set);
  981                         strcat(title, user_name);
  982                         gtk_window_set_title(GTK_WINDOW(window), title);
  983                         free(user_name);
  984                     }
  985                     /* And redraw GUI */
  986                     if (Pstr1) {
  987                         cb_app_button(NULL, GINT_TO_POINTER(REDRAW));
  988                     }
  989                     break;
  990                 default:
  991                     jp_logf(JP_LOG_WARN, _("Unknown command from sync process\n"));
  992                     jp_logf(JP_LOG_WARN, "buf=[%s]\n", buf);
  993             }
  994         }
  995     }
  996     return TRUE;
  997 }
  998 
  999 static void cb_about(GtkWidget *widget, gpointer data) {
 1000     char *button_text[] = {N_("OK")};
 1001     char about[256];
 1002     char options[1024];
 1003     int w;
 1004 
 1005     w = gdk_window_get_width(gtk_widget_get_window(window));
 1006     //h = gdk_window_get_height(gtk_widget_get_window(window));
 1007 
 1008     w = w / 2;
 1009     //h = 1;
 1010 
 1011     g_snprintf(about, sizeof(about), _("About %s"), PN);
 1012 
 1013     get_compile_options(options, sizeof(options));
 1014 
 1015     if (GTK_IS_WINDOW(window)) {
 1016         dialog_generic(GTK_WINDOW(window),
 1017                        about, DIALOG_INFO, options, 1, button_text);
 1018     }
 1019 }
 1020 
 1021 /* Experimental webmenu that has never been used in practice */
 1022 #ifdef WEBMENU
 1023 
 1024 #define NETSCAPE_EXISTING   0
 1025 #define NETSCAPE_NEW_WINDOW 1
 1026 #define NETSCAPE_NEW        2
 1027 #define MOZILLA_EXISTING    3
 1028 #define MOZILLA_NEW_WINDOW  4
 1029 #define MOZILLA_NEW_TAB     5
 1030 #define MOZILLA_NEW         6
 1031 #define GALEON_EXISTING     7
 1032 #define GALEON_NEW_WINDOW   8
 1033 #define GALEON_NEW_TAB      9
 1034 #define GALEON_NEW          10
 1035 #define OPERA_EXISTING      11
 1036 #define OPERA_NEW_WINDOW    12
 1037 #define OPERA_NEW           13
 1038 #define GNOME_URL           14
 1039 #define LYNX_NEW            15
 1040 #define LINKS_NEW           16
 1041 #define W3M_NEW             17
 1042 #define KONQUEROR_NEW       18
 1043 
 1044 static struct url_command {
 1045    int id;
 1046    char *desc;
 1047    char *command;
 1048 };
 1049 
 1050 /* These strings were taken from xchat 2.0.0 */
 1051 static struct url_command url_commands[]={
 1052      {NETSCAPE_EXISTING, "/Web/Netscape/Open jpilot.org in existing", "netscape -remote 'openURL(http://jpilot.org)'"},
 1053      {NETSCAPE_NEW_WINDOW, "/Web/Netscape/Open jpilot.org in new window", "netscape -remote 'openURL(http://jpilot.org,new-window)'"},
 1054      {NETSCAPE_NEW, "/Web/Netscape/Open jpilot.org in new Netscape", "netscape http://jpilot.org"},
 1055 
 1056      {MOZILLA_EXISTING, "/Web/Mozilla/Open jpilot.org in existing", "mozilla -remote 'openURL(http://jpilot.org)'"},
 1057      {MOZILLA_NEW_WINDOW, "/Web/Mozilla/Open jpilot.org in new window", "mozilla -remote 'openURL(http://jpilot.org,new-window)'"},
 1058      {MOZILLA_NEW_TAB, "/Web/Mozilla/Open jpilot.org in new tab", "mozilla -remote 'openURL(http://jpilot.org,new-tab)'"},
 1059      {MOZILLA_NEW, "/Web/Mozilla/Open jpilot.org in new Mozilla", "mozilla http://jpilot.org"},
 1060 
 1061      {GALEON_EXISTING, "/Web/Galeon/Open jpilot.org in existing", "galeon -x 'http://jpilot.org'"},
 1062      {GALEON_NEW_WINDOW, "/Web/Galeon/Open jpilot.org in new window", "galeon -w 'http://jpilot.org'"},
 1063      {GALEON_NEW_TAB, "/Web/Galeon/Open jpilot.org in new tab", "galeon -n 'http://jpilot.org'"},
 1064      {GALEON_NEW, "/Web/Galeon/Open jpilot.org in new Galeon", "galeon 'http://jpilot.org'"},
 1065 
 1066      {OPERA_EXISTING, "/Web/Opera/Open jpilot.org in existing", "opera -remote 'openURL(http://jpilot.org)' &"},
 1067      {OPERA_NEW_WINDOW, "/Web/Opera/Open jpilot.org in new window", "opera -remote 'openURL(http://jpilot.org,new-window)' &"},
 1068      {OPERA_NEW, "/Web/Opera/Open jpilot.org in new Opera", "opera http://jpilot.org &"},
 1069 
 1070      {GNOME_URL, "/Web/GnomeUrl/Gnome URL Handler for jpilot.org", "gnome-moz-remote http://jpilot.org"},
 1071 
 1072      {LYNX_NEW, "/Web/Lynx/Lynx jpilot.org", "xterm -e lynx http://jpilot.org &"},
 1073 
 1074      {LINKS_NEW, "/Web/Links/Links jpilot.org", "xterm -e links http://jpilot.org &"},
 1075 
 1076      {W3M_NEW, "/Web/W3M/w3m jpilot.org", "xterm -e w3m http://jpilot.org &"},
 1077 
 1078      {KONQUEROR_NEW, "/Web/Konqueror/Konqueror jpilot.org", "konqueror http://jpilot.org"}
 1079 };
 1080 
 1081 
 1082 
 1083 static void cb_web(GtkWidget *widget, gpointer data);
 1084 void openNetscapeExisting(){
 1085     cb_web(NULL,GINT_TO_POINTER(NETSCAPE_EXISTING));
 1086 }
 1087 void openNetscapeNewWindow(){
 1088     cb_web(NULL,GINT_TO_POINTER(NETSCAPE_NEW_WINDOW));
 1089 }
 1090 void openNetscapeNew(){
 1091     cb_web(NULL,GINT_TO_POINTER(NETSCAPE_NEW));
 1092 }
 1093 void openMozillaExisting(){
 1094     cb_web(NULL,GINT_TO_POINTER(MOZILLA_EXISTING));
 1095 }
 1096 void openMozillaNewWindow(){
 1097     cb_web(NULL,GINT_TO_POINTER(MOZILLA_NEW_WINDOW));
 1098 }
 1099 void openMozillaNewTab(){
 1100     cb_web(NULL,GINT_TO_POINTER(MOZILLA_NEW_TAB));
 1101 }
 1102 void openMozillaNew(){
 1103     cb_web(NULL,GINT_TO_POINTER(MOZILLA_NEW));
 1104 }
 1105 void openGaleonExisting(){
 1106     cb_web(NULL,GINT_TO_POINTER(GALEON_EXISTING));
 1107 }
 1108 void openGaleonNewWindow(){
 1109     cb_web(NULL,GINT_TO_POINTER(GALEON_NEW_WINDOW));
 1110 }
 1111 void openGaleonNewTab(){
 1112     cb_web(NULL,GINT_TO_POINTER(GALEON_NEW_TAB));
 1113 }
 1114 void openGaleonNew(){
 1115     cb_web(NULL,GINT_TO_POINTER(GALEON_NEW));
 1116 }
 1117 void openOperaExisting(){
 1118     cb_web(NULL,GINT_TO_POINTER(OPERA_EXISTING));
 1119 }
 1120 void openOperaNewWindow(){
 1121     cb_web(NULL,GINT_TO_POINTER(OPERA_NEW_WINDOW));
 1122 }
 1123 void openOperaNew(){
 1124     cb_web(NULL,GINT_TO_POINTER(OPERA_NEW));
 1125 }
 1126 void openGnomeNew(){
 1127     cb_web(NULL,GINT_TO_POINTER(GNOME_URL));
 1128 }
 1129 void openLynxNew(){
 1130     cb_web(NULL,GINT_TO_POINTER(LYNX_NEW));
 1131 }
 1132 void openLinksNew(){
 1133     cb_web(NULL,GINT_TO_POINTER(LINKS_NEW));
 1134 }
 1135 void openW3MNew(){
 1136     cb_web(NULL,GINT_TO_POINTER(W3M_NEW));
 1137 }
 1138 void openKonquerorNew(){
 1139     cb_web(NULL,GINT_TO_POINTER(KONQUEROR_NEW));
 1140 }
 1141 static void cb_web(GtkWidget *widget, gpointer data)
 1142 {
 1143    int sel;
 1144 
 1145    sel=GPOINTER_TO_INT(data);
 1146    jp_logf(JP_LOG_INFO, PN": executing %s\n", url_commands[sel].command);
 1147    if (system(url_commands[sel].command) == -1) {
 1148       jp_logf(JP_LOG_WARN, "system call failed %s %d\n", __FILE__, __LINE__);
 1149    }
 1150 }
 1151 
 1152 #endif
 1153 
 1154 static void install_gui_and_size(GtkWidget *main_window) {
 1155     int w, h, x, y;
 1156 
 1157     w = gdk_window_get_width(gtk_widget_get_window(window));
 1158     h = gdk_window_get_height(gtk_widget_get_window(window));
 1159     gdk_window_get_root_origin(gtk_widget_get_window(window), &x, &y);
 1160 
 1161     w = w / 2;
 1162     x += 40;
 1163 
 1164     install_gui(main_window, w, h, x, y);
 1165 }
 1166 
 1167 static void cb_install_gui(GtkWidget *widget, gpointer data) {
 1168     jp_logf(JP_LOG_DEBUG, "cb_install_gui()\n");
 1169 
 1170     install_gui_and_size(window);
 1171 }
 1172 
 1173 static GtkWidget* create_menu_item(GtkWidget *menu,
 1174                                    GtkAccelGroup *accel_group,
 1175                                    gchar *icon_name,
 1176                                    const char **pixbuf_data,
 1177                                    gchar *text,
 1178                                    guint accel_key,
 1179                                    GdkModifierType accel_mods,
 1180                                    void *callback,
 1181                                    gpointer *data)
 1182 {
 1183     GtkWidget *box;
 1184     GtkWidget *icon;
 1185     GtkWidget *label;
 1186     GtkWidget *menu_item;
 1187     if (accel_key > 0) {
 1188         label = gtk_accel_label_new(text);
 1189     } else {
 1190         label = gtk_label_new(text);
 1191     }
 1192     menu_item = gtk_menu_item_new();
 1193     box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
 1194 
 1195     if (pixbuf_data) {
 1196         GtkWidget *image;
 1197         GdkPixbuf *pixbuf;
 1198 
 1199         pixbuf = gdk_pixbuf_new_from_xpm_data(pixbuf_data);
 1200         image = gtk_image_new_from_pixbuf(pixbuf);
 1201         gtk_container_add(GTK_CONTAINER(box), image);
 1202         // FIX - Do I need to unref?
 1203         // g_object_unref(pixbuf);
 1204     } else {
 1205         icon = gtk_image_new_from_icon_name(icon_name, GTK_ICON_SIZE_MENU);
 1206         gtk_container_add(GTK_CONTAINER(box), icon);
 1207     }
 1208 
 1209     //gtk_label_set_use_underline(GTK_LABEL(label), TRUE);
 1210     gtk_label_set_xalign(GTK_LABEL(label), 0.0);
 1211 
 1212     if ((accel_key > 0) && (accel_group)) {
 1213         gtk_widget_add_accelerator(menu_item, "activate", accel_group,
 1214                                    accel_key, accel_mods, GTK_ACCEL_VISIBLE);
 1215         gtk_accel_label_set_accel_widget(GTK_ACCEL_LABEL(label), menu_item);
 1216     }
 1217 
 1218     gtk_box_pack_end(GTK_BOX(box), label, TRUE, TRUE, 0);
 1219 
 1220     gtk_container_add(GTK_CONTAINER(menu_item), box);
 1221 
 1222     g_signal_connect(G_OBJECT(menu_item), "activate", callback, data);
 1223     gtk_widget_show(menu_item);
 1224     gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
 1225 
 1226     return menu_item;
 1227 }
 1228 
 1229 static void get_main_menu(GtkWidget *my_window,
 1230                           GtkWidget **menubar,
 1231                           GtkWidget **menubar_help,
 1232                           GList *plugin_list) {
 1233     #ifdef ENABLE_PLUGINS
 1234        int count, help_count;
 1235        struct plugin_s *p;
 1236        GList *temp_list;
 1237        int F_KEYS[]={GDK_KEY_F5,GDK_KEY_F6,GDK_KEY_F7,GDK_KEY_F8,GDK_KEY_F9,GDK_KEY_F10,GDK_KEY_F11,GDK_KEY_F12};
 1238     #endif
 1239     /*
 1240      * New Menu Code
 1241      */
 1242     *menubar = gtk_menu_bar_new();
 1243     *menubar_help = gtk_menu_bar_new();
 1244     gtk_widget_set_hexpand(*menubar, FALSE);
 1245     gtk_widget_set_hexpand(*menubar_help, FALSE);
 1246 
 1247     GtkWidget *menu1 = gtk_menu_new();
 1248     GtkWidget *menu2 = gtk_menu_new();
 1249 #ifdef ENABLE_PLUGINS
 1250     GtkWidget *menu3 = gtk_menu_new();
 1251 #endif
 1252     GtkWidget *menu4 = gtk_menu_new();
 1253 
 1254     GtkWidget *m = gtk_menu_item_new_with_mnemonic("_File");
 1255     gtk_menu_item_set_submenu(GTK_MENU_ITEM(m), menu1);
 1256     gtk_menu_shell_append(GTK_MENU_SHELL(*menubar), m);
 1257     gtk_widget_show(m);
 1258 
 1259     m = gtk_menu_item_new_with_mnemonic("_View");
 1260     gtk_menu_item_set_submenu(GTK_MENU_ITEM(m), menu2);
 1261     gtk_menu_shell_append(GTK_MENU_SHELL(*menubar), m);
 1262     gtk_widget_show(m);
 1263 
 1264 #ifdef ENABLE_PLUGINS
 1265     /* plugin_list will be NULL if there are none */
 1266     if (plugin_list) {
 1267         m = gtk_menu_item_new_with_mnemonic("_Plugins");
 1268         gtk_menu_item_set_submenu(GTK_MENU_ITEM(m), menu3);
 1269         gtk_menu_shell_append(GTK_MENU_SHELL(*menubar), m);
 1270         gtk_widget_show(m);
 1271     }
 1272 #endif
 1273 
 1274     m = gtk_menu_item_new_with_mnemonic("_Help");
 1275     gtk_menu_item_set_submenu(GTK_MENU_ITEM(m), menu4);
 1276     gtk_menu_shell_append(GTK_MENU_SHELL(*menubar_help), m);
 1277     gtk_widget_show(m);
 1278 
 1279     GtkAccelGroup *accel_group = gtk_accel_group_new();
 1280     gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);
 1281 
 1282     // First menu ("File")
 1283     create_menu_item(menu1, accel_group, "gtk-find", NULL, "Find", GDK_KEY_f, GDK_CONTROL_MASK, cb_search_gui, NULL);
 1284     GtkWidget *sep = gtk_separator_menu_item_new();
 1285     gtk_menu_shell_append(GTK_MENU_SHELL(menu1), sep);
 1286     create_menu_item(menu1, accel_group, "gtk-open", NULL, "Install", GDK_KEY_i, GDK_CONTROL_MASK, cb_install_gui, NULL);
 1287     create_menu_item(menu1, NULL, "gtk-go-forward", NULL, "Import", -1, GDK_CONTROL_MASK, cb_import, NULL);
 1288     create_menu_item(menu1, NULL, "gtk-go-back", NULL, "Export", -1, GDK_CONTROL_MASK, cb_export, NULL);
 1289     create_menu_item(menu1, accel_group, "gtk-preferences", NULL, "Preferences", GDK_KEY_s, GDK_CONTROL_MASK, cb_prefs_gui, NULL);
 1290     create_menu_item(menu1, accel_group, "gtk-print", NULL, "Print", GDK_KEY_p, GDK_CONTROL_MASK, cb_print, NULL);
 1291     sep = gtk_separator_menu_item_new();
 1292     gtk_menu_shell_append(GTK_MENU_SHELL(menu1), sep);
 1293     create_menu_item(menu1, NULL, "", user_icon, "Install User", -1, GDK_CONTROL_MASK, cb_install_user, NULL);
 1294     create_menu_item(menu1, NULL, "gtk-redo", NULL, "Restore Handheld", -1, GDK_CONTROL_MASK, cb_restore, NULL);
 1295     sep = gtk_separator_menu_item_new();
 1296     gtk_menu_shell_append(GTK_MENU_SHELL(menu1), sep);
 1297     create_menu_item(menu1, accel_group, "gtk-quit", NULL, "Quit", GDK_KEY_q, GDK_CONTROL_MASK, cb_delete_event, NULL);
 1298 
 1299     // First menu ("View")
 1300     // RADIO
 1301     GSList *group = NULL;
 1302     char *private_menu_text[] = {N_("Hide Private Records"), N_("Show Private Records"), N_("Mask Private Records")};
 1303     int params[] = {HIDE_PRIVATES, SHOW_PRIVATES, MASK_PRIVATES};
 1304     GtkWidget *last_item = NULL;
 1305     GtkWidget *radio_item[3];
 1306     int i;
 1307     for (i = 0; i < 3; i++) {
 1308         radio_item[i] = gtk_radio_menu_item_new_with_label(group, private_menu_text[i]);
 1309         g_signal_connect(G_OBJECT(radio_item[i]), "activate", G_CALLBACK(cb_private), GINT_TO_POINTER(params[i]));
 1310         gtk_radio_menu_item_join_group(GTK_RADIO_MENU_ITEM(radio_item[i]), GTK_RADIO_MENU_ITEM(last_item));
 1311         last_item = radio_item[i];
 1312         gtk_menu_shell_append(GTK_MENU_SHELL(menu2), radio_item[i]);
 1313     }
 1314     menu_hide_privates = radio_item[0];
 1315     menu_show_privates = radio_item[1];
 1316     menu_mask_privates = radio_item[2];
 1317 
 1318     sep = gtk_separator_menu_item_new();
 1319     gtk_menu_shell_append(GTK_MENU_SHELL(menu2), sep);
 1320     create_menu_item(menu2, accel_group, "", date_menu_icon, "Datebook", GDK_KEY_F1, 0, cb_app_button, GINT_TO_POINTER(DATEBOOK));
 1321     create_menu_item(menu2, accel_group, "", addr_menu_icon, "Address", GDK_KEY_F2, 0, cb_app_button, GINT_TO_POINTER(ADDRESS));
 1322     create_menu_item(menu2, accel_group, "", todo_menu_icon, "Todos", GDK_KEY_F3, 0, cb_app_button, GINT_TO_POINTER(TODO));
 1323     create_menu_item(menu2, accel_group, "gtk-justify-left", NULL, "Memos", GDK_KEY_F4, 0, cb_app_button, GINT_TO_POINTER(MEMO));
 1324 
 1325 #ifdef ENABLE_PLUGINS
 1326     /* Count the plugin entries */
 1327     for (count=0, temp_list = plugin_list;
 1328          temp_list;
 1329          temp_list = temp_list->next) {
 1330         p = (struct plugin_s *)temp_list->data;
 1331         if (p->menu_name) {
 1332             count++;
 1333         }
 1334     }
 1335 
 1336     /* Count the plugin help entries */
 1337     for (help_count=0, temp_list = plugin_list;
 1338          temp_list;
 1339          temp_list = temp_list->next) {
 1340         p = (struct plugin_s *)temp_list->data;
 1341         if (p->help_name) {
 1342             help_count++;
 1343         }
 1344     }
 1345 
 1346     /* Create plugin menu */
 1347     for (i=0, temp_list = plugin_list; temp_list; temp_list = temp_list->next, i++) {
 1348         p = (struct plugin_s *)temp_list->data;
 1349         if (p->menu_name) {
 1350             create_menu_item(menu3, accel_group, "package_system", NULL, p->menu_name, F_KEYS[i], 0, cb_plugin_gui, GINT_TO_POINTER(p->number));
 1351         }
 1352     }
 1353     // About menu
 1354     create_menu_item(menu4, accel_group, "gtk-info", NULL, "About J-Pilot", 0, 0, cb_about, NULL);
 1355 
 1356     /* Append plugin help menu strings */
 1357     for (temp_list = plugin_list; temp_list; temp_list = temp_list->next) {
 1358         p = (struct plugin_s *)temp_list->data;
 1359         if (p->help_name) {
 1360             create_menu_item(menu4, accel_group, "gtk-info", NULL, p->help_name, 0, 0, cb_plugin_help, GINT_TO_POINTER(p->number));
 1361         }
 1362     }
 1363 #endif
 1364 }
 1365 
 1366 static void cb_delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) {
 1367     int pw, ph;
 1368     int x, y;
 1369 #ifdef ENABLE_PLUGINS
 1370     struct plugin_s *plugin;
 1371     GList *plugin_list, *temp_list;
 1372 #endif
 1373 
 1374     /* gdk_window_get_deskrelative_origin(window->window, &x, &y); */
 1375     gdk_window_get_origin(gtk_widget_get_window(window), &x, &y);
 1376     jp_logf(JP_LOG_DEBUG, "x=%d, y=%d\n", x, y);
 1377 
 1378     pw = gdk_window_get_width(gtk_widget_get_window(window));
 1379     ph = gdk_window_get_height(gtk_widget_get_window(window));
 1380     set_pref(PREF_WINDOW_WIDTH, pw, NULL, FALSE);
 1381     set_pref(PREF_WINDOW_HEIGHT, ph, NULL, FALSE);
 1382     set_pref(PREF_LAST_APP, glob_app, NULL, TRUE);
 1383 
 1384     gui_cleanup();
 1385 
 1386     if (weekview_window)
 1387         cb_weekview_quit(weekview_window, NULL);
 1388     if (monthview_window)
 1389         cb_monthview_quit(monthview_window, NULL);
 1390 
 1391 #ifdef ENABLE_PLUGINS
 1392     plugin_list = get_plugin_list();
 1393 
 1394     for (temp_list = plugin_list; temp_list; temp_list = temp_list->next) {
 1395         plugin = (struct plugin_s *) temp_list->data;
 1396         if (plugin) {
 1397             if (plugin->plugin_exit_cleanup) {
 1398                 jp_logf(JP_LOG_DEBUG, "calling plugin_exit_cleanup\n");
 1399                 plugin->plugin_exit_cleanup();
 1400             }
 1401         }
 1402     }
 1403 #endif
 1404 
 1405     if (glob_child_pid) {
 1406         jp_logf(JP_LOG_DEBUG, "killing %d\n", glob_child_pid);
 1407         kill(glob_child_pid, SIGTERM);
 1408     }
 1409     /* Save preferences in jpilot.rc */
 1410     pref_write_rc_file();
 1411 
 1412     cleanup_pc_files();
 1413 
 1414     cleanup_pidfile();
 1415 
 1416     gtk_main_quit();
 1417 }
 1418 
 1419 static void cb_output(GtkWidget *widget, gpointer data) {
 1420     int flags;
 1421     int h, output_height;
 1422 
 1423     flags = GPOINTER_TO_INT(data);
 1424 
 1425     if ((flags == OUTPUT_MINIMIZE) || (flags == OUTPUT_RESIZE)) {
 1426         jp_logf(JP_LOG_DEBUG, "paned pos = %d\n", gtk_paned_get_position(GTK_PANED(output_pane)));
 1427         h = gdk_window_get_height(gtk_widget_get_window(window));
 1428         output_height = (h - gtk_paned_get_position(GTK_PANED(output_pane)));
 1429         set_pref(PREF_OUTPUT_HEIGHT, output_height, NULL, TRUE);
 1430         if (flags == OUTPUT_MINIMIZE) {
 1431             gtk_paned_set_position(GTK_PANED(output_pane), h);
 1432         }
 1433         jp_logf(JP_LOG_DEBUG, "output height = %d\n", output_height);
 1434     }
 1435     if (flags == OUTPUT_CLEAR) {
 1436         gtk_text_buffer_set_text(g_output_text_buffer, "", -1);
 1437     }
 1438 }
 1439 
 1440 static gint cb_output_idle(gpointer data) {
 1441     cb_output(NULL, data);
 1442     /* returning false removes this handler from being called again */
 1443     return FALSE;
 1444 }
 1445 
 1446 static gint cb_output2(GtkWidget *widget, GdkEventButton *event, gpointer data) {
 1447     /* Because the pane isn't redrawn yet we can't get positions from it.
 1448      * So we have to call back after everything is drawn */
 1449     g_idle_add(cb_output_idle, data);
 1450 
 1451     return EXIT_SUCCESS;
 1452 }
 1453 
 1454 static gint cb_check_version(gpointer main_window) {
 1455     int major, minor, micro;
 1456     int r;
 1457     char str_ver[8];
 1458 
 1459     jp_logf(JP_LOG_DEBUG, "cb_check_version\n");
 1460 
 1461     r = sscanf(VERSION, "%d.%d.%d", &major, &minor, &micro);
 1462     if (r != 3) {
 1463         jp_logf(JP_LOG_DEBUG, "couldn't parse VERSION\n");
 1464         return FALSE;
 1465     }
 1466     /* These shouldn't be greater than 100, but just in case */
 1467     major %= 100;
 1468     minor %= 100;
 1469     micro %= 100;
 1470 
 1471     sprintf(str_ver, "%02d%02d%02d", major, minor, micro);
 1472 
 1473     set_pref(PREF_VERSION, 0, str_ver, 1);
 1474 
 1475     return FALSE;
 1476 }
 1477 
 1478 int main(int argc, char *argv[]) {
 1479     GtkWidget *main_vbox;
 1480     GtkWidget *temp_hbox;
 1481     GtkWidget *temp_vbox;
 1482     GtkWidget *button_datebook, *button_address, *button_todo, *button_memo;
 1483     GtkWidget *button;
 1484     GtkWidget *separator;
 1485     //gtk2 GtkStyle *style;
 1486     GtkWidget *pixbufwid;
 1487     GdkPixbuf *pixbuf;
 1488     GtkWidget *menubar = NULL;
 1489     GtkWidget *menubar_help = NULL;
 1490     GtkAccelGroup *accel_group;
 1491 /* Extract first day of week preference from locale in GTK2 */
 1492     int pref_fdow = 0;
 1493 #ifdef HAVE__NL_TIME_FIRST_WEEKDAY
 1494     char *langinfo;
 1495     int week_1stday = 0;
 1496     int first_weekday = 1;
 1497     unsigned int week_origin;
 1498 #else
 1499 #  ifdef ENABLE_NLS
 1500     char *week_start;
 1501 #  endif
 1502 #endif
 1503     unsigned char skip_past_alarms;
 1504     unsigned char skip_all_alarms;
 1505     int filedesc[2];
 1506     long ivalue;
 1507     const char *svalue;
 1508     int i, height;
 1509     char title[MAX_PREF_LEN + 256];
 1510     long pref_width, pref_height, show_tooltips;
 1511     long char_set;
 1512 #ifdef PARSE_GEOMETRY
 1513     char *geometry_str = NULL;
 1514 #endif
 1515     int iconify = 0;
 1516 #ifdef ENABLE_PLUGINS
 1517     GList *plugin_list;
 1518     GList *temp_list;
 1519     struct plugin_s *plugin;
 1520     jp_startup_info info;
 1521 #endif
 1522     int pid;
 1523     int remote_sync = FALSE;
 1524 
 1525     skip_plugins = FALSE;
 1526     skip_past_alarms = FALSE;
 1527     skip_all_alarms = FALSE;
 1528     /* log all output to a file */
 1529     glob_log_file_mask = JP_LOG_INFO | JP_LOG_WARN | JP_LOG_FATAL | JP_LOG_STDOUT;
 1530     glob_log_stdout_mask = JP_LOG_INFO | JP_LOG_WARN | JP_LOG_FATAL | JP_LOG_STDOUT;
 1531     glob_log_gui_mask = JP_LOG_FATAL | JP_LOG_WARN | JP_LOG_GUI;
 1532     glob_find_id = 0;
 1533 
 1534     /* Directory ~/.jpilot is created with permissions of 700 to prevent anyone
 1535      * but the user from looking at potentially sensitive files.
 1536      * Files within the directory have permission 600 */
 1537     umask(0077);
 1538 
 1539     /* enable internationalization(i18n) before printing any output */
 1540 #if defined(ENABLE_NLS)
 1541 #  ifdef HAVE_LOCALE_H
 1542     setlocale(LC_ALL, "");
 1543 #  endif
 1544     bindtextdomain(EPN, LOCALEDIR);
 1545     textdomain(EPN);
 1546 #endif
 1547 
 1548     pref_init();
 1549 
 1550     /* read jpilot.rc file for preferences */
 1551     pref_read_rc_file();
 1552 
 1553     /* Extract first day of week preference from locale in GTK2 */
 1554 #  ifdef HAVE__NL_TIME_FIRST_WEEKDAY
 1555     /* GTK 2.8 libraries */
 1556     langinfo = nl_langinfo(_NL_TIME_FIRST_WEEKDAY);
 1557     first_weekday = langinfo[0];
 1558     langinfo = nl_langinfo(_NL_TIME_WEEK_1STDAY);
 1559     week_origin = GPOINTER_TO_INT(langinfo);
 1560     if (week_origin == 19971130)      /* Sunday */
 1561         week_1stday = 0;
 1562     else if (week_origin == 19971201) /* Monday */
 1563         week_1stday = 1;
 1564     else
 1565         g_warning ("Unknown value of _NL_TIME_WEEK_1STDAY.\n");
 1566 
 1567     pref_fdow = (week_1stday + first_weekday - 1) % 7;
 1568 #  else
 1569     /* GTK 2.6 libraries */
 1570 #     if defined(ENABLE_NLS)
 1571        week_start = dgettext("gtk20", "calendar:week_start:0");
 1572        if (strncmp("calendar:week_start:", week_start, 20) == 0) {
 1573           pref_fdow = *(week_start + 20) - '0';
 1574        } else {
 1575           pref_fdow = -1;
 1576        }
 1577 #     endif
 1578 #  endif
 1579     if (pref_fdow > 1)
 1580         pref_fdow = 1;
 1581     if (pref_fdow < 0)
 1582         pref_fdow = 0;
 1583 
 1584     set_pref_possibility(PREF_FDOW, pref_fdow, TRUE);
 1585 
 1586     if (otherconv_init()) {
 1587         printf("Error: could not set character encoding\n");
 1588         exit(0);
 1589     }
 1590 
 1591     get_pref(PREF_WINDOW_WIDTH, &pref_width, NULL);
 1592     get_pref(PREF_WINDOW_HEIGHT, &pref_height, NULL);
 1593 
 1594     /* parse command line options */
 1595     for (i = 1; i < argc; i++) {
 1596         if (!strncasecmp(argv[i], "-v", 3)) {
 1597             char options[1024];
 1598             get_compile_options(options, sizeof(options));
 1599             printf("\n%s\n", options);
 1600             exit(0);
 1601         }
 1602         if ((!strncasecmp(argv[i], "-h", 3)) ||
 1603             (!strncasecmp(argv[i], "-?", 3))) {
 1604             fprint_usage_string(stderr);
 1605             exit(0);
 1606         }
 1607         if (!strncasecmp(argv[i], "-d", 3)) {
 1608             glob_log_stdout_mask = 0xFFFF;
 1609             glob_log_file_mask = 0xFFFF;
 1610             jp_logf(JP_LOG_DEBUG, "Debug messages on.\n");
 1611         }
 1612         if (!strncasecmp(argv[i], "-p", 3)) {
 1613             skip_plugins = TRUE;
 1614             jp_logf(JP_LOG_INFO, _("Not loading plugins.\n"));
 1615         }
 1616         if (!strncmp(argv[i], "-A", 3)) {
 1617             skip_all_alarms = TRUE;
 1618             jp_logf(JP_LOG_INFO, _("Ignoring all alarms.\n"));
 1619         }
 1620         if (!strncmp(argv[i], "-a", 3)) {
 1621             skip_past_alarms = TRUE;
 1622             jp_logf(JP_LOG_INFO, _("Ignoring past alarms.\n"));
 1623         }
 1624         if ((!strncmp(argv[i], "-s", 3)) ||
 1625             (!strncmp(argv[i], "--remote-sync", 14))) {
 1626             remote_sync = TRUE;
 1627         }
 1628         if ((!strncasecmp(argv[i], "-i", 3)) ||
 1629             (!strncasecmp(argv[i], "--iconic", 9))) {
 1630             iconify = 1;
 1631         }
 1632         if (!strncasecmp(argv[i], "-geometry", 9)) {
 1633 #ifdef PARSE_GEOMETRY
 1634             /* The '=' isn't specified in `man X`, but we will be nice */
 1635             if (argv[i][9] == '=') {
 1636                 geometry_str = argv[i] + 9;
 1637             } else {
 1638                 if (i < argc) {
 1639                     geometry_str = argv[i + 1];
 1640                 }
 1641             }
 1642 #endif
 1643             fprintf(stdout, "Geometry handling in GTK is deprecated as of version 3.20\n");
 1644             fprintf(stdout, "J-Pilot can be compiled with define PARSE_GEOMETRY to use it if its available.\n");
 1645         }
 1646     }
 1647 
 1648     /* Enable UTF8 *AFTER* potential printf to stdout for -h or -v */
 1649     /* Not all terminals(xterm, rxvt, etc.) are UTF8 compliant */
 1650 #if defined(ENABLE_NLS)
 1651     /* generate UTF-8 strings from gettext() & _() */
 1652     bind_textdomain_codeset(EPN, "UTF-8");
 1653 #endif
 1654 
 1655     /* Check to see if ~/.jpilot is there, or create it */
 1656     jp_logf(JP_LOG_DEBUG, "calling check_hidden_dir\n");
 1657     if (check_hidden_dir()) {
 1658         exit(1);
 1659     }
 1660 
 1661     /* Setup the pid file and check for a running jpilot */
 1662     setup_pidfile();
 1663     pid = check_for_jpilot();
 1664 
 1665     if (remote_sync) {
 1666         if (pid) {
 1667             printf("jpilot: syncing jpilot at %d\n", pid);
 1668             kill(pid, SIGUSR1);
 1669             exit(0);
 1670         } else {
 1671             fprintf(stderr, "%s\n", "J-Pilot not running.");
 1672             exit(1);
 1673         }
 1674     } else if (!pid) {
 1675         /* JPilot not running, install signal handler and write pid file */
 1676         signal(SIGUSR1, sync_sig_handler);
 1677         write_pid();
 1678     }
 1679 
 1680     /* Check to see if DB files are there */
 1681     /* If not copy some empty ones over */
 1682     check_copy_DBs_to_home();
 1683 
 1684 #ifdef ENABLE_PLUGINS
 1685     plugin_list = NULL;
 1686     if (!skip_plugins) {
 1687         load_plugins();
 1688     }
 1689     plugin_list = get_plugin_list();
 1690 
 1691     for (temp_list = plugin_list; temp_list; temp_list = temp_list->next) {
 1692         plugin = (struct plugin_s *) temp_list->data;
 1693         jp_logf(JP_LOG_DEBUG, "plugin: [%s] was loaded\n", plugin->name);
 1694         if (plugin) {
 1695             if (plugin->plugin_startup) {
 1696                 info.base_dir = strdup(BASE_DIR);
 1697                 jp_logf(JP_LOG_DEBUG, "calling plugin_startup for [%s]\n", plugin->name);
 1698                 plugin->plugin_startup(&info);
 1699                 if (info.base_dir) {
 1700                     free(info.base_dir);
 1701                 }
 1702             }
 1703         }
 1704     }
 1705 #endif
 1706 
 1707     glob_date_timer_tag = 0;
 1708     glob_child_pid = 0;
 1709 
 1710     /* Create a pipe to send data from sync child to parent */
 1711     if (pipe(filedesc) < 0) {
 1712         jp_logf(JP_LOG_FATAL, _("Unable to open pipe\n"));
 1713         exit(-1);
 1714     }
 1715     pipe_from_child = filedesc[0];
 1716     pipe_to_parent = filedesc[1];
 1717 
 1718     /* Create a pipe to send data from parent to sync child */
 1719     if (pipe(filedesc) < 0) {
 1720         jp_logf(JP_LOG_FATAL, _("Unable to open pipe\n"));
 1721         exit(-1);
 1722     }
 1723     pipe_from_parent = filedesc[0];
 1724     pipe_to_child = filedesc[1];
 1725 
 1726     get_pref(PREF_CHAR_SET, &char_set, NULL);
 1727     /* Deprecated in GTK3 */
 1728 #if 0
 1729     switch (char_set) {
 1730         case CHAR_SET_JAPANESE:
 1731             gtk_rc_parse("gtkrc.ja");
 1732             break;
 1733         case CHAR_SET_TRADITIONAL_CHINESE:
 1734             gtk_rc_parse("gtkrc.zh_TW.Big5");
 1735             break;
 1736         case CHAR_SET_KOREAN:
 1737             gtk_rc_parse("gtkrc.ko");
 1738             break;
 1739             /* Since Now, these are not supported yet. */
 1740 #if 0
 1741             case CHAR_SET_SIMPLIFIED_CHINESE:
 1742               gtk_rc_parse("gtkrc.zh_CN");
 1743               break;
 1744             case CHAR_SET_1250:
 1745               gtk_rc_parse("gtkrc.???");
 1746               break;
 1747             case CHAR_SET_1251:
 1748               gtk_rc_parse("gtkrc.iso-8859-5");
 1749               break;
 1750             case CHAR_SET_1251_B:
 1751               gtk_rc_parse("gtkrc.ru");
 1752               break;
 1753 #endif
 1754         default:
 1755             break;
 1756             /* do nothing */
 1757     }
 1758 #endif
 1759 
 1760     jpilot_master_pid = getpid();
 1761 
 1762     gtk_init(&argc, &argv);
 1763 
 1764     read_gtkrc_file();
 1765 
 1766     get_pref(PREF_USER, NULL, &svalue);
 1767 
 1768     strcpy(title, PN" "VERSION);
 1769     if ((svalue) && (svalue[0])) {
 1770         strcat(title, _(" User: "));
 1771         /* Convert user name so that it can be displayed in window title */
 1772         /* We assume user name is coded in jpilot.rc as it is on the Palm Pilot */
 1773         {
 1774             char *newvalue;
 1775 
 1776             newvalue = charset_p2newj(svalue, -1, char_set);
 1777             strcat(title, newvalue);
 1778             free(newvalue);
 1779         }
 1780     }
 1781 
 1782     window = gtk_widget_new(GTK_TYPE_WINDOW,
 1783                             "type", GTK_WINDOW_TOPLEVEL,
 1784                             "title", title,
 1785                             NULL);
 1786 
 1787     /* Set default size and position of main window */
 1788 #ifdef PARSE_GEOMETRY
 1789     int ret = 0;
 1790     if (geometry_str) {
 1791         ret = gtk_window_parse_geometry(GTK_WINDOW(window), geometry_str);
 1792     }
 1793     if ((!geometry_str) || (ret != 1)) {
 1794         gtk_window_set_default_size(GTK_WINDOW(window), pref_width, pref_height);
 1795     }
 1796 #else
 1797     gtk_window_set_default_size(GTK_WINDOW(window), pref_width, pref_height);
 1798 #endif
 1799     if (iconify) {
 1800         gtk_window_iconify(GTK_WINDOW(window));
 1801     }
 1802 
 1803     /* Set a handler for delete_event that immediately exits GTK. */
 1804     g_signal_connect(G_OBJECT(window), "delete_event",
 1805                        G_CALLBACK(cb_delete_event), NULL);
 1806 
 1807     gtk_container_set_border_width(GTK_CONTAINER(window), 0);
 1808 
 1809     main_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
 1810     g_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
 1811     g_vbox0 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
 1812 
 1813     /* Output Pane */
 1814     output_pane = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
 1815 
 1816     g_signal_connect(G_OBJECT(output_pane), "button_release_event",
 1817                        G_CALLBACK(cb_output2),
 1818                        GINT_TO_POINTER(OUTPUT_RESIZE));
 1819 
 1820     gtk_container_add(GTK_CONTAINER(window), output_pane);
 1821 
 1822     gtk_paned_pack1(GTK_PANED(output_pane), main_vbox, FALSE, FALSE);
 1823 
 1824     /* Create the Menu Bar at the top */
 1825 #ifdef ENABLE_PLUGINS
 1826     get_main_menu(window, &menubar, &menubar_help, plugin_list);
 1827 #else
 1828     get_main_menu(window, &menubar, &menubar_help, NULL);
 1829 #endif
 1830 
 1831     temp_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
 1832     gtk_box_pack_start(GTK_BOX(main_vbox), temp_hbox, FALSE, FALSE, 0);
 1833     gtk_box_pack_start(GTK_BOX(temp_hbox), menubar, FALSE, FALSE, 0);
 1834     gtk_box_pack_end(GTK_BOX(temp_hbox), menubar_help, FALSE, FALSE, 0);
 1835 
 1836     gtk_box_pack_start(GTK_BOX(main_vbox), g_hbox, TRUE, TRUE, 3);
 1837     gtk_container_set_border_width(GTK_CONTAINER(g_hbox), 10);
 1838     gtk_box_pack_start(GTK_BOX(g_hbox), g_vbox0, FALSE, FALSE, 3);
 1839 
 1840     /* Output Text scrolled window */
 1841     temp_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
 1842     gtk_container_set_border_width(GTK_CONTAINER(temp_hbox), 5);
 1843     gtk_paned_pack2(GTK_PANED(output_pane), temp_hbox, FALSE, TRUE);
 1844 
 1845     temp_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 3);
 1846     gtk_container_set_border_width(GTK_CONTAINER(temp_vbox), 6);
 1847     gtk_box_pack_end(GTK_BOX(temp_hbox), temp_vbox, FALSE, FALSE, 0);
 1848 
 1849     g_output_text = GTK_TEXT_VIEW(gtk_text_view_new());
 1850     g_output_text_buffer = gtk_text_view_get_buffer(g_output_text);
 1851     gtk_text_view_set_cursor_visible(g_output_text, FALSE);
 1852     gtk_text_view_set_editable(g_output_text, FALSE);
 1853     gtk_text_view_set_wrap_mode(g_output_text, GTK_WRAP_WORD);
 1854 
 1855     g_output_text_scrolled_window = gtk_scrolled_window_new(NULL, NULL);
 1856     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(g_output_text_scrolled_window),
 1857                                    GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
 1858 
 1859     gtk_container_add(GTK_CONTAINER(g_output_text_scrolled_window), GTK_WIDGET(g_output_text));
 1860     gtk_box_pack_start(GTK_BOX(temp_hbox), GTK_WIDGET(g_output_text_scrolled_window), TRUE, TRUE,0);
 1861 
 1862     button = gtk_button_new_with_label("Clear");
 1863     gtk_box_pack_start(GTK_BOX(temp_vbox), button, TRUE, TRUE, 3);
 1864     g_signal_connect(G_OBJECT(button), "clicked",
 1865                        G_CALLBACK(cb_output),
 1866                        GINT_TO_POINTER(OUTPUT_CLEAR));
 1867 
 1868     button = gtk_button_new_with_label("Remove");
 1869     gtk_box_pack_start(GTK_BOX(temp_vbox), button, TRUE, TRUE, 3);
 1870     g_signal_connect(G_OBJECT(button), "clicked",
 1871                        G_CALLBACK(cb_output),
 1872                        GINT_TO_POINTER(OUTPUT_MINIMIZE));
 1873 
 1874     /* "Datebook" button */
 1875     temp_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
 1876     button_datebook = gtk_button_new();
 1877     g_signal_connect(G_OBJECT(button_datebook), "clicked",
 1878                        G_CALLBACK(cb_app_button), GINT_TO_POINTER(DATEBOOK));
 1879     gtk_box_pack_start(GTK_BOX(g_vbox0), temp_hbox, FALSE, FALSE, 0);
 1880     gtk_box_pack_start(GTK_BOX(temp_hbox), button_datebook, TRUE, FALSE, 0);
 1881 
 1882     /* "Address" button */
 1883     temp_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
 1884     button_address = gtk_button_new();
 1885     g_signal_connect(G_OBJECT(button_address), "clicked",
 1886                        G_CALLBACK(cb_app_button), GINT_TO_POINTER(ADDRESS));
 1887     gtk_box_pack_start(GTK_BOX(g_vbox0), temp_hbox, FALSE, FALSE, 0);
 1888     gtk_box_pack_start(GTK_BOX(temp_hbox), button_address, TRUE, FALSE, 0);
 1889 
 1890     /* "Todo" button */
 1891     temp_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
 1892     button_todo = gtk_button_new();
 1893     g_signal_connect(G_OBJECT(button_todo), "clicked",
 1894                        G_CALLBACK(cb_app_button), GINT_TO_POINTER(TODO));
 1895     gtk_box_pack_start(GTK_BOX(g_vbox0), temp_hbox, FALSE, FALSE, 0);
 1896     gtk_box_pack_start(GTK_BOX(temp_hbox), button_todo, TRUE, FALSE, 0);
 1897 
 1898     /* "Memo" button */
 1899     temp_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
 1900     button_memo = gtk_button_new();
 1901     g_signal_connect(G_OBJECT(button_memo), "clicked",
 1902                        G_CALLBACK(cb_app_button), GINT_TO_POINTER(MEMO));
 1903     gtk_box_pack_start(GTK_BOX(g_vbox0), temp_hbox, FALSE, FALSE, 0);
 1904     gtk_box_pack_start(GTK_BOX(temp_hbox), button_memo, TRUE, FALSE, 0);
 1905 
 1906     gtk_widget_set_name(button_datebook, "button_app");
 1907     gtk_widget_set_name(button_address, "button_app");
 1908     gtk_widget_set_name(button_todo, "button_app");
 1909     gtk_widget_set_name(button_memo, "button_app");
 1910 
 1911 
 1912     /* Get preference to show tooltips */
 1913     get_pref(PREF_SHOW_TOOLTIPS, &show_tooltips, NULL);
 1914 
 1915     /* Create key accelerator */
 1916     accel_group = gtk_accel_group_new();
 1917     gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);
 1918 
 1919     /* Lock/Unlock/Mask buttons */
 1920     button_locked = gtk_button_new();
 1921     button_masklocked = gtk_button_new();
 1922     button_unlocked = gtk_button_new();
 1923     g_signal_connect(G_OBJECT(button_locked), "clicked",
 1924                        G_CALLBACK(cb_private),
 1925                        GINT_TO_POINTER(SHOW_PRIVATES));
 1926     g_signal_connect(G_OBJECT(button_masklocked), "clicked",
 1927                        G_CALLBACK(cb_private),
 1928                        GINT_TO_POINTER(HIDE_PRIVATES));
 1929     g_signal_connect(G_OBJECT(button_unlocked), "clicked",
 1930                        G_CALLBACK(cb_private),
 1931                        GINT_TO_POINTER(MASK_PRIVATES));
 1932     gtk_box_pack_start(GTK_BOX(g_vbox0), button_locked, FALSE, FALSE, 20);
 1933     gtk_box_pack_start(GTK_BOX(g_vbox0), button_masklocked, FALSE, FALSE, 20);
 1934     gtk_box_pack_start(GTK_BOX(g_vbox0), button_unlocked, FALSE, FALSE, 20);
 1935 
 1936     set_tooltip(show_tooltips,
 1937                 button_locked, _("Show private records   Ctrl+Z"));
 1938     gtk_widget_add_accelerator(button_locked, "clicked", accel_group,
 1939                                GDK_KEY_z, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
 1940 
 1941     set_tooltip(show_tooltips,
 1942                 button_masklocked, _("Hide private records   Ctrl+Z"));
 1943     gtk_widget_add_accelerator(button_masklocked, "clicked", accel_group,
 1944                                GDK_KEY_z, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
 1945 
 1946     set_tooltip(show_tooltips,
 1947                 button_unlocked, _("Mask private records   Ctrl+Z"));
 1948     gtk_widget_add_accelerator(button_unlocked, "clicked", accel_group,
 1949                                GDK_KEY_z, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
 1950 
 1951     /* "Sync" button */
 1952     button_sync = gtk_button_new();
 1953     g_signal_connect(G_OBJECT(button_sync), "clicked",
 1954                        G_CALLBACK(cb_sync),
 1955                        GINT_TO_POINTER(skip_plugins ? SYNC_NO_PLUGINS : 0));
 1956     gtk_box_pack_start(GTK_BOX(g_vbox0), button_sync, FALSE, FALSE, 3);
 1957 
 1958     set_tooltip(show_tooltips,
 1959                 button_sync, _("Sync your palm to the desktop   Ctrl+Y"));
 1960     gtk_widget_add_accelerator(button_sync, "clicked", accel_group, GDK_KEY_y,
 1961                                GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
 1962 
 1963     /* "Cancel Sync" button */
 1964     button_cancel_sync = gtk_button_new();
 1965     g_signal_connect(G_OBJECT(button_cancel_sync), "clicked",
 1966                        G_CALLBACK(cb_cancel_sync),
 1967                        NULL);
 1968     gtk_box_pack_start(GTK_BOX(g_vbox0), button_cancel_sync, FALSE, FALSE, 3);
 1969 
 1970     set_tooltip(show_tooltips,
 1971                 button_cancel_sync, _("Stop Sync process"));
 1972 
 1973     /* "Backup" button in left column */
 1974     button_backup = gtk_button_new();
 1975     g_signal_connect(G_OBJECT(button_backup), "clicked",
 1976                        G_CALLBACK(cb_sync),
 1977                        GINT_TO_POINTER
 1978                                (skip_plugins ? SYNC_NO_PLUGINS | SYNC_FULL_BACKUP
 1979                                              : SYNC_FULL_BACKUP));
 1980     gtk_box_pack_start(GTK_BOX(g_vbox0), button_backup, FALSE, FALSE, 3);
 1981 
 1982     set_tooltip(show_tooltips,
 1983                 button_backup, _("Sync your palm to the desktop\n"
 1984                                  "and then do a backup"));
 1985 
 1986     /* Separator */
 1987     separator = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
 1988     gtk_box_pack_start(GTK_BOX(g_vbox0), separator, FALSE, TRUE, 5);
 1989 
 1990     /* Creates the 2 main boxes that are changeable */
 1991     create_main_boxes();
 1992 
 1993     gtk_widget_show_all(window);
 1994     gtk_widget_show(window);
 1995 
 1996     //gtk2 style = gtk_widget_get_style(window);
 1997 
 1998     /* Jpilot Icon pixbuf */
 1999     //pixbuf = gdk_pixmap_create_from_xpm_d(window->window, &mask, NULL, jpilot_icon4_xpm);
 2000     //this method no longer exists in gtk3.  X11 handles this anyway.
 2001     // gdk_window_set_icon(window->window, NULL, pixbuf, mask);
 2002     gdk_window_set_icon_name(gtk_widget_get_window(window), PN);
 2003 
 2004     /* Create "Datebook" pixbuf */
 2005     pixbuf = gdk_pixbuf_new_from_xpm_data((const char **) datebook_xpm);
 2006     pixbufwid = gtk_image_new_from_pixbuf(pixbuf);
 2007     gtk_widget_show(pixbufwid);
 2008     gtk_container_add(GTK_CONTAINER(button_datebook), pixbufwid);
 2009     gtk_button_set_relief(GTK_BUTTON(button_datebook), GTK_RELIEF_NONE);
 2010 
 2011     /* Create "Address" pixbuf */
 2012     pixbuf = gdk_pixbuf_new_from_xpm_data((const char **) address_xpm);
 2013     pixbufwid = gtk_image_new_from_pixbuf(pixbuf);
 2014     gtk_widget_show(pixbufwid);
 2015     gtk_container_add(GTK_CONTAINER(button_address), pixbufwid);
 2016     gtk_button_set_relief(GTK_BUTTON(button_address), GTK_RELIEF_NONE);
 2017 
 2018     /* Create "Todo" pixbuf */
 2019     pixbuf = gdk_pixbuf_new_from_xpm_data((const char **) todo_xpm);
 2020     pixbufwid = gtk_image_new_from_pixbuf(pixbuf);
 2021     gtk_widget_show(pixbufwid);
 2022     gtk_container_add(GTK_CONTAINER(button_todo), pixbufwid);
 2023     gtk_button_set_relief(GTK_BUTTON(button_todo), GTK_RELIEF_NONE);
 2024 
 2025     /* Create "Memo" pixbuf */
 2026     pixbuf = gdk_pixbuf_new_from_xpm_data((const char **) memo_xpm);
 2027     pixbufwid = gtk_image_new_from_pixbuf(pixbuf);
 2028     gtk_widget_show(pixbufwid);
 2029     gtk_container_add(GTK_CONTAINER(button_memo), pixbufwid);
 2030     gtk_button_set_relief(GTK_BUTTON(button_memo), GTK_RELIEF_NONE);
 2031 
 2032     /* Show locked/unlocked/masked button */
 2033 #ifdef ENABLE_PRIVATE
 2034     gtk_widget_show(button_locked);
 2035     gtk_widget_hide(button_masklocked);
 2036     gtk_widget_hide(button_unlocked);
 2037 #else
 2038     gtk_widget_hide(button_locked);
 2039     gtk_widget_hide(button_masklocked);
 2040     gtk_widget_show(button_unlocked);
 2041 #endif
 2042 
 2043     /* Create "locked" pixbuf */
 2044     pixbuf = gdk_pixbuf_new_from_xpm_data((const char **) locked_xpm);
 2045     pixbufwid = gtk_image_new_from_pixbuf(pixbuf);
 2046     gtk_widget_show(pixbufwid);
 2047     gtk_container_add(GTK_CONTAINER(button_locked), pixbufwid);
 2048 
 2049     /* Create "masked" pixbuf */
 2050     pixbuf = gdk_pixbuf_new_from_xpm_data((const char **) masklocked_xpm);
 2051     pixbufwid = gtk_image_new_from_pixbuf(pixbuf);
 2052     gtk_widget_show(pixbufwid);
 2053     gtk_container_add(GTK_CONTAINER(button_masklocked), pixbufwid);
 2054 
 2055     /* Create "unlocked" pixbuf */
 2056     pixbuf = gdk_pixbuf_new_from_xpm_data((const char **) unlocked_xpm);
 2057     pixbufwid = gtk_image_new_from_pixbuf(pixbuf);
 2058     gtk_widget_show(pixbufwid);
 2059     gtk_container_add(GTK_CONTAINER(button_unlocked), pixbufwid);
 2060 
 2061     /* Create "sync" pixbuf */
 2062     pixbuf = gdk_pixbuf_new_from_xpm_data((const char **) sync_xpm);
 2063     pixbufwid = gtk_image_new_from_pixbuf(pixbuf);
 2064     gtk_widget_show(pixbufwid);
 2065     gtk_container_add(GTK_CONTAINER(button_sync), pixbufwid);
 2066 
 2067     /* Create "cancel sync" pixbuf */
 2068     /* Hide until sync process started */
 2069     gtk_widget_hide(button_cancel_sync);
 2070     pixbuf = gdk_pixbuf_new_from_xpm_data((const char **) cancel_sync_xpm);
 2071     pixbufwid = gtk_image_new_from_pixbuf(pixbuf);
 2072     gtk_widget_show(pixbufwid);
 2073     gtk_container_add(GTK_CONTAINER(button_cancel_sync), pixbufwid);
 2074 
 2075 
 2076     /* Create "backup" pixbuf */
 2077     gtk_widget_hide(button_cancel_sync);
 2078     pixbuf = gdk_pixbuf_new_from_xpm_data((const char **) backup_xpm);
 2079     pixbufwid = gtk_image_new_from_pixbuf(pixbuf);
 2080     gtk_widget_show(pixbufwid);
 2081     gtk_container_add(GTK_CONTAINER(button_backup), pixbufwid);
 2082 
 2083     set_tooltip(show_tooltips, button_datebook, _("Datebook/Go to Today"));
 2084     set_tooltip(show_tooltips, button_address, _("Address Book"));
 2085     set_tooltip(show_tooltips, button_todo, _("ToDo List"));
 2086     set_tooltip(show_tooltips, button_memo, _("Memo Pad"));
 2087 
 2088     /* Set a callback for our pipe from the sync child process */
 2089     GIOChannel *channel = g_io_channel_unix_new(pipe_from_child);
 2090     g_io_add_watch(channel,
 2091                    G_IO_IN | G_IO_HUP | G_IO_ERR,
 2092                    cb_read_pipe_from_child,
 2093                    window);
 2094 
 2095     //gtk2 gdk_input_add(pipe_from_child, GDK_INPUT_READ, cb_read_pipe_from_child, window);
 2096 
 2097     get_pref(PREF_LAST_APP, &ivalue, NULL);
 2098     /* We don't want to start up to a plugin because the plugin might
 2099      * repeatedly segfault.  Of course main apps can do that, but since I
 2100      * handle the email support...  */
 2101     if ((ivalue == ADDRESS) ||
 2102         (ivalue == DATEBOOK) ||
 2103         (ivalue == TODO) ||
 2104         (ivalue == MEMO)) {
 2105         cb_app_button(NULL, GINT_TO_POINTER(ivalue));
 2106     }
 2107 
 2108     /* Set the pane size */
 2109     height = 0;
 2110     // width = gdk_window_get_width(gtk_widget_get_window(window));
 2111     height = gdk_window_get_height(gtk_widget_get_window(window));
 2112     gtk_paned_set_position(GTK_PANED(output_pane), height);
 2113 
 2114     alarms_init(skip_past_alarms, skip_all_alarms);
 2115 
 2116     /* In-line code to switch user to UTF-8 encoding.
 2117      * Should probably be made a subroutine */
 2118     {
 2119         long utf_encoding;
 2120         char *button_text[] =
 2121                 {N_("Do it now"), N_("Remind me later"), N_("Don't tell me again!")};
 2122 
 2123         /* check if a UTF-8 one is used */
 2124         if (char_set >= CHAR_SET_UTF)
 2125             set_pref(PREF_UTF_ENCODING, 1, NULL, TRUE);
 2126 
 2127         get_pref(PREF_UTF_ENCODING, &utf_encoding, NULL);
 2128         if (0 == utf_encoding) {
 2129             /* user has not switched to UTF */
 2130             int ret;
 2131             char text[1000];
 2132 
 2133             g_snprintf(text, sizeof(text),
 2134                        _("J-Pilot uses the GTK2 graphical toolkit. "
 2135                          "This version of the toolkit uses UTF-8 to encode characters.\n"
 2136                          "You should select a UTF-8 charset so that you can see non-ASCII characters (accents for example).\n"
 2137                          "\n"
 2138                          /* Coded to reuse existing i18n strings */
 2139                          "Go to the menu \"%s\" and change the \"%s\"."), _("/File/Preferences"), _("Character Set"));
 2140             ret = dialog_generic(GTK_WINDOW(window),
 2141                                  _("Select a UTF-8 encoding"), DIALOG_QUESTION, text, 3, button_text);
 2142 
 2143             switch (ret) {
 2144                 case DIALOG_SAID_1:
 2145                     cb_prefs_gui(NULL, window);
 2146                     break;
 2147                 case DIALOG_SAID_2:
 2148                     /* Do nothing and remind user at next program invocation */
 2149                     break;
 2150                 case DIALOG_SAID_3:
 2151                     set_pref(PREF_UTF_ENCODING, 1, NULL, TRUE);
 2152                     break;
 2153             }
 2154         }
 2155     }
 2156 
 2157     g_idle_add(cb_check_version, window);
 2158 
 2159     gtk_main();
 2160 
 2161     otherconv_free();
 2162 
 2163     return EXIT_SUCCESS;
 2164 }