1 /* Directory tree browser for the Midnight Commander
2 Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
3 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
5 Written: 1994, 1996 Janne Kukonlehto
7 1996, 1999 Miguel de Icaza
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 This module has been converted to be a widget.
25 The program load and saves the tree each time the tree widget is
26 created and destroyed. This is required for the future vfs layer,
27 it will be possible to have tree views over virtual file systems.
32 * \brief Source: directory tree browser
40 #include <sys/types.h>
42 #include "lib/global.h"
44 #include "lib/tty/tty.h"
46 #include "lib/tty/mouse.h"
47 #include "lib/tty/key.h"
48 #include "lib/vfs/mc-vfs/vfs.h"
49 #include "lib/fileloc.h"
50 #include "lib/strutil.h"
52 #include "wtools.h" /* message() */
58 #include "main-widgets.h" /* the_menubar */
59 #include "menu.h" /* menubar_visible */
60 #include "file.h" /* copy_dir_dir(), move_dir_dir(), erase_dir() */
61 #include "layout.h" /* command_prompt */
63 #include "treestore.h"
71 const global_keymap_t
*tree_map
;
73 #define tlines(t) (t->is_panel ? t->widget.lines - 2 - (show_mini_info ? 2 : 0) : t->widget.lines)
75 /* Use the color of the parent widget for the unselected entries */
76 #define TREE_NORMALC(h) (DLG_NORMALC (h))
78 /* Specifies the display mode: 1d or 2d */
79 static gboolean tree_navigation_flag
= FALSE
;
83 struct TreeStore
*store
;
84 tree_entry
*selected_ptr
; /* The selected directory */
85 char search_buffer
[256]; /* Current search string */
86 tree_entry
**tree_shown
; /* Entries currently on screen */
87 int is_panel
; /* panel or plain widget flag */
88 int active
; /* if it's currently selected */
89 int searching
; /* Are we on searching mode? */
90 int topdiff
; /* The difference between the topmost
91 shown and the selected */
95 static void tree_rescan (void *data
);
98 back_ptr (tree_entry
*ptr
, int *count
)
102 while (ptr
&& ptr
->prev
&& i
< *count
){
111 forw_ptr (tree_entry
*ptr
, int *count
)
115 while (ptr
&& ptr
->next
&& i
< *count
){
124 remove_callback (tree_entry
*entry
, void *data
)
128 if (tree
->selected_ptr
== entry
){
129 if (tree
->selected_ptr
->next
)
130 tree
->selected_ptr
= tree
->selected_ptr
->next
;
132 tree
->selected_ptr
= tree
->selected_ptr
->prev
;
136 /* Save the ~/.mc/Tree file */
138 save_tree (WTree
*tree
)
144 error
= tree_store_save ();
148 tree_name
= g_build_filename (home_dir
, MC_USERCONF_DIR
,
149 MC_TREESTORE_FILE
, (char *) NULL
);
150 fprintf (stderr
, _("Cannot open the %s file for writing:\n%s\n"), tree_name
,
151 unix_error_string (error
));
157 tree_remove_entry (WTree
*tree
, char *name
)
160 tree_store_remove_entry (name
);
164 tree_destroy (WTree
*tree
)
166 tree_store_remove_entry_remove_hook (remove_callback
);
169 g_free (tree
->tree_shown
);
170 tree
->tree_shown
= 0;
171 tree
->selected_ptr
= NULL
;
174 /* Loads the .mc.tree file */
176 load_tree (WTree
*tree
)
180 tree
->selected_ptr
= tree
->store
->tree_first
;
181 tree_chdir (tree
, home_dir
);
185 tree_show_mini_info (WTree
*tree
, int tree_lines
, int tree_cols
)
187 Dlg_head
*h
= tree
->widget
.parent
;
198 tty_draw_hline (tree
->widget
.y
+ line
, tree
->widget
.x
+ 1, ' ', tree_cols
);
199 widget_move (&tree
->widget
, line
, 1);
201 if (tree
->searching
){
202 /* Show search string */
203 tty_setcolor (TREE_NORMALC (h
));
204 tty_setcolor (DLG_FOCUSC (h
));
205 tty_print_char (PATH_SEP
);
207 tty_print_string (str_fit_to_term (tree
->search_buffer
,
208 tree_cols
- 2, J_LEFT_FIT
));
209 tty_print_char (' ');
210 tty_setcolor (DLG_FOCUSC (h
));
212 /* Show full name of selected directory */
213 tty_print_string (str_fit_to_term (tree
->selected_ptr
->name
,
214 tree_cols
, J_LEFT_FIT
));
219 show_tree (WTree
*tree
)
221 Dlg_head
*h
= tree
->widget
.parent
;
223 int i
, j
, topsublevel
;
225 int tree_lines
, tree_cols
;
229 tree_lines
= tlines (tree
);
230 tree_cols
= tree
->widget
.cols
;
232 tty_setcolor (TREE_NORMALC (h
));
233 widget_move ((Widget
*)tree
, y
, x
);
239 g_free (tree
->tree_shown
);
240 tree
->tree_shown
= g_new0 (tree_entry
*, tree_lines
);
242 if (tree
->store
->tree_first
)
243 topsublevel
= tree
->store
->tree_first
->sublevel
;
246 if (!tree
->selected_ptr
){
247 tree
->selected_ptr
= tree
->store
->tree_first
;
250 current
= tree
->selected_ptr
;
252 /* Calculate the directory which is to be shown on the topmost line */
253 if (!tree_navigation_flag
)
254 current
= back_ptr (current
, &tree
->topdiff
);
257 while (current
->prev
&& i
< tree
->topdiff
){
258 current
= current
->prev
;
259 if (current
->sublevel
< tree
->selected_ptr
->sublevel
){
260 if (strncmp (current
->name
, tree
->selected_ptr
->name
,
261 strlen (current
->name
)) == 0)
263 } else if (current
->sublevel
== tree
->selected_ptr
->sublevel
){
264 for (j
= strlen (current
->name
) - 1; current
->name
[j
] != PATH_SEP
; j
--);
265 if (strncmp (current
->name
, tree
->selected_ptr
->name
, j
) == 0)
267 } else if (current
->sublevel
== tree
->selected_ptr
->sublevel
+ 1
268 && strlen (tree
->selected_ptr
->name
) > 1){
269 if (strncmp (current
->name
, tree
->selected_ptr
->name
,
270 strlen (tree
->selected_ptr
->name
)) == 0)
277 /* Loop for every line */
278 for (i
= 0; i
< tree_lines
; i
++){
279 /* Move to the beginning of the line */
280 tty_draw_hline (tree
->widget
.y
+ y
+ i
, tree
->widget
.x
+ x
, ' ', tree_cols
);
285 tree
->tree_shown
[i
] = current
;
286 if (current
->sublevel
== topsublevel
){
288 /* Top level directory */
289 if (tree
->active
&& current
== tree
->selected_ptr
) {
290 if (!tty_use_colors () && !tree
->is_panel
)
291 tty_setcolor (MARKED_COLOR
);
293 tty_setcolor (SELECTED_COLOR
);
297 tty_print_string (str_fit_to_term (current
->name
, tree_cols
- 6, J_LEFT_FIT
));
299 /* Sub level directory */
301 tty_set_alt_charset (TRUE
);
302 /* Output branch parts */
303 for (j
= 0; j
< current
->sublevel
- topsublevel
- 1; j
++){
304 if (tree_cols
- 8 - 3 * j
< 9)
306 tty_print_char (' ');
307 if (current
->submask
& (1 << (j
+ topsublevel
+ 1)))
308 tty_print_char (ACS_VLINE
);
310 tty_print_char (' ');
311 tty_print_char (' ');
313 tty_print_char (' '); j
++;
314 if (!current
->next
|| !(current
->next
->submask
& (1 << current
->sublevel
)))
315 tty_print_char (ACS_LLCORNER
);
317 tty_print_char (ACS_LTEE
);
318 tty_print_char (ACS_HLINE
);
319 tty_set_alt_charset (FALSE
);
321 if (tree
->active
&& current
== tree
->selected_ptr
) {
322 /* Selected directory -> change color */
323 if (!tty_use_colors () && !tree
->is_panel
)
324 tty_setcolor (MARKED_COLOR
);
326 tty_setcolor (SELECTED_COLOR
);
330 tty_print_char (' ');
331 tty_print_string (str_fit_to_term (current
->subname
,
332 tree_cols
- 2 - 4 - 3 * j
, J_LEFT_FIT
));
334 tty_print_char (' ');
336 /* Return to normal color */
337 tty_setcolor (TREE_NORMALC (h
));
339 /* Calculate the next value for current */
340 current
= current
->next
;
341 if (tree_navigation_flag
){
343 if (current
->sublevel
< tree
->selected_ptr
->sublevel
){
344 if (strncmp (current
->name
, tree
->selected_ptr
->name
,
345 strlen (current
->name
)) == 0)
347 } else if (current
->sublevel
== tree
->selected_ptr
->sublevel
){
348 for (j
= strlen (current
->name
) - 1; current
->name
[j
] != PATH_SEP
; j
--);
349 if (strncmp (current
->name
,tree
->selected_ptr
->name
,j
)== 0)
351 } else if (current
->sublevel
== tree
->selected_ptr
->sublevel
+1
352 && strlen (tree
->selected_ptr
->name
) > 1){
353 if (strncmp (current
->name
, tree
->selected_ptr
->name
,
354 strlen (tree
->selected_ptr
->name
)) == 0)
357 current
= current
->next
;
361 tree_show_mini_info (tree
, tree_lines
, tree_cols
);
365 tree_check_focus (WTree
*tree
)
367 if (tree
->topdiff
< 3)
369 else if (tree
->topdiff
>= tlines (tree
) - 3)
370 tree
->topdiff
= tlines (tree
) - 3 - 1;
374 tree_move_backward (WTree
*tree
, int i
)
376 if (!tree_navigation_flag
)
377 tree
->selected_ptr
= back_ptr (tree
->selected_ptr
, &i
);
382 current
= tree
->selected_ptr
;
383 while (j
< i
&& current
->prev
384 && current
->prev
->sublevel
>= tree
->selected_ptr
->sublevel
){
385 current
= current
->prev
;
386 if (current
->sublevel
== tree
->selected_ptr
->sublevel
){
387 tree
->selected_ptr
= current
;
395 tree_check_focus (tree
);
399 tree_move_forward (WTree
*tree
, int i
)
401 if (!tree_navigation_flag
)
402 tree
->selected_ptr
= forw_ptr (tree
->selected_ptr
, &i
);
407 current
= tree
->selected_ptr
;
408 while (j
< i
&& current
->next
409 && current
->next
->sublevel
>= tree
->selected_ptr
->sublevel
){
410 current
= current
->next
;
411 if (current
->sublevel
== tree
->selected_ptr
->sublevel
){
412 tree
->selected_ptr
= current
;
420 tree_check_focus (tree
);
424 tree_move_to_child (WTree
*tree
)
428 /* Do we have a starting point? */
429 if (!tree
->selected_ptr
)
431 /* Take the next entry */
432 current
= tree
->selected_ptr
->next
;
433 /* Is it the child of the selected entry */
434 if (current
&& current
->sublevel
> tree
->selected_ptr
->sublevel
){
435 /* Yes -> select this entry */
436 tree
->selected_ptr
= current
;
438 tree_check_focus (tree
);
440 /* No -> rescan and try again */
442 current
= tree
->selected_ptr
->next
;
443 if (current
&& current
->sublevel
> tree
->selected_ptr
->sublevel
){
444 tree
->selected_ptr
= current
;
446 tree_check_focus (tree
);
452 tree_move_to_parent (WTree
*tree
)
457 if (!tree
->selected_ptr
)
460 old
= tree
->selected_ptr
;
461 current
= tree
->selected_ptr
->prev
;
462 while (current
&& current
->sublevel
>= tree
->selected_ptr
->sublevel
){
463 current
= current
->prev
;
467 current
= tree
->store
->tree_first
;
468 tree
->selected_ptr
= current
;
469 tree_check_focus (tree
);
470 return tree
->selected_ptr
!= old
;
474 tree_move_to_top (WTree
*tree
)
476 tree
->selected_ptr
= tree
->store
->tree_first
;
481 tree_move_to_bottom (WTree
*tree
)
483 tree
->selected_ptr
= tree
->store
->tree_last
;
484 tree
->topdiff
= tlines (tree
) - 3 - 1;
487 /* Handle mouse click */
489 tree_event (WTree
*tree
, int y
)
491 if (tree
->tree_shown
[y
]){
492 tree
->selected_ptr
= tree
->tree_shown
[y
];
499 tree_chdir_sel (WTree
*tree
)
506 if (do_cd (tree
->selected_ptr
->name
, cd_exact
))
507 select_item (current_panel
);
509 message (D_ERROR
, MSG_ERROR
, _(" Cannot chdir to \"%s\" \n %s "),
510 tree
->selected_ptr
->name
, unix_error_string (errno
));
517 maybe_chdir (WTree
*tree
)
519 if (xtree_mode
&& tree
->is_panel
&& is_idle ())
520 tree_chdir_sel (tree
);
525 event_callback (Gpm_Event
*event
, void *data
)
529 /* rest of the upper frame, the menu is invisible - call menu */
530 if (tree
->is_panel
&& (event
->type
& GPM_DOWN
)
531 && event
->y
== 1 && !menubar_visible
) {
532 event
->x
+= tree
->widget
.x
;
533 return the_menubar
->widget
.mouse (event
, the_menubar
);
536 if (!(event
->type
& GPM_UP
))
548 tree_move_backward (tree
, tlines (tree
) - 1);
550 } else if (event
->y
>= tlines (tree
)){
551 tree_move_forward (tree
, tlines (tree
) - 1);
554 tree_event (tree
, event
->y
);
555 if ((event
->type
& (GPM_UP
|GPM_DOUBLE
)) == (GPM_UP
|GPM_DOUBLE
)){
556 tree_chdir_sel (tree
);
562 /* Search tree for text */
564 search_tree (WTree
*tree
, char *text
)
572 current
= tree
->selected_ptr
;
574 while (!wrapped
|| current
!= tree
->selected_ptr
){
575 if (strncmp (current
->subname
, text
, len
) == 0){
576 tree
->selected_ptr
= current
;
580 current
= current
->next
;
582 current
= tree
->store
->tree_first
;
587 tree_check_focus (tree
);
592 tree_do_search (WTree
*tree
, int key
)
596 l
= strlen (tree
->search_buffer
);
597 if ((l
!= 0) && (key
== KEY_BACKSPACE
))
598 tree
->search_buffer
[--l
] = '\0';
599 else if (key
&& l
< sizeof (tree
->search_buffer
)){
600 tree
->search_buffer
[l
] = key
;
601 tree
->search_buffer
[++l
] = '\0';
604 if (!search_tree (tree
, tree
->search_buffer
))
605 tree
->search_buffer
[--l
] = 0;
612 tree_rescan (void *data
)
614 char old_dir
[MC_MAXPATHLEN
];
617 if (!tree
->selected_ptr
|| !mc_get_current_wd (old_dir
, MC_MAXPATHLEN
) ||
618 mc_chdir (tree
->selected_ptr
->name
))
621 tree_store_rescan (tree
->selected_ptr
->name
);
626 tree_forget (void *data
)
629 if (tree
->selected_ptr
)
630 tree_remove_entry (tree
, tree
->selected_ptr
->name
);
634 tree_copy (WTree
*tree
, const char *default_dest
)
636 char msg
[BUF_MEDIUM
];
639 if (tree
->selected_ptr
== NULL
)
642 g_snprintf (msg
, sizeof (msg
), _("Copy \"%s\" directory to:"),
643 str_trunc (tree
->selected_ptr
->name
, 50));
644 dest
= input_expand_dialog (Q_("DialogTitle|Copy"),
645 msg
, MC_HISTORY_FM_TREE_COPY
, default_dest
);
647 if (dest
!= NULL
&& *dest
!= '\0') {
649 FileOpTotalContext
*tctx
;
651 ctx
= file_op_context_new (OP_COPY
);
652 tctx
= file_op_total_context_new ();
653 file_op_context_create_ui (ctx
, FALSE
, FILEGUI_DIALOG_MULTI_ITEM
);
654 tctx
->ask_overwrite
= FALSE
;
655 tctx
->is_toplevel_file
= FALSE
;
656 copy_dir_dir (tctx
, ctx
, tree
->selected_ptr
->name
, dest
, TRUE
, FALSE
, FALSE
, NULL
);
657 file_op_total_context_destroy (tctx
);
658 file_op_context_destroy (ctx
);
665 tree_move (WTree
*tree
, const char *default_dest
)
667 char msg
[BUF_MEDIUM
];
671 FileOpTotalContext
*tctx
;
673 if (tree
->selected_ptr
== NULL
)
676 g_snprintf (msg
, sizeof (msg
), _("Move \"%s\" directory to:"),
677 str_trunc (tree
->selected_ptr
->name
, 50));
678 dest
= input_expand_dialog (Q_("DialogTitle|Move"), msg
, MC_HISTORY_FM_TREE_MOVE
, default_dest
);
680 if (dest
== NULL
|| *dest
== '\0') {
685 if (stat (dest
, &buf
)){
686 message (D_ERROR
, MSG_ERROR
, _(" Cannot stat the destination \n %s "),
687 unix_error_string (errno
));
692 if (!S_ISDIR (buf
.st_mode
)){
693 file_error (_(" Destination \"%s\" must be a directory \n %s "),
699 ctx
= file_op_context_new (OP_MOVE
);
700 tctx
= file_op_total_context_new ();
701 file_op_context_create_ui (ctx
, FALSE
, FILEGUI_DIALOG_ONE_ITEM
);
702 move_dir_dir (tctx
, ctx
, tree
->selected_ptr
->name
, dest
);
703 file_op_total_context_destroy (tctx
);
704 file_op_context_destroy (ctx
);
711 tree_mkdir (WTree
*tree
)
713 char old_dir
[MC_MAXPATHLEN
];
715 if (!tree
->selected_ptr
)
717 if (!mc_get_current_wd (old_dir
, MC_MAXPATHLEN
))
719 if (chdir (tree
->selected_ptr
->name
))
730 tree_rmdir (void *data
)
734 FileOpTotalContext
*tctx
;
736 if (!tree
->selected_ptr
)
739 if (confirm_delete
) {
744 g_strdup_printf (_(" Delete %s? "),
745 tree
->selected_ptr
->name
);
747 query_dialog (Q_("DialogTitle|Delete"), buf
, D_ERROR
, 2, _("&Yes"), _("&No"));
753 ctx
= file_op_context_new (OP_DELETE
);
754 tctx
= file_op_total_context_new ();
756 file_op_context_create_ui (ctx
, FALSE
, FILEGUI_DIALOG_ONE_ITEM
);
757 if (erase_dir (tctx
, ctx
, tree
->selected_ptr
->name
) == FILE_CONT
)
759 file_op_total_context_destroy (tctx
);
760 file_op_context_destroy (ctx
);
764 tree_move_up (WTree
*tree
)
766 tree_move_backward (tree
, 1);
772 tree_move_down (WTree
*tree
)
774 tree_move_forward (tree
, 1);
780 tree_move_home (WTree
*tree
)
782 tree_move_to_top (tree
);
788 tree_move_end (WTree
*tree
)
790 tree_move_to_bottom (tree
);
796 tree_move_pgup (WTree
*tree
)
798 tree_move_backward (tree
, tlines (tree
) - 1);
804 tree_move_pgdn (WTree
*tree
)
806 tree_move_forward (tree
, tlines (tree
) - 1);
812 tree_move_left (WTree
*tree
)
816 if (tree_navigation_flag
) {
817 v
= tree_move_to_parent (tree
);
826 tree_move_right (WTree
*tree
)
830 if (tree_navigation_flag
) {
831 tree_move_to_child (tree
);
841 tree_start_search (WTree
*tree
)
845 if (tree
->searching
) {
846 if (tree
->selected_ptr
== tree
->store
->tree_last
)
847 tree_move_to_top (tree
);
849 /* set navigation mode temporarily to 'Static' because in
850 * dynamic navigation mode tree_move_forward will not move
851 * to a lower sublevel if necessary (sequent searches must
852 * start with the directory followed the last found directory)
854 i
= tree_navigation_flag
;
855 tree_navigation_flag
= 0;
856 tree_move_forward (tree
, 1);
857 tree_navigation_flag
= i
;
859 tree_do_search (tree
, 0);
862 tree
->search_buffer
[0] = 0;
867 tree_toggle_navig (WTree
*tree
)
869 tree_navigation_flag
= !tree_navigation_flag
;
870 buttonbar_set_label (find_buttonbar (tree
->widget
.parent
), 4,
871 tree_navigation_flag
? Q_("ButtonBar|Static")
872 : Q_("ButtonBar|Dynamc"),
873 tree_map
, (Widget
*) tree
);
877 tree_execute_cmd (WTree
*tree
, unsigned long command
)
879 cb_ret_t res
= MSG_HANDLED
;
881 if (command
!= CK_TreeStartSearch
)
886 interactive_display (NULL
, "[Directory Tree]");
891 case CK_TreeToggleNav
:
892 tree_toggle_navig (tree
);
895 tree_copy (tree
, "");
898 tree_move (tree
, "");
903 case CK_TreeMoveDown
:
904 tree_move_down (tree
);
906 case CK_TreeMoveHome
:
907 tree_move_home (tree
);
910 tree_move_end (tree
);
912 case CK_TreeMovePgUp
:
913 tree_move_pgup (tree
);
915 case CK_TreeMovePgDn
:
916 tree_move_pgdn (tree
);
919 tree_chdir_sel (tree
);
924 case CK_TreeStartSearch
:
925 tree_start_search (tree
);
931 res
= MSG_NOT_HANDLED
;
940 tree_key (WTree
*tree
, int key
)
944 for (i
= 0; tree_map
[i
].key
!= 0; i
++)
945 if (key
== tree_map
[i
].key
)
946 switch (tree_map
[i
].command
) {
947 case CK_TreeMoveLeft
:
948 return tree_move_left (tree
) ? MSG_HANDLED
: MSG_NOT_HANDLED
;
949 case CK_TreeMoveRight
:
950 return tree_move_right (tree
) ? MSG_HANDLED
: MSG_NOT_HANDLED
;
952 tree_execute_cmd (tree
, tree_map
[i
].command
);
956 if (is_abort_char (key
)) {
957 if (tree
->is_panel
) {
960 return MSG_HANDLED
; /* eat abort char */
962 /* modal tree dialog: let upper layer see the
963 abort character and close the dialog */
964 return MSG_NOT_HANDLED
;
967 /* Do not eat characters not meant for the tree below ' ' (e.g. C-l). */
968 if ((key
>= ' ' && key
<= 255) || key
== KEY_BACKSPACE
) {
969 if (tree
->searching
){
970 tree_do_search (tree
, key
);
975 if (!command_prompt
) {
976 tree_start_search (tree
);
977 tree_do_search (tree
, key
);
980 return tree
->is_panel
? MSG_HANDLED
: MSG_NOT_HANDLED
;
983 return MSG_NOT_HANDLED
;
987 tree_frame (Dlg_head
*h
, WTree
*tree
)
989 tty_setcolor (NORMAL_COLOR
);
990 widget_erase ((Widget
*) tree
);
991 if (tree
->is_panel
) {
992 draw_box (h
, tree
->widget
.y
, tree
->widget
.x
, tree
->widget
.lines
,
993 tree
->widget
.cols
, FALSE
);
996 tty_draw_hline (tree
->widget
.y
+ tlines (tree
) + 1,
998 ACS_HLINE
, tree
->widget
.cols
- 2);
1003 tree_callback (Widget
*w
, widget_msg_t msg
, int parm
)
1005 WTree
*tree
= (WTree
*) w
;
1006 Dlg_head
*h
= tree
->widget
.parent
;
1007 WButtonBar
*b
= find_buttonbar (h
);
1011 tree_frame (h
, tree
);
1017 buttonbar_set_label (b
, 1, Q_("ButtonBar|Help"), tree_map
, (Widget
*) tree
);
1018 buttonbar_set_label (b
, 2, Q_("ButtonBar|Rescan"), tree_map
, (Widget
*) tree
);
1019 buttonbar_set_label (b
, 3, Q_("ButtonBar|Forget"), tree_map
, (Widget
*) tree
);
1020 buttonbar_set_label (b
, 4, tree_navigation_flag
? Q_("ButtonBar|Static")
1021 : Q_("ButtonBar|Dynamc"),
1022 tree_map
, (Widget
*) tree
);
1023 buttonbar_set_label (b
, 5, Q_("ButtonBar|Copy"), tree_map
, (Widget
*) tree
);
1024 buttonbar_set_label (b
, 6, Q_("ButtonBar|RenMov"), tree_map
, (Widget
*) tree
);
1026 /* FIXME: mkdir is currently defunct */
1027 buttonbar_set_label (b
, 7, Q_("ButtonBar|Mkdir"), tree_map
, (Widget
*) tree
);
1029 buttonbar_clear_label (b
, 7, (Widget
*) tree
);
1031 buttonbar_set_label (b
, 8, Q_("ButtonBar|Rmdir"), tree_map
, (Widget
*) tree
);
1032 buttonbar_redraw (b
);
1034 /* FIXME: Should find a better way of only displaying the
1035 currently selected item */
1039 /* FIXME: Should find a better way of changing the color of the
1042 case WIDGET_UNFOCUS
:
1048 return tree_key (tree
, parm
);
1050 case WIDGET_COMMAND
:
1051 /* command from buttonbar */
1052 return tree_execute_cmd (tree
, parm
);
1054 case WIDGET_DESTROY
:
1055 tree_destroy (tree
);
1059 return default_proc (msg
, parm
);
1064 tree_new (int is_panel
, int y
, int x
, int lines
, int cols
)
1066 WTree
*tree
= g_new (WTree
, 1);
1068 init_widget (&tree
->widget
, y
, x
, lines
, cols
,
1069 tree_callback
, event_callback
);
1070 tree
->is_panel
= is_panel
;
1071 tree
->selected_ptr
= 0;
1073 tree
->store
= tree_store_get ();
1074 tree_store_add_entry_remove_hook (remove_callback
, tree
);
1075 tree
->tree_shown
= 0;
1076 tree
->search_buffer
[0] = 0;
1077 tree
->topdiff
= tree
->widget
.lines
/ 2;
1078 tree
->searching
= 0;
1081 /* We do not want to keep the cursor */
1082 widget_want_cursor (tree
->widget
, 0);
1088 tree_chdir (WTree
*tree
, const char *dir
)
1090 tree_entry
*current
;
1092 current
= tree_store_whereis (dir
);
1094 if (current
!= NULL
) {
1095 tree
->selected_ptr
= current
;
1096 tree_check_focus (tree
);
1100 /* Return name of the currently selected entry */
1102 tree_selected_name (const WTree
*tree
)
1104 return tree
->selected_ptr
->name
;
1108 sync_tree (const char *path
)
1110 tree_chdir (the_tree
, path
);
1114 find_tree (struct Dlg_head
*h
)
1116 return (WTree
*) find_widget_type (h
, tree_callback
);