4 * ROX-Filer, filer for the ROX desktop project
5 * By Thomas Leonard, <tal197@ecs.soton.ac.uk>.
8 /* menu.c - code for handling the popup menu */
13 #include <sys/types.h>
29 #include "gui_support.h"
34 #define C_ "<control>"
36 #define MENU_MARGIN 32
38 GtkAccelGroup
*filer_keys
;
39 GtkAccelGroup
*panel_keys
;
42 static GtkWidget
*xterm_here_entry
;
43 static char *xterm_here_value
;
45 /* Static prototypes */
46 static void position_menu(GtkMenu
*menu
, gint
*x
, gint
*y
, gpointer data
);
47 static void menu_closed(GtkWidget
*widget
);
48 static void items_sensitive(GtkWidget
*menu
, int from
, int n
, gboolean state
);
49 static char *load_xterm_here(char *data
);
51 static void not_yet(gpointer data
, guint action
, GtkWidget
*widget
);
53 static void hidden(gpointer data
, guint action
, GtkWidget
*widget
);
54 static void refresh(gpointer data
, guint action
, GtkWidget
*widget
);
56 static void copy_item(gpointer data
, guint action
, GtkWidget
*widget
);
57 static void rename_item(gpointer data
, guint action
, GtkWidget
*widget
);
58 static void link_item(gpointer data
, guint action
, GtkWidget
*widget
);
59 static void help(gpointer data
, guint action
, GtkWidget
*widget
);
60 static void show_file_info(gpointer data
, guint action
, GtkWidget
*widget
);
61 static void mount(gpointer data
, guint action
, GtkWidget
*widget
);
62 static void delete(gpointer data
, guint action
, GtkWidget
*widget
);
64 static void select_all(gpointer data
, guint action
, GtkWidget
*widget
);
65 static void clear_selection(gpointer data
, guint action
, GtkWidget
*widget
);
66 static void show_options(gpointer data
, guint action
, GtkWidget
*widget
);
67 static void new_directory(gpointer data
, guint action
, GtkWidget
*widget
);
68 static void xterm_here(gpointer data
, guint action
, GtkWidget
*widget
);
69 static void open_parent(gpointer data
, guint action
, GtkWidget
*widget
);
71 static void open_as_dir(gpointer data
, guint action
, GtkWidget
*widget
);
72 static void close_panel(gpointer data
, guint action
, GtkWidget
*widget
);
74 static GtkWidget
*create_options();
75 static void update_options();
76 static void set_options();
77 static void save_options();
79 static OptionsSection options
=
89 static GtkWidget
*filer_menu
; /* The popup filer menu */
90 static GtkWidget
*filer_file_item
; /* The File '' label */
91 static GtkWidget
*filer_file_menu
; /* The File '' menu */
92 static GtkWidget
*panel_menu
; /* The popup panel menu */
93 static GtkWidget
*panel_file_item
; /* The File '' label */
94 static GtkWidget
*panel_file_menu
; /* The File '' menu */
96 static gint screen_width
, screen_height
;
98 static GtkItemFactoryEntry filer_menu_def
[] = {
99 {"/Display", NULL
, NULL
, 0, "<Branch>"},
100 {"/Display/Large Icons", NULL
, not_yet
, 0, "<RadioItem>"},
101 {"/Display/Small Icons", NULL
, not_yet
, 0, "/Display/Large Icons"},
102 {"/Display/Full Info", NULL
, not_yet
, 0, "/Display/Large Icons"},
103 {"/Display/Separator", NULL
, not_yet
, 0, "<Separator>"},
104 {"/Display/Sort by Name", NULL
, not_yet
, 0, "<RadioItem>"},
105 {"/Display/Sort by Type", NULL
, not_yet
, 0, "/Display/Sort by Name"},
106 {"/Display/Sort by Date", NULL
, not_yet
, 0, "/Display/Sort by Name"},
107 {"/Display/Sort by Size", NULL
, not_yet
, 0, "/Display/Sort by Name"},
108 {"/Display/Sort by Owner", NULL
, not_yet
, 0, "/Display/Sort by Name"},
109 {"/Display/Separator", NULL
, NULL
, 0, "<Separator>"},
110 {"/Display/Show Hidden", C_
"H", hidden
, 0, "<ToggleItem>"},
111 {"/Display/Refresh", C_
"L", refresh
, 0, NULL
},
112 {"/File", NULL
, NULL
, 0, "<Branch>"},
113 {"/File/Copy...", NULL
, copy_item
, 0, NULL
},
114 {"/File/Rename...", NULL
, rename_item
, 0, NULL
},
115 {"/File/Link...", NULL
, link_item
, 0, NULL
},
116 {"/File/Help", "F1", help
, 0, NULL
},
117 {"/File/Info", "I", show_file_info
, 0, NULL
},
118 {"/File/Separator", NULL
, NULL
, 0, "<Separator>"},
119 {"/File/Mount", "M", mount
, 0, NULL
},
120 {"/File/Delete", C_
"X", delete, 0, NULL
},
121 {"/File/Disk Usage", C_
"U", not_yet
, 0, NULL
},
122 {"/File/Permissions", NULL
, not_yet
, 0, NULL
},
123 {"/File/Touch", NULL
, not_yet
, 0, NULL
},
124 {"/File/Find", NULL
, not_yet
, 0, NULL
},
125 {"/Select All", C_
"A", select_all
, 0, NULL
},
126 {"/Clear Selection", C_
"Z", clear_selection
, 0, NULL
},
127 {"/Options...", NULL
, show_options
, 0, NULL
},
128 {"/New directory", NULL
, new_directory
, 0, NULL
},
129 {"/Xterm here", NULL
, xterm_here
, 0, NULL
},
130 {"/Open parent", NULL
, open_parent
, 0, NULL
},
133 static GtkItemFactoryEntry panel_menu_def
[] = {
134 {"/Display", NULL
, NULL
, 0, "<Branch>"},
135 {"/Display/Large Icons", NULL
, not_yet
, 0, "<RadioItem>"},
136 {"/Display/Small Icons", NULL
, not_yet
, 0, "/Display/Large Icons"},
137 {"/Display/Full Info", NULL
, not_yet
, 0, "/Display/Large Icons"},
138 {"/Display/Separator", NULL
, NULL
, 0, "<Separator>"},
139 {"/Display/Sort by Name", NULL
, not_yet
, 0, "<RadioItem>"},
140 {"/Display/Sort by Type", NULL
, not_yet
, 0, "/Display/Sort by Name"},
141 {"/Display/Sort by Date", NULL
, not_yet
, 0, "/Display/Sort by Name"},
142 {"/Display/Sort by Size", NULL
, not_yet
, 0, "/Display/Sort by Name"},
143 {"/Display/Sort by Owner", NULL
, not_yet
, 0, "/Display/Sort by Name"},
144 {"/Display/Separator", NULL
, NULL
, 0, "<Separator>"},
145 {"/Display/Show Hidden", NULL
, hidden
, 0, "<ToggleItem>"},
146 {"/Display/Refresh", NULL
, refresh
, 0, NULL
},
147 {"/File", NULL
, NULL
, 0, "<Branch>"},
148 {"/File/Help", NULL
, help
, 0, NULL
},
149 {"/File/Info", NULL
, show_file_info
, 0, NULL
},
150 {"/File/Delete", NULL
, delete, 0, NULL
},
151 {"/Open as directory", NULL
, open_as_dir
, 0, NULL
},
152 {"/Close panel", NULL
, close_panel
, 0, NULL
},
157 GtkItemFactory
*item_factory
;
161 /* This call starts returning strange values after a while, so get
162 * the result here during init.
164 gdk_window_get_size(GDK_ROOT_PARENT(), &screen_width
, &screen_height
);
166 filer_keys
= gtk_accel_group_new();
167 item_factory
= gtk_item_factory_new(GTK_TYPE_MENU
,
170 gtk_item_factory_create_items(item_factory
,
171 sizeof(filer_menu_def
) / sizeof(*filer_menu_def
),
174 filer_menu
= gtk_item_factory_get_widget(item_factory
, "<filer>");
175 filer_file_menu
= gtk_item_factory_get_widget(item_factory
,
177 items
= gtk_container_children(GTK_CONTAINER(filer_menu
));
178 filer_file_item
= GTK_BIN(g_list_nth(items
, 1)->data
)->child
;
181 panel_keys
= gtk_accel_group_new();
182 item_factory
= gtk_item_factory_new(GTK_TYPE_MENU
,
185 gtk_item_factory_create_items(item_factory
,
186 sizeof(panel_menu_def
) / sizeof(*panel_menu_def
),
189 panel_menu
= gtk_item_factory_get_widget(item_factory
, "<panel>");
190 panel_file_menu
= gtk_item_factory_get_widget(item_factory
,
192 items
= gtk_container_children(GTK_CONTAINER(panel_menu
));
193 panel_file_item
= GTK_BIN(g_list_nth(items
, 1)->data
)->child
;
196 menurc
= choices_find_path_load("menus");
198 gtk_item_factory_parse_rc(menurc
);
200 gtk_signal_connect(GTK_OBJECT(panel_menu
), "unmap_event",
201 GTK_SIGNAL_FUNC(menu_closed
), NULL
);
202 gtk_signal_connect(GTK_OBJECT(filer_menu
), "unmap_event",
203 GTK_SIGNAL_FUNC(menu_closed
), NULL
);
205 gtk_accel_group_lock(panel_keys
);
207 options_sections
= g_slist_prepend(options_sections
, &options
);
208 xterm_here_value
= g_strdup("xterm");
209 option_register("xterm_here", load_xterm_here
);
212 /* Build up some option widgets to go in the options dialog, but don't
215 static GtkWidget
*create_options()
217 GtkWidget
*table
, *label
;
219 table
= gtk_table_new(2, 2, FALSE
);
220 gtk_container_set_border_width(GTK_CONTAINER(table
), 4);
222 label
= gtk_label_new("To set the keyboard short-cuts you simply open "
223 "the menu over a filer window, move the pointer over "
224 "the item you want to use and press a key. The key "
225 "will appear next to the menu item and you can just "
226 "press that key without opening the menu in future. "
227 "To save the current menu short-cuts for next time, "
228 "click the Save button at the bottom of this window.");
229 gtk_label_set_line_wrap(GTK_LABEL(label
), TRUE
);
230 gtk_table_attach_defaults(GTK_TABLE(table
), label
, 0, 2, 0, 1);
232 label
= gtk_label_new("'Xterm here' program:");
233 gtk_table_attach_defaults(GTK_TABLE(table
), label
, 0, 1, 1, 2);
234 xterm_here_entry
= gtk_entry_new();
235 gtk_table_attach_defaults(GTK_TABLE(table
), xterm_here_entry
,
241 static char *load_xterm_here(char *data
)
243 g_free(xterm_here_value
);
244 xterm_here_value
= g_strdup(data
);
248 static void update_options()
250 gtk_entry_set_text(GTK_ENTRY(xterm_here_entry
), xterm_here_value
);
253 static void set_options()
255 g_free(xterm_here_value
);
256 xterm_here_value
= g_strdup(gtk_entry_get_text(
257 GTK_ENTRY(xterm_here_entry
)));
260 static void save_options()
264 menurc
= choices_find_path_save("menus");
266 gtk_item_factory_dump_rc(menurc
, NULL
, TRUE
);
268 option_write("xterm_here", xterm_here_value
);
272 static void items_sensitive(GtkWidget
*menu
, int from
, int n
, gboolean state
)
276 items
= gtk_container_children(GTK_CONTAINER(menu
));
278 item
= g_list_nth(items
, from
);
281 gtk_widget_set_sensitive(GTK_BIN(item
->data
)->child
, state
);
288 static void position_menu(GtkMenu
*menu
, gint
*x
, gint
*y
, gpointer data
)
290 int *pos
= (int *) data
;
291 GtkRequisition requisition
;
293 gtk_widget_size_request(GTK_WIDGET(menu
), &requisition
);
296 *x
= screen_width
- MENU_MARGIN
- requisition
.width
;
297 else if (pos
[0] == -2)
300 *x
= pos
[0] - (requisition
.width
>> 2);
303 *y
= screen_height
- MENU_MARGIN
- requisition
.height
;
304 else if (pos
[1] == -2)
307 *y
= pos
[1] - (requisition
.height
>> 2);
309 *x
= CLAMP(*x
, 0, screen_width
- requisition
.width
);
310 *y
= CLAMP(*y
, 0, screen_height
- requisition
.height
);
313 void show_filer_menu(FilerWindow
*filer_window
, GdkEventButton
*event
,
317 GtkWidget
*file_label
, *file_menu
;
321 pos
[0] = event
->x_root
;
322 pos
[1] = event
->y_root
;
324 window_with_focus
= filer_window
;
326 if (filer_window
->panel
)
328 switch (filer_window
->panel_side
)
330 case TOP
: pos
[1] = -2; break;
331 case BOTTOM
: pos
[1] = -1; break;
332 case LEFT
: pos
[0] = -2; break;
333 case RIGHT
: pos
[0] = -1; break;
337 if (filer_window
->panel
)
338 collection_clear_selection(filer_window
->collection
); /* ??? */
340 if (filer_window
->collection
->number_selected
== 0 && item
>= 0)
342 collection_select_item(filer_window
->collection
, item
);
343 filer_window
->temp_item_selected
= TRUE
;
346 filer_window
->temp_item_selected
= FALSE
;
348 if (filer_window
->panel
)
350 file_label
= panel_file_item
;
351 file_menu
= panel_file_menu
;
355 file_label
= filer_file_item
;
356 file_menu
= filer_file_menu
;
359 buffer
= g_string_new(NULL
);
360 switch (filer_window
->collection
->number_selected
)
363 g_string_assign(buffer
, "<nothing selected>");
364 items_sensitive(file_menu
, 0, 5, FALSE
);
365 items_sensitive(file_menu
, 6, -1, FALSE
);
366 gtk_widget_set_sensitive(file_label
, FALSE
);
369 items_sensitive(file_menu
, 0, 5, TRUE
);
370 items_sensitive(file_menu
, 6, -1, TRUE
);
371 gtk_widget_set_sensitive(file_label
, TRUE
);
372 file_item
= selected_item(filer_window
->collection
);
373 g_string_sprintf(buffer
, "%s '%s'",
374 basetype_name(file_item
),
375 file_item
->leafname
);
378 items_sensitive(file_menu
, 0, 5, FALSE
);
379 items_sensitive(file_menu
, 6, -1, TRUE
);
380 gtk_widget_set_sensitive(file_label
, TRUE
);
381 g_string_sprintf(buffer
, "%d items",
382 filer_window
->collection
->number_selected
);
386 gtk_label_set_text(GTK_LABEL(file_label
), buffer
->str
);
388 g_string_free(buffer
, TRUE
);
390 gtk_menu_popup(filer_window
->panel
? GTK_MENU(panel_menu
)
391 : GTK_MENU(filer_menu
),
392 NULL
, NULL
, position_menu
,
393 (gpointer
) pos
, event
->button
, event
->time
);
396 static void menu_closed(GtkWidget
*widget
)
398 if (window_with_focus
== NULL
)
399 return; /* Close panel item chosen? */
401 if (window_with_focus
->temp_item_selected
)
403 collection_clear_selection(window_with_focus
->collection
);
404 window_with_focus
->temp_item_selected
= FALSE
;
410 /* Fake action to warn when a menu item does nothing */
411 static void not_yet(gpointer data
, guint action
, GtkWidget
*widget
)
413 delayed_error("ROX-Filer", "Sorry, that feature isn't implemented yet");
416 static void hidden(gpointer data
, guint action
, GtkWidget
*widget
)
418 g_return_if_fail(window_with_focus
!= NULL
);
420 window_with_focus
->show_hidden
= !window_with_focus
->show_hidden
;
421 update_dir(window_with_focus
);
424 static void refresh(gpointer data
, guint action
, GtkWidget
*widget
)
426 g_return_if_fail(window_with_focus
!= NULL
);
428 update_dir(window_with_focus
);
431 static void delete(gpointer data
, guint action
, GtkWidget
*widget
)
433 g_return_if_fail(window_with_focus
!= NULL
);
435 action_delete(window_with_focus
);
438 static gboolean
copy_cb(char *initial
, char *path
)
440 char *new_dir
, *slash
;
443 gboolean retval
= TRUE
;
445 slash
= strrchr(path
, '/');
448 report_error("ROX-Filer", "Missing '/' in new pathname");
452 if (access(path
, F_OK
) == 0)
454 report_error("ROX-Filer",
455 "An item with this name already exists");
460 new_dir
= g_malloc(len
+ 1);
461 memcpy(new_dir
, path
, len
);
464 command
= g_string_new(NULL
);
465 g_string_sprintf(command
, "cp -a %s %s", initial
, path
);
467 if (system(command
->str
))
469 g_string_append(command
, " failed!");
470 report_error("ROX-Filer", command
->str
);
474 g_string_free(command
, TRUE
);
476 refresh_dirs(new_dir
);
480 static void copy_item(gpointer data
, guint action
, GtkWidget
*widget
)
482 Collection
*collection
;
484 g_return_if_fail(window_with_focus
!= NULL
);
486 collection
= window_with_focus
->collection
;
487 if (collection
->number_selected
!= 1)
488 report_error("ROX-Filer", "You must select a single "
492 FileItem
*item
= selected_item(collection
);
494 savebox_show(window_with_focus
, "Copy",
495 window_with_focus
->path
, item
->leafname
,
496 item
->image
, copy_cb
);
500 static gboolean
rename_cb(char *initial
, char *path
)
502 if (rename(initial
, path
))
504 report_error("ROX-Filer: rename()", g_strerror(errno
));
510 static void rename_item(gpointer data
, guint action
, GtkWidget
*widget
)
512 Collection
*collection
;
514 g_return_if_fail(window_with_focus
!= NULL
);
516 collection
= window_with_focus
->collection
;
517 if (collection
->number_selected
!= 1)
518 report_error("ROX-Filer", "You must select a single "
522 FileItem
*item
= selected_item(collection
);
524 savebox_show(window_with_focus
, "Rename",
525 window_with_focus
->path
, item
->leafname
,
526 item
->image
, rename_cb
);
530 static gboolean
link_cb(char *initial
, char *path
)
532 if (symlink(initial
, path
))
534 report_error("ROX-Filer: symlink()", g_strerror(errno
));
540 static void link_item(gpointer data
, guint action
, GtkWidget
*widget
)
542 Collection
*collection
;
544 g_return_if_fail(window_with_focus
!= NULL
);
546 collection
= window_with_focus
->collection
;
547 if (collection
->number_selected
!= 1)
548 report_error("ROX-Filer", "You must select a single "
552 FileItem
*item
= selected_item(collection
);
554 savebox_show(window_with_focus
, "Symlink",
555 window_with_focus
->path
, item
->leafname
,
556 item
->image
, link_cb
);
560 static void show_file_info(gpointer data
, guint action
, GtkWidget
*widget
)
562 GtkWidget
*window
, *table
, *label
, *button
, *frame
;
563 GtkWidget
*file_label
;
569 char *argv
[] = {"file", "-b", NULL
, NULL
};
571 Collection
*collection
;
575 g_return_if_fail(window_with_focus
!= NULL
);
577 collection
= window_with_focus
->collection
;
578 if (collection
->number_selected
!= 1)
580 report_error("ROX-Filer", "You must select a single "
581 "item before using Info");
584 file
= selected_item(collection
);
585 path
= make_path(window_with_focus
->path
, file
->leafname
)->str
;
586 if (lstat(path
, &info
))
588 delayed_error("ROX-Filer", g_strerror(errno
));
592 gstring
= g_string_new(NULL
);
594 window
= gtk_window_new(GTK_WINDOW_DIALOG
);
595 gtk_window_set_position(GTK_WINDOW(window
), GTK_WIN_POS_MOUSE
);
596 gtk_container_set_border_width(GTK_CONTAINER(window
), 4);
597 gtk_window_set_title(GTK_WINDOW(window
), path
);
599 table
= gtk_table_new(9, 2, FALSE
);
600 gtk_container_add(GTK_CONTAINER(window
), table
);
601 gtk_table_set_row_spacings(GTK_TABLE(table
), 8);
602 gtk_table_set_col_spacings(GTK_TABLE(table
), 4);
604 label
= gtk_label_new("Owner, group:");
605 gtk_misc_set_alignment(GTK_MISC(label
), 1, .5);
606 gtk_label_set_justify(GTK_LABEL(label
), GTK_JUSTIFY_RIGHT
);
607 gtk_table_attach_defaults(GTK_TABLE(table
), label
, 0, 1, 0, 1);
608 g_string_sprintf(gstring
, "%s, %s", user_name(info
.st_uid
),
609 group_name(info
.st_gid
));
610 label
= gtk_label_new(gstring
->str
);
611 gtk_misc_set_alignment(GTK_MISC(label
), 0, .5);
612 gtk_table_attach_defaults(GTK_TABLE(table
), label
, 1, 2, 0, 1);
614 label
= gtk_label_new("Size:");
615 gtk_misc_set_alignment(GTK_MISC(label
), 1, .5);
616 gtk_table_attach_defaults(GTK_TABLE(table
), label
, 0, 1, 1, 2);
617 g_string_sprintf(gstring
, "%ld", info
.st_size
);
618 label
= gtk_label_new(gstring
->str
);
619 gtk_misc_set_alignment(GTK_MISC(label
), 0, .5);
620 gtk_table_attach_defaults(GTK_TABLE(table
), label
, 1, 2, 1, 2);
622 label
= gtk_label_new("Change time:");
623 gtk_misc_set_alignment(GTK_MISC(label
), 1, .5);
624 gtk_table_attach_defaults(GTK_TABLE(table
), label
, 0, 1, 2, 3);
625 g_string_sprintf(gstring
, "%s", ctime(&info
.st_ctime
));
626 g_string_truncate(gstring
, gstring
->len
- 1);
627 label
= gtk_label_new(gstring
->str
);
628 gtk_misc_set_alignment(GTK_MISC(label
), 0, .5);
629 gtk_table_attach_defaults(GTK_TABLE(table
), label
, 1, 2, 2, 3);
631 label
= gtk_label_new("Modify time:");
632 gtk_misc_set_alignment(GTK_MISC(label
), 1, .5);
633 gtk_table_attach_defaults(GTK_TABLE(table
), label
, 0, 1, 3, 4);
634 g_string_sprintf(gstring
, "%s", ctime(&info
.st_mtime
));
635 g_string_truncate(gstring
, gstring
->len
- 1);
636 label
= gtk_label_new(gstring
->str
);
637 gtk_misc_set_alignment(GTK_MISC(label
), 0, .5);
638 gtk_table_attach_defaults(GTK_TABLE(table
), label
, 1, 2, 3, 4);
640 label
= gtk_label_new("Access time:");
641 gtk_misc_set_alignment(GTK_MISC(label
), 1, .5);
642 gtk_table_attach_defaults(GTK_TABLE(table
), label
, 0, 1, 4, 5);
643 g_string_sprintf(gstring
, "%s", ctime(&info
.st_atime
));
644 g_string_truncate(gstring
, gstring
->len
- 1);
645 label
= gtk_label_new(gstring
->str
);
646 gtk_misc_set_alignment(GTK_MISC(label
), 0, .5);
647 gtk_table_attach_defaults(GTK_TABLE(table
), label
, 1, 2, 4, 5);
649 label
= gtk_label_new("Permissions:");
650 gtk_misc_set_alignment(GTK_MISC(label
), 1, .5);
651 gtk_table_attach_defaults(GTK_TABLE(table
), label
, 0, 1, 5, 6);
652 g_string_sprintf(gstring
, "%o", info
.st_mode
);
653 label
= gtk_label_new(gstring
->str
);
654 gtk_misc_set_alignment(GTK_MISC(label
), 0, .5);
655 gtk_table_attach_defaults(GTK_TABLE(table
), label
, 1, 2, 5, 6);
657 label
= gtk_label_new("MIME type:");
658 gtk_misc_set_alignment(GTK_MISC(label
), 1, .5);
659 gtk_table_attach_defaults(GTK_TABLE(table
), label
, 0, 1, 6, 7);
662 string
= g_strconcat(file
->mime_type
->media_type
, "/",
663 file
->mime_type
->subtype
, NULL
);
664 label
= gtk_label_new(string
);
668 label
= gtk_label_new("-");
669 gtk_misc_set_alignment(GTK_MISC(label
), 0, .5);
670 gtk_table_attach_defaults(GTK_TABLE(table
), label
, 1, 2, 6, 7);
672 frame
= gtk_frame_new("file(1) says...");
673 gtk_table_attach_defaults(GTK_TABLE(table
), frame
, 0, 2, 7, 8);
674 file_label
= gtk_label_new("<nothing yet>");
675 gtk_misc_set_padding(GTK_MISC(file_label
), 4, 4);
676 gtk_label_set_line_wrap(GTK_LABEL(file_label
), TRUE
);
677 gtk_container_add(GTK_CONTAINER(frame
), file_label
);
679 button
= gtk_button_new_with_label("OK");
680 gtk_table_attach(GTK_TABLE(table
), button
, 0, 2, 8, 9,
681 GTK_EXPAND
| GTK_FILL
| GTK_SHRINK
, 0, 40, 4);
682 gtk_signal_connect_object(GTK_OBJECT(button
), "clicked",
683 gtk_widget_destroy
, GTK_OBJECT(window
));
685 gtk_widget_show_all(window
);
694 gtk_label_set_text(GTK_LABEL(file_label
),
696 g_string_free(gstring
, TRUE
);
700 dup2(file_data
[1], STDOUT_FILENO
);
701 dup2(file_data
[1], STDERR_FILENO
);
703 if (execvp(argv
[0], argv
))
704 fprintf(stderr
, "execvp() error: %s\n",
708 /* We are the parent... */
710 g_string_truncate(gstring
, 0);
711 while (gtk_events_pending())
712 g_main_iteration(FALSE
);
713 while ((got
= read(file_data
[0], buffer
, sizeof(buffer
) - 1)))
716 g_string_append(gstring
, buffer
);
719 gtk_label_set_text(GTK_LABEL(file_label
), gstring
->str
);
720 g_string_free(gstring
, TRUE
);
723 static void help(gpointer data
, guint action
, GtkWidget
*widget
)
725 Collection
*collection
;
728 g_return_if_fail(window_with_focus
!= NULL
);
730 collection
= window_with_focus
->collection
;
731 if (collection
->number_selected
!= 1)
733 report_error("ROX-Filer", "You must select a single "
734 "item to get help on");
737 item
= selected_item(collection
);
738 switch (item
->base_type
)
741 if (item
->flags
& ITEM_FLAG_EXEC_FILE
)
742 report_error("Executable file",
743 "This is a file with an eXecute bit "
744 "set - it can be run as a program.");
747 "This is a data file. Try using the "
748 "Info menu item to find out more...");
751 if (item
->flags
& ITEM_FLAG_APPDIR
)
753 make_path(window_with_focus
->path
,
754 item
->leafname
)->str
);
755 else if (item
->flags
& ITEM_FLAG_MOUNT_POINT
)
756 report_error("Mount point",
757 "A mount point is a directory which another "
758 "filing system can be mounted on. Everything "
759 "on the mounted filesystem then appears to be "
760 "inside the directory.");
762 report_error("Directory",
763 "This is a directory. It contains an index to "
764 "other items - open it to see the list.");
766 case TYPE_CHAR_DEVICE
:
767 case TYPE_BLOCK_DEVICE
:
768 report_error("Device file",
769 "Device files allow you to read from or write "
770 "to a device driver as though it was an "
774 report_error("Named pipe",
775 "Pipes allow different programs to "
776 "communicate. One program writes data to the "
777 "pipe while another one reads it out again.");
780 report_error("Socket",
781 "Sockets allow processes to communicate.");
784 report_error("Unknown type",
785 "I couldn't find out what kind of file this "
786 "is. Maybe it doesn't exist anymore or you "
787 "don't have search permission on the directory "
793 static void mount(gpointer data
, guint action
, GtkWidget
*widget
)
797 Collection
*collection
;
801 g_return_if_fail(window_with_focus
!= NULL
);
803 collection
= window_with_focus
->collection
;
805 for (i
= 0; i
< collection
->number_of_items
; i
++)
806 if (collection
->items
[i
].selected
)
808 item
= (FileItem
*) collection
->items
[i
].data
;
809 if (item
->flags
& ITEM_FLAG_MOUNT_POINT
)
811 char *argv
[] = {"mount", NULL
, NULL
};
815 if (item
->flags
& ITEM_FLAG_MOUNTED
)
817 argv
[1] = make_path(window_with_focus
->path
,
818 item
->leafname
)->str
;
821 waitpid(child
, NULL
, 0);
823 error
= "Failed to run mount/umount";
827 update_dir(window_with_focus
);
829 error
= "You must select some mount points first!";
832 report_error("ROX-Filer", error
);
835 static void select_all(gpointer data
, guint action
, GtkWidget
*widget
)
837 g_return_if_fail(window_with_focus
!= NULL
);
839 collection_select_all(window_with_focus
->collection
);
840 window_with_focus
->temp_item_selected
= FALSE
;
843 static void clear_selection(gpointer data
, guint action
, GtkWidget
*widget
)
845 g_return_if_fail(window_with_focus
!= NULL
);
847 collection_clear_selection(window_with_focus
->collection
);
848 window_with_focus
->temp_item_selected
= FALSE
;
851 static void show_options(gpointer data
, guint action
, GtkWidget
*widget
)
853 g_return_if_fail(window_with_focus
!= NULL
);
855 options_show(window_with_focus
);
858 static gboolean
new_directory_cb(char *initial
, char *path
)
860 if (mkdir(path
, S_IRWXU
| S_IRWXG
| S_IRWXO
))
862 report_error("mkdir", g_strerror(errno
));
868 static void new_directory(gpointer data
, guint action
, GtkWidget
*widget
)
870 g_return_if_fail(window_with_focus
!= NULL
);
872 savebox_show(window_with_focus
, "Create directory",
873 window_with_focus
->path
, "NewDir",
874 default_pixmap
+ TYPE_DIRECTORY
, new_directory_cb
);
877 static void xterm_here(gpointer data
, guint action
, GtkWidget
*widget
)
879 char *argv
[] = {NULL
, NULL
};
881 argv
[0] = xterm_here_value
;
883 g_return_if_fail(window_with_focus
!= NULL
);
885 if (!spawn_full(argv
, window_with_focus
->path
, 0))
886 report_error("ROX-Filer", "Failed to fork() child "
890 static void open_parent(gpointer data
, guint action
, GtkWidget
*widget
)
892 g_return_if_fail(window_with_focus
!= NULL
);
894 filer_opendir(make_path(window_with_focus
->path
, "/..")->str
,
898 static void open_as_dir(gpointer data
, guint action
, GtkWidget
*widget
)
900 g_return_if_fail(window_with_focus
!= NULL
);
902 filer_opendir(window_with_focus
->path
, FALSE
, BOTTOM
);
905 static void close_panel(gpointer data
, guint action
, GtkWidget
*widget
)
907 g_return_if_fail(window_with_focus
!= NULL
);
909 gtk_widget_destroy(window_with_focus
->window
);