Gosh, some little cosmetics here...
[midnight-commander.git] / gnome / gpopup2.c
blob5efa6c2147a72204db48e90204447af02c85ad2b
1 /* Popup menus for the Midnight Commander
3 * Copyright (C) 1998 The Free Software Foundation
5 * Authors: Federico Mena <federico@nuclecu.unam.mx>
6 * Miguel de Icaza <miguel@nuclecu.unam.mx>
7 * Jonathan Blandford <jrb@redhat.com>
8 */
10 /* These rules really need to be duplicated elsewhere.
11 * They should exist for the menu bar too...
14 #include <config.h>
15 #include "global.h"
16 #include <gnome.h>
17 #include "panel.h"
18 #include "file.h"
19 #include "cmd.h"
20 #include "dialog.h"
21 #include "ext.h"
22 #include "main.h"
23 #include "../vfs/vfs.h"
24 #include "gpopup.h"
25 #include "gnome-file-property-dialog.h"
26 #include "gnome-open-dialog.h"
27 #include "gmain.h"
28 #include "gmount.h"
29 #define CLIST_FROM_SW(panel_list) GTK_CLIST (GTK_BIN (panel_list)->child)
31 int is_trash_panel = FALSE;
33 /* Flags for the popup menu entries. They specify to which kinds of files an
34 * entry is valid for.
36 enum {
37 F_ALL = 1 << 0, /* Applies to all files */
38 F_REGULAR = 1 << 1, /* Applies only to regular files */
39 F_SYMLINK = 1 << 2, /* Applies only to symlinks */
40 F_SINGLE = 1 << 3, /* Applies only to a single file, not to multiple files */
41 F_NOTDIR = 1 << 4, /* Applies to non-directories */
42 F_NOTDEV = 1 << 5, /* Applies to non-devices only (ie. reg, lnk, dir) */
43 F_ADVANCED = 1 << 6, /* Only appears in advanced mode */
44 F_MIME_ACTIONS = 1 << 7 /* Special marker for the position of MIME actions */
47 /* An entry in the actions menu */
49 typedef gboolean (*menu_func) (WPanel *panel, DesktopIconInfo *dii);
51 struct action {
52 char *text; /* Menu item text */
53 int flags; /* Flags from the above enum */
54 gpointer callback; /* Callback for menu item */
55 menu_func func; /* NULL if item is always present; a predicate otherwise */
59 /* Multiple File commands */
60 static void handle_open (GtkWidget *widget, WPanel *panel);
61 static void handle_mount (GtkWidget *widget, WPanel *panel);
62 static void handle_unmount (GtkWidget *widget, WPanel *panel);
63 static void handle_eject (GtkWidget *widget, WPanel *panel);
64 static void handle_view (GtkWidget *widget, WPanel *panel);
65 static void handle_view_unfiltered (GtkWidget *widget, WPanel *panel);
66 static void handle_edit (GtkWidget *widget, WPanel *panel);
67 static void handle_copy (GtkWidget *widget, WPanel *panel);
68 static void handle_trash (GtkWidget *widget, WPanel *panel);
69 static void handle_empty_trash (GtkWidget *widget, WPanel *panel);
70 static void handle_delete (GtkWidget *widget, WPanel *panel);
71 static void handle_move (GtkWidget *widget, WPanel *panel);
73 /* F_SINGLE file commands */
74 static void handle_properties (GtkWidget *widget, WPanel *panel);
75 static void handle_open_with (GtkWidget *widget, WPanel *panel);
76 static void handle_symlink (GtkWidget *widget, WPanel *panel);
77 static void handle_hard_link (GtkWidget *widget, WPanel *panel);
78 static void handle_edit_symlink (GtkWidget *widget, WPanel *panel);
80 /* Helper funcs and testing funcs. */
81 static gboolean check_mount_func (WPanel *panel, DesktopIconInfo *dii);
82 static gboolean check_unmount_func (WPanel *panel, DesktopIconInfo *dii);
83 static gboolean check_eject_func (WPanel *panel, DesktopIconInfo *dii);
84 static gboolean check_device_func (WPanel *panel, DesktopIconInfo *dii);
85 static gboolean check_trash_func (WPanel *panel, DesktopIconInfo *dii);
86 static gboolean check_trash_icon_func (WPanel *panel, DesktopIconInfo *dii);
88 static gchar * get_full_filename (WPanel *panel);
90 /* Now, the actual code */
91 static gchar *
92 get_full_filename (WPanel *panel)
94 if (is_a_desktop_panel (panel)) {
95 gint i;
96 for (i = 0; i < panel->count; i++)
97 if (panel->dir.list [i].f.marked) {
98 return concat_dir_and_file (panel->cwd,
99 panel->dir.list [i].fname);
101 g_return_val_if_fail (FALSE, NULL);
102 } else
103 return concat_dir_and_file (panel->cwd, selection (panel)->fname);
107 static gboolean
108 check_mount_umount (DesktopIconInfo *dii, int mount)
110 char *full_name;
111 file_entry *fe;
112 int v;
113 int is_mounted;
115 full_name = g_concat_dir_and_file (desktop_directory, dii->filename);
116 fe = file_entry_from_file (full_name);
117 if (!fe) {
118 g_free (full_name);
119 return FALSE;
122 v = is_mountable (full_name, fe, &is_mounted, NULL);
123 file_entry_free (fe);
124 g_free (full_name);
126 if (!v)
127 return FALSE;
129 if (is_mounted && mount)
130 return FALSE;
132 if (!is_mounted && !mount)
133 return FALSE;
135 return TRUE;
138 static gboolean
139 check_mount_func (WPanel *panel, DesktopIconInfo *dii)
141 if (!dii)
142 return FALSE;
144 return check_mount_umount (dii, TRUE);
147 static gboolean
148 check_unmount_func (WPanel *panel, DesktopIconInfo *dii)
150 if (!dii)
151 return FALSE;
153 return check_mount_umount (dii, FALSE);
156 static gboolean
157 check_eject_func (WPanel *panel, DesktopIconInfo *dii)
159 char *full_name;
160 file_entry *fe;
161 int v;
162 int is_mounted;
163 int retval;
165 if (!dii)
166 return FALSE;
168 full_name = g_concat_dir_and_file (desktop_directory, dii->filename);
169 fe = file_entry_from_file (full_name);
170 if (!fe) {
171 g_free (full_name);
172 return FALSE;
175 v = is_mountable (full_name, fe, &is_mounted, NULL);
176 file_entry_free (fe);
178 if (!v)
179 retval = FALSE;
180 else if (!is_ejectable (full_name))
181 retval = FALSE;
182 else
183 retval = TRUE;
185 g_free (full_name);
186 return retval;
188 static gboolean
189 check_device_func (WPanel *panel, DesktopIconInfo *dii)
191 return (check_mount_func (panel, dii) ||
192 check_unmount_func (panel, dii) ||
193 check_eject_func (panel, dii));
196 static gboolean
197 check_trash_func (WPanel *panel, DesktopIconInfo *dii)
199 gchar *trash_dir;
200 struct stat st;
201 gint i;
202 trash_dir = g_strconcat (gnome_user_home_dir, "/",
203 DESKTOP_DIR_NAME, "/",
204 "Trash.gmc",
205 NULL);
207 if (mc_stat (trash_dir, &st) || !S_ISDIR (st.st_mode)) {
208 g_free (trash_dir);
209 return FALSE;
212 if (strncmp (trash_dir, panel->cwd, strlen (trash_dir)) == 0) {
213 g_free (trash_dir);
214 return FALSE;
217 for (i = 0; i < panel->count; i++) {
218 if (panel->dir.list [i].f.marked) {
219 gchar *desktop_file = concat_dir_and_file (panel->cwd,
220 panel->dir.list [i].fname);
221 if (strncmp (desktop_file, trash_dir, strlen (trash_dir)) == 0) {
222 g_free (desktop_file);
223 g_free (trash_dir);
224 return FALSE;
226 g_free (desktop_file);
230 g_free (trash_dir);
231 return TRUE;
234 static gboolean
235 check_trash_icon_func (WPanel *panel, DesktopIconInfo *dii)
237 gchar *trash_dir;
238 gchar *file_name;
240 if (!is_a_desktop_panel (panel))
241 return FALSE;
243 trash_dir = g_strconcat (gnome_user_home_dir, "/",
244 DESKTOP_DIR_NAME, "/",
245 "Trash.gmc",
246 NULL);
247 file_name = get_full_filename (panel);
249 if (strncmp (trash_dir, file_name, strlen (trash_dir)) == 0) {
250 DIR *dirp;
251 struct dirent *dp;
252 gint i = 0;
254 dirp = mc_opendir (file_name);
255 g_free (trash_dir);
256 g_free (file_name);
258 for (dp = mc_readdir (dirp); dp; dp = mc_readdir (dirp)) {
259 i ++;
260 if (i > 2) {
261 mc_closedir (dirp);
262 return TRUE;
265 mc_closedir (dirp);
266 return FALSE;
268 g_free (trash_dir);
269 g_free (file_name);
270 return FALSE;
273 /* global vars */
274 extern int we_can_afford_the_speed;
276 static struct action file_actions[] = {
277 { N_("Open"), F_NOTDEV | F_SINGLE, handle_open, NULL },
278 { "", F_NOTDEV | F_SINGLE, NULL, NULL },
279 { N_("Mount device"), F_ALL | F_SINGLE, handle_mount, check_mount_func },
280 { N_("Unmount device"), F_ALL | F_SINGLE, handle_unmount, check_unmount_func },
281 { N_("Eject device"), F_ALL | F_SINGLE, handle_eject, check_eject_func },
282 { N_("Empty Trash"), F_SINGLE, handle_empty_trash, check_trash_icon_func },
283 /* Custom actions go here */
284 { "", F_MIME_ACTIONS | F_SINGLE, NULL, check_device_func },
285 { N_("Open with..."), F_REGULAR | F_SINGLE, handle_open_with, NULL },
286 { N_("View"), F_REGULAR | F_SINGLE, handle_view, NULL },
287 { N_("View Unfiltered"), F_REGULAR | F_ADVANCED | F_SINGLE, handle_view_unfiltered, NULL },
288 { N_("Edit"), F_REGULAR | F_SINGLE, handle_edit, NULL },
289 { "", F_REGULAR | F_SINGLE, NULL, NULL },
290 { N_("Copy..."), F_ALL, handle_copy, NULL },
291 { N_("Move to Trash"), F_ALL, handle_trash, check_trash_func },
292 { N_("Delete"), F_ALL, handle_delete, NULL },
293 { N_("Move..."), F_ALL, handle_move, NULL },
294 { N_("Hard Link..."), F_ADVANCED | F_SINGLE, handle_hard_link, NULL },
295 { N_("Symlink..."), F_SINGLE, handle_symlink, NULL },
296 { N_("Edit Symlink..."), F_SYMLINK | F_SINGLE, handle_edit_symlink, NULL },
297 { "", F_SINGLE | F_ALL, NULL, NULL },
298 { N_("Properties..."), F_SINGLE | F_ALL, handle_properties, NULL },
299 { NULL, 0, NULL, NULL }
302 /* This is our custom signal connection function for popup menu items -- see below for the
303 * marshaller information. We pass the original callback function as the data pointer for the
304 * marshaller (uiinfo->moreinfo).
306 static void
307 popup_connect_func (GnomeUIInfo *uiinfo, gchar *signal_name, GnomeUIBuilderData *uibdata)
309 g_assert (uibdata->is_interp);
311 if (uiinfo->moreinfo) {
312 gtk_object_set_data (GTK_OBJECT (uiinfo->widget), "popup_user_data",
313 uiinfo->user_data);
314 gtk_signal_connect_full (GTK_OBJECT (uiinfo->widget), signal_name,
315 NULL,
316 uibdata->relay_func,
317 uiinfo->moreinfo,
318 uibdata->destroy_func,
319 FALSE,
320 FALSE);
324 /* Our custom marshaller for menu items. We need it so that it can extract the
325 * per-attachment user_data pointer from the parent menu shell and pass it to
326 * the callback. This overrides the user-specified data from the GnomeUIInfo
327 * structures.
330 typedef void (* ActivateFunc) (GtkObject *object, WPanel *panel);
332 static void
333 popup_marshal_func (GtkObject *object, gpointer data, guint n_args, GtkArg *args)
335 ActivateFunc func;
336 gpointer user_data;
338 func = (ActivateFunc) data;
339 user_data = gtk_object_get_data (object, "popup_user_data");
341 gtk_object_set_data (GTK_OBJECT (GTK_WIDGET (object)->parent), "popup_active_item", object);
342 (* func) (object, user_data);
345 /* Fills the menu with the specified uiinfo at the specified position, using our
346 * magic marshallers to be able to fetch the active item. The code is
347 * shamelessly ripped from gnome-popup-menu.
349 static void
350 fill_menu (GtkMenuShell *menu_shell, GnomeUIInfo *uiinfo, int pos)
352 GnomeUIBuilderData uibdata;
354 /* We use our own callback marshaller so that it can fetch the popup
355 * user data from the popup menu and pass it on to the user-defined
356 * callbacks.
359 uibdata.connect_func = popup_connect_func;
360 uibdata.data = NULL;
361 uibdata.is_interp = TRUE;
362 uibdata.relay_func = popup_marshal_func;
363 uibdata.destroy_func = NULL;
365 gnome_app_fill_menu_custom (menu_shell, uiinfo, &uibdata, NULL, FALSE, pos);
368 /* Convenience function to free something when an object is destroyed */
369 static void
370 free_on_destroy (GtkObject *object, gpointer data)
372 g_free (data);
375 /* Callback for MIME-based actions */
376 static void
377 mime_action_callback (GtkWidget *widget, gpointer data)
379 char *filename;
380 char *key, *buf;
381 const char *mime_type;
382 const char *value;
383 int needs_terminal = 0;
384 int size;
386 filename = data;
387 key = gtk_object_get_user_data (GTK_OBJECT (widget));
389 g_assert (filename != NULL);
390 g_assert (key != NULL);
392 if (use_magic)
393 mime_type = gnome_mime_type_or_default_of_file (filename, NULL);
394 else
395 mime_type = gnome_mime_type_or_default (filename, NULL);
396 g_assert (mime_type != NULL);
399 * Find out if we need to run this in a terminal
401 if (gnome_metadata_get (filename, "flags", &size, &buf) == 0){
402 needs_terminal = strstr (buf, "needsterminal") != 0;
403 g_free (buf);
404 } else {
405 char *flag_key;
406 const char *flags;
408 flag_key = g_strconcat ("flags.", key, "flags", NULL);
409 flags = gnome_mime_get_value (filename, flag_key);
410 g_free (flag_key);
411 if (flags)
412 needs_terminal = strstr (flags, "needsterminal") != 0;
415 value = gnome_mime_get_value (mime_type, key);
416 exec_extension (filename, value, NULL, NULL, 0, needs_terminal);
419 /* Escapes the underlines in the specified string for use by GtkLabel */
420 static char *
421 escape_underlines (char *str)
423 char *buf;
424 char *p;
426 buf = g_new (char, 2 * strlen (str) + 1);
428 for (p = buf; *str; str++) {
429 if (*str == '_')
430 *p++ = '_';
432 *p++ = *str;
435 *p = '\0';
437 return buf;
440 /* Creates the menu items for actions based on the MIME type of the selected
441 * file in the panel.
443 static int
444 create_mime_actions (GtkWidget *menu, WPanel *panel, int pos, DesktopIconInfo *dii)
446 char *full_name;
447 const char *mime_type;
448 GList *keys, *l;
449 gint pos_init = pos;
450 GnomeUIInfo uiinfo[] = {
451 { 0 },
452 GNOMEUIINFO_END
455 if (is_a_desktop_panel (panel)) {
456 g_assert (dii != NULL);
457 full_name = g_concat_dir_and_file (panel->cwd, dii->filename);
458 } else
459 full_name = g_concat_dir_and_file (panel->cwd,
460 panel->dir.list[panel->selected].fname);
461 if (use_magic)
462 mime_type = gnome_mime_type_or_default_of_file (full_name, NULL);
463 else
464 mime_type = gnome_mime_type_or_default (full_name, NULL);
465 if (!mime_type) {
466 g_free (full_name);
467 return pos;
470 keys = gnome_mime_get_keys (mime_type);
471 for (l = keys; l; l = l->next) {
472 char *key;
473 char *str;
475 str = key = l->data;
477 if (strncmp (key, "open.", 5) != 0)
478 continue;
480 str += 5;
481 while (*str && *str != '.')
482 str++;
484 if (*str)
485 str++;
487 if (!*str)
488 continue;
490 /* Create the item for that entry */
492 str = escape_underlines (str);
494 uiinfo[0].type = GNOME_APP_UI_ITEM;
495 uiinfo[0].label = str;
496 uiinfo[0].hint = NULL;
497 uiinfo[0].moreinfo = mime_action_callback;
498 uiinfo[0].user_data = full_name;
499 uiinfo[0].unused_data = NULL;
500 uiinfo[0].pixmap_type = GNOME_APP_PIXMAP_NONE;
501 uiinfo[0].pixmap_info = NULL;
502 uiinfo[0].accelerator_key = 0;
503 uiinfo[0].ac_mods = 0;
504 uiinfo[0].widget = NULL;
506 fill_menu (GTK_MENU_SHELL (menu), uiinfo, pos++);
507 g_free (str);
509 gtk_object_set_user_data (GTK_OBJECT (uiinfo[0].widget), key);
513 /* Remember to free this memory */
514 gtk_signal_connect (GTK_OBJECT (menu), "destroy",
515 (GtkSignalFunc) free_on_destroy,
516 full_name);
518 if (pos_init != pos) {
519 uiinfo[0].type = GNOME_APP_UI_SEPARATOR;
520 fill_menu (GTK_MENU_SHELL (menu), uiinfo, pos++);
521 g_list_free (keys);
524 return pos;
527 /* Creates the menu items for the standard actions. Returns the position at
528 * which additional menu items should be inserted.
530 static void
531 create_actions (GtkWidget *menu, gint flags, WPanel *panel, DesktopIconInfo *dii)
533 struct action *action;
534 int pos;
535 GnomeUIInfo uiinfo[] = {
536 { 0 },
537 GNOMEUIINFO_END
540 pos = 0;
542 for (action = file_actions; action->text; action++) {
543 /* Insert the MIME actions if appropriate */
544 if ((action->flags & F_MIME_ACTIONS) && (flags & F_SINGLE)) {
545 int curpos = pos;
546 pos = create_mime_actions (menu, panel, pos, dii);
547 /* Why do we do this? If the mime actions are there, and it's mountable,
548 * we can count on the separator at the end of the mime_actions
549 * menu. However, if the mime_actions aren't there, we need a separator */
550 if (pos == curpos && (action->func)(panel, dii)) {
551 uiinfo[0].type = GNOME_APP_UI_SEPARATOR;
552 fill_menu (GTK_MENU_SHELL (menu), uiinfo, pos++);
554 continue;
557 /* Filter the actions that are not appropriate */
558 if ((action->flags & flags) != action->flags)
559 continue;
561 if (action->func && !((action->func)(panel, dii)))
562 continue;
564 /* Create the menu item for this action */
565 if (action->text[0]) {
566 uiinfo[0].type = GNOME_APP_UI_ITEM;
567 uiinfo[0].label = _(action->text);
568 uiinfo[0].hint = NULL;
569 uiinfo[0].moreinfo = action->callback;
570 uiinfo[0].user_data = (gpointer) panel;
571 uiinfo[0].unused_data = NULL;
572 uiinfo[0].pixmap_type = GNOME_APP_PIXMAP_NONE;
573 uiinfo[0].pixmap_info = NULL;
574 uiinfo[0].accelerator_key = 0;
575 uiinfo[0].ac_mods = 0;
576 uiinfo[0].widget = NULL;
577 } else
578 uiinfo[0].type = GNOME_APP_UI_SEPARATOR;
580 fill_menu (GTK_MENU_SHELL (menu), uiinfo, pos++);
584 /* Convenience callback to exit the main loop of a modal popup menu when it is deactivated*/
585 static void
586 menu_shell_deactivated (GtkMenuShell *menu_shell, WPanel *panel)
588 gtk_main_quit ();
591 /* Returns the index of the active item in the specified menu, or -1 if none is active */
592 static int
593 get_active_index (GtkMenu *menu)
595 GList *l;
596 GtkWidget *active;
597 int i;
599 active = gtk_object_get_data (GTK_OBJECT (menu), "popup_active_item");
601 for (i = 0, l = GTK_MENU_SHELL (menu)->children; l; l = l->next, i++)
602 if (active == l->data)
603 return i;
605 return -1;
608 #define REMOVE(x,f) x &= ~f
611 gpopup_do_popup2 (GdkEventButton *event, WPanel *panel, DesktopIconInfo *dii)
613 GtkWidget *menu;
614 gint flags = F_ALL | F_REGULAR | F_SYMLINK | F_SINGLE | F_NOTDEV | F_NOTDIR;
615 struct stat s;
616 guint id;
617 int i;
618 int marked;
620 g_return_val_if_fail (event != NULL, -1);
621 g_return_val_if_fail (panel != NULL, -1);
623 menu = gtk_menu_new ();
625 /* Connect to the deactivation signal to be able to quit our modal main
626 * loop.
628 id = gtk_signal_connect (GTK_OBJECT (menu), "deactivate",
629 (GtkSignalFunc) menu_shell_deactivated,
630 NULL);
632 marked = 0;
634 for (i = 0; i < panel->count; i++) {
635 if (!strcmp (panel->dir.list [i].fname, "..") || !panel->dir.list[i].f.marked)
636 continue;
638 marked++;
640 s = panel->dir.list[i].buf;
642 if (S_ISLNK (s.st_mode))
643 mc_stat (panel->dir.list [i].fname, &s);
644 else
645 REMOVE (flags, F_SYMLINK);
647 if (S_ISDIR (s.st_mode))
648 REMOVE (flags, F_NOTDIR);
650 if (!S_ISREG (s.st_mode))
651 REMOVE (flags, F_REGULAR);
653 if (S_ISCHR (s.st_mode) || S_ISBLK (s.st_mode))
654 REMOVE (flags, F_NOTDEV);
657 if (marked == 0)
658 return 1;
660 if (marked > 1)
661 REMOVE (flags, F_SINGLE);
663 /* Fill the menu */
664 create_actions (menu, flags, panel, dii);
666 /* Run it */
667 gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, event->button, event->time);
668 gtk_grab_add (menu);
669 gtk_main ();
670 gtk_grab_remove (menu);
672 gtk_signal_disconnect (GTK_OBJECT (menu), id);
674 i = get_active_index (GTK_MENU (menu));
675 gtk_widget_unref (menu);
676 return 1;
679 static void
680 handle_open (GtkWidget *widget, WPanel *panel)
684 if (is_a_desktop_panel (panel)) {
685 gchar *full_name;
686 DesktopIconInfo *dii;
688 full_name = get_full_filename (panel);
689 dii = desktop_icon_info_get_by_filename (x_basename (full_name));
690 g_assert (dii != NULL);
692 desktop_icon_info_open (dii);
693 g_free (full_name);
694 return;
696 do_enter (panel);
699 static void
700 perform_mount_unmount (WPanel *panel, int mount)
702 char *full_name;
703 DesktopIconInfo *dii;
705 g_assert (is_a_desktop_panel (panel));
707 full_name = get_full_filename (panel);
708 dii = desktop_icon_info_get_by_filename (x_basename (full_name));
709 g_assert (dii != NULL);
711 desktop_icon_set_busy (dii, TRUE);
712 do_mount_umount (full_name, mount);
713 desktop_icon_set_busy (dii, FALSE);
714 g_free (full_name);
717 static void
718 handle_mount (GtkWidget *widget, WPanel *panel)
720 perform_mount_unmount (panel, TRUE);
721 update_panels (UP_RELOAD, UP_KEEPSEL);
724 static void
725 handle_unmount (GtkWidget *widget, WPanel *panel)
727 perform_mount_unmount (panel, FALSE);
728 update_panels (UP_RELOAD, UP_KEEPSEL);
731 static void
732 handle_eject (GtkWidget *widget, WPanel *panel)
734 char *full_name;
735 char *lname;
736 DesktopIconInfo *dii;
738 g_assert (is_a_desktop_panel (panel));
740 full_name = get_full_filename (panel);
741 dii = desktop_icon_info_get_by_filename (x_basename (full_name));
742 g_assert (dii != NULL);
744 desktop_icon_set_busy (dii, TRUE);
746 lname = g_readlink (full_name);
747 if (!lname){
748 g_free (full_name);
749 desktop_icon_set_busy (dii, FALSE);
750 return;
753 if (is_block_device_mounted (lname))
754 do_mount_umount (full_name, FALSE);
756 do_eject (lname);
758 desktop_icon_set_busy (dii, FALSE);
759 update_panels (UP_RELOAD, UP_KEEPSEL);
760 g_free (lname);
761 g_free (full_name);
764 static void
765 handle_view (GtkWidget *widget, WPanel *panel)
767 gchar *full_name;
769 full_name = get_full_filename (panel);
770 gmc_view (full_name, 0);
771 g_free (full_name);
774 static void
775 handle_view_unfiltered (GtkWidget *widget, WPanel *panel)
777 /* We need it to do the right thing later. */
778 /*view_simple_cmd (panel);*/
779 return;
782 static void
783 handle_edit (GtkWidget *widget, WPanel *panel)
785 gchar *full_name;
787 full_name = get_full_filename (panel);
788 gmc_edit (full_name);
789 g_free (full_name);
792 static void
793 handle_copy (GtkWidget *widget, WPanel *panel)
795 copy_cmd ();
798 /* Empties trash when in the Trash panel */
799 static void
800 handle_trash (GtkWidget *widget, WPanel *panel)
802 gchar *trash_dir;
804 trash_dir = g_strconcat (gnome_user_home_dir, "/",
805 DESKTOP_DIR_NAME, "/",
806 "Trash.gmc",
807 NULL);
809 if (panel_operate (cpanel, OP_MOVE, trash_dir, FALSE)) {
810 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
811 repaint_screen ();
815 /* Empties trash from the desktop */
816 static void
817 handle_empty_trash (GtkWidget *widget, WPanel *panel)
819 gnome_empty_trash (NULL, NULL);
822 static void
823 handle_delete (GtkWidget *widget, WPanel *panel)
825 delete_cmd ();
828 static void
829 handle_move (GtkWidget *widget, WPanel *panel)
831 ren_cmd ();
834 /* F_SINGLE file commands */
835 static void
836 handle_properties (GtkWidget *widget, WPanel *panel)
838 gint retval = 0;
839 GtkWidget *dialog;
840 gchar *full_name = NULL;
841 int run;
843 full_name = get_full_filename (panel);
844 dialog = gnome_file_property_dialog_new (full_name,
845 (is_a_desktop_panel (panel)
846 ? TRUE
847 : we_can_afford_the_speed));
849 if (!is_a_desktop_panel (panel))
850 gnome_dialog_set_parent (GNOME_DIALOG (dialog), GTK_WINDOW (panel->xwindow));
852 run = gnome_dialog_run (GNOME_DIALOG (dialog));
853 if (run == 0)
854 retval = gnome_file_property_dialog_make_changes (
855 GNOME_FILE_PROPERTY_DIALOG (dialog));
857 if (run != -1)
858 gtk_widget_destroy (dialog);
860 g_free (full_name);
861 if (retval && !is_a_desktop_panel (panel))
862 reread_cmd ();
865 static void
866 handle_open_with (GtkWidget *widget, WPanel *panel)
868 gchar *full_name;
869 full_name = get_full_filename (panel);
870 gmc_open_with (full_name);
871 g_free (full_name);
874 static void
875 handle_hard_link (GtkWidget *widget, WPanel *panel)
877 /* yeah right d: -jrb */
878 link_cmd ();
881 static void
882 handle_symlink (GtkWidget *widget, WPanel *panel)
884 symlink_cmd ();
887 static void
888 handle_edit_symlink (GtkWidget *widget, WPanel *panel)
890 edit_symlink_cmd ();