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
43 #include "../src/tty/tty.h"
44 #include "../src/tty/color.h"
45 #include "../src/tty/mouse.h"
46 #include "../src/tty/key.h"
48 #include "wtools.h" /* message() */
54 #include "file.h" /* For copy_dir_dir(), move_dir_dir(), erase_dir() */
57 #include "treestore.h"
62 #define tlines(t) (t->is_panel ? t->widget.lines-2 - (show_mini_info ? 2 : 0) : t->widget.lines)
64 extern int command_prompt
;
66 /* Use the color of the parent widget for the unselected entries */
67 #define TREE_NORMALC(h) (DLG_NORMALC (h))
69 /* Specifies the display mode: 1d or 2d */
70 static int tree_navigation_flag
;
74 struct TreeStore
*store
;
75 tree_entry
*selected_ptr
; /* The selected directory */
76 char search_buffer
[256]; /* Current search string */
77 tree_entry
**tree_shown
; /* Entries currently on screen */
78 int is_panel
; /* panel or plain widget flag */
79 int active
; /* if it's currently selected */
80 int searching
; /* Are we on searching mode? */
81 int topdiff
; /* The difference between the topmost
82 shown and the selected */
86 static void save_tree (WTree
*tree
);
87 static void tree_rescan_cmd (WTree
*);
89 static tree_entry
*back_ptr (tree_entry
*ptr
, int *count
)
93 while (ptr
&& ptr
->prev
&& i
< *count
){
101 static tree_entry
*forw_ptr (tree_entry
*ptr
, int *count
)
105 while (ptr
&& ptr
->next
&& i
< *count
){
114 remove_callback (tree_entry
*entry
, void *data
)
118 if (tree
->selected_ptr
== entry
){
119 if (tree
->selected_ptr
->next
)
120 tree
->selected_ptr
= tree
->selected_ptr
->next
;
122 tree
->selected_ptr
= tree
->selected_ptr
->prev
;
126 static void tree_remove_entry (WTree
*tree
, char *name
)
129 tree_store_remove_entry (name
);
132 static void tree_destroy (WTree
*tree
)
134 tree_store_remove_entry_remove_hook (remove_callback
);
137 g_free (tree
->tree_shown
);
138 tree
->tree_shown
= 0;
139 tree
->selected_ptr
= NULL
;
142 /* Loads the .mc.tree file */
143 static void load_tree (WTree
*tree
)
147 tree
->selected_ptr
= tree
->store
->tree_first
;
148 tree_chdir (tree
, home_dir
);
151 /* Save the .mc.tree file */
152 static void save_tree (WTree
*tree
)
157 error
= tree_store_save ();
160 fprintf (stderr
, _("Cannot open the %s file for writing:\n%s\n"), MC_TREE
,
161 unix_error_string (error
));
165 static void tree_show_mini_info (WTree
*tree
, int tree_lines
, int tree_cols
)
167 Dlg_head
*h
= tree
->widget
.parent
;
178 tty_draw_hline (tree
->widget
.y
+ line
, tree
->widget
.x
+ 1, ' ', tree_cols
);
179 widget_move (&tree
->widget
, line
, 1);
181 if (tree
->searching
){
182 /* Show search string */
183 tty_setcolor (TREE_NORMALC (h
));
184 tty_setcolor (DLG_FOCUSC (h
));
185 tty_print_char (PATH_SEP
);
187 tty_print_string (str_fit_to_term (tree
->search_buffer
,
188 tree_cols
- 2, J_LEFT_FIT
));
189 tty_print_char (' ');
190 tty_setcolor (DLG_FOCUSC (h
));
192 /* Show full name of selected directory */
193 tty_print_string (str_fit_to_term (tree
->selected_ptr
->name
,
194 tree_cols
, J_LEFT_FIT
));
198 static void show_tree (WTree
*tree
)
200 Dlg_head
*h
= tree
->widget
.parent
;
202 int i
, j
, topsublevel
;
204 int tree_lines
, tree_cols
;
208 tree_lines
= tlines (tree
);
209 tree_cols
= tree
->widget
.cols
;
211 tty_setcolor (TREE_NORMALC (h
));
212 widget_move ((Widget
*)tree
, y
, x
);
218 g_free (tree
->tree_shown
);
219 tree
->tree_shown
= g_new (tree_entry
*, tree_lines
);
221 for (i
= 0; i
< tree_lines
; i
++)
222 tree
->tree_shown
[i
] = NULL
;
223 if (tree
->store
->tree_first
)
224 topsublevel
= tree
->store
->tree_first
->sublevel
;
227 if (!tree
->selected_ptr
){
228 tree
->selected_ptr
= tree
->store
->tree_first
;
231 current
= tree
->selected_ptr
;
233 /* Calculate the directory which is to be shown on the topmost line */
234 if (tree_navigation_flag
){
236 while (current
->prev
&& i
< tree
->topdiff
){
237 current
= current
->prev
;
238 if (current
->sublevel
< tree
->selected_ptr
->sublevel
){
239 if (strncmp (current
->name
, tree
->selected_ptr
->name
,
240 strlen (current
->name
)) == 0)
242 } else if (current
->sublevel
== tree
->selected_ptr
->sublevel
){
243 for (j
= strlen (current
->name
) - 1; current
->name
[j
] != PATH_SEP
; j
--);
244 if (strncmp (current
->name
, tree
->selected_ptr
->name
, j
) == 0)
246 } else if (current
->sublevel
== tree
->selected_ptr
->sublevel
+ 1
247 && strlen (tree
->selected_ptr
->name
) > 1){
248 if (strncmp (current
->name
, tree
->selected_ptr
->name
,
249 strlen (tree
->selected_ptr
->name
)) == 0)
255 current
= back_ptr (current
, &tree
->topdiff
);
257 /* Loop for every line */
258 for (i
= 0; i
< tree_lines
; i
++){
259 /* Move to the beginning of the line */
260 tty_draw_hline (tree
->widget
.y
+ y
+ i
, tree
->widget
.x
+ x
,
266 tree
->tree_shown
[i
] = current
;
267 if (current
->sublevel
== topsublevel
){
269 /* Top level directory */
270 if (tree
->active
&& current
== tree
->selected_ptr
) {
271 if (!tty_use_colors () && !tree
->is_panel
)
272 tty_setcolor (MARKED_COLOR
);
274 tty_setcolor (SELECTED_COLOR
);
278 tty_print_string (str_fit_to_term (current
->name
, tree_cols
- 6, J_LEFT_FIT
));
280 /* Sub level directory */
282 tty_set_alt_charset (TRUE
);
283 /* Output branch parts */
284 for (j
= 0; j
< current
->sublevel
- topsublevel
- 1; j
++){
285 if (tree_cols
- 8 - 3 * j
< 9)
287 tty_print_char (' ');
288 if (current
->submask
& (1 << (j
+ topsublevel
+ 1)))
289 tty_print_char (ACS_VLINE
);
291 tty_print_char (' ');
292 tty_print_char (' ');
294 tty_print_char (' '); j
++;
295 if (!current
->next
|| !(current
->next
->submask
& (1 << current
->sublevel
)))
296 tty_print_char (ACS_LLCORNER
);
298 tty_print_char (ACS_LTEE
);
299 tty_print_char (ACS_HLINE
);
300 tty_set_alt_charset (FALSE
);
302 if (tree
->active
&& current
== tree
->selected_ptr
) {
303 /* Selected directory -> change color */
304 if (!tty_use_colors () && !tree
->is_panel
)
305 tty_setcolor (MARKED_COLOR
);
307 tty_setcolor (SELECTED_COLOR
);
311 tty_print_char (' ');
312 tty_print_string (str_fit_to_term (current
->subname
,
313 tree_cols
- 2 - 4 - 3 * j
, J_LEFT_FIT
));
315 tty_print_char (' ');
317 /* Return to normal color */
318 tty_setcolor (TREE_NORMALC (h
));
320 /* Calculate the next value for current */
321 current
= current
->next
;
322 if (tree_navigation_flag
){
324 if (current
->sublevel
< tree
->selected_ptr
->sublevel
){
325 if (strncmp (current
->name
, tree
->selected_ptr
->name
,
326 strlen (current
->name
)) == 0)
328 } else if (current
->sublevel
== tree
->selected_ptr
->sublevel
){
329 for (j
= strlen (current
->name
) - 1; current
->name
[j
] != PATH_SEP
; j
--);
330 if (strncmp (current
->name
,tree
->selected_ptr
->name
,j
)== 0)
332 } else if (current
->sublevel
== tree
->selected_ptr
->sublevel
+1
333 && strlen (tree
->selected_ptr
->name
) > 1){
334 if (strncmp (current
->name
, tree
->selected_ptr
->name
,
335 strlen (tree
->selected_ptr
->name
)) == 0)
338 current
= current
->next
;
342 tree_show_mini_info (tree
, tree_lines
, tree_cols
);
345 static void check_focus (WTree
*tree
)
347 if (tree
->topdiff
< 3)
349 else if (tree
->topdiff
>= tlines (tree
) - 3)
350 tree
->topdiff
= tlines (tree
) - 3 - 1;
353 static void tree_move_backward (WTree
*tree
, int i
)
358 if (tree_navigation_flag
){
359 current
= tree
->selected_ptr
;
360 while (j
< i
&& current
->prev
361 && current
->prev
->sublevel
>= tree
->selected_ptr
->sublevel
){
362 current
= current
->prev
;
363 if (current
->sublevel
== tree
->selected_ptr
->sublevel
){
364 tree
->selected_ptr
= current
;
370 tree
->selected_ptr
= back_ptr (tree
->selected_ptr
, &i
);
375 static void tree_move_forward (WTree
*tree
, int i
)
380 if (tree_navigation_flag
){
381 current
= tree
->selected_ptr
;
382 while (j
< i
&& current
->next
383 && current
->next
->sublevel
>= tree
->selected_ptr
->sublevel
){
384 current
= current
->next
;
385 if (current
->sublevel
== tree
->selected_ptr
->sublevel
){
386 tree
->selected_ptr
= current
;
392 tree
->selected_ptr
= forw_ptr (tree
->selected_ptr
, &i
);
397 static void tree_move_to_child (WTree
*tree
)
401 /* Do we have a starting point? */
402 if (!tree
->selected_ptr
)
404 /* Take the next entry */
405 current
= tree
->selected_ptr
->next
;
406 /* Is it the child of the selected entry */
407 if (current
&& current
->sublevel
> tree
->selected_ptr
->sublevel
){
408 /* Yes -> select this entry */
409 tree
->selected_ptr
= current
;
413 /* No -> rescan and try again */
414 tree_rescan_cmd (tree
);
415 current
= tree
->selected_ptr
->next
;
416 if (current
&& current
->sublevel
> tree
->selected_ptr
->sublevel
){
417 tree
->selected_ptr
= current
;
424 static int tree_move_to_parent (WTree
*tree
)
429 if (!tree
->selected_ptr
)
431 old
= tree
->selected_ptr
;
432 current
= tree
->selected_ptr
->prev
;
433 while (current
&& current
->sublevel
>= tree
->selected_ptr
->sublevel
){
434 current
= current
->prev
;
438 current
= tree
->store
->tree_first
;
439 tree
->selected_ptr
= current
;
441 return tree
->selected_ptr
!= old
;
444 static void tree_move_to_top (WTree
*tree
)
446 tree
->selected_ptr
= tree
->store
->tree_first
;
450 static void tree_move_to_bottom (WTree
*tree
)
452 tree
->selected_ptr
= tree
->store
->tree_last
;
453 tree
->topdiff
= tlines (tree
) - 3 - 1;
456 void tree_chdir (WTree
*tree
, const char *dir
)
460 current
= tree_store_whereis (dir
);
462 tree
->selected_ptr
= current
;
468 sync_tree (const char *path
)
470 tree_chdir (the_tree
, path
);
473 /* Handle mouse click */
475 tree_event (WTree
*tree
, int y
)
477 if (tree
->tree_shown
[y
]){
478 tree
->selected_ptr
= tree
->tree_shown
[y
];
484 static void chdir_sel (WTree
*tree
);
486 static void maybe_chdir (WTree
*tree
)
488 if (!(xtree_mode
&& tree
->is_panel
))
496 event_callback (Gpm_Event
*event
, void *data
)
500 if (!(event
->type
& GPM_UP
))
512 tree_move_backward (tree
, tlines (tree
) - 1);
515 else if (event
->y
>= tlines (tree
)){
516 tree_move_forward (tree
, tlines (tree
) - 1);
519 tree_event (tree
, event
->y
);
520 if ((event
->type
& (GPM_UP
|GPM_DOUBLE
)) == (GPM_UP
|GPM_DOUBLE
)){
527 /* Search tree for text */
528 static int search_tree (WTree
*tree
, char *text
)
536 current
= tree
->selected_ptr
;
538 while (!wrapped
|| current
!= tree
->selected_ptr
){
539 if (strncmp (current
->subname
, text
, len
) == 0){
540 tree
->selected_ptr
= current
;
544 current
= current
->next
;
546 current
= tree
->store
->tree_first
;
555 static void tree_do_search (WTree
*tree
, int key
)
559 l
= strlen (tree
->search_buffer
);
560 if (l
&& (key
== KEY_BACKSPACE
))
561 tree
->search_buffer
[--l
] = 0;
563 if (key
&& l
< sizeof (tree
->search_buffer
)){
564 tree
->search_buffer
[l
] = key
;
565 tree
->search_buffer
[l
+1] = 0;
570 if (!search_tree (tree
, tree
->search_buffer
))
571 tree
->search_buffer
[--l
] = 0;
578 tree_rescan_cmd (WTree
*tree
)
580 char old_dir
[MC_MAXPATHLEN
];
582 if (!tree
->selected_ptr
|| !mc_get_current_wd (old_dir
, MC_MAXPATHLEN
) ||
583 mc_chdir (tree
->selected_ptr
->name
))
586 tree_store_rescan (tree
->selected_ptr
->name
);
591 tree_forget_cmd (void *data
)
594 if (tree
->selected_ptr
)
595 tree_remove_entry (tree
, tree
->selected_ptr
->name
);
598 static void tree_copy (WTree
*tree
, const char *default_dest
)
605 if (!tree
->selected_ptr
)
607 g_snprintf (cmd_buf
, sizeof(cmd_buf
), _("Copy \"%s\" directory to:"),
608 str_trunc (tree
->selected_ptr
->name
, 50));
609 dest
= input_expand_dialog (_(" Copy "), cmd_buf
, MC_HISTORY_FM_TREE_COPY
, default_dest
);
619 ctx
= file_op_context_new (OP_COPY
);
620 file_op_context_create_ui (ctx
, FALSE
);
621 copy_dir_dir (ctx
, tree
->selected_ptr
->name
, dest
, 1, 0, 0, 0, &count
, &bytes
);
622 file_op_context_destroy (ctx
);
630 interactive_display (NULL
, "[Directory Tree]");
634 tree_copy_cmd (void *data
)
637 tree_copy (tree
, "");
640 static void tree_move (WTree
*tree
, const char *default_dest
)
648 if (!tree
->selected_ptr
)
650 g_snprintf (cmd_buf
, sizeof (cmd_buf
), _("Move \"%s\" directory to:"),
651 str_trunc (tree
->selected_ptr
->name
, 50));
652 dest
= input_expand_dialog (_(" Move "), cmd_buf
, MC_HISTORY_FM_TREE_MOVE
, default_dest
);
659 if (stat (dest
, &buf
)){
660 message (D_ERROR
, MSG_ERROR
, _(" Cannot stat the destination \n %s "),
661 unix_error_string (errno
));
665 if (!S_ISDIR (buf
.st_mode
)){
666 file_error (_(" Destination \"%s\" must be a directory \n %s "),
672 ctx
= file_op_context_new (OP_MOVE
);
673 file_op_context_create_ui (ctx
, FALSE
);
674 move_dir_dir (ctx
, tree
->selected_ptr
->name
, dest
, &count
, &bytes
);
675 file_op_context_destroy (ctx
);
681 tree_move_cmd (void *data
)
684 tree_move (tree
, "");
689 tree_mkdir_cmd (WTree
*tree
)
691 char old_dir
[MC_MAXPATHLEN
];
693 if (!tree
->selected_ptr
)
695 if (!mc_get_current_wd (old_dir
, MC_MAXPATHLEN
))
697 if (chdir (tree
->selected_ptr
->name
))
702 tree_rescan_cmd (tree
);
708 tree_rmdir_cmd (WTree
*tree
)
714 if (!tree
->selected_ptr
)
717 if (confirm_delete
) {
722 g_strdup_printf (_(" Delete %s? "),
723 tree
->selected_ptr
->name
);
725 query_dialog (_(" Delete "), buf
, D_ERROR
, 2, _("&Yes"), _("&No"));
731 ctx
= file_op_context_new (OP_DELETE
);
732 file_op_context_create_ui (ctx
, FALSE
);
733 if (erase_dir (ctx
, tree
->selected_ptr
->name
, &count
, &bytes
) ==
735 tree_forget_cmd (tree
);
736 file_op_context_destroy (ctx
);
739 static void set_navig_label (WTree
*tree
);
742 tree_toggle_navig (void *data
)
745 /* FIXME: invalid use of boolean variable */
746 tree_navigation_flag
= 1 - tree_navigation_flag
;
747 set_navig_label (tree
);
751 set_navig_label (WTree
*tree
)
753 buttonbar_set_label_data (tree
->widget
.parent
, 4,
754 tree_navigation_flag
? _("Static") : _("Dynamc"),
755 tree_toggle_navig
, tree
);
759 move_down (WTree
*tree
)
761 tree_move_forward (tree
, 1);
767 move_up (WTree
*tree
)
769 tree_move_backward (tree
, 1);
775 move_home (WTree
*tree
)
777 tree_move_to_top (tree
);
783 move_end (WTree
*tree
)
785 tree_move_to_bottom (tree
);
791 move_left (WTree
*tree
)
795 if (tree_navigation_flag
){
796 v
= tree_move_to_parent (tree
);
805 move_right (WTree
*tree
)
807 if (tree_navigation_flag
){
808 tree_move_to_child (tree
);
817 move_prevp (WTree
*tree
)
819 tree_move_backward (tree
, tlines (tree
) - 1);
825 move_nextp (WTree
*tree
)
827 tree_move_forward (tree
, tlines (tree
) - 1);
833 chdir_sel (WTree
*tree
)
835 if (!tree
->is_panel
) {
839 if (do_cd (tree
->selected_ptr
->name
, cd_exact
)) {
840 select_item (current_panel
);
842 message (D_ERROR
, MSG_ERROR
, _(" Cannot chdir to \"%s\" \n %s "),
843 tree
->selected_ptr
->name
, unix_error_string (errno
));
851 tree_start_search (WTree
*tree
)
855 if (tree
->searching
){
857 if (tree
->selected_ptr
== tree
->store
->tree_last
)
858 tree_move_to_top(tree
);
860 /* set navigation mode temporarily to 'Static' because in
861 * dynamic navigation mode tree_move_forward will not move
862 * to a lower sublevel if necessary (sequent searches must
863 * start with the directory followed the last found directory)
865 i
= tree_navigation_flag
;
866 tree_navigation_flag
= 0;
867 tree_move_forward (tree
, 1);
868 tree_navigation_flag
= i
;
870 tree_do_search (tree
, 0);
874 tree
->search_buffer
[0] = 0;
878 typedef void (*tree_key_action
) (WTree
*);
884 static const tree_key_map tree_keymap
[] = {
885 { XCTRL('n'), move_down
},
886 { XCTRL('p'), move_up
},
887 { KEY_DOWN
, move_down
},
890 { KEY_ENTER
, chdir_sel
},
891 { KEY_HOME
, move_home
},
892 { KEY_A1
, move_home
},
893 { ALT ('<'), move_home
},
894 { KEY_END
, move_end
},
895 { KEY_C1
, move_end
},
896 { ALT ('>'), move_end
},
897 { KEY_NPAGE
, move_nextp
},
898 { KEY_PPAGE
, move_prevp
},
899 { XCTRL('v'), move_nextp
},
900 { ALT('v'), move_prevp
},
901 { XCTRL('p'), move_up
},
902 { XCTRL('p'), move_down
},
903 { XCTRL('s'), tree_start_search
},
904 { ALT('s'), tree_start_search
},
905 { XCTRL('r'), tree_rescan_cmd
},
906 { KEY_DC
, tree_rmdir_cmd
},
910 static inline cb_ret_t
911 tree_key (WTree
*tree
, int key
)
915 for (i
= 0; tree_keymap
[i
].key_code
; i
++){
916 if (key
== tree_keymap
[i
].key_code
){
917 if (tree_keymap
[i
].fn
!= tree_start_search
)
919 (*tree_keymap
[i
].fn
)(tree
);
925 /* We do not want to use them if we do not need to */
926 /* Input line may want to take the motion key event */
928 return move_left (tree
) ? MSG_HANDLED
: MSG_NOT_HANDLED
;
930 if (key
== KEY_RIGHT
)
931 return move_right (tree
) ? MSG_HANDLED
: MSG_NOT_HANDLED
;
933 if (is_abort_char (key
)) {
934 if (tree
->is_panel
) {
937 return MSG_HANDLED
; /* eat abort char */
939 /* modal tree dialog: let upper layer see the
940 abort character and close the dialog */
941 return MSG_NOT_HANDLED
;
944 /* Do not eat characters not meant for the tree below ' ' (e.g. C-l). */
945 if ((key
>= ' ' && key
<= 255) || key
== KEY_BACKSPACE
) {
946 if (tree
->searching
){
947 tree_do_search (tree
, key
);
952 if (!command_prompt
) {
953 tree_start_search (tree
);
954 tree_do_search (tree
, key
);
957 return tree
->is_panel
? MSG_HANDLED
: MSG_NOT_HANDLED
;
960 return MSG_NOT_HANDLED
;
964 tree_frame (Dlg_head
*h
, WTree
*tree
)
966 tty_setcolor (NORMAL_COLOR
);
967 widget_erase ((Widget
*) tree
);
968 if (tree
->is_panel
) {
969 draw_box (h
, tree
->widget
.y
, tree
->widget
.x
, tree
->widget
.lines
,
973 tty_draw_hline (tree
->widget
.y
+ tlines (tree
) + 1,
975 ACS_HLINE
, tree
->widget
.cols
- 2);
980 tree_rescan_command (void *data
)
983 tree_rescan_cmd (tree
);
987 tree_rmdir_command (void *data
)
990 tree_rmdir_cmd (tree
);
994 tree_callback (Widget
*w
, widget_msg_t msg
, int parm
)
996 WTree
*tree
= (WTree
*) w
;
997 Dlg_head
*h
= tree
->widget
.parent
;
1001 tree_frame (h
, tree
);
1006 return tree_key (tree
, parm
);
1010 buttonbar_set_label (h
, 1, _("Help"), tree_help_cmd
);
1011 buttonbar_set_label_data (h
, 2, _("Rescan"),
1012 tree_rescan_command
, tree
);
1013 buttonbar_set_label_data (h
, 3, _("Forget"), tree_forget_cmd
, tree
);
1014 buttonbar_set_label_data (h
, 5, _("Copy"), tree_copy_cmd
, tree
);
1015 buttonbar_set_label_data (h
, 6, _("RenMov"), tree_move_cmd
, tree
);
1017 /* FIXME: mkdir is currently defunct */
1018 buttonbar_set_label_data (h
, 7, _("Mkdir"), tree_mkdir_cmd
, tree
);
1020 buttonbar_clear_label (h
, 7);
1022 buttonbar_set_label_data (h
, 8, _("Rmdir"), tree_rmdir_command
, tree
);
1023 set_navig_label (tree
);
1024 buttonbar_redraw (h
);
1027 /* FIXME: Should find a better way of only displaying the
1028 currently selected item */
1032 /* FIXME: Should find a better way of changing the color of the
1035 case WIDGET_UNFOCUS
:
1040 case WIDGET_DESTROY
:
1041 tree_destroy (tree
);
1045 return default_proc (msg
, parm
);
1050 tree_new (int is_panel
, int y
, int x
, int lines
, int cols
)
1052 WTree
*tree
= g_new (WTree
, 1);
1054 init_widget (&tree
->widget
, y
, x
, lines
, cols
,
1055 tree_callback
, event_callback
);
1056 tree
->is_panel
= is_panel
;
1057 tree
->selected_ptr
= 0;
1059 tree
->store
= tree_store_get ();
1060 tree_store_add_entry_remove_hook (remove_callback
, tree
);
1061 tree
->tree_shown
= 0;
1062 tree
->search_buffer
[0] = 0;
1063 tree
->topdiff
= tree
->widget
.lines
/ 2;
1064 tree
->searching
= 0;
1067 /* We do not want to keep the cursor */
1068 widget_want_cursor (tree
->widget
, 0);
1073 /* Return name of the currently selected entry */
1075 tree_selected_name (WTree
*tree
)
1077 return tree
->selected_ptr
->name
;