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"
45 #include "lib/tty/mouse.h"
46 #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 "lib/widget.h"
57 #include "main-widgets.h" /* the_menubar */
58 #include "file.h" /* copy_dir_dir(), move_dir_dir(), erase_dir() */
59 #include "layout.h" /* command_prompt */
61 #include "treestore.h"
63 #include "keybind-defaults.h"
68 /*** global variables ****************************************************************************/
70 /*** file scope macro definitions ****************************************************************/
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) (h->color[DLG_COLOR_NORMAL])
76 #define TREE_CURRENTC(h) (h->color[DLG_COLOR_FOCUS])
78 /*** file scope type declarations ****************************************************************/
83 struct TreeStore
*store
;
84 tree_entry
*selected_ptr
; /* The selected directory */
85 char search_buffer
[MC_MAXFILENAMELEN
]; /* 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 */
94 /*** file scope variables ************************************************************************/
96 /* Specifies the display mode: 1d or 2d */
97 static gboolean tree_navigation_flag
= FALSE
;
99 /*** file scope functions ************************************************************************/
100 /* --------------------------------------------------------------------------------------------- */
102 static void tree_rescan (void *data
);
104 /* --------------------------------------------------------------------------------------------- */
107 back_ptr (tree_entry
* ptr
, int *count
)
111 while (ptr
&& ptr
->prev
&& i
< *count
)
120 /* --------------------------------------------------------------------------------------------- */
123 forw_ptr (tree_entry
* ptr
, int *count
)
127 while (ptr
&& ptr
->next
&& i
< *count
)
136 /* --------------------------------------------------------------------------------------------- */
139 remove_callback (tree_entry
* entry
, void *data
)
143 if (tree
->selected_ptr
== entry
)
145 if (tree
->selected_ptr
->next
)
146 tree
->selected_ptr
= tree
->selected_ptr
->next
;
148 tree
->selected_ptr
= tree
->selected_ptr
->prev
;
152 /* --------------------------------------------------------------------------------------------- */
153 /** Save the ~/.mc/Tree file */
156 save_tree (WTree
* tree
)
162 error
= tree_store_save ();
167 tree_name
= g_build_filename (home_dir
, MC_USERCONF_DIR
, MC_TREESTORE_FILE
, (char *) NULL
);
168 fprintf (stderr
, _("Cannot open the %s file for writing:\n%s\n"), tree_name
,
169 unix_error_string (error
));
174 /* --------------------------------------------------------------------------------------------- */
177 tree_remove_entry (WTree
* tree
, char *name
)
180 tree_store_remove_entry (name
);
183 /* --------------------------------------------------------------------------------------------- */
186 tree_destroy (WTree
* tree
)
188 tree_store_remove_entry_remove_hook (remove_callback
);
191 g_free (tree
->tree_shown
);
192 tree
->tree_shown
= 0;
193 tree
->selected_ptr
= NULL
;
196 /* --------------------------------------------------------------------------------------------- */
197 /** Loads the .mc.tree file */
200 load_tree (WTree
* tree
)
204 tree
->selected_ptr
= tree
->store
->tree_first
;
205 tree_chdir (tree
, home_dir
);
208 /* --------------------------------------------------------------------------------------------- */
211 tree_show_mini_info (WTree
* tree
, int tree_lines
, int tree_cols
)
213 Dlg_head
*h
= tree
->widget
.owner
;
221 line
= tree_lines
+ 2;
224 line
= tree_lines
+ 1;
228 /* Show search string */
229 tty_setcolor (INPUT_COLOR
);
230 tty_draw_hline (tree
->widget
.y
+ line
, tree
->widget
.x
+ 1, ' ', tree_cols
);
231 widget_move (&tree
->widget
, line
, 1);
232 tty_print_char (PATH_SEP
);
233 tty_print_string (str_fit_to_term (tree
->search_buffer
, tree_cols
- 2, J_LEFT_FIT
));
234 tty_print_char (' ');
238 /* Show full name of selected directory */
239 tty_setcolor (tree
->is_panel
? NORMAL_COLOR
: TREE_NORMALC (h
));
240 tty_draw_hline (tree
->widget
.y
+ line
, tree
->widget
.x
+ 1, ' ', tree_cols
);
241 widget_move (&tree
->widget
, line
, 1);
242 tty_print_string (str_fit_to_term (tree
->selected_ptr
->name
, tree_cols
, J_LEFT_FIT
));
246 /* --------------------------------------------------------------------------------------------- */
249 show_tree (WTree
* tree
)
251 Dlg_head
*h
= tree
->widget
.owner
;
253 int i
, j
, topsublevel
;
255 int tree_lines
, tree_cols
;
258 tree_lines
= tlines (tree
);
259 tree_cols
= tree
->widget
.cols
;
261 widget_move ((Widget
*) tree
, y
, x
);
268 g_free (tree
->tree_shown
);
269 tree
->tree_shown
= g_new0 (tree_entry
*, tree_lines
);
271 if (tree
->store
->tree_first
)
272 topsublevel
= tree
->store
->tree_first
->sublevel
;
275 if (!tree
->selected_ptr
)
277 tree
->selected_ptr
= tree
->store
->tree_first
;
280 current
= tree
->selected_ptr
;
282 /* Calculate the directory which is to be shown on the topmost line */
283 if (!tree_navigation_flag
)
284 current
= back_ptr (current
, &tree
->topdiff
);
288 while (current
->prev
&& i
< tree
->topdiff
)
290 current
= current
->prev
;
291 if (current
->sublevel
< tree
->selected_ptr
->sublevel
)
293 if (strncmp (current
->name
, tree
->selected_ptr
->name
, strlen (current
->name
)) == 0)
296 else if (current
->sublevel
== tree
->selected_ptr
->sublevel
)
298 for (j
= strlen (current
->name
) - 1; current
->name
[j
] != PATH_SEP
; j
--);
299 if (strncmp (current
->name
, tree
->selected_ptr
->name
, j
) == 0)
302 else if (current
->sublevel
== tree
->selected_ptr
->sublevel
+ 1
303 && strlen (tree
->selected_ptr
->name
) > 1)
305 if (strncmp (current
->name
, tree
->selected_ptr
->name
,
306 strlen (tree
->selected_ptr
->name
)) == 0)
313 /* Loop for every line */
314 for (i
= 0; i
< tree_lines
; i
++)
316 tty_setcolor (tree
->is_panel
? NORMAL_COLOR
: TREE_NORMALC (h
));
318 /* Move to the beginning of the line */
319 tty_draw_hline (tree
->widget
.y
+ y
+ i
, tree
->widget
.x
+ x
, ' ', tree_cols
);
325 tty_setcolor (tree
->active
&& current
== tree
->selected_ptr
326 ? SELECTED_COLOR
: NORMAL_COLOR
);
328 tty_setcolor (current
== tree
->selected_ptr
? TREE_CURRENTC (h
) : TREE_NORMALC (h
));
330 tree
->tree_shown
[i
] = current
;
331 if (current
->sublevel
== topsublevel
)
334 tty_print_string (str_fit_to_term
335 (current
->name
, tree_cols
+ (tree
->is_panel
? 0 : 1), J_LEFT_FIT
));
339 /* Sub level directory */
340 tty_set_alt_charset (TRUE
);
342 /* Output branch parts */
343 for (j
= 0; j
< current
->sublevel
- topsublevel
- 1; j
++)
345 if (tree_cols
- 8 - 3 * j
< 9)
347 tty_print_char (' ');
348 if (current
->submask
& (1 << (j
+ topsublevel
+ 1)))
349 tty_print_char (ACS_VLINE
);
351 tty_print_char (' ');
352 tty_print_char (' ');
354 tty_print_char (' ');
356 if (!current
->next
|| !(current
->next
->submask
& (1 << current
->sublevel
)))
357 tty_print_char (ACS_LLCORNER
);
359 tty_print_char (ACS_LTEE
);
360 tty_print_char (ACS_HLINE
);
361 tty_set_alt_charset (FALSE
);
364 tty_print_char (' ');
365 tty_print_string (str_fit_to_term
366 (current
->subname
, tree_cols
- x
- 3 * j
, J_LEFT_FIT
));
369 /* Calculate the next value for current */
370 current
= current
->next
;
371 if (tree_navigation_flag
)
373 while (current
!= NULL
)
375 if (current
->sublevel
< tree
->selected_ptr
->sublevel
)
377 if (strncmp (current
->name
, tree
->selected_ptr
->name
,
378 strlen (current
->name
)) == 0)
381 else if (current
->sublevel
== tree
->selected_ptr
->sublevel
)
383 for (j
= strlen (current
->name
) - 1; current
->name
[j
] != PATH_SEP
; j
--)
385 if (strncmp (current
->name
, tree
->selected_ptr
->name
, j
) == 0)
388 else if (current
->sublevel
== tree
->selected_ptr
->sublevel
+ 1
389 && strlen (tree
->selected_ptr
->name
) > 1)
391 if (strncmp (current
->name
, tree
->selected_ptr
->name
,
392 strlen (tree
->selected_ptr
->name
)) == 0)
395 current
= current
->next
;
400 tree_show_mini_info (tree
, tree_lines
, tree_cols
);
403 /* --------------------------------------------------------------------------------------------- */
406 tree_check_focus (WTree
* tree
)
408 if (tree
->topdiff
< 3)
410 else if (tree
->topdiff
>= tlines (tree
) - 3)
411 tree
->topdiff
= tlines (tree
) - 3 - 1;
414 /* --------------------------------------------------------------------------------------------- */
417 tree_move_backward (WTree
* tree
, int i
)
419 if (!tree_navigation_flag
)
420 tree
->selected_ptr
= back_ptr (tree
->selected_ptr
, &i
);
426 current
= tree
->selected_ptr
;
427 while (j
< i
&& current
->prev
&& current
->prev
->sublevel
>= tree
->selected_ptr
->sublevel
)
429 current
= current
->prev
;
430 if (current
->sublevel
== tree
->selected_ptr
->sublevel
)
432 tree
->selected_ptr
= current
;
440 tree_check_focus (tree
);
443 /* --------------------------------------------------------------------------------------------- */
446 tree_move_forward (WTree
* tree
, int i
)
448 if (!tree_navigation_flag
)
449 tree
->selected_ptr
= forw_ptr (tree
->selected_ptr
, &i
);
455 current
= tree
->selected_ptr
;
456 while (j
< i
&& current
->next
&& current
->next
->sublevel
>= tree
->selected_ptr
->sublevel
)
458 current
= current
->next
;
459 if (current
->sublevel
== tree
->selected_ptr
->sublevel
)
461 tree
->selected_ptr
= current
;
469 tree_check_focus (tree
);
472 /* --------------------------------------------------------------------------------------------- */
475 tree_move_to_child (WTree
* tree
)
479 /* Do we have a starting point? */
480 if (!tree
->selected_ptr
)
482 /* Take the next entry */
483 current
= tree
->selected_ptr
->next
;
484 /* Is it the child of the selected entry */
485 if (current
&& current
->sublevel
> tree
->selected_ptr
->sublevel
)
487 /* Yes -> select this entry */
488 tree
->selected_ptr
= current
;
490 tree_check_focus (tree
);
494 /* No -> rescan and try again */
496 current
= tree
->selected_ptr
->next
;
497 if (current
&& current
->sublevel
> tree
->selected_ptr
->sublevel
)
499 tree
->selected_ptr
= current
;
501 tree_check_focus (tree
);
506 /* --------------------------------------------------------------------------------------------- */
509 tree_move_to_parent (WTree
* tree
)
514 if (!tree
->selected_ptr
)
517 old
= tree
->selected_ptr
;
518 current
= tree
->selected_ptr
->prev
;
519 while (current
&& current
->sublevel
>= tree
->selected_ptr
->sublevel
)
521 current
= current
->prev
;
525 current
= tree
->store
->tree_first
;
526 tree
->selected_ptr
= current
;
527 tree_check_focus (tree
);
528 return tree
->selected_ptr
!= old
;
531 /* --------------------------------------------------------------------------------------------- */
534 tree_move_to_top (WTree
* tree
)
536 tree
->selected_ptr
= tree
->store
->tree_first
;
540 /* --------------------------------------------------------------------------------------------- */
543 tree_move_to_bottom (WTree
* tree
)
545 tree
->selected_ptr
= tree
->store
->tree_last
;
546 tree
->topdiff
= tlines (tree
) - 3 - 1;
549 /* --------------------------------------------------------------------------------------------- */
550 /** Handle mouse click */
553 tree_event (WTree
* tree
, int y
)
555 if (tree
->tree_shown
[y
])
557 tree
->selected_ptr
= tree
->tree_shown
[y
];
563 /* --------------------------------------------------------------------------------------------- */
566 tree_chdir_sel (WTree
* tree
)
573 if (do_cd (tree
->selected_ptr
->name
, cd_exact
))
574 select_item (current_panel
);
576 message (D_ERROR
, MSG_ERROR
, _("Cannot chdir to \"%s\"\n%s"),
577 tree
->selected_ptr
->name
, unix_error_string (errno
));
583 /* --------------------------------------------------------------------------------------------- */
586 maybe_chdir (WTree
* tree
)
588 if (xtree_mode
&& tree
->is_panel
&& is_idle ())
589 tree_chdir_sel (tree
);
592 /* --------------------------------------------------------------------------------------------- */
593 /** Mouse callback */
596 event_callback (Gpm_Event
* event
, void *data
)
600 /* rest of the upper frame, the menu is invisible - call menu */
601 if (tree
->is_panel
&& (event
->type
& GPM_DOWN
) && event
->y
== 1 && !menubar_visible
)
603 event
->x
+= tree
->widget
.x
;
604 return the_menubar
->widget
.mouse (event
, the_menubar
);
607 if (!(event
->type
& GPM_UP
))
620 tree_move_backward (tree
, tlines (tree
) - 1);
623 else if (event
->y
>= tlines (tree
))
625 tree_move_forward (tree
, tlines (tree
) - 1);
630 tree_event (tree
, event
->y
);
631 if ((event
->type
& (GPM_UP
| GPM_DOUBLE
)) == (GPM_UP
| GPM_DOUBLE
))
633 tree_chdir_sel (tree
);
639 /* --------------------------------------------------------------------------------------------- */
640 /** Search tree for text */
643 search_tree (WTree
* tree
, char *text
)
651 current
= tree
->selected_ptr
;
653 while (!wrapped
|| current
!= tree
->selected_ptr
)
655 if (strncmp (current
->subname
, text
, len
) == 0)
657 tree
->selected_ptr
= current
;
661 current
= current
->next
;
664 current
= tree
->store
->tree_first
;
669 tree_check_focus (tree
);
673 /* --------------------------------------------------------------------------------------------- */
676 tree_do_search (WTree
* tree
, int key
)
680 l
= strlen (tree
->search_buffer
);
681 if ((l
!= 0) && (key
== KEY_BACKSPACE
))
682 tree
->search_buffer
[--l
] = '\0';
683 else if (key
&& l
< sizeof (tree
->search_buffer
))
685 tree
->search_buffer
[l
] = key
;
686 tree
->search_buffer
[++l
] = '\0';
689 if (!search_tree (tree
, tree
->search_buffer
))
690 tree
->search_buffer
[--l
] = 0;
696 /* --------------------------------------------------------------------------------------------- */
699 tree_rescan (void *data
)
701 char old_dir
[MC_MAXPATHLEN
];
705 if (tree
->selected_ptr
== NULL
|| mc_get_current_wd (old_dir
, MC_MAXPATHLEN
) == NULL
706 || mc_chdir (tree
->selected_ptr
->name
))
709 tree_store_rescan (tree
->selected_ptr
->name
);
710 ret
= mc_chdir (old_dir
);
713 /* --------------------------------------------------------------------------------------------- */
716 tree_forget (void *data
)
719 if (tree
->selected_ptr
)
720 tree_remove_entry (tree
, tree
->selected_ptr
->name
);
723 /* --------------------------------------------------------------------------------------------- */
726 tree_copy (WTree
* tree
, const char *default_dest
)
728 char msg
[BUF_MEDIUM
];
731 if (tree
->selected_ptr
== NULL
)
734 g_snprintf (msg
, sizeof (msg
), _("Copy \"%s\" directory to:"),
735 str_trunc (tree
->selected_ptr
->name
, 50));
736 dest
= input_expand_dialog (Q_ ("DialogTitle|Copy"),
737 msg
, MC_HISTORY_FM_TREE_COPY
, default_dest
);
739 if (dest
!= NULL
&& *dest
!= '\0')
742 FileOpTotalContext
*tctx
;
744 ctx
= file_op_context_new (OP_COPY
);
745 tctx
= file_op_total_context_new ();
746 file_op_context_create_ui (ctx
, FALSE
, FILEGUI_DIALOG_MULTI_ITEM
);
747 tctx
->ask_overwrite
= FALSE
;
748 tctx
->is_toplevel_file
= FALSE
;
749 copy_dir_dir (tctx
, ctx
, tree
->selected_ptr
->name
, dest
, TRUE
, FALSE
, FALSE
, NULL
);
750 file_op_total_context_destroy (tctx
);
751 file_op_context_destroy (ctx
);
757 /* --------------------------------------------------------------------------------------------- */
760 tree_move (WTree
* tree
, const char *default_dest
)
762 char msg
[BUF_MEDIUM
];
766 FileOpTotalContext
*tctx
;
768 if (tree
->selected_ptr
== NULL
)
771 g_snprintf (msg
, sizeof (msg
), _("Move \"%s\" directory to:"),
772 str_trunc (tree
->selected_ptr
->name
, 50));
774 input_expand_dialog (Q_ ("DialogTitle|Move"), msg
, MC_HISTORY_FM_TREE_MOVE
, default_dest
);
776 if (dest
== NULL
|| *dest
== '\0')
782 if (stat (dest
, &buf
))
784 message (D_ERROR
, MSG_ERROR
, _("Cannot stat the destination\n%s"),
785 unix_error_string (errno
));
790 if (!S_ISDIR (buf
.st_mode
))
792 file_error (_("Destination \"%s\" must be a directory\n%s"), dest
);
797 ctx
= file_op_context_new (OP_MOVE
);
798 tctx
= file_op_total_context_new ();
799 file_op_context_create_ui (ctx
, FALSE
, FILEGUI_DIALOG_ONE_ITEM
);
800 move_dir_dir (tctx
, ctx
, tree
->selected_ptr
->name
, dest
);
801 file_op_total_context_destroy (tctx
);
802 file_op_context_destroy (ctx
);
807 /* --------------------------------------------------------------------------------------------- */
811 tree_mkdir (WTree
* tree
)
813 char old_dir
[MC_MAXPATHLEN
];
815 if (!tree
->selected_ptr
)
817 if (mc_get_current_wd (old_dir
, MC_MAXPATHLEN
) == NULL
)
819 if (chdir (tree
->selected_ptr
->name
))
829 /* --------------------------------------------------------------------------------------------- */
832 tree_rmdir (void *data
)
836 FileOpTotalContext
*tctx
;
838 if (!tree
->selected_ptr
)
846 buf
= g_strdup_printf (_("Delete %s?"), tree
->selected_ptr
->name
);
847 result
= query_dialog (Q_ ("DialogTitle|Delete"), buf
, D_ERROR
, 2, _("&Yes"), _("&No"));
853 ctx
= file_op_context_new (OP_DELETE
);
854 tctx
= file_op_total_context_new ();
856 file_op_context_create_ui (ctx
, FALSE
, FILEGUI_DIALOG_ONE_ITEM
);
857 if (erase_dir (tctx
, ctx
, tree
->selected_ptr
->name
) == FILE_CONT
)
859 file_op_total_context_destroy (tctx
);
860 file_op_context_destroy (ctx
);
863 /* --------------------------------------------------------------------------------------------- */
866 tree_move_up (WTree
* tree
)
868 tree_move_backward (tree
, 1);
873 /* --------------------------------------------------------------------------------------------- */
876 tree_move_down (WTree
* tree
)
878 tree_move_forward (tree
, 1);
883 /* --------------------------------------------------------------------------------------------- */
886 tree_move_home (WTree
* tree
)
888 tree_move_to_top (tree
);
893 /* --------------------------------------------------------------------------------------------- */
896 tree_move_end (WTree
* tree
)
898 tree_move_to_bottom (tree
);
903 /* --------------------------------------------------------------------------------------------- */
906 tree_move_pgup (WTree
* tree
)
908 tree_move_backward (tree
, tlines (tree
) - 1);
913 /* --------------------------------------------------------------------------------------------- */
916 tree_move_pgdn (WTree
* tree
)
918 tree_move_forward (tree
, tlines (tree
) - 1);
923 /* --------------------------------------------------------------------------------------------- */
926 tree_move_left (WTree
* tree
)
930 if (tree_navigation_flag
)
932 v
= tree_move_to_parent (tree
);
940 /* --------------------------------------------------------------------------------------------- */
943 tree_move_right (WTree
* tree
)
947 if (tree_navigation_flag
)
949 tree_move_to_child (tree
);
958 /* --------------------------------------------------------------------------------------------- */
961 tree_start_search (WTree
* tree
)
967 if (tree
->selected_ptr
== tree
->store
->tree_last
)
968 tree_move_to_top (tree
);
971 /* set navigation mode temporarily to 'Static' because in
972 * dynamic navigation mode tree_move_forward will not move
973 * to a lower sublevel if necessary (sequent searches must
974 * start with the directory followed the last found directory)
976 i
= tree_navigation_flag
;
977 tree_navigation_flag
= 0;
978 tree_move_forward (tree
, 1);
979 tree_navigation_flag
= i
;
981 tree_do_search (tree
, 0);
986 tree
->search_buffer
[0] = 0;
990 /* --------------------------------------------------------------------------------------------- */
993 tree_toggle_navig (WTree
* tree
)
995 tree_navigation_flag
= !tree_navigation_flag
;
996 buttonbar_set_label (find_buttonbar (tree
->widget
.owner
), 4,
997 tree_navigation_flag
? Q_ ("ButtonBar|Static")
998 : Q_ ("ButtonBar|Dynamc"), tree_map
, (Widget
*) tree
);
1001 /* --------------------------------------------------------------------------------------------- */
1004 tree_execute_cmd (WTree
* tree
, unsigned long command
)
1006 cb_ret_t res
= MSG_HANDLED
;
1008 if (command
!= CK_TreeStartSearch
)
1009 tree
->searching
= 0;
1014 interactive_display (NULL
, "[Directory Tree]");
1019 case CK_TreeToggleNav
:
1020 tree_toggle_navig (tree
);
1023 tree_copy (tree
, "");
1026 tree_move (tree
, "");
1029 tree_move_up (tree
);
1031 case CK_TreeMoveDown
:
1032 tree_move_down (tree
);
1034 case CK_TreeMoveHome
:
1035 tree_move_home (tree
);
1037 case CK_TreeMoveEnd
:
1038 tree_move_end (tree
);
1040 case CK_TreeMovePgUp
:
1041 tree_move_pgup (tree
);
1043 case CK_TreeMovePgDn
:
1044 tree_move_pgdn (tree
);
1047 tree_chdir_sel (tree
);
1052 case CK_TreeStartSearch
:
1053 tree_start_search (tree
);
1059 res
= MSG_NOT_HANDLED
;
1067 /* --------------------------------------------------------------------------------------------- */
1070 tree_key (WTree
* tree
, int key
)
1074 for (i
= 0; tree_map
[i
].key
!= 0; i
++)
1075 if (key
== tree_map
[i
].key
)
1076 switch (tree_map
[i
].command
)
1078 case CK_TreeMoveLeft
:
1079 return tree_move_left (tree
) ? MSG_HANDLED
: MSG_NOT_HANDLED
;
1080 case CK_TreeMoveRight
:
1081 return tree_move_right (tree
) ? MSG_HANDLED
: MSG_NOT_HANDLED
;
1083 tree_execute_cmd (tree
, tree_map
[i
].command
);
1087 if (is_abort_char (key
))
1091 tree
->searching
= 0;
1093 return MSG_HANDLED
; /* eat abort char */
1095 /* modal tree dialog: let upper layer see the
1096 abort character and close the dialog */
1097 return MSG_NOT_HANDLED
;
1100 /* Do not eat characters not meant for the tree below ' ' (e.g. C-l). */
1101 if ((key
>= ' ' && key
<= 255) || key
== KEY_BACKSPACE
)
1103 if (tree
->searching
)
1105 tree_do_search (tree
, key
);
1110 if (!command_prompt
)
1112 tree_start_search (tree
);
1113 tree_do_search (tree
, key
);
1116 return tree
->is_panel
? MSG_HANDLED
: MSG_NOT_HANDLED
;
1119 return MSG_NOT_HANDLED
;
1122 /* --------------------------------------------------------------------------------------------- */
1125 tree_frame (Dlg_head
* h
, WTree
* tree
)
1127 tty_setcolor (NORMAL_COLOR
);
1128 widget_erase ((Widget
*) tree
);
1131 const char *title
= _("Directory tree");
1132 const int len
= str_term_width1 (title
);
1134 draw_box (h
, tree
->widget
.y
, tree
->widget
.x
, tree
->widget
.lines
, tree
->widget
.cols
, FALSE
);
1136 widget_move (&tree
->widget
, 0, (tree
->widget
.cols
- len
- 2) / 2);
1137 tty_printf (" %s ", title
);
1140 widget_move (&tree
->widget
, tlines (tree
) + 1, 0);
1141 tty_print_alt_char (ACS_LTEE
, FALSE
);
1142 widget_move (&tree
->widget
, tlines (tree
) + 1, tree
->widget
.cols
- 1);
1143 tty_print_alt_char (ACS_RTEE
, FALSE
);
1144 tty_draw_hline (tree
->widget
.y
+ tlines (tree
) + 1,
1145 tree
->widget
.x
+ 1, ACS_HLINE
, tree
->widget
.cols
- 2);
1149 /* --------------------------------------------------------------------------------------------- */
1152 tree_callback (Widget
* w
, widget_msg_t msg
, int parm
)
1154 WTree
*tree
= (WTree
*) w
;
1155 Dlg_head
*h
= tree
->widget
.owner
;
1156 WButtonBar
*b
= find_buttonbar (h
);
1161 tree_frame (h
, tree
);
1167 buttonbar_set_label (b
, 1, Q_ ("ButtonBar|Help"), tree_map
, (Widget
*) tree
);
1168 buttonbar_set_label (b
, 2, Q_ ("ButtonBar|Rescan"), tree_map
, (Widget
*) tree
);
1169 buttonbar_set_label (b
, 3, Q_ ("ButtonBar|Forget"), tree_map
, (Widget
*) tree
);
1170 buttonbar_set_label (b
, 4, tree_navigation_flag
? Q_ ("ButtonBar|Static")
1171 : Q_ ("ButtonBar|Dynamc"), tree_map
, (Widget
*) tree
);
1172 buttonbar_set_label (b
, 5, Q_ ("ButtonBar|Copy"), tree_map
, (Widget
*) tree
);
1173 buttonbar_set_label (b
, 6, Q_ ("ButtonBar|RenMov"), tree_map
, (Widget
*) tree
);
1175 /* FIXME: mkdir is currently defunct */
1176 buttonbar_set_label (b
, 7, Q_ ("ButtonBar|Mkdir"), tree_map
, (Widget
*) tree
);
1178 buttonbar_clear_label (b
, 7, (Widget
*) tree
);
1180 buttonbar_set_label (b
, 8, Q_ ("ButtonBar|Rmdir"), tree_map
, (Widget
*) tree
);
1181 buttonbar_redraw (b
);
1183 /* FIXME: Should find a better way of only displaying the
1184 currently selected item */
1188 /* FIXME: Should find a better way of changing the color of the
1191 case WIDGET_UNFOCUS
:
1193 tree
->searching
= 0;
1198 return tree_key (tree
, parm
);
1200 case WIDGET_COMMAND
:
1201 /* command from buttonbar */
1202 return tree_execute_cmd (tree
, parm
);
1204 case WIDGET_DESTROY
:
1205 tree_destroy (tree
);
1209 return default_proc (msg
, parm
);
1213 /* --------------------------------------------------------------------------------------------- */
1214 /*** public functions ****************************************************************************/
1215 /* --------------------------------------------------------------------------------------------- */
1218 tree_new (int y
, int x
, int lines
, int cols
, gboolean is_panel
)
1220 WTree
*tree
= g_new (WTree
, 1);
1222 init_widget (&tree
->widget
, y
, x
, lines
, cols
, tree_callback
, event_callback
);
1223 tree
->is_panel
= is_panel
;
1224 tree
->selected_ptr
= 0;
1226 tree
->store
= tree_store_get ();
1227 tree_store_add_entry_remove_hook (remove_callback
, tree
);
1228 tree
->tree_shown
= 0;
1229 tree
->search_buffer
[0] = 0;
1230 tree
->topdiff
= tree
->widget
.lines
/ 2;
1231 tree
->searching
= 0;
1234 /* We do not want to keep the cursor */
1235 widget_want_cursor (tree
->widget
, 0);
1240 /* --------------------------------------------------------------------------------------------- */
1243 tree_chdir (WTree
* tree
, const char *dir
)
1245 tree_entry
*current
;
1247 current
= tree_store_whereis (dir
);
1249 if (current
!= NULL
)
1251 tree
->selected_ptr
= current
;
1252 tree_check_focus (tree
);
1256 /* --------------------------------------------------------------------------------------------- */
1257 /** Return name of the currently selected entry */
1260 tree_selected_name (const WTree
* tree
)
1262 return tree
->selected_ptr
->name
;
1265 /* --------------------------------------------------------------------------------------------- */
1268 sync_tree (const char *path
)
1270 tree_chdir (the_tree
, path
);
1273 /* --------------------------------------------------------------------------------------------- */
1276 find_tree (struct Dlg_head
*h
)
1278 return (WTree
*) find_widget_type (h
, tree_callback
);
1281 /* --------------------------------------------------------------------------------------------- */