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

📄 widget.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Widgets for the Midnight Commander

   Copyright (C) 1994, 1995, 1996 the Free Software Foundation

   Authors: 1994, 1995 Radek Doulik
            1994, 1995 Miguel de Icaza
            1995 Jakub Jelinek
	    1996 Andrej Borsenkow
	    1997 Norbert Warmuth

   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.

 */
/* "$Id: widget.c 15218 2005-05-11 16:50:39Z weiden $" */

#include <config.h>
#include <string.h>
#include <stdio.h>
#include <malloc.h>
#include "tty.h"
#include <ctype.h>
#include "mad.h"
#include "global.h"
#include "util.h"
#include "color.h"
#include "mouse.h"
#include "dlg.h"
#include "widget.h"
#include "win.h"
#include "complete.h"
#include "key.h"		/* XCTRL and ALT macros  */
#include "x.h"
#include "profile.h"	/* for history loading and saving */

#ifndef HAVE_X
#   define x_create_button(a,b,c)  1
#   define x_create_radio(a,b,c)   1
#   define x_create_check(a,b,c)   1
#   define x_create_label(a,b,c)   1
#   define x_create_input(a,b,c)   1
#   define x_create_listbox(a,b,c) 1
#   define x_create_buttonbar(a,b,c) 1
#   define x_create_gauge(a,b,c) 1
#   define x_listbox_select_nth(a,b)
#   define x_list_insert(a,b,c)
#   define x_redefine_label(a,b)
#endif

#ifndef PORT_HAS_DESTROY_CMD
#   define x_destroy_cmd(w)
#endif

#ifndef PORT_HAS_RADIO_FOCUS_ITEM
#   define x_radio_focus_item(r)
#endif

#ifndef PORT_HAS_RADIO_TOGGLE
#   define x_radio_toggle
#endif

static int button_event (Gpm_Event *event, WButton *b);

int quote = 0;

static int
button_callback (Dlg_head *h, WButton *b, int Msg, int Par)
{
    char *txt, buf[256];
    int stop = 0;
    int off = 0;

    switch (Msg){
    case WIDGET_INIT:
	return x_create_button (h, h->wdata, b);
#ifndef	HAVE_XVIEW
    case WIDGET_HOTKEY:
        if (b->hotkey == Par ||  toupper(b->hotkey) == Par){
	    button_callback (h, b, WIDGET_KEY, ' '); /* to make action */
	    return 1;
	} else
	    return 0;

    case WIDGET_KEY:
	if (Par != ' ' && Par != '\n')
	    break;

	if (b->callback)
	    stop = (*b->callback)(b->action, b->callback_data);
	if (!b->callback || stop){
	    h->ret_value = b->action;
	    dlg_stop (h);
	}
	return 1;

#ifdef HAVE_TK
    case WIDGET_FOCUS:
    case WIDGET_CURSOR:
    {
	char *s = b->action == B_ENTER ? ".button" : "";

	tk_evalf ("focus %s%s", (char *)(b->widget.wdata)+1, s);
	/* Do not call default_proc: we did the tk focus command */
	return 1;
    }
#else

    case WIDGET_CURSOR:
	switch (b->flags) {
	    case DEFPUSH_BUTTON:
		off = 3;
		break;
	    case NORMAL_BUTTON:
		off = 2;
		break;
	    case NARROW_BUTTON:
		off = 1;
		break;
	    case HIDDEN_BUTTON:
	    default:
		off = 0;
		break;
        }
	widget_move (&b->widget, 0, b->hotpos + off);
	return 1;

    case WIDGET_UNFOCUS:
    case WIDGET_FOCUS:
    case WIDGET_DRAW:
	if (Msg==WIDGET_UNFOCUS)
	    b->selected = 0;
	else if (Msg==WIDGET_FOCUS)
	    b->selected = 1;

	switch (b->flags){
	    case DEFPUSH_BUTTON:
		sprintf (buf, "[< %s >]", b->text);
		off = 3;
		break;
	    case NORMAL_BUTTON:
		sprintf (buf, "[ %s ]", b->text);
		off = 2;
		break;
	    case NARROW_BUTTON:
		sprintf (buf, "[%s]", b->text);
		off = 1;
		break;
	    case HIDDEN_BUTTON:
	    default:
		buf[0] = '\0';
		off = 0;
		break;
	}
	txt = buf;

	attrset ((b->selected) ? FOCUSC : NORMALC);
	widget_move (&b->widget, 0, 0);

	addstr (txt);

	if (b->hotpos >= 0){
	    attrset ((b->selected) ? HOT_FOCUSC : HOT_NORMALC);
	    widget_move (&b->widget, 0, b->hotpos+off);
	    addch ((unsigned char)b->text [b->hotpos]);
        }
	if (Msg == WIDGET_FOCUS)
	    break;
	else
	    return 1;
	break;
#endif
#endif /* !HAVE_XVIEW */
    }
    return default_proc (h, Msg, Par);
}

