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

📄 widget.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 4 页
字号:
	if (label->auto_adjust_cols) {
	    newcols = strlen (text);
	    if (newcols > label->widget.cols)
	    label->widget.cols = newcols;
	}
    } else
	label->text = 0;

    if (label->widget.parent)
#ifdef HAVE_X
	x_label_set_text (label, text);
#else
	label_callback (label->widget.parent, label, WIDGET_DRAW, 0);
#endif
    if (newcols < label->widget.cols)
        label->widget.cols = newcols;
}

static void
label_destroy (WLabel *l)
{
    x_destroy_cmd (l);
    if (l->text)
	free (l->text);
}

WLabel *
label_new (int y, int x, char *text, char *tkname)
{
    WLabel *l = xmalloc (sizeof (WLabel), "label_new");

    init_widget (&l->widget, y, x, 1, 1,
		 (callback_fn) label_callback,
		 (destroy_fn) label_destroy, NULL, tkname);
    l->text = text ? strdup (text) : 0;
    l->auto_adjust_cols = 1;
    l->transparent = 0;
    widget_want_cursor (l->widget, 0);
    return l;
}


/* Gauge widget (progress indicator) */
/* Currently width is hardcoded here for text mode */
#define gauge_len 47

static int
gauge_callback (Dlg_head *h, WGauge *g, int Msg, int Par)
{

    if (Msg == WIDGET_INIT)
	return x_create_gauge (h, h->wdata, g);

    /* We don't want to get the focus */
    if (Msg == WIDGET_FOCUS)
	return 0;

#ifndef HAVE_X
    if (Msg == WIDGET_DRAW){
	widget_move (&g->widget, 0, 0);
	attrset (NORMALC);
	if (!g->shown)
	    printw ("%*s", gauge_len, "");
	else {
	    long percentage, columns;
	    long total = g->max, done = g->current;

	    if (total <= 0 || done < 0) {
	        done = 0;
	        total = 100;
	    }
	    if (done > total)
	        done = total;
	    while (total > 65535) {
	        total /= 256;
	        done /= 256;
	    }
	    percentage = (200 * done / total + 1) / 2;
	    columns = (2 * (gauge_len - 7) * done / total + 1) / 2;
	    addch ('[');
	    attrset (GAUGE_COLOR);
	    printw ("%*s", columns, "");
	    attrset (NORMALC);
	    printw ("%*s] %3d%%", gauge_len - 7 - columns, "", percentage);
	}
	return 1;
    }
#endif
    return default_proc (h, Msg, Par);
}

void
gauge_set_value (WGauge *g, int max, int current)
{
    if (g->current == current && g->max == max)
    	return; /* Do not flicker */
    if (max == 0)
        max = 1; /* I do not like division by zero :) */
#ifdef HAVE_X
/* NOTE: x_gauge_set_value has to be called before we change actual
 *       max and current values in g, since it assumes g->max and
 *       g->current as the previous values and max and current
 *       as the new ones :) */
    x_gauge_set_value (g, max, current);
#endif
    g->current = current;
    g->max = max;
#ifndef HAVE_X
    gauge_callback (g->widget.parent, g, WIDGET_DRAW, 0);
#endif
}

void
gauge_show (WGauge *g, int shown)
{
    if (g->shown == shown)
        return;
    g->shown = shown;
#ifdef HAVE_X
    x_gauge_show (g);
#else
    gauge_callback (g->widget.parent, g, WIDGET_DRAW, 0);
#endif
}

static void
gauge_destroy (WGauge *g)
{
    /* nothing */
}

WGauge *
gauge_new (int y, int x, int shown, int max, int current, char *tkname)
{
    WGauge *g = xmalloc (sizeof (WGauge), "gauge_new");

    init_widget (&g->widget, y, x, 1, gauge_len,
		 (callback_fn) gauge_callback,
		 (destroy_fn) gauge_destroy, NULL, tkname);
    g->shown = shown;
    if (max == 0)
        max = 1; /* I do not like division by zero :) */
    g->max = max;
    g->current = current;
    g->pixels = 0;
    widget_want_cursor (g->widget, 0);
    return g;
}


