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
)
182 filename
= concat_dir_and_file (home_dir
, MC_TREE
);
183 v
= tree_store_load (filename
);
186 tree
->selected_ptr
= tree
->store
->tree_first
;
188 tree_chdir (tree
, home_dir
);
191 /* Save the .mc.tree file */
192 void save_tree (WTree
*tree
)
197 filename
= concat_dir_and_file (home_dir
, MC_TREE
);
198 error
= tree_store_save (filename
);
202 fprintf (stderr
, _("Can't open the %s file for writing:\n%s\n"), MC_TREE
,
203 unix_error_string (error
));
208 static void tree_show_mini_info (WTree
*tree
, int tree_lines
, int tree_cols
)
210 Dlg_head
*h
= tree
->widget
.parent
;
221 widget_move (&tree
->widget
, line
, 1);
222 hline (' ', tree_cols
);
223 widget_move (&tree
->widget
, line
, 1);
225 if (tree
->searching
){
226 /* Show search string */
227 attrset (TREE_NORMALC
);
231 addstr (name_trunc (tree
->search_buffer
, tree_cols
-2));
235 /* Show full name of selected directory */
236 addstr (name_trunc (tree
->selected_ptr
->name
, tree_cols
));
240 void show_tree (WTree
*tree
)
242 Dlg_head
*h
= tree
->widget
.parent
;
244 int i
, j
, topsublevel
;
246 int tree_lines
, tree_cols
;
250 tree_lines
= tlines (tree
);
251 tree_cols
= tree
->widget
.cols
;
253 attrset (TREE_NORMALC
);
254 widget_move ((Widget
*)tree
, y
, x
);
260 if (tree
->tree_shown
)
261 g_free (tree
->tree_shown
);
262 tree
->tree_shown
= g_new (tree_entry
*, tree_lines
);
264 for (i
= 0; i
< tree_lines
; i
++)
265 tree
->tree_shown
[i
] = NULL
;
266 if (tree
->store
->tree_first
)
267 topsublevel
= tree
->store
->tree_first
->sublevel
;
270 if (!tree
->selected_ptr
){
271 tree
->selected_ptr
= tree
->store
->tree_first
;
274 current
= tree
->selected_ptr
;
276 /* Calculate the directory which is to be shown on the topmost line */
277 if (tree_navigation_flag
){
279 while (current
->prev
&& i
< tree
->topdiff
){
280 current
= current
->prev
;
281 if (current
->sublevel
< tree
->selected_ptr
->sublevel
){
282 if (strncmp (current
->name
, tree
->selected_ptr
->name
,
283 strlen (current
->name
)) == 0)
285 } else if (current
->sublevel
== tree
->selected_ptr
->sublevel
){
286 for (j
= strlen (current
->name
) - 1; current
->name
[j
] != PATH_SEP
; j
--);
287 if (strncmp (current
->name
, tree
->selected_ptr
->name
, j
) == 0)
289 } else if (current
->sublevel
== tree
->selected_ptr
->sublevel
+ 1
290 && strlen (tree
->selected_ptr
->name
) > 1){
291 if (strncmp (current
->name
, tree
->selected_ptr
->name
,
292 strlen (tree
->selected_ptr
->name
)) == 0)
298 current
= back_ptr (current
, &tree
->topdiff
);
300 /* Loop for every line */
301 for (i
= 0; i
< tree_lines
; i
++){
302 /* Move to the beginning of the line */
303 widget_move (&tree
->widget
, y
+i
, x
);
305 hline (' ', tree_cols
);
306 widget_move (&tree
->widget
, y
+i
, x
);
311 tree
->tree_shown
[i
] = current
;
312 if (current
->sublevel
== topsublevel
){
314 /* Top level directory */
315 if (tree
->active
&& current
== tree
->selected_ptr
) {
316 if (!use_colors
&& !tree
->is_panel
)
317 attrset (MARKED_COLOR
);
319 attrset (SELECTED_COLOR
);
323 addstr (name_trunc (current
->name
, tree_cols
- 6));
325 /* Sub level directory */
328 /* Output branch parts */
329 for (j
= 0; j
< current
->sublevel
- topsublevel
- 1; j
++){
330 if (tree_cols
- 8 - 3 * j
< 9)
333 if (current
->submask
& (1 << (j
+ topsublevel
+ 1)))
340 if (!current
->next
|| !(current
->next
->submask
& (1 << current
->sublevel
)))
341 addch (ACS_LLCORNER
);
347 if (tree
->active
&& current
== tree
->selected_ptr
) {
348 /* Selected directory -> change color */
349 if (!use_colors
&& !tree
->is_panel
)
350 attrset (MARKED_COLOR
);
352 attrset (SELECTED_COLOR
);
357 addstr (name_trunc (current
->subname
,
358 tree_cols
- 2 - 4 - 3 * j
));
362 /* Return to normal color */
363 attrset (TREE_NORMALC
);
365 /* Calculate the next value for current */
366 if (tree_navigation_flag
){
367 current
= current
->next
;
369 if (current
->sublevel
< tree
->selected_ptr
->sublevel
){
370 if (strncmp (current
->name
, tree
->selected_ptr
->name
,
371 strlen (current
->name
)) == 0)
373 } else if (current
->sublevel
== tree
->selected_ptr
->sublevel
){
374 for (j
= strlen (current
->name
) - 1; current
->name
[j
] != PATH_SEP
; j
--);
375 if (strncmp (current
->name
,tree
->selected_ptr
->name
,j
)== 0)
377 } else if (current
->sublevel
== tree
->selected_ptr
->sublevel
+1
378 && strlen (tree
->selected_ptr
->name
) > 1){
379 if (strncmp (current
->name
, tree
->selected_ptr
->name
,
380 strlen (tree
->selected_ptr
->name
)) == 0)
383 current
= current
->next
;
386 current
= current
->next
;
388 tree_show_mini_info (tree
, tree_lines
, tree_cols
);
391 static void check_focus (WTree
*tree
)
393 if (tree
->topdiff
< 3)
395 else if (tree
->topdiff
>= tlines (tree
) - 3)
396 tree
->topdiff
= tlines (tree
) - 3 - 1;
399 void tree_move_backward (WTree
*tree
, int i
)
404 if (tree_navigation_flag
){
405 current
= tree
->selected_ptr
;
406 while (j
< i
&& current
->prev
407 && current
->prev
->sublevel
>= tree
->selected_ptr
->sublevel
){
408 current
= current
->prev
;
409 if (current
->sublevel
== tree
->selected_ptr
->sublevel
){
410 tree
->selected_ptr
= current
;
416 tree
->selected_ptr
= back_ptr (tree
->selected_ptr
, &i
);
421 void tree_move_forward (WTree
*tree
, int i
)
426 if (tree_navigation_flag
){
427 current
= tree
->selected_ptr
;
428 while (j
< i
&& current
->next
429 && current
->next
->sublevel
>= tree
->selected_ptr
->sublevel
){
430 current
= current
->next
;
431 if (current
->sublevel
== tree
->selected_ptr
->sublevel
){
432 tree
->selected_ptr
= current
;
438 tree
->selected_ptr
= forw_ptr (tree
->selected_ptr
, &i
);
443 void tree_move_to_child (WTree
*tree
)
447 /* Do we have a starting point? */
448 if (!tree
->selected_ptr
)
450 /* Take the next entry */
451 current
= tree
->selected_ptr
->next
;
452 /* Is it the child of the selected entry */
453 if (current
&& current
->sublevel
> tree
->selected_ptr
->sublevel
){
454 /* Yes -> select this entry */
455 tree
->selected_ptr
= current
;
459 /* No -> rescan and try again */
460 tree_rescan_cmd (tree
);
461 current
= tree
->selected_ptr
->next
;
462 if (current
&& current
->sublevel
> tree
->selected_ptr
->sublevel
){
463 tree
->selected_ptr
= current
;
470 int tree_move_to_parent (WTree
*tree
)
475 if (!tree
->selected_ptr
)
477 old
= tree
->selected_ptr
;
478 current
= tree
->selected_ptr
->prev
;
479 while (current
&& current
->sublevel
>= tree
->selected_ptr
->sublevel
){
480 current
= current
->prev
;
484 current
= tree
->store
->tree_first
;
485 tree
->selected_ptr
= current
;
487 return tree
->selected_ptr
!= old
;
490 void tree_move_to_top (WTree
*tree
)
492 tree
->selected_ptr
= tree
->store
->tree_first
;
496 void tree_move_to_bottom (WTree
*tree
)
498 tree
->selected_ptr
= tree
->store
->tree_last
;
499 tree
->topdiff
= tlines (tree
) - 3 - 1;
502 void tree_chdir (WTree
*tree
, char *dir
)
506 current
= tree_store_whereis (dir
);
508 tree
->selected_ptr
= current
;
514 sync_tree (char *path
)
516 tree_chdir (the_tree
, path
);
519 /* Handle mouse click */
520 void tree_event (WTree
*tree
, int y
)
522 if (tree
->tree_shown
[y
]){
523 tree
->selected_ptr
= tree
->tree_shown
[y
];
529 static void chdir_sel (WTree
*tree
);
531 static void maybe_chdir (WTree
*tree
)
533 if (!(xtree_mode
&& tree
->is_panel
))
540 static int event_callback (Gpm_Event
*event
, WTree
*tree
)
542 if (!(event
->type
& GPM_UP
))
554 tree_move_backward (tree
, tlines (tree
) - 1);
557 else if (event
->y
>= tlines (tree
)){
558 tree_move_forward (tree
, tlines (tree
) - 1);
561 tree_event (tree
, event
->y
);
562 if ((event
->type
& (GPM_UP
|GPM_DOUBLE
)) == (GPM_UP
|GPM_DOUBLE
)){
569 /* Search tree for text */
570 int search_tree (WTree
*tree
, char *text
)
578 current
= tree
->selected_ptr
;
580 while (!wrapped
|| current
!= tree
->selected_ptr
){
581 if (strncmp (current
->subname
, text
, len
) == 0){
582 tree
->selected_ptr
= current
;
586 current
= current
->next
;
588 current
= tree
->store
->tree_first
;
597 static void tree_do_search (WTree
*tree
, int key
)
601 l
= strlen (tree
->search_buffer
);
602 if (l
&& (key
== 8 || key
== 0177 || key
== KEY_BACKSPACE
))
603 tree
->search_buffer
[--l
] = 0;
605 if (key
&& l
< sizeof (tree
->search_buffer
)){
606 tree
->search_buffer
[l
] = key
;
607 tree
->search_buffer
[l
+1] = 0;
612 if (!search_tree (tree
, tree
->search_buffer
))
613 tree
->search_buffer
[--l
] = 0;
619 void tree_rescan_cmd (WTree
*tree
)
621 char old_dir
[MC_MAXPATHLEN
];
623 if (!tree
->selected_ptr
|| !mc_get_current_wd (old_dir
, MC_MAXPATHLEN
) ||
624 mc_chdir (tree
->selected_ptr
->name
))
627 tree_store_rescan (tree
->selected_ptr
->name
);
631 int tree_forget_cmd (WTree
*tree
)
633 if (tree
->selected_ptr
)
634 tree_remove_entry (tree
, tree
->selected_ptr
->name
);
638 void tree_copy (WTree
*tree
, char *default_dest
)
645 if (!tree
->selected_ptr
)
647 g_snprintf (cmd_buf
, sizeof(cmd_buf
), _("Copy \"%s\" directory to:"),
648 name_trunc (tree
->selected_ptr
->name
, 50));
649 dest
= input_expand_dialog (_(" Copy "), cmd_buf
, default_dest
);
650 if (!dest
|| !*dest
){
654 ctx
= file_op_context_new ();
655 file_op_context_create_ui (ctx
, OP_COPY
, FALSE
);
656 copy_dir_dir (ctx
, tree
->selected_ptr
->name
, dest
, 1, 0, 0, 0, &count
, &bytes
);
657 file_op_context_destroy (ctx
);
662 static void tree_help_cmd (void)
664 char *hlpfile
= concat_dir_and_file (mc_home
, "mc.hlp");
665 interactive_display (hlpfile
, "[Directory Tree]");
669 static int tree_copy_cmd (WTree
*tree
)
671 tree_copy (tree
, "");
675 void tree_move (WTree
*tree
, char *default_dest
)
683 if (!tree
->selected_ptr
)
685 g_snprintf (cmd_buf
, sizeof (cmd_buf
), _("Move \"%s\" directory to:"),
686 name_trunc (tree
->selected_ptr
->name
, 50));
687 dest
= input_expand_dialog (_(" Move "), cmd_buf
, default_dest
);
688 if (!dest
|| !*dest
){
691 if (stat (dest
, &buf
)){
692 message (1, _(" Error "), _(" Can't stat the destination \n %s "),
693 unix_error_string (errno
));
697 if (!S_ISDIR (buf
.st_mode
)){
698 message (1, _(" Error "), _(" The destination isn't a directory "));
703 ctx
= file_op_context_new ();
704 file_op_context_create_ui (ctx
, OP_MOVE
, FALSE
);
705 move_dir_dir (ctx
, tree
->selected_ptr
->name
, dest
, &count
, &bytes
);
706 file_op_context_destroy (ctx
);
712 tree_move_cmd (WTree
*tree
)
714 tree_move (tree
, "");
719 tree_mkdir_cmd (WTree
*tree
)
721 char old_dir
[MC_MAXPATHLEN
];
723 if (!tree
->selected_ptr
)
725 if (!mc_get_current_wd (old_dir
, MC_MAXPATHLEN
))
727 if (chdir (tree
->selected_ptr
->name
))
732 tree_rescan_cmd (tree
);
738 tree_rmdir_cmd (WTree
*tree
)
740 char old_dir
[MC_MAXPATHLEN
];
745 if (tree
->selected_ptr
){
746 if (!mc_get_current_wd (old_dir
, MC_MAXPATHLEN
))
748 if (mc_chdir (PATH_SEP_STR
))
754 buf
= g_strdup_printf (_(" Delete %s? "), tree
->selected_ptr
->name
);
755 result
= query_dialog (_(" Delete "), buf
, 3, 2, _("&Yes"), _("&No"));
762 ctx
= file_op_context_new ();
763 file_op_context_create_ui (ctx
, OP_DELETE
, FALSE
);
764 if (erase_dir (ctx
, tree
->selected_ptr
->name
, &count
, &bytes
) == FILE_CONT
)
765 tree_forget_cmd (tree
);
766 file_op_context_destroy (ctx
);
773 static void set_navig_label (Dlg_head
*h
);
776 tree_toggle_navig (Dlg_head
*h
)
778 tree_navigation_flag
= 1 - tree_navigation_flag
;
783 set_navig_label (Dlg_head
*h
)
785 define_label_data (h
, (Widget
*)tree
,
786 4, tree_navigation_flag
? _("Static") : _("Dynamc"),
787 (void (*)(void *))tree_toggle_navig
, h
);
791 move_down (WTree
*tree
)
793 tree_move_forward (tree
, 1);
799 move_up (WTree
*tree
)
801 tree_move_backward (tree
, 1);
807 move_home (WTree
*tree
)
809 tree_move_to_top (tree
);
815 move_end (WTree
*tree
)
817 tree_move_to_bottom (tree
);
823 move_left (WTree
*tree
)
827 if (tree_navigation_flag
){
828 v
= tree_move_to_parent (tree
);
837 move_right (WTree
*tree
)
839 if (tree_navigation_flag
){
840 tree_move_to_child (tree
);
849 move_prevp (WTree
*tree
)
851 tree_move_backward (tree
, tlines (tree
) - 1);
857 move_nextp (WTree
*tree
)
859 tree_move_forward (tree
, tlines (tree
) - 1);
865 chdir_sel (WTree
*tree
)
867 if (!tree
->is_panel
){
872 if (do_cd (tree
->selected_ptr
->name
, cd_exact
)){
873 paint_panel (cpanel
);
874 select_item (cpanel
);
876 message (1, MSG_ERROR
, _(" Can't chdir to \"%s\" \n %s "),
877 tree
->selected_ptr
->name
, unix_error_string (errno
));
885 start_search (WTree
*tree
)
889 if (tree
->searching
){
891 if (tree
->selected_ptr
== tree
->store
->tree_last
)
892 tree_move_to_top(tree
);
894 /* set navigation mode temporarily to 'Static' because in
895 * dynamic navigation mode tree_move_forward will not move
896 * to a lower sublevel if necessary (sequent searches must
897 * start with the directory followed the last found directory)
899 i
= tree_navigation_flag
;
900 tree_navigation_flag
= 0;
901 tree_move_forward (tree
, 1);
902 tree_navigation_flag
= i
;
904 tree_do_search (tree
, 0);
908 tree
->search_buffer
[0] = 0;
912 static key_map tree_keymap
[] = {
913 { XCTRL('n'), move_down
},
914 { XCTRL('p'), move_up
},
915 { KEY_DOWN
, move_down
},
918 { KEY_ENTER
, chdir_sel
},
919 { KEY_HOME
, move_home
},
920 { KEY_C1
, move_end
},
921 { KEY_END
, move_end
},
922 { KEY_A1
, move_home
},
923 { KEY_NPAGE
, move_nextp
},
924 { KEY_PPAGE
, move_prevp
},
925 { XCTRL('v'), move_nextp
},
926 { ALT('v'), move_prevp
},
927 { XCTRL('p'), move_up
},
928 { XCTRL('p'), move_down
},
929 { XCTRL('s'), start_search
},
930 { ALT('s'), start_search
},
931 { XCTRL('r'), tree_rescan_cmd
},
932 { KEY_DC
, tree_rmdir_cmd
},
937 tree_key (WTree
*tree
, int key
)
941 for (i
= 0; tree_keymap
[i
].key_code
; i
++){
942 if (key
== tree_keymap
[i
].key_code
){
943 if (tree_keymap
[i
].fn
!= start_search
)
945 (*tree_keymap
[i
].fn
)(tree
);
951 /* We do not want to use them if we do not need to */
952 /* Input line may want to take the motion key event */
954 return move_left (tree
);
956 if (key
== KEY_RIGHT
)
957 return move_right (tree
);
959 if (is_abort_char (key
)) {
960 if (tree
->is_panel
) {
963 return 1; /* eat abort char */
965 return 0; /* modal tree dialog: let upper layer see the
966 abort character and close the dialog */
969 /* Do not eat characters not meant for the tree below ' ' (e.g. C-l). */
970 if ((key
>= ' '&& key
<= 255) || key
== 8 || key
== KEY_BACKSPACE
) {
971 if (tree
->searching
){
972 tree_do_search (tree
, key
);
977 if (!command_prompt
) {
979 tree_do_search (tree
, key
);
982 return tree
->is_panel
;
989 tree_frame (Dlg_head
*h
, WTree
*tree
)
991 attrset (NORMAL_COLOR
);
992 widget_erase ((Widget
*) tree
);
994 draw_double_box (h
, tree
->widget
.y
, tree
->widget
.x
, tree
->widget
.lines
,
997 if (show_mini_info
&& tree
->is_panel
){
998 widget_move (tree
, tlines (tree
) + 1, 1);
999 hline (ACS_HLINE
, tree
->widget
.cols
- 2);
1005 tree_callback (Dlg_head
*h
, WTree
*tree
, int msg
, int par
)
1009 tree_frame (h
, tree
);
1014 return tree_key (tree
, par
);
1018 define_label (h
, (Widget
*)tree
, 1, _("Help"), (voidfn
) tree_help_cmd
);
1019 define_label_data (h
, (Widget
*)tree
,
1020 2, _("Rescan"), (buttonbarfn
)tree_rescan_cmd
, tree
);
1021 define_label_data (h
, (Widget
*)tree
,
1022 3, _("Forget"), (buttonbarfn
)tree_forget_cmd
, tree
);
1023 define_label_data (h
, (Widget
*)tree
,
1024 5, _("Copy"), (buttonbarfn
) tree_copy_cmd
, tree
);
1025 define_label_data (h
, (Widget
*)tree
,
1026 6, _("RenMov"), (buttonbarfn
) tree_move_cmd
, tree
);
1028 /* FIXME: mkdir is currently defunct */
1029 define_label_data (h
, (Widget
*)tree
,
1030 7, _("Mkdir"), (buttonbarfn
) tree_mkdir_cmd
, tree
);
1032 define_label (h
, (Widget
*)tree
, 7, "", 0);
1034 define_label_data (h
, (Widget
*)tree
,
1035 8, _("Rmdir"), (buttonbarfn
) tree_rmdir_cmd
, tree
);
1036 set_navig_label (h
);
1037 redraw_labels (h
, (Widget
*)tree
);
1040 /* FIXME: Should find a better way of only displaying the
1041 currently selected item */
1045 /* FIXME: Should find a better way of changing the color of the
1047 case WIDGET_UNFOCUS
:
1052 return default_proc (h
, msg
, par
);
1056 tree_new (int is_panel
, int y
, int x
, int lines
, int cols
)
1058 WTree
*tree
= g_new (WTree
, 1);
1060 init_widget (&tree
->widget
, y
, x
, lines
, cols
, tcallback
,
1061 (destroy_fn
) tree_destroy
, (mouse_h
) event_callback
, NULL
);
1062 tree
->is_panel
= is_panel
;
1063 tree
->selected_ptr
= 0;
1065 tree
->store
= tree_store_init ();
1066 tree_store_add_entry_remove_hook (remove_callback
, tree
);
1067 tree
->tree_shown
= 0;
1068 tree
->search_buffer
[0] = 0;
1069 tree
->topdiff
= tree
->widget
.lines
/ 2;
1070 tree
->searching
= 0;
1074 /* We do not want to keep the cursor */
1075 widget_want_cursor (tree
->widget
, 0);