Changed treestore functions to handle vfs_path_t objects.

Signed-off-by: Slava Zanko <slavazanko@gmail.com>
This commit is contained in:
Slava Zanko 2011-10-04 15:58:24 +03:00
parent fec5cd6c5d
commit 5480fe5f80
8 changed files with 303 additions and 243 deletions

View File

@ -918,7 +918,7 @@ tree_box (const char *current_dir)
((Widget *) bar)->y = LINES - 1; ((Widget *) bar)->y = LINES - 1;
if (run_dlg (dlg) == B_ENTER) if (run_dlg (dlg) == B_ENTER)
val = g_strdup (tree_selected_name (mytree)); val = vfs_path_to_str (tree_selected_name (mytree));
destroy_dlg (dlg); destroy_dlg (dlg);
return val; return val;

View File

@ -553,7 +553,7 @@ do_load_dir (const char *path, dir_list * list, sortfn * sort, gboolean lc_rever
goto ret; goto ret;
} }
tree_store_start_check (path); tree_store_start_check (vpath);
/* Do not add a ".." entry to the root directory */ /* Do not add a ".." entry to the root directory */
if ((path[0] == PATH_SEP) && (path[1] == '\0')) if ((path[0] == PATH_SEP) && (path[1] == '\0'))
@ -637,8 +637,7 @@ do_reload_dir (const vfs_path_t * vpath, dir_list * list, sortfn * sort, int cou
return set_zero_dir (list) ? 1 : 0; return set_zero_dir (list) ? 1 : 0;
} }
tmp_path = vfs_path_to_str (vpath); tree_store_start_check (vpath);
tree_store_start_check (tmp_path);
marked_files = g_hash_table_new (g_str_hash, g_str_equal); marked_files = g_hash_table_new (g_str_hash, g_str_equal);
alloc_dir_copy (list->size); alloc_dir_copy (list->size);
@ -661,13 +660,15 @@ do_reload_dir (const vfs_path_t * vpath, dir_list * list, sortfn * sort, int cou
/* Add ".." except to the root directory. The ".." entry /* Add ".." except to the root directory. The ".." entry
(if any) must be the first in the list. */ (if any) must be the first in the list. */
if (!((tmp_path[0] == PATH_SEP) && (tmp_path[1] == '\0'))) tmp_path = vfs_path_get_by_index (vpath, 0)->path;
if (!
(vfs_path_elements_count (vpath) == 1 && (tmp_path[0] == PATH_SEP)
&& (tmp_path[1] == '\0')))
{ {
if (!set_zero_dir (list)) if (!set_zero_dir (list))
{ {
clean_dir (list, count); clean_dir (list, count);
clean_dir (&dir_copy, count); clean_dir (&dir_copy, count);
g_free (tmp_path);
return next_free; return next_free;
} }
@ -676,7 +677,6 @@ do_reload_dir (const vfs_path_t * vpath, dir_list * list, sortfn * sort, int cou
next_free++; next_free++;
} }
g_free (tmp_path);
while ((dp = mc_readdir (dirp))) while ((dp = mc_readdir (dirp)))
{ {

View File

@ -1176,7 +1176,7 @@ panel_get_file (WPanel * panel)
WTree *tree; WTree *tree;
tree = (WTree *) get_panel_widget (get_current_index ()); tree = (WTree *) get_panel_widget (get_current_index ());
return tree_selected_name (tree); return vfs_path_to_str (tree_selected_name (tree));
} }
if (panel->marked != 0) if (panel->marked != 0)
@ -1185,10 +1185,9 @@ panel_get_file (WPanel * panel)
for (i = 0; i < panel->count; i++) for (i = 0; i < panel->count; i++)
if (panel->dir.list[i].f.marked) if (panel->dir.list[i].f.marked)
return panel->dir.list[i].fname; return g_strdup (panel->dir.list[i].fname);
} }
return g_strdup (panel->dir.list[panel->selected].fname);
return panel->dir.list[panel->selected].fname;
} }
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
@ -2627,12 +2626,13 @@ panel_operate (void *source_panel, FileOperation operation, gboolean force_singl
vfs_path_t *source_vpath; vfs_path_t *source_vpath;
if (force_single) if (force_single)
source = selection (panel)->fname; source = g_strdup (selection (panel)->fname);
else else
source = panel_get_file (panel); source = panel_get_file (panel);
if (strcmp (source, "..") == 0) if (strcmp (source, "..") == 0)
{ {
g_free (source);
message (D_ERROR, MSG_ERROR, _("Cannot operate on \"..\"!")); message (D_ERROR, MSG_ERROR, _("Cannot operate on \"..\"!"));
return FALSE; return FALSE;
} }
@ -2924,20 +2924,22 @@ panel_operate (void *source_panel, FileOperation operation, gboolean force_singl
/* Loop for every file, perform the actual copy operation */ /* Loop for every file, perform the actual copy operation */
for (i = 0; i < panel->count; i++) for (i = 0; i < panel->count; i++)
{ {
const char *source2;
if (!panel->dir.list[i].f.marked) if (!panel->dir.list[i].f.marked)
continue; /* Skip the unmarked ones */ continue; /* Skip the unmarked ones */
source = panel->dir.list[i].fname; source2 = panel->dir.list[i].fname;
src_stat = panel->dir.list[i].st; src_stat = panel->dir.list[i].st;
#ifdef WITH_FULL_PATHS #ifdef WITH_FULL_PATHS
g_free (source_with_path_str); g_free (source_with_path_str);
vfs_path_free (source_with_vpath); vfs_path_free (source_with_vpath);
if (g_path_is_absolute (source)) if (g_path_is_absolute (source2))
source_with_vpath = vfs_path_from_str (source); source_with_vpath = vfs_path_from_str (source2);
else else
source_with_vpath = source_with_vpath =
vfs_path_append_new (panel->cwd_vpath, source, (char *) NULL); vfs_path_append_new (panel->cwd_vpath, source2, (char *) NULL);
source_with_path_str = vfs_path_to_str (source_with_vpath); source_with_path_str = vfs_path_to_str (source_with_vpath);
#endif /* WITH_FULL_PATHS */ #endif /* WITH_FULL_PATHS */
@ -3074,6 +3076,7 @@ panel_operate (void *source_panel, FileOperation operation, gboolean force_singl
file_op_total_context_destroy (tctx); file_op_total_context_destroy (tctx);
ret_fast: ret_fast:
file_op_context_destroy (ctx); file_op_context_destroy (ctx);
g_free (source);
return ret_val; return ret_val;
} }

View File

@ -752,12 +752,14 @@ put_prog_name (void)
if (get_current_type () == view_tree) if (get_current_type () == view_tree)
{ {
WTree *tree = (WTree *) get_panel_widget (get_current_index ()); WTree *tree = (WTree *) get_panel_widget (get_current_index ());
tmp = tree_selected_name (tree);
tmp = vfs_path_to_str (tree_selected_name (tree));
} }
else else
tmp = selection (current_panel)->fname; tmp = g_strdup (selection (current_panel)->fname);
command_insert (cmdline, tmp, TRUE); command_insert (cmdline, tmp, TRUE);
g_free (tmp);
} }
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */

View File

@ -55,7 +55,6 @@
#include "lib/widget.h" #include "lib/widget.h"
#include "lib/event.h" /* mc_event_raise() */ #include "lib/event.h" /* mc_event_raise() */
#include "src/setup.h" /* confirm_delete, panels_options */ #include "src/setup.h" /* confirm_delete, panels_options */
#include "src/keybind-defaults.h" #include "src/keybind-defaults.h"
#include "src/history.h" #include "src/history.h"
@ -188,10 +187,10 @@ save_tree (WTree * tree)
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
static void static void
tree_remove_entry (WTree * tree, char *name) tree_remove_entry (WTree * tree, const vfs_path_t * name_vpath)
{ {
(void) tree; (void) tree;
tree_store_remove_entry (name); tree_store_remove_entry (name_vpath);
} }
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
@ -250,10 +249,14 @@ tree_show_mini_info (WTree * tree, int tree_lines, int tree_cols)
else else
{ {
/* Show full name of selected directory */ /* Show full name of selected directory */
char *tmp_path;
tty_setcolor (tree->is_panel ? NORMAL_COLOR : TREE_NORMALC (h)); tty_setcolor (tree->is_panel ? NORMAL_COLOR : TREE_NORMALC (h));
tty_draw_hline (tree->widget.y + line, tree->widget.x + 1, ' ', tree_cols); tty_draw_hline (tree->widget.y + line, tree->widget.x + 1, ' ', tree_cols);
widget_move (&tree->widget, line, 1); widget_move (&tree->widget, line, 1);
tty_print_string (str_fit_to_term (tree->selected_ptr->name, tree_cols, J_LEFT_FIT)); tmp_path = vfs_path_to_str (tree->selected_ptr->name);
tty_print_string (str_fit_to_term (tmp_path, tree_cols, J_LEFT_FIT));
g_free (tmp_path);
} }
} }
@ -301,25 +304,33 @@ show_tree (WTree * tree)
i = 0; i = 0;
while (current->prev && i < tree->topdiff) while (current->prev && i < tree->topdiff)
{ {
char *current_name;
current = current->prev; current = current->prev;
current_name = vfs_path_to_str (current->name);
if (current->sublevel < tree->selected_ptr->sublevel) if (current->sublevel < tree->selected_ptr->sublevel)
{ {
if (strncmp (current->name, tree->selected_ptr->name, strlen (current->name)) == 0) if (vfs_path_cmp (current->name, tree->selected_ptr->name) == 0)
i++; i++;
} }
else if (current->sublevel == tree->selected_ptr->sublevel) else if (current->sublevel == tree->selected_ptr->sublevel)
{ {
for (j = strlen (current->name) - 1; current->name[j] != PATH_SEP; j--); for (j = strlen (current_name) - 1; current_name[j] != PATH_SEP; j--);
if (strncmp (current->name, tree->selected_ptr->name, j) == 0) if (vfs_path_ncmp (current->name, tree->selected_ptr->name, j) == 0)
i++; i++;
} }
else if (current->sublevel == tree->selected_ptr->sublevel + 1 else
&& strlen (tree->selected_ptr->name) > 1)
{ {
if (strncmp (current->name, tree->selected_ptr->name, if (current->sublevel == tree->selected_ptr->sublevel + 1
strlen (tree->selected_ptr->name)) == 0) && vfs_path_len (tree->selected_ptr->name) > 1)
i++; {
if (vfs_path_ncmp (current->name, tree->selected_ptr->name,
vfs_path_len (tree->selected_ptr->name)) == 0)
i++;
}
} }
g_free (current_name);
} }
tree->topdiff = i; tree->topdiff = i;
} }
@ -345,8 +356,12 @@ show_tree (WTree * tree)
if (current->sublevel == topsublevel) if (current->sublevel == topsublevel)
{ {
/* Show full name */ /* Show full name */
char *current_name;
current_name = vfs_path_to_str (current->name);
tty_print_string (str_fit_to_term tty_print_string (str_fit_to_term
(current->name, tree_cols + (tree->is_panel ? 0 : 1), J_LEFT_FIT)); (current_name, tree_cols + (tree->is_panel ? 0 : 1), J_LEFT_FIT));
g_free (current_name);
} }
else else
{ {
@ -388,22 +403,26 @@ show_tree (WTree * tree)
{ {
if (current->sublevel < tree->selected_ptr->sublevel) if (current->sublevel < tree->selected_ptr->sublevel)
{ {
if (strncmp (current->name, tree->selected_ptr->name, if (vfs_path_ncmp (current->name, tree->selected_ptr->name,
strlen (current->name)) == 0) vfs_path_len (current->name)) == 0)
break; break;
} }
else if (current->sublevel == tree->selected_ptr->sublevel) else if (current->sublevel == tree->selected_ptr->sublevel)
{ {
for (j = strlen (current->name) - 1; current->name[j] != PATH_SEP; j--) char *current_name;
current_name = vfs_path_to_str (current->name);
for (j = strlen (current_name) - 1; current_name[j] != PATH_SEP; j--)
; ;
if (strncmp (current->name, tree->selected_ptr->name, j) == 0) g_free (current_name);
if (vfs_path_ncmp (current->name, tree->selected_ptr->name, j) == 0)
break; break;
} }
else if (current->sublevel == tree->selected_ptr->sublevel + 1 else if (current->sublevel == tree->selected_ptr->sublevel + 1
&& strlen (tree->selected_ptr->name) > 1) && vfs_path_len (tree->selected_ptr->name) > 1)
{ {
if (strncmp (current->name, tree->selected_ptr->name, if (vfs_path_ncmp (current->name, tree->selected_ptr->name,
strlen (tree->selected_ptr->name)) == 0) vfs_path_len (tree->selected_ptr->name)) == 0)
break; break;
} }
current = current->next; current = current->next;
@ -579,17 +598,21 @@ tree_event (WTree * tree, int y)
static void static void
tree_chdir_sel (WTree * tree) tree_chdir_sel (WTree * tree)
{ {
char *tmp_path;
if (!tree->is_panel) if (!tree->is_panel)
return; return;
change_panel (); change_panel ();
if (do_cd (tree->selected_ptr->name, cd_exact)) tmp_path = vfs_path_to_str (tree->selected_ptr->name);
if (do_cd (tmp_path, cd_exact))
select_item (current_panel); select_item (current_panel);
else else
message (D_ERROR, MSG_ERROR, _("Cannot chdir to \"%s\"\n%s"), message (D_ERROR, MSG_ERROR, _("Cannot chdir to \"%s\"\n%s"),
tree->selected_ptr->name, unix_error_string (errno)); tmp_path, unix_error_string (errno));
g_free (tmp_path);
change_panel (); change_panel ();
show_tree (tree); show_tree (tree);
} }
@ -713,27 +736,19 @@ static void
tree_rescan (void *data) tree_rescan (void *data)
{ {
WTree *tree = data; WTree *tree = data;
char *old_dir; int ret;
vfs_path_t *vpath = NULL; vfs_path_t *old_vpath;
int r;
old_dir = vfs_get_current_dir (); old_vpath = vfs_path_clone (vfs_get_raw_current_dir ());
if (old_dir == NULL) if (old_vpath == NULL)
return; return;
if (tree->selected_ptr == NULL) if (tree->selected_ptr != NULL && mc_chdir (tree->selected_ptr->name) == 0)
goto ret; {
tree_store_rescan (tree->selected_ptr->name);
vpath = vfs_path_from_str (tree->selected_ptr->name); ret = mc_chdir (old_vpath);
if (mc_chdir (vpath) != 0) }
goto ret; vfs_path_free (old_vpath);
tree_store_rescan (vpath);
vpath = vfs_path_from_str (old_dir);
r = mc_chdir (vpath);
ret:
vfs_path_free (vpath);
g_free (old_dir);
} }
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
@ -752,13 +767,15 @@ static void
tree_copy (WTree * tree, const char *default_dest) tree_copy (WTree * tree, const char *default_dest)
{ {
char msg[BUF_MEDIUM]; char msg[BUF_MEDIUM];
char *dest; char *dest, *selected_ptr_name;
if (tree->selected_ptr == NULL) if (tree->selected_ptr == NULL)
return; return;
selected_ptr_name = vfs_path_to_str (tree->selected_ptr->name);
g_snprintf (msg, sizeof (msg), _("Copy \"%s\" directory to:"), g_snprintf (msg, sizeof (msg), _("Copy \"%s\" directory to:"),
str_trunc (tree->selected_ptr->name, 50)); str_trunc (selected_ptr_name, 50));
dest = input_expand_dialog (Q_ ("DialogTitle|Copy"), dest = input_expand_dialog (Q_ ("DialogTitle|Copy"),
msg, MC_HISTORY_FM_TREE_COPY, default_dest); msg, MC_HISTORY_FM_TREE_COPY, default_dest);
@ -771,12 +788,13 @@ tree_copy (WTree * tree, const char *default_dest)
tctx = file_op_total_context_new (); tctx = file_op_total_context_new ();
file_op_context_create_ui (ctx, FALSE, FILEGUI_DIALOG_MULTI_ITEM); file_op_context_create_ui (ctx, FALSE, FILEGUI_DIALOG_MULTI_ITEM);
tctx->ask_overwrite = FALSE; tctx->ask_overwrite = FALSE;
copy_dir_dir (tctx, ctx, tree->selected_ptr->name, dest, TRUE, FALSE, FALSE, NULL); copy_dir_dir (tctx, ctx, selected_ptr_name, dest, TRUE, FALSE, FALSE, NULL);
file_op_total_context_destroy (tctx); file_op_total_context_destroy (tctx);
file_op_context_destroy (ctx); file_op_context_destroy (ctx);
} }
g_free (dest); g_free (dest);
g_free (selected_ptr_name);
} }
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
@ -785,7 +803,7 @@ static void
tree_move (WTree * tree, const char *default_dest) tree_move (WTree * tree, const char *default_dest)
{ {
char msg[BUF_MEDIUM]; char msg[BUF_MEDIUM];
char *dest; char *dest, *selected_ptr_name;
struct stat buf; struct stat buf;
FileOpContext *ctx; FileOpContext *ctx;
FileOpTotalContext *tctx; FileOpTotalContext *tctx;
@ -793,39 +811,38 @@ tree_move (WTree * tree, const char *default_dest)
if (tree->selected_ptr == NULL) if (tree->selected_ptr == NULL)
return; return;
selected_ptr_name = vfs_path_to_str (tree->selected_ptr->name);
g_snprintf (msg, sizeof (msg), _("Move \"%s\" directory to:"), g_snprintf (msg, sizeof (msg), _("Move \"%s\" directory to:"),
str_trunc (tree->selected_ptr->name, 50)); str_trunc (selected_ptr_name, 50));
dest = dest =
input_expand_dialog (Q_ ("DialogTitle|Move"), msg, MC_HISTORY_FM_TREE_MOVE, default_dest); input_expand_dialog (Q_ ("DialogTitle|Move"), msg, MC_HISTORY_FM_TREE_MOVE, default_dest);
if (dest == NULL || *dest == '\0') if (dest == NULL || *dest == '\0')
{ goto ret;
g_free (dest);
return;
}
if (stat (dest, &buf)) if (stat (dest, &buf))
{ {
message (D_ERROR, MSG_ERROR, _("Cannot stat the destination\n%s"), message (D_ERROR, MSG_ERROR, _("Cannot stat the destination\n%s"),
unix_error_string (errno)); unix_error_string (errno));
g_free (dest); goto ret;
return;
} }
if (!S_ISDIR (buf.st_mode)) if (!S_ISDIR (buf.st_mode))
{ {
file_error (_("Destination \"%s\" must be a directory\n%s"), dest); file_error (_("Destination \"%s\" must be a directory\n%s"), dest);
g_free (dest); goto ret;
return;
} }
ctx = file_op_context_new (OP_MOVE); ctx = file_op_context_new (OP_MOVE);
tctx = file_op_total_context_new (); tctx = file_op_total_context_new ();
file_op_context_create_ui (ctx, FALSE, FILEGUI_DIALOG_ONE_ITEM); file_op_context_create_ui (ctx, FALSE, FILEGUI_DIALOG_ONE_ITEM);
move_dir_dir (tctx, ctx, tree->selected_ptr->name, dest); move_dir_dir (tctx, ctx, selected_ptr_name, dest);
file_op_total_context_destroy (tctx); file_op_total_context_destroy (tctx);
file_op_context_destroy (ctx); file_op_context_destroy (ctx);
ret:
g_free (selected_ptr_name);
g_free (dest); g_free (dest);
} }
@ -857,30 +874,37 @@ tree_rmdir (void *data)
WTree *tree = data; WTree *tree = data;
FileOpContext *ctx; FileOpContext *ctx;
FileOpTotalContext *tctx; FileOpTotalContext *tctx;
char *selected_ptr_name;
if (!tree->selected_ptr) if (!tree->selected_ptr)
return; return;
selected_ptr_name = vfs_path_to_str (tree->selected_ptr->name);
if (confirm_delete) if (confirm_delete)
{ {
char *buf; char *buf;
int result; int result;
buf = g_strdup_printf (_("Delete %s?"), tree->selected_ptr->name); buf = g_strdup_printf (_("Delete %s?"), selected_ptr_name);
result = query_dialog (Q_ ("DialogTitle|Delete"), buf, D_ERROR, 2, _("&Yes"), _("&No")); result = query_dialog (Q_ ("DialogTitle|Delete"), buf, D_ERROR, 2, _("&Yes"), _("&No"));
g_free (buf); g_free (buf);
if (result != 0) if (result != 0)
{
g_free (selected_ptr_name);
return; return;
}
} }
ctx = file_op_context_new (OP_DELETE); ctx = file_op_context_new (OP_DELETE);
tctx = file_op_total_context_new (); tctx = file_op_total_context_new ();
file_op_context_create_ui (ctx, FALSE, FILEGUI_DIALOG_ONE_ITEM); file_op_context_create_ui (ctx, FALSE, FILEGUI_DIALOG_ONE_ITEM);
if (erase_dir (tctx, ctx, tree->selected_ptr->name) == FILE_CONT) if (erase_dir (tctx, ctx, selected_ptr_name) == FILE_CONT)
tree_forget (tree); tree_forget (tree);
file_op_total_context_destroy (tctx); file_op_total_context_destroy (tctx);
file_op_context_destroy (ctx); file_op_context_destroy (ctx);
g_free (selected_ptr_name);
} }
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
@ -1267,21 +1291,23 @@ tree_new (int y, int x, int lines, int cols, gboolean is_panel)
void void
tree_chdir (WTree * tree, const char *dir) tree_chdir (WTree * tree, const char *dir)
{ {
vfs_path_t *vpath;
tree_entry *current; tree_entry *current;
current = tree_store_whereis (dir); vpath = vfs_path_from_str (dir);
current = tree_store_whereis (vpath);
if (current != NULL) if (current != NULL)
{ {
tree->selected_ptr = current; tree->selected_ptr = current;
tree_check_focus (tree); tree_check_focus (tree);
} }
vfs_path_free (vpath);
} }
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
/** Return name of the currently selected entry */ /** Return name of the currently selected entry */
char * vfs_path_t *
tree_selected_name (const WTree * tree) tree_selected_name (const WTree * tree)
{ {
return tree->selected_ptr->name; return tree->selected_ptr->name;

View File

@ -27,7 +27,7 @@ struct Dlg_head;
WTree *tree_new (int y, int x, int lines, int cols, gboolean is_panel); WTree *tree_new (int y, int x, int lines, int cols, gboolean is_panel);
void tree_chdir (WTree * tree, const char *dir); void tree_chdir (WTree * tree, const char *dir);
char *tree_selected_name (const WTree * tree); vfs_path_t *tree_selected_name (const WTree * tree);
void sync_tree (const char *pathname); void sync_tree (const char *pathname);

View File

@ -53,6 +53,7 @@
#include "lib/mcconfig.h" #include "lib/mcconfig.h"
#include "lib/vfs/vfs.h" #include "lib/vfs/vfs.h"
#include "lib/fileloc.h" #include "lib/fileloc.h"
#include "lib/strescape.h"
#include "lib/hook.h" #include "lib/hook.h"
#include "lib/util.h" #include "lib/util.h"
@ -77,7 +78,7 @@ static hook_t *remove_entry_hooks;
/*** file scope functions ************************************************************************/ /*** file scope functions ************************************************************************/
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
static tree_entry *tree_store_add_entry (const char *name); static tree_entry *tree_store_add_entry (const vfs_path_t * name);
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
@ -88,57 +89,85 @@ tree_store_dirty (int state)
} }
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
/** Returns the number of common bytes in the strings. */ /**
*
* @return the number of common bytes in the strings.
*/
static size_t static size_t
str_common (const char *s1, const char *s2) str_common (const vfs_path_t * s1_vpath, const vfs_path_t * s2_vpath)
{ {
size_t result = 0; size_t result = 0;
char *s1, *fs1;
char *s2, *fs2;
s1 = fs1 = vfs_path_to_str (s1_vpath);
s2 = fs2 = vfs_path_to_str (s2_vpath);
while (*s1 != '\0' && *s2 != '\0' && *s1++ == *s2++) while (*s1 != '\0' && *s2 != '\0' && *s1++ == *s2++)
result++; result++;
g_free (fs1);
g_free (fs2);
return result; return result;
} }
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
/* The directory names are arranged in a single linked list in the same /** The directory names are arranged in a single linked list in the same
order as they are displayed. When the tree is displayed the expected * order as they are displayed. When the tree is displayed the expected
order is like this: * order is like this:
/ * /
/bin * /bin
/etc * /etc
/etc/X11 * /etc/X11
/etc/rc.d * /etc/rc.d
/etc.old/X11 * /etc.old/X11
/etc.old/rc.d * /etc.old/rc.d
/usr * /usr
*
i.e. the required collating sequence when comparing two directory names is * i.e. the required collating sequence when comparing two directory names is
'\0' < PATH_SEP < all-other-characters-in-encoding-order * '\0' < PATH_SEP < all-other-characters-in-encoding-order
*
Since strcmp doesn't fulfil this requirement we use pathcmp when * Since strcmp doesn't fulfil this requirement we use pathcmp when
inserting directory names into the list. The meaning of the return value * inserting directory names into the list. The meaning of the return value
of pathcmp and strcmp are the same (an integer less than, equal to, or * of pathcmp and strcmp are the same (an integer less than, equal to, or
greater than zero if p1 is found to be less than, to match, or be greater * greater than zero if p1 is found to be less than, to match, or be greater
than p2. * than p2.
*/ */
static int static int
pathcmp (const char *p1, const char *p2) pathcmp (const vfs_path_t * p1_vpath, const vfs_path_t * p2_vpath)
{ {
int ret_val;
char *p1, *fp1;
char *p2, *fp2;
p1 = fp1 = vfs_path_to_str (p1_vpath);
p2 = fp2 = vfs_path_to_str (p2_vpath);
for (; *p1 == *p2; p1++, p2++) for (; *p1 == *p2; p1++, p2++)
if (*p1 == '\0') if (*p1 == '\0')
{
g_free (fp1);
g_free (fp2);
return 0; return 0;
}
if (*p1 == '\0') if (*p1 == '\0')
return -1; ret_val = -1;
if (*p2 == '\0') else if (*p2 == '\0')
return 1; ret_val = 1;
if (*p1 == PATH_SEP) else if (*p1 == PATH_SEP)
return -1; ret_val = -1;
if (*p2 == PATH_SEP) else if (*p2 == PATH_SEP)
return 1; ret_val = 1;
return (*p1 - *p2); else
ret_val = (*p1 - *p2);
g_free (fp1);
g_free (fp2);
return ret_val;
} }
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
@ -250,11 +279,17 @@ tree_store_load_from (char *name)
different = strtok (NULL, ""); different = strtok (NULL, "");
if (different) if (different)
{ {
vfs_path_t *vpath = vfs_path_from_str (oldname); vfs_path_t *vpath;
vpath = vfs_path_from_str (oldname);
strcpy (oldname + common, different); strcpy (oldname + common, different);
if (vfs_file_is_local (vpath)) if (vfs_file_is_local (vpath))
{ {
e = tree_store_add_entry (oldname); vfs_path_t *tmp_vpath;
tmp_vpath = vfs_path_from_str (oldname);
e = tree_store_add_entry (tmp_vpath);
vfs_path_free (tmp_vpath);
e->scanned = scanned; e->scanned = scanned;
} }
vfs_path_free (vpath); vfs_path_free (vpath);
@ -263,10 +298,12 @@ tree_store_load_from (char *name)
} }
else else
{ {
vfs_path_t *vpath = vfs_path_from_str (lc_name); vfs_path_t *vpath;
vpath = vfs_path_from_str (lc_name);
if (vfs_file_is_local (vpath)) if (vfs_file_is_local (vpath))
{ {
e = tree_store_add_entry (lc_name); e = tree_store_add_entry (vpath);
e->scanned = scanned; e->scanned = scanned;
} }
vfs_path_free (vpath); vfs_path_free (vpath);
@ -281,7 +318,7 @@ tree_store_load_from (char *name)
if (!ts.tree_first) if (!ts.tree_first)
{ {
vfs_path_t *tmp_vpath = vfs_path_from_str (PATH_SEP_STR); vfs_path_t *tmp_vpath = vfs_path_from_str (PATH_SEP_STR);
tree_store_add_entry (PATH_SEP_STR); tree_store_add_entry (tmp_vpath);
tree_store_rescan (tmp_vpath); tree_store_rescan (tmp_vpath);
vfs_path_free (tmp_vpath); vfs_path_free (tmp_vpath);
ts.loaded = TRUE; ts.loaded = TRUE;
@ -293,43 +330,14 @@ tree_store_load_from (char *name)
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
static char * static char *
encode (const char *string) encode (const vfs_path_t * vpath, size_t offset)
{ {
int special_chars; char *string, *ret_val;
const char *p;
char *q;
char *res;
for (special_chars = 0, p = string; *p; p++) string = vfs_path_to_str (vpath);
{ ret_val = strutils_escape (string + offset, -1, "\n\\", FALSE);
if (*p == '\n' || *p == '\\') g_free (string);
special_chars++; return ret_val;
}
res = g_malloc (p - string + special_chars + 1);
for (p = string, q = res; *p; p++, q++)
{
if (*p != '\n' && *p != '\\')
{
*q = *p;
continue;
}
*q++ = '\\';
switch (*p)
{
case '\n':
*q = 'n';
break;
case '\\':
*q = '\\';
break;
}
}
*q = 0;
return res;
} }
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
@ -351,21 +359,20 @@ tree_store_save_to (char *name)
while (current) while (current)
{ {
int i, common; int i, common;
vfs_path_t *vpath = vfs_path_from_str (current->name);
if (vfs_file_is_local (vpath)) if (vfs_file_is_local (current->name))
{ {
/* Clear-text compression */ /* Clear-text compression */
if (current->prev && (common = str_common (current->prev->name, current->name)) > 2) if (current->prev && (common = str_common (current->prev->name, current->name)) > 2)
{ {
char *encoded = encode (current->name + common); char *encoded = encode (current->name, common);
i = fprintf (file, "%d:%d %s\n", current->scanned, common, encoded); i = fprintf (file, "%d:%d %s\n", current->scanned, common, encoded);
g_free (encoded); g_free (encoded);
} }
else else
{ {
char *encoded = encode (current->name); char *encoded = encode (current->name, 0);
i = fprintf (file, "%d:%s\n", current->scanned, encoded); i = fprintf (file, "%d:%s\n", current->scanned, encoded);
g_free (encoded); g_free (encoded);
@ -375,11 +382,9 @@ tree_store_save_to (char *name)
{ {
fprintf (stderr, _("Cannot write to the %s file:\n%s\n"), fprintf (stderr, _("Cannot write to the %s file:\n%s\n"),
name, unix_error_string (errno)); name, unix_error_string (errno));
vfs_path_free (vpath);
break; break;
} }
} }
vfs_path_free (vpath);
current = current->next; current = current->next;
} }
tree_store_dirty (FALSE); tree_store_dirty (FALSE);
@ -391,13 +396,12 @@ tree_store_save_to (char *name)
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
static tree_entry * static tree_entry *
tree_store_add_entry (const char *name) tree_store_add_entry (const vfs_path_t * name)
{ {
int flag = -1; int flag = -1;
tree_entry *current = ts.tree_first; tree_entry *current = ts.tree_first;
tree_entry *old = NULL; tree_entry *old = NULL;
tree_entry *new; tree_entry *new;
int i, len;
int submask = 0; int submask = 0;
if (ts.tree_last && ts.tree_last->next) if (ts.tree_last && ts.tree_last->next)
@ -452,15 +456,16 @@ tree_store_add_entry (const char *name)
} }
/* Calculate attributes */ /* Calculate attributes */
new->name = g_strdup (name); new->name = vfs_path_clone (name);
len = strlen (new->name); new->sublevel = vfs_path_tokens_count (new->name) + 1;
new->sublevel = 0; {
for (i = 0; i < len; i++) const char *new_name;
if (new->name[i] == PATH_SEP)
{ new_name = vfs_path_get_last_path_str (new->name);
new->sublevel++; new->subname = strrchr (new_name, '/');
new->subname = new->name + i + 1; if (new->subname == NULL)
} new->subname = new_name;
}
if (new->next) if (new->next)
submask = new->next->submask; submask = new->next->submask;
else else
@ -483,18 +488,11 @@ tree_store_add_entry (const char *name)
if (new->sublevel > 1) if (new->sublevel > 1)
{ {
/* Let's check if the parent directory is in the tree */ /* Let's check if the parent directory is in the tree */
char *parent = g_strdup (new->name); vfs_path_t *tmp_vpath;
for (i = strlen (parent) - 1; i > 1; i--) tmp_vpath = vfs_path_vtokens_get (new->name, 0, new->sublevel - 1);
{ tree_store_add_entry (tmp_vpath);
if (parent[i] == PATH_SEP) vfs_path_free (tmp_vpath);
{
parent[i] = 0;
tree_store_add_entry (parent);
break;
}
}
g_free (parent);
} }
tree_store_dirty (TRUE); tree_store_dirty (TRUE);
@ -587,11 +585,13 @@ process_special_dirs (GList ** special_dirs, char *file)
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
static gboolean static gboolean
should_skip_directory (const char *dir) should_skip_directory (const vfs_path_t * vpath)
{ {
static GList *special_dirs = NULL; static GList *special_dirs = NULL;
GList *l; GList *l;
static gboolean loaded = FALSE; static gboolean loaded = FALSE;
char *dir;
gboolean ret = FALSE;
if (!loaded) if (!loaded)
{ {
@ -601,11 +601,16 @@ should_skip_directory (const char *dir)
process_special_dirs (&special_dirs, global_profile_name); process_special_dirs (&special_dirs, global_profile_name);
} }
dir = vfs_path_to_str (vpath);
for (l = special_dirs; l != NULL; l = g_list_next (l)) for (l = special_dirs; l != NULL; l = g_list_next (l))
if (strncmp (dir, l->data, strlen (l->data)) == 0) if (strncmp (dir, l->data, strlen (l->data)) == 0)
return TRUE; {
ret = TRUE;
break;
}
return FALSE; g_free (dir);
return ret;
} }
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
@ -614,7 +619,7 @@ should_skip_directory (const char *dir)
/* Searches for specified directory */ /* Searches for specified directory */
tree_entry * tree_entry *
tree_store_whereis (const char *name) tree_store_whereis (const vfs_path_t * name)
{ {
tree_entry *current = ts.tree_first; tree_entry *current = ts.tree_first;
int flag = -1; int flag = -1;
@ -705,36 +710,48 @@ tree_store_remove_entry_remove_hook (tree_store_remove_fn callback)
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
void void
tree_store_remove_entry (const char *name) tree_store_remove_entry (const vfs_path_t * name_vpath)
{ {
tree_entry *current, *base, *old; tree_entry *current, *base, *old;
int len; size_t len;
g_return_if_fail (name != NULL); g_return_if_fail (name_vpath != NULL);
/* Miguel Ugly hack */ /* Miguel Ugly hack */
if (name[0] == PATH_SEP && name[1] == 0) {
return; char *name;
gboolean is_root;
name = vfs_path_to_str (name_vpath);
is_root = (name[0] == PATH_SEP && name[1] == '\0');
g_free (name);
if (is_root)
return;
}
/* Miguel Ugly hack end */ /* Miguel Ugly hack end */
base = tree_store_whereis (name); base = tree_store_whereis (name_vpath);
if (!base) if (!base)
return; /* Doesn't exist */ return; /* Doesn't exist */
len = strlen (base->name); len = vfs_path_len (base->name);
current = base->next; current = base->next;
while (current while (current != NULL && vfs_path_ncmp (current->name, base->name, len) == 0)
&& strncmp (current->name, base->name, len) == 0
&& (current->name[len] == '\0' || current->name[len] == PATH_SEP))
{ {
char *current_name;
gboolean ok;
current_name = vfs_path_to_str (current->name);
ok = (current_name[len] == '\0' || current_name[len] == PATH_SEP);
g_free (current_name);
if (!ok)
break;
old = current; old = current;
current = current->next; current = current->next;
remove_entry (old); remove_entry (old);
} }
remove_entry (base); remove_entry (base);
tree_store_dirty (TRUE); tree_store_dirty (TRUE);
return;
} }
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
@ -743,9 +760,10 @@ tree_store_remove_entry (const char *name)
void void
tree_store_mark_checked (const char *subname) tree_store_mark_checked (const char *subname)
{ {
char *name; vfs_path_t *name;
char *check_name;
tree_entry *current, *base; tree_entry *current, *base;
int flag = 1, len; int flag = 1;
if (!ts.loaded) if (!ts.loaded)
return; return;
@ -755,10 +773,13 @@ tree_store_mark_checked (const char *subname)
/* Calculate the full name of the subdirectory */ /* Calculate the full name of the subdirectory */
if (subname[0] == '.' && (subname[1] == 0 || (subname[1] == '.' && subname[2] == 0))) if (subname[0] == '.' && (subname[1] == 0 || (subname[1] == '.' && subname[2] == 0)))
return; return;
if (ts.check_name[0] == PATH_SEP && ts.check_name[1] == 0)
name = g_strconcat (PATH_SEP_STR, subname, (char *) NULL); check_name = vfs_path_to_str (ts.check_name);
if (check_name[0] == PATH_SEP && check_name[1] == 0)
name = vfs_path_build_filename (PATH_SEP_STR, subname, NULL);
else else
name = concat_dir_and_file (ts.check_name, subname); name = vfs_path_append_new (ts.check_name, subname, NULL);
g_free (check_name);
/* Search for the subdirectory */ /* Search for the subdirectory */
current = ts.check_start; current = ts.check_start;
@ -769,7 +790,7 @@ tree_store_mark_checked (const char *subname)
{ {
/* Doesn't exist -> add it */ /* Doesn't exist -> add it */
current = tree_store_add_entry (name); current = tree_store_add_entry (name);
ts.add_queue = g_list_prepend (ts.add_queue, g_strdup (name)); ts.add_queue_vpath = g_list_prepend (ts.add_queue_vpath, vfs_path_clone (name));
} }
g_free (name); g_free (name);
@ -777,13 +798,20 @@ tree_store_mark_checked (const char *subname)
base = current; base = current;
if (base) if (base)
{ {
len = strlen (base->name); size_t len;
len = vfs_path_len (base->name);
base->mark = 0; base->mark = 0;
current = base->next; current = base->next;
while (current while (current != NULL && vfs_path_ncmp (current->name, base->name, len) == 0)
&& strncmp (current->name, base->name, len) == 0
&& (current->name[len] == '\0' || current->name[len] == PATH_SEP || len == 1))
{ {
gboolean ok;
check_name = vfs_path_to_str (current->name);
ok = (check_name[len] == '\0' || check_name[len] == PATH_SEP || len == 1);
g_free (check_name);
if (!ok)
break;
current->mark = 0; current->mark = 0;
current = current->next; current = current->next;
} }
@ -794,7 +822,7 @@ tree_store_mark_checked (const char *subname)
/** Mark the subdirectories of the current directory for delete */ /** Mark the subdirectories of the current directory for delete */
tree_entry * tree_entry *
tree_store_start_check (const char *path) tree_store_start_check (const vfs_path_t * vpath)
{ {
tree_entry *current, *retval; tree_entry *current, *retval;
size_t len; size_t len;
@ -806,41 +834,42 @@ tree_store_start_check (const char *path)
ts.check_start = NULL; ts.check_start = NULL;
/* Search for the start of subdirectories */ /* Search for the start of subdirectories */
current = tree_store_whereis (path); current = tree_store_whereis (vpath);
if (!current) if (!current)
{ {
struct stat s; struct stat s;
vfs_path_t *vpath = vfs_path_from_str (path);
if (mc_stat (vpath, &s) == -1) if (mc_stat (vpath, &s) == -1)
{
vfs_path_free (vpath);
return NULL; return NULL;
}
vfs_path_free (vpath);
if (!S_ISDIR (s.st_mode)) if (!S_ISDIR (s.st_mode))
return NULL; return NULL;
current = tree_store_add_entry (path); current = tree_store_add_entry (vpath);
ts.check_name = g_strdup (path); ts.check_name = vfs_path_clone (vpath);
return current; return current;
} }
ts.check_name = g_strdup (path); ts.check_name = vfs_path_clone (vpath);
retval = current; retval = current;
/* Mark old subdirectories for delete */ /* Mark old subdirectories for delete */
ts.check_start = current->next; ts.check_start = current->next;
len = strlen (ts.check_name); len = vfs_path_len (ts.check_name);
current = ts.check_start; current = ts.check_start;
while (current while (current != NULL && vfs_path_cmp (current->name, ts.check_name) == 0)
&& strncmp (current->name, ts.check_name, len) == 0
&& (current->name[len] == '\0' || current->name[len] == PATH_SEP || len == 1))
{ {
char *current_name;
gboolean ok;
current_name = vfs_path_to_str (current->name);
ok = (current_name[len] == '\0' || (current_name[len] == PATH_SEP || len == 1));
g_free (current_name);
if (!ok)
break;
current->mark = 1; current->mark = 1;
current = current->next; current = current->next;
} }
@ -864,13 +893,20 @@ tree_store_end_check (void)
g_return_if_fail (ts.check_name != NULL); g_return_if_fail (ts.check_name != NULL);
/* Check delete marks and delete if found */ /* Check delete marks and delete if found */
len = strlen (ts.check_name); len = vfs_path_len (ts.check_name);
current = ts.check_start; current = ts.check_start;
while (current while (current != NULL && vfs_path_ncmp (current->name, ts.check_name, len) == 0)
&& strncmp (current->name, ts.check_name, len) == 0
&& (current->name[len] == '\0' || current->name[len] == PATH_SEP || len == 1))
{ {
char *current_name;
gboolean ok;
current_name = vfs_path_to_str (current->name);
ok = (current_name[len] == '\0' || current_name[len] == PATH_SEP || len == 1);
g_free (current_name);
if (!ok)
break;
old = current; old = current;
current = current->next; current = current->next;
if (old->mark) if (old->mark)
@ -878,13 +914,13 @@ tree_store_end_check (void)
} }
/* get the stuff in the scan order */ /* get the stuff in the scan order */
ts.add_queue = g_list_reverse (ts.add_queue); ts.add_queue_vpath = g_list_reverse (ts.add_queue_vpath);
the_queue = ts.add_queue; the_queue = ts.add_queue_vpath;
ts.add_queue = NULL; ts.add_queue_vpath = NULL;
g_free (ts.check_name); g_free (ts.check_name);
ts.check_name = NULL; ts.check_name = NULL;
g_list_foreach (the_queue, (GFunc) g_free, NULL); g_list_foreach (the_queue, (GFunc) vfs_path_free, NULL);
g_list_free (the_queue); g_list_free (the_queue);
} }
@ -897,23 +933,17 @@ tree_store_rescan (const vfs_path_t * vpath)
struct dirent *dp; struct dirent *dp;
struct stat buf; struct stat buf;
tree_entry *entry; tree_entry *entry;
char *dir = vfs_path_to_str (vpath);
if (should_skip_directory (dir)) if (should_skip_directory (vpath))
{ {
entry = tree_store_add_entry (dir); entry = tree_store_add_entry (vpath);
entry->scanned = 1; entry->scanned = 1;
g_free (dir);
return entry; return entry;
} }
entry = tree_store_start_check (dir); entry = tree_store_start_check (vpath);
if (entry == NULL)
if (!entry)
{
g_free (dir);
return NULL; return NULL;
}
dirp = mc_opendir (vpath); dirp = mc_opendir (vpath);
if (dirp) if (dirp)
@ -940,7 +970,6 @@ tree_store_rescan (const vfs_path_t * vpath)
} }
tree_store_end_check (); tree_store_end_check ();
entry->scanned = 1; entry->scanned = 1;
g_free (dir);
return entry; return entry;
} }

View File

@ -21,7 +21,7 @@ typedef void (*tree_store_remove_fn) (struct tree_entry * tree, void *data);
typedef struct tree_entry typedef struct tree_entry
{ {
char *name; /* The full path of directory */ vfs_path_t *name; /* The full path of directory */
int sublevel; /* Number of parent directories (slashes) */ int sublevel; /* Number of parent directories (slashes) */
long submask; /* Bitmask of existing sublevels after this entry */ long submask; /* Bitmask of existing sublevels after this entry */
const char *subname; /* The last part of name (the actual name) */ const char *subname; /* The last part of name (the actual name) */
@ -36,8 +36,8 @@ struct TreeStore
tree_entry *tree_first; /* First entry in the list */ tree_entry *tree_first; /* First entry in the list */
tree_entry *tree_last; /* Last entry in the list */ tree_entry *tree_last; /* Last entry in the list */
tree_entry *check_start; /* Start of checked subdirectories */ tree_entry *check_start; /* Start of checked subdirectories */
char *check_name; vfs_path_t *check_name;
GList *add_queue; /* List of strings of added directories */ GList *add_queue_vpath; /* List of vfs_path_t objects of added directories */
unsigned int loaded:1; unsigned int loaded:1;
unsigned int dirty:1; unsigned int dirty:1;
}; };
@ -49,11 +49,11 @@ struct TreeStore
struct TreeStore *tree_store_get (void); struct TreeStore *tree_store_get (void);
int tree_store_load (void); int tree_store_load (void);
int tree_store_save (void); int tree_store_save (void);
void tree_store_remove_entry (const char *name); void tree_store_remove_entry (const vfs_path_t * name_vpath);
tree_entry *tree_store_start_check (const char *path); tree_entry *tree_store_start_check (const vfs_path_t * vpath);
void tree_store_mark_checked (const char *subname); void tree_store_mark_checked (const char *subname);
void tree_store_end_check (void); void tree_store_end_check (void);
tree_entry *tree_store_whereis (const char *name); tree_entry *tree_store_whereis (const vfs_path_t * name);
tree_entry *tree_store_rescan (const vfs_path_t * vpath); tree_entry *tree_store_rescan (const vfs_path_t * vpath);
void tree_store_add_entry_remove_hook (tree_store_remove_fn callback, void *data); void tree_store_add_entry_remove_hook (tree_store_remove_fn callback, void *data);