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

📄 hotlist.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Directory hotlist -- for the Midnight Commander
   Copyright (C) 1994, 1995, 1996, 1997 the Free Software Foundation.

   Written by:
    1994 Radek Doulik
    1995 Janne Kukonlehto
    1996 Andrej Borsenkow
    1997 Norbert Warmuth

   Janne did the original Hotlist code, Andrej made the groupable
   hotlist; the move hotlist and revamped the file format and made
   it stronger.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <config.h>
#ifdef HAVE_UNISTD_H
#   include <unistd.h>
#endif
#include <string.h>
#include <stdio.h>
#include <stdlib.h>		/* For malloc() */
#include <ctype.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#ifdef SCO_FLAVOR
#	include <sys/timeb.h>	/* alex: for struct timeb, used in time.h */
#endif /* SCO_FLAVOR */
#include <time.h>
#ifndef OS2_NT
#    include <grp.h>
#    include <pwd.h>
#else
#    include <io.h>
#endif
#include "tty.h"
#include "mad.h"
#include "util.h"		/* Needed for the externs */
#include "win.h"
#include "color.h"
#include "dlg.h"
#include "widget.h"
#include "dialog.h"		/* For do_refresh() */
#include "setup.h"		/* For profile_bname */
#include "profile.h"		/* Load/save directories hotlist */

#include "../vfs/vfs.h"
/* Needed for the extern declarations of integer parameters */
#include "wtools.h"
#include "dir.h"
#include "panel.h"		/* Needed for the externs */
#include "file.h"
#include "main.h"
#include "global.h"
#include "hotlist.h"
#include "key.h"
#include "command.h"

#ifdef HAVE_TK
#    include "tkwidget.h"
#endif

#define UX		5
#define UY		2

#define BX		UX
#define BY		LINES-6

#define BUTTONS		(sizeof(hotlist_but)/sizeof(struct _hotlist_but))
#define LABELS          3
#define B_ADD_CURRENT	B_USER
#define B_REMOVE        (B_USER + 1)
#define B_NEW_GROUP	(B_USER + 2)
#define B_NEW_ENTRY	(B_USER + 3)
#define B_UP_GROUP	(B_USER + 4)
#define B_INSERT	(B_USER + 5)
#define B_APPEND	(B_USER + 6)
#define B_MOVE		(B_USER + 7)

static WListbox *l_hotlist;
static WListbox *l_movelist;

static Dlg_head *hotlist_dlg;
static Dlg_head *movelist_dlg;

static WLabel *pname, *pname_group, *movelist_group;

enum HotListType {
    HL_TYPE_GROUP,
    HL_TYPE_ENTRY,
    HL_TYPE_COMMENT
};

static struct {
    /*
     * these parameters are intended to be user configurable
     */
    int		expanded;	/* expanded view of all groups at startup */

    /*
     * these reflect run time state
     */

    int		loaded;		/* hotlist is loaded */
    int		readonly;	/* hotlist readonly */
    int		file_error;	/* parse error while reading file */
    int		running;	/* we are running dlg (and have to
    				   update listbox */
    int		moving;		/* we are in moving hotlist currently */
    int		modified;	/* hotlist was modified */
    int		type;		/* LIST_HOTLIST || LIST_VFSLIST */
}   hotlist_state;

