예제 #1
0
파일: node.c 프로젝트: sffej/gnome-inform7
gboolean
i7_node_in_thread(I7Node *self, I7Node *endnode)
{
	return (endnode == self) || g_node_is_ancestor(self->gnode, endnode->gnode);
}
예제 #2
0
파일: colexp.c 프로젝트: Explorer09/fsv
/* This keeps the directory tree and the map geometry in sync
 * (expansion state vs. "deployment" value) */
void
colexp( GNode *dnode, ColExpMesg mesg )
{
	static double colexp_time;
	static int depth = 0;
	static int max_depth;
	GNode *node;
	double wait_time;
	double pan_time;
	int wait_count = 0;
	boolean curnode_is_ancestor, curnode_is_descendant, curnode_is_equal;

	g_assert( NODE_IS_DIR(dnode) );

	if (depth == 0) {
#ifdef DEBUG
		if (mesg != COLEXP_EXPAND_ANY) {
			/* All ancestor directories must be expanded */
			node = dnode->parent;
			while (NODE_IS_DIR(node)) {
				g_assert( DIR_NODE_DESC(node)->deployment > (1.0 - EPSILON) );
				node = node->parent;
			}
		}
#endif

		/* Update ctree and determine maximum recursion depth */
		switch (mesg) {
			case COLEXP_COLLAPSE_RECURSIVE:
			dirtree_entry_collapse_recursive( dnode );
			max_depth = max_expanded_depth( dnode );
			break;

			case COLEXP_EXPAND:
			dirtree_entry_expand( dnode );
			max_depth = 0;
			break;

			case COLEXP_EXPAND_ANY:
			dirtree_entry_expand( dnode );
			max_depth = collapsed_depth( dnode );
			break;

			case COLEXP_EXPAND_RECURSIVE:
			dirtree_entry_expand_recursive( dnode );
			/* max_depth will be used as a high-water mark */
			max_depth = 0;
			break;

			SWITCH_FAIL
		}

		/* Make file list appropriately (in)accessible */
		filelist_reset_access( );

		gui_update( );

		/* Collapse/expand time for current visualization mode */
		switch (globals.fsv_mode) {
			case FSV_DISCV:
			colexp_time = DISCV_COLEXP_TIME;
			break;

			case FSV_MAPV:
			colexp_time = MAPV_COLEXP_TIME;
			break;

			case FSV_TREEV:
			colexp_time = TREEV_COLEXP_TIME;
			break;

                        SWITCH_FAIL
		}
	}

	morph_break( &DIR_NODE_DESC(dnode)->deployment );

	/* Determine time to wait before collapsing/expanding directory */
	switch (mesg) {
		case COLEXP_COLLAPSE_RECURSIVE:
		wait_count = max_depth - depth;
		break;

		case COLEXP_EXPAND_RECURSIVE:
		case COLEXP_EXPAND:
		wait_count = depth;
		break;

		case COLEXP_EXPAND_ANY:
		wait_count = max_depth - depth;
		break;

		SWITCH_FAIL
	}
	if (wait_count > 0) {
		wait_time = (double)wait_count * colexp_time;
		morph( &DIR_NODE_DESC(dnode)->deployment, MORPH_LINEAR, DIR_NODE_DESC(dnode)->deployment, wait_time );
	}

	/* Initiate collapse/expand */
	switch (mesg) {
		case COLEXP_COLLAPSE_RECURSIVE:
		morph_full( &DIR_NODE_DESC(dnode)->deployment, MORPH_QUADRATIC, 0.0, colexp_time, colexp_progress_cb, colexp_progress_cb, dnode );
		break;

		case COLEXP_EXPAND:
		case COLEXP_EXPAND_ANY:
		case COLEXP_EXPAND_RECURSIVE:
		morph_full( &DIR_NODE_DESC(dnode)->deployment, MORPH_INV_QUADRATIC, 1.0, colexp_time, colexp_progress_cb, colexp_progress_cb, dnode );
		break;

		SWITCH_FAIL
	}

	/* Recursion */
	/* geometry_colexp_initiated( ) is called at differing points below
	 * because (at least in TreeV mode) notification must always
	 * proceed from parent to children, and not the other way around */
	switch (mesg) {
		case COLEXP_EXPAND:
		/* Initial collapse/expand notify */
		geometry_colexp_initiated( dnode );
		/* EXPAND does not walk the tree */
		break;

		case COLEXP_EXPAND_ANY:
		/* Ensure that all parent directories are expanded */
		if (NODE_IS_DIR(dnode->parent)) {
			++depth;
			colexp( dnode->parent, COLEXP_EXPAND_ANY );
			--depth;
		}
		/* Initial collapse/expand notify */
		geometry_colexp_initiated( dnode );
		break;

		case COLEXP_COLLAPSE_RECURSIVE:
		case COLEXP_EXPAND_RECURSIVE:
		/* Initial collapse/expand notify */
		geometry_colexp_initiated( dnode );
		/* Perform action on subdirectories */
		++depth;
		node = dnode->children;
		while (node != NULL) {
			if (NODE_IS_DIR(node))
				colexp( node, mesg );
			else
				break;
			node = node->next;
		}
		--depth;
		break;

		SWITCH_FAIL
	}

	if (mesg == COLEXP_EXPAND_RECURSIVE) {
		/* Update high-water mark */
		max_depth = MAX(max_depth, depth);
	}

	if (depth == 0) {
		/* Determine position of current node w.r.t. the
		 * collapsing/expanding directory node */
		curnode_is_ancestor = g_node_is_ancestor( globals.current_node, dnode );
		curnode_is_equal = globals.current_node == dnode;
		curnode_is_descendant = g_node_is_ancestor( dnode, globals.current_node );

		/* Handle the camera semi-intelligently if it is not under
		 * manual control */
		if (!camera->manual_control) {
			switch (mesg) {
				case COLEXP_COLLAPSE_RECURSIVE:
				pan_time = (double)(max_depth + 1) * colexp_time;
				if (curnode_is_ancestor || curnode_is_equal)
					camera_look_at_full( globals.current_node, MORPH_LINEAR, pan_time );
				else if (curnode_is_descendant)
					camera_look_at_full( dnode, MORPH_LINEAR, pan_time );
				break;

				case COLEXP_EXPAND:
				case COLEXP_EXPAND_RECURSIVE:
				if (curnode_is_ancestor || curnode_is_equal) {
					pan_time = (double)(max_depth + 1) * colexp_time;
					camera_look_at_full( globals.current_node, MORPH_LINEAR, pan_time );
				}
				break;

				case COLEXP_EXPAND_ANY:
				/* Don't do anything. Something else
				 * should already be doing something
				 * with the camera */
				break;

				SWITCH_FAIL
			}
		}

		/* If, in TreeV mode, the current node is an ancestor of
		 * a collapsing/expanding directory, the scrollbars may
		 * need updating to reflect a new scroll range */
		scrollbars_colexp_adjust = FALSE;
		if (curnode_is_ancestor && (globals.fsv_mode == FSV_TREEV))
			scrollbars_colexp_adjust = TRUE;
	}
예제 #3
0
파일: ino.c 프로젝트: jimenezrick/fast-move
gboolean remove_from_tree(GNode *file, gboolean unmount)
{
	int position = g_list_position(lines, FILE(file)->line);
	gboolean refresh_needed = FALSE;
	GList *line_ptr, *line_ptr2;
	GNode *dir_ptr;

	if (G_NODE_IS_ROOT(file)) {
		endwin();
		clean_up();
		printf("The tree root was removed\n");
		exit(EXIT_SUCCESS);
	}
	if (g_node_is_ancestor(file, NODE(selected_line)))
		select_file(file);
	if (FILE(file)->type == directory_type) {
		close_directory(file);
		destroy_directory_content_real(file, FALSE);
		if (unmount)
			return TRUE;
	} else if (FILE(file)->type == file_type) {
		for (dir_ptr = file->parent; !G_NODE_IS_ROOT(dir_ptr);
				dir_ptr = dir_ptr->parent) {
			if (FILE(dir_ptr)->open == FALSE) {
				g_node_unlink(file);
				return FALSE;
			}
		}
		if (FILE(dir_ptr)->open == FALSE) {
			g_node_unlink(file);
			return FALSE;
		}
	}
	g_node_unlink(file);

	if (g_list_position(lines, first_line) <= position &&
			position <= g_list_position(lines, last_line)) {
		if (first_line == FILE(file)->line && selected_line == FILE(file)->line) {
			selected_line = first_line = g_list_previous(first_line);
			lines = g_list_delete_link(lines, FILE(file)->line);
			print_lines(first_line, first_line, FALSE);
		} else if (position < g_list_position(lines, selected_line)) {
			if (first_line == FILE(file)->line)
				first_line = g_list_next(first_line);
			line_ptr = g_list_previous(FILE(file)->line);
			lines = g_list_delete_link(lines, FILE(file)->line);
			if ((line_ptr2 = g_list_previous(first_line)) != NULL) {
				first_line = line_ptr2;
				print_lines(first_line, line_ptr, FALSE);
			} else if ((line_ptr2 = g_list_next(last_line)) != NULL) {
				last_line = line_ptr2;
				print_lines(line_ptr, last_line, FALSE);
			} else
				print_lines(line_ptr, last_line, TRUE);
		} else {
			if (FILE(file)->line == selected_line)
				selected_line = g_list_previous(selected_line);
			if (last_line == FILE(file)->line)
				last_line = g_list_previous(last_line);
			line_ptr = g_list_previous(FILE(file)->line);
			lines = g_list_delete_link(lines, FILE(file)->line);
			if ((line_ptr2 = g_list_next(last_line)) != NULL) {
				last_line = line_ptr2;
				print_lines(line_ptr, last_line, FALSE);
			} else
				print_lines(line_ptr, last_line, TRUE);
		}
		refresh_needed = TRUE;
	} else {
		if (last_line == g_list_previous(FILE(file)->line)) {
			lines = g_list_delete_link(lines, FILE(file)->line);
			print_lines(last_line, last_line, FALSE);
			refresh_needed = TRUE;
		} else
			lines = g_list_delete_link(lines, FILE(file)->line);
	}
	free_node_data(file, NULL);
	g_node_destroy(file);

	return refresh_needed;
}
예제 #4
0
/* return the reversed thread tree */
GNode *procmsg_get_thread_tree(GSList *mlist)
{
	GNode *root, *parent, *node, *next;
	GHashTable *msgid_table;
	GRelation *subject_relation;
	MsgInfo *msginfo;
	const gchar *msgid;

	root = g_node_new(NULL);
	msgid_table = g_hash_table_new(g_str_hash, g_str_equal);
	subject_relation = g_relation_new(2);
	g_relation_index(subject_relation, 0, g_str_hash, g_str_equal);

	for (; mlist != NULL; mlist = mlist->next) {
		msginfo = (MsgInfo *)mlist->data;
		parent = root;

		if (msginfo->inreplyto) {
			parent = g_hash_table_lookup(msgid_table, msginfo->inreplyto);
			if (parent == NULL) {
				parent = root;
			}
		}
		node = g_node_insert_data_before
			(parent, parent == root ? parent->children : NULL,
			 msginfo);
		if ((msgid = msginfo->msgid) && g_hash_table_lookup(msgid_table, msgid) == NULL)
			g_hash_table_insert(msgid_table, (gchar *)msgid, node);

		/* CLAWS: add subject to relation (without prefix) */
		if (prefs_common.thread_by_subject) {
			subject_relation_insert(subject_relation, node);
		}
	}

	/* complete the unfinished threads */
	for (node = root->children; node != NULL; ) {
		parent = NULL;
		next = node->next;
		msginfo = (MsgInfo *)node->data;
		if (msginfo->inreplyto) { 
			parent = g_hash_table_lookup(msgid_table, msginfo->inreplyto);
			/* node should not be the parent, and node should not 
			   be an ancestor of parent (circular reference) */
			if (parent && parent != node && 
			    !g_node_is_ancestor(node, parent)) {
				g_node_unlink(node);
				g_node_insert_before
					(parent, parent->children, node);
			}				
		}
		node = next;
	}

	if (prefs_common.thread_by_subject) {
		for (node = root->children; node && node != NULL;) {
			next = node->next;
			msginfo = (MsgInfo *) node->data;
			
			parent = subject_relation_lookup(subject_relation, msginfo);
			
			/* the node may already be threaded by IN-REPLY-TO, so go up 
			 * in the tree to 
			   find the parent node */
			if (parent != NULL) {
				if (g_node_is_ancestor(node, parent))
					parent = NULL;
				if (parent == node)
					parent = NULL;
			}
			
			if (parent) {
				g_node_unlink(node);
				g_node_append(parent, node);
			}

			node = next;
		}	
	}
	
	g_relation_destroy(subject_relation);
	g_hash_table_destroy(msgid_table);

	return root;
}