1 /* Directory tree browser for the Midnight Commander
2 Copyright (C) 1994, 1995, 1996, 1997 The Free Software Foundation
4 Written: 1994, 1996 Janne Kukonlehto
6 1996, 1999 Miguel de Icaza
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This module has been converted to be a widget.
24 The program load and saves the tree each time the tree widget is
25 created and destroyed. This is required for the future vfs layer,
26 it will be possible to have tree views over virtual file systems.
43 #include "file.h" /* For copy_dir_dir(), move_dir_dir(), erase_dir() */
44 #include "fileopctx.h"
46 #include "key.h" /* For mi_getch() */
49 #include "../vfs/vfs.h"
51 extern int command_prompt
;
53 #define TREE_NORMALC HOT_FOCUSC
55 /* Specifies the display mode: 1d or 2d */
56 int tree_navigation_flag
;
59 static int tree_callback (Dlg_head
*h
, WTree
*tree
, int msg
, int par
);
60 #define tcallback (callback_fn) tree_callback
64 static tree_entry
*back_ptr (tree_entry
*ptr
, int *count
)
68 while (ptr
&& ptr
->prev
&& i
< *count
){
76 static tree_entry
*forw_ptr (tree_entry
*ptr
, int *count
)
80 while (ptr
&& ptr
->next
&& i
< *count
){
88 /* Add a directory to the list of directories */
89 tree_entry
*tree_add_entry (WTree
*tree
, char *name
)
94 return tree_store_add_entry (name
);
98 /* Append a directory to the list of directories */
99 static tree_entry
*tree_append_entry (WTree
*tree
, char *name
)
101 tree_entry
*current
, *new;
105 /* We assume the directory is not yet in the list */
107 new = g_new (tree_entry
, 1);
108 if (!tree
->store
->tree_first
){
110 tree
->store
->tree_first
= new;
113 tree
->tree_last
->next
= new;
114 new->prev
= tree
->tree_last
;
117 tree
->store
->tree_last
= new;
119 /* Calculate attributes */
120 new->name
= g_strdup (name
);
121 len
= strlen (new->name
);
123 for (i
= 0; i
< len
; i
++)
124 if (new->name
[i
] == PATH_SEP
){
126 new->subname
= new->name
+ i
+ 1;
128 submask
= 1 << new->sublevel
;
129 submask
&= (2 << new->sublevel
) - 1;
130 new->submask
= submask
;
133 /* Correct the submasks of the previous entries */
135 while (current
&& current
->sublevel
> new->sublevel
){
136 current
->submask
|= 1 << new->sublevel
;
137 current
= current
->prev
;
140 /* The entry has now been appended */
146 remove_callback (tree_entry
*entry
, void *data
)
150 if (tree
->selected_ptr
== entry
){
151 if (tree
->selected_ptr
->next
)
152 tree
->selected_ptr
= tree
->selected_ptr
->next
;
154 tree
->selected_ptr
= tree
->selected_ptr
->prev
;
158 void tree_remove_entry (WTree
*tree
, char *name
)
160 tree_store_remove_entry (name
);
163 void tree_destroy (WTree
*tree
)
165 tree_store_remove_entry_remove_hook (remove_callback
);
167 tree_store_destroy ();
169 if (tree
->tree_shown
){
170 g_free (tree
->tree_shown
);
171 tree
->tree_shown
= 0;
173 tree
->selected_ptr
= NULL
;
176 /* Loads the .mc.tree file */
177 void load_tree (WTree
*tree
)
181 tree
->selected_ptr
= tree
->store
->tree_first
;
182 tree_chdir (tree
, home_dir
);
185 /* Save the .mc.tree file */
186 void save_tree (WTree
*tree
)
190 error
= tree_store_save ();
193 fprintf (stderr
, _("Can't open the %s file for writing:\n%s\n"), MC_TREE
,
194 unix_error_string (error
));
199 static void tree_show_mini_info (WTree
*tree
, int tree_lines
, int tree_cols
)
201 Dlg_head
*h
= tree
->widget
.parent
;
212 widget_move (&tree
->widget
, line
, 1);
213 hline (' ', tree_cols
);
214 widget_move (&tree
->widget
, line
, 1);
216 if (tree
->searching
){
217 /* Show search string */
218 attrset (TREE_NORMALC
);
222 addstr (name_trunc (tree
->search_buffer
, tree_cols
-2));
226 /* Show full name of selected directory */
227 addstr (name_trunc (tree
->selected_ptr
->name
, tree_cols
));
231 void show_tree (WTree
*tree
)
233 Dlg_head
*h
= tree
->widget
.parent
;
235 int i
, j
, topsublevel
;
237 int tree_lines
, tree_cols
;
241 tree_lines
= tlines (tree
);
242 tree_cols
= tree
->widget
.cols
;
244 attrset (TREE_NORMALC
);
245 widget_move ((Widget
*)tree
, y
, x
);
251 if (tree
->tree_shown
)
252 g_free (tree
->tree_shown
);
253 tree
->tree_shown
= g_new (tree_entry
*, tree_lines
);
255 for (i
= 0; i
< tree_lines
; i
++)
256 tree
->tree_shown
[i
] = NULL
;
257 if (tree
->store
->tree_first
)
258 topsublevel
= tree
->store
->tree_first
->sublevel
;
261 if (!tree
->selected_ptr
){
262 tree
->selected_ptr
= tree
->store
->tree_first
;
265 current
= tree
->selected_ptr
;
267 /* Calculate the directory which is to be shown on the topmost line */
268 if (tree_navigation_flag
){
270 while (current
->prev
&& i
< tree
->topdiff
){
271 current
= current
->prev
;
272 if (current
->sublevel
< tree
->selected_ptr
->sublevel
){
273 if (strncmp (current
->name
, tree
->selected_ptr
->name
,
274 strlen (current
->name
)) == 0)
276 } else if (current
->sublevel
== tree
->selected_ptr
->sublevel
){
277 for (j
= strlen (current
->name
) - 1; current
->name
[j
] != PATH_SEP
; j
--);
278 if (strncmp (current
->name
, tree
->selected_ptr
->name
, j
) == 0)
280 } else if (current
->sublevel
== tree
->selected_ptr
->sublevel
+ 1
281 && strlen (tree
->selected_ptr
->name
) > 1){
282 if (strncmp (current
->name
, tree
->selected_ptr
->name
,
283 strlen (tree
->selected_ptr
->name
)) == 0)
289 current
= back_ptr (current
, &tree
->topdiff
);
291 /* Loop for every line */
292 for (i
= 0; i
< tree_lines
; i
++){
293 /* Move to the beginning of the line */
294 widget_move (&tree
->widget
, y
+i
, x
);
296 hline (' ', tree_cols
);
297 widget_move (&tree
->widget
, y
+i
, x
);
302 tree
->tree_shown
[i
] = current
;
303 if (current
->sublevel
== topsublevel
){
305 /* Top level directory */
306 if (tree
->active
&& current
== tree
->selected_ptr
) {
307 if (!use_colors
&& !tree
->is_panel
)
308 attrset (MARKED_COLOR
);
310 attrset (SELECTED_COLOR
);
314 addstr (name_trunc (current
->name
, tree_cols
- 6));
316 /* Sub level directory */
319 /* Output branch parts */
320 for (j
= 0; j
< current
->sublevel
- topsublevel
- 1; j
++){
321 if (tree_cols
- 8 - 3 * j
< 9)
324 if (current
->submask
& (1 << (j
+ topsublevel
+ 1)))
331 if (!current
->next
|| !(current
->next
->submask
& (1 << current
->sublevel
)))
332 addch (ACS_LLCORNER
);
338 if (tree
->active
&& current
== tree
->selected_ptr
) {
339 /* Selected directory -> change color */
340 if (!use_colors
&& !tree
->is_panel
)
341 attrset (MARKED_COLOR
);
343 attrset (SELECTED_COLOR
);
348 addstr (name_trunc (current
->subname
,
349 tree_cols
- 2 - 4 - 3 * j
));
353 /* Return to normal color */
354 attrset (TREE_NORMALC
);
356 /* Calculate the next value for current */
357 if (tree_navigation_flag
){
358 current
= current
->next
;
360 if (current
->sublevel
< tree
->selected_ptr
->sublevel
){
361 if (strncmp (current
->name
, tree
->selected_ptr
->name
,
362 strlen (current
->name
)) == 0)
364 } else if (current
->sublevel
== tree
->selected_ptr
->sublevel
){
365 for (j
= strlen (current
->name
) - 1; current
->name
[j
] != PATH_SEP
; j
--);
366 if (strncmp (current
->name
,tree
->selected_ptr
->name
,j
)== 0)
368 } else if (current
->sublevel
== tree
->selected_ptr
->sublevel
+1
369 && strlen (tree
->selected_ptr
->name
) > 1){
370 if (strncmp (current
->name
, tree
->selected_ptr
->name
,
371 strlen (tree
->selected_ptr
->name
)) == 0)
374 current
= current
->next
;
377 current
= current
->next
;
379 tree_show_mini_info (tree
, tree_lines
, tree_cols
);
382 static void check_focus (WTree
*tree
)
384 if (tree
->topdiff
< 3)
386 else if (tree
->topdiff
>= tlines (tree
) - 3)
387 tree
->topdiff
= tlines (tree
) - 3 - 1;
390 void tree_move_backward (WTree
*tree
, int i
)
395 if (tree_navigation_flag
){
396 current
= tree
->selected_ptr
;
397 while (j
< i
&& current
->prev
398 && current
->prev
->sublevel
>= tree
->selected_ptr
->sublevel
){
399 current
= current
->prev
;
400 if (current
->sublevel
== tree
->selected_ptr
->sublevel
){
401 tree
->selected_ptr
= current
;
407 tree
->selected_ptr
= back_ptr (tree
->selected_ptr
, &i
);
412 void tree_move_forward (WTree
*tree
, int i
)
417 if (tree_navigation_flag
){
418 current
= tree
->selected_ptr
;
419 while (j
< i
&& current
->next
420 && current
->next
->sublevel
>= tree
->selected_ptr
->sublevel
){
421 current
= current
->next
;
422 if (current
->sublevel
== tree
->selected_ptr
->sublevel
){
423 tree
->selected_ptr
= current
;
429 tree
->selected_ptr
= forw_ptr (tree
->selected_ptr
, &i
);
434 void tree_move_to_child (WTree
*tree
)
438 /* Do we have a starting point? */
439 if (!tree
->selected_ptr
)
441 /* Take the next entry */
442 current
= tree
->selected_ptr
->next
;
443 /* Is it the child of the selected entry */
444 if (current
&& current
->sublevel
> tree
->selected_ptr
->sublevel
){
445 /* Yes -> select this entry */
446 tree
->selected_ptr
= current
;
450 /* No -> rescan and try again */
451 tree_rescan_cmd (tree
);
452 current
= tree
->selected_ptr
->next
;
453 if (current
&& current
->sublevel
> tree
->selected_ptr
->sublevel
){
454 tree
->selected_ptr
= current
;
461 int tree_move_to_parent (WTree
*tree
)
466 if (!tree
->selected_ptr
)
468 old
= tree
->selected_ptr
;
469 current
= tree
->selected_ptr
->prev
;
470 while (current
&& current
->sublevel
>= tree
->selected_ptr
->sublevel
){
471 current
= current
->prev
;
475 current
= tree
->store
->tree_first
;
476 tree
->selected_ptr
= current
;
478 return tree
->selected_ptr
!= old
;
481 void tree_move_to_top (WTree
*tree
)
483 tree
->selected_ptr
= tree
->store
->tree_first
;
487 void tree_move_to_bottom (WTree
*tree
)
489 tree
->selected_ptr
= tree
->store
->tree_last
;
490 tree
->topdiff
= tlines (tree
) - 3 - 1;
493 void tree_chdir (WTree
*tree
, char *dir
)
497 current
= tree_store_whereis (dir
);
499 tree
->selected_ptr
= current
;
505 sync_tree (char *path
)
507 tree_chdir (the_tree
, path
);
510 /* Handle mouse click */
511 void tree_event (WTree
*tree
, int y
)
513 if (tree
->tree_shown
[y
]){
514 tree
->selected_ptr
= tree
->tree_shown
[y
];
520 static void chdir_sel (WTree
*tree
);
522 static void maybe_chdir (WTree
*tree
)
524 if (!(xtree_mode
&& tree
->is_panel
))
531 static int event_callback (Gpm_Event
*event
, WTree
*tree
)
533 if (!(event
->type
& GPM_UP
))
545 tree_move_backward (tree
, tlines (tree
) - 1);
548 else if (event
->y
>= tlines (tree
)){
549 tree_move_forward (tree
, tlines (tree
) - 1);
552 tree_event (tree
, event
->y
);
553 if ((event
->type
& (GPM_UP
|GPM_DOUBLE
)) == (GPM_UP
|GPM_DOUBLE
)){
560 /* Search tree for text */
561 int search_tree (WTree
*tree
, char *text
)
569 current
= tree
->selected_ptr
;
571 while (!wrapped
|| current
!= tree
->selected_ptr
){
572 if (strncmp (current
->subname
, text
, len
) == 0){
573 tree
->selected_ptr
= current
;
577 current
= current
->next
;
579 current
= tree
->store
->tree_first
;
588 static void tree_do_search (WTree
*tree
, int key
)
592 l
= strlen (tree
->search_buffer
);
593 if (l
&& (key
== 8 || key
== 0177 || key
== KEY_BACKSPACE
))
594 tree
->search_buffer
[--l
] = 0;
596 if (key
&& l
< sizeof (tree
->search_buffer
)){
597 tree
->search_buffer
[l
] = key
;
598 tree
->search_buffer
[l
+1] = 0;
603 if (!search_tree (tree
, tree
->search_buffer
))
604 tree
->search_buffer
[--l
] = 0;
610 void tree_rescan_cmd (WTree
*tree
)
612 char old_dir
[MC_MAXPATHLEN
];
614 if (!tree
->selected_ptr
|| !mc_get_current_wd (old_dir
, MC_MAXPATHLEN
) ||
615 mc_chdir (tree
->selected_ptr
->name
))
618 tree_store_rescan (tree
->selected_ptr
->name
);
622 int tree_forget_cmd (WTree
*tree
)
624 if (tree
->selected_ptr
)
625 tree_remove_entry (tree
, tree
->selected_ptr
->name
);
629 void tree_copy (WTree
*tree
, char *default_dest
)
636 if (!tree
->selected_ptr
)
638 g_snprintf (cmd_buf
, sizeof(cmd_buf
), _("Copy \"%s\" directory to:"),
639 name_trunc (tree
->selected_ptr
->name
, 50));
640 dest
= input_expand_dialog (_(" Copy "), cmd_buf
, default_dest
);
641 if (!dest
|| !*dest
){
645 ctx
= file_op_context_new ();
646 file_op_context_create_ui (ctx
, OP_COPY
, FALSE
);
647 copy_dir_dir (ctx
, tree
->selected_ptr
->name
, dest
, 1, 0, 0, 0, &count
, &bytes
);
648 file_op_context_destroy (ctx
);
653 static void tree_help_cmd (void)
655 char *hlpfile
= concat_dir_and_file (mc_home
, "mc.hlp");
656 interactive_display (hlpfile
, "[Directory Tree]");
660 static int tree_copy_cmd (WTree
*tree
)
662 tree_copy (tree
, "");
666 void tree_move (WTree
*tree
, char *default_dest
)
674 if (!tree
->selected_ptr
)
676 g_snprintf (cmd_buf
, sizeof (cmd_buf
), _("Move \"%s\" directory to:"),
677 name_trunc (tree
->selected_ptr
->name
, 50));
678 dest
= input_expand_dialog (_(" Move "), cmd_buf
, default_dest
);
679 if (!dest
|| !*dest
){
682 if (stat (dest
, &buf
)){
683 message (1, _(" Error "), _(" Can't stat the destination \n %s "),
684 unix_error_string (errno
));
688 if (!S_ISDIR (buf
.st_mode
)){
689 message (1, _(" Error "), _(" The destination isn't a directory "));
694 ctx
= file_op_context_new ();
695 file_op_context_create_ui (ctx
, OP_MOVE
, FALSE
);
696 move_dir_dir (ctx
, tree
->selected_ptr
->name
, dest
, &count
, &bytes
);
697 file_op_context_destroy (ctx
);
703 tree_move_cmd (WTree
*tree
)
705 tree_move (tree
, "");
710 tree_mkdir_cmd (WTree
*tree
)
712 char old_dir
[MC_MAXPATHLEN
];
714 if (!tree
->selected_ptr
)
716 if (!mc_get_current_wd (old_dir
, MC_MAXPATHLEN
))
718 if (chdir (tree
->selected_ptr
->name
))
723 tree_rescan_cmd (tree
);
729 tree_rmdir_cmd (WTree
*tree
)
731 char old_dir
[MC_MAXPATHLEN
];
736 if (tree
->selected_ptr
){
737 if (!mc_get_current_wd (old_dir
, MC_MAXPATHLEN
))
739 if (mc_chdir (PATH_SEP_STR
))
745 buf
= g_strdup_printf (_(" Delete %s? "), tree
->selected_ptr
->name
);
746 result
= query_dialog (_(" Delete "), buf
, 3, 2, _("&Yes"), _("&No"));
753 ctx
= file_op_context_new ();
754 file_op_context_create_ui (ctx
, OP_DELETE
, FALSE
);
755 if (erase_dir (ctx
, tree
->selected_ptr
->name
, &count
, &bytes
) == FILE_CONT
)
756 tree_forget_cmd (tree
);
757 file_op_context_destroy (ctx
);
764 static void set_navig_label (Dlg_head
*h
);
767 tree_toggle_navig (Dlg_head
*h
)
769 tree_navigation_flag
= 1 - tree_navigation_flag
;
774 set_navig_label (Dlg_head
*h
)
776 define_label_data (h
, (Widget
*)tree
,
777 4, tree_navigation_flag
? _("Static") : _("Dynamc"),
778 (void (*)(void *))tree_toggle_navig
, h
);
782 move_down (WTree
*tree
)
784 tree_move_forward (tree
, 1);
790 move_up (WTree
*tree
)
792 tree_move_backward (tree
, 1);
798 move_home (WTree
*tree
)
800 tree_move_to_top (tree
);
806 move_end (WTree
*tree
)
808 tree_move_to_bottom (tree
);
814 move_left (WTree
*tree
)
818 if (tree_navigation_flag
){
819 v
= tree_move_to_parent (tree
);
828 move_right (WTree
*tree
)
830 if (tree_navigation_flag
){
831 tree_move_to_child (tree
);
840 move_prevp (WTree
*tree
)
842 tree_move_backward (tree
, tlines (tree
) - 1);
848 move_nextp (WTree
*tree
)
850 tree_move_forward (tree
, tlines (tree
) - 1);
856 chdir_sel (WTree
*tree
)
858 if (!tree
->is_panel
){
863 if (do_cd (tree
->selected_ptr
->name
, cd_exact
)){
864 paint_panel (cpanel
);
865 select_item (cpanel
);
867 message (1, MSG_ERROR
, _(" Can't chdir to \"%s\" \n %s "),
868 tree
->selected_ptr
->name
, unix_error_string (errno
));
876 tree_start_search (WTree
*tree
)
880 if (tree
->searching
){
882 if (tree
->selected_ptr
== tree
->store
->tree_last
)
883 tree_move_to_top(tree
);
885 /* set navigation mode temporarily to 'Static' because in
886 * dynamic navigation mode tree_move_forward will not move
887 * to a lower sublevel if necessary (sequent searches must
888 * start with the directory followed the last found directory)
890 i
= tree_navigation_flag
;
891 tree_navigation_flag
= 0;
892 tree_move_forward (tree
, 1);
893 tree_navigation_flag
= i
;
895 tree_do_search (tree
, 0);
899 tree
->search_buffer
[0] = 0;
903 static key_map tree_keymap
[] = {
904 { XCTRL('n'), move_down
},
905 { XCTRL('p'), move_up
},
906 { KEY_DOWN
, move_down
},
909 { KEY_ENTER
, chdir_sel
},
910 { KEY_HOME
, move_home
},
911 { KEY_C1
, move_end
},
912 { KEY_END
, move_end
},
913 { KEY_A1
, move_home
},
914 { KEY_NPAGE
, move_nextp
},
915 { KEY_PPAGE
, move_prevp
},
916 { XCTRL('v'), move_nextp
},
917 { ALT('v'), move_prevp
},
918 { XCTRL('p'), move_up
},
919 { XCTRL('p'), move_down
},
920 { XCTRL('s'), tree_start_search
},
921 { ALT('s'), tree_start_search
},
922 { XCTRL('r'), tree_rescan_cmd
},
923 { KEY_DC
, tree_rmdir_cmd
},
928 tree_key (WTree
*tree
, int key
)
932 for (i
= 0; tree_keymap
[i
].key_code
; i
++){
933 if (key
== tree_keymap
[i
].key_code
){
934 if (tree_keymap
[i
].fn
!= tree_start_search
)
936 (*tree_keymap
[i
].fn
)(tree
);
942 /* We do not want to use them if we do not need to */
943 /* Input line may want to take the motion key event */
945 return move_left (tree
);
947 if (key
== KEY_RIGHT
)
948 return move_right (tree
);
950 if (is_abort_char (key
)) {
951 if (tree
->is_panel
) {
954 return 1; /* eat abort char */
956 return 0; /* modal tree dialog: let upper layer see the
957 abort character and close the dialog */
960 /* Do not eat characters not meant for the tree below ' ' (e.g. C-l). */
961 if ((key
>= ' '&& key
<= 255) || key
== 8 || key
== KEY_BACKSPACE
) {
962 if (tree
->searching
){
963 tree_do_search (tree
, key
);
968 if (!command_prompt
) {
969 tree_start_search (tree
);
970 tree_do_search (tree
, key
);
973 return tree
->is_panel
;
980 tree_frame (Dlg_head
*h
, WTree
*tree
)
982 attrset (NORMAL_COLOR
);
983 widget_erase ((Widget
*) tree
);
985 draw_double_box (h
, tree
->widget
.y
, tree
->widget
.x
, tree
->widget
.lines
,
988 if (show_mini_info
&& tree
->is_panel
){
989 widget_move (tree
, tlines (tree
) + 1, 1);
990 hline (ACS_HLINE
, tree
->widget
.cols
- 2);
996 tree_callback (Dlg_head
*h
, WTree
*tree
, int msg
, int par
)
1000 tree_frame (h
, tree
);
1005 return tree_key (tree
, par
);
1009 define_label (h
, (Widget
*)tree
, 1, _("Help"), (voidfn
) tree_help_cmd
);
1010 define_label_data (h
, (Widget
*)tree
,
1011 2, _("Rescan"), (buttonbarfn
)tree_rescan_cmd
, tree
);
1012 define_label_data (h
, (Widget
*)tree
,
1013 3, _("Forget"), (buttonbarfn
)tree_forget_cmd
, tree
);
1014 define_label_data (h
, (Widget
*)tree
,
1015 5, _("Copy"), (buttonbarfn
) tree_copy_cmd
, tree
);
1016 define_label_data (h
, (Widget
*)tree
,
1017 6, _("RenMov"), (buttonbarfn
) tree_move_cmd
, tree
);
1019 /* FIXME: mkdir is currently defunct */
1020 define_label_data (h
, (Widget
*)tree
,
1021 7, _("Mkdir"), (buttonbarfn
) tree_mkdir_cmd
, tree
);
1023 define_label (h
, (Widget
*)tree
, 7, "", 0);
1025 define_label_data (h
, (Widget
*)tree
,
1026 8, _("Rmdir"), (buttonbarfn
) tree_rmdir_cmd
, tree
);
1027 set_navig_label (h
);
1028 redraw_labels (h
, (Widget
*)tree
);
1031 /* FIXME: Should find a better way of only displaying the
1032 currently selected item */
1036 /* FIXME: Should find a better way of changing the color of the
1038 case WIDGET_UNFOCUS
:
1043 return default_proc (h
, msg
, par
);
1047 tree_new (int is_panel
, int y
, int x
, int lines
, int cols
)
1049 WTree
*tree
= g_new (WTree
, 1);
1051 init_widget (&tree
->widget
, y
, x
, lines
, cols
, tcallback
,
1052 (destroy_fn
) tree_destroy
, (mouse_h
) event_callback
, NULL
);
1053 tree
->is_panel
= is_panel
;
1054 tree
->selected_ptr
= 0;
1056 tree
->store
= tree_store_init ();
1057 tree_store_add_entry_remove_hook (remove_callback
, tree
);
1058 tree
->tree_shown
= 0;
1059 tree
->search_buffer
[0] = 0;
1060 tree
->topdiff
= tree
->widget
.lines
/ 2;
1061 tree
->searching
= 0;
1065 /* We do not want to keep the cursor */
1066 widget_want_cursor (tree
->widget
, 0);