struct _hotlist_but {
    int ret_cmd, flags, y, x;
    char *text;
    char *tkname;
    int   type;
} hotlist_but[] = {
    { B_MOVE, NORMAL_BUTTON,         1,   42, N_("&Move"),       "move", LIST_HOTLIST},
    { B_REMOVE, NORMAL_BUTTON,       1,   30, N_("&Remove"),     "r",    LIST_HOTLIST},
    { B_APPEND, NORMAL_BUTTON,       1,   15, N_("&Append"),     "e",    LIST_MOVELIST},
    { B_INSERT, NORMAL_BUTTON,       1,    0, N_("&Insert"),     "g",    LIST_MOVELIST},
    { B_NEW_ENTRY, NORMAL_BUTTON,    1,   15, N_("New &Entry"),  "e",    LIST_HOTLIST},
    { B_NEW_GROUP, NORMAL_BUTTON,    1,    0, N_("New &Group"),  "g",    LIST_HOTLIST},
    { B_CANCEL, NORMAL_BUTTON,       0,   53, N_("&Cancel"),     "cc",   LIST_HOTLIST|LIST_VFSLIST|LIST_MOVELIST},
    { B_UP_GROUP, NORMAL_BUTTON,     0,   42, N_("&Up"),         "up",   LIST_HOTLIST|LIST_MOVELIST},
    { B_ADD_CURRENT, NORMAL_BUTTON,  0,   20, N_("&Add current"),"ad",   LIST_HOTLIST},
    { B_ENTER, DEFPUSH_BUTTON,       0,    0, N_("Change &To"),  "ct",   LIST_HOTLIST|LIST_VFSLIST|LIST_MOVELIST},
};

/* Directory hotlist */
static struct hotlist{
    enum  HotListType type;
    char *directory;
    char *label;
    struct hotlist *head;
    struct hotlist *up;
    struct hotlist *next;
} *hotlist = NULL;

struct hotlist *current_group;

static void remove_from_hotlist (struct hotlist *entry);
void add_new_group_cmd (void);

static struct hotlist *new_hotlist (void)
{
    struct hotlist *hl;

    hl = xmalloc (sizeof (struct hotlist), "new-hotlist");
    hl->type     = 0;
    hl->directory =
	hl->label = 0;
    hl->head =
	hl->up =
	    hl->next = 0;

    return hl;
}

#ifndef HAVE_X
static void hotlist_refresh (Dlg_head *dlg)
{
    dialog_repaint (dlg, COLOR_NORMAL, COLOR_HOT_NORMAL);
    attrset (COLOR_NORMAL);
    draw_box (dlg, 2, 5,
		dlg->lines - (hotlist_state.moving ? 6 : 10),
		dlg->cols - (UX*2));
    if (!hotlist_state.moving)
	draw_box (dlg, dlg->lines-8, 5, 3, dlg->cols - (UX*2));
}
#endif

/* If current->data is 0, then we are dealing with a VFS pathname */
static INLINE void update_path_name ()
{
    char *text, *p;
    WListbox  *list = hotlist_state.moving ? l_movelist : l_hotlist;
    Dlg_head  *dlg = hotlist_state.moving ? movelist_dlg : hotlist_dlg;

    if (list->current){
	if (list->current->data != 0) {
	    struct hotlist *hlp = (struct hotlist *)list->current->data;

	    if (hlp->type == HL_TYPE_ENTRY)
		text = hlp->directory;
	    else
		text = _("Subgroup - press ENTER to see list");

#ifndef HAVE_X
	    p = copy_strings (" ", current_group->label, " ", (char *)0);
	    if (!hotlist_state.moving)
		label_set_text (pname_group, name_trunc (p, dlg->cols - (UX*2+4)));
	    else
		label_set_text (movelist_group, name_trunc (p, dlg->cols - (UX*2+4)));
	    free (p);
#endif
	} else {
	    text = list->current->text;
	}
    } else {
	text = "";
    }
    if (!hotlist_state.moving)
	label_set_text (pname, name_trunc (text, dlg->cols - (UX*2+4)));
    dlg_redraw (dlg);
}

#define CHECK_BUFFER  \
do { \
    int               i; \
\
    if ((i = strlen (current->label) + 3) > buflen) { \
      free (buf); \
      buf = xmalloc (buflen = 1024 * (i/1024 + 1), "fill_listbox"); \
    } \
    buf[0] = '\0'; \
} while (0)