/* Input widget */

/* {{{ history button */

#define LARGE_HISTORY_BUTTON 1

#ifdef LARGE_HISTORY_BUTTON
#  define HISTORY_BUTTON_WIDTH 3
#else
#  define HISTORY_BUTTON_WIDTH 1
#endif

#define should_show_history_button(in) \
	    (in->history && in->field_len > HISTORY_BUTTON_WIDTH * 2 + 1 && in->widget.parent)

static void draw_history_button (WInput * in)
{
    char c;
    c = in->history->next ? (in->history->prev ? '|' : 'v') : '^';
    widget_move (&in->widget, 0, in->field_len - HISTORY_BUTTON_WIDTH);
#ifdef LARGE_HISTORY_BUTTON
    {
	Dlg_head *h;
	h = in->widget.parent;
#if 0
	attrset (NORMALC);	/* button has the same colour as other buttons */
	addstr ("[ ]");
	attrset (HOT_NORMALC);
#else
	attrset (NORMAL_COLOR);
	addstr ("[ ]");
	/* Too distracting: attrset (MARKED_COLOR); */
#endif
	widget_move (&in->widget, 0, in->field_len - HISTORY_BUTTON_WIDTH + 1);
	addch (c);
    }
#else
    attrset (MARKED_COLOR);
    addch (c);
#endif
}

/* }}} history button */


/* Input widgets now have a global kill ring */
/* Pointer to killed data */
static char *kill_buffer = 0;

void
update_input (WInput *in, int clear_first)
{
#ifndef HAVE_XVIEW
    int has_history = 0;
    int    i, j;
    char   c;
    int    buf_len = strlen (in->buffer);

    if (should_show_history_button (in))
	has_history = HISTORY_BUTTON_WIDTH;

    if (in->disable_update)
	return;

    /* Make the point visible */
    if ((in->point < in->first_shown) ||
	(in->point >= in->first_shown+in->field_len - has_history)){
	in->first_shown = in->point - (in->field_len / 3);
	if (in->first_shown < 0)
	    in->first_shown = 0;
    }

    /* Adjust the mark */
    if (in->mark > buf_len)
	in->mark = buf_len;

#ifdef HAVE_X
    if (clear_first && in->first)
	    in->first = -1;
    x_update_input (in);
#else

    if (has_history)
	draw_history_button (in);

    attrset (in->color);

    widget_move (&in->widget, 0, 0);
    for (i = 0; i < in->field_len - has_history; i++)
	addch (' ');
    widget_move (&in->widget, 0, 0);

    for (i = 0, j = in->first_shown; i < in->field_len - has_history && in->buffer [j]; i++){
	c = in->buffer [j++];
	c = is_printable (c) ? c : '.';
	if (in->is_password)
	    c = '*';
	addch (c);
    }
    widget_move (&in->widget, 0, in->point - in->first_shown);

    if (clear_first)
	    in->first = 0;
#endif

#endif
}

void
winput_set_origin (WInput *in, int x, int field_len)
{
    in->widget.x    = x;
    in->field_len = in->widget.cols = field_len;
    update_input (in, 0);
}

/* {{{ history saving and loading */

/*
   This loads and saves the history of an input line to and from the
   widget. It is called with the widgets tk name on creation of the
   widget, and returns the Hist list. It stores histories in the file
   ~/.mc/history in using the profile code.

   If def_text is passed as INPUT_LAST_TEXT (to the input_new()
   function) then input_new assigns the default text to be the last text
   entered, or "" if not found.
 */

int num_history_items_recorded = 60;

