diff options
-rw-r--r-- | Makefile.nmake | 2 | ||||
-rw-r--r-- | ui/gtk/capture_file_dlg.c | 169 | ||||
-rw-r--r-- | ui/gtk/file_dlg.c | 123 | ||||
-rw-r--r-- | ui/gtk/file_dlg.h | 9 |
4 files changed, 180 insertions, 123 deletions
diff --git a/Makefile.nmake b/Makefile.nmake index 10b3652309..a6ecdf8897 100644 --- a/Makefile.nmake +++ b/Makefile.nmake @@ -73,7 +73,7 @@ dumpcap_OBJECTS = $(dumpcap_SOURCES:.c=.obj) randpkt_OBJECTS = $(randpkt_SOURCES:.c=.obj) wireshark_LIBS= wiretap\wiretap-$(WTAP_VERSION).lib \ - wsock32.lib user32.lib shell32.lib comctl32.lib \ + wsock32.lib user32.lib shell32.lib comctl32.lib ole32.lib \ $(GTHREAD_LIBS) \ $(HHC_LIBS) \ wsutil\libwsutil.lib \ diff --git a/ui/gtk/capture_file_dlg.c b/ui/gtk/capture_file_dlg.c index fecdee1fb8..dafe457845 100644 --- a/ui/gtk/capture_file_dlg.c +++ b/ui/gtk/capture_file_dlg.c @@ -47,7 +47,6 @@ #include <wsutil/file_util.h> #include "ui/alert_box.h" -#include "ui/last_open_dir.h" #include "ui/recent.h" #include "ui/simple_dialog.h" #include "ui/ui_util.h" @@ -70,7 +69,11 @@ #include "ui/gtk/range_utils.h" #include "ui/gtk/filter_autocomplete.h" -#if _WIN32 +#ifdef _WIN32 +#define USE_WIN32_FILE_DIALOGS +#endif + +#ifdef USE_WIN32_FILE_DIALOGS #include <gdk/gdkwin32.h> #include <windows.h> #include "ui/win32/file_dlg_win32.h" @@ -422,9 +425,9 @@ preview_new(void) static void file_open_cmd(GtkWidget *w) { -#if _WIN32 +#ifdef USE_WIN32_FILE_DIALOGS win32_open_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level))); -#else /* _WIN32 */ +#else /* USE_WIN32_FILE_DIALOGS */ GtkWidget *file_open_w; GtkWidget *main_hb, *main_vb, *filter_hbox, *filter_bt, *filter_te, *m_resolv_cb, *n_resolv_cb, *t_resolv_cb, *prev; @@ -541,26 +544,12 @@ file_open_cmd(GtkWidget *w) * Loop until the user either selects a file or gives up. */ for (;;) { - if (gtk_dialog_run(GTK_DIALOG(file_open_w)) != GTK_RESPONSE_ACCEPT) { - /* They clicked "Cancel" or closed the dialog or.... */ - window_destroy(file_open_w); + cf_name = file_selection_run(file_open_w); + if (cf_name == NULL) { + /* User cancelled or closed the dialog. */ return; } - cf_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_open_w)); - - /* Perhaps the user specified a directory instead of a file. - Check whether they did. */ - if (test_for_directory(cf_name) == EISDIR) { - /* It's a directory - set the file selection box to display that - directory, and go back and re-run it; don't try to open the - directory as a capture file. */ - set_last_open_dir(cf_name); - g_free(cf_name); - file_selection_set_current_folder(file_open_w, get_last_open_dir()); - continue; - } - /* Get the specified read filter and try to compile it. */ rfilter = gtk_entry_get_text(GTK_ENTRY(filter_te)); if (!dfilter_compile(rfilter, &rfcode)) { @@ -633,7 +622,7 @@ file_open_cmd(GtkWidget *w) g_free(cf_name); return; } -#endif /* _WIN32 */ +#endif /* USE_WIN32_FILE_DIALOGS */ } void @@ -648,11 +637,11 @@ file_open_cmd_cb(GtkWidget *widget, gpointer data _U_) { static void file_merge_cmd(GtkWidget *w) { -#if _WIN32 +#ifdef USE_WIN32_FILE_DIALOGS win32_merge_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level))); new_packet_list_freeze(); new_packet_list_thaw(); -#else /* _WIN32 */ +#else /* USE_WIN32_FILE_DIALOGS */ GtkWidget *file_merge_w; GtkWidget *main_hb, *main_vb, *ft_hb, *ft_lb, *ft_combo_box, *filter_hbox, *filter_bt, *filter_te, *prepend_rb, *chrono_rb, @@ -794,26 +783,12 @@ file_merge_cmd(GtkWidget *w) * Loop until the user either selects a file or gives up. */ for (;;) { - if (gtk_dialog_run(GTK_DIALOG(file_merge_w)) != GTK_RESPONSE_ACCEPT) { - /* They clicked "Cancel" or closed the dialog or.... */ - window_destroy(file_merge_w); + cf_name = file_selection_run(file_merge_w); + if (cf_name == NULL) { + /* User cancelled or closed the dialog. */ return; } - cf_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_merge_w)); - - /* Perhaps the user specified a directory instead of a file. - Check whether they did. */ - if (test_for_directory(cf_name) == EISDIR) { - /* It's a directory - set the file selection box to display that - directory, and go back and re-run it; don't try to open the - directory as a capture file. */ - set_last_open_dir(cf_name); - g_free(cf_name); - file_selection_set_current_folder(file_merge_w, get_last_open_dir()); - continue; - } - /* Get the specified read filter and try to compile it. */ rfilter = gtk_entry_get_text(GTK_ENTRY(filter_te)); if (!dfilter_compile(rfilter, &rfcode)) { @@ -903,7 +878,7 @@ file_merge_cmd(GtkWidget *w) set_last_open_dir(s); return; } -#endif /* _WIN32 */ +#endif /* USE_WIN32_FILE_DIALOGS */ } void @@ -1594,9 +1569,9 @@ static void do_file_save_as(capture_file *cf, gboolean must_support_comments, gboolean dont_reopen) { -#if _WIN32 +#ifdef USE_WIN32_FILE_DIALOGS win32_save_as_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level))); -#else /* _WIN32 */ +#else /* USE_WIN32_FILE_DIALOGS */ GtkWidget *file_save_as_w; GtkWidget *main_vb, *ft_hb, *ft_lb, *ft_combo_box, *compressed_cb; char *cf_name; @@ -1648,26 +1623,12 @@ do_file_save_as(capture_file *cf, gboolean must_support_comments, * Loop until the user either selects a file or gives up. */ for (;;) { - if (gtk_dialog_run(GTK_DIALOG(file_save_as_w)) != GTK_RESPONSE_ACCEPT) { - /* They clicked "Cancel" or closed the dialog or.... */ - window_destroy(file_save_as_w); + cf_name = file_selection_run(file_save_as_w); + if (cf_name == NULL) { + /* User cancelled or closed the dialog. */ return; } - cf_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_save_as_w)); - - /* Perhaps the user specified a directory instead of a file. - Check whether they did. */ - if (test_for_directory(cf_name) == EISDIR) { - /* It's a directory - set the file selection box to display that - directory, and go back and re-run it; don't try to write onto - the directory (which won't work anyway). */ - set_last_open_dir(cf_name); - g_free(cf_name); - file_selection_set_current_folder(file_save_as_w, get_last_open_dir()); - continue; - } - /* If the file has comments, does the format the user selected support them? If not, ask the user whether they want to discard the comments or choose a different format. */ @@ -1704,6 +1665,7 @@ do_file_save_as(capture_file *cf, gboolean must_support_comments, return; } +#ifndef _WIN32 /* If the file exists and it's user-immutable or not writable, ask the user whether they want to override that. */ if (!file_target_unwritable_ui(file_save_as_w, cf_name)) { @@ -1711,6 +1673,7 @@ do_file_save_as(capture_file *cf, gboolean must_support_comments, g_free(cf_name); continue; } +#endif /* Attempt to save the file */ g_free(cf_name); @@ -1733,7 +1696,7 @@ do_file_save_as(capture_file *cf, gboolean must_support_comments, return; } } -#endif /* _WIN32 */ +#endif /* USE_WIN32_FILE_DIALOGS */ } void @@ -1806,9 +1769,9 @@ file_save_as_cb(GtkWidget *fs, gboolean discard_comments, void file_export_specified_packets_cmd_cb(GtkWidget *widget _U_, gpointer data _U_) { -#if _WIN32 +#ifdef USE_WIN32_FILE_DIALOGS win32_export_specified_packets_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level))); -#else /* _WIN32 */ +#else /* USE_WIN32_FILE_DIALOGS */ GtkWidget *file_export_specified_packets_w; GtkWidget *main_vb, *ft_hb, *ft_lb, *ft_combo_box, *range_fr, *range_tb, *compressed_cb; @@ -1881,26 +1844,12 @@ file_export_specified_packets_cmd_cb(GtkWidget *widget _U_, gpointer data _U_) * Loop until the user either selects a file or gives up. */ for (;;) { - if (gtk_dialog_run(GTK_DIALOG(file_export_specified_packets_w)) != GTK_RESPONSE_ACCEPT) { - /* They clicked "Cancel" or closed the dialog or.... */ - window_destroy(file_export_specified_packets_w); + cf_name = file_selection_run(file_export_specified_packets_w); + if (cf_name == NULL) { + /* User cancelled or closed the dialog. */ return; } - cf_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_export_specified_packets_w)); - - /* Perhaps the user specified a directory instead of a file. - Check whether they did. */ - if (test_for_directory(cf_name) == EISDIR) { - /* It's a directory - set the file selection box to display that - directory, and go back and re-run it; don't try to write onto - the directory (which won't work anyway). */ - set_last_open_dir(cf_name); - g_free(cf_name); - file_selection_set_current_folder(file_export_specified_packets_w, get_last_open_dir()); - continue; - } - /* Check whether the range is valid. */ if (!range_check_validity_modal(file_export_specified_packets_w, &range)) { /* The range isn't valid; the user was told that, and dismissed @@ -1935,6 +1884,7 @@ file_export_specified_packets_cmd_cb(GtkWidget *widget _U_, gpointer data _U_) continue; } +#ifndef _WIN32 /* If the file exists and it's user-immutable or not writable, ask the user whether they want to override that. */ if (!file_target_unwritable_ui(file_export_specified_packets_w, cf_name)) { @@ -1942,6 +1892,7 @@ file_export_specified_packets_cmd_cb(GtkWidget *widget _U_, gpointer data _U_) g_free(cf_name); continue; } +#endif /* attempt to export the packets */ g_free(cf_name); @@ -1961,7 +1912,7 @@ file_export_specified_packets_cmd_cb(GtkWidget *widget _U_, gpointer data _U_) return; } } -#endif /* _WIN32 */ +#endif /* USE_WIN32_FILE_DIALOGS */ } /* all tests ok, we only have to write out the packets */ @@ -2062,9 +2013,9 @@ color_global_cb(GtkWidget *widget _U_, gpointer data) void file_color_import_cmd_cb(GtkWidget *color_filters, gpointer filter_list _U_) { -#if _WIN32 +#ifdef USE_WIN32_FILE_DIALOGS win32_import_color_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level)), color_filters); -#else /* _WIN32 */ +#else /* USE_WIN32_FILE_DIALOGS */ GtkWidget *main_vb, *cfglobal_but; gchar *cf_name, *s; @@ -2090,26 +2041,12 @@ file_color_import_cmd_cb(GtkWidget *color_filters, gpointer filter_list _U_) * Loop until the user either selects a file or gives up. */ for (;;) { - if (gtk_dialog_run(GTK_DIALOG(file_color_import_w)) != GTK_RESPONSE_ACCEPT) { - /* They clicked "Cancel" or closed the dialog or.... */ - window_destroy(file_color_import_w); + cf_name = file_selection_run(file_color_import_w); + if (cf_name == NULL) { + /* User cancelled or closed the dialog. */ return; } - cf_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_color_import_w)); - - /* Perhaps the user specified a directory instead of a file. - Check whether they did. */ - if (test_for_directory(cf_name) == EISDIR) { - /* It's a directory - set the file selection box to display that - directory, and go back and re-run it; don't try to open the - directory as a color filter file. */ - set_last_open_dir(cf_name); - g_free(cf_name); - file_selection_set_current_folder(file_color_import_w, get_last_open_dir()); - continue; - } - /* Try to open the color filter file. */ if (!color_filters_import(cf_name, color_filters)) { /* We couldn't open it; don't dismiss the open dialog box, @@ -2132,7 +2069,7 @@ file_color_import_cmd_cb(GtkWidget *color_filters, gpointer filter_list _U_) g_free(cf_name); return; } -#endif /* _WIN32 */ +#endif /* USE_WIN32_FILE_DIALOGS */ } /* @@ -2167,9 +2104,9 @@ color_toggle_selected_cb(GtkWidget *widget, gpointer data _U_) void file_color_export_cmd_cb(GtkWidget *w _U_, gpointer filter_list) { -#if _WIN32 +#if USE_WIN32_FILE_DIALOGS win32_export_color_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level)), filter_list); -#else /* _WIN32 */ +#else /* USE_WIN32_FILE_DIALOGS */ GtkWidget *file_color_export_w; GtkWidget *main_vb, *cfglobal_but; GtkWidget *cfselect_cb; @@ -2207,26 +2144,13 @@ file_color_export_cmd_cb(GtkWidget *w _U_, gpointer filter_list) * Loop until the user either selects a file or gives up. */ for (;;) { - if (gtk_dialog_run(GTK_DIALOG(file_color_export_w)) != GTK_RESPONSE_ACCEPT) { - /* They clicked "Cancel" or closed the dialog or.... */ - window_destroy(file_color_export_w); + cf_name = file_selection_run(file_color_export_w); + if (cf_name == NULL) { + /* User cancelled or closed the dialog. */ return; } - cf_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_color_export_w)); - - /* Perhaps the user specified a directory instead of a file. - Check whether they did. */ - if (test_for_directory(cf_name) == EISDIR) { - /* It's a directory - set the file selection box to display that - directory, and go back and re-run it; don't try to write onto - the directory (which wn't work anyway). */ - set_last_open_dir(cf_name); - g_free(cf_name); - file_selection_set_current_folder(file_color_export_w, get_last_open_dir()); - continue; - } - +#ifndef _WIN32 /* If the file exists and it's user-immutable or not writable, ask the user whether they want to override that. */ if (!file_target_unwritable_ui(file_color_export_w, cf_name)) { @@ -2234,6 +2158,7 @@ file_color_export_cmd_cb(GtkWidget *w _U_, gpointer filter_list) g_free(cf_name); continue; } +#endif /* Write out the filters (all, or only the ones that are currently displayed or selected) to the file with the specified name. */ @@ -2253,5 +2178,5 @@ file_color_export_cmd_cb(GtkWidget *w _U_, gpointer filter_list) set_last_open_dir(dirname); g_free(cf_name); } -#endif /* _WIN32 */ +#endif /* USE_WIN32_FILE_DIALOGS */ } diff --git a/ui/gtk/file_dlg.c b/ui/gtk/file_dlg.c index 1173e6eab0..d633e80cc8 100644 --- a/ui/gtk/file_dlg.c +++ b/ui/gtk/file_dlg.c @@ -22,6 +22,15 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* + * Code to handle Windows shortcuts courtesy of: + * + * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client + * Copyright (C) 1999-2012 Hiroyuki Yamamoto + * + * licensed under the GPL2 or later. + */ + #ifdef HAVE_CONFIG_H # include "config.h" #endif @@ -30,12 +39,22 @@ #include <gtk/gtk.h> +#ifdef _WIN32 +# define COBJMACROS +# include <windows.h> +# include <objbase.h> +# include <objidl.h> +# include <shlobj.h> +#endif + #include <wsutil/file_util.h> #ifndef _WIN32 #include <epan/filesystem.h> #endif +#include "ui/last_open_dir.h" + #include "ui/gtk/gtkglobals.h" #include "ui/gtk/gui_utils.h" #include "ui/gtk/file_dlg.h" @@ -157,6 +176,110 @@ file_selection_set_extra_widget(GtkWidget *fs, GtkWidget *extra) gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(fs), extra); } +#ifdef _WIN32 +static gchar *filesel_get_link(const gchar *link_file) +{ + WIN32_FIND_DATAW wfd; + IShellLinkW *psl; + IPersistFile *ppf; + wchar_t *wlink_file; + wchar_t wtarget[MAX_PATH]; + gchar *target = NULL; + + wtarget[0] = 0L; + + CoInitialize(NULL); + if (S_OK == CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, + &IID_IShellLinkW, (void **)&psl)) { + if (S_OK == IShellLinkW_QueryInterface(psl, &IID_IPersistFile, + (void **)&ppf)) { + wlink_file = g_utf8_to_utf16(link_file, -1, NULL, NULL, NULL); + if (S_OK == IPersistFile_Load(ppf, wlink_file, STGM_READ)) { + if (S_OK == IShellLinkW_GetPath(psl, wtarget, MAX_PATH, &wfd, + SLGP_UNCPRIORITY)) { + target = g_utf16_to_utf8(wtarget, -1, NULL, NULL, NULL); + } + } + IPersistFile_Release(ppf); + g_free(wlink_file); + } + IShellLinkW_Release(psl); + } + CoUninitialize(); + + return target; +} +#endif /* _WIN32 */ + +/* Run the dialog, and handle some common operations, such as, if the + user selects a directory, browsing that directory, and handling + shortcuts on Windows. + + Returns NULL if the user decided not to open/write to a file, + returns the pathname of the selected file if they selected a + file. */ +gchar * +file_selection_run(GtkWidget *fs) +{ + gchar *cf_name; +#ifdef _WIN32 + gchar *target; + const gchar *ext; +#endif + + for (;;) { + if (gtk_dialog_run(GTK_DIALOG(fs)) != GTK_RESPONSE_ACCEPT) { + /* They clicked "Cancel" or closed the dialog or...; + destroy the dialog and tell our caller the user decided + not to do anything with the file. */ + window_destroy(fs); + return NULL; + } + + cf_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)); + + /* Perhaps the user specified a directory instead of a file. + Check whether they did. */ + if (test_for_directory(cf_name) == EISDIR) { + /* It's a directory - set the file selection box to display that + directory, and go back and re-run it; don't try to open the + directory as a file (you'll get crap if you get anything) or + write to it (which won't work anyway). */ + set_last_open_dir(cf_name); + g_free(cf_name); + file_selection_set_current_folder(fs, get_last_open_dir()); + continue; + } + +#ifdef _WIN32 + /* Perhaps the user specified a "shortcut" instead of a file. + Check whether they did. */ + if ((ext = strrchr(cf_name, '.')) && g_ascii_strcasecmp(ext, ".lnk") == 0) { + /* It ends with ".lnk", so it might be a shortcut. */ + target = filesel_get_link(cf_name); + if (target != NULL) { + /* We resolved it, so it must've been a shortcut. */ + g_free(cf_name); + if (test_for_directory(target)) { + /* It's a shortcut that points to a directory; treat it the same + way we treat a directory. */ + set_last_open_dir(target); + g_free(target); + file_selection_set_current_folder(fs, get_last_open_dir()); + continue; + } + /* It's a shortcut that points to a file; act as if the target + is what's selected. */ + cf_name = target; + } + } +#endif + break; + } + + return cf_name; +} + #ifndef _WIN32 /* If the specified file doesn't exist, return TRUE. If it exists and is neither user-immutable nor not writable, return diff --git a/ui/gtk/file_dlg.h b/ui/gtk/file_dlg.h index 9ee50f1afd..47da219e77 100644 --- a/ui/gtk/file_dlg.h +++ b/ui/gtk/file_dlg.h @@ -85,6 +85,15 @@ extern gboolean file_selection_set_current_folder(GtkWidget *fs, const gchar *fi */ extern void file_selection_set_extra_widget(GtkWidget *fs, GtkWidget *extra); +/** Run the dialog, and handle some common operations, such as, if the + * user selects a directory, browsing that directory, and handling + * shortcuts on Windows. + * @param fs the file selection dialog from file_selection_new() + * @return the pathname of the selected file if the user selected a + * file, NULL if they cancelled or closed the dialog. + */ +extern gchar *file_selection_run(GtkWidget *fs); + #ifndef _WIN32 /** If the specified file doesn't exist, return TRUE. * If it exists and is neither user-immutable nor not writable, return |