static int
button_event (Gpm_Event *event, WButton *b)
{
#ifndef HAVE_X
    if (event->type & (GPM_DOWN|GPM_UP)){
    	Dlg_head *h=b->widget.parent;
	dlg_select_widget (h, b);
	if (event->type & GPM_UP){
	    button_callback (h, b, WIDGET_KEY, ' ');
	    (*h->callback) (h, ' ', DLG_POST_KEY);
	    return MOU_NORMAL;
	}
    }
#endif
    return MOU_NORMAL;
}

static void
button_destroy (WButton *b)
{
    x_destroy_cmd (b);
    free (b->text);
}

static int
button_len (const char *text, unsigned int flags)
{
#ifndef	HAVE_X
    int ret = strlen (text);
    switch (flags){
	case DEFPUSH_BUTTON:
	    ret += 6;
	    break;
	case NORMAL_BUTTON:
	    ret += 4;
	    break;
	case NARROW_BUTTON:
	    ret += 2;
	    break;
	case HIDDEN_BUTTON:
	default:
	    return 0;
    }
    return ret;
#else
    return strlen (text);
#endif
}

/*
 * Assuming that button text is malloc'ed, we may safely change it
 * (as opposed to statically allocated); from other hand, excluding &
 * and shifting data past it to the left results to one unused byte.
 * This does not harm though :)
 */
void
button_scan_hotkey(WButton* b)
{
    char* cp = strchr (b->text, '&');

    if (cp != NULL && cp[1] != '\0'){
	strcpy (cp, cp+1);
	b->hotkey = tolower (*cp);
	b->hotpos = cp - b->text;
    }
}

WButton *
button_new (int y, int x, int action, int flags, char *text,
	    int (*callback)(int, void *), void *callback_data, char *tkname)
{
    WButton *b = xmalloc (sizeof (WButton), "new_button");

    init_widget (&b->widget, y, x, 1, button_len (text, flags),
		 (callback_fn) button_callback,
		 (destroy_fn) button_destroy, (mouse_h)button_event, tkname);

    b->action = action;
    b->flags  = flags;
    b->selected = 0;
    b->text   = strdup (text);
    b->callback = callback;
    b->callback_data = callback_data;
    widget_want_hotkey (b->widget, 1);
    b->hotkey = 0;
    b->hotpos = -1;

    button_scan_hotkey(b);
    return b;
}

void
button_set_text (WButton *b, char *text)
{
    free (b->text);
    b->text = strdup (text);
    b->widget.cols = button_len (text, b->flags);
    button_scan_hotkey(b);
#ifdef HAVE_X
    x_button_set (b, b->text);
#else
    dlg_redraw (b->widget.parent);
#endif
}


/* Radio button widget */
static int radio_event (Gpm_Event *event, WRadio *r);