Hist *history_get (char *input_name)
{
    int i;
    Hist *old = 0, *new = 0;
    char *profile;

    if (!num_history_items_recorded)	/* this is how to disable */
	return 0;
    if (!input_name)
	return 0;
    if (!*input_name)
	return 0;
    profile = concat_dir_and_file (home_dir, HISTORY_FILE_NAME);
    for (i = 0;; i++) {
	char key_name[32];
	char this_entry[1024];
	sprintf (key_name, "%d", i);
	GetPrivateProfileString (input_name, key_name, "", this_entry, sizeof (this_entry), profile);
	if (!*this_entry)
	    break;
	new = xmalloc (sizeof (Hist), "history_get");
	memset (new, 0, sizeof (Hist));
	new->text = strdup (this_entry);
	new->prev = old;	/* set up list pointers */
	if (old)
	    old->next = new;
	old = new;
    }
    free (profile);
    return new;			/* return pointer to last entry in list */
}

#ifdef PORT_WIDGET_WANTS_HISTORY
void history_put (char *input_name, Hist *h)
{
    int i;
    char *profile;

    if (!input_name)
	return;

    if (!*input_name)
	return;

    if (!h)
	return;

    if (!num_history_items_recorded)	/* this is how to disable */
	return;

    profile = concat_dir_and_file (home_dir, HISTORY_FILE_NAME);
    while (h->next)		/* go to end of list */
	h = h->next;

    /* go back 60 places */
    for (i = 0; i < num_history_items_recorded - 1 && h->prev; i++)
	h = h->prev;
    i = 0;

    if (input_name)
	profile_clean_section (input_name, profile);

    /* dump histories into profile */
    while (h){
	if (h->text){

	    /* probably aren't any null entries, but lets be sure */
	    if (*(h->text)){
		char key_name[32];
		sprintf (key_name, "%d", i++);
		WritePrivateProfileString (input_name, key_name, h->text, profile);
	    }
	}
	h = h->next;
    }
    free (profile);
}
#else
void history_put (char *input_name, Hist *h)
{
}
#endif

/* }}} history saving and loading */


/* {{{ history display */

static const char history_title[] = " History ";

int history_callback (Dlg_head * h, int Par, int Msg)
{
#ifndef HAVE_X
    switch (Msg) {
    case DLG_DRAW:
	attrset (COLOR_NORMAL);
	dlg_erase (h);
	draw_box (h, 0, 0, h->lines, h->cols);
	attrset (COLOR_HOT_NORMAL);
	dlg_move (h, 0, (h->cols - strlen (history_title)) / 2);
	printw ((char *) history_title);
	break;
    }
#endif
    return 0;
}

static inline int listbox_fwd (WListbox *l);

char *show_hist (Hist *history, int widget_x, int widget_y)
{
    Hist *hi, *z;
    int maxlen = strlen(history_title), i, count = 0;
    int x, y, w, h;
    char *q, *r = 0;
    Dlg_head *query_dlg;
    WListbox *query_list;

    z = history;
    if (!z)
		return 0;

    while (z->prev)		/* goto first */
		z = z->prev;
    hi = z;
    while (hi) {
		if ((i = strlen (hi->text)) > maxlen)
		    maxlen = i;
		count++;
		hi = hi->next;
    }

       y = widget_y;
	h = count + 2;
	if (h <= y || y > LINES - 6)
	{
		h = min(h, y - 1);
		y -= h;
	}
	else
	{
		y++;
		h = min(h, LINES - y);
	}

	x = widget_x - 2;
	if ((w = maxlen + 4) + x > COLS)
	{
		w = min(w,COLS);
		x = COLS - w;
	}

    query_dlg = create_dlg (y, x, h, w, dialog_colors, history_callback,
			    "[History-query]", "history", DLG_NONE);
    query_list = listbox_new (1, 1, w - 2, h - 2, listbox_finish, 0, NULL);
    add_widget (query_dlg, query_list);
    hi = z;
    if (y < widget_y) {
		while (hi) {		/* traverse */
		    listbox_add_item (query_list, 0, 0, hi->text, NULL);
	    	hi = hi->next;
		}
		while (listbox_fwd (query_list));
    } else {
		while (hi->next)
		    hi = hi->next;
		while (hi) {		/* traverse backwards */
		    listbox_add_item (query_list, 0, 0, hi->text, NULL);
	    	hi = hi->prev;
		}
    }
    run_dlg (query_dlg);
    q = NULL;
    if (query_dlg->ret_value != B_CANCEL) {
		listbox_get_current (query_list, &q, NULL);
		if (q)
		    r = strdup (q);
    }
    destroy_dlg (query_dlg);
    return r;
}

