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)
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
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 /* filer.c - code for handling filer windows */
29 #include <sys/param.h>
36 #include <gdk/gdkkeysyms.h>
37 #include "collection.h"
41 #include "gui_support.h"
51 #include "minibuffer.h"
53 #define ROW_HEIGHT_LARGE 64
54 #define ROW_HEIGHT_SMALL 32
55 #define ROW_HEIGHT_FULL_INFO 44
56 #define SMALL_ICON_HEIGHT 20
57 #define SMALL_ICON_WIDTH 48
58 #define MAX_ICON_HEIGHT 42
59 #define MAX_ICON_WIDTH 48
60 #define PANEL_BORDER 2
61 #define MIN_ITEM_WIDTH 64
63 extern int collection_menu_button
;
64 extern gboolean collection_single_click
;
66 FilerWindow
*window_with_focus
= NULL
;
67 GdkFont
*fixed_font
= NULL
;
68 GList
*all_filer_windows
= NULL
;
70 static FilerWindow
*window_with_selection
= NULL
;
73 static GtkWidget
*create_options();
74 static void update_options();
75 static void set_options();
76 static void save_options();
77 static char *filer_single_click(char *data
);
78 static char *filer_menu_on_2(char *data
);
79 static char *filer_new_window_on_1(char *data
);
80 static char *filer_toolbar(char *data
);
82 static OptionsSection options
=
84 "Filer window options",
90 static gboolean o_toolbar
= TRUE
;
91 static GtkWidget
*toggle_toolbar
;
92 static gboolean o_single_click
= FALSE
;
93 static GtkWidget
*toggle_single_click
;
94 static gboolean o_new_window_on_1
= FALSE
; /* Button 1 => New window */
95 static GtkWidget
*toggle_new_window_on_1
;
96 static GtkWidget
*toggle_menu_on_2
;
98 /* Static prototypes */
99 static void attach(FilerWindow
*filer_window
);
100 static void detach(FilerWindow
*filer_window
);
101 static void filer_window_destroyed(GtkWidget
*widget
,
102 FilerWindow
*filer_window
);
103 static void show_menu(Collection
*collection
, GdkEventButton
*event
,
104 int number_selected
, gpointer user_data
);
105 static gint
focus_in(GtkWidget
*widget
,
106 GdkEventFocus
*event
,
107 FilerWindow
*filer_window
);
108 static gint
focus_out(GtkWidget
*widget
,
109 GdkEventFocus
*event
,
110 FilerWindow
*filer_window
);
111 static void add_item(FilerWindow
*filer_window
, DirItem
*item
);
112 static void toolbar_up_clicked(GtkWidget
*widget
, FilerWindow
*filer_window
);
113 static void toolbar_home_clicked(GtkWidget
*widget
, FilerWindow
*filer_window
);
114 static void add_button(GtkContainer
*box
, int pixmap
,
115 GtkSignalFunc cb
, gpointer data
, char *tip
);
116 static GtkWidget
*create_toolbar(FilerWindow
*filer_window
);
117 static int filer_confirm_close(GtkWidget
*widget
, GdkEvent
*event
,
118 FilerWindow
*window
);
119 static int calc_width(FilerWindow
*filer_window
, DirItem
*item
);
120 static void draw_large_icon(GtkWidget
*widget
,
124 static void draw_string(GtkWidget
*widget
,
131 static void draw_item_large(GtkWidget
*widget
,
132 CollectionItem
*item
,
134 static void draw_item_small(GtkWidget
*widget
,
135 CollectionItem
*item
,
137 static void draw_item_full_info(GtkWidget
*widget
,
138 CollectionItem
*colitem
,
140 static gboolean
test_point_large(Collection
*collection
,
141 int point_x
, int point_y
,
142 CollectionItem
*item
,
143 int width
, int height
);
144 static gboolean
test_point_small(Collection
*collection
,
145 int point_x
, int point_y
,
146 CollectionItem
*item
,
147 int width
, int height
);
148 static gboolean
test_point_full_info(Collection
*collection
,
149 int point_x
, int point_y
,
150 CollectionItem
*item
,
151 int width
, int height
);
152 static void update_display(Directory
*dir
,
155 FilerWindow
*filer_window
);
156 static void shrink_width(FilerWindow
*filer_window
);
157 static gboolean
may_rescan(FilerWindow
*filer_window
, gboolean warning
);
158 static void open_item(Collection
*collection
,
159 gpointer item_data
, int item_number
,
162 static GdkAtom xa_string
;
169 static GdkCursor
*busy_cursor
= NULL
;
170 static GtkTooltips
*tooltips
= NULL
;
174 xa_string
= gdk_atom_intern("STRING", FALSE
);
176 options_sections
= g_slist_prepend(options_sections
, &options
);
177 option_register("filer_new_window_on_1", filer_new_window_on_1
);
178 option_register("filer_menu_on_2", filer_menu_on_2
);
179 option_register("filer_single_click", filer_single_click
);
180 option_register("filer_toolbar", filer_toolbar
);
182 fixed_font
= gdk_font_load("fixed");
184 busy_cursor
= gdk_cursor_new(GDK_WATCH
);
186 tooltips
= gtk_tooltips_new();
189 static gboolean
if_deleted(gpointer item
, gpointer removed
)
191 int i
= ((GPtrArray
*) removed
)->len
;
192 DirItem
**r
= (DirItem
**) ((GPtrArray
*) removed
)->pdata
;
193 char *leafname
= ((DirItem
*) item
)->leafname
;
197 if (strcmp(leafname
, r
[i
]->leafname
) == 0)
204 static void update_item(FilerWindow
*filer_window
, DirItem
*item
)
207 char *leafname
= item
->leafname
;
209 if (leafname
[0] == '.')
211 if (filer_window
->show_hidden
== FALSE
|| leafname
[1] == '\0'
212 || (leafname
[1] == '.' && leafname
[2] == '\0'))
216 i
= collection_find_item(filer_window
->collection
, item
, dir_item_cmp
);
219 collection_draw_item(filer_window
->collection
, i
, TRUE
);
221 g_warning("Failed to find '%s'\n", item
->leafname
);
224 static void update_display(Directory
*dir
,
227 FilerWindow
*filer_window
)
230 int cursor
= filer_window
->collection
->cursor_item
;
232 Collection
*collection
= filer_window
->collection
;
237 as
= filer_window
->auto_select
;
239 for (i
= 0; i
< items
->len
; i
++)
241 DirItem
*item
= (DirItem
*) items
->pdata
[i
];
243 add_item(filer_window
, item
);
245 if (cursor
!= -1 || !as
)
248 if (strcmp(as
, item
->leafname
) != 0)
251 cursor
= collection
->number_of_items
- 1;
252 if (filer_window
->had_cursor
)
254 collection_set_cursor_item(collection
,
256 filer_window
->mini_cursor_base
= cursor
;
259 collection_wink_item(collection
,
263 collection_qsort(filer_window
->collection
,
264 filer_window
->sort_fn
);
267 collection_delete_if(filer_window
->collection
,
272 if (filer_window
->window
->window
)
273 gdk_window_set_cursor(
274 filer_window
->window
->window
,
276 shrink_width(filer_window
);
277 if (filer_window
->had_cursor
&&
278 collection
->cursor_item
== -1)
280 collection_set_cursor_item(collection
, 0);
281 filer_window
->had_cursor
= FALSE
;
285 for (i
= 0; i
< items
->len
; i
++)
287 DirItem
*item
= (DirItem
*) items
->pdata
[i
];
289 update_item(filer_window
, item
);
291 collection_qsort(filer_window
->collection
,
292 filer_window
->sort_fn
);
297 static void attach(FilerWindow
*filer_window
)
299 gdk_window_set_cursor(filer_window
->window
->window
, busy_cursor
);
300 collection_clear(filer_window
->collection
);
301 dir_attach(filer_window
->directory
, (DirCallback
) update_display
,
305 static void detach(FilerWindow
*filer_window
)
307 g_return_if_fail(filer_window
->directory
!= NULL
);
309 dir_detach(filer_window
->directory
,
310 (DirCallback
) update_display
, filer_window
);
311 g_fscache_data_unref(dir_cache
, filer_window
->directory
);
312 filer_window
->directory
= NULL
;
315 static void filer_window_destroyed(GtkWidget
*widget
,
316 FilerWindow
*filer_window
)
318 all_filer_windows
= g_list_remove(all_filer_windows
, filer_window
);
320 gtk_idle_remove_by_data(filer_window
);
322 if (window_with_selection
== filer_window
)
323 window_with_selection
= NULL
;
324 if (window_with_focus
== filer_window
)
325 window_with_focus
= NULL
;
327 if (filer_window
->directory
)
328 detach(filer_window
);
330 g_free(filer_window
->auto_select
);
331 g_free(filer_window
->path
);
332 g_free(filer_window
);
334 if (--number_of_windows
< 1)
338 static int calc_width(FilerWindow
*filer_window
, DirItem
*item
)
340 int pix_width
= item
->image
->width
;
342 switch (filer_window
->display_style
)
345 return MAX_ICON_WIDTH
+ 12 +
346 MAX(item
->details_width
, item
->name_width
);
348 return SMALL_ICON_WIDTH
+ 12 + item
->name_width
;
350 return MAX(pix_width
, item
->name_width
) + 4;
354 /* Add a single object to a directory display */
355 static void add_item(FilerWindow
*filer_window
, DirItem
*item
)
357 char *leafname
= item
->leafname
;
360 if (leafname
[0] == '.')
362 if (filer_window
->show_hidden
== FALSE
|| leafname
[1] == '\0'
363 || (leafname
[1] == '.' && leafname
[2] == '\0'))
367 item_width
= calc_width(filer_window
, item
);
368 if (item_width
> filer_window
->collection
->item_width
)
369 collection_set_item_size(filer_window
->collection
,
371 filer_window
->collection
->item_height
);
372 collection_insert(filer_window
->collection
, item
);
375 /* Is a point inside an item? */
376 static gboolean
test_point_large(Collection
*collection
,
377 int point_x
, int point_y
,
378 CollectionItem
*colitem
,
379 int width
, int height
)
381 DirItem
*item
= (DirItem
*) colitem
->data
;
382 GdkFont
*font
= GTK_WIDGET(collection
)->style
->font
;
383 int text_height
= font
->ascent
+ font
->descent
;
384 MaskedPixmap
*image
= item
->image
;
385 int image_y
= MAX(0, MAX_ICON_HEIGHT
- image
->height
);
386 int image_width
= (image
->width
>> 1) + 2;
387 int text_width
= (item
->name_width
>> 1) + 2;
390 if (point_y
< image_y
)
391 return FALSE
; /* Too high up (don't worry about too low) */
393 if (point_y
<= image_y
+ image
->height
+ 2)
394 x_limit
= image_width
;
395 else if (point_y
> height
- text_height
- 2)
396 x_limit
= text_width
;
398 x_limit
= MIN(image_width
, text_width
);
400 return ABS(point_x
- (width
>> 1)) < x_limit
;
403 static gboolean
test_point_full_info(Collection
*collection
,
404 int point_x
, int point_y
,
405 CollectionItem
*colitem
,
406 int width
, int height
)
408 DirItem
*item
= (DirItem
*) colitem
->data
;
409 GdkFont
*font
= GTK_WIDGET(collection
)->style
->font
;
410 MaskedPixmap
*image
= item
->image
;
411 int image_y
= MAX(0, MAX_ICON_HEIGHT
- image
->height
);
413 - fixed_font
->descent
- 2 - fixed_font
->ascent
;
415 if (point_x
< image
->width
+ 2)
416 return point_x
> 2 && point_y
> image_y
;
418 point_x
-= MAX_ICON_WIDTH
+ 8;
420 if (point_y
>= low_top
)
421 return point_x
< item
->details_width
;
422 if (point_y
>= low_top
- font
->ascent
- font
->descent
)
423 return point_x
< item
->name_width
;
427 static gboolean
test_point_small(Collection
*collection
,
428 int point_x
, int point_y
,
429 CollectionItem
*colitem
,
430 int width
, int height
)
432 DirItem
*item
= (DirItem
*) colitem
->data
;
433 MaskedPixmap
*image
= item
->image
;
434 int image_y
= MAX(0, SMALL_ICON_HEIGHT
- image
->height
);
435 GdkFont
*font
= GTK_WIDGET(collection
)->style
->font
;
437 - fixed_font
->descent
- 2 - font
->ascent
;
438 int iwidth
= MIN(SMALL_ICON_WIDTH
, image
->width
);
440 if (point_x
< iwidth
+ 2)
441 return point_x
> 2 && point_y
> image_y
;
443 point_x
-= SMALL_ICON_WIDTH
+ 4;
445 if (point_y
>= low_top
)
446 return point_x
< item
->name_width
;
450 static void draw_small_icon(GtkWidget
*widget
,
455 MaskedPixmap
*image
= item
->image
;
456 int width
= MIN(image
->width
, SMALL_ICON_WIDTH
);
457 int height
= MIN(image
->height
, SMALL_ICON_HEIGHT
);
458 int image_x
= area
->x
+ ((area
->width
- width
) >> 1);
460 GdkGC
*gc
= selected
? widget
->style
->white_gc
461 : widget
->style
->black_gc
;
465 gdk_gc_set_clip_mask(gc
, item
->image
->mask
);
467 image_y
= MAX(0, SMALL_ICON_HEIGHT
- image
->height
);
468 gdk_gc_set_clip_origin(gc
, image_x
, area
->y
+ image_y
);
469 gdk_draw_pixmap(widget
->window
, gc
,
471 0, 0, /* Source x,y */
472 image_x
, area
->y
+ image_y
, /* Dest x,y */
477 gdk_gc_set_function(gc
, GDK_INVERT
);
478 gdk_draw_rectangle(widget
->window
,
480 TRUE
, image_x
, area
->y
+ image_y
,
482 gdk_gc_set_function(gc
, GDK_COPY
);
485 if (item
->flags
& ITEM_FLAG_SYMLINK
)
487 gdk_gc_set_clip_origin(gc
, image_x
, area
->y
+ 8);
488 gdk_gc_set_clip_mask(gc
,
489 default_pixmap
[TYPE_SYMLINK
].mask
);
490 gdk_draw_pixmap(widget
->window
, gc
,
491 default_pixmap
[TYPE_SYMLINK
].pixmap
,
492 0, 0, /* Source x,y */
493 image_x
, area
->y
+ 8, /* Dest x,y */
496 else if (item
->flags
& ITEM_FLAG_MOUNT_POINT
)
498 int type
= item
->flags
& ITEM_FLAG_MOUNTED
501 gdk_gc_set_clip_origin(gc
, image_x
, area
->y
+ 8);
502 gdk_gc_set_clip_mask(gc
,
503 default_pixmap
[type
].mask
);
504 gdk_draw_pixmap(widget
->window
, gc
,
505 default_pixmap
[type
].pixmap
,
506 0, 0, /* Source x,y */
507 image_x
, area
->y
+ 8, /* Dest x,y */
511 gdk_gc_set_clip_mask(gc
, NULL
);
512 gdk_gc_set_clip_origin(gc
, 0, 0);
515 static void draw_large_icon(GtkWidget
*widget
,
520 MaskedPixmap
*image
= item
->image
;
521 int width
= MIN(image
->width
, MAX_ICON_WIDTH
);
522 int height
= MIN(image
->height
, MAX_ICON_WIDTH
);
523 int image_x
= area
->x
+ ((area
->width
- width
) >> 1);
525 GdkGC
*gc
= selected
? widget
->style
->white_gc
526 : widget
->style
->black_gc
;
528 gdk_gc_set_clip_mask(gc
, item
->image
->mask
);
530 image_y
= MAX(0, MAX_ICON_HEIGHT
- image
->height
);
531 gdk_gc_set_clip_origin(gc
, image_x
, area
->y
+ image_y
);
532 gdk_draw_pixmap(widget
->window
, gc
,
534 0, 0, /* Source x,y */
535 image_x
, area
->y
+ image_y
, /* Dest x,y */
540 gdk_gc_set_function(gc
, GDK_INVERT
);
541 gdk_draw_rectangle(widget
->window
,
543 TRUE
, image_x
, area
->y
+ image_y
,
545 gdk_gc_set_function(gc
, GDK_COPY
);
548 if (item
->flags
& ITEM_FLAG_SYMLINK
)
550 gdk_gc_set_clip_origin(gc
, image_x
, area
->y
+ 8);
551 gdk_gc_set_clip_mask(gc
,
552 default_pixmap
[TYPE_SYMLINK
].mask
);
553 gdk_draw_pixmap(widget
->window
, gc
,
554 default_pixmap
[TYPE_SYMLINK
].pixmap
,
555 0, 0, /* Source x,y */
556 image_x
, area
->y
+ 8, /* Dest x,y */
559 else if (item
->flags
& ITEM_FLAG_MOUNT_POINT
)
561 int type
= item
->flags
& ITEM_FLAG_MOUNTED
564 gdk_gc_set_clip_origin(gc
, image_x
, area
->y
+ 8);
565 gdk_gc_set_clip_mask(gc
,
566 default_pixmap
[type
].mask
);
567 gdk_draw_pixmap(widget
->window
, gc
,
568 default_pixmap
[type
].pixmap
,
569 0, 0, /* Source x,y */
570 image_x
, area
->y
+ 8, /* Dest x,y */
574 gdk_gc_set_clip_mask(gc
, NULL
);
575 gdk_gc_set_clip_origin(gc
, 0, 0);
578 static void draw_string(GtkWidget
*widget
,
586 int text_height
= font
->ascent
+ font
->descent
;
589 gtk_paint_flat_box(widget
->style
, widget
->window
,
590 GTK_STATE_SELECTED
, GTK_SHADOW_NONE
,
591 NULL
, widget
, "text",
596 gdk_draw_text(widget
->window
,
598 selected
? widget
->style
->white_gc
599 : widget
->style
->black_gc
,
601 string
, strlen(string
));
604 /* Return a string (valid until next call) giving details
607 char *details(DirItem
*item
)
609 mode_t m
= item
->mode
;
610 static GString
*buf
= NULL
;
613 buf
= g_string_new(NULL
);
615 g_string_sprintf(buf
, "%s, %c%c%c:%c%c%c:%c%c%c:%c%c"
621 S_ISCHR(m
) ? "Char" :
622 S_ISBLK(m
) ? "Blck" :
623 S_ISLNK(m
) ? "Link" :
624 S_ISSOCK(m
) ? "Sock" :
625 S_ISFIFO(m
) ? "Pipe" : "File",
627 m
& S_IRUSR
? 'r' : '-',
628 m
& S_IWUSR
? 'w' : '-',
629 m
& S_IXUSR
? 'x' : '-',
631 m
& S_IRGRP
? 'r' : '-',
632 m
& S_IWGRP
? 'w' : '-',
633 m
& S_IXGRP
? 'x' : '-',
635 m
& S_IROTH
? 'r' : '-',
636 m
& S_IWOTH
? 'w' : '-',
637 m
& S_IXOTH
? 'x' : '-',
639 m
& S_ISUID
? 'U' : '-',
640 m
& S_ISGID
? 'G' : '-',
642 m
& S_ISVTX
? 'T' : '-',
644 format_size(item
->size
));
649 static void draw_item_full_info(GtkWidget
*widget
,
650 CollectionItem
*colitem
,
653 DirItem
*item
= (DirItem
*) colitem
->data
;
654 MaskedPixmap
*image
= item
->image
;
655 GdkFont
*font
= widget
->style
->font
;
656 int text_x
= area
->x
+ MAX_ICON_WIDTH
+ 8;
657 int low_text_y
= area
->y
+ area
->height
- fixed_font
->descent
- 2;
658 gboolean selected
= colitem
->selected
;
659 GdkRectangle pic_area
;
661 pic_area
.x
= area
->x
;
662 pic_area
.y
= area
->y
;
663 pic_area
.width
= image
->width
+ 8;
664 pic_area
.height
= area
->height
;
666 draw_large_icon(widget
, &pic_area
, item
, selected
);
672 low_text_y
- font
->descent
- fixed_font
->ascent
,
683 static void draw_item_small(GtkWidget
*widget
,
684 CollectionItem
*colitem
,
687 DirItem
*item
= (DirItem
*) colitem
->data
;
688 GdkFont
*font
= widget
->style
->font
;
689 int text_x
= area
->x
+ SMALL_ICON_WIDTH
+ 4;
690 int low_text_y
= area
->y
+ area
->height
- font
->descent
- 2;
691 gboolean selected
= colitem
->selected
;
692 GdkRectangle pic_area
;
694 pic_area
.x
= area
->x
;
695 pic_area
.y
= area
->y
;
696 pic_area
.width
= SMALL_ICON_WIDTH
;
697 pic_area
.height
= SMALL_ICON_HEIGHT
;
699 draw_small_icon(widget
, &pic_area
, item
, selected
);
710 static void draw_item_large(GtkWidget
*widget
,
711 CollectionItem
*colitem
,
714 DirItem
*item
= (DirItem
*) colitem
->data
;
715 GdkFont
*font
= widget
->style
->font
;
716 int text_x
= area
->x
+ ((area
->width
- item
->name_width
) >> 1);
717 int text_y
= area
->y
+ area
->height
- font
->descent
- 2;
718 gboolean selected
= colitem
->selected
;
720 draw_large_icon(widget
, area
, item
, selected
);
725 text_x
, text_y
, item
->name_width
,
729 static void show_menu(Collection
*collection
, GdkEventButton
*event
,
730 int item
, gpointer user_data
)
732 show_filer_menu((FilerWindow
*) user_data
, event
, item
);
735 /* Returns TRUE iff the directory still exits. */
736 static gboolean
may_rescan(FilerWindow
*filer_window
, gboolean warning
)
740 g_return_val_if_fail(filer_window
!= NULL
, FALSE
);
742 /* We do a fresh lookup (rather than update) because the inode may
745 dir
= g_fscache_lookup(dir_cache
, filer_window
->path
);
749 delayed_error("ROX-Filer", "Directory missing/deleted");
750 gtk_widget_destroy(filer_window
->window
);
753 if (dir
== filer_window
->directory
)
754 g_fscache_data_unref(dir_cache
, dir
);
757 detach(filer_window
);
758 filer_window
->directory
= dir
;
759 attach(filer_window
);
765 /* Another app has grabbed the selection */
766 static gint
collection_lose_selection(GtkWidget
*widget
,
767 GdkEventSelection
*event
)
769 if (window_with_selection
&&
770 window_with_selection
->collection
== COLLECTION(widget
))
772 FilerWindow
*filer_window
= window_with_selection
;
773 window_with_selection
= NULL
;
774 collection_clear_selection(filer_window
->collection
);
780 /* Someone wants us to send them the selection */
781 static void selection_get(GtkWidget
*widget
,
782 GtkSelectionData
*selection_data
,
787 GString
*reply
, *header
;
788 FilerWindow
*filer_window
;
790 Collection
*collection
;
792 filer_window
= gtk_object_get_data(GTK_OBJECT(widget
), "filer_window");
794 reply
= g_string_new(NULL
);
795 header
= g_string_new(NULL
);
800 g_string_sprintf(header
, " %s",
801 make_path(filer_window
->path
, "")->str
);
803 case TARGET_URI_LIST
:
804 g_string_sprintf(header
, " file://%s%s",
806 make_path(filer_window
->path
, "")->str
);
810 collection
= filer_window
->collection
;
811 for (i
= 0; i
< collection
->number_of_items
; i
++)
813 if (collection
->items
[i
].selected
)
816 (DirItem
*) collection
->items
[i
].data
;
818 g_string_append(reply
, header
->str
);
819 g_string_append(reply
, item
->leafname
);
822 /* This works, but I don't think I like it... */
823 /* g_string_append_c(reply, ' '); */
825 gtk_selection_data_set(selection_data
, xa_string
,
826 8, reply
->str
+ 1, reply
->len
- 1);
827 g_string_free(reply
, TRUE
);
828 g_string_free(header
, TRUE
);
831 /* No items are now selected. This might be because another app claimed
832 * the selection or because the user unselected all the items.
834 static void lose_selection(Collection
*collection
,
838 FilerWindow
*filer_window
= (FilerWindow
*) user_data
;
840 if (window_with_selection
== filer_window
)
842 window_with_selection
= NULL
;
843 gtk_selection_owner_set(NULL
,
844 GDK_SELECTION_PRIMARY
,
849 static void gain_selection(Collection
*collection
,
853 FilerWindow
*filer_window
= (FilerWindow
*) user_data
;
855 if (gtk_selection_owner_set(GTK_WIDGET(collection
),
856 GDK_SELECTION_PRIMARY
,
859 window_with_selection
= filer_window
;
862 collection_clear_selection(filer_window
->collection
);
865 int sort_by_name(const void *item1
, const void *item2
)
867 return strcmp((*((DirItem
**)item1
))->leafname
,
868 (*((DirItem
**)item2
))->leafname
);
871 int sort_by_type(const void *item1
, const void *item2
)
873 const DirItem
*i1
= (DirItem
*) ((CollectionItem
*) item1
)->data
;
874 const DirItem
*i2
= (DirItem
*) ((CollectionItem
*) item2
)->data
;
877 int diff
= i1
->base_type
- i2
->base_type
;
880 diff
= (i1
->flags
& ITEM_FLAG_APPDIR
)
881 - (i2
->flags
& ITEM_FLAG_APPDIR
);
883 return diff
> 0 ? 1 : -1;
890 diff
= strcmp(m1
->media_type
, m2
->media_type
);
892 diff
= strcmp(m1
->subtype
, m2
->subtype
);
900 return diff
> 0 ? 1 : -1;
902 return sort_by_name(item1
, item2
);
905 int sort_by_date(const void *item1
, const void *item2
)
907 const DirItem
*i1
= (DirItem
*) ((CollectionItem
*) item1
)->data
;
908 const DirItem
*i2
= (DirItem
*) ((CollectionItem
*) item2
)->data
;
910 return i1
->mtime
> i2
->mtime
? -1 :
911 i1
->mtime
< i2
->mtime
? 1 :
912 sort_by_name(item1
, item2
);
915 int sort_by_size(const void *item1
, const void *item2
)
917 const DirItem
*i1
= (DirItem
*) ((CollectionItem
*) item1
)->data
;
918 const DirItem
*i2
= (DirItem
*) ((CollectionItem
*) item2
)->data
;
920 return i1
->size
> i2
->size
? -1 :
921 i1
->size
< i2
->size
? 1 :
922 sort_by_name(item1
, item2
);
925 static void open_item(Collection
*collection
,
926 gpointer item_data
, int item_number
,
929 FilerWindow
*filer_window
= (FilerWindow
*) user_data
;
931 GdkEventButton
*bevent
;
934 gboolean adjust
; /* do alternative action */
936 event
= (GdkEvent
*) gtk_get_current_event();
938 bevent
= (GdkEventButton
*) event
;
939 kevent
= (GdkEventKey
*) event
;
943 case GDK_2BUTTON_PRESS
:
944 case GDK_BUTTON_PRESS
:
945 case GDK_BUTTON_RELEASE
:
946 shift
= bevent
->state
& GDK_SHIFT_MASK
;
947 adjust
= (bevent
->button
!= 1)
948 ^ ((bevent
->state
& GDK_CONTROL_MASK
) != 0
949 && o_single_click
== 0);
952 shift
= kevent
->state
& GDK_SHIFT_MASK
;
961 filer_openitem(filer_window
, item_number
, shift
, adjust
);
964 /* Return the full path to the directory containing object 'path'.
965 * Relative paths are resolved from the filerwindow's path.
967 static void follow_symlink(FilerWindow
*filer_window
, char *path
)
973 path
= make_path(filer_window
->path
, path
)->str
;
975 real
= pathdup(path
);
976 slash
= strrchr(real
, '/');
980 delayed_error("ROX-Filer",
981 "Broken symlink (or you don't have permission "
993 if (filer_window
->panel
)
994 filer_opendir(new_dir
, FALSE
, BOTTOM
);
996 filer_change_to(filer_window
, new_dir
, slash
+ 1);
1001 void filer_openitem(FilerWindow
*filer_window
, int item_number
,
1002 gboolean shift
, gboolean adjust
)
1006 DirItem
*item
= (DirItem
*)
1007 filer_window
->collection
->items
[item_number
].data
;
1008 gboolean wink
= TRUE
;
1010 widget
= filer_window
->window
;
1011 full_path
= make_path(filer_window
->path
,
1012 item
->leafname
)->str
;
1014 if (item
->flags
& ITEM_FLAG_SYMLINK
&& shift
)
1016 char path
[MAXPATHLEN
+ 1];
1019 got
= readlink(make_path(filer_window
->path
,
1020 item
->leafname
)->str
,
1023 delayed_error("ROX-Filer", g_strerror(errno
));
1026 g_return_if_fail(got
<= MAXPATHLEN
);
1029 follow_symlink(filer_window
, path
);
1034 switch (item
->base_type
)
1036 case TYPE_DIRECTORY
:
1037 if (item
->flags
& ITEM_FLAG_APPDIR
&& !shift
)
1039 run_app(make_path(filer_window
->path
,
1040 item
->leafname
)->str
);
1041 if (adjust
&& !filer_window
->panel
)
1042 gtk_widget_destroy(widget
);
1046 if (item
->flags
& ITEM_FLAG_MOUNT_POINT
&& shift
)
1048 action_mount(filer_window
, item
);
1049 if (item
->flags
& ITEM_FLAG_MOUNTED
)
1053 if ((adjust
^ o_new_window_on_1
) || filer_window
->panel
)
1054 filer_opendir(full_path
, FALSE
, BOTTOM
);
1058 filer_change_to(filer_window
, full_path
, NULL
);
1062 if (item
->flags
& ITEM_FLAG_EXEC_FILE
1065 char *argv
[] = {NULL
, NULL
};
1067 argv
[0] = full_path
;
1069 if (spawn_full(argv
, getenv("HOME"), 0))
1071 if (adjust
&& !filer_window
->panel
)
1074 gtk_widget_destroy(widget
);
1078 report_error("ROX-Filer",
1079 "Failed to fork() child");
1084 MIME_type
*type
= shift
? &text_plain
1087 g_return_if_fail(type
!= NULL
);
1089 if (type_open(full_path
, type
))
1091 if (adjust
&& !filer_window
->panel
)
1094 gtk_widget_destroy(widget
);
1099 message
= g_string_new(NULL
);
1100 g_string_sprintf(message
, "No open "
1101 "action specified for files of "
1102 "this type (%s/%s)",
1105 report_error("ROX-Filer", message
->str
);
1106 g_string_free(message
, TRUE
);
1111 report_error("open_item",
1112 "I don't know how to open that");
1117 collection_wink_item(filer_window
->collection
, item_number
);
1120 static gint
pointer_in(GtkWidget
*widget
,
1121 GdkEventCrossing
*event
,
1122 FilerWindow
*filer_window
)
1124 may_rescan(filer_window
, TRUE
);
1128 static gint
focus_in(GtkWidget
*widget
,
1129 GdkEventFocus
*event
,
1130 FilerWindow
*filer_window
)
1132 window_with_focus
= filer_window
;
1137 static gint
focus_out(GtkWidget
*widget
,
1138 GdkEventFocus
*event
,
1139 FilerWindow
*filer_window
)
1141 /* TODO: Shade the cursor */
1146 /* Handle keys that can't be bound with the menu */
1147 static gint
key_press_event(GtkWidget
*widget
,
1149 FilerWindow
*filer_window
)
1151 switch (event
->keyval
)
1154 change_to_parent(filer_window
);
1163 static void toolbar_refresh_clicked(GtkWidget
*widget
,
1164 FilerWindow
*filer_window
)
1167 update_dir(filer_window
, TRUE
);
1170 static void toolbar_home_clicked(GtkWidget
*widget
, FilerWindow
*filer_window
)
1172 filer_change_to(filer_window
, getenv("HOME"), NULL
);
1175 static void toolbar_up_clicked(GtkWidget
*widget
, FilerWindow
*filer_window
)
1177 change_to_parent(filer_window
);
1180 void change_to_parent(FilerWindow
*filer_window
)
1185 if (filer_window
->path
[0] == '/' && filer_window
->path
[1] == '\0')
1186 return; /* Already in the root */
1188 copy
= g_strdup(filer_window
->path
);
1189 slash
= strrchr(copy
, '/');
1194 filer_change_to(filer_window
,
1199 g_warning("No / in directory path!\n");
1205 /* Make filer_window display path. When finished, highlight item 'from', or
1206 * the first item if from is NULL. If there is currently no cursor then
1207 * simply wink 'from' (if not NULL).
1209 void filer_change_to(FilerWindow
*filer_window
, char *path
, char *from
)
1213 from_dup
= from
&& *from
? g_strdup(from
) : NULL
;
1215 detach(filer_window
);
1216 g_free(filer_window
->path
);
1217 filer_window
->path
= pathdup(path
);
1219 filer_window
->directory
= g_fscache_lookup(dir_cache
,
1220 filer_window
->path
);
1221 if (filer_window
->directory
)
1223 g_free(filer_window
->auto_select
);
1224 filer_window
->had_cursor
=
1225 filer_window
->collection
->cursor_item
!= -1
1226 || filer_window
->had_cursor
;
1227 filer_window
->auto_select
= from_dup
;
1229 gtk_window_set_title(GTK_WINDOW(filer_window
->window
),
1230 filer_window
->path
);
1231 collection_set_cursor_item(filer_window
->collection
, -1);
1232 attach(filer_window
);
1234 if (GTK_WIDGET_VISIBLE(filer_window
->minibuffer
))
1235 gtk_idle_add((GtkFunction
) minibuffer_show
,
1243 error
= g_strdup_printf("Directory '%s' is not accessible.",
1245 delayed_error("ROX-Filer", error
);
1247 gtk_widget_destroy(filer_window
->window
);
1251 int selected_item_number(Collection
*collection
)
1255 g_return_val_if_fail(collection
!= NULL
, -1);
1256 g_return_val_if_fail(IS_COLLECTION(collection
), -1);
1257 g_return_val_if_fail(collection
->number_selected
== 1, -1);
1259 for (i
= 0; i
< collection
->number_of_items
; i
++)
1260 if (collection
->items
[i
].selected
)
1263 g_warning("selected_item: number_selected is wrong\n");
1268 DirItem
*selected_item(Collection
*collection
)
1272 item
= selected_item_number(collection
);
1275 return (DirItem
*) collection
->items
[item
].data
;
1279 static int filer_confirm_close(GtkWidget
*widget
, GdkEvent
*event
,
1280 FilerWindow
*window
)
1282 /* TODO: We can open lots of these - very irritating! */
1283 return get_choice("Close panel?",
1284 "You have tried to close a panel via the window "
1285 "manager - I usually find that this is accidental... "
1287 2, "Remove", "Cancel") != 0;
1290 /* Make the items as narrow as possible */
1291 static void shrink_width(FilerWindow
*filer_window
)
1294 Collection
*col
= filer_window
->collection
;
1295 int width
= MIN_ITEM_WIDTH
;
1297 DisplayStyle style
= filer_window
->display_style
;
1301 font
= gtk_widget_get_default_style()->font
;
1302 text_height
= font
->ascent
+ font
->descent
;
1304 for (i
= 0; i
< col
->number_of_items
; i
++)
1306 this_width
= calc_width(filer_window
,
1307 (DirItem
*) col
->items
[i
].data
);
1308 if (this_width
> width
)
1312 collection_set_item_size(filer_window
->collection
,
1314 style
== FULL_INFO
? MAX_ICON_HEIGHT
+ 4 :
1315 style
== SMALL_ICONS
? MAX(text_height
, SMALL_ICON_HEIGHT
) + 4
1316 : text_height
+ MAX_ICON_HEIGHT
+ 8);
1319 void filer_set_sort_fn(FilerWindow
*filer_window
,
1320 int (*fn
)(const void *a
, const void *b
))
1322 if (filer_window
->sort_fn
== fn
)
1325 filer_window
->sort_fn
= fn
;
1326 collection_qsort(filer_window
->collection
,
1327 filer_window
->sort_fn
);
1330 void filer_style_set(FilerWindow
*filer_window
, DisplayStyle style
)
1332 if (filer_window
->display_style
== style
)
1335 filer_window
->display_style
= style
;
1339 collection_set_functions(filer_window
->collection
,
1340 draw_item_small
, test_point_small
);
1343 collection_set_functions(filer_window
->collection
,
1344 draw_item_full_info
, test_point_full_info
);
1347 collection_set_functions(filer_window
->collection
,
1348 draw_item_large
, test_point_large
);
1352 shrink_width(filer_window
);
1355 void filer_opendir(char *path
, gboolean panel
, Side panel_side
)
1357 GtkWidget
*hbox
, *scrollbar
, *collection
;
1358 FilerWindow
*filer_window
;
1359 GtkTargetEntry target_table
[] =
1361 {"text/uri-list", 0, TARGET_URI_LIST
},
1362 {"STRING", 0, TARGET_STRING
},
1365 filer_window
= g_new(FilerWindow
, 1);
1366 filer_window
->minibuffer
= NULL
;
1367 filer_window
->path
= pathdup(path
);
1368 filer_window
->had_cursor
= FALSE
;
1369 filer_window
->auto_select
= NULL
;
1371 filer_window
->directory
= g_fscache_lookup(dir_cache
,
1372 filer_window
->path
);
1373 if (!filer_window
->directory
)
1377 error
= g_strdup_printf("Directory '%s' not found.", path
);
1378 delayed_error("ROX-Filer", error
);
1380 g_free(filer_window
->path
);
1381 g_free(filer_window
);
1385 filer_window
->show_hidden
= FALSE
;
1386 filer_window
->panel
= panel
;
1387 filer_window
->panel_side
= panel_side
;
1388 filer_window
->temp_item_selected
= FALSE
;
1389 filer_window
->sort_fn
= sort_by_type
;
1390 filer_window
->flags
= (FilerFlags
) 0;
1391 filer_window
->display_style
= UNKNOWN_STYLE
;
1393 filer_window
->window
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
1394 gtk_window_set_title(GTK_WINDOW(filer_window
->window
),
1395 filer_window
->path
);
1397 collection
= collection_new(NULL
);
1398 gtk_object_set_data(GTK_OBJECT(collection
),
1399 "filer_window", filer_window
);
1400 filer_window
->collection
= COLLECTION(collection
);
1402 gtk_widget_add_events(filer_window
->window
, GDK_ENTER_NOTIFY
);
1403 gtk_signal_connect(GTK_OBJECT(filer_window
->window
),
1404 "enter-notify-event",
1405 GTK_SIGNAL_FUNC(pointer_in
), filer_window
);
1406 gtk_signal_connect(GTK_OBJECT(filer_window
->window
), "focus_in_event",
1407 GTK_SIGNAL_FUNC(focus_in
), filer_window
);
1408 gtk_signal_connect(GTK_OBJECT(filer_window
->window
), "focus_out_event",
1409 GTK_SIGNAL_FUNC(focus_out
), filer_window
);
1410 gtk_signal_connect(GTK_OBJECT(filer_window
->window
), "destroy",
1411 filer_window_destroyed
, filer_window
);
1413 gtk_signal_connect(GTK_OBJECT(filer_window
->collection
), "open_item",
1414 open_item
, filer_window
);
1415 gtk_signal_connect(GTK_OBJECT(collection
), "show_menu",
1416 show_menu
, filer_window
);
1417 gtk_signal_connect(GTK_OBJECT(collection
), "gain_selection",
1418 gain_selection
, filer_window
);
1419 gtk_signal_connect(GTK_OBJECT(collection
), "lose_selection",
1420 lose_selection
, filer_window
);
1421 gtk_signal_connect(GTK_OBJECT(collection
), "drag_selection",
1422 drag_selection
, filer_window
);
1423 gtk_signal_connect(GTK_OBJECT(collection
), "drag_data_get",
1424 drag_data_get
, filer_window
);
1425 gtk_signal_connect(GTK_OBJECT(collection
), "selection_clear_event",
1426 GTK_SIGNAL_FUNC(collection_lose_selection
), NULL
);
1427 gtk_signal_connect (GTK_OBJECT(collection
), "selection_get",
1428 GTK_SIGNAL_FUNC(selection_get
), NULL
);
1429 gtk_selection_add_targets(collection
, GDK_SELECTION_PRIMARY
,
1431 sizeof(target_table
) / sizeof(*target_table
));
1433 filer_style_set(filer_window
, LARGE_ICONS
);
1434 drag_set_dest(collection
);
1438 int swidth
, sheight
, iwidth
, iheight
;
1439 GtkWidget
*frame
, *win
= filer_window
->window
;
1441 gtk_window_set_wmclass(GTK_WINDOW(win
), "ROX-Panel",
1443 collection_set_panel(filer_window
->collection
, TRUE
);
1444 gtk_signal_connect(GTK_OBJECT(filer_window
->window
),
1446 GTK_SIGNAL_FUNC(filer_confirm_close
),
1449 gdk_window_get_size(GDK_ROOT_PARENT(), &swidth
, &sheight
);
1450 iwidth
= filer_window
->collection
->item_width
;
1451 iheight
= filer_window
->collection
->item_height
;
1453 if (panel_side
== TOP
|| panel_side
== BOTTOM
)
1455 int height
= iheight
+ PANEL_BORDER
;
1456 int y
= panel_side
== TOP
1458 : sheight
- height
- PANEL_BORDER
;
1460 gtk_widget_set_usize(collection
, swidth
, height
);
1461 gtk_widget_set_uposition(win
, 0, y
);
1465 int width
= iwidth
+ PANEL_BORDER
;
1466 int x
= panel_side
== LEFT
1468 : swidth
- width
- PANEL_BORDER
;
1470 gtk_widget_set_usize(collection
, width
, sheight
);
1471 gtk_widget_set_uposition(win
, x
, 0);
1474 frame
= gtk_frame_new(NULL
);
1475 gtk_frame_set_shadow_type(GTK_FRAME(frame
), GTK_SHADOW_OUT
);
1476 gtk_container_add(GTK_CONTAINER(frame
), collection
);
1477 gtk_container_add(GTK_CONTAINER(win
), frame
);
1479 gtk_widget_show_all(frame
);
1480 gtk_widget_realize(win
);
1481 if (override_redirect
)
1482 gdk_window_set_override_redirect(win
->window
, TRUE
);
1483 make_panel_window(win
->window
);
1489 gtk_signal_connect(GTK_OBJECT(collection
),
1491 GTK_SIGNAL_FUNC(key_press_event
), filer_window
);
1492 gtk_window_set_default_size(GTK_WINDOW(filer_window
->window
),
1493 filer_window
->display_style
== LARGE_ICONS
? 400 : 512,
1494 o_toolbar
? 220 : 200);
1496 hbox
= gtk_hbox_new(FALSE
, 0);
1497 gtk_container_add(GTK_CONTAINER(filer_window
->window
),
1500 vbox
= gtk_vbox_new(FALSE
, 0);
1501 gtk_box_pack_start(GTK_BOX(hbox
), vbox
, TRUE
, TRUE
, 0);
1507 toolbar
= create_toolbar(filer_window
);
1508 gtk_box_pack_start(GTK_BOX(vbox
), toolbar
,
1510 gtk_widget_show_all(toolbar
);
1513 gtk_box_pack_start(GTK_BOX(vbox
), collection
, TRUE
, TRUE
, 0);
1515 filer_window
->minibuffer
= create_minibuffer(filer_window
);
1516 gtk_box_pack_start(GTK_BOX(vbox
), filer_window
->minibuffer
,
1519 scrollbar
= gtk_vscrollbar_new(COLLECTION(collection
)->vadj
);
1520 gtk_box_pack_start(GTK_BOX(hbox
), scrollbar
, FALSE
, TRUE
, 0);
1521 gtk_accel_group_attach(filer_keys
,
1522 GTK_OBJECT(filer_window
->window
));
1523 gtk_window_set_focus(GTK_WINDOW(filer_window
->window
),
1526 gtk_widget_show(hbox
);
1527 gtk_widget_show(vbox
);
1528 gtk_widget_show(scrollbar
);
1529 gtk_widget_show(collection
);
1532 number_of_windows
++;
1533 gtk_widget_show(filer_window
->window
);
1534 attach(filer_window
);
1536 all_filer_windows
= g_list_prepend(all_filer_windows
, filer_window
);
1539 static GtkWidget
*create_toolbar(FilerWindow
*filer_window
)
1541 GtkWidget
*frame
, *box
;
1543 frame
= gtk_frame_new(NULL
);
1544 gtk_frame_set_shadow_type(GTK_FRAME(frame
), GTK_SHADOW_OUT
);
1546 box
= gtk_hbutton_box_new();
1547 gtk_button_box_set_child_size_default(16, 16);
1548 gtk_hbutton_box_set_spacing_default(2);
1549 gtk_button_box_set_layout(GTK_BUTTON_BOX(box
), GTK_BUTTONBOX_START
);
1550 gtk_container_add(GTK_CONTAINER(frame
), box
);
1552 add_button(GTK_CONTAINER(box
), TOOLBAR_UP_ICON
,
1553 GTK_SIGNAL_FUNC(toolbar_up_clicked
),
1554 filer_window
, "Change to parent directory");
1555 add_button(GTK_CONTAINER(box
), TOOLBAR_HOME_ICON
,
1556 GTK_SIGNAL_FUNC(toolbar_home_clicked
),
1557 filer_window
, "Change to home directory");
1558 add_button(GTK_CONTAINER(box
), TOOLBAR_REFRESH_ICON
,
1559 GTK_SIGNAL_FUNC(toolbar_refresh_clicked
),
1560 filer_window
, "Rescan directory contents");
1565 static void add_button(GtkContainer
*box
, int pixmap
,
1566 GtkSignalFunc cb
, gpointer data
,
1569 GtkWidget
*button
, *icon
;
1571 button
= gtk_button_new();
1572 GTK_WIDGET_UNSET_FLAGS(button
, GTK_CAN_FOCUS
);
1573 gtk_container_add(box
, button
);
1575 icon
= gtk_pixmap_new(default_pixmap
[pixmap
].pixmap
,
1576 default_pixmap
[pixmap
].mask
);
1577 gtk_container_add(GTK_CONTAINER(button
), icon
);
1578 gtk_signal_connect(GTK_OBJECT(button
), "clicked", cb
, data
);
1580 gtk_tooltips_set_tip(tooltips
, button
, tip
, NULL
);
1583 /* Build up some option widgets to go in the options dialog, but don't
1586 static GtkWidget
*create_options()
1590 vbox
= gtk_vbox_new(FALSE
, 0);
1591 gtk_container_set_border_width(GTK_CONTAINER(vbox
), 4);
1593 toggle_new_window_on_1
=
1594 gtk_check_button_new_with_label("New window on button 1 "
1596 gtk_box_pack_start(GTK_BOX(vbox
), toggle_new_window_on_1
,
1600 gtk_check_button_new_with_label("Menu on button 2 "
1602 gtk_box_pack_start(GTK_BOX(vbox
), toggle_menu_on_2
, FALSE
, TRUE
, 0);
1604 toggle_single_click
=
1605 gtk_check_button_new_with_label("Single-click nagivation");
1606 gtk_box_pack_start(GTK_BOX(vbox
), toggle_single_click
, FALSE
, TRUE
, 0);
1609 gtk_check_button_new_with_label("Show toolbar on new windows");
1610 gtk_box_pack_start(GTK_BOX(vbox
), toggle_toolbar
, FALSE
, TRUE
, 0);
1615 /* Reflect current state by changing the widgets in the options box */
1616 static void update_options()
1618 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle_new_window_on_1
),
1620 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle_menu_on_2
),
1621 collection_menu_button
== 2 ? 1 : 0);
1622 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle_single_click
),
1624 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle_toolbar
),
1628 /* Set current values by reading the states of the widgets in the options box */
1629 static void set_options()
1631 o_new_window_on_1
= gtk_toggle_button_get_active(
1632 GTK_TOGGLE_BUTTON(toggle_new_window_on_1
));
1634 collection_menu_button
= gtk_toggle_button_get_active(
1635 GTK_TOGGLE_BUTTON(toggle_menu_on_2
)) ? 2 : 3;
1637 o_single_click
= gtk_toggle_button_get_active(
1638 GTK_TOGGLE_BUTTON(toggle_single_click
));
1639 collection_single_click
= o_single_click
? TRUE
: FALSE
;
1641 o_toolbar
= gtk_toggle_button_get_active(
1642 GTK_TOGGLE_BUTTON(toggle_toolbar
));
1645 static void save_options()
1647 option_write("filer_new_window_on_1", o_new_window_on_1
? "1" : "0");
1648 option_write("filer_menu_on_2",
1649 collection_menu_button
== 2 ? "1" : "0");
1650 option_write("filer_single_click", o_single_click
? "1" : "0");
1651 option_write("filer_toolbar", o_toolbar
? "1" : "0");
1654 static char *filer_new_window_on_1(char *data
)
1656 o_new_window_on_1
= atoi(data
) != 0;
1660 static char *filer_menu_on_2(char *data
)
1662 collection_menu_button
= atoi(data
) != 0 ? 2 : 3;
1666 static char *filer_single_click(char *data
)
1668 o_single_click
= atoi(data
) != 0;
1669 collection_single_click
= o_single_click
? TRUE
: FALSE
;
1673 static char *filer_toolbar(char *data
)
1675 o_toolbar
= atoi(data
) != 0;
1679 /* Note that filer_window may not exist after this call. */
1680 void update_dir(FilerWindow
*filer_window
, gboolean warning
)
1682 if (may_rescan(filer_window
, warning
))
1683 dir_update(filer_window
->directory
, filer_window
->path
);
1686 void filer_set_hidden(FilerWindow
*filer_window
, gboolean hidden
)
1688 Directory
*dir
= filer_window
->directory
;
1690 if (filer_window
->show_hidden
== hidden
)
1693 filer_window
->show_hidden
= hidden
;
1695 g_fscache_data_ref(dir_cache
, dir
);
1696 detach(filer_window
);
1697 filer_window
->directory
= dir
;
1698 attach(filer_window
);
1701 /* Refresh the various caches even if we don't think we need to */
1702 void full_refresh(void)
1707 /* This path has been mounted/umounted - update all dirs */
1708 void filer_check_mounted(char *path
)
1710 GList
*next
= all_filer_windows
;
1717 FilerWindow
*filer_window
= (FilerWindow
*) next
->data
;
1721 if (strncmp(path
, filer_window
->path
, len
) == 0)
1723 char s
= filer_window
->path
[len
];
1725 if (s
== '/' || s
== '\0')
1726 update_dir(filer_window
, FALSE
);