⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tree.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 3 页
字号:
    len = strlen (tree->check_name);

    current = tree->check_start;
    while (current
	   && strncmp (current->name, tree->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 (tree, old);
    }
}

/* Loads the .mc.tree file */
void load_tree (WTree *tree)
{
    char *filename;
    FILE *file;
    char name [MC_MAXPATHLEN], oldname[MC_MAXPATHLEN];
    char *different;
    int len, common;

    filename = concat_dir_and_file (home_dir, MC_TREE);
    file = fopen (filename, "r");
    free (filename);
    if (!file){
	/* No new tree file -> let's try the old file */
	filename = concat_dir_and_file (home_dir, MC_TREE);
	file = fopen (filename, "r");
	free (filename);
    }

    if (file){
	/* File open -> read contents */
	oldname [0] = 0;
	while (fgets (name, MC_MAXPATHLEN, file)){
	    len = strlen (name);
	    if (name [len - 1] == '\n'){
		name [--len] = 0;
	    }
#ifdef OS2_NT
            /* .ado: Drives for NT and OS/2 */
            if ((len > 2)         &&
                 isalpha(name[0]) &&
                 (name[1] == ':') &&
                 (name[2] == '\\')) {
        		tree_add_entry (tree, 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);
			tree_add_entry (tree, oldname);
		    }
		}
	    } else {
		tree_add_entry (tree, name);
		strcpy (oldname, name);
	    }
	}
	fclose (file);
    }
    if (!tree->tree_first){
	/* Nothing loaded -> let's add some standard directories */
	tree_add_entry (tree, PATH_SEP_STR);
	tree->selected_ptr = tree->tree_first;
	tree_rescan_cmd (tree);
	tree_add_entry (tree, home_dir);
	tree_chdir (tree, home_dir);
	tree_rescan_cmd (tree);
    }
}

/* Save the .mc.tree file */
void save_tree (WTree *tree)
{
    tree_entry *current;
    char *filename;
    FILE *file;
    int i, common;

    filename = concat_dir_and_file (home_dir, MC_TREE);
    file = fopen (filename, "w");
    free (filename);
    if (!file){
	fprintf (stderr, _("Can't open the %s file for writing:\n%s\n"), MC_TREE,
		 unix_error_string (errno));
	return;
    }

    current = tree->tree_first;
    while (current){
	if (current->prev && (common = str_common (current->prev->name, current->name)) > 2)
	    /* Clear-text compression */
	    i = fprintf (file, "%d %s\n", common, current->name + common);
	else
	    i = fprintf (file, "%s\n", current->name);
	if (i == EOF){
	    fprintf (stderr, _("Can't write to the %s file:\n%s\n"), MC_TREE,
		 unix_error_string (errno));
	    break;
	}
	current = current->next;
    }
    fclose (file);
}

static void tree_show_mini_info (WTree *tree, int tree_lines, int tree_cols)
{
    Dlg_head *h = tree->widget.parent;
    int      line;

    /* Show mini info */
    if (tree->is_panel){
	if (!show_mini_info)
	    return;
	line = tree_lines+2;
    } else
	line = tree_lines+1;

    widget_move (&tree->widget, line, 1);
    hline (' ', tree_cols);
    widget_move (&tree->widget, line, 1);

    if (tree->searching){
	/* Show search string */
	attrset (TREE_NORMALC);
	attrset (FOCUSC);
	addch (PATH_SEP);

	addstr (name_trunc (tree->search_buffer, tree_cols-2));
	addch (' ');
	attrset (FOCUSC);
    } else {
	/* Show full name of selected directory */
	addstr (name_trunc (tree->selected_ptr->name, tree_cols));
    }
}

