r68: Added full Adjust actions for files/dirs/apps for windows and panels.
[rox-filer.git] / ROX-Filer / src / menu.c
blobaeb75c23a5bb31130db2ec76372b9850f3e1eee8
1 /* vi: set cindent:
2 * $Id$
4 * ROX-Filer, filer for the ROX desktop project
5 * By Thomas Leonard, <tal197@ecs.soton.ac.uk>.
6 */
8 /* menu.c - code for handling the popup menu */
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <sys/stat.h>
13 #include <sys/types.h>
14 #include <sys/wait.h>
15 #include <fcntl.h>
16 #include <unistd.h>
17 #include <errno.h>
18 #include <string.h>
20 #include <gdk/gdkx.h>
21 #include <gtk/gtk.h>
23 #include "apps.h"
24 #include "action.h"
25 #include "filer.h"
26 #include "type.h"
27 #include "support.h"
28 #include "gui_support.h"
29 #include "options.h"
30 #include "choices.h"
31 #include "savebox.h"
33 #define C_ "<control>"
35 #define MENU_MARGIN 32
37 GtkAccelGroup *filer_keys;
38 GtkAccelGroup *panel_keys;
40 /* Options */
41 static GtkWidget *xterm_here_entry;
42 static char *xterm_here_value;
44 /* Static prototypes */
45 static void position_menu(GtkMenu *menu, gint *x, gint *y, gpointer data);
46 static void menu_closed(GtkWidget *widget);
47 static void items_sensitive(GtkWidget *menu, int from, int n, gboolean state);
48 static char *load_xterm_here(char *data);
50 static void hidden(gpointer data, guint action, GtkWidget *widget);
51 static void refresh(gpointer data, guint action, GtkWidget *widget);
53 static void copy_item(gpointer data, guint action, GtkWidget *widget);
54 static void rename_item(gpointer data, guint action, GtkWidget *widget);
55 static void link_item(gpointer data, guint action, GtkWidget *widget);
56 static void help(gpointer data, guint action, GtkWidget *widget);
57 static void show_file_info(gpointer data, guint action, GtkWidget *widget);
58 static void mount(gpointer data, guint action, GtkWidget *widget);
59 static void delete(gpointer data, guint action, GtkWidget *widget);
61 static void select_all(gpointer data, guint action, GtkWidget *widget);
62 static void clear_selection(gpointer data, guint action, GtkWidget *widget);
63 static void show_options(gpointer data, guint action, GtkWidget *widget);
64 static void new_directory(gpointer data, guint action, GtkWidget *widget);
65 static void xterm_here(gpointer data, guint action, GtkWidget *widget);
66 static void open_parent(gpointer data, guint action, GtkWidget *widget);
68 static void open_as_dir(gpointer data, guint action, GtkWidget *widget);
69 static void close_panel(gpointer data, guint action, GtkWidget *widget);
71 static GtkWidget *filer_menu; /* The popup filer menu */
72 static GtkWidget *filer_file_item; /* The File '' label */
73 static GtkWidget *filer_file_menu; /* The File '' menu */
74 static GtkWidget *panel_menu; /* The popup panel menu */
75 static GtkWidget *panel_file_item; /* The File '' label */
76 static GtkWidget *panel_file_menu; /* The File '' menu */
78 static GtkItemFactoryEntry filer_menu_def[] = {
79 {"/Display", NULL, NULL, 0, "<Branch>"},
80 {"/Display/Large Icons", NULL, NULL, 0, "<RadioItem>"},
81 {"/Display/Small Icons", NULL, NULL, 0, "/Display/Large Icons"},
82 {"/Display/Full Info", NULL, NULL, 0, "/Display/Large Icons"},
83 {"/Display/Separator", NULL, NULL, 0, "<Separator>"},
84 {"/Display/Sort by Name", NULL, NULL, 0, "<RadioItem>"},
85 {"/Display/Sort by Type", NULL, NULL, 0, "/Display/Sort by Name"},
86 {"/Display/Sort by Date", NULL, NULL, 0, "/Display/Sort by Name"},
87 {"/Display/Sort by Size", NULL, NULL, 0, "/Display/Sort by Name"},
88 {"/Display/Sort by Owner", NULL, NULL, 0, "/Display/Sort by Name"},
89 {"/Display/Separator", NULL, NULL, 0, "<Separator>"},
90 {"/Display/Show Hidden", C_"H", hidden, 0, "<ToggleItem>"},
91 {"/Display/Refresh", C_"L", refresh, 0, NULL},
92 {"/File", NULL, NULL, 0, "<Branch>"},
93 {"/File/Copy...", NULL, copy_item, 0, NULL},
94 {"/File/Rename...", NULL, rename_item, 0, NULL},
95 {"/File/Link...", NULL, link_item, 0, NULL},
96 {"/File/Help", "F1", help, 0, NULL},
97 {"/File/Info", "I", show_file_info, 0, NULL},
98 {"/File/Separator", NULL, NULL, 0, "<Separator>"},
99 {"/File/Mount", C_"M", mount, 0, NULL},
100 {"/File/Delete", C_"X", delete, 0, NULL},
101 {"/File/Disk Usage", C_"U", NULL, 0, NULL},
102 {"/File/Permissions", NULL, NULL, 0, NULL},
103 {"/File/Touch", NULL, NULL, 0, NULL},
104 {"/File/Find", NULL, NULL, 0, NULL},
105 {"/Select All", C_"A", select_all, 0, NULL},
106 {"/Clear Selection", C_"Z", clear_selection, 0, NULL},
107 {"/Options...", NULL, show_options, 0, NULL},
108 {"/New directory", NULL, new_directory, 0, NULL},
109 {"/Xterm here", NULL, xterm_here, 0, NULL},
110 {"/Open parent", NULL, open_parent, 0, NULL},
113 static GtkItemFactoryEntry panel_menu_def[] = {
114 {"/Display", NULL, NULL, 0, "<Branch>"},
115 {"/Display/Large Icons", NULL, NULL, 0, "<RadioItem>"},
116 {"/Display/Small Icons", NULL, NULL, 0, "/Display/Large Icons"},
117 {"/Display/Full Info", NULL, NULL, 0, "/Display/Large Icons"},
118 {"/Display/Separator", NULL, NULL, 0, "<Separator>"},
119 {"/Display/Sort by Name", NULL, NULL, 0, "<RadioItem>"},
120 {"/Display/Sort by Type", NULL, NULL, 0, "/Display/Sort by Name"},
121 {"/Display/Sort by Date", NULL, NULL, 0, "/Display/Sort by Name"},
122 {"/Display/Sort by Size", NULL, NULL, 0, "/Display/Sort by Name"},
123 {"/Display/Sort by Owner", NULL, NULL, 0, "/Display/Sort by Name"},
124 {"/Display/Separator", NULL, NULL, 0, "<Separator>"},
125 {"/Display/Show Hidden", NULL, hidden, 0, "<ToggleItem>"},
126 {"/Display/Refresh", NULL, refresh, 0, NULL},
127 {"/File", NULL, NULL, 0, "<Branch>"},
128 {"/File/Help", NULL, help, 0, NULL},
129 {"/File/Info", NULL, show_file_info, 0, NULL},
130 {"/File/Delete", NULL, delete, 0, NULL},
131 {"/Open as directory", NULL, open_as_dir, 0, NULL},
132 {"/Close panel", NULL, close_panel, 0, NULL},
135 void menu_init()
137 GtkItemFactory *item_factory;
138 char *menurc;
139 GList *items;
141 filer_keys = gtk_accel_group_new();
142 item_factory = gtk_item_factory_new(GTK_TYPE_MENU,
143 "<filer>",
144 filer_keys);
145 gtk_item_factory_create_items(item_factory,
146 sizeof(filer_menu_def) / sizeof(*filer_menu_def),
147 filer_menu_def,
148 NULL);
149 filer_menu = gtk_item_factory_get_widget(item_factory, "<filer>");
150 filer_file_menu = gtk_item_factory_get_widget(item_factory,
151 "<filer>/File");
152 items = gtk_container_children(GTK_CONTAINER(filer_menu));
153 filer_file_item = GTK_BIN(g_list_nth(items, 1)->data)->child;
154 g_list_free(items);
156 panel_keys = gtk_accel_group_new();
157 item_factory = gtk_item_factory_new(GTK_TYPE_MENU,
158 "<panel>",
159 panel_keys);
160 gtk_item_factory_create_items(item_factory,
161 sizeof(panel_menu_def) / sizeof(*panel_menu_def),
162 panel_menu_def,
163 NULL);
164 panel_menu = gtk_item_factory_get_widget(item_factory, "<panel>");
165 panel_file_menu = gtk_item_factory_get_widget(item_factory,
166 "<panel>/File");
167 items = gtk_container_children(GTK_CONTAINER(panel_menu));
168 panel_file_item = GTK_BIN(g_list_nth(items, 1)->data)->child;
169 g_list_free(items);
171 menurc = choices_find_path_load("menus");
172 if (menurc)
173 gtk_item_factory_parse_rc(menurc);
175 gtk_signal_connect(GTK_OBJECT(panel_menu), "unmap_event",
176 GTK_SIGNAL_FUNC(menu_closed), NULL);
177 gtk_signal_connect(GTK_OBJECT(filer_menu), "unmap_event",
178 GTK_SIGNAL_FUNC(menu_closed), NULL);
180 gtk_accel_group_lock(panel_keys);
182 xterm_here_value = g_strdup("xterm");
183 option_register("xterm_here", load_xterm_here);
186 /* Build up some option widgets to go in the options dialog, but don't
187 * fill them in yet.
189 GtkWidget *create_menu_options()
191 GtkWidget *table, *label;
193 table = gtk_table_new(2, 2, FALSE);
194 gtk_container_set_border_width(GTK_CONTAINER(table), 4);
196 label = gtk_label_new("To set the keyboard short-cuts you simply open "
197 "the menu over a filer window, move the pointer over "
198 "the item you want to use and press a key. The key "
199 "will appear next to the menu item and you can just "
200 "press that key without opening the menu in future. "
201 "To save the current menu short-cuts for next time, "
202 "click the Save button at the bottom of this window.");
203 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
204 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 2, 0, 1);
206 label = gtk_label_new("'Xterm here' program:");
207 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2);
208 xterm_here_entry = gtk_entry_new();
209 gtk_table_attach_defaults(GTK_TABLE(table), xterm_here_entry,
210 1, 2, 1, 2);
212 return table;
215 static char *load_xterm_here(char *data)
217 g_free(xterm_here_value);
218 xterm_here_value = g_strdup(data);
219 return NULL;
222 void menu_update_options()
224 gtk_entry_set_text(GTK_ENTRY(xterm_here_entry), xterm_here_value);
227 void menu_set_options()
229 g_free(xterm_here_value);
230 xterm_here_value = g_strdup(gtk_entry_get_text(
231 GTK_ENTRY(xterm_here_entry)));
234 void menu_save_options()
236 char *menurc;
238 menurc = choices_find_path_save("menus");
239 if (menurc)
240 gtk_item_factory_dump_rc(menurc, NULL, TRUE);
242 option_write("xterm_here", xterm_here_value);
246 static void items_sensitive(GtkWidget *menu, int from, int n, gboolean state)
248 GList *items, *item;
250 items = gtk_container_children(GTK_CONTAINER(menu));
252 item = g_list_nth(items, from);
253 while (item && n--)
255 gtk_widget_set_sensitive(GTK_BIN(item->data)->child, state);
256 item = item->next;
259 g_list_free(items);
262 static void position_menu(GtkMenu *menu, gint *x, gint *y, gpointer data)
264 int *pos = (int *) data;
265 int swidth, sheight;
266 GtkRequisition requisition;
268 gdk_window_get_size(GDK_ROOT_PARENT(), &swidth, &sheight);
269 /* XXX: GDK sometimes seems to get the height wrong... */
270 if (sheight < 2)
272 g_print("ROX-Filer: Root window height reported as %d\n",
273 sheight);
274 sheight = 768;
277 gtk_widget_size_request(GTK_WIDGET(menu), &requisition);
279 if (pos[0] == -1)
280 *x = swidth - MENU_MARGIN - requisition.width;
281 else if (pos[0] == -2)
282 *x = MENU_MARGIN;
283 else
284 *x = pos[0] - (requisition.width >> 2);
286 if (pos[1] == -1)
287 *y = sheight - MENU_MARGIN - requisition.height;
288 else if (pos[1] == -2)
289 *y = MENU_MARGIN;
290 else
291 *y = pos[1] - (requisition.height >> 2);
293 *x = CLAMP(*x, 0, swidth - requisition.width);
294 *y = CLAMP(*y, 0, sheight - requisition.height);
297 void show_filer_menu(FilerWindow *filer_window, GdkEventButton *event,
298 int item)
300 GString *buffer;
301 GtkWidget *file_label, *file_menu;
302 FileItem *file_item;
303 int pos[] = {event->x_root, event->y_root};
305 window_with_focus = filer_window;
307 if (filer_window->panel)
309 switch (filer_window->panel_side)
311 case TOP: pos[1] = -2; break;
312 case BOTTOM: pos[1] = -1; break;
313 case LEFT: pos[0] = -2; break;
314 case RIGHT: pos[0] = -1; break;
318 if (filer_window->panel)
320 collection_clear_selection(filer_window->collection);
321 panel_set_timeout(NULL, 0);
324 if (filer_window->collection->number_selected == 0 && item >= 0)
326 collection_select_item(filer_window->collection, item);
327 filer_window->temp_item_selected = TRUE;
329 else
330 filer_window->temp_item_selected = FALSE;
332 if (filer_window->panel)
334 file_label = panel_file_item;
335 file_menu = panel_file_menu;
337 else
339 file_label = filer_file_item;
340 file_menu = filer_file_menu;
343 buffer = g_string_new(NULL);
344 switch (filer_window->collection->number_selected)
346 case 0:
347 g_string_assign(buffer, "<nothing selected>");
348 items_sensitive(file_menu, 0, 5, FALSE);
349 items_sensitive(file_menu, 6, -1, FALSE);
350 gtk_widget_set_sensitive(file_label, FALSE);
351 break;
352 case 1:
353 items_sensitive(file_menu, 0, 5, TRUE);
354 items_sensitive(file_menu, 6, -1, TRUE);
355 gtk_widget_set_sensitive(file_label, TRUE);
356 file_item = selected_item(filer_window->collection);
357 g_string_sprintf(buffer, "%s '%s'",
358 basetype_name(file_item),
359 file_item->leafname);
360 break;
361 default:
362 items_sensitive(file_menu, 0, 5, FALSE);
363 items_sensitive(file_menu, 6, -1, TRUE);
364 gtk_widget_set_sensitive(file_label, TRUE);
365 g_string_sprintf(buffer, "%d items",
366 filer_window->collection->number_selected);
367 break;
370 gtk_label_set_text(GTK_LABEL(file_label), buffer->str);
372 g_string_free(buffer, TRUE);
374 gtk_menu_popup(filer_window->panel ? GTK_MENU(panel_menu)
375 : GTK_MENU(filer_menu),
376 NULL, NULL, position_menu,
377 (gpointer) pos, event->button, event->time);
380 static void menu_closed(GtkWidget *widget)
382 if (window_with_focus == NULL)
383 return; /* Close panel item chosen? */
385 if (window_with_focus->temp_item_selected)
387 collection_clear_selection(window_with_focus->collection);
388 window_with_focus->temp_item_selected = FALSE;
392 /* Actions */
394 static void hidden(gpointer data, guint action, GtkWidget *widget)
396 g_return_if_fail(window_with_focus != NULL);
398 window_with_focus->show_hidden = !window_with_focus->show_hidden;
399 scan_dir(window_with_focus);
402 static void refresh(gpointer data, guint action, GtkWidget *widget)
404 g_return_if_fail(window_with_focus != NULL);
406 scan_dir(window_with_focus);
409 static void delete(gpointer data, guint action, GtkWidget *widget)
411 g_return_if_fail(window_with_focus != NULL);
413 action_delete(window_with_focus);
416 static gboolean copy_cb(char *initial, char *path)
418 char *new_dir, *slash;
419 int len;
420 GString *command;
421 gboolean retval = TRUE;
423 slash = strrchr(path, '/');
424 if (!slash)
426 report_error("ROX-Filer", "Missing '/' in new pathname");
427 return FALSE;
430 if (access(path, F_OK) == 0)
432 report_error("ROX-Filer",
433 "An item with this name already exists");
434 return FALSE;
437 len = slash - path;
438 new_dir = g_malloc(len + 1);
439 memcpy(new_dir, path, len);
440 new_dir[len] = '\0';
442 command = g_string_new(NULL);
443 g_string_sprintf(command, "cp -a %s %s", initial, path);
445 if (system(command->str))
447 g_string_append(command, " failed!");
448 report_error("ROX-Filer", command->str);
449 retval = FALSE;
452 g_string_free(command, TRUE);
454 refresh_dirs(new_dir);
455 return retval;
458 static void copy_item(gpointer data, guint action, GtkWidget *widget)
460 Collection *collection;
462 g_return_if_fail(window_with_focus != NULL);
464 collection = window_with_focus->collection;
465 if (collection->number_selected != 1)
466 report_error("ROX-Filer", "You must select a single "
467 "item to copy");
468 else
470 FileItem *item = selected_item(collection);
472 savebox_show(window_with_focus, "Copy",
473 window_with_focus->path, item->leafname,
474 item->image, copy_cb);
478 static gboolean rename_cb(char *initial, char *path)
480 if (rename(initial, path))
482 report_error("ROX-Filer: rename()", g_strerror(errno));
483 return FALSE;
485 return TRUE;
488 static void rename_item(gpointer data, guint action, GtkWidget *widget)
490 Collection *collection;
492 g_return_if_fail(window_with_focus != NULL);
494 collection = window_with_focus->collection;
495 if (collection->number_selected != 1)
496 report_error("ROX-Filer", "You must select a single "
497 "item to rename");
498 else
500 FileItem *item = selected_item(collection);
502 savebox_show(window_with_focus, "Rename",
503 window_with_focus->path, item->leafname,
504 item->image, rename_cb);
508 static gboolean link_cb(char *initial, char *path)
510 if (symlink(initial, path))
512 report_error("ROX-Filer: symlink()", g_strerror(errno));
513 return FALSE;
515 return TRUE;
518 static void link_item(gpointer data, guint action, GtkWidget *widget)
520 Collection *collection;
522 g_return_if_fail(window_with_focus != NULL);
524 collection = window_with_focus->collection;
525 if (collection->number_selected != 1)
526 report_error("ROX-Filer", "You must select a single "
527 "item to link");
528 else
530 FileItem *item = selected_item(collection);
532 savebox_show(window_with_focus, "Symlink",
533 window_with_focus->path, item->leafname,
534 item->image, link_cb);
538 static void show_file_info(gpointer data, guint action, GtkWidget *widget)
540 GtkWidget *window, *table, *label, *button, *frame;
541 GtkWidget *file_label;
542 GString *gstring;
543 char *string;
544 int file_data[2];
545 char *path;
546 char buffer[20];
547 char *argv[] = {"file", "-b", NULL, NULL};
548 int got;
549 Collection *collection;
550 FileItem *file;
551 struct stat info;
553 g_return_if_fail(window_with_focus != NULL);
555 collection = window_with_focus->collection;
556 if (collection->number_selected != 1)
558 report_error("ROX-Filer", "You must select a single "
559 "item before using Info");
560 return;
562 file = selected_item(collection);
563 path = make_path(window_with_focus->path, file->leafname)->str;
564 if (lstat(path, &info))
566 delayed_error("ROX-Filer", g_strerror(errno));
567 return;
570 gstring = g_string_new(NULL);
572 window = gtk_window_new(GTK_WINDOW_DIALOG);
573 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_MOUSE);
574 gtk_container_set_border_width(GTK_CONTAINER(window), 4);
575 gtk_window_set_title(GTK_WINDOW(window), path);
577 table = gtk_table_new(4, 2, FALSE);
578 gtk_container_add(GTK_CONTAINER(window), table);
579 gtk_table_set_row_spacings(GTK_TABLE(table), 8);
580 gtk_table_set_col_spacings(GTK_TABLE(table), 4);
582 label = gtk_label_new("Owner, group:");
583 gtk_misc_set_alignment(GTK_MISC(label), 1, .5);
584 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_RIGHT);
585 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
586 g_string_sprintf(gstring, "%s, %s", user_name(info.st_uid),
587 group_name(info.st_gid));
588 label = gtk_label_new(gstring->str);
589 gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 2, 0, 1);
591 label = gtk_label_new("Permissions:");
592 gtk_misc_set_alignment(GTK_MISC(label), 1, .5);
593 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2);
594 g_string_sprintf(gstring, "%o", info.st_mode);
595 label = gtk_label_new(gstring->str);
596 gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 2, 1, 2);
598 label = gtk_label_new("MIME type:");
599 gtk_misc_set_alignment(GTK_MISC(label), 1, .5);
600 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3);
601 if (file->base_type == TYPE_FILE &&
602 !(file->flags & ITEM_FLAG_EXEC_FILE))
604 string = g_strconcat(file->mime_type->media_type, "/",
605 file->mime_type->subtype, NULL);
606 label = gtk_label_new(string);
607 g_free(string);
609 else
610 label = gtk_label_new("-");
611 gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 2, 2, 3);
613 frame = gtk_frame_new("file(1) says...");
614 gtk_table_attach_defaults(GTK_TABLE(table), frame, 0, 2, 3, 4);
615 file_label = gtk_label_new("<nothing yet>");
616 gtk_misc_set_padding(GTK_MISC(file_label), 4, 4);
617 gtk_label_set_line_wrap(GTK_LABEL(file_label), TRUE);
618 gtk_container_add(GTK_CONTAINER(frame), file_label);
620 button = gtk_button_new_with_label("OK");
621 gtk_table_attach(GTK_TABLE(table), button, 0, 2, 4, 5,
622 GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 40, 4);
623 gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
624 gtk_widget_destroy, GTK_OBJECT(window));
626 gtk_widget_show_all(window);
627 gdk_flush();
629 pipe(file_data);
630 switch (fork())
632 case -1:
633 close(file_data[0]);
634 close(file_data[1]);
635 gtk_label_set_text(GTK_LABEL(file_label),
636 "fork() error");
637 g_string_free(gstring, TRUE);
638 return;
639 case 0:
640 close(file_data[0]);
641 dup2(file_data[1], STDOUT_FILENO);
642 dup2(file_data[1], STDERR_FILENO);
643 argv[2] = path;
644 if (execvp(argv[0], argv))
645 fprintf(stderr, "execvp() error: %s\n",
646 g_strerror(errno));
647 _exit(0);
649 /* We are the parent... */
650 close(file_data[1]);
651 g_string_truncate(gstring, 0);
652 while (gtk_events_pending())
653 g_main_iteration(FALSE);
654 while ((got = read(file_data[0], buffer, sizeof(buffer) - 1)))
656 buffer[got] = '\0';
657 g_string_append(gstring, buffer);
659 close(file_data[0]);
660 gtk_label_set_text(GTK_LABEL(file_label), gstring->str);
661 g_string_free(gstring, TRUE);
664 static void help(gpointer data, guint action, GtkWidget *widget)
666 Collection *collection;
667 FileItem *item;
669 g_return_if_fail(window_with_focus != NULL);
671 collection = window_with_focus->collection;
672 if (collection->number_selected != 1)
674 report_error("ROX-Filer", "You must select a single "
675 "item to get help on");
676 return;
678 item = selected_item(collection);
679 switch (item->base_type)
681 case TYPE_FILE:
682 if (item->flags & ITEM_FLAG_EXEC_FILE)
683 report_error("Executable file",
684 "This is a file with an eXecute bit "
685 "set - it can be run as a program.");
686 else
687 report_error("File",
688 "This is a data file. Try using the "
689 "Info menu item to find out more...");
690 break;
691 case TYPE_DIRECTORY:
692 if (item->flags & ITEM_FLAG_APPDIR)
693 app_show_help(
694 make_path(window_with_focus->path,
695 item->leafname)->str);
696 else if (item->flags & ITEM_FLAG_MOUNT_POINT)
697 report_error("Mount point",
698 "A mount point is a directory which another "
699 "filing system can be mounted on. Everything "
700 "on the mounted filesystem then appears to be "
701 "inside the directory.");
702 else
703 report_error("Directory",
704 "This is a directory. It contains an index to "
705 "other items - open it to see the list.");
706 break;
707 case TYPE_CHAR_DEVICE:
708 case TYPE_BLOCK_DEVICE:
709 report_error("Device file",
710 "Device files allow you to read from or write "
711 "to a device driver as though it was an "
712 "ordinary file.");
713 break;
714 case TYPE_PIPE:
715 report_error("Named pipe",
716 "Pipes allow different programs to "
717 "communicate. One program writes data to the "
718 "pipe while another one reads it out again.");
719 break;
720 case TYPE_SOCKET:
721 report_error("Socket",
722 "Sockets allow processes to communicate.");
723 break;
724 default:
725 report_error("Unknown type",
726 "I couldn't find out what kind of file this "
727 "is. Maybe it doesn't exist anymore or you "
728 "don't have search permission on the directory "
729 "it's in?");
730 break;
734 static void mount(gpointer data, guint action, GtkWidget *widget)
736 FileItem *item;
737 int i;
738 Collection *collection;
739 char *error = NULL;
740 int count = 0;
742 g_return_if_fail(window_with_focus != NULL);
744 collection = window_with_focus->collection;
746 for (i = 0; i < collection->number_of_items; i++)
747 if (collection->items[i].selected)
749 item = (FileItem *) collection->items[i].data;
750 if (item->flags & ITEM_FLAG_MOUNT_POINT)
752 char *argv[] = {"mount", NULL, NULL};
753 int child;
755 count++;
756 if (item->flags & ITEM_FLAG_MOUNTED)
757 argv[0] = "umount";
758 argv[1] = make_path(window_with_focus->path,
759 item->leafname)->str;
760 child = spawn(argv);
761 if (child)
762 waitpid(child, NULL, 0);
763 else
764 error = "Failed to run mount/umount";
767 if (count)
768 scan_dir(window_with_focus);
769 else if (!error)
770 error = "You must select some mount points first!";
772 if (error)
773 report_error("ROX-Filer", error);
776 static void select_all(gpointer data, guint action, GtkWidget *widget)
778 g_return_if_fail(window_with_focus != NULL);
780 collection_select_all(window_with_focus->collection);
781 window_with_focus->temp_item_selected = FALSE;
784 static void clear_selection(gpointer data, guint action, GtkWidget *widget)
786 g_return_if_fail(window_with_focus != NULL);
788 collection_clear_selection(window_with_focus->collection);
789 window_with_focus->temp_item_selected = FALSE;
792 static void show_options(gpointer data, guint action, GtkWidget *widget)
794 g_return_if_fail(window_with_focus != NULL);
796 options_show(window_with_focus);
799 static gboolean new_directory_cb(char *initial, char *path)
801 if (mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO))
803 report_error("mkdir", g_strerror(errno));
804 return FALSE;
806 return TRUE;
809 static void new_directory(gpointer data, guint action, GtkWidget *widget)
811 g_return_if_fail(window_with_focus != NULL);
813 savebox_show(window_with_focus, "Create directory",
814 window_with_focus->path, "NewDir",
815 default_pixmap + TYPE_DIRECTORY, new_directory_cb);
818 static void xterm_here(gpointer data, guint action, GtkWidget *widget)
820 char *argv[] = {xterm_here_value, NULL};
822 g_return_if_fail(window_with_focus != NULL);
824 if (!spawn_full(argv, window_with_focus->path, 0))
825 report_error("ROX-Filer", "Failed to fork() child "
826 "process");
829 static void open_parent(gpointer data, guint action, GtkWidget *widget)
831 g_return_if_fail(window_with_focus != NULL);
833 filer_opendir(make_path(window_with_focus->path, "/..")->str,
834 FALSE, BOTTOM);
837 static void open_as_dir(gpointer data, guint action, GtkWidget *widget)
839 g_return_if_fail(window_with_focus != NULL);
841 filer_opendir(window_with_focus->path, FALSE, BOTTOM);
844 static void close_panel(gpointer data, guint action, GtkWidget *widget)
846 g_return_if_fail(window_with_focus != NULL);
848 gtk_widget_destroy(window_with_focus->window);