widget.c
来自「ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机」· C语言 代码 · 共 2,500 行 · 第 1/4 页
C
2,500 行
}
void
listbox_remove_list (WListbox *l)
{
WLEntry *p, *q;
if (!l->count)
return;
#ifdef HAVE_X
if (l->widget.wdata != (widget_data) NULL) {
int i;
for (i = 0; i < l->count; i++)
x_listbox_delete_nth (l, i);
}
#endif
p = l->list;
while (l->count--) {
q = p->next;
free (p->text);
free (p);
p = q;
}
l->pos = l->count = 0;
l->list = l->top = l->current = 0;
}
/*
* bor 30.10.96: added force flag to remove *last* entry as well
* bor 30.10.96: corrected selection bug if last entry was removed
*/
void
listbox_remove_current (WListbox *l, int force)
{
WLEntry *p;
/* Ok, note: this won't allow for emtpy lists */
if (!force && (!l->count || l->count == 1))
return;
#ifdef HAVE_X
if (l->widget.wdata != (widget_data) NULL) {
x_listbox_delete_nth (l, l->pos);
if (l->count > 1)
if (l->current->next != l->list)
x_listbox_select_nth (l, l->pos);
else if (l->current != l->list)
x_listbox_select_nth (l, l->pos - 1);
else
x_listbox_select_nth (l, 0);
}
#endif
l->count--;
p = l->current;
if (l->count) {
l->current->next->prev = l->current->prev;
l->current->prev->next = l->current->next;
if (p->next == l->list) {
l->current = p->prev;
l->pos--;
}
else
l->current = p->next;
if (p == l->list)
l->list = l->top = p->next;
} else {
l->pos = 0;
l->list = l->top = l->current = 0;
}
free (p->text);
free (p);
}
/* Makes *e the selected entry (sets current and pos) */
void
listbox_select_entry (WListbox *l, WLEntry *dest)
{
WLEntry *e;
int pos;
int top_seen;
top_seen = 0;
/* Special case */
for (pos = 0, e = l->list; pos < l->count; e = e->next, pos++){
if (e == l->top)
top_seen = 1;
if (e == dest){
l->current = e;
if (top_seen){
while (listbox_cdiff (l->top, l->current) >= l->height)
l->top = l->top->next;
} else {
l->top = l->current;
}
l->pos = pos;
x_listbox_select_nth (l, l->pos);
return;
}
}
/* If we are unable to find it, set decent values */
l->current = l->top = l->list;
l->pos = 0;
x_listbox_select_nth (l, l->pos);
}
/* Selects from base the pos element */
static WLEntry *
listbox_select_pos (WListbox *l, WLEntry *base, int pos)
{
WLEntry *last = l->list->prev;
if (base == last)
return last;
while (pos--){
base = base->next;
if (base == last)
break;
}
return base;
}
static inline int
listbox_back (WListbox *l)
{
if (l->pos){
listbox_select_entry (l, listbox_select_pos (l, l->list, l->pos-1));
return 1;
}
return 0;
}
static inline int
listbox_fwd (WListbox *l)
{
if (l->current != l->list->prev){
listbox_select_entry (l, listbox_select_pos (l, l->list, l->pos+1));
return 1;
}
return 0;
}
/* Returns 1 if we want a redraw */
static int
listbox_key (WListbox *l, int key)
{
int i;
int j = 0;
if (!l->list)
return 0;
switch (key){
case KEY_HOME:
case KEY_A1:
l->current = l->top = l->list;
l->pos = 0;
return 1;
case KEY_END:
case KEY_C1:
l->current = l->top = l->list->prev;
for (i = min (l->height - 1, l->count - 1); i; i--)
l->top = l->top->prev;
l->pos = l->count - 1;
return 1;
case XCTRL('p'):
case KEY_UP:
listbox_back (l);
return 1;
case XCTRL('n'):
case KEY_DOWN:
listbox_fwd (l);
return 1;
case KEY_NPAGE:
case XCTRL('v'):
for (i = 0; i < l->height-1; i++)
j |= listbox_fwd (l);
return j > 0;
case KEY_PPAGE:
case ALT('v'):
for (i = 0; i < l->height-1; i++)
j |= listbox_back (l);
return j > 0;
}
return 0;
}
static int listbox_event (Gpm_Event *event, WListbox *l);
static int
listbox_callback (Dlg_head *h, WListbox *l, int msg, int par)
{
WLEntry *e;
/* int selected_color; Never used */
int ret_code;
switch (msg){
case WIDGET_INIT:
return x_create_listbox (h, h->wdata, l);
#ifndef HAVE_XVIEW
case WIDGET_HOTKEY:
if ((e = listbox_check_hotkey (l, par)) != NULL){
listbox_select_entry (l, e);
/* Take the appropriate action */
if (l->action == listbox_finish){
l->widget.parent->running = 0;
l->widget.parent->ret_value = B_ENTER;
} else if (l->action == listbox_cback){
if ((*l->cback)(l) == listbox_finish){
l->widget.parent->running = 0;
l->widget.parent->ret_value = B_ENTER;
}
}
return 1;
} else
return 0;
case WIDGET_KEY:
if ((ret_code = listbox_key (l, par)))
listbox_draw (l, h, 1);
return ret_code;
#ifndef HAVE_X
case WIDGET_CURSOR:
widget_move (&l->widget, l->cursor_y, 0);
return 1;
case WIDGET_FOCUS:
case WIDGET_UNFOCUS:
case WIDGET_DRAW:
listbox_draw (l, h, msg != WIDGET_UNFOCUS);
return 1;
#endif
#endif /* !HAVE_XVIEW */
}
return default_proc (h, msg, par);
}
static int
listbox_event (Gpm_Event *event, WListbox *l)
{
#ifndef HAVE_X
int i;
Dlg_head *h = l->widget.parent;
/* Single click */
if (event->type & GPM_DOWN)
dlg_select_widget (l->widget.parent, l);
if (!l->list)
return MOU_NORMAL;
if (event->type & (GPM_DOWN|GPM_DRAG)){
if (event->x < 0 || event->x >= l->width)
return MOU_REPEAT;
if (event->y < 1)
for (i = -event->y; i >= 0; i--)
listbox_back (l);
else if (event->y > l->height)
for (i = event->y - l->height; i > 0; i--)
listbox_fwd (l);
else
listbox_select_entry (l, listbox_select_pos (l, l->top,
event->y - 1));
/* We need to refresh ourselves since the dialog manager doesn't */
/* know about this event */
listbox_callback (h, l, WIDGET_DRAW, 0);
mc_refresh ();
return MOU_REPEAT;
}
/* Double click */
if ((event->type & (GPM_DOUBLE|GPM_UP)) == (GPM_UP|GPM_DOUBLE)){
if (event->x < 0 || event->x >= l->width)
return MOU_NORMAL;
if (event->y < 1 || event->y > l->height)
return MOU_NORMAL;
dlg_select_widget (l->widget.parent, l);
listbox_select_entry (l, listbox_select_pos (l, l->top, event->y - 1));
switch (l->action){
case listbox_nothing:
break;
case listbox_finish:
h->ret_value = B_ENTER;
dlg_stop (h);
return MOU_ENDLOOP;
case listbox_cback:
if ((*l->cback)(l) == listbox_finish)
return MOU_ENDLOOP;
}
}
#endif
return MOU_NORMAL;
}
static void
listbox_destroy (WListbox *l)
{
WLEntry *n, *p = l->list;
int i;
x_destroy_cmd (l);
for (i = 0; i < l->count; i++){
n = p->next;
free (p->text);
free (p);
p = n;
}
}
WListbox *
listbox_new (int y, int x, int width, int height,
int action, lcback callback, char *tkname)
{
WListbox *l = xmalloc (sizeof (WListbox), "listbox_new");
extern int slow_terminal;
init_widget (&l->widget, y, x, height, width,
(callback_fn)listbox_callback,
(destroy_fn) listbox_destroy, (mouse_h)listbox_event, tkname);
l->list = l->top = l->current = 0;
l->pos = 0;
l->width = width;
l->height = height;
l->count = 0;
l->top = 0;
l->current= 0;
l->cback = callback;
l->action = action;
l->allow_duplicates = 1;
l->scrollbar = slow_terminal ? 0 : 1;
widget_want_hotkey (l->widget, 1);
return l;
}
/* Listbox item adding function. They still lack a lot of functionality */
/* any takers? */
/* 1.11.96 bor: added pos argument to control placement of new entry */
static void
listbox_append_item (WListbox *l, WLEntry *e, enum append_pos pos)
{
if (!l->list){
l->list = e;
l->top = e;
l->current = e;
e->next = l->list;
e->prev = l->list;
} else if (pos == LISTBOX_APPEND_AT_END) {
e->next = l->list;
e->prev = l->list->prev;
l->list->prev->next = e;
l->list->prev = e;
} else if (pos == LISTBOX_APPEND_BEFORE){
e->next = l->current;
e->prev = l->current->prev;
l->current->prev->next = e;
l->current->prev = e;
if (l->list == l->current) { /* move list one position down */
l->list = e;
l->top = e;
}
} else if (pos == LISTBOX_APPEND_AFTER) {
e->prev = l->current;
e->next = l->current->next;
l->current->next->prev = e;
l->current->next = e;
}
x_list_insert (l, l->list, e);
l->count++;
}
char *
listbox_add_item (WListbox *l, enum append_pos pos, int hotkey, char *text,
void *data)
{
WLEntry *entry;
if (!l)
return 0;
if (!l->allow_duplicates)
if (listbox_search_text (l, text))
return 0;
entry = xmalloc (sizeof (WLEntry), "listbox_add_item");
entry->text = strdup (text);
entry->data = data;
entry->hotkey = hotkey;
listbox_append_item (l, entry, pos);
return entry->text;
}
/* Selects the nth entry in the listbox */
void
listbox_select_by_number (WListbox *l, int n)
{
listbox_select_entry (l, listbox_select_pos (l, l->list, n));
}
WLEntry *
listbox_search_text (WListbox *l, char *text)
{
WLEntry *e;
e = l->list;
if (!e)
return NULL;
do {
if(!strcmp (e->text, text))
return e;
e = e->next;
} while (e!=l->list);
return NULL;
}
/* Returns the current string text as well as the associated extra data */
void
listbox_get_current (WListbox *l, char **string, char **extra)
{
if (!l->current){
*string = 0;
*extra = 0;
}
if (string && l->current)
*string = l->current->text;
if (extra && l->current)
*extra = l->current->data;
}
int
buttonbar_callback (Dlg_head *h, WButtonBar *bb, int msg, int par)
{
int i;
switch (msg){
case WIDGET_INIT:
return x_create_buttonbar (h, h->wdata, bb);
case WIDGET_FOCUS:
return 0;
#ifndef HAVE_XVIEW
case WIDGET_HOTKEY:
for (i = 0; i < 10; i++){
if (par == KEY_F(i+1) && bb->labels [i].function){
(*bb->labels [i].function)(bb->labels [i].data);
return 1;
}
}
return 0;
#ifndef HAVE_X
case WIDGET_DRAW:
if (!bb->visible)
return 1;
widget_move (&bb->widget, 0, 0);
attrset (DEFAULT_COLOR);
printw ("%-*s", bb->widget.cols - 1, "");
for (i = 0; i < COLS/8 && i < 10; i++){
widget_move (&bb->widget, 0, i*8);
attrset (DEFAULT_COLOR);
printw ("%d", i+1);
attrset (SELECTED_COLOR);
printw ("%-*s", ((i+1) * 8 == COLS ? 5 : 6),
bb->labels [i].text ? bb->labels [i].text : "");
attrset (DEFAULT_COLOR);
}
attrset (SELECTED_COLOR);
return 1;
#endif
#endif /* !HAVE_XVIEW */
}
return default_proc (h, msg, par);
}
static void
buttonbar_destroy (WButtonBar *bb)
{
int i;
for (i = 0; i < 10; i++){
if (bb->labels [i].text)
free (bb->labels [i].text);
}
}
static int
buttonbar_event (Gpm_Event *event, WButtonBar *bb)
{
#ifndef HAVE_X
int button;
if (!(event->type & GPM_UP))
return MOU_NORMAL;
if (event->y == 2)
return MOU_NORMAL;
button = event->x / 8;
if (button < 10 && bb->labels [button].function)
(*bb->labels [button].function)(bb->labels [button].data);
#endif
return MOU_NORMAL;
}
WButtonBar *
buttonbar_new (int visible)
{
int i;
WButtonBar *bb = xmalloc (sizeof (WButtonBar), "buttonbar_new");
init_widget (&bb->widget, LINES-1, 0, 1, COLS,
(callback_fn) buttonbar_callback,
(destroy_fn) buttonbar_destroy, (mouse_h) buttonbar_event, NULL);
bb->visible = visible;
for (i = 0; i < 10; i++){
bb->labels [i].text = 0;
bb->labels [i].function = 0;
}
widget_want_hotkey (bb->widget, 1);
widget_want_cursor (bb->widget, 0);
return bb;
}
void
set_label_text (WButtonBar *bb, int index, char *text)
{
if (bb->labels [index-1].text)
free (bb->labels [index-1].text);
bb->labels [index-1].text = strdup (text);
}
/* paneletc is either the panel widget, or info or view or tree widget */
WButtonBar *
find_buttonbar (Dlg_head *h, Widget *paneletc)
{
WButtonBar *bb;
Widget_Item *item;
int i;
bb = 0;
for (i = 0, item = h->current; i < h->count; i++, item = item->next){
if (item->widget->callback == (callback_fn) buttonbar_callback){
bb = (WButtonBar *) item->widget;
#ifdef HAVE_XVIEW
/* Jakub: do we really need this routine here?
* Does XView hold more that a buttonbar per Dlg_head?
*/
if (x_find_buttonbar_check (bb, paneletc)) {
bb = 0;
continue;
}
#endif
break;
}
}
return bb;
}
void
define_label_data (Dlg_head *h, Widget *paneletc, int idx, char *text,
buttonbarfn cback, void *data)
{
WButtonBar *bb = find_buttonbar (h, paneletc);
if (!bb)
return;
set_label_text (bb, idx, text);
bb->labels [idx-1].function = (void (*)(void *)) cback;
bb->labels [idx-1].data = data;
x_redefine_label (bb, idx);
}
void
define_label (Dlg_head *h, Widget *paneletc, int idx, char *text, void (*cback)(void))
{
define_label_data (h, paneletc, idx, text, (void (*)(void *)) cback, 0);
}
#ifdef HAVE_X
void redraw_labels (Dlg_head *h, Widget *paneletc)
{
}
#else
void
redraw_labels (Dlg_head *h, Widget *paneletc)
{
Widget_Item *item;
int i;
for (i = 0, item = h->current; i < h->count; i++, item = item->next){
if (item->widget->callback == (callback_fn) buttonbar_callback){
widget_redraw (h, item);
return;
}
}
}
#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?