void show_tree (WTree *tree)
{
    Dlg_head *h = tree->widget.parent;
    tree_entry *current;
    int i, j, topsublevel;
    int x, y;
    int tree_lines, tree_cols;

    /* Initialize */
    x = y = 0;
    tree_lines = tlines (tree);
    tree_cols  = tree->widget.cols;

    attrset (TREE_NORMALC);
    widget_move ((Widget*)tree, y, x);
    if (tree->is_panel){
	tree_cols  -= 2;
	x = y = 1;
    }

    if (tree->tree_shown)
	free (tree->tree_shown);
    tree->tree_shown = (tree_entry**)xmalloc (sizeof (tree_entry*)*tree_lines,
					      "tree, show_tree");
    for (i = 0; i < tree_lines; i++)
	tree->tree_shown [i] = NULL;
    if (tree->tree_first)
	topsublevel = tree->tree_first->sublevel;
    else
	topsublevel = 0;
    if (!tree->selected_ptr){
	tree->selected_ptr = tree->tree_first;
	tree->topdiff = 0;
    }
    current = tree->selected_ptr;

    /* Calculate the directory which is to be shown on the topmost line */
    if (tree_navigation_flag){
	i = 0;
	while (current->prev && i < tree->topdiff){
	    current = current->prev;
	    if (current->sublevel < tree->selected_ptr->sublevel){
		if (strncmp (current->name, tree->selected_ptr->name,
			     strlen (current->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)
		    i++;
	    } else if (current->sublevel == tree->selected_ptr->sublevel + 1
		       && strlen (tree->selected_ptr->name) > 1){
		if (strncmp (current->name, tree->selected_ptr->name,
			     strlen (tree->selected_ptr->name)) == 0)
		    i++;
	    }
	}
	tree->topdiff = i;
    } else
	current = back_ptr (current, &tree->topdiff);

    /* Loop for every line */
    for (i = 0; i < tree_lines; i++){
	/* Move to the beginning of the line */
	widget_move (&tree->widget, y+i, x);

	hline (' ', tree_cols);
	widget_move (&tree->widget, y+i, x);

	if (!current)
	    continue;

	tree->tree_shown [i] = current;
	if (current->sublevel == topsublevel){

	    /* Top level directory */
	    if (tree->active && current == tree->selected_ptr)
		if (!use_colors && !tree->is_panel)
			attrset (MARKED_COLOR);
		else
			attrset (SELECTED_COLOR);

	    /* Show full name */
	    addstr (name_trunc (current->name, tree_cols - 6));
	} else{
	    /* Sub level directory */

	    acs ();
	    /* Output branch parts */
	    for (j = 0; j < current->sublevel - topsublevel - 1; j++){
		if (tree_cols - 8 - 3 * j < 9)
		    break;
		addch (' ');
		if (current->submask & (1 << (j + topsublevel + 1)))
		    addch (ACS_VLINE);
		else
		    addch (' ');
		addch (' ');
	    }
	    addch (' '); j++;
	    if (!current->next || !(current->next->submask & (1 << current->sublevel)))
		addch (ACS_LLCORNER);
	    else
		addch (ACS_LTEE);
	    addch (ACS_HLINE);
	    noacs ();

	    if (tree->active && current == tree->selected_ptr)
		/* Selected directory -> change color */
		if (!use_colors && !tree->is_panel)
		    attrset (MARKED_COLOR);
		else
		    attrset (SELECTED_COLOR);

	    /* Show sub-name */
	    addch (' ');
	    addstr (name_trunc (current->subname,
				tree_cols - 2 - 4 - 3 * j));
	}
	addch (' ');

	/* Return to normal color */
	attrset (TREE_NORMALC);

	/* Calculate the next value for current */
	if (tree_navigation_flag){
	    current = current->next;
	    while (current){
		if (current->sublevel < tree->selected_ptr->sublevel){
		    if (strncmp (current->name, tree->selected_ptr->name,
				 strlen (current->name)) == 0)
			break;
		} 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)
			break;
		} else if (current->sublevel == tree->selected_ptr->sublevel+1
			   && strlen (tree->selected_ptr->name) > 1){
		    if (strncmp (current->name, tree->selected_ptr->name,
				 strlen (tree->selected_ptr->name)) == 0)
			break;
		}
		current = current->next;
	    }
	} else
	    current = current->next;
    }
    tree_show_mini_info (tree, tree_lines, tree_cols);
}

static void check_focus (WTree *tree)
{
    if (tree->topdiff < 3)
	tree->topdiff = 3;
    else if (tree->topdiff >= tlines (tree) - 3)
	tree->topdiff = tlines (tree) - 3 - 1;
}

void tree_move_backward (WTree *tree, int i)
{
    tree_entry *current;
    int j = 0;

    if (tree_navigation_flag){
	current = tree->selected_ptr;
	while (j < i && current->prev
	       && current->prev->sublevel >= tree->selected_ptr->sublevel){
	    current = current->prev;
	    if (current->sublevel == tree->selected_ptr->sublevel){
		tree->selected_ptr = current;
		j ++;
	    }
	}
	i = j;
    } else
	tree->selected_ptr = back_ptr (tree->selected_ptr, &i);
    tree->topdiff -= i;
    check_focus (tree);
}

void tree_move_forward (WTree *tree, int i)
{
    tree_entry *current;
    int j = 0;

    if (tree_navigation_flag){
	current = tree->selected_ptr;
	while (j < i && current->next
	       && current->next->sublevel >= tree->selected_ptr->sublevel){
	    current = current->next;
	    if (current->sublevel == tree->selected_ptr->sublevel){
		tree->selected_ptr = current;
		j ++;
	    }
	}
	i = j;
    } else
	tree->selected_ptr = forw_ptr (tree->selected_ptr, &i);
    tree->topdiff += i;
    check_focus (tree);
}