static void fill_listbox (void)
{
    struct hotlist *current = current_group->head;
    static char *buf;
    static int   buflen;

    if (!buf)
	buf = xmalloc (buflen = 1024, "fill_listbox");
    buf[0] = '\0';

    while (current){
	switch (current->type) {
	case HL_TYPE_GROUP:
	    {
		CHECK_BUFFER;
		strcat (strcat (buf, "->"), current->label);
		if (hotlist_state.moving)
		    listbox_add_item (l_movelist, 0, 0, buf, current);
		else
		    listbox_add_item (l_hotlist, 0, 0, buf, current);
	    }
	    break;
	case HL_TYPE_ENTRY:
		if (hotlist_state.moving)
		    listbox_add_item (l_movelist, 0, 0, current->label, current);
		else
		    listbox_add_item (l_hotlist, 0, 0, current->label, current);
	    break;
	}
	current = current->next;
    }
}

#undef CHECK_BUFFER

static void
unlink_entry (struct hotlist *entry)
{
    struct hotlist *current = current_group->head;

    if (current == entry)
	current_group->head = entry->next;
    else
	while (current && current->next != entry)
	    current = current->next;
	if (current)
	    current->next = entry->next;
    entry->next =
	entry->up = 0;
}

static void add_new_entry_cmd (void);
static void init_movelist (int, struct hotlist *);

static int hotlist_button_callback (int action, void *data)
{
    switch (action) {
    case B_MOVE:
	{
	    struct hotlist  *saved = current_group;
	    struct hotlist  *item;
	    struct hotlist  *moveto_item = 0;
	    struct hotlist  *moveto_group = 0;
	    int             ret;

	    if (!l_hotlist->current)
		return 0;		/* empty group - nothing to do */
	    item = l_hotlist->current->data;
	    hotlist_state.moving = 1;
	    init_movelist (LIST_MOVELIST, item);
	    run_dlg (movelist_dlg);
	    ret = movelist_dlg->ret_value;
	    hotlist_state.moving = 0;
	    if (l_movelist->current)
		moveto_item = l_movelist->current->data;
	    moveto_group = current_group;
	    destroy_dlg (movelist_dlg);
	    current_group = saved;
	    if (ret == B_CANCEL)
		return 0;
	    if (moveto_item == item)
		return 0;		/* If we insert/append a before/after a
					   it hardly changes anything ;) */
	    unlink_entry (item);
	    listbox_remove_current (l_hotlist, 1);
	    item->up = moveto_group;
	    if (!moveto_group->head)
		moveto_group->head = item;
	    else if (!moveto_item) {	/* we have group with just comments */
		struct hotlist *p = moveto_group->head;

		/* skip comments */
		while (p->next)
		    p = p->next;
		p->next = item;
	    } else if (ret == B_ENTER || ret == B_APPEND)
		if (!moveto_item->next)
		    moveto_item->next = item;
		else {
		    item->next = moveto_item->next;
		    moveto_item->next = item;
		}
	    else if (moveto_group->head == moveto_item) {
		    moveto_group->head = item;
		    item->next = moveto_item;
		} else {
		    struct hotlist *p = moveto_group->head;

		    while (p->next != moveto_item)
			p = p->next;
		    item->next = p->next;
		    p->next = item;
		}
	    listbox_remove_list (l_hotlist);
	    fill_listbox ();
#ifdef HAVE_X
	    x_listbox_select_nth (l_hotlist, 0);
#endif
	    repaint_screen ();
	    hotlist_state.modified = 1;
	    return 0;
	    break;
	}
    case B_REMOVE:
	if (l_hotlist->current)
	    remove_from_hotlist (l_hotlist->current->data);
	return 0;
	break;

    case B_NEW_GROUP:
	add_new_group_cmd ();
	return 0;
	break;

    case B_ADD_CURRENT:
	add2hotlist_cmd ();
	return 0;
	break;

    case B_NEW_ENTRY:
	add_new_entry_cmd ();
	return 0;
	break;

    case B_ENTER:
	{
	WListbox *list = hotlist_state.moving ? l_movelist : l_hotlist;
	if (list->current){
	    if (list->current->data) {
		struct hotlist *hlp = (struct hotlist*) list->current->data;
		if (hlp->type == HL_TYPE_ENTRY)
		    return 1;
		else {
		    listbox_remove_list (list);
		    current_group = hlp;
		    fill_listbox ();
		    return 0;
		}
	    } else
		return 1;
	}
	}
	/* Fall through if list empty - just go up */

    case B_UP_GROUP:
	{
	WListbox *list = hotlist_state.moving ? l_movelist : l_hotlist;
	listbox_remove_list (list);
	current_group = current_group->up;
	fill_listbox ();
#ifdef HAVE_X
	x_listbox_select_nth (list, 0);
#endif
	return 0;
	break;
	}

    default:
	return 1;
	break;

    }
}

