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

📄 tree.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 3 页
字号:
	for (dp = readdir (dirp); dp; dp = readdir (dirp)){
	    lstat (dp->d_name, &buf);
	    if (S_ISDIR (buf.st_mode))
		do_tree_check (tree, dp->d_name);
	}
	closedir (dirp);
    }
    end_tree_check (tree);
    mc_chdir (old_dir);
}

int tree_forget_cmd (WTree *tree)
{
    if (tree->selected_ptr)
	tree_remove_entry (tree, tree->selected_ptr->name);
    return 1;
}

#if 0
static int toggle_nav_mode (void)
{
    tree_navigation_flag = 1 - tree_navigation_flag;

    return 1;
}
#endif

void tree_copy (WTree *tree, char *default_dest)
{
    char *dest;

    if (!tree->selected_ptr)
	return;
    sprintf (cmd_buf, _("Copy \"%s\" directory to:"),
	     name_trunc (tree->selected_ptr->name, 50));
    dest = input_expand_dialog (_(" Copy "), cmd_buf, default_dest);
    if (!dest || !*dest){
	return;
    }
    create_op_win (OP_COPY, 0);
    file_mask_defaults ();
    copy_dir_dir (tree->selected_ptr->name, dest, 1, 0, 0, 0);
    destroy_op_win ();
    free (dest);
}

static void tree_help_cmd (void)
{
    char *hlpfile = concat_dir_and_file (mc_home, "mc.hlp");
    interactive_display (hlpfile,  "[Directory Tree]");
    free (hlpfile);
}

static int tree_copy_cmd (WTree *tree)
{
    tree_copy (tree, "");
    return 1;
}

void tree_move (WTree *tree, char *default_dest)
{
    char *dest;
    struct stat buf;

    if (!tree->selected_ptr)
	return;
    sprintf (cmd_buf, _("Move \"%s\" directory to:"),
	     name_trunc (tree->selected_ptr->name, 50));
    dest = input_expand_dialog (_(" Move "), cmd_buf, default_dest);
    if (!dest || !*dest){
	return;
    }
    if (stat (dest, &buf)){
	message (1, _(" Error "), _(" Can't stat the destination \n %s "),
		 unix_error_string (errno));
	free (dest);
	return;
    }
    if (!S_ISDIR (buf.st_mode)){
	message (1, _(" Error "), _(" The destination isn't a directory "));
	free (dest);
	return;
    }
    create_op_win (OP_MOVE, 0);
    file_mask_defaults ();
    move_dir_dir (tree->selected_ptr->name, dest);
    destroy_op_win ();
    free (dest);
}

static int tree_move_cmd (WTree *tree)
{
    tree_move (tree, "");
    return 1;
}

static int tree_mkdir_cmd (WTree *tree)
{
    char old_dir [MC_MAXPATHLEN];

    if (!tree->selected_ptr)
	return 0;
    if (!mc_get_current_wd (old_dir, MC_MAXPATHLEN))
	return 0;
    if (chdir (tree->selected_ptr->name))
	return 0;
    /* FIXME
    mkdir_cmd (tree);
    */
    tree_rescan_cmd (tree);
    chdir (old_dir);
    return 1;
}

static void tree_rmdir_cmd (WTree *tree)
{
    char old_dir [MC_MAXPATHLEN];

    if (tree->selected_ptr){
	if (!mc_get_current_wd (old_dir, MC_MAXPATHLEN))
	    return;
	if (mc_chdir (PATH_SEP_STR))
	    return;
	if (confirm_delete){
	    char *cmd_buf;
	    int result;

	    cmd_buf = xmalloc (strlen (tree->selected_ptr->name) + 20,
			       "tree, rmdir_cmd");
	    sprintf (cmd_buf, _("  Delete %s?  "), tree->selected_ptr->name);
	    result = query_dialog (_(" Delete "), cmd_buf, 3, 2, _("&Yes"), _("&No"));
	    free (cmd_buf);
	    if (result != 0){
		return;
	    }
	}
	create_op_win (OP_DELETE, 0);
	if (erase_dir (tree->selected_ptr->name) == FILE_CONT)
	    tree_forget_cmd (tree);
	destroy_op_win ();
	mc_chdir (old_dir);
	return;
    } else
	return;
}

#if 0
static int tree_quit_cmd (void)
{
    /*
       FIXME
    return done = 1;
    */
    return 1;
}
#endif

static void set_navig_label (Dlg_head *h);
static void tree_toggle_navig (Dlg_head *h)
{
    tree_navigation_flag = 1 - tree_navigation_flag;
    set_navig_label (h);
}

void set_navig_label (Dlg_head *h)
{
    define_label_data (h, (Widget *)tree,
		       4, tree_navigation_flag ? _("Static") : _("Dynamc"),
		       (void (*)(void *))tree_toggle_navig, h);
}

static void move_down (WTree *tree)
{
    tree_move_forward (tree, 1);
    show_tree (tree);
    maybe_chdir (tree);
}

