|
@@ -28,8 +28,8 @@
|
|
|
The program load and saves the tree each time the tree widget is
|
|
|
created and destroyed. This is required for the future vfs layer,
|
|
|
it will be possible to have tree views over virtual file systems.
|
|
|
+*/
|
|
|
|
|
|
- */
|
|
|
#include <config.h>
|
|
|
#include <sys/types.h>
|
|
|
#ifdef HAVE_UNISTD_H
|
|
@@ -51,19 +51,15 @@
|
|
|
|
|
|
static TreeStore ts;
|
|
|
|
|
|
-void (*tree_store_dirty_notify)(int state) = NULL;
|
|
|
-
|
|
|
static void
|
|
|
-tree_store_dirty (int state)
|
|
|
+tree_store_dirty(int state)
|
|
|
{
|
|
|
- ts.dirty = state;
|
|
|
-
|
|
|
- if (tree_store_dirty_notify)
|
|
|
- (*tree_store_dirty_notify)(state);
|
|
|
+ ts.dirty = state;
|
|
|
}
|
|
|
|
|
|
/* Returns number of common characters */
|
|
|
-static int str_common (char *s1, char *s2)
|
|
|
+static int
|
|
|
+str_common(char *s1, char *s2)
|
|
|
{
|
|
|
int result = 0;
|
|
|
|
|
@@ -94,174 +90,173 @@ static int str_common (char *s1, char *s2)
|
|
|
than p2.
|
|
|
*/
|
|
|
static int
|
|
|
-pathcmp (const char *p1, const char *p2)
|
|
|
+pathcmp(const char *p1, const char *p2)
|
|
|
{
|
|
|
- for ( ;*p1 == *p2; p1++, p2++)
|
|
|
- if (*p1 == '\0' )
|
|
|
- return 0;
|
|
|
-
|
|
|
+ for (; *p1 == *p2; p1++, p2++)
|
|
|
+ if (*p1 == '\0')
|
|
|
+ return 0;
|
|
|
+
|
|
|
if (*p1 == '\0')
|
|
|
- return -1;
|
|
|
+ return -1;
|
|
|
if (*p2 == '\0')
|
|
|
- return 1;
|
|
|
+ return 1;
|
|
|
if (*p1 == PATH_SEP)
|
|
|
- return -1;
|
|
|
+ return -1;
|
|
|
if (*p2 == PATH_SEP)
|
|
|
- return 1;
|
|
|
+ return 1;
|
|
|
return (*p1 - *p2);
|
|
|
}
|
|
|
|
|
|
/* Searches for specified directory */
|
|
|
tree_entry *
|
|
|
-tree_store_whereis (char *name)
|
|
|
+tree_store_whereis(char *name)
|
|
|
{
|
|
|
- tree_entry *current = ts.tree_first;
|
|
|
- int flag = -1;
|
|
|
-
|
|
|
- while (current && (flag = pathcmp (current->name, name)) < 0)
|
|
|
- current = current->next;
|
|
|
-
|
|
|
- if (flag == 0)
|
|
|
- return current;
|
|
|
- else
|
|
|
- return NULL;
|
|
|
+ tree_entry *current = ts.tree_first;
|
|
|
+ int flag = -1;
|
|
|
+
|
|
|
+ while (current && (flag = pathcmp(current->name, name)) < 0)
|
|
|
+ current = current->next;
|
|
|
+
|
|
|
+ if (flag == 0)
|
|
|
+ return current;
|
|
|
+ else
|
|
|
+ return NULL;
|
|
|
}
|
|
|
|
|
|
TreeStore *
|
|
|
-tree_store_get (void)
|
|
|
+tree_store_get(void)
|
|
|
{
|
|
|
- return &ts;
|
|
|
+ return &ts;
|
|
|
}
|
|
|
|
|
|
static char *
|
|
|
-decode (char *buffer)
|
|
|
+decode(char *buffer)
|
|
|
{
|
|
|
- char *res = g_strdup (buffer);
|
|
|
- char *p, *q;
|
|
|
-
|
|
|
- for (p = q = res; *p; p++, q++){
|
|
|
- if (*p == '\n'){
|
|
|
- *q = 0;
|
|
|
- return res;
|
|
|
- }
|
|
|
+ char *res = g_strdup(buffer);
|
|
|
+ char *p, *q;
|
|
|
|
|
|
- if (*p != '\\'){
|
|
|
- *q = *p;
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- p++;
|
|
|
-
|
|
|
- switch (*p){
|
|
|
- case 'n':
|
|
|
- *q = '\n';
|
|
|
- break;
|
|
|
- case '\\':
|
|
|
- *q = '\\';
|
|
|
- break;
|
|
|
- }
|
|
|
+ for (p = q = res; *p; p++, q++) {
|
|
|
+ if (*p == '\n') {
|
|
|
+ *q = 0;
|
|
|
+ return res;
|
|
|
}
|
|
|
- *q = *p;
|
|
|
|
|
|
- return res;
|
|
|
+ if (*p != '\\') {
|
|
|
+ *q = *p;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ p++;
|
|
|
+
|
|
|
+ switch (*p) {
|
|
|
+ case 'n':
|
|
|
+ *q = '\n';
|
|
|
+ break;
|
|
|
+ case '\\':
|
|
|
+ *q = '\\';
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ *q = *p;
|
|
|
+
|
|
|
+ return res;
|
|
|
}
|
|
|
|
|
|
/* Loads the tree store from the specified filename */
|
|
|
static int
|
|
|
-tree_store_load_from (char *name)
|
|
|
+tree_store_load_from(char *name)
|
|
|
{
|
|
|
- FILE *file;
|
|
|
- char buffer [MC_MAXPATHLEN + 20], oldname[MC_MAXPATHLEN];
|
|
|
- char *different;
|
|
|
- int len, common;
|
|
|
- int do_load;
|
|
|
-
|
|
|
- g_return_val_if_fail (name != NULL, FALSE);
|
|
|
-
|
|
|
- if (ts.loaded)
|
|
|
- return TRUE;
|
|
|
-
|
|
|
- file = fopen (name, "r");
|
|
|
-
|
|
|
- if (file){
|
|
|
- fgets (buffer, sizeof (buffer), file);
|
|
|
-
|
|
|
- if (strncmp (buffer, TREE_SIGNATURE, strlen (TREE_SIGNATURE)) != 0){
|
|
|
- fclose (file);
|
|
|
- do_load = FALSE;
|
|
|
- } else
|
|
|
- do_load = TRUE;
|
|
|
+ FILE *file;
|
|
|
+ char buffer[MC_MAXPATHLEN + 20], oldname[MC_MAXPATHLEN];
|
|
|
+ char *different;
|
|
|
+ int len, common;
|
|
|
+ int do_load;
|
|
|
+
|
|
|
+ g_return_val_if_fail(name != NULL, FALSE);
|
|
|
+
|
|
|
+ if (ts.loaded)
|
|
|
+ return TRUE;
|
|
|
+
|
|
|
+ file = fopen(name, "r");
|
|
|
+
|
|
|
+ if (file) {
|
|
|
+ fgets(buffer, sizeof(buffer), file);
|
|
|
+
|
|
|
+ if (strncmp(buffer, TREE_SIGNATURE, strlen(TREE_SIGNATURE)) != 0) {
|
|
|
+ fclose(file);
|
|
|
+ do_load = FALSE;
|
|
|
} else
|
|
|
- do_load = FALSE;
|
|
|
+ do_load = TRUE;
|
|
|
+ } else
|
|
|
+ do_load = FALSE;
|
|
|
|
|
|
- if (do_load){
|
|
|
- ts.loaded = TRUE;
|
|
|
+ if (do_load) {
|
|
|
+ ts.loaded = TRUE;
|
|
|
|
|
|
- /* File open -> read contents */
|
|
|
- oldname [0] = 0;
|
|
|
- while (fgets (buffer, MC_MAXPATHLEN, file)){
|
|
|
- tree_entry *e;
|
|
|
- int scanned;
|
|
|
- char *name;
|
|
|
+ /* File open -> read contents */
|
|
|
+ oldname[0] = 0;
|
|
|
+ while (fgets(buffer, MC_MAXPATHLEN, file)) {
|
|
|
+ tree_entry *e;
|
|
|
+ int scanned;
|
|
|
+ char *name;
|
|
|
|
|
|
- /* Skip invalid records */
|
|
|
- if ((buffer [0] != '0' && buffer [0] != '1'))
|
|
|
- continue;
|
|
|
-
|
|
|
- if (buffer [1] != ':')
|
|
|
- continue;
|
|
|
+ /* Skip invalid records */
|
|
|
+ if ((buffer[0] != '0' && buffer[0] != '1'))
|
|
|
+ continue;
|
|
|
|
|
|
- scanned = buffer [0] == '1';
|
|
|
+ if (buffer[1] != ':')
|
|
|
+ continue;
|
|
|
|
|
|
- name = decode (buffer+2);
|
|
|
+ scanned = buffer[0] == '1';
|
|
|
|
|
|
- len = strlen (name);
|
|
|
+ name = decode(buffer + 2);
|
|
|
+
|
|
|
+ len = strlen(name);
|
|
|
#ifdef OS2_NT
|
|
|
- /* .ado: Drives for NT and OS/2 */
|
|
|
- if ((len > 2) &&
|
|
|
- isalpha(name[0]) &&
|
|
|
- (name[1] == ':') &&
|
|
|
- (name[2] == '\\')) {
|
|
|
- tree_store_add_entry (name);
|
|
|
- strcpy (oldname, name);
|
|
|
- } else
|
|
|
+ /* .ado: Drives for NT and OS/2 */
|
|
|
+ if ((len > 2) &&
|
|
|
+ isalpha(name[0]) &&
|
|
|
+ (name[1] == ':') && (name[2] == '\\')) {
|
|
|
+ tree_store_add_entry(name);
|
|
|
+ strcpy(oldname, name);
|
|
|
+ } else
|
|
|
#endif
|
|
|
- /* UNIX Version */
|
|
|
- if (name [0] != PATH_SEP){
|
|
|
- /* Clear-text decompression */
|
|
|
- char *s = strtok (name, " ");
|
|
|
-
|
|
|
- if (s){
|
|
|
- common = atoi (s);
|
|
|
- different = strtok (NULL, "");
|
|
|
- if (different){
|
|
|
- strcpy (oldname + common, different);
|
|
|
- if (vfs_file_is_local (oldname)){
|
|
|
- e = tree_store_add_entry (oldname);
|
|
|
- e->scanned = scanned;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- if (vfs_file_is_local (name)){
|
|
|
- e = tree_store_add_entry (name);
|
|
|
- e->scanned = scanned;
|
|
|
- }
|
|
|
- strcpy (oldname, name);
|
|
|
- }
|
|
|
- g_free (name);
|
|
|
+ /* UNIX Version */
|
|
|
+ if (name[0] != PATH_SEP) {
|
|
|
+ /* Clear-text decompression */
|
|
|
+ char *s = strtok(name, " ");
|
|
|
+
|
|
|
+ if (s) {
|
|
|
+ common = atoi(s);
|
|
|
+ different = strtok(NULL, "");
|
|
|
+ if (different) {
|
|
|
+ strcpy(oldname + common, different);
|
|
|
+ if (vfs_file_is_local(oldname)) {
|
|
|
+ e = tree_store_add_entry(oldname);
|
|
|
+ e->scanned = scanned;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (vfs_file_is_local(name)) {
|
|
|
+ e = tree_store_add_entry(name);
|
|
|
+ e->scanned = scanned;
|
|
|
}
|
|
|
- fclose (file);
|
|
|
+ strcpy(oldname, name);
|
|
|
+ }
|
|
|
+ g_free(name);
|
|
|
}
|
|
|
+ fclose(file);
|
|
|
+ }
|
|
|
|
|
|
- /* Nothing loaded, we add some standard directories */
|
|
|
- if (!ts.tree_first){
|
|
|
- tree_store_add_entry (PATH_SEP_STR);
|
|
|
- tree_store_rescan (PATH_SEP_STR);
|
|
|
- ts.loaded = TRUE;
|
|
|
- }
|
|
|
-
|
|
|
- return TRUE;
|
|
|
+ /* Nothing loaded, we add some standard directories */
|
|
|
+ if (!ts.tree_first) {
|
|
|
+ tree_store_add_entry(PATH_SEP_STR);
|
|
|
+ tree_store_rescan(PATH_SEP_STR);
|
|
|
+ ts.loaded = TRUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ return TRUE;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -273,97 +268,99 @@ tree_store_load_from (char *name)
|
|
|
* Return value: TRUE if success, FALSE otherwise.
|
|
|
**/
|
|
|
int
|
|
|
-tree_store_load (void)
|
|
|
+tree_store_load(void)
|
|
|
{
|
|
|
- char *name;
|
|
|
- int retval;
|
|
|
+ char *name;
|
|
|
+ int retval;
|
|
|
|
|
|
- name = concat_dir_and_file (home_dir, MC_TREE);
|
|
|
- retval = tree_store_load_from (name);
|
|
|
- g_free (name);
|
|
|
+ name = concat_dir_and_file(home_dir, MC_TREE);
|
|
|
+ retval = tree_store_load_from(name);
|
|
|
+ g_free(name);
|
|
|
|
|
|
- return retval;
|
|
|
+ return retval;
|
|
|
}
|
|
|
|
|
|
static char *
|
|
|
-encode (char *string)
|
|
|
-{
|
|
|
- int special_chars;
|
|
|
- char *p, *q;
|
|
|
- char *res;
|
|
|
-
|
|
|
- for (special_chars = 0, p = string; *p; p++){
|
|
|
- if (*p == '\n' || *p == '\\')
|
|
|
- special_chars++;
|
|
|
+encode(char *string)
|
|
|
+{
|
|
|
+ int special_chars;
|
|
|
+ char *p, *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;
|
|
|
}
|
|
|
-
|
|
|
- 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++ = '\\';
|
|
|
+
|
|
|
+ switch (*p) {
|
|
|
+ case '\n':
|
|
|
+ *q = 'n';
|
|
|
+ break;
|
|
|
+
|
|
|
+ case '\\':
|
|
|
+ *q = '\\';
|
|
|
+ break;
|
|
|
}
|
|
|
- *q = 0;
|
|
|
- return res;
|
|
|
+ }
|
|
|
+ *q = 0;
|
|
|
+ return res;
|
|
|
}
|
|
|
|
|
|
/* Saves the tree to the specified filename */
|
|
|
static int
|
|
|
-tree_store_save_to (char *name)
|
|
|
-{
|
|
|
- tree_entry *current;
|
|
|
- FILE *file;
|
|
|
-
|
|
|
- file = fopen (name, "w");
|
|
|
- if (!file)
|
|
|
- return errno;
|
|
|
-
|
|
|
- fprintf (file, "%s\n", TREE_SIGNATURE);
|
|
|
-
|
|
|
- current = ts.tree_first;
|
|
|
- while (current){
|
|
|
- int i, common;
|
|
|
-
|
|
|
- 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);
|
|
|
-
|
|
|
- i = fprintf (file, "%d:%d %s\n", current->scanned, common, encoded);
|
|
|
- g_free (encoded);
|
|
|
- } else {
|
|
|
- char *encoded = encode (current->name);
|
|
|
-
|
|
|
- i = fprintf (file, "%d:%s\n", current->scanned, encoded);
|
|
|
- g_free (encoded);
|
|
|
- }
|
|
|
-
|
|
|
- if (i == EOF){
|
|
|
- fprintf (stderr, _("Cannot write to the %s file:\n%s\n"), name,
|
|
|
- unix_error_string (errno));
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- current = current->next;
|
|
|
+tree_store_save_to(char *name)
|
|
|
+{
|
|
|
+ tree_entry *current;
|
|
|
+ FILE *file;
|
|
|
+
|
|
|
+ file = fopen(name, "w");
|
|
|
+ if (!file)
|
|
|
+ return errno;
|
|
|
+
|
|
|
+ fprintf(file, "%s\n", TREE_SIGNATURE);
|
|
|
+
|
|
|
+ current = ts.tree_first;
|
|
|
+ while (current) {
|
|
|
+ int i, common;
|
|
|
+
|
|
|
+ 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);
|
|
|
+
|
|
|
+ i = fprintf(file, "%d:%d %s\n", current->scanned, common,
|
|
|
+ encoded);
|
|
|
+ g_free(encoded);
|
|
|
+ } else {
|
|
|
+ char *encoded = encode(current->name);
|
|
|
+
|
|
|
+ i = fprintf(file, "%d:%s\n", current->scanned, encoded);
|
|
|
+ g_free(encoded);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (i == EOF) {
|
|
|
+ fprintf(stderr, _("Cannot write to the %s file:\n%s\n"),
|
|
|
+ name, unix_error_string(errno));
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
- tree_store_dirty (FALSE);
|
|
|
- fclose (file);
|
|
|
+ current = current->next;
|
|
|
+ }
|
|
|
+ tree_store_dirty(FALSE);
|
|
|
+ fclose(file);
|
|
|
|
|
|
- return 0;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -375,573 +372,462 @@ tree_store_save_to (char *name)
|
|
|
* Return value: 0 if success, errno on error.
|
|
|
**/
|
|
|
int
|
|
|
-tree_store_save (void)
|
|
|
+tree_store_save(void)
|
|
|
{
|
|
|
- char *tmp;
|
|
|
- char *name;
|
|
|
- int retval;
|
|
|
+ char *tmp;
|
|
|
+ char *name;
|
|
|
+ int retval;
|
|
|
|
|
|
- tmp = concat_dir_and_file (home_dir, MC_TREE_TMP);
|
|
|
- retval = tree_store_save_to (tmp);
|
|
|
+ tmp = concat_dir_and_file(home_dir, MC_TREE_TMP);
|
|
|
+ retval = tree_store_save_to(tmp);
|
|
|
|
|
|
- if (retval) {
|
|
|
- g_free (tmp);
|
|
|
- return retval;
|
|
|
- }
|
|
|
+ if (retval) {
|
|
|
+ g_free(tmp);
|
|
|
+ return retval;
|
|
|
+ }
|
|
|
|
|
|
- name = concat_dir_and_file (home_dir, MC_TREE);
|
|
|
- retval = rename (tmp, name);
|
|
|
+ name = concat_dir_and_file(home_dir, MC_TREE);
|
|
|
+ retval = rename(tmp, name);
|
|
|
|
|
|
- g_free (tmp);
|
|
|
- g_free (name);
|
|
|
+ g_free(tmp);
|
|
|
+ g_free(name);
|
|
|
|
|
|
- if (retval)
|
|
|
- return errno;
|
|
|
- else
|
|
|
- return 0;
|
|
|
+ if (retval)
|
|
|
+ return errno;
|
|
|
+ else
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
tree_entry *
|
|
|
-tree_store_add_entry (char *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)
|
|
|
- abort ();
|
|
|
-
|
|
|
- /* Search for the correct place */
|
|
|
- while (current && (flag = pathcmp (current->name, name)) < 0){
|
|
|
- old = current;
|
|
|
- current = current->next;
|
|
|
+tree_store_add_entry(char *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)
|
|
|
+ abort();
|
|
|
+
|
|
|
+ /* Search for the correct place */
|
|
|
+ while (current && (flag = pathcmp(current->name, name)) < 0) {
|
|
|
+ old = current;
|
|
|
+ current = current->next;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (flag == 0)
|
|
|
+ return current; /* Already in the list */
|
|
|
+
|
|
|
+ /* Not in the list -> add it */
|
|
|
+ new = g_new0(tree_entry, 1);
|
|
|
+ if (!current) {
|
|
|
+ /* Append to the end of the list */
|
|
|
+ if (!ts.tree_first) {
|
|
|
+ /* Empty list */
|
|
|
+ ts.tree_first = new;
|
|
|
+ new->prev = NULL;
|
|
|
+ } else {
|
|
|
+ old->next = new;
|
|
|
+ new->prev = old;
|
|
|
}
|
|
|
-
|
|
|
- if (flag == 0)
|
|
|
- return current; /* Already in the list */
|
|
|
-
|
|
|
- /* Not in the list -> add it */
|
|
|
- new = g_new0 (tree_entry, 1);
|
|
|
- if (!current){
|
|
|
- /* Append to the end of the list */
|
|
|
- if (!ts.tree_first){
|
|
|
- /* Empty list */
|
|
|
- ts.tree_first = new;
|
|
|
- new->prev = NULL;
|
|
|
- } else {
|
|
|
- old->next = new;
|
|
|
- new->prev = old;
|
|
|
- }
|
|
|
- new->next = NULL;
|
|
|
- ts.tree_last = new;
|
|
|
+ new->next = NULL;
|
|
|
+ ts.tree_last = new;
|
|
|
+ } else {
|
|
|
+ /* Insert in to the middle of the list */
|
|
|
+ new->prev = old;
|
|
|
+ if (old) {
|
|
|
+ /* Yes, in the middle */
|
|
|
+ new->next = old->next;
|
|
|
+ old->next = new;
|
|
|
} else {
|
|
|
- /* Insert in to the middle of the list */
|
|
|
- new->prev = old;
|
|
|
- if (old){
|
|
|
- /* Yes, in the middle */
|
|
|
- new->next = old->next;
|
|
|
- old->next = new;
|
|
|
- } else {
|
|
|
- /* Nope, in the beginning of the list */
|
|
|
- new->next = ts.tree_first;
|
|
|
- ts.tree_first = new;
|
|
|
- }
|
|
|
- new->next->prev = new;
|
|
|
+ /* Nope, in the beginning of the list */
|
|
|
+ new->next = ts.tree_first;
|
|
|
+ ts.tree_first = new;
|
|
|
}
|
|
|
-
|
|
|
- /* 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;
|
|
|
- }
|
|
|
- if (new->next)
|
|
|
- submask = new->next->submask;
|
|
|
- else
|
|
|
- submask = 0;
|
|
|
- submask |= 1 << new->sublevel;
|
|
|
- submask &= (2 << new->sublevel) - 1;
|
|
|
- new->submask = submask;
|
|
|
- new->mark = 0;
|
|
|
-
|
|
|
- /* Correct the submasks of the previous entries */
|
|
|
- current = new->prev;
|
|
|
- while (current && current->sublevel > new->sublevel){
|
|
|
- current->submask |= 1 << new->sublevel;
|
|
|
- current = current->prev;
|
|
|
+ new->next->prev = new;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 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;
|
|
|
}
|
|
|
-
|
|
|
- /* The entry has now been added */
|
|
|
-
|
|
|
- if (new->sublevel > 1){
|
|
|
- /* Let's check if the parent directory is in the tree */
|
|
|
- char *parent = g_strdup (new->name);
|
|
|
- int i;
|
|
|
-
|
|
|
- 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);
|
|
|
+ if (new->next)
|
|
|
+ submask = new->next->submask;
|
|
|
+ else
|
|
|
+ submask = 0;
|
|
|
+ submask |= 1 << new->sublevel;
|
|
|
+ submask &= (2 << new->sublevel) - 1;
|
|
|
+ new->submask = submask;
|
|
|
+ new->mark = 0;
|
|
|
+
|
|
|
+ /* Correct the submasks of the previous entries */
|
|
|
+ current = new->prev;
|
|
|
+ while (current && current->sublevel > new->sublevel) {
|
|
|
+ current->submask |= 1 << new->sublevel;
|
|
|
+ current = current->prev;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* The entry has now been added */
|
|
|
+
|
|
|
+ if (new->sublevel > 1) {
|
|
|
+ /* Let's check if the parent directory is in the tree */
|
|
|
+ char *parent = g_strdup(new->name);
|
|
|
+ int i;
|
|
|
+
|
|
|
+ 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);
|
|
|
+ }
|
|
|
|
|
|
- tree_store_dirty (TRUE);
|
|
|
- return new;
|
|
|
+ tree_store_dirty(TRUE);
|
|
|
+ return new;
|
|
|
}
|
|
|
|
|
|
-static tree_entry *
|
|
|
-remove_entry (tree_entry *entry)
|
|
|
-{
|
|
|
- tree_entry *current = entry->prev;
|
|
|
- long submask = 0;
|
|
|
- tree_entry *ret = NULL;
|
|
|
-
|
|
|
- tree_store_notify_remove (entry);
|
|
|
-
|
|
|
- /* Correct the submasks of the previous entries */
|
|
|
- if (entry->next)
|
|
|
- submask = entry->next->submask;
|
|
|
- while (current && current->sublevel > entry->sublevel){
|
|
|
- submask |= 1 << current->sublevel;
|
|
|
- submask &= (2 << current->sublevel) - 1;
|
|
|
- current->submask = submask;
|
|
|
- current = current->prev;
|
|
|
- }
|
|
|
-
|
|
|
- /* Unlink the entry from the list */
|
|
|
- if (entry->prev)
|
|
|
- entry->prev->next = entry->next;
|
|
|
- else
|
|
|
- ts.tree_first = entry->next;
|
|
|
-
|
|
|
- if (entry->next)
|
|
|
- entry->next->prev = entry->prev;
|
|
|
- else
|
|
|
- ts.tree_last = entry->prev;
|
|
|
-
|
|
|
- /* Free the memory used by the entry */
|
|
|
- g_free (entry->name);
|
|
|
- g_free (entry);
|
|
|
-
|
|
|
- return ret;
|
|
|
-}
|
|
|
+static Hook *remove_entry_hooks;
|
|
|
|
|
|
void
|
|
|
-tree_store_remove_entry (char *name)
|
|
|
+tree_store_add_entry_remove_hook(tree_store_remove_fn callback, void *data)
|
|
|
{
|
|
|
- tree_entry *current, *base, *old;
|
|
|
- int len, base_sublevel;
|
|
|
-
|
|
|
- g_return_if_fail (name != NULL);
|
|
|
- g_return_if_fail (ts.check_name != NULL);
|
|
|
-
|
|
|
- /* Miguel Ugly hack */
|
|
|
- if (name [0] == PATH_SEP && name [1] == 0)
|
|
|
- return;
|
|
|
- /* Miguel Ugly hack end */
|
|
|
-
|
|
|
- base = tree_store_whereis (name);
|
|
|
- if (!base)
|
|
|
- return; /* Doesn't exist */
|
|
|
-
|
|
|
- if (ts.check_name [0] == PATH_SEP && ts.check_name [1] == 0)
|
|
|
- base_sublevel = base->sublevel;
|
|
|
- else
|
|
|
- base_sublevel = base->sublevel + 1;
|
|
|
-
|
|
|
- len = strlen (base->name);
|
|
|
- current = base->next;
|
|
|
- while (current
|
|
|
- && strncmp (current->name, base->name, len) == 0
|
|
|
- && (current->name[len] == '\0' || current->name[len] == PATH_SEP)) {
|
|
|
- old = current;
|
|
|
- current = current->next;
|
|
|
- remove_entry (old);
|
|
|
- }
|
|
|
- remove_entry (base);
|
|
|
- tree_store_dirty (TRUE);
|
|
|
-
|
|
|
- return;
|
|
|
+ add_hook(&remove_entry_hooks, (void (*)(void *)) callback, data);
|
|
|
}
|
|
|
|
|
|
-/* This subdirectory exists -> clear deletion mark */
|
|
|
void
|
|
|
-tree_store_mark_checked (const char *subname)
|
|
|
+tree_store_remove_entry_remove_hook(tree_store_remove_fn callback)
|
|
|
{
|
|
|
- char *name;
|
|
|
- tree_entry *current, *base;
|
|
|
- int flag = 1, len;
|
|
|
- if (!ts.loaded)
|
|
|
- return;
|
|
|
-
|
|
|
- if (ts.check_name == NULL)
|
|
|
- return;
|
|
|
-
|
|
|
- /* 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, NULL);
|
|
|
- else
|
|
|
- name = concat_dir_and_file (ts.check_name, subname);
|
|
|
-
|
|
|
- /* Search for the subdirectory */
|
|
|
- current = ts.check_start;
|
|
|
- while (current && (flag = pathcmp (current->name, name)) < 0)
|
|
|
- current = current->next;
|
|
|
-
|
|
|
- if (flag != 0){
|
|
|
- /* Doesn't exist -> add it */
|
|
|
- current = tree_store_add_entry (name);
|
|
|
- ts.add_queue = g_list_prepend (ts.add_queue, g_strdup (name));
|
|
|
- }
|
|
|
- g_free (name);
|
|
|
-
|
|
|
- /* Clear the deletion mark from the subdirectory and its children */
|
|
|
- base = current;
|
|
|
- if (base){
|
|
|
- len = strlen (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)){
|
|
|
- current->mark = 0;
|
|
|
- current = current->next;
|
|
|
- }
|
|
|
- }
|
|
|
+ delete_hook(&remove_entry_hooks, (void (*)(void *)) callback);
|
|
|
}
|
|
|
|
|
|
-/* Mark the subdirectories of the current directory for delete */
|
|
|
-tree_entry *
|
|
|
-tree_store_start_check (char *path)
|
|
|
+static void
|
|
|
+tree_store_notify_remove(tree_entry * entry)
|
|
|
{
|
|
|
- tree_entry *current, *retval;
|
|
|
- int len;
|
|
|
-
|
|
|
- if (!ts.loaded)
|
|
|
- return NULL;
|
|
|
-
|
|
|
- g_return_val_if_fail (ts.check_name == NULL, NULL);
|
|
|
- ts.check_start = NULL;
|
|
|
+ Hook *p = remove_entry_hooks;
|
|
|
+ tree_store_remove_fn r;
|
|
|
|
|
|
- tree_store_set_freeze (TRUE);
|
|
|
-
|
|
|
- /* Search for the start of subdirectories */
|
|
|
- current = tree_store_whereis (path);
|
|
|
- if (!current){
|
|
|
- struct stat s;
|
|
|
-
|
|
|
- if (mc_stat (path, &s) == -1)
|
|
|
- return NULL;
|
|
|
+ while (p) {
|
|
|
+ r = (tree_store_remove_fn) p->hook_fn;
|
|
|
+ r(entry, p->hook_data);
|
|
|
+ p = p->next;
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
- if (!S_ISDIR (s.st_mode))
|
|
|
- return NULL;
|
|
|
+static tree_entry *
|
|
|
+remove_entry(tree_entry * entry)
|
|
|
+{
|
|
|
+ tree_entry *current = entry->prev;
|
|
|
+ long submask = 0;
|
|
|
+ tree_entry *ret = NULL;
|
|
|
|
|
|
- current = tree_store_add_entry (path);
|
|
|
- ts.check_name = g_strdup (path);
|
|
|
+ tree_store_notify_remove(entry);
|
|
|
|
|
|
- return current;
|
|
|
- }
|
|
|
+ /* Correct the submasks of the previous entries */
|
|
|
+ if (entry->next)
|
|
|
+ submask = entry->next->submask;
|
|
|
+ while (current && current->sublevel > entry->sublevel) {
|
|
|
+ submask |= 1 << current->sublevel;
|
|
|
+ submask &= (2 << current->sublevel) - 1;
|
|
|
+ current->submask = submask;
|
|
|
+ current = current->prev;
|
|
|
+ }
|
|
|
|
|
|
- ts.check_name = g_strdup (path);
|
|
|
-
|
|
|
- retval = current;
|
|
|
+ /* Unlink the entry from the list */
|
|
|
+ if (entry->prev)
|
|
|
+ entry->prev->next = entry->next;
|
|
|
+ else
|
|
|
+ ts.tree_first = entry->next;
|
|
|
|
|
|
- /* Mark old subdirectories for delete */
|
|
|
- ts.check_start = current->next;
|
|
|
- len = strlen (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)){
|
|
|
- current->mark = 1;
|
|
|
- current = current->next;
|
|
|
- }
|
|
|
+ if (entry->next)
|
|
|
+ entry->next->prev = entry->prev;
|
|
|
+ else
|
|
|
+ ts.tree_last = entry->prev;
|
|
|
|
|
|
- return retval;
|
|
|
-}
|
|
|
+ /* Free the memory used by the entry */
|
|
|
+ g_free(entry->name);
|
|
|
+ g_free(entry);
|
|
|
|
|
|
-tree_entry *
|
|
|
-tree_store_start_check_cwd (void)
|
|
|
-{
|
|
|
- char buffer [MC_MAXPATHLEN];
|
|
|
-
|
|
|
- mc_get_current_wd (buffer, MC_MAXPATHLEN);
|
|
|
- return tree_store_start_check (buffer);
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
-/* Delete subdirectories which still have the deletion mark */
|
|
|
void
|
|
|
-tree_store_end_check (void)
|
|
|
+tree_store_remove_entry(char *name)
|
|
|
{
|
|
|
- tree_entry *current, *old;
|
|
|
- int len;
|
|
|
- GList *the_queue, *l;
|
|
|
-
|
|
|
- if (!ts.loaded)
|
|
|
- return;
|
|
|
-
|
|
|
- g_return_if_fail (ts.check_name != NULL);
|
|
|
-
|
|
|
- /* Check delete marks and delete if found */
|
|
|
- len = strlen (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)){
|
|
|
- old = current;
|
|
|
- current = current->next;
|
|
|
- if (old->mark)
|
|
|
- remove_entry (old);
|
|
|
- }
|
|
|
+ tree_entry *current, *base, *old;
|
|
|
+ int len, base_sublevel;
|
|
|
|
|
|
- /* 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;
|
|
|
- g_free (ts.check_name);
|
|
|
- ts.check_name = NULL;
|
|
|
-
|
|
|
- for (l = the_queue; l; l = l->next){
|
|
|
- tree_store_notify_add (l->data);
|
|
|
- g_free (l->data);
|
|
|
- }
|
|
|
-
|
|
|
- g_list_free (the_queue);
|
|
|
+ g_return_if_fail(name != NULL);
|
|
|
+ g_return_if_fail(ts.check_name != NULL);
|
|
|
|
|
|
- tree_store_set_freeze (FALSE);
|
|
|
-}
|
|
|
+ /* Miguel Ugly hack */
|
|
|
+ if (name[0] == PATH_SEP && name[1] == 0)
|
|
|
+ return;
|
|
|
+ /* Miguel Ugly hack end */
|
|
|
|
|
|
-static void
|
|
|
-process_special_dirs (GList **special_dirs, char *file)
|
|
|
-{
|
|
|
- char *token;
|
|
|
- char *buffer = g_malloc (4096);
|
|
|
- char *s;
|
|
|
-
|
|
|
- GetPrivateProfileString ("Special dirs", "list",
|
|
|
- "", buffer, 4096, file);
|
|
|
- s = buffer;
|
|
|
- while ((token = strtok (s, ",")) != NULL){
|
|
|
- *special_dirs = g_list_prepend (*special_dirs, g_strdup (token));
|
|
|
- s = NULL;
|
|
|
- }
|
|
|
- g_free (buffer);
|
|
|
+ base = tree_store_whereis(name);
|
|
|
+ if (!base)
|
|
|
+ return; /* Doesn't exist */
|
|
|
+
|
|
|
+ if (ts.check_name[0] == PATH_SEP && ts.check_name[1] == 0)
|
|
|
+ base_sublevel = base->sublevel;
|
|
|
+ else
|
|
|
+ base_sublevel = base->sublevel + 1;
|
|
|
+
|
|
|
+ len = strlen(base->name);
|
|
|
+ current = base->next;
|
|
|
+ while (current
|
|
|
+ && strncmp(current->name, base->name, len) == 0
|
|
|
+ && (current->name[len] == '\0'
|
|
|
+ || current->name[len] == PATH_SEP)) {
|
|
|
+ old = current;
|
|
|
+ current = current->next;
|
|
|
+ remove_entry(old);
|
|
|
+ }
|
|
|
+ remove_entry(base);
|
|
|
+ tree_store_dirty(TRUE);
|
|
|
+
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
-static gboolean
|
|
|
-should_skip_directory (char *dir)
|
|
|
+/* This subdirectory exists -> clear deletion mark */
|
|
|
+void
|
|
|
+tree_store_mark_checked(const char *subname)
|
|
|
{
|
|
|
- static GList *special_dirs;
|
|
|
- GList *l;
|
|
|
- static int loaded;
|
|
|
-
|
|
|
- if (loaded == 0){
|
|
|
- loaded = 1;
|
|
|
- setup_init ();
|
|
|
- process_special_dirs (&special_dirs, profile_name);
|
|
|
- process_special_dirs (&special_dirs, CONFDIR "mc.global");
|
|
|
- }
|
|
|
+ char *name;
|
|
|
+ tree_entry *current, *base;
|
|
|
+ int flag = 1, len;
|
|
|
+ if (!ts.loaded)
|
|
|
+ return;
|
|
|
+
|
|
|
+ if (ts.check_name == NULL)
|
|
|
+ return;
|
|
|
|
|
|
- for (l = special_dirs; l; l = l->next){
|
|
|
- if (strncmp (dir, l->data, strlen (l->data)) == 0)
|
|
|
- return TRUE;
|
|
|
+ /* 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, NULL);
|
|
|
+ else
|
|
|
+ name = concat_dir_and_file(ts.check_name, subname);
|
|
|
+
|
|
|
+ /* Search for the subdirectory */
|
|
|
+ current = ts.check_start;
|
|
|
+ while (current && (flag = pathcmp(current->name, name)) < 0)
|
|
|
+ current = current->next;
|
|
|
+
|
|
|
+ if (flag != 0) {
|
|
|
+ /* Doesn't exist -> add it */
|
|
|
+ current = tree_store_add_entry(name);
|
|
|
+ ts.add_queue = g_list_prepend(ts.add_queue, g_strdup(name));
|
|
|
+ }
|
|
|
+ g_free(name);
|
|
|
+
|
|
|
+ /* Clear the deletion mark from the subdirectory and its children */
|
|
|
+ base = current;
|
|
|
+ if (base) {
|
|
|
+ len = strlen(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)) {
|
|
|
+ current->mark = 0;
|
|
|
+ current = current->next;
|
|
|
}
|
|
|
- return FALSE;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+/* Mark the subdirectories of the current directory for delete */
|
|
|
tree_entry *
|
|
|
-tree_store_rescan (char *dir)
|
|
|
+tree_store_start_check(char *path)
|
|
|
{
|
|
|
- DIR *dirp;
|
|
|
- struct dirent *dp;
|
|
|
- struct stat buf;
|
|
|
- tree_entry *entry;
|
|
|
-
|
|
|
- if (should_skip_directory (dir)){
|
|
|
- entry = tree_store_add_entry (dir);
|
|
|
- entry->scanned = 1;
|
|
|
-
|
|
|
- return entry;
|
|
|
- }
|
|
|
+ tree_entry *current, *retval;
|
|
|
+ int len;
|
|
|
|
|
|
- entry = tree_store_start_check (dir);
|
|
|
+ if (!ts.loaded)
|
|
|
+ return NULL;
|
|
|
|
|
|
- if (!entry)
|
|
|
- return NULL;
|
|
|
+ g_return_val_if_fail(ts.check_name == NULL, NULL);
|
|
|
+ ts.check_start = NULL;
|
|
|
|
|
|
- dirp = mc_opendir (dir);
|
|
|
- if (dirp){
|
|
|
- for (dp = mc_readdir (dirp); dp; dp = mc_readdir (dirp)){
|
|
|
- char *full_name;
|
|
|
+ /* Search for the start of subdirectories */
|
|
|
+ current = tree_store_whereis(path);
|
|
|
+ if (!current) {
|
|
|
+ struct stat s;
|
|
|
|
|
|
- if (dp->d_name [0] == '.'){
|
|
|
- if (dp->d_name [1] == 0
|
|
|
- || (dp->d_name [1] == '.' && dp->d_name [2] == 0))
|
|
|
- continue;
|
|
|
- }
|
|
|
+ if (mc_stat(path, &s) == -1)
|
|
|
+ return NULL;
|
|
|
|
|
|
- full_name = concat_dir_and_file (dir, dp->d_name);
|
|
|
- if (mc_lstat (full_name, &buf) != -1){
|
|
|
- if (S_ISDIR (buf.st_mode))
|
|
|
- tree_store_mark_checked (dp->d_name);
|
|
|
- }
|
|
|
- g_free (full_name);
|
|
|
- }
|
|
|
- mc_closedir (dirp);
|
|
|
- }
|
|
|
- tree_store_end_check ();
|
|
|
- entry->scanned = 1;
|
|
|
+ if (!S_ISDIR(s.st_mode))
|
|
|
+ return NULL;
|
|
|
|
|
|
- return entry;
|
|
|
-}
|
|
|
+ current = tree_store_add_entry(path);
|
|
|
+ ts.check_name = g_strdup(path);
|
|
|
|
|
|
-static Hook *remove_entry_hooks;
|
|
|
-static Hook *add_entry_hooks;
|
|
|
-static Hook *freeze_hooks;
|
|
|
+ return current;
|
|
|
+ }
|
|
|
|
|
|
-void
|
|
|
-tree_store_add_entry_remove_hook (tree_store_remove_fn callback, void *data)
|
|
|
-{
|
|
|
- add_hook (&remove_entry_hooks, (void (*)(void *))callback, data);
|
|
|
-}
|
|
|
+ ts.check_name = g_strdup(path);
|
|
|
|
|
|
-void
|
|
|
-tree_store_remove_entry_remove_hook (tree_store_remove_fn callback)
|
|
|
-{
|
|
|
- delete_hook (&remove_entry_hooks, (void (*)(void *))callback);
|
|
|
-}
|
|
|
+ retval = current;
|
|
|
|
|
|
-void
|
|
|
-tree_store_notify_remove (tree_entry *entry)
|
|
|
-{
|
|
|
- Hook *p = remove_entry_hooks;
|
|
|
- tree_store_remove_fn r;
|
|
|
-
|
|
|
-
|
|
|
- while (p){
|
|
|
- r = (tree_store_remove_fn) p->hook_fn;
|
|
|
- r (entry, p->hook_data);
|
|
|
- p = p->next;
|
|
|
- }
|
|
|
-}
|
|
|
-void
|
|
|
-tree_store_add_entry_add_hook (tree_store_add_fn callback, void *data)
|
|
|
-{
|
|
|
- add_hook (&add_entry_hooks, (void (*)(void *))callback, data);
|
|
|
-}
|
|
|
+ /* Mark old subdirectories for delete */
|
|
|
+ ts.check_start = current->next;
|
|
|
+ len = strlen(ts.check_name);
|
|
|
|
|
|
-void
|
|
|
-tree_store_remove_entry_add_hook (tree_store_add_fn callback)
|
|
|
-{
|
|
|
- delete_hook (&add_entry_hooks, (void (*)(void *))callback);
|
|
|
-}
|
|
|
+ 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)) {
|
|
|
+ current->mark = 1;
|
|
|
+ current = current->next;
|
|
|
+ }
|
|
|
|
|
|
-void
|
|
|
-tree_store_notify_add (char *directory)
|
|
|
-{
|
|
|
- Hook *p = add_entry_hooks;
|
|
|
- tree_store_add_fn r;
|
|
|
-
|
|
|
- while (p) {
|
|
|
- r = (tree_store_add_fn) p->hook_fn;
|
|
|
- r (directory, p->hook_data);
|
|
|
- p = p->next;
|
|
|
- }
|
|
|
+ return retval;
|
|
|
}
|
|
|
|
|
|
-void
|
|
|
-tree_store_add_freeze_hook (tree_freeze_fn callback, void *data)
|
|
|
+tree_entry *
|
|
|
+tree_store_start_check_cwd(void)
|
|
|
{
|
|
|
- add_hook (&freeze_hooks, (void (*)(void *)) callback, data);
|
|
|
-}
|
|
|
+ char buffer[MC_MAXPATHLEN];
|
|
|
|
|
|
-void
|
|
|
-tree_store_remove_freeze_hook (tree_freeze_fn callback)
|
|
|
-{
|
|
|
- delete_hook (&freeze_hooks, (void (*)(void *))callback);
|
|
|
+ mc_get_current_wd(buffer, MC_MAXPATHLEN);
|
|
|
+ return tree_store_start_check(buffer);
|
|
|
}
|
|
|
|
|
|
+/* Delete subdirectories which still have the deletion mark */
|
|
|
void
|
|
|
-tree_store_set_freeze (int freeze)
|
|
|
+tree_store_end_check(void)
|
|
|
{
|
|
|
- Hook *p = freeze_hooks;
|
|
|
- tree_freeze_fn f;
|
|
|
-
|
|
|
- while (p) {
|
|
|
- f = (tree_freeze_fn) p->hook_fn;
|
|
|
- f (freeze, p->hook_data);
|
|
|
- p = p->next;
|
|
|
- }
|
|
|
+ tree_entry *current, *old;
|
|
|
+ int len;
|
|
|
+ GList *the_queue, *l;
|
|
|
+
|
|
|
+ if (!ts.loaded)
|
|
|
+ return;
|
|
|
+
|
|
|
+ g_return_if_fail(ts.check_name != NULL);
|
|
|
+
|
|
|
+ /* Check delete marks and delete if found */
|
|
|
+ len = strlen(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)) {
|
|
|
+ old = current;
|
|
|
+ current = current->next;
|
|
|
+ if (old->mark)
|
|
|
+ remove_entry(old);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 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;
|
|
|
+ g_free(ts.check_name);
|
|
|
+ ts.check_name = NULL;
|
|
|
+
|
|
|
+ for (l = the_queue; l; l = l->next) {
|
|
|
+ g_free(l->data);
|
|
|
+ }
|
|
|
+
|
|
|
+ g_list_free(the_queue);
|
|
|
}
|
|
|
|
|
|
-tree_scan *
|
|
|
-tree_store_opendir (char *path)
|
|
|
+static void
|
|
|
+process_special_dirs(GList ** special_dirs, char *file)
|
|
|
{
|
|
|
- tree_entry *entry;
|
|
|
- tree_scan *scan;
|
|
|
-
|
|
|
- entry = tree_store_whereis (path);
|
|
|
- if (!entry || (entry && !entry->scanned)) {
|
|
|
- entry = tree_store_rescan (path);
|
|
|
+ char *token;
|
|
|
+ char *buffer = g_malloc(4096);
|
|
|
+ char *s;
|
|
|
|
|
|
- if (!entry)
|
|
|
- return NULL;
|
|
|
- }
|
|
|
+ GetPrivateProfileString("Special dirs", "list",
|
|
|
+ "", buffer, 4096, file);
|
|
|
+ s = buffer;
|
|
|
+ while ((token = strtok(s, ",")) != NULL) {
|
|
|
+ *special_dirs = g_list_prepend(*special_dirs, g_strdup(token));
|
|
|
+ s = NULL;
|
|
|
+ }
|
|
|
+ g_free(buffer);
|
|
|
+}
|
|
|
|
|
|
- if (entry->next == NULL)
|
|
|
- return NULL;
|
|
|
+static gboolean
|
|
|
+should_skip_directory(char *dir)
|
|
|
+{
|
|
|
+ static GList *special_dirs;
|
|
|
+ GList *l;
|
|
|
+ static int loaded;
|
|
|
|
|
|
- scan = g_new (tree_scan, 1);
|
|
|
- scan->base = entry;
|
|
|
- scan->current = entry->next;
|
|
|
- scan->sublevel = entry->next->sublevel;
|
|
|
+ if (loaded == 0) {
|
|
|
+ loaded = 1;
|
|
|
+ setup_init();
|
|
|
+ process_special_dirs(&special_dirs, profile_name);
|
|
|
+ process_special_dirs(&special_dirs, CONFDIR "mc.global");
|
|
|
+ }
|
|
|
|
|
|
- scan->base_dir_len = strlen (path);
|
|
|
- return scan;
|
|
|
+ for (l = special_dirs; l; l = l->next) {
|
|
|
+ if (strncmp(dir, l->data, strlen(l->data)) == 0)
|
|
|
+ return TRUE;
|
|
|
+ }
|
|
|
+ return FALSE;
|
|
|
}
|
|
|
|
|
|
tree_entry *
|
|
|
-tree_store_readdir (tree_scan *scan)
|
|
|
+tree_store_rescan(char *dir)
|
|
|
{
|
|
|
- tree_entry *entry;
|
|
|
- int len;
|
|
|
-
|
|
|
- g_assert (scan != NULL);
|
|
|
-
|
|
|
- len = scan->base_dir_len;
|
|
|
- entry = scan->current;
|
|
|
- while (entry &&
|
|
|
- (strncmp (entry->name, scan->base->name, len) == 0) &&
|
|
|
- (entry->name [len] == 0 || entry->name [len] == PATH_SEP || len == 1)){
|
|
|
-
|
|
|
- if (entry->sublevel == scan->sublevel){
|
|
|
- scan->current = entry->next;
|
|
|
- return entry;
|
|
|
- }
|
|
|
- entry = entry->next;
|
|
|
- }
|
|
|
+ DIR *dirp;
|
|
|
+ struct dirent *dp;
|
|
|
+ struct stat buf;
|
|
|
+ tree_entry *entry;
|
|
|
|
|
|
+ if (should_skip_directory(dir)) {
|
|
|
+ entry = tree_store_add_entry(dir);
|
|
|
+ entry->scanned = 1;
|
|
|
+
|
|
|
+ return entry;
|
|
|
+ }
|
|
|
+
|
|
|
+ entry = tree_store_start_check(dir);
|
|
|
+
|
|
|
+ if (!entry)
|
|
|
return NULL;
|
|
|
-}
|
|
|
|
|
|
-void
|
|
|
-tree_store_closedir (tree_scan *scanner)
|
|
|
-{
|
|
|
- g_assert (scanner != NULL);
|
|
|
-
|
|
|
- g_free (scanner);
|
|
|
+ dirp = mc_opendir(dir);
|
|
|
+ if (dirp) {
|
|
|
+ for (dp = mc_readdir(dirp); dp; dp = mc_readdir(dirp)) {
|
|
|
+ char *full_name;
|
|
|
+
|
|
|
+ if (dp->d_name[0] == '.') {
|
|
|
+ if (dp->d_name[1] == 0
|
|
|
+ || (dp->d_name[1] == '.' && dp->d_name[2] == 0))
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ full_name = concat_dir_and_file(dir, dp->d_name);
|
|
|
+ if (mc_lstat(full_name, &buf) != -1) {
|
|
|
+ if (S_ISDIR(buf.st_mode))
|
|
|
+ tree_store_mark_checked(dp->d_name);
|
|
|
+ }
|
|
|
+ g_free(full_name);
|
|
|
+ }
|
|
|
+ mc_closedir(dirp);
|
|
|
+ }
|
|
|
+ tree_store_end_check();
|
|
|
+ entry->scanned = 1;
|
|
|
+
|
|
|
+ return entry;
|
|
|
}
|