Browse Source

* treestore.c: Remove unused code, reformat.
* treestore.h: Remove unused declarations.

Pavel Roskin 22 years ago
parent
commit
cafbb72684
3 changed files with 589 additions and 733 deletions
  1. 3 0
      src/ChangeLog
  2. 585 699
      src/treestore.c
  3. 1 34
      src/treestore.h

+ 3 - 0
src/ChangeLog

@@ -1,5 +1,8 @@
 2002-08-15  Pavel Roskin  <proski@gnu.org>
 
+	* treestore.c: Remove unused code, reformat.
+	* treestore.h: Remove unused declarations.
+
 	* fs.h (compute_namelen): New inline function to take care of
 	the d_namlen field if and only if it's needed.
 

+ 585 - 699
src/treestore.c

@@ -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;
 }

+ 1 - 34
src/treestore.h

@@ -39,10 +39,6 @@ typedef struct {
 	unsigned int dirty : 1;
 } TreeStore;
 
-#define TREE_CHECK_NAME ts.check_name_list->data
-
-extern void (*tree_store_dirty_notify)(int state);
-
 TreeStore  *tree_store_get             (void);
 int         tree_store_load            (void);
 int         tree_store_save            (void);
@@ -62,34 +58,5 @@ typedef void (*tree_store_remove_fn)(tree_entry *tree, void *data);
 void        tree_store_add_entry_remove_hook    (tree_store_remove_fn callback, void *data);
 void        tree_store_remove_entry_remove_hook (tree_store_remove_fn callback);
 
-/*
- * Register/unregister notification functions for "entry_add"
- */
-typedef void (*tree_store_add_fn)(char *name, void *data);
-void        tree_store_add_entry_add_hook    (tree_store_add_fn callback, void *data);
-void        tree_store_remove_entry_add_hook (tree_store_add_fn callback);
-
-/*
- * Register/unregister freeze/unfreeze functions for the tree
- */
-typedef void (*tree_freeze_fn)(int freeze, void *data);
-void tree_store_add_freeze_hook              (tree_freeze_fn callback, void *data);
-void tree_store_remove_freeze_hook           (tree_freeze_fn);
-
-/*
- * Changes in the tree_entry are notified with these
- */
-void        tree_store_notify_remove   (tree_entry *entry);
-void        tree_store_notify_add      (char *directory);
-
-/*
- * Freeze unfreeze notification
- */
-void        tree_store_set_freeze    (int freeze);
-
-tree_scan  *tree_store_opendir       (char *path);
-tree_entry *tree_store_readdir       (tree_scan *scanner);
-void        tree_store_closedir      (tree_scan *scanner);
-
-#endif
+#endif /* !__TREE_STORE_H */