static void move_up (WTree *tree)
{
    tree_move_backward (tree, 1);
    show_tree (tree);
    maybe_chdir (tree);
}

static void move_home (WTree *tree)
{
    tree_move_to_top (tree);
    show_tree (tree);
    maybe_chdir (tree);
}

static void move_end (WTree *tree)
{
    tree_move_to_bottom (tree);
    show_tree (tree);
    maybe_chdir (tree);
}

static int move_left (WTree *tree)
{
    int v;

    if (tree_navigation_flag){
	v = tree_move_to_parent (tree);
	show_tree (tree);
	maybe_chdir (tree);
	return v;
    }
    return 0;
}

static int move_right (WTree *tree)
{
    if (tree_navigation_flag){
	tree_move_to_child (tree);
	show_tree (tree);
	maybe_chdir (tree);
	return 1;
    }
    return 0;
}

static void move_prevp (WTree *tree)
{
    tree_move_backward (tree, tlines (tree) - 1);
    show_tree (tree);
    maybe_chdir (tree);
}

static void move_nextp (WTree *tree)
{
    tree_move_forward (tree, tlines (tree) - 1);
    show_tree (tree);
    maybe_chdir (tree);
}

static void chdir_sel (WTree *tree)
{
    if (!tree->is_panel){
	tree->done = 1;
	return;
    }
    change_panel ();
    if (do_cd (tree->selected_ptr->name, cd_exact)){
	paint_panel (cpanel);
	select_item (cpanel);
    } else {
	message (1, MSG_ERROR, _(" Can't chdir to \"%s\" \n %s "),
		 tree->selected_ptr->name, unix_error_string (errno));
    }
    change_panel ();
    show_tree (tree);
    return;
}

static void start_search (WTree *tree)
{
    int i;

    if (tree->searching){

	if (tree->selected_ptr == tree->tree_last)
	    tree_move_to_top(tree);
	else {
	/* set navigation mode temporarily to 'Static' because in
	 * dynamic navigation mode tree_move_forward will not move
	 * to a lower sublevel if necessary (sequent searches must
	 * start with the directory followed the last found directory)
         */
	    i = tree_navigation_flag;
	    tree_navigation_flag = 0;
	    tree_move_forward (tree, 1);
	    tree_navigation_flag = i;
	}
	tree_do_search (tree, 0);
    }
    else {
	tree->searching = 1;
	tree->search_buffer[0] = 0;
    }
}

static key_map tree_keymap [] = {
    { XCTRL('n'), move_down    },
    { XCTRL('p'), move_up      },
    { KEY_DOWN,   move_down    },
    { KEY_UP,     move_up      },
    { '\n',       chdir_sel    },
    { KEY_ENTER,  chdir_sel    },
    { KEY_HOME,   move_home    },
    { KEY_C1,     move_end     },
    { KEY_END,    move_end     },
    { KEY_A1,     move_home    },
    { KEY_NPAGE,  move_nextp   },
    { KEY_PPAGE,  move_prevp   },
    { XCTRL('v'), move_nextp   },
    { ALT('v'),   move_prevp   },
    { XCTRL('p'), move_up      },
    { XCTRL('p'), move_down    },
    { XCTRL('s'), start_search },
    { ALT('s'),   start_search },
    { XCTRL('r'), tree_rescan_cmd },
    { KEY_DC,     tree_rmdir_cmd },
    { 0, 0 }
    };

static inline int tree_key (WTree *tree, int key)
{
    int i;

    for (i = 0; tree_keymap [i].key_code; i++){
	if (key == tree_keymap [i].key_code){
	    if (tree_keymap [i].fn != start_search)
	        tree->searching = 0;
	    (*tree_keymap [i].fn)(tree);
	    show_tree (tree);
	    return 1;
	}
    }

    /* We do not want to use them if we do not need to */
    /* Input line may want to take the motion key event */
    if (key == KEY_LEFT)
	return move_left (tree);

    if (key == KEY_RIGHT)
	return move_right (tree);

    if (is_abort_char (key)) {
	if (tree->is_panel) {
	    tree->searching = 0;
	    show_tree (tree);
	    return 1;  /* eat abort char */
	}
	return 0;  /* modal tree dialog: let upper layer see the
		      abort character and close the dialog */
    }

    /* Do not eat characters not meant for the tree below ' ' (e.g. C-l). */
    if ((key >= ' '&& key <= 255) || key == 8 || key == KEY_BACKSPACE) {
	if (tree->searching){
	    tree_do_search (tree, key);
	    show_tree (tree);
	    return 1;
	}

	if (!command_prompt) {
	    start_search (tree);
	    tree_do_search (tree, key);
	    return 1;
	}
	return tree->is_panel;
    }

    return 0;
}