static int
radio_callback (Dlg_head *h, WRadio *r, int Msg, int Par)
{
    int i;

    switch (Msg) {
    case WIDGET_INIT:
	return x_create_radio (h, h->wdata, r);

#ifndef HAVE_XVIEW
    case WIDGET_HOTKEY:
	{
	    int i, lp = tolower(Par);
	    char *cp;

	    for (i = 0; i < r->count; i++){
		cp = strchr (r->texts [i], '&');
		if (cp != NULL && cp[1] != '\0'){
		    int c = tolower (cp [1]);

		    if (c != lp)
			continue;
		    r->pos = i;
		    radio_callback (h, r, WIDGET_KEY, ' '); /* Take action */
		    return 1;
		}
	    }
	}
	return 0;

    case WIDGET_KEY:
	switch (Par){
	case ' ':
	    r->sel = r->pos;
    	    (*h->callback) (h, h->current->dlg_id, DLG_ACTION);
	    radio_callback (h, r, WIDGET_FOCUS, ' ');
	    x_radio_toggle (r);
	    return 1;

	case KEY_UP:
	case KEY_LEFT:
	    if (r->pos > 0){
		r->pos--;
		x_radio_focus_item (r);
		return 1;
	    }
	    return 0;

	case KEY_DOWN:
	case KEY_RIGHT:
	    if (r->count - 1 > r->pos) {
		r->pos++;
		x_radio_focus_item (r);
		return 1;
	    }
	}
	return 0;

#ifdef HAVE_X
    case WIDGET_FOCUS:
    case WIDGET_CURSOR:
	    x_radio_focus_item (r);
	    return 1;
#endif
#endif

#ifndef HAVE_X
    case WIDGET_CURSOR:
	(*h->callback) (h, h->current->dlg_id, DLG_ACTION);
	radio_callback (h, r, WIDGET_FOCUS, ' ');
	widget_move (&r->widget, r->pos, 1);
	break;

    case WIDGET_UNFOCUS:
    case WIDGET_FOCUS:
    case WIDGET_DRAW:
	for (i = 0; i < r->count; i++){
		register char* cp;
	    attrset ((i==r->pos && Msg==WIDGET_FOCUS) ? FOCUSC :NORMALC);
	    widget_move (&r->widget, i, 0);

		printw("(%c) ", (r->sel == i) ? '*' : ' ');
		for (cp =  r->texts[i]; *cp; cp++)
		{
			if (*cp == '&')
			{
				attrset ((i==r->pos && Msg==WIDGET_FOCUS)
					? HOT_FOCUSC : HOT_NORMALC);
				addch(*++cp);
				attrset ((i==r->pos && Msg==WIDGET_FOCUS) ? FOCUSC : NORMALC);
			}
			else
				addch(*cp);
		}
	}
	return 1;
	break;
#endif
    }
    return default_proc (h, Msg, Par);
}

#ifdef HAVE_TK
    static void Radio_destroy (WRadio *r)
    {
	x_destroy_cmd (r);
    }
#   define radio_destroy (destroy_fn) Radio_destroy
#else
#   define radio_destroy 0
#endif

static int
radio_event (Gpm_Event *event, WRadio *r)
{
#ifndef HAVE_X
    if (event->type & (GPM_DOWN|GPM_UP)){
    	Dlg_head *h = r->widget.parent;

	r->pos = event->y - 1;
	dlg_select_widget (h, r);
	if (event->type & GPM_UP){
	    radio_callback (h, r, WIDGET_KEY, ' ');
	    radio_callback (h, r, WIDGET_FOCUS, 0);
	    (*h->callback) (h, ' ', DLG_POST_KEY);
	    return MOU_NORMAL;
	}
    }
#endif
    return MOU_NORMAL;
}

WRadio *
radio_new (int y, int x, int count, char **texts, int use_hotkey, char *tkname)
{
    WRadio *r = xmalloc (sizeof (WRadio), "radio_new");
    int i, max, m;

    /* Compute the longest string */
    max = 0;
    for (i = 0; i < count; i++){
	m = strlen (texts [i]);
	if (m > max)
	    max = m;
    }

    init_widget (&r->widget, y, x, count, max, (callback_fn) radio_callback,
		 radio_destroy, (mouse_h) radio_event, tkname);
    r->state = 1;
    r->pos = 0;
    r->sel = 0;
    r->count = count;
    r->texts = texts;
    r->upper_letter_is_hotkey = use_hotkey;
    widget_want_hotkey (r->widget, 1);

    return r;
}


/* Checkbutton widget */

static int check_event (Gpm_Event *event, WCheck *b);