static int hotlist_callback (Dlg_head * h, int Par, int Msg)
{
    switch (Msg) {
#ifndef HAVE_X
    case DLG_DRAW:
	hotlist_refresh (h);
	break;
#endif

    case DLG_UNHANDLED_KEY:
	switch (Par) {
	case '\n':
	    if (ctrl_pressed())
		goto l1;
	case KEY_ENTER:
	case KEY_RIGHT:
	    if (hotlist_button_callback (B_ENTER, 0)) {
		h->ret_value = B_ENTER;
		dlg_stop (h);
	    };
	    return 1;
	    break;
	case KEY_LEFT:
	    if (hotlist_state.type != LIST_VFSLIST )
    		return !hotlist_button_callback (B_UP_GROUP, 0);
	    else
		return 0;
	    break;
l1:
	case ALT('\n'):
	case ALT('\r'):
	    if (!hotlist_state.moving)
	    {
    		if (l_hotlist->current){
		    if (l_hotlist->current->data) {
			struct hotlist *hlp = (struct hotlist*) l_hotlist->current->data;
			if (hlp->type == HL_TYPE_ENTRY) {
			    char *tmp = copy_strings( "cd ", hlp->directory, NULL);
			    stuff (input_w (cmdline), tmp, 0);
			    free (tmp);
			    dlg_stop (h);
			    h->ret_value = B_CANCEL;
			    return 1;
		        }
		    }
		}
	    }
	    return 1; /* ignore key */
	default:
	    return 0;
	}
	break;

    case DLG_POST_KEY:
	if (hotlist_state.moving)
	    dlg_select_widget (movelist_dlg, l_movelist);
	else
	    dlg_select_widget (hotlist_dlg, l_hotlist);
	/* always stay on hotlist */
	/* fall through */

    case DLG_INIT:
	attrset (MENU_ENTRY_COLOR);
	update_path_name ();
	break;
    }
    return 0;
}

static int l_call (void *l)
{
    WListbox *list = (WListbox *) l;
    Dlg_head *dlg = hotlist_state.moving ? movelist_dlg : hotlist_dlg;

    if (list->current){
	if (list->current->data) {
	    struct hotlist *hlp = (struct hotlist*) list->current->data;
	    if (hlp->type == HL_TYPE_ENTRY) {
		dlg->ret_value = B_ENTER;
		dlg_stop (dlg);
		return listbox_finish;
	    } else {
		hotlist_button_callback (B_ENTER, (void *)0);
		hotlist_callback (dlg, '\n', DLG_POST_KEY);
		return listbox_nothing;
	    }
	} else {
	    dlg->ret_value = B_ENTER;
	    dlg_stop (dlg);
	    return listbox_finish;
	}
    }

    hotlist_button_callback (B_UP_GROUP, (void *)0);
    hotlist_callback (dlg, 'u', DLG_POST_KEY);
    return listbox_nothing;
}

static void add_name_to_list (char *path)
{
    listbox_add_item (l_hotlist, 0, 0, path, 0);
}

/*
 * Expands all button names (once) and recalculates button positions.
 * returns number of columns in the dialog box, which is 10 chars longer
 * then buttonbar.
 *
 * If common width of the window (i.e. in xterm) is less than returned
 * width - sorry :)  (anyway this did not handled in previous version too)
 */
static int
init_i18n_stuff(int list_type, int cols)
{
	register int i;
	static char* cancel_but = "&Cancel";

#ifdef ENABLE_NLS
	static int hotlist_i18n_flag = 0;

⌨️ 快捷键说明

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