static void tree_frame (Dlg_head *h, WTree *tree)
{
    attrset (NORMAL_COLOR);
    widget_erase ((Widget*) tree);
    if (tree->is_panel)
	draw_double_box (h, tree->widget.y, tree->widget.x, tree->widget.lines,
		         tree->widget.cols);

    if (show_mini_info && tree->is_panel){
	widget_move (tree, tlines (tree) + 1, 1);
	hline (ACS_HLINE, tree->widget.cols - 2);
    }
}


static int tree_callback (Dlg_head *h, WTree *tree, int msg, int par)
{
    switch (msg){
    case WIDGET_DRAW:
	tree_frame (h, tree);
	show_tree (tree);
	return 1;

    case WIDGET_KEY:
	return tree_key (tree, par);

    case WIDGET_FOCUS:
	tree->active = 1;
	define_label (h, (Widget *)tree, 1, _("Help"), (voidfn) tree_help_cmd);
	define_label_data (h, (Widget *)tree,
	    2, _("Rescan"), (buttonbarfn)tree_rescan_cmd, tree);
	define_label_data (h, (Widget *)tree,
	    3, _("Forget"), (buttonbarfn)tree_forget_cmd, tree);
	define_label_data (h, (Widget *)tree,
	    5, _("Copy"),   (buttonbarfn) tree_copy_cmd, tree);
	define_label_data (h, (Widget *)tree,
	    6, _("RenMov"), (buttonbarfn) tree_move_cmd, tree);
#if 0
	/* FIXME: mkdir is currently defunct */
	define_label_data (h, (Widget *)tree,
	    7, _("Mkdir"),  (buttonbarfn) tree_mkdir_cmd, tree);
#else
        define_label (h, (Widget *)tree, 7, "", 0);
#endif
	define_label_data (h, (Widget *)tree,
	    8, _("Rmdir"),  (buttonbarfn) tree_rmdir_cmd, tree);
	set_navig_label (h);
	redraw_labels (h, (Widget *)tree);


	/* FIXME: Should find a better way of only displaying the
	   currently selected item */
	show_tree (tree);
	return 1;

	/* FIXME: Should find a better way of changing the color of the
	   selected item */
    case WIDGET_UNFOCUS:
	tree->active = 0;
	show_tree (tree);
	return 1;
    }
    return default_proc (h, msg, par);
}

WTree *tree_new (int is_panel, int y, int x, int lines, int cols)
{
    WTree *tree = xmalloc (sizeof (WTree), "tree_new");

    init_widget (&tree->widget, y, x, lines, cols, tcallback,
		 (destroy_fn) tree_destroy, (mouse_h) event_callback, NULL);
    tree->is_panel = is_panel;
    tree->selected_ptr = 0;
    tree->tree_shown = 0;
    tree->search_buffer [0] = 0;
    tree->tree_first = tree->tree_last = 0;
    tree->topdiff = tree->widget.lines / 2;
    tree->searching = 0;
    tree->done = 0;
    tree->active = 0;

    /* We do not want to keep the cursor */
    widget_want_cursor (tree->widget, 0);
    load_tree (tree);
    return tree;
}

static char *get_absolute_name (char *file)
{
    char dir [MC_MAXPATHLEN];

    if (file [0] == PATH_SEP)
	return strdup (file);
    mc_get_current_wd (dir, MC_MAXPATHLEN);
    return get_full_name (dir, file);
}

static int my_mkdir_rec (char *s, mode_t mode)
{
    char *p, *q;
    int result;

    if (!mc_mkdir (s, mode))
        return 0;

    /* FIXME: should check instead if s is at the root of that filesystem */
    if (!vfs_file_is_local (s))
	return -1;
    if (!strcmp (vfs_path(s), PATH_SEP_STR))
        return ENOTDIR;
    p = concat_dir_and_file (s, "..");
    q = vfs_canon (p);
    free (p);
    if (!(result = my_mkdir_rec (q, mode))) {
    	result = mc_mkdir (s, mode);
    }
    free (q);
    return result;
}

int my_mkdir (char *s, mode_t mode)
{
    int result;
#if FIXME
    WTree *tree = 0;
#endif

    result = mc_mkdir (s, mode);
#ifdef OS2_NT
    /* .ado: it will be disabled in OS/2 and NT */
    /* otherwise crash if directory already exists. */
    return result;
#endif
    if (result) {
        char *p = vfs_canon (s);

        result = my_mkdir_rec (p, mode);
        free (p);
    }
    if (result == 0){
	s = get_absolute_name (s);
#if FIXME
	/* FIXME: Should receive a Wtree! */

	tree_add_entry (tree, s);
#endif
	free (s);
    }
    return result;
}

int my_rmdir (char *s)
{
    int result;
#if FIXME
    WTree *tree = 0;
#endif

    /* FIXME: Should receive a Wtree! */
    result = mc_rmdir (s);
    if (result == 0){
	s = get_absolute_name (s);
#if FIXME
	tree_remove_entry (tree, s);
#endif
	free (s);
    }
    return result;
}


⌨️ 快捷键说明

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