static int
check_callback (Dlg_head *h, WCheck *c, int Msg, int Par)
{
    switch (Msg) {
    case WIDGET_INIT:
	return x_create_check (h, h->wdata, c);

#ifndef	HAVE_XVIEW
    case WIDGET_HOTKEY:
        if (c->hotkey==Par ||
	    (c->hotkey>='a' && c->hotkey<='z' && c->hotkey-32==Par)){
	    check_callback (h, c, WIDGET_KEY, ' ');        /* make action */
	    return 1;
	} else
	    return 0;

    case WIDGET_KEY:
	if (Par != ' ')
	    break;
	c->state ^= C_BOOL;
	c->state ^= C_CHANGE;
        (*h->callback) (h, h->current->dlg_id, DLG_ACTION);
	check_callback (h, c, WIDGET_FOCUS, ' ');
	return 1;

#ifndef HAVE_X
    case WIDGET_CURSOR:
	widget_move (&c->widget, 0, 1);
	break;

    case WIDGET_FOCUS:
    case WIDGET_UNFOCUS:
    case WIDGET_DRAW:
	attrset ((Msg == WIDGET_FOCUS) ? FOCUSC : NORMALC);
	widget_move (&c->widget, 0, 0);
	printw ("[%c] %s", (c->state & C_BOOL) ? 'x' : ' ', c->text);

	if (c->hotpos >= 0){
	    attrset ((Msg == WIDGET_FOCUS) ? HOT_FOCUSC : HOT_NORMALC);
	    widget_move (&c->widget, 0, + c->hotpos+4);
	    addch ((unsigned char)c->text [c->hotpos]);
	}
	return 1;
#endif /* !HAVE_X */
#endif /* !HAVE_XVIEW */
    }
    return default_proc (h, Msg, Par);
}

static int
check_event (Gpm_Event *event, WCheck *c)
{
#ifndef HAVE_X
    if (event->type & (GPM_DOWN|GPM_UP)){
    	Dlg_head *h = c->widget.parent;

	dlg_select_widget (h, c);
	if (event->type & GPM_UP){
	    check_callback (h, c, WIDGET_KEY, ' ');
	    check_callback (h, c, WIDGET_FOCUS, 0);
	    (*h->callback) (h, ' ', DLG_POST_KEY);
	    return MOU_NORMAL;
	}
    }
#endif
    return MOU_NORMAL;
}

static void
check_destroy (WCheck *c)
{
	x_destroy_cmd (c);
	free (c->text);
}

WCheck *
check_new (int y, int x, int state, char *text, char *tkname)
{
    WCheck *c =  xmalloc (sizeof (WCheck), "check_new");
    char *s, *t;

    init_widget (&c->widget, y, x, 1, strlen (text),
		 (callback_fn)check_callback,
		 (destroy_fn)check_destroy, (mouse_h) check_event, tkname);
    c->state = state ? C_BOOL : 0;
    c->text = strdup (text);
    c->hotkey = 0;
    c->hotpos = -1;
    widget_want_hotkey (c->widget, 1);

    /* Scan for the hotkey */
    for (s = text, t = c->text; *s; s++, t++){
	if (*s != '&'){
	    *t = *s;
	    continue;
	}
	s++;
	if (*s){
	    c->hotkey = tolower (*s);
	    c->hotpos = t - c->text;
	}
	*t = *s;
    }
    *t = 0;
    return c;
}


/* Label widget */

static int
label_callback (Dlg_head *h, WLabel *l, int Msg, int Par)
{
    if (Msg == WIDGET_INIT)
	return x_create_label (h, h->wdata, l);

    /* We don't want to get the focus */
    if (Msg == WIDGET_FOCUS)
	return 0;
#ifndef HAVE_X
    if (Msg == WIDGET_DRAW && l->text){
	char *p = l->text, *q, c = 0;
	int y = 0;
	if (l->transparent)
	    attrset (DEFAULT_COLOR);
	else
	    attrset (NORMALC);
	for (;;){
	    int xlen;

	    q = strchr (p, '\n');
	    if (q){
		c = *q;
		*q = 0;
	    }
	    widget_move (&l->widget, y, 0);
	    printw ("%s", p);
	    xlen = l->widget.cols - strlen (p);
	    if (xlen > 0)
		printw ("%*s", xlen, " ");
	    if (!q)
		break;
	    *q = c;
	    p = q + 1;
	    y++;
	}
	return 1;
    }
#endif
    return default_proc (h, Msg, Par);
}

void
label_set_text (WLabel *label, char *text)
{
    int newcols = label->widget.cols;

    if (label->text && text && !strcmp (label->text, text))
        return; /* Flickering is not nice */

    if (label->text){
	free (label->text);
    }
    if (text){
	label->text = strdup (text);

⌨️ 快捷键说明

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