static void do_show_hist (WInput * in)
{
    char *r;
    r = show_hist (in->history, in->widget.x, in->widget.y);
    if (r) {
	assign_text (in, r);
	free (r);
    }
}

/* }}} history display */

static void
input_destroy (WInput *in)
{
    if (!in){
	fprintf (stderr, "Internal error: null Input *\n");
	exit (1);
    }

    new_input (in);
    if (in->history){
	Hist *current, *old;

	if (!in->is_password && PORT_WIDGET_WANTS_HISTORY)	/* don't save passwords ;-) */
	    history_put (in->history_name, in->history);

	current = in->history;
	while (current->next)
	    current = current->next;
	while (current){
	    old = current;
	    current = current->prev;
	    free (old->text);
	    free (old);
	}
    }
    x_destroy_cmd (in);
    free (in->buffer);
    free_completions (in);
    if (in->history_name)
	free (in->history_name);
}

static char disable_update = 0;

void
input_disable_update (WInput *in)
{
    in->disable_update++;
}

void
input_enable_update (WInput *in)
{
    in->disable_update--;
    update_input (in, 0);
}

int
push_history (WInput *in, char *text)
{
    Hist *new;
    char *p;

    for (p = text; *p == ' ' || *p == '\t'; p++);
    if (!*p)
        return 0;
    if (in->history){
	while (in->history->next)
	    in->history = in->history->next;
	if (!strcmp (in->history->text, text))
	    return 1;
    	new = xmalloc (sizeof (Hist), "push_history");
	in->history->next = new;
    } else
    	new = xmalloc (sizeof (Hist), "push_history");
    in->need_push = 0;
    new->next = 0;
    new->prev = in->history;
    new->text = strdup (text);
    in->history = new;
    return 2;
}

/* Cleans the input line and adds the current text to the history */
void
new_input (WInput *in)
{
    if (in->buffer)
	push_history (in, in->buffer);
    in->need_push = 1;
    in->buffer [0] = 0;
    in->point = 0;
    in->mark = 0;
    free_completions (in);
    update_input (in, 0);
}

static int
insert_char (WInput *in, int c_code)
{
    int i;

    if (c_code == -1)
	return 0;

    in->need_push = 1;
    if (strlen (in->buffer)+1 == in->current_max_len){
	/* Expand the buffer */
	char *narea = xmalloc(in->current_max_len + in->field_len, "string expansion");
	if (narea){
	    char *p = in->buffer;

	    strcpy (narea, in->buffer);
	    in->buffer = narea;
	    in->current_max_len += in->field_len;
	    free (p);
	}
    }
    if (strlen (in->buffer)+1 < in->current_max_len){
	int l = strlen (&in->buffer [in->point]);
	for (i = l+1; i > 0; i--)
	    in->buffer [in->point+i] = in->buffer [in->point+i-1];
	in->buffer [in->point] = c_code;
	in->point++;
    }
    return 1;
}

static void
beginning_of_line (WInput *in)
{
    in->point = 0;
}

static void
end_of_line (WInput *in)
{
    in->point = strlen (in->buffer);
}

static void
backward_char (WInput *in)
{
    if (in->point)
	in->point--;
}

static void
forward_char (WInput *in)
{
    if (in->buffer [in->point])
	in->point++;
}

static void
forward_word (WInput *in)
{
    char *p = in->buffer+in->point;

    while ((*p && isspace (*p)) || ispunct (*p))

⌨️ 快捷键说明

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