/* * GUI actions module * See actions.h about the details. * * Copyright INOUE Seiichiro , licensed under the GPL. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #if defined(HAVE_ERRNO_H) #include #else defined(HAVE_SYS_ERRNO_H) #include #endif #include #include "diff.h" #include "misc.h" #include "gui.h" #include "gdwin.h" #include "actions.h" #include "basepane-widget.h" #include "merge-widget.h" #include "dirview.h" #include "onepaneview.h" #include "multipaneview.h" #include "mergeview.h" #include "viewmisc.h" #include "guimisc.h" #include "menu-tool-bar.h" #include "hide.h" #include "properties.h" /* Private function declarations */ static void act_dv_reload(GtkWidget *dirview); static void act_fv_reload(GtkWidget *fview); static gboolean is_file_modified(GtkWidget *fview, GdiffBasePane *basepane); static char* get_filename(const char *default_fname); #ifndef DEBUG static void filesel_ok_click(GtkWidget *w, gpointer data); static void filesel_destroy_cb(GtkWidget *w, gpointer data); #endif /* Macros */ /* very annoying.. I could make a base class for them... */ #define update_fv_menu(fview, pref) G_STMT_START { \ GDiffWindow *gdwin = NULL; \ \ if (GDIFF_IS_ONEPVIEW(fview)) { \ gdwin = GDIFF_ONEPVIEW(fview)->gdwin; \ menubar_update(gdwin, &pref, \ GDIFF_ONEPVIEW_NUM_FILES(fview) == 2 ? ONEPANE2_VIEW : ONEPANE3_VIEW); \ } else if (GDIFF_IS_MULTIPVIEW(fview)) { \ gdwin = GDIFF_MULTIPVIEW(fview)->gdwin; \ menubar_update(gdwin, &pref, \ GDIFF_MULTIPVIEW_NUM_FILES(fview) == 2 ? MULTIPANE2_VIEW : MULTIPANE3_VIEW); \ } else if (GDIFF_IS_MERGEVIEW(fview)) { \ gdwin = GDIFF_MERGEVIEW(fview)->gdwin; \ menubar_update(gdwin, &pref, \ GDIFF_MERGEVIEW_NUM_FILES(fview) == 2 ? MERGE2_VIEW : MERGE3_VIEW); \ } \ } G_STMT_END /* The follwoing macros assume the variables are already defined. */ #define get_fview_vals1(fview) G_STMT_START { \ if (GDIFF_IS_ONEPVIEW(fview)) { \ gdwin = GDIFF_ONEPVIEW(fview)->gdwin; \ diffdir = GDIFF_ONEPVIEW_DIFFDIR(fview); \ dfiles = GDIFF_ONEPVIEW_DFILES(fview); \ is_under_dir = GDIFF_ONEPVIEW(fview)->is_under_dir; \ } else if (GDIFF_IS_MULTIPVIEW(fview)) { \ gdwin = GDIFF_MULTIPVIEW(fview)->gdwin; \ diffdir = GDIFF_MULTIPVIEW_DIFFDIR(fview); \ dfiles = GDIFF_MULTIPVIEW_DFILES(fview); \ is_under_dir = GDIFF_MULTIPVIEW(fview)->is_under_dir; \ } else if (GDIFF_IS_MERGEVIEW(fview)) { \ gdwin = GDIFF_MERGEVIEW(fview)->gdwin; \ diffdir = GDIFF_MERGEVIEW_DIFFDIR(fview); \ dfiles = GDIFF_MERGEVIEW_DFILES(fview); \ is_under_dir = GDIFF_MERGEVIEW(fview)->is_under_dir; \ } \ } G_STMT_END /* Don't forget to free *fnames[] */ #define get_fview_vals2(fview) G_STMT_START { \ if (GDIFF_IS_ONEPVIEW(fview)) { \ fnames[0] = g_strdup(GDIFF_ONEPVIEW_FILENAME(fview, FIRST_FILE)); \ fnames[1] = g_strdup(GDIFF_ONEPVIEW_FILENAME(fview, SECOND_FILE)); \ if (GDIFF_ONEPVIEW_NUM_FILES(fview) == 2) { \ vtype = ONEPANE2_VIEW; \ } else { \ fnames[2] = g_strdup(GDIFF_ONEPVIEW_FILENAME(fview, THIRD_FILE)); \ vtype = ONEPANE3_VIEW; \ } \ } else if (GDIFF_IS_MULTIPVIEW(fview)) { \ fnames[0] = g_strdup(GDIFF_MULTIPVIEW_FILENAME(fview, FIRST_FILE)); \ fnames[1] = g_strdup(GDIFF_MULTIPVIEW_FILENAME(fview, SECOND_FILE)); \ if (GDIFF_MULTIPVIEW_NUM_FILES(fview) == 2) {\ vtype = MULTIPANE2_VIEW; \ } else { \ fnames[2] = g_strdup(GDIFF_MULTIPVIEW_FILENAME(fview, THIRD_FILE)); \ vtype = MULTIPANE3_VIEW; \ } \ } else if (GDIFF_IS_MERGEVIEW(fview)) { \ fnames[0] = g_strdup(GDIFF_MERGEVIEW_FILENAME(fview, FIRST_FILE)); \ fnames[1] = g_strdup(GDIFF_MERGEVIEW_FILENAME(fview, SECOND_FILE));\ if (GDIFF_MERGEVIEW_NUM_FILES(fview) == 2) {\ vtype = MERGE2_VIEW; \ } else { \ fnames[2] = g_strdup(GDIFF_MERGEVIEW_FILENAME(fview, THIRD_FILE)); \ vtype = MERGE3_VIEW; \ } \ } \ } G_STMT_END #define is_fview_under_dir(fview) \ ((GDIFF_IS_ONEPVIEW(fview) \ && GDIFF_ONEPVIEW(view)->is_under_dir) \ || (GDIFF_IS_MULTIPVIEW(fview) \ && GDIFF_MULTIPVIEW(view)->is_under_dir) \ || (GDIFF_IS_MERGEVIEW(fview) \ && GDIFF_MERGEVIEW(view)->is_under_dir)) /** Actions for common view **/ /** * act_close_view: * If @view is a directory view, close all file views under this directory, * and close its own directory view. * If @view is a file view, there is two cases. * If @view is under a directory view, just hide it. * (actual close is up to the directory view) * If @view is not under a directory view, do check whether a visible view * for the same backend data exists or not. * If it exists, just hide it (actual close is up to the last visible view). * If there is no other visible view for this backend data, close all file views. **/ void act_close_view(GtkWidget *view) { if (view == NULL) return; if (GDIFF_IS_DIRVIEW(view)) { GDiffWindow *gdwin = GDIFF_DIRVIEW(view)->gdwin; const DiffDir *diffdir = GDIFF_DIRVIEW_DIFFDIR(view); GtkWidget *fview; while ((fview = gdwin_find_fview_with_diffdir(gdwin, diffdir))) { gdwin_remove_view(gdwin, fview); } gdwin_remove_view(gdwin, view); } else { if (is_fview_under_dir(view)) { gtk_widget_hide(view); } else { GDiffWindow *gdwin = NULL; DiffDir *diffdir = NULL; DiffFiles *dfiles = NULL; gboolean is_under_dir = FALSE; GtkWidget *tmp_fview; get_fview_vals1(view); /* Kludge: hide own */ gtk_widget_hide(view); /* If there are no other visible views, close all file views for this dfiles */ if ((tmp_fview = gdwin_find_fview_with_dfiles(gdwin, dfiles, TRUE)) == NULL) { gdwin_remove_view(gdwin, view); while ((tmp_fview = gdwin_find_fview_with_dfiles(gdwin, dfiles, FALSE))) { gdwin_remove_view(gdwin, tmp_fview); } } } } } void act_reload(GtkWidget *view) { if (view == NULL) return; if (GDIFF_IS_DIRVIEW(view)) act_dv_reload(view); else act_fv_reload(view); } /** Actions for directory view **/ /** * act_dv_show_path: * Show paths on directory view, otherwise show only file names. **/ void act_dv_show_path(GtkWidget *dirview, ShowPathDView show_path) { if (dirview == NULL || !GDIFF_IS_DIRVIEW(dirview)) return; g_pref.dvpref.show_path = show_path;/* global preference */ GDIFF_DIRVIEW_PREF(dirview).show_path = show_path; gdiff_dirview_redisplay(GDIFF_DIRVIEW(dirview)); } /** * act_dv_rowhide_func:: * To hide(or show) the row of directory view depending on the filter functions. **/ void act_dv_rowhide_func(GtkWidget *dirview, RowHideMask rh_mask, gboolean mask_on) { if (dirview == NULL || !GDIFF_IS_DIRVIEW(dirview)) return; if (mask_on == TRUE) { GDIFF_DIRVIEW_PREF(dirview).row_hide_func_mask |= rh_mask; } else { GDIFF_DIRVIEW_PREF(dirview).row_hide_func_mask &= ~rh_mask; } g_pref.dvpref.row_hide_func_mask = GDIFF_DIRVIEW_PREF(dirview).row_hide_func_mask;/* global preference */ gdiff_dirview_redisplay(GDIFF_DIRVIEW(dirview)); } /** * act_dv_rowhide_stat: * To hide(or show) the row of directory view depending on the files stat. **/ void act_dv_rowhide_stat(GtkWidget *dirview, FilesStatus hide_mask, gboolean mask_on) { if (dirview == NULL || !GDIFF_IS_DIRVIEW(dirview)) return; if (mask_on == TRUE) { GDIFF_DIRVIEW_PREF(dirview).row_hide_stat_mask |= hide_mask; } else { GDIFF_DIRVIEW_PREF(dirview).row_hide_stat_mask &= ~hide_mask; } g_pref.dvpref.row_hide_stat_mask = GDIFF_DIRVIEW_PREF(dirview).row_hide_stat_mask;/* global preference */ gdiff_dirview_redisplay(GDIFF_DIRVIEW(dirview)); } /** * act_dv_checksum: * Calculate check sum of the files. Result is shown in status bar. **/ void act_dv_checksum(GtkWidget *dirview) { if (dirview == NULL || !GDIFF_IS_DIRVIEW(dirview)) return; gdiff_dirview_checksum(GDIFF_DIRVIEW(dirview)); } /** * act_dv_reload: * Close the current directory view, and create a new directory view * for the same directories. **/ static void act_dv_reload(GtkWidget *dirview) { /* XXX: diff3 is not supported yet */ GDiffWindow *gdwin; const char *dirname1; const char *dirname2; GtkWidget *new_dirview; DiffDir *new_diffdir; Preference pref = g_pref;/* copy */ /* Keep the necessary info from the current view before close it */ gdwin = GDIFF_DIRVIEW(dirview)->gdwin; dirname1 = g_strdup(GDIFF_DIRVIEW(dirview)->dirname[FIRST_FILE]); dirname2 = g_strdup(GDIFF_DIRVIEW(dirview)->dirname[SECOND_FILE]); act_close_view(dirview); new_diffdir = diffdir_new(dirname1, dirname2, NULL, g_pref.diff_args); new_dirview = gdiff_dirview_new(new_diffdir); gdwin_add_view(gdwin, new_dirview); g_free((gpointer)dirname1); g_free((gpointer)dirname2); /* update menu */ pref.dvpref = GDIFF_DIRVIEW_PREF(new_dirview);/* copy */ menubar_update(gdwin, &pref, DIR_VIEW); } /** Actions for file view **/ /** * act_fv_mode_change: * Change the view type. * At first, search the specified-type view. * If it exists, focus it. * If it doesn't exist, opne a new view in the specified-type. **/ void act_fv_mode_change(GtkWidget *fview, ViewType vtype) { GdiffBasePane *basepane; GDiffWindow *gdwin = NULL; DiffDir *diffdir = NULL;/* passed to a new view */ DiffFiles *dfiles = NULL;/* passed to a new view */ gboolean is_under_dir = FALSE;/* passed to a new view */ GtkWidget *fview_vtype;/* view with this type */ if (fview == NULL || GDIFF_IS_DIRVIEW(fview)) return; basepane = view_get_pane(fview, "basepane"); if (basepane== NULL) return; if (is_file_modified(fview, basepane) == TRUE) return; g_pref.fvpref.view_type = vtype;/* global preference */ get_fview_vals1(fview); fview_vtype = gdwin_find_fview_with_vtype(gdwin, dfiles, vtype); if (fview_vtype) { /* Desirable view is already open, so focus it */ gint page; page = gtk_notebook_page_num(gdwin->notebook, fview_vtype); if (!GTK_WIDGET_VISIBLE(fview_vtype)) { gtk_widget_show(fview_vtype); } gtk_notebook_set_page(gdwin->notebook, page); } else { GtkWidget *new_view = NULL; /* Desirable view is not open, so open it */ if (vtype & ONEPANE_MASK_VIEW) new_view = GTK_WIDGET(gdiff_onepview_new(diffdir, dfiles, is_under_dir)); else if (vtype & MULTIPANE_MASK_VIEW) new_view = GTK_WIDGET(gdiff_multipview_new(diffdir, dfiles, is_under_dir)); else if (vtype & MERGE_MASK_VIEW) new_view = GTK_WIDGET(gdiff_mergeview_new(diffdir, dfiles, is_under_dir)); else return; gdwin_add_view(gdwin, new_view); } } /** * act_fv_show_linenum: * Toggle show(hide) the line numbers for the view. **/ void act_fv_show_linenum(GtkWidget *fview, gboolean to_show) { GdiffBasePane *basepane; GdiffBasePane *auxpane = NULL; Preference pref = g_pref;/* copy */ if (fview == NULL || GDIFF_IS_DIRVIEW(fview)) return; basepane = view_get_pane(fview, "basepane"); if (basepane == NULL) return; if (is_file_modified(fview, basepane) == TRUE) return; gdiff_basepane_show_linenum(basepane, to_show); if (GDIFF_IS_MERGEVIEW(fview)) { auxpane = view_get_pane(fview, "auxpane"); if (auxpane) { gdiff_basepane_show_linenum(auxpane, to_show); } } /* update global preference */ g_pref.fvpref.show_line_num = to_show; /* update menu */ if (auxpane) pref.fvpref = auxpane->pref;/* copy */ else pref.fvpref = basepane->pref;/* copy */ update_fv_menu(fview, pref); } /** * act_fv_highlight: **/ void act_fv_highlight(GtkWidget *fview, gboolean to_highlight) { GdiffBasePane *basepane; GdiffBasePane *auxpane = NULL; Preference pref = g_pref;/* copy */ if (fview == NULL || GDIFF_IS_DIRVIEW(fview)) return; basepane = view_get_pane(fview, "basepane"); if (basepane == NULL) return; gdiff_basepane_set_highlight(basepane, to_highlight); if (GDIFF_IS_MERGEVIEW(fview)) { auxpane = view_get_pane(fview, "auxpane"); if (auxpane) { gdiff_basepane_set_highlight(auxpane, to_highlight); } } /* update global preference */ g_pref.fvpref.highlight = to_highlight; /* update menu */ if (auxpane) pref.fvpref = auxpane->pref;/* copy */ else pref.fvpref = basepane->pref;/* copy */ update_fv_menu(fview, pref); } /** * act_fv_show_fill: * Show(hide) the fill parts for the view. **/ void act_fv_show_fill(GtkWidget *fview, gboolean to_show) { GdiffBasePane *basepane; GdiffBasePane *auxpane = NULL; Preference pref = g_pref;/* copy */ if (fview == NULL || GDIFF_IS_DIRVIEW(fview)) return; basepane = view_get_pane(fview, "basepane"); if (basepane == NULL) return; if (is_file_modified(fview, basepane) == TRUE) return; gdiff_basepane_show_fill(basepane, to_show); if (GDIFF_IS_MERGEVIEW(fview)) { auxpane = view_get_pane(fview, "auxpane"); if (auxpane) { gdiff_basepane_show_fill(auxpane, to_show); } } /* update global preference */ g_pref.fvpref.show_fill = to_show; /* update menu */ if (auxpane) pref.fvpref = auxpane->pref;/* copy */ else if (auxpane) pref.fvpref = basepane->pref;/* copy */ update_fv_menu(fview, pref); } /** * act_fv_go_dirview: * Search the appropriate directory view, and focus it. **/ void act_fv_go_dirview(GtkWidget *fview) { const GDiffWindow *gdwin = NULL; const DiffDir *diffdir = NULL; const DiffFiles *dfiles = NULL;/* not used */ gboolean is_under_dir = FALSE;/* not used */ GtkWidget *dirview; if (fview == NULL || GDIFF_IS_DIRVIEW(fview)) return; get_fview_vals1(fview); dirview = gdwin_find_dirview_with_diffdir(gdwin, diffdir); if (dirview) { int page; page = gtk_notebook_page_num(gdwin->notebook, dirview); gtk_notebook_set_page(gdwin->notebook, page); } } /** * act_fv_toggle_textwrap: * Toggle the view's text widget line wrap mode. **/ void act_fv_toggle_textwrap(GtkWidget *fview) { GdiffBasePane *basepane; GdiffBasePane *auxpane = NULL; gboolean b_wrap; Preference pref = g_pref;/* copy */ if (fview == NULL || GDIFF_IS_DIRVIEW(fview)) return; basepane = view_get_pane(fview, "basepane"); if (basepane == NULL) return; b_wrap = gdiff_basepane_toggle_textwrap(basepane); if (GDIFF_IS_MERGEVIEW(fview)) { auxpane = view_get_pane(fview, "auxpane"); if (auxpane) { b_wrap = gdiff_basepane_toggle_textwrap(auxpane); } } /* update global preference */ g_pref.fvpref.line_wrap = b_wrap; /* update menu */ if (auxpane) pref.fvpref = auxpane->pref;/* copy */ else pref.fvpref = basepane->pref;/* copy */ update_fv_menu(fview, pref); } /** * act_fv_move_diff: * Move around different portions. **/ void act_fv_move_diff(GtkWidget *fview, MoveDiff mv_diff) { GdiffBasePane *basepane; if (fview == NULL || GDIFF_IS_DIRVIEW(fview)) return; basepane = view_get_pane(fview, "basepane"); if (basepane == NULL) return; gdiff_basepane_move_diff(basepane, mv_diff); } /** * act_fv_reload: * At first, close all file views related to the same backend data. * Then create a new file view for the same files. **/ static void act_fv_reload(GtkWidget *fview) { GDiffWindow *gdwin = NULL; DiffDir *diffdir = NULL;/* passed to a new view */ DiffFiles *dfiles = NULL;/* passed to a new view */ gboolean is_under_dir = FALSE;/* passed to a new view */ ViewType vtype = NO_VIEW; const char *fnames[MAX_NUM_COMPARE_FILES] = { NULL, NULL, NULL }; GtkWidget *new_fview = NULL; GtkWidget *tmp_fview; Preference pref = g_pref;/* copy */ gboolean is_diff3; int n; get_fview_vals1(fview); get_fview_vals2(fview); is_diff3 = dfiles->is_diff3; /* close all file views for this dfiles */ gdwin_remove_view(gdwin, fview); while ((tmp_fview = gdwin_find_fview_with_dfiles(gdwin, dfiles, FALSE))) { gdwin_remove_view(gdwin, tmp_fview); } if (is_under_dir == TRUE) { DiffFiles *new_dfiles; GtkWidget *dirview; /* update backend data */ diffdir_remove_dfiles(diffdir, dfiles); /* XXX: currently, directory diff means diff instead of diff3 */ new_dfiles = diffdir_add_dfiles(diffdir, fnames[FIRST_FILE], fnames[SECOND_FILE], NULL); run_diff(diffdir, fnames[FIRST_FILE], fnames[SECOND_FILE], g_pref.diff_args, new_dfiles); if (vtype & ONEPANE_MASK_VIEW) new_fview = gdiff_onepview_new(diffdir, new_dfiles, TRUE); else if (vtype & MULTIPANE_MASK_VIEW) new_fview = gdiff_multipview_new(diffdir, new_dfiles, TRUE); else if (vtype & MERGE_MASK_VIEW) new_fview = gdiff_mergeview_new(diffdir, new_dfiles, TRUE); else g_assert_not_reached(); gdwin_add_view(gdwin, new_fview); /* Set dirty-bit of directory view */ dirview = gdwin_find_dirview_with_diffdir(gdwin, diffdir); g_assert(dirview != NULL); GDIFF_DIRVIEW(dirview)->b_dirty = TRUE; } else { DiffDir *new_diffdir; DiffFiles *new_dfiles; /* update backend data */ if (is_diff3) { new_diffdir = diffdir_new(fnames[FIRST_FILE], fnames[SECOND_FILE], fnames[THIRD_FILE], g_pref.diff3_args); } else { new_diffdir = diffdir_new(fnames[FIRST_FILE], fnames[SECOND_FILE], NULL, g_pref.diff_args); } new_dfiles = g_slist_nth_data(new_diffdir->dfiles_list, 0); if (vtype & ONEPANE_MASK_VIEW) new_fview = gdiff_onepview_new(new_diffdir, new_dfiles, FALSE); else if (vtype & MULTIPANE_MASK_VIEW) new_fview = gdiff_multipview_new(new_diffdir, new_dfiles, FALSE); else if (vtype & MERGE_MASK_VIEW) new_fview = gdiff_mergeview_new(new_diffdir, new_dfiles, FALSE); else g_assert_not_reached(); gdwin_add_view(gdwin, new_fview); } for (n = 0; n < MAX_NUM_COMPARE_FILES; n++) g_free((gpointer)fnames[n]); /* update menu */ update_fv_menu(new_fview, pref); } /** * act_fv_edit_file: **/ void act_fv_edit_file(GtkWidget *fview, const char *filename) { char *editor_path; char *editor; if (fview == NULL || GDIFF_IS_DIRVIEW(fview)) return; if (filename == NULL || filename[0] == '\0') return; editor = g_getenv("EDITOR"); if (editor == NULL || editor[0] == '\0') { g_message(_("No \"EDITOR\" environment variable\n")); return; } editor_path = gnome_is_program_in_path(editor); if (editor_path == NULL) { g_message(_("\"EDITOR\" environment variable %s is not executable.\n"), editor); return; } else { switch (fork()) { case 0: /* the child */ close_allfd_except_std(); execl(editor_path, editor, filename, NULL); g_error("\"EDITOR\" environment variable \"%s\" exec error\n", editor); gtk_exit(1); break; case -1: /* the error */ g_error("edit_file_cb:fork %d\n", errno); break; default:/* the parent */ break; } g_free(editor_path); } } /** Actions for merge view **/ void act_merge_insert_remove_all(GtkWidget *mergeview, WhichFile whichfile, gboolean to_insert) { GdiffBasePane *basepane; if (mergeview == NULL || !GDIFF_IS_MERGEVIEW(mergeview)) return; basepane = view_get_pane(mergeview, "basepane"); if (basepane == NULL) return; if (to_insert) gdiff_merge_insert_all(GDIFF_MERGE(basepane), whichfile); else gdiff_merge_remove_all(GDIFF_MERGE(basepane), whichfile); } void act_merge_insert_remove(GtkWidget *mergeview, WhichFile whichfile, gboolean to_insert) { GdiffBasePane *basepane; if (mergeview == NULL || !GDIFF_IS_MERGEVIEW(mergeview)) return; basepane = view_get_pane(mergeview, "basepane"); if (basepane == NULL) return; if (to_insert) gdiff_merge_insert(GDIFF_MERGE(basepane), whichfile); else gdiff_merge_remove(GDIFF_MERGE(basepane), whichfile); } void act_merge_output_file(GtkWidget *mergeview) { GdiffBasePane *basepane; char *filename; if (mergeview == NULL || !GDIFF_IS_MERGEVIEW(mergeview)) return; basepane = view_get_pane(mergeview, "basepane"); if (basepane == NULL) return; if (GDIFF_MERGEVIEW(mergeview)->outfile) { filename = g_strdup(GDIFF_MERGEVIEW(mergeview)->outfile); } else { const FileInfo *fi; /* Use the last file name as a default output file name */ fi = dfiles_get_fileinfo(PANE_DFILES(basepane), GDIFF_MERGEVIEW_NUM_FILES(mergeview) - 1, FALSE); if (fi->fname == NULL || fi->fname[0] == '\0') { fi = dfiles_get_fileinfo(PANE_DFILES(basepane), FIRST_FILE, FALSE); } filename = get_filename(fi->fname); if (filename == NULL || filename[0] == '\0') goto DONE; } /* for safety, ask a user to overwrite the existing file */ if (g_file_exists(filename)) { QDialogReply reply; char *msg; msg = g_strdup_printf(_("%s exists. Overwrite?"), filename); reply = ask_yes_no(msg); g_free(msg); if (reply != QD_YES) goto DONE; } /* Do output */ gdiff_merge_output_file(GDIFF_MERGE(basepane), filename); DONE: if (filename) g_free(filename); } /* ---The followings are private functions--- */ /** * is_file_modified: * Check the files have been modified. * If modified, ask a user to reload them, and if he answers yes, reload them. * If modified, return TRUE. **/ static gboolean is_file_modified(GtkWidget *fview, GdiffBasePane *basepane) { FileModStatue fms; fms = dfiles_has_file_modified(basepane->dfiles); if (fms == MOD_MODIFIED) { QDialogReply reply; reply = ask_yes_no(_("The files look modified. Will you reload the files?")); if (reply == QD_YES) act_fv_reload(fview); return TRUE; } return FALSE; } /** * get_filename: * Open a modal file selection dialog box. * Return the selected file name, which should be freed by the caller. * which should be freed by caller. **/ static char *out_fname; /* Via this, get_filename() and filesel_ok_click() communicate. Ugly. */ static char* get_filename(const char *default_fname) { #ifdef DEBUG out_fname = g_strdup("/tmp/gtkdiff.merge"); #else GtkWidget *filesel; out_fname = NULL; filesel = gtk_file_selection_new(_("Save as")); if (default_fname) gtk_file_selection_set_filename(GTK_FILE_SELECTION(filesel), default_fname); gtk_window_set_modal(GTK_WINDOW(filesel), TRUE); gtk_signal_connect(GTK_OBJECT(filesel), "destroy", GTK_SIGNAL_FUNC(filesel_destroy_cb), NULL); gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(filesel)->ok_button), "clicked", GTK_SIGNAL_FUNC(filesel_ok_click), filesel); gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(filesel)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(filesel)); gtk_widget_show(filesel); gtk_main(); #endif return out_fname; } #ifndef DEBUG static void filesel_ok_click(GtkWidget *w, gpointer data) { GtkFileSelection *filesel = data; out_fname = g_strdup(gtk_file_selection_get_filename(filesel)); gtk_widget_destroy(GTK_WIDGET(filesel)); } static void filesel_destroy_cb(GtkWidget *w, gpointer data) { gtk_main_quit(); } #endif