diff options
Diffstat (limited to 'src/filesel.c')
| -rw-r--r-- | src/filesel.c | 611 |
1 files changed, 611 insertions, 0 deletions
diff --git a/src/filesel.c b/src/filesel.c new file mode 100644 index 0000000..e4e3ecd --- /dev/null +++ b/src/filesel.c | |||
| @@ -0,0 +1,611 @@ | |||
| 1 | /* | ||
| 2 | * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client | ||
| 3 | * Copyright (C) 1999-2014 Hiroyuki Yamamoto | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License as published by | ||
| 7 | * the Free Software Foundation; either version 2 of the License, or | ||
| 8 | * (at your option) any later version. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <glib.h> | ||
| 21 | #include <glib/gi18n.h> | ||
| 22 | #include <gdk/gdkkeysyms.h> | ||
| 23 | #include <gtk/gtkversion.h> | ||
| 24 | #include <gtk/gtkfilechooserdialog.h> | ||
| 25 | #include <gtk/gtkexpander.h> | ||
| 26 | #include <gtk/gtkcombobox.h> | ||
| 27 | #include <gtk/gtkstock.h> | ||
| 28 | |||
| 29 | #ifdef G_OS_WIN32 | ||
| 30 | # define COBJMACROS | ||
| 31 | # include <windows.h> | ||
| 32 | # include <objbase.h> | ||
| 33 | # include <objidl.h> | ||
| 34 | # include <shlobj.h> | ||
| 35 | #endif | ||
| 36 | |||
| 37 | #include "main.h" | ||
| 38 | #include "filesel.h" | ||
| 39 | #include "manage_window.h" | ||
| 40 | #include "alertpanel.h" | ||
| 41 | #include "utils.h" | ||
| 42 | #include "prefs_common.h" | ||
| 43 | #include "inc.h" | ||
| 44 | |||
| 45 | |||
| 46 | static GSList *filesel_select_file_full (const gchar *title, | ||
| 47 | const gchar *file, | ||
| 48 | GtkFileChooserAction action, | ||
| 49 | gboolean multiple, | ||
| 50 | FileselFileType *types, | ||
| 51 | gint default_type, | ||
| 52 | gint *selected_type); | ||
| 53 | |||
| 54 | static GtkWidget *filesel_create (const gchar *title, | ||
| 55 | GtkFileChooserAction action); | ||
| 56 | |||
| 57 | static void filesel_save_expander_set_expanded (GtkWidget *dialog, | ||
| 58 | gboolean expanded); | ||
| 59 | static gboolean filesel_save_expander_get_expanded (GtkWidget *dialog); | ||
| 60 | |||
| 61 | static gchar *filesel_get_filename_with_ext (const gchar *filename, | ||
| 62 | const gchar *ext); | ||
| 63 | |||
| 64 | static void filesel_combo_changed_cb (GtkComboBox *combo_box, | ||
| 65 | gpointer data); | ||
| 66 | |||
| 67 | #if GTK_CHECK_VERSION(2, 8, 0) | ||
| 68 | static GtkFileChooserConfirmation filesel_confirm_overwrite_cb | ||
| 69 | (GtkFileChooser *chooser, | ||
| 70 | gpointer data); | ||
| 71 | #endif | ||
| 72 | #ifdef G_OS_WIN32 | ||
| 73 | static gboolean is_ext_lnk (const gchar *filename); | ||
| 74 | static gchar *filesel_get_link (const gchar *link_file); | ||
| 75 | static GSList *filesel_resolve_link (GtkFileChooser *chooser, | ||
| 76 | GSList *list, | ||
| 77 | gboolean *dir_selected); | ||
| 78 | #endif | ||
| 79 | |||
| 80 | |||
| 81 | gchar *filesel_select_file(const gchar *title, const gchar *file, | ||
| 82 | GtkFileChooserAction action) | ||
| 83 | { | ||
| 84 | GSList *list; | ||
| 85 | gchar *selected = NULL; | ||
| 86 | |||
| 87 | list = filesel_select_file_full(title, file, action, FALSE, NULL, 0, NULL); | ||
| 88 | if (list) { | ||
| 89 | selected = (gchar *)list->data; | ||
| 90 | slist_free_strings(list->next); | ||
| 91 | } | ||
| 92 | g_slist_free(list); | ||
| 93 | |||
| 94 | return selected; | ||
| 95 | } | ||
| 96 | |||
| 97 | GSList *filesel_select_files(const gchar *title, const gchar *file, | ||
| 98 | GtkFileChooserAction action) | ||
| 99 | { | ||
| 100 | return filesel_select_file_full(title, file, action, TRUE, NULL, 0, NULL); | ||
| 101 | } | ||
| 102 | |||
| 103 | static void filesel_change_dir_for_action(GtkFileChooserAction action) | ||
| 104 | { | ||
| 105 | const gchar *cwd = NULL; | ||
| 106 | |||
| 107 | switch (action) { | ||
| 108 | case GTK_FILE_CHOOSER_ACTION_OPEN: | ||
| 109 | if (prefs_common.prev_open_dir && | ||
| 110 | is_dir_exist(prefs_common.prev_open_dir)) | ||
| 111 | cwd = prefs_common.prev_open_dir; | ||
| 112 | else { | ||
| 113 | g_free(prefs_common.prev_open_dir); | ||
| 114 | prefs_common.prev_open_dir = NULL; | ||
| 115 | } | ||
| 116 | break; | ||
| 117 | case GTK_FILE_CHOOSER_ACTION_SAVE: | ||
| 118 | if (prefs_common.prev_save_dir && | ||
| 119 | is_dir_exist(prefs_common.prev_save_dir)) | ||
| 120 | cwd = prefs_common.prev_save_dir; | ||
| 121 | else { | ||
| 122 | g_free(prefs_common.prev_save_dir); | ||
| 123 | prefs_common.prev_save_dir = NULL; | ||
| 124 | } | ||
| 125 | break; | ||
| 126 | case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER: | ||
| 127 | if (prefs_common.prev_folder_dir && | ||
| 128 | is_dir_exist(prefs_common.prev_folder_dir)) | ||
| 129 | cwd = prefs_common.prev_folder_dir; | ||
| 130 | else { | ||
| 131 | g_free(prefs_common.prev_folder_dir); | ||
| 132 | prefs_common.prev_folder_dir = NULL; | ||
| 133 | } | ||
| 134 | break; | ||
| 135 | default: | ||
| 136 | break; | ||
| 137 | } | ||
| 138 | |||
| 139 | if (cwd) | ||
| 140 | change_dir(cwd); | ||
| 141 | else | ||
| 142 | change_dir(get_document_dir()); | ||
| 143 | } | ||
| 144 | |||
| 145 | static void filesel_save_dir_for_action(GtkFileChooserAction action, | ||
| 146 | const gchar *cwd) | ||
| 147 | { | ||
| 148 | switch (action) { | ||
| 149 | case GTK_FILE_CHOOSER_ACTION_OPEN: | ||
| 150 | g_free(prefs_common.prev_open_dir); | ||
| 151 | prefs_common.prev_open_dir = g_strdup(cwd); | ||
| 152 | break; | ||
| 153 | case GTK_FILE_CHOOSER_ACTION_SAVE: | ||
| 154 | g_free(prefs_common.prev_save_dir); | ||
| 155 | prefs_common.prev_save_dir = g_strdup(cwd); | ||
| 156 | break; | ||
| 157 | case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER: | ||
| 158 | g_free(prefs_common.prev_folder_dir); | ||
| 159 | prefs_common.prev_folder_dir = g_strdup(cwd); | ||
| 160 | break; | ||
| 161 | default: | ||
| 162 | break; | ||
| 163 | } | ||
| 164 | } | ||
| 165 | |||
| 166 | static GSList *filesel_select_file_full(const gchar *title, const gchar *file, | ||
| 167 | GtkFileChooserAction action, | ||
| 168 | gboolean multiple, | ||
| 169 | FileselFileType *types, | ||
| 170 | gint default_type, gint *selected_type) | ||
| 171 | { | ||
| 172 | gchar *cwd; | ||
| 173 | GtkWidget *dialog; | ||
| 174 | gchar *prev_dir; | ||
| 175 | static gboolean save_expander_expanded = FALSE; | ||
| 176 | GSList *list = NULL; | ||
| 177 | GtkWidget *combo = NULL; | ||
| 178 | |||
| 179 | prev_dir = g_get_current_dir(); | ||
| 180 | |||
| 181 | filesel_change_dir_for_action(action); | ||
| 182 | |||
| 183 | dialog = filesel_create(title, action); | ||
| 184 | |||
| 185 | manage_window_set_transient(GTK_WINDOW(dialog)); | ||
| 186 | |||
| 187 | cwd = g_get_current_dir(); | ||
| 188 | gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), cwd); | ||
| 189 | g_free(cwd); | ||
| 190 | cwd = NULL; | ||
| 191 | |||
| 192 | if (file) | ||
| 193 | gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), | ||
| 194 | file); | ||
| 195 | |||
| 196 | gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), | ||
| 197 | multiple); | ||
| 198 | |||
| 199 | if (action == GTK_FILE_CHOOSER_ACTION_SAVE && save_expander_expanded) { | ||
| 200 | filesel_save_expander_set_expanded | ||
| 201 | (dialog, save_expander_expanded); | ||
| 202 | } | ||
| 203 | |||
| 204 | #if GTK_CHECK_VERSION(2, 8, 0) | ||
| 205 | if (action == GTK_FILE_CHOOSER_ACTION_SAVE) { | ||
| 206 | gtk_file_chooser_set_do_overwrite_confirmation | ||
| 207 | (GTK_FILE_CHOOSER(dialog), TRUE); | ||
| 208 | g_signal_connect(GTK_FILE_CHOOSER(dialog), "confirm-overwrite", | ||
| 209 | G_CALLBACK(filesel_confirm_overwrite_cb), | ||
| 210 | NULL); | ||
| 211 | } | ||
| 212 | #endif | ||
| 213 | |||
| 214 | /* create types combo box */ | ||
| 215 | if (types) { | ||
| 216 | GtkWidget *hbox; | ||
| 217 | GtkWidget *label; | ||
| 218 | gint i; | ||
| 219 | |||
| 220 | hbox = gtk_hbox_new(FALSE, 12); | ||
| 221 | label = gtk_label_new(_("File type:")); | ||
| 222 | gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | ||
| 223 | |||
| 224 | combo = gtk_combo_box_new_text(); | ||
| 225 | for (i = 0; types[i].type != NULL; i++) { | ||
| 226 | gtk_combo_box_append_text(GTK_COMBO_BOX(combo), types[i].type); | ||
| 227 | } | ||
| 228 | gtk_box_pack_start(GTK_BOX(hbox), combo, FALSE, FALSE, 0); | ||
| 229 | |||
| 230 | gtk_widget_show_all(hbox); | ||
| 231 | gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(dialog), hbox); | ||
| 232 | if (default_type < 0 || default_type >= i) | ||
| 233 | default_type = 0; | ||
| 234 | gtk_combo_box_set_active(GTK_COMBO_BOX(combo), default_type); | ||
| 235 | g_object_set_data(G_OBJECT(combo), "types", types); | ||
| 236 | g_signal_connect(GTK_COMBO_BOX(combo), "changed", | ||
| 237 | G_CALLBACK(filesel_combo_changed_cb), dialog); | ||
| 238 | |||
| 239 | if (file) { | ||
| 240 | gchar *newfile; | ||
| 241 | |||
| 242 | newfile = filesel_get_filename_with_ext | ||
| 243 | (file, types[default_type].ext); | ||
| 244 | gtk_file_chooser_set_current_name | ||
| 245 | (GTK_FILE_CHOOSER(dialog), newfile); | ||
| 246 | g_free(newfile); | ||
| 247 | } | ||
| 248 | } | ||
| 249 | |||
| 250 | gtk_widget_show(dialog); | ||
| 251 | |||
| 252 | change_dir(prev_dir); | ||
| 253 | g_free(prev_dir); | ||
| 254 | |||
| 255 | inc_lock(); | ||
| 256 | |||
| 257 | #ifdef G_OS_WIN32 | ||
| 258 | again: | ||
| 259 | #endif | ||
| 260 | if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { | ||
| 261 | list = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)); | ||
| 262 | #ifdef G_OS_WIN32 | ||
| 263 | if (list) { | ||
| 264 | /* resolve Windows shortcut */ | ||
| 265 | gboolean dir_selected = FALSE; | ||
| 266 | list = filesel_resolve_link(GTK_FILE_CHOOSER(dialog), | ||
| 267 | list, &dir_selected); | ||
| 268 | if (!list) { | ||
| 269 | if (!dir_selected) | ||
| 270 | alertpanel_error(_("The link target not found.")); | ||
| 271 | goto again; | ||
| 272 | } | ||
| 273 | } | ||
| 274 | #endif | ||
| 275 | if (list) { | ||
| 276 | cwd = gtk_file_chooser_get_current_folder | ||
| 277 | (GTK_FILE_CHOOSER(dialog)); | ||
| 278 | if (cwd) { | ||
| 279 | filesel_save_dir_for_action(action, cwd); | ||
| 280 | g_free(cwd); | ||
| 281 | } | ||
| 282 | } | ||
| 283 | } | ||
| 284 | |||
| 285 | inc_unlock(); | ||
| 286 | |||
| 287 | if (combo && selected_type) { | ||
| 288 | *selected_type = gtk_combo_box_get_active(GTK_COMBO_BOX(combo)); | ||
| 289 | } | ||
| 290 | |||
| 291 | if (action == GTK_FILE_CHOOSER_ACTION_SAVE) | ||
| 292 | save_expander_expanded = | ||
| 293 | filesel_save_expander_get_expanded(dialog); | ||
| 294 | |||
| 295 | manage_window_focus_out(dialog, NULL, NULL); | ||
| 296 | gtk_widget_destroy(dialog); | ||
| 297 | |||
| 298 | return list; | ||
| 299 | } | ||
| 300 | |||
| 301 | gchar *filesel_save_as(const gchar *file) | ||
| 302 | { | ||
| 303 | gchar *filename; | ||
| 304 | |||
| 305 | filename = filesel_select_file(_("Save as"), file, | ||
| 306 | GTK_FILE_CHOOSER_ACTION_SAVE); | ||
| 307 | |||
| 308 | #if !GTK_CHECK_VERSION(2, 8, 0) | ||
| 309 | if (filename && is_file_exist(filename)) { | ||
| 310 | AlertValue aval; | ||
| 311 | |||
| 312 | aval = alertpanel(_("Overwrite existing file"), | ||
| 313 | _("The file already exists. Do you want to replace it?"), | ||
| 314 | GTK_STOCK_YES, GTK_STOCK_NO, NULL); | ||
| 315 | if (G_ALERTDEFAULT != aval) { | ||
| 316 | g_free(filename); | ||
| 317 | filename = NULL; | ||
| 318 | } | ||
| 319 | } | ||
| 320 | #endif | ||
| 321 | |||
| 322 | return filename; | ||
| 323 | } | ||
| 324 | |||
| 325 | gchar *filesel_save_as_type(const gchar *file, FileselFileType *types, | ||
| 326 | gint default_type, gint *selected_type) | ||
| 327 | { | ||
| 328 | GSList *list; | ||
| 329 | gchar *filename = NULL; | ||
| 330 | |||
| 331 | list = filesel_select_file_full(_("Save as"), file, | ||
| 332 | GTK_FILE_CHOOSER_ACTION_SAVE, FALSE, | ||
| 333 | types, | ||
| 334 | default_type, selected_type); | ||
| 335 | if (list) { | ||
| 336 | filename = (gchar *)list->data; | ||
| 337 | slist_free_strings(list->next); | ||
| 338 | } | ||
| 339 | g_slist_free(list); | ||
| 340 | |||
| 341 | #if !GTK_CHECK_VERSION(2, 8, 0) | ||
| 342 | if (filename && is_file_exist(filename)) { | ||
| 343 | AlertValue aval; | ||
| 344 | |||
| 345 | aval = alertpanel(_("Overwrite existing file"), | ||
| 346 | _("The file already exists. Do you want to replace it?"), | ||
| 347 | GTK_STOCK_YES, GTK_STOCK_NO, NULL); | ||
| 348 | if (G_ALERTDEFAULT != aval) { | ||
| 349 | g_free(filename); | ||
| 350 | filename = NULL; | ||
| 351 | } | ||
| 352 | } | ||
| 353 | #endif | ||
| 354 | |||
| 355 | return filename; | ||
| 356 | } | ||
| 357 | |||
| 358 | gchar *filesel_select_dir(const gchar *dir) | ||
| 359 | { | ||
| 360 | GSList *list; | ||
| 361 | gchar *selected = NULL; | ||
| 362 | |||
| 363 | list = filesel_select_file_full(_("Select folder"), dir, | ||
| 364 | GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, | ||
| 365 | FALSE, NULL, 0, NULL); | ||
| 366 | if (list) { | ||
| 367 | selected = (gchar *)list->data; | ||
| 368 | slist_free_strings(list->next); | ||
| 369 | } | ||
| 370 | g_slist_free(list); | ||
| 371 | |||
| 372 | return selected; | ||
| 373 | } | ||
| 374 | |||
| 375 | static GtkWidget *filesel_create(const gchar *title, | ||
| 376 | GtkFileChooserAction action) | ||
| 377 | { | ||
| 378 | GtkWidget *dialog; | ||
| 379 | |||
| 380 | if (prefs_common.comply_gnome_hig) | ||
| 381 | dialog = gtk_file_chooser_dialog_new | ||
| 382 | (title, NULL, action, | ||
| 383 | GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | ||
| 384 | (action == GTK_FILE_CHOOSER_ACTION_SAVE || | ||
| 385 | action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) | ||
| 386 | ? GTK_STOCK_SAVE : GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, | ||
| 387 | NULL); | ||
| 388 | else | ||
| 389 | dialog = gtk_file_chooser_dialog_new | ||
| 390 | (title, NULL, action, | ||
| 391 | (action == GTK_FILE_CHOOSER_ACTION_SAVE || | ||
| 392 | action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) | ||
| 393 | ? GTK_STOCK_SAVE : GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, | ||
| 394 | GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | ||
| 395 | NULL); | ||
| 396 | gtk_window_set_position(GTK_WINDOW(dialog), | ||
| 397 | GTK_WIN_POS_CENTER_ON_PARENT); | ||
| 398 | gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); | ||
| 399 | gtk_window_set_wmclass | ||
| 400 | (GTK_WINDOW(dialog), "file_selection", "Sylpheed"); | ||
| 401 | gtk_dialog_set_default_response | ||
| 402 | (GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); | ||
| 403 | |||
| 404 | MANAGE_WINDOW_SIGNALS_CONNECT(dialog); | ||
| 405 | |||
| 406 | return dialog; | ||
| 407 | } | ||
| 408 | |||
| 409 | static void container_foreach_cb(GtkWidget *widget, gpointer data) | ||
| 410 | { | ||
| 411 | GtkWidget **expander = (GtkWidget **)data; | ||
| 412 | |||
| 413 | if (*expander == NULL) { | ||
| 414 | if (GTK_IS_EXPANDER(widget)) | ||
| 415 | *expander = widget; | ||
| 416 | else if (GTK_IS_CONTAINER(widget)) | ||
| 417 | gtk_container_foreach(GTK_CONTAINER(widget), | ||
| 418 | container_foreach_cb, data); | ||
| 419 | } | ||
| 420 | } | ||
| 421 | |||
| 422 | static void filesel_save_expander_set_expanded(GtkWidget *dialog, | ||
| 423 | gboolean expanded) | ||
| 424 | { | ||
| 425 | GtkWidget *expander = NULL; | ||
| 426 | |||
| 427 | gtk_container_foreach(GTK_CONTAINER(dialog), container_foreach_cb, | ||
| 428 | &expander); | ||
| 429 | if (expander) | ||
| 430 | gtk_expander_set_expanded(GTK_EXPANDER(expander), expanded); | ||
| 431 | } | ||
| 432 | |||
| 433 | static gboolean filesel_save_expander_get_expanded(GtkWidget *dialog) | ||
| 434 | { | ||
| 435 | GtkWidget *expander = NULL; | ||
| 436 | |||
| 437 | gtk_container_foreach(GTK_CONTAINER(dialog), container_foreach_cb, | ||
| 438 | &expander); | ||
| 439 | if (expander) | ||
| 440 | return gtk_expander_get_expanded(GTK_EXPANDER(expander)); | ||
| 441 | else | ||
| 442 | return FALSE; | ||
| 443 | } | ||
| 444 | |||
| 445 | static gchar *filesel_get_filename_with_ext(const gchar *filename, const gchar *ext) | ||
| 446 | { | ||
| 447 | gchar *base; | ||
| 448 | gchar *new_filename; | ||
| 449 | gchar *p; | ||
| 450 | |||
| 451 | base = g_path_get_basename(filename); | ||
| 452 | p = strrchr(base, '.'); | ||
| 453 | if (p) | ||
| 454 | *p = '\0'; | ||
| 455 | new_filename = g_strconcat(base, ".", ext, NULL); | ||
| 456 | debug_print("new_filename: %s\n", new_filename); | ||
| 457 | g_free(base); | ||
| 458 | |||
| 459 | return new_filename; | ||
| 460 | } | ||
| 461 | |||
| 462 | static void filesel_combo_changed_cb(GtkComboBox *combo_box, gpointer data) | ||
| 463 | { | ||
| 464 | GtkFileChooser *chooser = data; | ||
| 465 | gint active; | ||
| 466 | gchar *filename; | ||
| 467 | gchar *new_filename; | ||
| 468 | FileselFileType *types; | ||
| 469 | |||
| 470 | active = gtk_combo_box_get_active(combo_box); | ||
| 471 | filename = gtk_file_chooser_get_filename(chooser); | ||
| 472 | if (!filename) | ||
| 473 | return; | ||
| 474 | types = g_object_get_data(G_OBJECT(combo_box), "types"); | ||
| 475 | debug_print("active: %d filename: %s\n", active, filename); | ||
| 476 | debug_print("type ext: %s\n", types[active].ext); | ||
| 477 | new_filename = filesel_get_filename_with_ext(filename, types[active].ext); | ||
| 478 | gtk_file_chooser_set_current_name(chooser, new_filename); | ||
| 479 | g_free(new_filename); | ||
| 480 | g_free(filename); | ||
| 481 | } | ||
| 482 | |||
| 483 | #if GTK_CHECK_VERSION(2, 8, 0) | ||
| 484 | static GtkFileChooserConfirmation filesel_confirm_overwrite_cb | ||
| 485 | (GtkFileChooser *chooser, | ||
| 486 | gpointer data) | ||
| 487 | { | ||
| 488 | gchar *filename; | ||
| 489 | GtkFileChooserConfirmation ret = | ||
| 490 | GTK_FILE_CHOOSER_CONFIRMATION_ACCEPT_FILENAME; | ||
| 491 | |||
| 492 | filename = gtk_file_chooser_get_filename(chooser); | ||
| 493 | |||
| 494 | if (filename && is_file_exist(filename)) { | ||
| 495 | AlertValue aval; | ||
| 496 | |||
| 497 | #ifdef G_OS_WIN32 | ||
| 498 | gchar *target = NULL; | ||
| 499 | |||
| 500 | if (is_ext_lnk(filename) && | ||
| 501 | (target = filesel_get_link(filename)) != NULL && | ||
| 502 | is_dir_exist(target)) { | ||
| 503 | gtk_file_chooser_set_current_folder(chooser, target); | ||
| 504 | g_free(target); | ||
| 505 | g_free(filename); | ||
| 506 | return GTK_FILE_CHOOSER_CONFIRMATION_SELECT_AGAIN; | ||
| 507 | } | ||
| 508 | g_free(target); | ||
| 509 | #endif | ||
| 510 | |||
| 511 | aval = alertpanel(_("Overwrite existing file"), | ||
| 512 | _("The file already exists. Do you want to replace it?"), | ||
| 513 | GTK_STOCK_YES, GTK_STOCK_NO, NULL); | ||
| 514 | if (G_ALERTDEFAULT == aval) | ||
| 515 | ret = GTK_FILE_CHOOSER_CONFIRMATION_ACCEPT_FILENAME; | ||
| 516 | else | ||
| 517 | ret = GTK_FILE_CHOOSER_CONFIRMATION_SELECT_AGAIN; | ||
| 518 | } | ||
| 519 | |||
| 520 | g_free(filename); | ||
| 521 | |||
| 522 | return ret; | ||
| 523 | } | ||
| 524 | #endif | ||
| 525 | |||
| 526 | #ifdef G_OS_WIN32 | ||
| 527 | static gboolean is_ext_lnk(const gchar *filename) | ||
| 528 | { | ||
| 529 | const gchar *ext; | ||
| 530 | |||
| 531 | if (filename && (ext = strrchr(filename, '.')) && | ||
| 532 | g_ascii_strcasecmp(ext, ".lnk") == 0) | ||
| 533 | return TRUE; | ||
| 534 | |||
| 535 | return FALSE; | ||
| 536 | } | ||
| 537 | |||
| 538 | static gchar *filesel_get_link(const gchar *link_file) | ||
| 539 | { | ||
| 540 | WIN32_FIND_DATAW wfd; | ||
| 541 | IShellLinkW *psl; | ||
| 542 | IPersistFile *ppf; | ||
| 543 | HRESULT hr; | ||
| 544 | wchar_t *wlink_file; | ||
| 545 | wchar_t wtarget[MAX_PATH]; | ||
| 546 | gchar *target = NULL; | ||
| 547 | |||
| 548 | wtarget[0] = 0L; | ||
| 549 | |||
| 550 | debug_print("link_file: %s\n", link_file); | ||
| 551 | |||
| 552 | CoInitialize(NULL); | ||
| 553 | if (S_OK == CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLinkW, (void **)&psl)) { | ||
| 554 | if (S_OK == IShellLinkW_QueryInterface(psl, &IID_IPersistFile, (void **)&ppf)) { | ||
| 555 | wlink_file = g_utf8_to_utf16(link_file, -1, NULL, NULL, NULL); | ||
| 556 | if (S_OK == IPersistFile_Load(ppf, wlink_file, STGM_READ)) { | ||
| 557 | if (S_OK == IShellLinkW_GetPath(psl, wtarget, MAX_PATH, &wfd, SLGP_UNCPRIORITY)) { | ||
| 558 | target = g_utf16_to_utf8(wtarget, -1, NULL, NULL, NULL); | ||
| 559 | } | ||
| 560 | } | ||
| 561 | IPersistFile_Release(ppf); | ||
| 562 | g_free(wlink_file); | ||
| 563 | } | ||
| 564 | IShellLinkW_Release(psl); | ||
| 565 | } | ||
| 566 | CoUninitialize(); | ||
| 567 | |||
| 568 | if (target) | ||
| 569 | debug_print("target: %s\n", target); | ||
| 570 | else | ||
| 571 | debug_print("target not found\n"); | ||
| 572 | |||
| 573 | return target; | ||
| 574 | } | ||
| 575 | |||
| 576 | static GSList *filesel_resolve_link(GtkFileChooser *chooser, GSList *list, gboolean *dir_selected) | ||
| 577 | { | ||
| 578 | GSList *cur; | ||
| 579 | GSList *new_list = NULL; | ||
| 580 | gchar *target; | ||
| 581 | |||
| 582 | for (cur = list; cur != NULL; cur = cur->next) { | ||
| 583 | gchar *selected = (gchar *)cur->data; | ||
| 584 | |||
| 585 | if (is_ext_lnk(selected)) { | ||
| 586 | target = filesel_get_link(selected); | ||
| 587 | |||
| 588 | if (is_dir_exist(target)) { | ||
| 589 | gtk_file_chooser_set_current_folder(chooser, target); | ||
| 590 | g_free(target); | ||
| 591 | slist_free_strings(new_list); | ||
| 592 | g_slist_free(new_list); | ||
| 593 | new_list = NULL; | ||
| 594 | *dir_selected = TRUE; | ||
| 595 | break; | ||
| 596 | } else if (is_file_exist(target)) { | ||
| 597 | new_list = g_slist_append(new_list, target); | ||
| 598 | } else { | ||
| 599 | g_free(target); | ||
| 600 | } | ||
| 601 | } else { | ||
| 602 | new_list = g_slist_append(new_list, g_strdup(selected)); | ||
| 603 | } | ||
| 604 | } | ||
| 605 | |||
| 606 | slist_free_strings(list); | ||
| 607 | g_slist_free(list); | ||
| 608 | |||
| 609 | return new_list; | ||
| 610 | } | ||
| 611 | #endif | ||
