2 * Utilities to use when constructing file selection dialogs
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #include <gdk/gdkkeysyms.h>
34 #include <epan/filesystem.h>
40 #include "gtkglobals.h"
41 #include "gui_utils.h"
43 #include "dlg_utils.h"
47 #include "compat_macros.h"
58 static gchar *last_open_dir = NULL;
59 static gboolean updated_last_open_dir = FALSE;
61 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 4) || GTK_MAJOR_VERSION < 2
62 static void file_selection_browse_ok_cb(GtkWidget *w, gpointer data);
64 static void file_selection_browse_destroy_cb(GtkWidget *win, GtkWidget* file_te);
67 #define E_FS_CALLER_PTR_KEY "fs_caller_ptr"
69 /* Create a file selection dialog box window that belongs to Wireshark's
71 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
73 file_selection_new(const gchar *title, file_selection_action_t action)
76 GtkFileChooserAction gtk_action;
78 char *u3devicedocumentpath;
80 const gchar *ok_button_text;
84 case FILE_SELECTION_OPEN:
85 gtk_action = GTK_FILE_CHOOSER_ACTION_OPEN;
86 ok_button_text = GTK_STOCK_OPEN;
89 case FILE_SELECTION_READ_BROWSE:
90 gtk_action = GTK_FILE_CHOOSER_ACTION_OPEN;
91 ok_button_text = GTK_STOCK_OK;
94 case FILE_SELECTION_SAVE:
95 gtk_action = GTK_FILE_CHOOSER_ACTION_SAVE;
96 ok_button_text = GTK_STOCK_SAVE;
99 case FILE_SELECTION_WRITE_BROWSE:
100 gtk_action = GTK_FILE_CHOOSER_ACTION_SAVE;
101 ok_button_text = GTK_STOCK_OK;
104 case FILE_SELECTION_CREATE_FOLDER:
105 gtk_action = GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER;
106 ok_button_text = GTK_STOCK_OK;
110 g_assert_not_reached();
112 ok_button_text = NULL;
115 win = gtk_file_chooser_dialog_new(title, GTK_WINDOW(top_level), gtk_action,
117 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
118 ok_button_text, GTK_RESPONSE_ACCEPT,
120 ok_button_text, GTK_RESPONSE_ACCEPT,
121 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
125 /* If we've opened a file before, start out by showing the files in the directory
126 in which that file resided. */
128 file_selection_set_current_folder(win, last_open_dir);
131 u3devicedocumentpath = getenv_utf8("U3_DEVICE_DOCUMENT_PATH");
132 if(u3devicedocumentpath != NULL)
133 file_selection_set_current_folder(win, u3devicedocumentpath);
141 file_selection_new(const gchar *title, file_selection_action_t action _U_)
145 char *u3devicedocumentpath;
147 win = gtk_file_selection_new(title);
148 #if GTK_MAJOR_VERSION >= 2
149 gtk_window_set_position(GTK_WINDOW(win), GTK_WIN_POS_CENTER_ON_PARENT);
151 gtk_window_set_transient_for(GTK_WINDOW(win), GTK_WINDOW(top_level));
153 /* XXX - why are we doing this? We don't do it with the GtkFileChooser,
154 as it complains that the file name isn't being set to an absolute
155 path; does this provoke a similar complaint? */
156 gtk_file_selection_set_filename(GTK_FILE_SELECTION(win), "");
158 /* If we've opened a file before, start out by showing the files in the directory
159 in which that file resided. */
161 file_selection_set_current_folder(win, last_open_dir);
164 u3devicedocumentpath = getenv_utf8("U3_DEVICE_DOCUMENT_PATH");
165 if(u3devicedocumentpath != NULL)
166 file_selection_set_current_folder(win, u3devicedocumentpath);
174 /* Set the current folder for a file selection dialog. */
176 file_selection_set_current_folder(GtkWidget *fs, const gchar *filename)
178 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
180 int filename_len = strlen(filename);
183 /* trim filename, so gtk_file_chooser_set_current_folder() likes it, see below */
184 if (filename[filename_len -1] == G_DIR_SEPARATOR
186 && filename_len > 3) /* e.g. "D:\" */
188 && filename_len > 1) /* e.g. "/" */
191 new_filename = g_strdup(filename);
192 new_filename[filename_len-1] = '\0';
194 new_filename = g_strdup(filename);
197 /* this function is very pedantic about it's filename parameter */
198 /* no trailing '\' allowed, unless a win32 root dir "D:\" */
199 ret = gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fs), new_filename);
200 g_free(new_filename);
203 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), filename);
208 /* Set the "extra" widget for a file selection dialog, with user-supplied
211 file_selection_set_extra_widget(GtkWidget *fs, GtkWidget *extra)
213 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
214 gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(fs), extra);
216 gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(fs)->action_area), extra,
223 * A generic select_file routine that is intended to be connected to
224 * a Browse button on other dialog boxes. This allows the user to browse
225 * for a file and select it. We fill in the text_entry that is given to us.
227 * We display the window label specified in our args.
230 file_selection_browse(GtkWidget *file_bt, GtkWidget *file_te, const char *label, file_selection_action_t action)
232 GtkWidget *caller = gtk_widget_get_toplevel(file_bt);
234 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
238 /* Has a file selection dialog box already been opened for that top-level
240 fs = OBJECT_GET_DATA(caller, E_FILE_SEL_DIALOG_PTR_KEY);
242 /* Yes. Just re-activate that dialog box. */
243 reactivate_window(fs);
247 fs = file_selection_new(label, action);
249 OBJECT_SET_DATA(fs, PRINT_FILE_TE_KEY, file_te);
251 /* Set the E_FS_CALLER_PTR_KEY for the new dialog to point to our caller. */
252 OBJECT_SET_DATA(fs, E_FS_CALLER_PTR_KEY, caller);
254 /* Set the E_FILE_SEL_DIALOG_PTR_KEY for the caller to point to us */
255 OBJECT_SET_DATA(caller, E_FILE_SEL_DIALOG_PTR_KEY, fs);
257 /* Call a handler when the file selection box is destroyed, so we can inform
258 our caller, if any, that it's been destroyed. */
259 SIGNAL_CONNECT(fs, "destroy", GTK_SIGNAL_FUNC(file_selection_browse_destroy_cb),
262 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
263 if (gtk_dialog_run(GTK_DIALOG(fs)) == GTK_RESPONSE_ACCEPT)
265 f_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
266 gtk_entry_set_text(GTK_ENTRY(file_te), f_name);
271 SIGNAL_CONNECT(GTK_FILE_SELECTION(fs)->ok_button, "clicked",
272 file_selection_browse_ok_cb, fs);
274 window_set_cancel_button(fs, GTK_FILE_SELECTION(fs)->cancel_button,
275 window_cancel_button_cb);
277 SIGNAL_CONNECT(fs, "delete_event", window_delete_event_cb, fs);
285 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 4) || GTK_MAJOR_VERSION < 2
287 file_selection_browse_ok_cb(GtkWidget *w _U_, gpointer data)
290 GtkWidget *win = data;
292 f_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION (data)));
294 /* Perhaps the user specified a directory instead of a file.
295 Check whether they did. */
296 if (test_for_directory(f_name) == EISDIR) {
297 /* It's a directory - set the file selection box to display it. */
298 set_last_open_dir(f_name);
300 file_selection_set_current_folder(data, last_open_dir);
304 gtk_entry_set_text(GTK_ENTRY(OBJECT_GET_DATA(win, PRINT_FILE_TE_KEY)),
306 window_destroy(GTK_WIDGET(win));
313 file_selection_browse_destroy_cb(GtkWidget *win, GtkWidget* parent_te)
317 /* Get the widget that requested that we be popped up.
318 (It should arrange to destroy us if it's destroyed, so
319 that we don't get a pointer to a non-existent window here.) */
320 caller = OBJECT_GET_DATA(win, E_FS_CALLER_PTR_KEY);
322 /* Tell it we no longer exist. */
323 OBJECT_SET_DATA(caller, E_FILE_SEL_DIALOG_PTR_KEY, NULL);
325 /* Give the focus to the file text entry widget so the user can just press
326 Return to print to the file. */
327 gtk_widget_grab_focus(parent_te);
332 set_last_open_dir(char *dirname)
335 gchar *new_last_open_dir;
338 len = strlen(dirname);
339 if (dirname[len-1] == G_DIR_SEPARATOR) {
340 new_last_open_dir = g_strconcat(dirname, NULL);
343 new_last_open_dir = g_strconcat(dirname,
344 G_DIR_SEPARATOR_S, NULL);
347 if (last_open_dir == NULL ||
348 strcmp(last_open_dir, new_last_open_dir) != 0)
349 updated_last_open_dir = TRUE;
352 new_last_open_dir = NULL;
353 if (last_open_dir != NULL)
354 updated_last_open_dir = TRUE;
358 g_free(last_open_dir);
360 last_open_dir = new_last_open_dir;
364 get_last_open_dir(void)
366 return last_open_dir;