From 3529890d0cddb0a593662e03b8d7d1660a49ad51 Mon Sep 17 00:00:00 2001 From: Slava Zanko Date: Tue, 4 Oct 2011 15:58:24 +0300 Subject: [PATCH] Changed treestore functions to handle vfs_path_t objects. Signed-off-by: Slava Zanko --- src/filemanager/boxes.c | 2 +- src/filemanager/dir.c | 12 +- src/filemanager/file.c | 21 +-- src/filemanager/midnight.c | 6 +- src/filemanager/tree.c | 144 ++++++++++-------- src/filemanager/tree.h | 2 +- src/filemanager/treestore.c | 347 ++++++++++++++++++++++++-------------------- src/filemanager/treestore.h | 12 +- 8 files changed, 303 insertions(+), 243 deletions(-) diff --git a/src/filemanager/boxes.c b/src/filemanager/boxes.c index 26374050b..7abc8dc21 100644 --- a/src/filemanager/boxes.c +++ b/src/filemanager/boxes.c @@ -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; diff --git a/src/filemanager/dir.c b/src/filemanager/dir.c index 6b50fd8b8..e47109345 100644 --- a/src/filemanager/dir.c +++ b/src/filemanager/dir.c @@ -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))) { diff --git a/src/filemanager/file.c b/src/filemanager/file.c index 42d427243..24785d044 100644 --- a/src/filemanager/file.c +++ b/src/filemanager/file.c @@ -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; } diff --git a/src/filemanager/midnight.c b/src/filemanager/midnight.c index b062d2392..fb956229a 100644 --- a/src/filemanager/midnight.c +++ b/src/filemanager/midnight.c @@ -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); } /* --------------------------------------------------------------------------------------------- */ diff --git a/src/filemanager/tree.c b/src/filemanager/tree.c index cb64dd034..368fb808d 100644 --- a/src/filemanager/tree.c +++ b/src/filemanager/tree.c @@ -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; diff --git a/src/filemanager/tree.h b/src/filemanager/tree.h index 93c50d883..a8c4f5016 100644 --- a/src/filemanager/tree.h +++ b/src/filemanager/tree.h @@ -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); diff --git a/src/filemanager/treestore.c b/src/filemanager/treestore.c index 7bd96a1bb..70981080f 100644 --- a/src/filemanager/treestore.c +++ b/src/filemanager/treestore.c @@ -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; - - 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; + char *string, *ret_val; - 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; } diff --git a/src/filemanager/treestore.h b/src/filemanager/treestore.h index afa15e85a..b9cf425c8 100644 --- a/src/filemanager/treestore.h +++ b/src/filemanager/treestore.h @@ -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); -- 2.11.4.GIT