r171: Fixed a compile problem on IRIX. Updating items now resorts.
[rox-filer.git] / ROX-Filer / src / action.c
blob753da1a122925b690ede42227d598a6e9e157cdf
1 /*
2 * $Id$
4 * ROX-Filer, filer for the ROX desktop project
5 * Copyright (C) 1999, Thomas Leonard, <tal197@ecs.soton.ac.uk>.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
22 /* action.c - code for handling the filer action windows.
23 * These routines generally fork() and talk to us via pipes.
26 #include "config.h"
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31 #include <errno.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <signal.h>
35 #include <dirent.h>
37 #include "action.h"
38 #include "string.h"
39 #include "support.h"
40 #include "gui_support.h"
41 #include "filer.h"
42 #include "main.h"
44 static GdkColor red = {0, 0xffff, 0, 0};
46 typedef struct _GUIside GUIside;
47 typedef void ActionChild(gpointer data);
48 typedef gboolean ForDirCB(char *path, char *dest_path);
50 struct _GUIside
52 int from_child; /* File descriptor */
53 FILE *to_child;
54 int input_tag; /* gdk_input_add() */
55 GtkWidget *log, *window, *actions, *dir;
56 int child; /* Process ID */
57 int errors;
58 gboolean show_info; /* For Disk Usage */
60 char *next_dir; /* NULL => no timer active */
61 gint next_timer;
64 /* These don't need to be in a structure because we fork() before
65 * using them again.
67 static int from_parent = 0;
68 static FILE *to_parent = NULL;
69 static gboolean quiet = FALSE;
70 static GString *message = NULL;
71 static char *action_dest = NULL;
72 static gboolean (*action_do_func)(char *source, char *dest);
73 static size_t size_tally; /* For Disk Usage */
74 static DirItem *mount_item;
76 /* Static prototypes */
77 static gboolean send();
78 static gboolean send_error();
79 static gboolean send_dir(char *dir);
80 static gboolean read_exact(int source, char *buffer, ssize_t len);
81 static void do_mount(FilerWindow *filer_window, DirItem *item);
83 static gboolean display_dir(gpointer data)
85 GUIside *gui_side = (GUIside *) data;
87 gtk_label_set_text(GTK_LABEL(gui_side->dir), gui_side->next_dir + 1);
88 g_free(gui_side->next_dir);
89 gui_side->next_dir = NULL;
91 return FALSE;
94 /* Called when the child sends us a message */
95 static void message_from_child(gpointer data,
96 gint source,
97 GdkInputCondition condition)
99 char buf[5];
100 GUIside *gui_side = (GUIside *) data;
101 GtkWidget *log = gui_side->log;
103 if (read_exact(source, buf, 4))
105 ssize_t message_len;
106 char *buffer;
108 buf[4] = '\0';
109 message_len = strtol(buf, NULL, 16);
110 buffer = g_malloc(message_len + 1);
111 if (message_len > 0 && read_exact(source, buffer, message_len))
113 buffer[message_len] = '\0';
114 if (*buffer == '?')
115 gtk_widget_set_sensitive(gui_side->actions,
116 TRUE);
117 else if (*buffer == '+')
119 refresh_dirs(buffer + 1);
120 g_free(buffer);
121 return;
123 else if (*buffer == 'm')
125 filer_check_mounted(buffer + 1);
126 g_free(buffer);
127 return;
129 else if (*buffer == '/')
131 if (gui_side->next_dir)
132 g_free(gui_side->next_dir);
133 else
134 gui_side->next_timer =
135 gtk_timeout_add(500,
136 display_dir,
137 gui_side);
138 gui_side->next_dir = buffer;
139 return;
141 else if (*buffer == '!')
142 gui_side->errors++;
144 gtk_text_insert(GTK_TEXT(log),
145 NULL,
146 *buffer == '!' ? &red : NULL,
147 NULL,
148 buffer + 1, message_len - 1);
149 g_free(buffer);
150 return;
152 g_print("Child died in the middle of a message.\n");
155 /* The child is dead */
156 gui_side->child = 0;
158 fclose(gui_side->to_child);
159 close(gui_side->from_child);
160 gdk_input_remove(gui_side->input_tag);
162 if (gui_side->errors)
164 GString *report;
165 report = g_string_new(NULL);
166 g_string_sprintf(report, "There %s %d error%s.\n",
167 gui_side->errors == 1 ? "was" : "were",
168 gui_side->errors,
169 gui_side->errors == 1 ? "" : "s");
170 gtk_text_insert(GTK_TEXT(log), NULL, &red, NULL,
171 report->str, report->len);
173 g_string_free(report, TRUE);
175 else if (gui_side->show_info == FALSE)
176 gtk_widget_destroy(gui_side->window);
179 /* Scans src_dir, updating dest_path whenever cb returns TRUE */
180 static void for_dir_contents(ForDirCB *cb, char *src_dir, char *dest_path)
182 DIR *d;
183 struct dirent *ent;
184 GSList *list = NULL, *next;
186 d = opendir(src_dir);
187 if (!d)
189 send_error();
190 return;
193 send_dir(src_dir);
195 while ((ent = readdir(d)))
197 if (ent->d_name[0] == '.' && (ent->d_name[1] == '\0'
198 || (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
199 continue;
200 list = g_slist_append(list, g_strdup(make_path(src_dir,
201 ent->d_name)->str));
203 closedir(d);
205 if (!list)
206 return;
208 next = list;
210 while (next)
212 if (cb((char *) next->data, dest_path))
214 g_string_sprintf(message, "+%s", dest_path);
215 send();
218 g_free(next->data);
219 next = next->next;
221 g_slist_free(list);
222 return;
225 /* Read this many bytes into the buffer. TRUE on success. */
226 static gboolean read_exact(int source, char *buffer, ssize_t len)
228 while (len > 0)
230 ssize_t got;
231 got = read(source, buffer, len);
232 if (got < 1)
233 return FALSE;
234 len -= got;
235 buffer += got;
237 return TRUE;
240 /* Send 'message' to our parent process. TRUE on success. */
241 static gboolean send()
243 char len_buffer[5];
244 ssize_t len;
246 g_return_val_if_fail(message->len < 0xffff, FALSE);
248 sprintf(len_buffer, "%04x", message->len);
249 fwrite(len_buffer, 1, 4, to_parent);
250 len = fwrite(message->str, 1, message->len, to_parent);
251 fflush(to_parent);
252 return len == message->len;
255 /* Set the directory indicator at the top of the window */
256 static gboolean send_dir(char *dir)
258 g_string_sprintf(message, "/%s", dir);
259 return send();
262 static gboolean send_error()
264 g_string_sprintf(message, "!ERROR: %s\n", g_strerror(errno));
265 return send();
268 static void button_reply(GtkWidget *button, GUIside *gui_side)
270 char *text;
272 text = gtk_object_get_data(GTK_OBJECT(button), "send-code");
273 g_return_if_fail(text != NULL);
274 fputc(*text, gui_side->to_child);
275 fflush(gui_side->to_child);
277 gtk_widget_set_sensitive(gui_side->actions, FALSE);
280 /* Get one char from fd. Quit on error. */
281 static char reply(int fd)
283 ssize_t len;
284 char retval;
286 len = read(fd, &retval, 1);
287 if (len == 1)
288 return retval;
290 fprintf(stderr, "read() error: %s\n", g_strerror(errno));
291 _exit(1); /* Parent died? */
292 return '!';
295 static void destroy_action_window(GtkWidget *widget, gpointer data)
297 GUIside *gui_side = (GUIside *) data;
299 if (gui_side->child)
301 kill(gui_side->child, SIGTERM);
302 fclose(gui_side->to_child);
303 close(gui_side->from_child);
304 gdk_input_remove(gui_side->input_tag);
307 if (gui_side->next_dir)
309 gtk_timeout_remove(gui_side->next_timer);
310 g_free(gui_side->next_dir);
312 g_free(gui_side);
314 if (--number_of_windows < 1)
315 gtk_main_quit();
318 /* Create two pipes, fork() a child and return a pointer to a GUIside struct
319 * (NULL on failure). The child calls func().
321 static GUIside *start_action(gpointer data, ActionChild *func)
323 int filedes[4]; /* 0 and 2 are for reading */
324 GUIside *gui_side;
325 int child;
326 GtkWidget *vbox, *button, *control, *hbox, *scrollbar;
328 if (pipe(filedes))
330 report_error("ROX-Filer", g_strerror(errno));
331 return NULL;
334 if (pipe(filedes + 2))
336 close(filedes[0]);
337 close(filedes[1]);
338 report_error("ROX-Filer", g_strerror(errno));
339 return NULL;
342 child = fork();
343 switch (child)
345 case -1:
346 report_error("ROX-Filer", g_strerror(errno));
347 return NULL;
348 case 0:
349 /* We are the child */
350 message = g_string_new(NULL);
351 close(filedes[0]);
352 close(filedes[3]);
353 to_parent = fdopen(filedes[1], "wb");
354 from_parent = filedes[2];
355 func(data);
356 _exit(0);
359 /* We are the parent */
360 close(filedes[1]);
361 close(filedes[2]);
362 gui_side = g_malloc(sizeof(GUIside));
363 gui_side->from_child = filedes[0];
364 gui_side->to_child = fdopen(filedes[3], "wb");
365 gui_side->log = NULL;
366 gui_side->child = child;
367 gui_side->errors = 0;
368 gui_side->show_info = FALSE;
370 gui_side->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
371 gtk_window_set_default_size(GTK_WINDOW(gui_side->window), 500, 100);
372 gtk_signal_connect(GTK_OBJECT(gui_side->window), "destroy",
373 GTK_SIGNAL_FUNC(destroy_action_window), gui_side);
375 vbox = gtk_vbox_new(FALSE, 4);
376 gtk_container_add(GTK_CONTAINER(gui_side->window), vbox);
378 gui_side->dir = gtk_label_new("<dir>");
379 gui_side->next_dir = NULL;
380 gtk_misc_set_alignment(GTK_MISC(gui_side->dir), 0.5, 0.5);
381 gtk_box_pack_start(GTK_BOX(vbox), gui_side->dir, FALSE, TRUE, 0);
383 hbox = gtk_hbox_new(FALSE, 0);
384 gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
386 gui_side->log = gtk_text_new(NULL, NULL);
387 gtk_box_pack_start(GTK_BOX(hbox), gui_side->log, TRUE, TRUE, 0);
388 scrollbar = gtk_vscrollbar_new(GTK_TEXT(gui_side->log)->vadj);
389 gtk_box_pack_start(GTK_BOX(hbox), scrollbar, FALSE, TRUE, 0);
391 gui_side->actions = gtk_hbox_new(TRUE, 4);
392 gtk_box_pack_start(GTK_BOX(vbox), gui_side->actions, FALSE, TRUE, 0);
394 button = gtk_button_new_with_label("Always");
395 gtk_object_set_data(GTK_OBJECT(button), "send-code", "A");
396 gtk_box_pack_start(GTK_BOX(gui_side->actions), button, TRUE, TRUE, 0);
397 gtk_signal_connect(GTK_OBJECT(button), "clicked",
398 button_reply, gui_side);
399 button = gtk_button_new_with_label("Yes");
400 gtk_object_set_data(GTK_OBJECT(button), "send-code", "Y");
401 gtk_box_pack_start(GTK_BOX(gui_side->actions), button, TRUE, TRUE, 0);
402 gtk_signal_connect(GTK_OBJECT(button), "clicked",
403 button_reply, gui_side);
404 button = gtk_button_new_with_label("No");
405 gtk_object_set_data(GTK_OBJECT(button), "send-code", "N");
406 gtk_box_pack_start(GTK_BOX(gui_side->actions), button, TRUE, TRUE, 0);
407 gtk_signal_connect(GTK_OBJECT(button), "clicked",
408 button_reply, gui_side);
409 gtk_widget_set_sensitive(gui_side->actions, FALSE);
411 control = gtk_hbox_new(TRUE, 4);
412 gtk_box_pack_start(GTK_BOX(vbox), control, FALSE, TRUE, 0);
414 button = gtk_button_new_with_label("Suspend");
415 gtk_box_pack_start(GTK_BOX(control), button, TRUE, TRUE, 0);
417 button = gtk_button_new_with_label("Resume");
418 gtk_widget_set_sensitive(button, FALSE);
419 gtk_box_pack_start(GTK_BOX(control), button, TRUE, TRUE, 0);
421 button = gtk_button_new_with_label("Abort");
422 gtk_box_pack_start(GTK_BOX(control), button, TRUE, TRUE, 0);
423 gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
424 gtk_widget_destroy, GTK_OBJECT(gui_side->window));
426 gui_side->input_tag = gdk_input_add(gui_side->from_child,
427 GDK_INPUT_READ,
428 message_from_child,
429 gui_side);
431 return gui_side;
434 /* ACTIONS ON ONE ITEM */
436 /* These may call themselves recursively, or ask questions, etc.
437 * TRUE iff the directory containing dest_path needs to be rescanned.
440 /* dest_path is the dir containing src_path.
441 * Updates the global size_tally.
443 static gboolean do_usage(char *src_path, char *dest_path)
445 struct stat info;
447 if (lstat(src_path, &info))
449 g_string_sprintf(message, "'%s:\n", src_path);
450 send();
451 send_error();
452 return FALSE;
455 if (S_ISREG(info.st_mode) || S_ISLNK(info.st_mode))
456 size_tally += info.st_size;
457 else if (S_ISDIR(info.st_mode))
459 char *safe_path;
460 safe_path = g_strdup(src_path);
461 for_dir_contents(do_usage, safe_path, safe_path);
462 g_free(safe_path);
465 return FALSE;
468 /* dest_path is the dir containing src_path */
469 static gboolean do_delete(char *src_path, char *dest_path)
471 struct stat info;
472 gboolean write_prot;
473 char rep;
475 if (lstat(src_path, &info))
477 send_error();
478 return FALSE;
481 write_prot = S_ISLNK(info.st_mode) ? FALSE
482 : access(src_path, W_OK) != 0;
483 if (quiet == 0 || write_prot)
485 g_string_sprintf(message, "?Delete %s'%s'?\n",
486 write_prot ? "WRITE-PROTECTED " : " ",
487 src_path);
488 send();
489 rep = reply(from_parent);
490 if (rep == 'A')
491 quiet = TRUE;
492 else if (rep != 'Y')
493 return FALSE;
495 if (S_ISDIR(info.st_mode))
497 char *safe_path;
498 safe_path = g_strdup(src_path);
499 for_dir_contents(do_delete, safe_path, safe_path);
500 if (rmdir(safe_path))
502 g_free(safe_path);
503 send_error();
504 return FALSE;
506 g_string_assign(message, "'Directory deleted\n");
507 send();
508 g_free(safe_path);
510 else if (unlink(src_path) == 0)
512 g_string_sprintf(message, "'Deleted '%s'\n", src_path);
513 send();
515 else
517 send_error();
518 return FALSE;
521 return TRUE;
524 static gboolean do_copy(char *path, char *dest)
526 char *dest_path;
527 char *leaf;
528 struct stat info;
529 gboolean retval = TRUE;
531 leaf = strrchr(path, '/');
532 if (!leaf)
533 leaf = path; /* Error? */
534 else
535 leaf++;
537 dest_path = make_path(dest, leaf)->str;
539 g_string_sprintf(message, "'Copying %s as %s\n", path, dest_path);
540 send();
542 if (access(dest_path, F_OK) == 0)
544 char rep;
545 g_string_sprintf(message, "?'%s' already exists - overwrite?\n",
546 dest_path);
547 send();
549 rep = reply(from_parent);
550 if (rep == 'A')
551 quiet = TRUE;
552 else if (rep != 'Y')
553 return FALSE;
556 if (lstat(path, &info))
558 send_error();
559 return FALSE;
562 if (S_ISDIR(info.st_mode))
564 char *safe_path, *safe_dest;
565 struct stat dest_info;
566 gboolean exists;
568 /* (we will do the update ourselves now, rather than
569 * afterwards)
571 retval = FALSE;
573 safe_path = g_strdup(path);
574 safe_dest = g_strdup(dest_path);
576 exists = !lstat(dest_path, &dest_info);
578 if (exists && !S_ISDIR(dest_info.st_mode))
580 g_string_sprintf(message,
581 "!ERROR: Destination already exists, "
582 "but is not a directory\n");
584 else if (exists == FALSE && mkdir(dest_path, info.st_mode))
585 send_error();
586 else
588 if (!exists)
590 /* (just been created then) */
591 g_string_sprintf(message, "+%s", dest);
592 send();
595 for_dir_contents(do_copy, safe_path, safe_dest);
596 /* Note: dest_path now invalid... */
599 g_free(safe_path);
600 g_free(safe_dest);
602 else
604 g_string_sprintf(message, "cp -af %s %s", path, dest_path);
605 if (system(message->str))
607 g_string_sprintf(message, "!ERROR: %s\n",
608 "Copy failed\n");
609 send();
610 retval = FALSE;
614 return retval;
617 static gboolean do_move(char *path, char *dest)
619 char *dest_path;
620 char *leaf;
621 gboolean retval = TRUE;
623 leaf = strrchr(path, '/');
624 if (!leaf)
625 leaf = path; /* Error? */
626 else
627 leaf++;
629 dest_path = make_path(dest, leaf)->str;
631 g_string_sprintf(message, "'Moving %s into %s...\n", path, dest);
632 send();
634 if (access(dest_path, F_OK) == 0)
636 char rep;
637 struct stat info;
639 g_string_sprintf(message, "?'%s' already exists - overwrite?\n",
640 dest_path);
641 send();
643 rep = reply(from_parent);
644 if (rep == 'A')
645 quiet = TRUE;
646 else if (rep != 'Y')
647 return FALSE;
649 if (lstat(dest_path, &info))
651 send_error();
652 return FALSE;
655 if (S_ISDIR(info.st_mode))
657 char *safe_path, *safe_dest;
659 safe_path = g_strdup(path);
660 safe_dest = g_strdup(dest_path);
661 for_dir_contents(do_move, safe_path, safe_dest);
662 g_free(safe_dest);
663 if (rmdir(safe_path))
665 g_free(safe_path);
666 send_error();
667 return FALSE;
669 g_string_assign(message, "'Directory deleted\n");
670 send();
671 g_free(safe_path);
672 g_string_sprintf(message, "+%s", path);
673 g_string_truncate(message, leaf - path);
674 send();
675 return TRUE;
679 g_string_sprintf(message, "mv -f %s %s", path, dest);
680 if (system(message->str) == 0)
682 g_string_sprintf(message, "+%s", path);
683 g_string_truncate(message, leaf - path);
684 send();
686 else
688 g_string_sprintf(message, "!ERROR: Failed to move %s as %s\n",
689 path, dest_path);
690 retval = FALSE;
692 send();
694 return retval;
697 static gboolean do_link(char *path, char *dest)
699 char *dest_path;
700 char *leaf;
702 leaf = strrchr(path, '/');
703 if (!leaf)
704 leaf = path; /* Error? */
705 else
706 leaf++;
708 dest_path = make_path(dest, leaf)->str;
710 if (symlink(path, dest_path))
712 send_error();
713 return FALSE;
715 else
717 g_string_sprintf(message, "'Symlinked %s as %s\n",
718 path, dest_path);
719 send();
722 return TRUE;
725 /* Mount/umount this item */
726 static void do_mount(FilerWindow *filer_window, DirItem *item)
728 char *command;
729 char *path;
731 path = make_path(filer_window->path, item->leafname)->str;
733 command = g_strdup_printf("%smount %s",
734 item->flags & ITEM_FLAG_MOUNTED ? "u" : "", path);
735 g_string_sprintf(message, "'> %s\n", command);
736 send();
737 if (system(command) == 0)
739 g_string_sprintf(message, "+%s", filer_window->path);
740 send();
741 g_string_sprintf(message, "m%s", path);
742 send();
744 else
746 g_string_sprintf(message, "!Operation failed.\n");
747 send();
749 g_free(command);
752 /* CHILD MAIN LOOPS */
754 /* After forking, the child calls one of these functions */
756 static void usage_cb(gpointer data)
758 FilerWindow *filer_window = (FilerWindow *) data;
759 Collection *collection = filer_window->collection;
760 DirItem *item;
761 int left = collection->number_selected;
762 int i = -1;
763 off_t total_size = 0;
765 send_dir(filer_window->path);
767 while (left > 0)
769 i++;
770 if (!collection->items[i].selected)
771 continue;
772 item = (DirItem *) collection->items[i].data;
773 size_tally = 0;
774 do_usage(make_path(filer_window->path,
775 item->leafname)->str,
776 filer_window->path);
777 g_string_sprintf(message, "'%s: %s\n",
778 item->leafname,
779 format_size((unsigned long) size_tally));
780 send();
781 total_size += size_tally;
782 left--;
785 g_string_sprintf(message, "'\nTotal: %s\n",
786 format_size((unsigned long) total_size));
787 send();
790 #ifdef DO_MOUNT_POINTS
791 static void mount_cb(gpointer data)
793 FilerWindow *filer_window = (FilerWindow *) data;
794 Collection *collection = filer_window->collection;
795 DirItem *item;
796 int i;
797 gboolean mount_points = FALSE;
799 send_dir(filer_window->path);
801 if (mount_item)
802 do_mount(filer_window, mount_item);
803 else
805 for (i = 0; i < collection->number_of_items; i++)
807 if (!collection->items[i].selected)
808 continue;
809 item = (DirItem *) collection->items[i].data;
810 if (!(item->flags & ITEM_FLAG_MOUNT_POINT))
811 continue;
812 mount_points = TRUE;
814 do_mount(filer_window, item);
817 if (!mount_points)
819 g_string_sprintf(message,
820 "!No mount points selected!\n");
821 send();
825 g_string_sprintf(message, "'\nDone\n");
826 send();
828 #endif
830 static void delete_cb(gpointer data)
832 FilerWindow *filer_window = (FilerWindow *) data;
833 Collection *collection = filer_window->collection;
834 DirItem *item;
835 int left = collection->number_selected;
836 int i = -1;
838 send_dir(filer_window->path);
840 while (left > 0)
842 i++;
843 if (!collection->items[i].selected)
844 continue;
845 item = (DirItem *) collection->items[i].data;
846 if (do_delete(make_path(filer_window->path,
847 item->leafname)->str,
848 filer_window->path))
850 g_string_sprintf(message, "+%s", filer_window->path);
851 send();
853 left--;
856 g_string_sprintf(message, "'\nDone\n");
857 send();
860 static void list_cb(gpointer data)
862 GSList *paths = (GSList *) data;
864 while (paths)
866 send_dir((char *) paths->data);
868 if (action_do_func((char *) paths->data, action_dest))
870 g_string_sprintf(message, "+%s", action_dest);
871 send();
874 paths = paths->next;
877 g_string_sprintf(message, "'\nDone\n");
878 send();
881 /* EXTERNAL INTERFACE */
883 /* Count disk space used by selected items */
884 void action_usage(FilerWindow *filer_window)
886 GUIside *gui_side;
887 Collection *collection;
889 collection = filer_window->collection;
891 if (collection->number_selected < 1)
893 report_error("ROX-Filer", "You need to select some items "
894 "to count");
895 return;
898 gui_side = start_action(filer_window, usage_cb);
899 if (!gui_side)
900 return;
902 gui_side->show_info = TRUE;
904 gtk_window_set_title(GTK_WINDOW(gui_side->window), "Disk Usage");
905 number_of_windows++;
906 gtk_widget_show_all(gui_side->window);
909 /* Mount/unmount 'item', or all selected mount points if NULL. */
910 void action_mount(FilerWindow *filer_window, DirItem *item)
912 #ifdef DO_MOUNT_POINTS
913 GUIside *gui_side;
914 Collection *collection;
916 collection = filer_window->collection;
918 if (item == NULL && collection->number_selected < 1)
920 report_error("ROX-Filer", "You need to select some items "
921 "to mount or unmount");
922 return;
925 mount_item = item;
926 gui_side = start_action(filer_window, mount_cb);
927 if (!gui_side)
928 return;
930 gtk_window_set_title(GTK_WINDOW(gui_side->window), "Mount / Unmount");
931 number_of_windows++;
932 gtk_widget_show_all(gui_side->window);
933 #else
934 report_error("ROX-Filer",
935 "ROX-Filer does not yet support mount points on your "
936 "system. Sorry.");
937 #endif /* DO_MOUNT_POINTS */
940 /* Deletes all selected items in the window */
941 void action_delete(FilerWindow *filer_window)
943 GUIside *gui_side;
944 Collection *collection;
946 collection = filer_window->collection;
948 if (collection->number_selected < 1)
950 report_error("ROX-Filer", "You need to select some items "
951 "to delete");
952 return;
955 gui_side = start_action(filer_window, delete_cb);
956 if (!gui_side)
957 return;
959 gtk_window_set_title(GTK_WINDOW(gui_side->window), "Delete");
960 number_of_windows++;
961 gtk_widget_show_all(gui_side->window);
964 void action_copy(GSList *paths, char *dest)
966 GUIside *gui_side;
968 action_dest = dest;
969 action_do_func = do_copy;
970 gui_side = start_action(paths, list_cb);
971 if (!gui_side)
972 return;
974 gtk_window_set_title(GTK_WINDOW(gui_side->window), "Copy");
975 number_of_windows++;
976 gtk_widget_show_all(gui_side->window);
979 void action_move(GSList *paths, char *dest)
981 GUIside *gui_side;
983 action_dest = dest;
984 action_do_func = do_move;
985 gui_side = start_action(paths, list_cb);
986 if (!gui_side)
987 return;
989 gtk_window_set_title(GTK_WINDOW(gui_side->window), "Move");
990 number_of_windows++;
991 gtk_widget_show_all(gui_side->window);
994 void action_link(GSList *paths, char *dest)
996 GUIside *gui_side;
998 action_dest = dest;
999 action_do_func = do_link;
1000 gui_side = start_action(paths, list_cb);
1001 if (!gui_side)
1002 return;
1004 gtk_window_set_title(GTK_WINDOW(gui_side->window), "Link");
1005 number_of_windows++;
1006 gtk_widget_show_all(gui_side->window);