/* * Module for main() function and some initializations. * * Copyright INOUE Seiichiro , licensed under the GPL. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "diff.h" #include "misc.h" #include "gui.h" #include "gdwin.h" #include "dirview.h" #include "onepaneview.h" #include "multipaneview.h" #include "mergeview.h" #include "properties.h" #include "style.h" /* Private function declarations */ static void gtkdiff_init(void); static void argument_init(GDiffWindow *gdwin, char **arg_files); #if !defined(DEBUG) || defined(MSG_DIALOG) static void msg_handler(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data); #endif static void signal_child(int sig); static char *merge_outfile = NULL; int main(int argc, char *argv[]) { GDiffWindow *gdwin; char **arg_files; static char *geometry_string = NULL; poptContext ctx; static const struct poptOption options[] = { {"geometry", 'g', POPT_ARG_STRING, &geometry_string, 0, N_("Specify geometry"), N_("GEOMETRY")}, {"output", 'o', POPT_ARG_STRING, &merge_outfile, 0, N_("Merge output filename"), N_("FILENAME")}, {NULL, '\0', 0, NULL, 0, NULL, NULL} }; /* Initialize the i18n stuff */ bindtextdomain(PACKAGE, GNOMELOCALEDIR); textdomain(PACKAGE); /* * gnome_init() is always called at the beginning of a program. it * takes care of initializing both Gtk and GNOME. It also parses * the command-line arguments. */ gnome_init_with_popt_table(APPNAME, VERSION, argc, argv, options, 0, &ctx); #if !defined(DEBUG) || defined(MSG_DIALOG) g_log_set_handler(G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, msg_handler, NULL); #endif style_init(); gtkdiff_init(); properties_init(); /* Create window */ gdwin = gdwin_new(geometry_string); arg_files = poptGetArgs(ctx); argument_init(gdwin, arg_files); poptFreeContext(ctx); gtk_main(); /* after gtk_main_quit() */ properties_exit(); return 0; } /* ---The followings are private functions--- */ /** * gtkdiff_init: * In the future, it will do more. **/ static void gtkdiff_init(void) { #ifdef HAVE_SIGACTION struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = signal_child; sa.sa_flags = SA_RESTART; if (sigaction(SIGCHLD, &sa, NULL) == -1) { gtk_exit(1); } #else signal(SIGCHLD, signal_child); #endif } /** * argument_init: * Take care of the files specified by command line option. **/ static void argument_init(GDiffWindow *gdwin, char **arg_files) { const char *fname[MAX_NUM_COMPARE_FILES]; FileType ftype[MAX_NUM_COMPARE_FILES]; GtkWidget *new_view = NULL; DiffDir *diffdir; int n; gboolean is_diff3 = FALSE; if (arg_files && arg_files[0] && arg_files[1]) { fname[FIRST_FILE] = arg_files[0]; fname[SECOND_FILE] = arg_files[1]; if (arg_files[2]) { fname[THIRD_FILE] = arg_files[2]; is_diff3 = TRUE; } } else return; for (n = 0; n < (is_diff3 ? 3 : 2); n++) { ftype[n] = check_filetype(fname[n]); } if (ftype[0] != ftype[1] || (ftype[0] != DIRECTORY && ftype[0] != REGULARFILE)) { g_message(_("you can't compare %1$s and %2$s.\n"), fname[0], fname[1]); return; } if (is_diff3) { if (ftype[1] != ftype[2]) { g_message(_("you can't compare %1$s, %2$s and %3$s.\n"), fname[0], fname[1], fname[2]); return; } } /* Now, directory diff3 isn't supported */ if (is_diff3 && ftype[0] == DIRECTORY) { g_message("Currently, directory diff3 is not supported.");/* No need to translate */ return; } if (is_diff3) diffdir = diffdir_new(fname[FIRST_FILE], fname[SECOND_FILE], fname[THIRD_FILE], g_pref.diff3_args); else diffdir = diffdir_new(fname[FIRST_FILE], fname[SECOND_FILE], NULL, g_pref.diff_args); if (merge_outfile) g_pref.fvpref.view_type = MERGE_MASK_VIEW; if (ftype[0] == DIRECTORY) { new_view = gdiff_dirview_new(diffdir); } else if (ftype[0] == REGULARFILE) { DiffFiles *dfiles = g_slist_nth_data(diffdir->dfiles_list, 0); if (g_pref.fvpref.view_type & ONEPANE_MASK_VIEW) new_view = gdiff_onepview_new(diffdir, dfiles, FALSE); else if (g_pref.fvpref.view_type & MULTIPANE_MASK_VIEW) new_view = gdiff_multipview_new(diffdir, dfiles, FALSE); else if (g_pref.fvpref.view_type & MERGE_MASK_VIEW) { new_view = gdiff_mergeview_new(diffdir, dfiles, FALSE); if (merge_outfile) gdiff_mergeview_set_outfile(GDIFF_MERGEVIEW(new_view), merge_outfile); } else return; } else g_assert_not_reached(); gdwin_add_view(gdwin, new_view); } #if !defined(DEBUG) || defined(MSG_DIALOG) /** * msg_handler: * Handler for g_message(). Show a modal dialog box. **/ static void msg_handler(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data) { GtkWidget *dialog; dialog = gnome_message_box_new(message, GNOME_MESSAGE_BOX_WARNING, GNOME_STOCK_BUTTON_OK, NULL); /* I can't use this, because it internally calls gtk_widget_show(), so set_position doesn't work. dialog = gnome_warning_dialog(message); */ gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE); gtk_widget_show(dialog); } #endif /** * signal_child: * (Unix)signal handler. * It takes care of child process death. **/ static void signal_child(int sig) { int stat; if (sig == SIGCHLD) { #ifdef HAVE_WAITPID while (waitpid(-1, &stat, WNOHANG) > 0) ; #else wait(&stat); #endif } }