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 ddf8c542c9
commit 3529890d0c
8 changed files with 303 additions and 243 deletions

View File

@ -916,7 +916,7 @@ tree_box (const char *current_dir)
((Widget *) bar)->y = LINES - 1;
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);
return val;

View File

@ -553,7 +553,7 @@ do_load_dir (const char *path, dir_list * list, sortfn * sort, gboolean lc_rever
goto ret;
}
tree_store_start_check (path);
tree_store_start_check (vpath);
/* Do not add a ".." entry to the root directory */
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;
}
tmp_path = vfs_path_to_str (vpath);
tree_store_start_check (tmp_path);
tree_store_start_check (vpath);
marked_files = g_hash_table_new (g_str_hash, g_str_equal);
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
(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))
{
clean_dir (list, count);
clean_dir (&dir_copy, count);
g_free (tmp_path);
return next_free;
}
@ -676,7 +677,6 @@ do_reload_dir (const vfs_path_t * vpath, dir_list * list, sortfn * sort, int cou
next_free++;
}
g_free (tmp_path);
while ((dp = mc_readdir (dirp)))
{

View File

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

View File

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

View File

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

View File

@ -53,6 +53,7 @@
#include "lib/mcconfig.h"
#include "lib/vfs/vfs.h"
#include "lib/fileloc.h"
#include "lib/strescape.h"
#include "lib/hook.h"
#include "lib/util.h"
@ -77,7 +78,7 @@ static hook_t *remove_entry_hooks;
/*** 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
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;
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++)
result++;
g_free (fs1);
g_free (fs2);
return result;
}
/* --------------------------------------------------------------------------------------------- */
/* 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 is like this:
/
/bin
/etc
/etc/X11
/etc/rc.d
/etc.old/X11
/etc.old/rc.d
/usr
i.e. the required collating sequence when comparing two directory names is
'\0' < PATH_SEP < all-other-characters-in-encoding-order
Since strcmp doesn't fulfil this requirement we use pathcmp when
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
greater than zero if p1 is found to be less than, to match, or be greater
than p2.
/** 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 is like this:
* /
* /bin
* /etc
* /etc/X11
* /etc/rc.d
* /etc.old/X11
* /etc.old/rc.d
* /usr
*
* i.e. the required collating sequence when comparing two directory names is
* '\0' < PATH_SEP < all-other-characters-in-encoding-order
*
* Since strcmp doesn't fulfil this requirement we use pathcmp when
* 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
* greater than zero if p1 is found to be less than, to match, or be greater
* than p2.
*/
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++)
if (*p1 == '\0')
{
g_free (fp1);
g_free (fp2);
return 0;
}
if (*p1 == '\0')
return -1;
if (*p2 == '\0')
return 1;
if (*p1 == PATH_SEP)
return -1;
if (*p2 == PATH_SEP)
return 1;
return (*p1 - *p2);
ret_val = -1;
else if (*p2 == '\0')
ret_val = 1;
else if (*p1 == PATH_SEP)
ret_val = -1;
else if (*p2 == PATH_SEP)
ret_val = 1;
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, "");
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);
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;
}
vfs_path_free (vpath);
@ -263,10 +298,12 @@ tree_store_load_from (char *name)
}
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))
{
e = tree_store_add_entry (lc_name);
e = tree_store_add_entry (vpath);
e->scanned = scanned;
}
vfs_path_free (vpath);
@ -281,7 +318,7 @@ tree_store_load_from (char *name)
if (!ts.tree_first)
{
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);
vfs_path_free (tmp_vpath);
ts.loaded = TRUE;
@ -293,43 +330,14 @@ tree_store_load_from (char *name)
/* --------------------------------------------------------------------------------------------- */
static char *
encode (const char *string)
encode (const vfs_path_t * vpath, size_t offset)
{
int special_chars;
const char *p;
char *q;
char *res;
char *string, *ret_val;
for (special_chars = 0, p = string; *p; p++)
{
if (*p == '\n' || *p == '\\')
special_chars++;
}
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;
string = vfs_path_to_str (vpath);
ret_val = strutils_escape (string + offset, -1, "\n\\", FALSE);
g_free (string);
return ret_val;
}
/* --------------------------------------------------------------------------------------------- */
@ -351,21 +359,20 @@ tree_store_save_to (char *name)
while (current)
{
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 */
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);
g_free (encoded);
}
else
{
char *encoded = encode (current->name);
char *encoded = encode (current->name, 0);
i = fprintf (file, "%d:%s\n", current->scanned, 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"),
name, unix_error_string (errno));
vfs_path_free (vpath);
break;
}
}
vfs_path_free (vpath);
current = current->next;
}
tree_store_dirty (FALSE);
@ -391,13 +396,12 @@ tree_store_save_to (char *name)
/* --------------------------------------------------------------------------------------------- */
static tree_entry *
tree_store_add_entry (const char *name)
tree_store_add_entry (const vfs_path_t * name)
{
int flag = -1;
tree_entry *current = ts.tree_first;
tree_entry *old = NULL;
tree_entry *new;
int i, len;
int submask = 0;
if (ts.tree_last && ts.tree_last->next)
@ -452,15 +456,16 @@ tree_store_add_entry (const char *name)
}
/* Calculate attributes */
new->name = g_strdup (name);
len = strlen (new->name);
new->sublevel = 0;
for (i = 0; i < len; i++)
if (new->name[i] == PATH_SEP)
{
new->sublevel++;
new->subname = new->name + i + 1;
}
new->name = vfs_path_clone (name);
new->sublevel = vfs_path_tokens_count (new->name) + 1;
{
const char *new_name;
new_name = vfs_path_get_last_path_str (new->name);
new->subname = strrchr (new_name, '/');
if (new->subname == NULL)
new->subname = new_name;
}
if (new->next)
submask = new->next->submask;
else
@ -483,18 +488,11 @@ tree_store_add_entry (const char *name)
if (new->sublevel > 1)
{
/* 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--)
{
if (parent[i] == PATH_SEP)
{
parent[i] = 0;
tree_store_add_entry (parent);
break;
}
}
g_free (parent);
tmp_vpath = vfs_path_vtokens_get (new->name, 0, new->sublevel - 1);
tree_store_add_entry (tmp_vpath);
vfs_path_free (tmp_vpath);
}
tree_store_dirty (TRUE);
@ -587,11 +585,13 @@ process_special_dirs (GList ** special_dirs, char *file)
/* --------------------------------------------------------------------------------------------- */
static gboolean
should_skip_directory (const char *dir)
should_skip_directory (const vfs_path_t * vpath)
{
static GList *special_dirs = NULL;
GList *l;
static gboolean loaded = FALSE;
char *dir;
gboolean ret = FALSE;
if (!loaded)
{
@ -601,11 +601,16 @@ should_skip_directory (const char *dir)
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))
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 */
tree_entry *
tree_store_whereis (const char *name)
tree_store_whereis (const vfs_path_t * name)
{
tree_entry *current = ts.tree_first;
int flag = -1;
@ -705,36 +710,48 @@ tree_store_remove_entry_remove_hook (tree_store_remove_fn callback)
/* --------------------------------------------------------------------------------------------- */
void
tree_store_remove_entry (const char *name)
tree_store_remove_entry (const vfs_path_t * name_vpath)
{
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 */
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 */
base = tree_store_whereis (name);
base = tree_store_whereis (name_vpath);
if (!base)
return; /* Doesn't exist */
len = strlen (base->name);
len = vfs_path_len (base->name);
current = base->next;
while (current
&& strncmp (current->name, base->name, len) == 0
&& (current->name[len] == '\0' || current->name[len] == PATH_SEP))
while (current != NULL && vfs_path_ncmp (current->name, base->name, len) == 0)
{
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;
current = current->next;
remove_entry (old);
}
remove_entry (base);
tree_store_dirty (TRUE);
return;
}
/* --------------------------------------------------------------------------------------------- */
@ -743,9 +760,10 @@ tree_store_remove_entry (const char *name)
void
tree_store_mark_checked (const char *subname)
{
char *name;
vfs_path_t *name;
char *check_name;
tree_entry *current, *base;
int flag = 1, len;
int flag = 1;
if (!ts.loaded)
return;
@ -755,10 +773,13 @@ tree_store_mark_checked (const char *subname)
/* Calculate the full name of the subdirectory */
if (subname[0] == '.' && (subname[1] == 0 || (subname[1] == '.' && subname[2] == 0)))
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
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 */
current = ts.check_start;
@ -769,7 +790,7 @@ tree_store_mark_checked (const char *subname)
{
/* Doesn't exist -> add it */
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);
@ -777,13 +798,20 @@ tree_store_mark_checked (const char *subname)
base = current;
if (base)
{
len = strlen (base->name);
size_t len;
len = vfs_path_len (base->name);
base->mark = 0;
current = base->next;
while (current
&& strncmp (current->name, base->name, len) == 0
&& (current->name[len] == '\0' || current->name[len] == PATH_SEP || len == 1))
while (current != NULL && vfs_path_ncmp (current->name, base->name, len) == 0)
{
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 = current->next;
}
@ -794,7 +822,7 @@ tree_store_mark_checked (const char *subname)
/** Mark the subdirectories of the current directory for delete */
tree_entry *
tree_store_start_check (const char *path)
tree_store_start_check (const vfs_path_t * vpath)
{
tree_entry *current, *retval;
size_t len;
@ -806,41 +834,42 @@ tree_store_start_check (const char *path)
ts.check_start = NULL;
/* Search for the start of subdirectories */
current = tree_store_whereis (path);
current = tree_store_whereis (vpath);
if (!current)
{
struct stat s;
vfs_path_t *vpath = vfs_path_from_str (path);
if (mc_stat (vpath, &s) == -1)
{
vfs_path_free (vpath);
return NULL;
}
vfs_path_free (vpath);
if (!S_ISDIR (s.st_mode))
return NULL;
current = tree_store_add_entry (path);
ts.check_name = g_strdup (path);
current = tree_store_add_entry (vpath);
ts.check_name = vfs_path_clone (vpath);
return current;
}
ts.check_name = g_strdup (path);
ts.check_name = vfs_path_clone (vpath);
retval = current;
/* Mark old subdirectories for delete */
ts.check_start = current->next;
len = strlen (ts.check_name);
len = vfs_path_len (ts.check_name);
current = ts.check_start;
while (current
&& strncmp (current->name, ts.check_name, len) == 0
&& (current->name[len] == '\0' || current->name[len] == PATH_SEP || len == 1))
while (current != NULL && vfs_path_cmp (current->name, ts.check_name) == 0)
{
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 = current->next;
}
@ -864,13 +893,20 @@ tree_store_end_check (void)
g_return_if_fail (ts.check_name != NULL);
/* Check delete marks and delete if found */
len = strlen (ts.check_name);
len = vfs_path_len (ts.check_name);
current = ts.check_start;
while (current
&& strncmp (current->name, ts.check_name, len) == 0
&& (current->name[len] == '\0' || current->name[len] == PATH_SEP || len == 1))
while (current != NULL && vfs_path_ncmp (current->name, ts.check_name, len) == 0)
{
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;
current = current->next;
if (old->mark)
@ -878,13 +914,13 @@ tree_store_end_check (void)
}
/* get the stuff in the scan order */
ts.add_queue = g_list_reverse (ts.add_queue);
the_queue = ts.add_queue;
ts.add_queue = NULL;
ts.add_queue_vpath = g_list_reverse (ts.add_queue_vpath);
the_queue = ts.add_queue_vpath;
ts.add_queue_vpath = NULL;
g_free (ts.check_name);
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);
}
@ -897,23 +933,17 @@ tree_store_rescan (const vfs_path_t * vpath)
struct dirent *dp;
struct stat buf;
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;
g_free (dir);
return entry;
}
entry = tree_store_start_check (dir);
if (!entry)
{
g_free (dir);
entry = tree_store_start_check (vpath);
if (entry == NULL)
return NULL;
}
dirp = mc_opendir (vpath);
if (dirp)
@ -940,7 +970,6 @@ tree_store_rescan (const vfs_path_t * vpath)
}
tree_store_end_check ();
entry->scanned = 1;
g_free (dir);
return entry;
}

View File

@ -21,7 +21,7 @@ typedef void (*tree_store_remove_fn) (struct tree_entry * tree, void *data);
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) */
long submask; /* Bitmask of existing sublevels after this entry */
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_last; /* Last entry in the list */
tree_entry *check_start; /* Start of checked subdirectories */
char *check_name;
GList *add_queue; /* List of strings of added directories */
vfs_path_t *check_name;
GList *add_queue_vpath; /* List of vfs_path_t objects of added directories */
unsigned int loaded:1;
unsigned int dirty:1;
};
@ -49,11 +49,11 @@ struct TreeStore
struct TreeStore *tree_store_get (void);
int tree_store_load (void);
int tree_store_save (void);
void tree_store_remove_entry (const char *name);
tree_entry *tree_store_start_check (const char *path);
void tree_store_remove_entry (const vfs_path_t * name_vpath);
tree_entry *tree_store_start_check (const vfs_path_t * vpath);
void tree_store_mark_checked (const char *subname);
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);
void tree_store_add_entry_remove_hook (tree_store_remove_fn callback, void *data);