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"
70 const global_keymap_t
*tree_map
;
72 #define tlines(t) (t->is_panel ? t->widget.lines - 2 - (show_mini_info ? 2 : 0) : t->widget.lines)
74 /* Use the color of the parent widget for the unselected entries */
75 #define TREE_NORMALC(h) (DLG_NORMALC (h))
76 #define TREE_CURRENTC(h) (DLG_FOCUSC (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
;
200 /* Show search string */
201 tty_setcolor (INPUT_COLOR
);
202 tty_draw_hline (tree
->widget
.y
+ line
, tree
->widget
.x
+ 1, ' ', tree_cols
);
203 widget_move (&tree
->widget
, line
, 1);
204 tty_print_char (PATH_SEP
);
205 tty_print_string (str_fit_to_term (tree
->search_buffer
, tree_cols
- 2, J_LEFT_FIT
));
206 tty_print_char (' ');
210 /* Show full name of selected directory */
211 tty_setcolor (tree
->is_panel
? NORMAL_COLOR
: TREE_NORMALC (h
));
212 tty_draw_hline (tree
->widget
.y
+ line
, tree
->widget
.x
+ 1, ' ', tree_cols
);
213 widget_move (&tree
->widget
, line
, 1);
214 tty_print_string (str_fit_to_term (tree
->selected_ptr
->name
, 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 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
++)
280 tty_setcolor (tree
->is_panel
? NORMAL_COLOR
: TREE_NORMALC (h
));
282 /* Move to the beginning of the line */
283 tty_draw_hline (tree
->widget
.y
+ y
+ i
, tree
->widget
.x
+ x
, ' ', tree_cols
);
289 tty_setcolor (tree
->active
&& current
== tree
->selected_ptr
290 ? SELECTED_COLOR
: NORMAL_COLOR
);
292 tty_setcolor (current
== tree
->selected_ptr
? TREE_CURRENTC (h
) : TREE_NORMALC (h
));
294 tree
->tree_shown
[i
] = current
;
295 if (current
->sublevel
== topsublevel
)
298 tty_print_string (str_fit_to_term (current
->name
, tree_cols
- 6, J_LEFT_FIT
));
302 /* Sub level directory */
303 tty_set_alt_charset (TRUE
);
305 /* Output branch parts */
306 for (j
= 0; j
< current
->sublevel
- topsublevel
- 1; j
++)
308 if (tree_cols
- 8 - 3 * j
< 9)
310 tty_print_char (' ');
311 if (current
->submask
& (1 << (j
+ topsublevel
+ 1)))
312 tty_print_char (ACS_VLINE
);
314 tty_print_char (' ');
315 tty_print_char (' ');
317 tty_print_char (' ');
319 if (!current
->next
|| !(current
->next
->submask
& (1 << current
->sublevel
)))
320 tty_print_char (ACS_LLCORNER
);
322 tty_print_char (ACS_LTEE
);
323 tty_print_char (ACS_HLINE
);
324 tty_set_alt_charset (FALSE
);
327 tty_print_char (' ');
328 tty_print_string (str_fit_to_term (current
->subname
,
329 tree_cols
- 2 - 4 - 3 * j
, J_LEFT_FIT
));
331 tty_print_char (' ');
334 /* Calculate the next value for current */
335 current
= current
->next
;
336 if (tree_navigation_flag
)
338 while (current
!= NULL
)
340 if (current
->sublevel
< tree
->selected_ptr
->sublevel
)
342 if (strncmp (current
->name
, tree
->selected_ptr
->name
,
343 strlen (current
->name
)) == 0)
346 else if (current
->sublevel
== tree
->selected_ptr
->sublevel
)
348 for (j
= strlen (current
->name
) - 1; current
->name
[j
] != PATH_SEP
; j
--)
350 if (strncmp (current
->name
, tree
->selected_ptr
->name
, j
) == 0)
353 else if (current
->sublevel
== tree
->selected_ptr
->sublevel
+ 1
354 && strlen (tree
->selected_ptr
->name
) > 1)
356 if (strncmp (current
->name
, tree
->selected_ptr
->name
,
357 strlen (tree
->selected_ptr
->name
)) == 0)
360 current
= current
->next
;
365 tree_show_mini_info (tree
, tree_lines
, tree_cols
);
369 tree_check_focus (WTree
*tree
)
371 if (tree
->topdiff
< 3)
373 else if (tree
->topdiff
>= tlines (tree
) - 3)
374 tree
->topdiff
= tlines (tree
) - 3 - 1;
378 tree_move_backward (WTree
*tree
, int i
)
380 if (!tree_navigation_flag
)
381 tree
->selected_ptr
= back_ptr (tree
->selected_ptr
, &i
);
386 current
= tree
->selected_ptr
;
387 while (j
< i
&& current
->prev
388 && current
->prev
->sublevel
>= tree
->selected_ptr
->sublevel
){
389 current
= current
->prev
;
390 if (current
->sublevel
== tree
->selected_ptr
->sublevel
){
391 tree
->selected_ptr
= current
;
399 tree_check_focus (tree
);
403 tree_move_forward (WTree
*tree
, int i
)
405 if (!tree_navigation_flag
)
406 tree
->selected_ptr
= forw_ptr (tree
->selected_ptr
, &i
);
411 current
= tree
->selected_ptr
;
412 while (j
< i
&& current
->next
413 && current
->next
->sublevel
>= tree
->selected_ptr
->sublevel
){
414 current
= current
->next
;
415 if (current
->sublevel
== tree
->selected_ptr
->sublevel
){
416 tree
->selected_ptr
= current
;
424 tree_check_focus (tree
);
428 tree_move_to_child (WTree
*tree
)
432 /* Do we have a starting point? */
433 if (!tree
->selected_ptr
)
435 /* Take the next entry */
436 current
= tree
->selected_ptr
->next
;
437 /* Is it the child of the selected entry */
438 if (current
&& current
->sublevel
> tree
->selected_ptr
->sublevel
){
439 /* Yes -> select this entry */
440 tree
->selected_ptr
= current
;
442 tree_check_focus (tree
);
444 /* No -> rescan and try again */
446 current
= tree
->selected_ptr
->next
;
447 if (current
&& current
->sublevel
> tree
->selected_ptr
->sublevel
){
448 tree
->selected_ptr
= current
;
450 tree_check_focus (tree
);
456 tree_move_to_parent (WTree
*tree
)
461 if (!tree
->selected_ptr
)
464 old
= tree
->selected_ptr
;
465 current
= tree
->selected_ptr
->prev
;
466 while (current
&& current
->sublevel
>= tree
->selected_ptr
->sublevel
){
467 current
= current
->prev
;
471 current
= tree
->store
->tree_first
;
472 tree
->selected_ptr
= current
;
473 tree_check_focus (tree
);
474 return tree
->selected_ptr
!= old
;
478 tree_move_to_top (WTree
*tree
)
480 tree
->selected_ptr
= tree
->store
->tree_first
;
485 tree_move_to_bottom (WTree
*tree
)
487 tree
->selected_ptr
= tree
->store
->tree_last
;
488 tree
->topdiff
= tlines (tree
) - 3 - 1;
491 /* Handle mouse click */
493 tree_event (WTree
*tree
, int y
)
495 if (tree
->tree_shown
[y
]){
496 tree
->selected_ptr
= tree
->tree_shown
[y
];
503 tree_chdir_sel (WTree
*tree
)
510 if (do_cd (tree
->selected_ptr
->name
, cd_exact
))
511 select_item (current_panel
);
513 message (D_ERROR
, MSG_ERROR
, _(" Cannot chdir to \"%s\" \n %s "),
514 tree
->selected_ptr
->name
, unix_error_string (errno
));
521 maybe_chdir (WTree
*tree
)
523 if (xtree_mode
&& tree
->is_panel
&& is_idle ())
524 tree_chdir_sel (tree
);
529 event_callback (Gpm_Event
*event
, void *data
)
533 /* rest of the upper frame, the menu is invisible - call menu */
534 if (tree
->is_panel
&& (event
->type
& GPM_DOWN
)
535 && event
->y
== 1 && !menubar_visible
) {
536 event
->x
+= tree
->widget
.x
;
537 return the_menubar
->widget
.mouse (event
, the_menubar
);
540 if (!(event
->type
& GPM_UP
))
552 tree_move_backward (tree
, tlines (tree
) - 1);
554 } else if (event
->y
>= tlines (tree
)){
555 tree_move_forward (tree
, tlines (tree
) - 1);
558 tree_event (tree
, event
->y
);
559 if ((event
->type
& (GPM_UP
|GPM_DOUBLE
)) == (GPM_UP
|GPM_DOUBLE
)){
560 tree_chdir_sel (tree
);
566 /* Search tree for text */
568 search_tree (WTree
*tree
, char *text
)
576 current
= tree
->selected_ptr
;
578 while (!wrapped
|| current
!= tree
->selected_ptr
){
579 if (strncmp (current
->subname
, text
, len
) == 0){
580 tree
->selected_ptr
= current
;
584 current
= current
->next
;
586 current
= tree
->store
->tree_first
;
591 tree_check_focus (tree
);
596 tree_do_search (WTree
*tree
, int key
)
600 l
= strlen (tree
->search_buffer
);
601 if ((l
!= 0) && (key
== KEY_BACKSPACE
))
602 tree
->search_buffer
[--l
] = '\0';
603 else if (key
&& l
< sizeof (tree
->search_buffer
)){
604 tree
->search_buffer
[l
] = key
;
605 tree
->search_buffer
[++l
] = '\0';
608 if (!search_tree (tree
, tree
->search_buffer
))
609 tree
->search_buffer
[--l
] = 0;
616 tree_rescan (void *data
)
618 char old_dir
[MC_MAXPATHLEN
];
621 if (!tree
->selected_ptr
|| !mc_get_current_wd (old_dir
, MC_MAXPATHLEN
) ||
622 mc_chdir (tree
->selected_ptr
->name
))
625 tree_store_rescan (tree
->selected_ptr
->name
);
630 tree_forget (void *data
)
633 if (tree
->selected_ptr
)
634 tree_remove_entry (tree
, tree
->selected_ptr
->name
);
638 tree_copy (WTree
*tree
, const char *default_dest
)
640 char msg
[BUF_MEDIUM
];
646 if (tree
->selected_ptr
== NULL
)
649 g_snprintf (msg
, sizeof (msg
), _("Copy \"%s\" directory to:"),
650 str_trunc (tree
->selected_ptr
->name
, 50));
651 dest
= input_expand_dialog (Q_("DialogTitle|Copy"), msg
, MC_HISTORY_FM_TREE_COPY
, default_dest
);
653 if (dest
!= NULL
&& *dest
!= '\0') {
654 ctx
= file_op_context_new (OP_COPY
);
655 file_op_context_create_ui (ctx
, FALSE
);
656 copy_dir_dir (ctx
, tree
->selected_ptr
->name
, dest
, 1, 0, 0, 0, &count
, &bytes
);
657 file_op_context_destroy (ctx
);
664 tree_move (WTree
*tree
, const char *default_dest
)
666 char msg
[BUF_MEDIUM
];
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 file_op_context_create_ui (ctx
, FALSE
);
701 move_dir_dir (ctx
, tree
->selected_ptr
->name
, dest
, &count
, &bytes
);
702 file_op_context_destroy (ctx
);
709 tree_mkdir (WTree
*tree
)
711 char old_dir
[MC_MAXPATHLEN
];
713 if (!tree
->selected_ptr
)
715 if (!mc_get_current_wd (old_dir
, MC_MAXPATHLEN
))
717 if (chdir (tree
->selected_ptr
->name
))
728 tree_rmdir (void *data
)
735 if (!tree
->selected_ptr
)
738 if (confirm_delete
) {
743 g_strdup_printf (_(" Delete %s? "),
744 tree
->selected_ptr
->name
);
746 query_dialog (Q_("DialogTitle|Delete"), buf
, D_ERROR
, 2, _("&Yes"), _("&No"));
752 ctx
= file_op_context_new (OP_DELETE
);
753 file_op_context_create_ui (ctx
, FALSE
);
754 if (erase_dir (ctx
, tree
->selected_ptr
->name
, &count
, &bytes
) == FILE_CONT
)
756 file_op_context_destroy (ctx
);
760 tree_move_up (WTree
*tree
)
762 tree_move_backward (tree
, 1);
768 tree_move_down (WTree
*tree
)
770 tree_move_forward (tree
, 1);
776 tree_move_home (WTree
*tree
)
778 tree_move_to_top (tree
);
784 tree_move_end (WTree
*tree
)
786 tree_move_to_bottom (tree
);
792 tree_move_pgup (WTree
*tree
)
794 tree_move_backward (tree
, tlines (tree
) - 1);
800 tree_move_pgdn (WTree
*tree
)
802 tree_move_forward (tree
, tlines (tree
) - 1);
808 tree_move_left (WTree
*tree
)
812 if (tree_navigation_flag
) {
813 v
= tree_move_to_parent (tree
);
822 tree_move_right (WTree
*tree
)
826 if (tree_navigation_flag
) {
827 tree_move_to_child (tree
);
837 tree_start_search (WTree
*tree
)
841 if (tree
->searching
) {
842 if (tree
->selected_ptr
== tree
->store
->tree_last
)
843 tree_move_to_top (tree
);
845 /* set navigation mode temporarily to 'Static' because in
846 * dynamic navigation mode tree_move_forward will not move
847 * to a lower sublevel if necessary (sequent searches must
848 * start with the directory followed the last found directory)
850 i
= tree_navigation_flag
;
851 tree_navigation_flag
= 0;
852 tree_move_forward (tree
, 1);
853 tree_navigation_flag
= i
;
855 tree_do_search (tree
, 0);
858 tree
->search_buffer
[0] = 0;
863 tree_toggle_navig (WTree
*tree
)
865 tree_navigation_flag
= !tree_navigation_flag
;
866 buttonbar_set_label (find_buttonbar (tree
->widget
.parent
), 4,
867 tree_navigation_flag
? Q_("ButtonBar|Static")
868 : Q_("ButtonBar|Dynamc"),
869 tree_map
, (Widget
*) tree
);
873 tree_execute_cmd (WTree
*tree
, unsigned long command
)
875 cb_ret_t res
= MSG_HANDLED
;
877 if (command
!= CK_TreeStartSearch
)
882 interactive_display (NULL
, "[Directory Tree]");
887 case CK_TreeToggleNav
:
888 tree_toggle_navig (tree
);
891 tree_copy (tree
, "");
894 tree_move (tree
, "");
899 case CK_TreeMoveDown
:
900 tree_move_down (tree
);
902 case CK_TreeMoveHome
:
903 tree_move_home (tree
);
906 tree_move_end (tree
);
908 case CK_TreeMovePgUp
:
909 tree_move_pgup (tree
);
911 case CK_TreeMovePgDn
:
912 tree_move_pgdn (tree
);
915 tree_chdir_sel (tree
);
920 case CK_TreeStartSearch
:
921 tree_start_search (tree
);
927 res
= MSG_NOT_HANDLED
;
936 tree_key (WTree
*tree
, int key
)
940 for (i
= 0; tree_map
[i
].key
!= 0; i
++)
941 if (key
== tree_map
[i
].key
)
942 switch (tree_map
[i
].command
) {
943 case CK_TreeMoveLeft
:
944 return tree_move_left (tree
) ? MSG_HANDLED
: MSG_NOT_HANDLED
;
945 case CK_TreeMoveRight
:
946 return tree_move_right (tree
) ? MSG_HANDLED
: MSG_NOT_HANDLED
;
948 tree_execute_cmd (tree
, tree_map
[i
].command
);
952 if (is_abort_char (key
)) {
953 if (tree
->is_panel
) {
956 return MSG_HANDLED
; /* eat abort char */
958 /* modal tree dialog: let upper layer see the
959 abort character and close the dialog */
960 return MSG_NOT_HANDLED
;
963 /* Do not eat characters not meant for the tree below ' ' (e.g. C-l). */
964 if ((key
>= ' ' && key
<= 255) || key
== KEY_BACKSPACE
) {
965 if (tree
->searching
){
966 tree_do_search (tree
, key
);
971 if (!command_prompt
) {
972 tree_start_search (tree
);
973 tree_do_search (tree
, key
);
976 return tree
->is_panel
? MSG_HANDLED
: MSG_NOT_HANDLED
;
979 return MSG_NOT_HANDLED
;
983 tree_frame (Dlg_head
*h
, WTree
*tree
)
985 tty_setcolor (NORMAL_COLOR
);
986 widget_erase ((Widget
*) tree
);
987 if (tree
->is_panel
) {
988 draw_box (h
, tree
->widget
.y
, tree
->widget
.x
, tree
->widget
.lines
,
992 tty_draw_hline (tree
->widget
.y
+ tlines (tree
) + 1,
994 ACS_HLINE
, tree
->widget
.cols
- 2);
999 tree_callback (Widget
*w
, widget_msg_t msg
, int parm
)
1001 WTree
*tree
= (WTree
*) w
;
1002 Dlg_head
*h
= tree
->widget
.parent
;
1003 WButtonBar
*b
= find_buttonbar (h
);
1007 tree_frame (h
, tree
);
1013 buttonbar_set_label (b
, 1, Q_("ButtonBar|Help"), tree_map
, (Widget
*) tree
);
1014 buttonbar_set_label (b
, 2, Q_("ButtonBar|Rescan"), tree_map
, (Widget
*) tree
);
1015 buttonbar_set_label (b
, 3, Q_("ButtonBar|Forget"), tree_map
, (Widget
*) tree
);
1016 buttonbar_set_label (b
, 4, tree_navigation_flag
? Q_("ButtonBar|Static")
1017 : Q_("ButtonBar|Dynamc"),
1018 tree_map
, (Widget
*) tree
);
1019 buttonbar_set_label (b
, 5, Q_("ButtonBar|Copy"), tree_map
, (Widget
*) tree
);
1020 buttonbar_set_label (b
, 6, Q_("ButtonBar|RenMov"), tree_map
, (Widget
*) tree
);
1022 /* FIXME: mkdir is currently defunct */
1023 buttonbar_set_label (b
, 7, Q_("ButtonBar|Mkdir"), tree_map
, (Widget
*) tree
);
1025 buttonbar_clear_label (b
, 7, (Widget
*) tree
);
1027 buttonbar_set_label (b
, 8, Q_("ButtonBar|Rmdir"), tree_map
, (Widget
*) tree
);
1028 buttonbar_redraw (b
);
1030 /* FIXME: Should find a better way of only displaying the
1031 currently selected item */
1035 /* FIXME: Should find a better way of changing the color of the
1038 case WIDGET_UNFOCUS
:
1044 return tree_key (tree
, parm
);
1046 case WIDGET_COMMAND
:
1047 /* command from buttonbar */
1048 return tree_execute_cmd (tree
, parm
);
1050 case WIDGET_DESTROY
:
1051 tree_destroy (tree
);
1055 return default_proc (msg
, parm
);
1060 tree_new (int is_panel
, int y
, int x
, int lines
, int cols
)
1062 WTree
*tree
= g_new (WTree
, 1);
1064 init_widget (&tree
->widget
, y
, x
, lines
, cols
,
1065 tree_callback
, event_callback
);
1066 tree
->is_panel
= is_panel
;
1067 tree
->selected_ptr
= 0;
1069 tree
->store
= tree_store_get ();
1070 tree_store_add_entry_remove_hook (remove_callback
, tree
);
1071 tree
->tree_shown
= 0;
1072 tree
->search_buffer
[0] = 0;
1073 tree
->topdiff
= tree
->widget
.lines
/ 2;
1074 tree
->searching
= 0;
1077 /* We do not want to keep the cursor */
1078 widget_want_cursor (tree
->widget
, 0);
1084 tree_chdir (WTree
*tree
, const char *dir
)
1086 tree_entry
*current
;
1088 current
= tree_store_whereis (dir
);
1090 if (current
!= NULL
) {
1091 tree
->selected_ptr
= current
;
1092 tree_check_focus (tree
);
1096 /* Return name of the currently selected entry */
1098 tree_selected_name (const WTree
*tree
)
1100 return tree
->selected_ptr
->name
;
1104 sync_tree (const char *path
)
1106 tree_chdir (the_tree
, path
);
1110 find_tree (struct Dlg_head
*h
)
1112 return (WTree
*) find_widget_type (h
, tree_callback
);