void tree_move_to_child (WTree *tree)
{
    tree_entry *current;

    /* Do we have a starting point? */
    if (!tree->selected_ptr)
	return;
    /* Take the next entry */
    current = tree->selected_ptr->next;
    /* Is it the child of the selected entry */
    if (current && current->sublevel > tree->selected_ptr->sublevel){
	/* Yes -> select this entry */
	tree->selected_ptr = current;
	tree->topdiff++;
	check_focus (tree);
    } else {
	/* No -> rescan and try again */
	tree_rescan_cmd (tree);
	current = tree->selected_ptr->next;
	if (current && current->sublevel > tree->selected_ptr->sublevel){
	    tree->selected_ptr = current;
	    tree->topdiff++;
	    check_focus (tree);
	}
    }
}

int tree_move_to_parent (WTree *tree)
{
    tree_entry *current;
    tree_entry *old;

    if (!tree->selected_ptr)
	return 0;
    old = tree->selected_ptr;
    current = tree->selected_ptr->prev;
    while (current && current->sublevel >= tree->selected_ptr->sublevel){
	current = current->prev;
	tree->topdiff--;
    }
    if (!current)
	current = tree->tree_first;
    tree->selected_ptr = current;
    check_focus (tree);
    return tree->selected_ptr != old;
}

void tree_move_to_top (WTree *tree)
{
    tree->selected_ptr = tree->tree_first;
    tree->topdiff = 0;
}

void tree_move_to_bottom (WTree *tree)
{
    tree->selected_ptr = tree->tree_last;
    tree->topdiff = tlines (tree) - 3 - 1;
}

void tree_chdir (WTree *tree, char *dir)
{
    tree_entry *current;

    current = whereis (tree, dir);
    if (current){
	tree->selected_ptr = current;
	check_focus (tree);
    }
}

/* Handle mouse click */
void tree_event (WTree *tree, int y)
{
    if (tree->tree_shown [y]){
	tree->selected_ptr = tree->tree_shown [y];
	tree->topdiff = y;
    }
    show_tree (tree);
}

static void chdir_sel (WTree *tree);

static void maybe_chdir (WTree *tree)
{
    if (!(xtree_mode && tree->is_panel))
	return;
    if (is_idle ())
	chdir_sel (tree);
}

/* Mouse callback */
static int event_callback (Gpm_Event *event, WTree *tree)
{
    if (!(event->type & GPM_UP))
	return MOU_ENDLOOP;

    if (tree->is_panel)
	event->y--;

    event->y--;

    if (!tree->active)
	change_panel ();

    if (event->y < 0){
	tree_move_backward (tree, tlines (tree) - 1);
	show_tree (tree);
    }
    else if (event->y >= tlines (tree)){
	tree_move_forward (tree, tlines (tree) - 1);
	show_tree (tree);
    } else {
	tree_event (tree, event->y);
	if ((event->type & (GPM_UP|GPM_DOUBLE)) == (GPM_UP|GPM_DOUBLE)){
	    chdir_sel (tree);
	}
    }
    return MOU_ENDLOOP;
}

/* Search tree for text */
int search_tree (WTree *tree, char *text)
{
    tree_entry *current;
    int len;
    int wrapped = 0;
    int found = 0;

    len = strlen (text);
    current = tree->selected_ptr;
    found = 0;
    while (!wrapped || current != tree->selected_ptr){
	if (strncmp (current->subname, text, len) == 0){
	    tree->selected_ptr = current;
	    found = 1;
	    break;
	}
	current = current->next;
	if (!current){
	    current = tree->tree_first;
	    wrapped = 1;
	}
	tree->topdiff++;
    }
    check_focus (tree);
    return found;
}

static void tree_do_search (WTree *tree, int key)
{
    int l;

    l = strlen (tree->search_buffer);
    if (l && (key == 8 || key == 0177 || key == KEY_BACKSPACE))
	tree->search_buffer [--l] = 0;
    else {
	if (key && l < sizeof (tree->search_buffer)){
	    tree->search_buffer [l] = key;
	    tree->search_buffer [l+1] = 0;
	    l++;
	}
    }

    if (!search_tree (tree, tree->search_buffer))
	tree->search_buffer [--l] = 0;

    show_tree (tree);
    maybe_chdir (tree);
}

void tree_rescan_cmd (WTree *tree)
{
    DIR *dirp;
    struct dirent *dp;
    struct stat buf;
    char old_dir [MC_MAXPATHLEN];

    if (!tree->selected_ptr || !mc_get_current_wd (old_dir, MC_MAXPATHLEN) ||
	mc_chdir (tree->selected_ptr->name))
	return;

    start_tree_check (tree);
    dirp = opendir (".");
    if (dirp){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -