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

📄 dlg.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Dlg box features module for the Midnight Commander
   Copyright (C) 1994, 1995 Radek Doulik, Miguel de Icaza

   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>
/* "$Id: dlg.c 15091 2005-05-07 21:24:31Z sedwards $" */
#include <string.h>
#include <stdio.h>
#include <malloc.h>
#include <ctype.h>
#include "tty.h"
#include <stdarg.h>
#include "mad.h"
#include "x.h"
#include "util.h"
#include "menu.h"
#include "global.h"
#include "win.h"
#include "color.h"
#include "mouse.h"
#include "help.h"
#include "key.h"	/* For mi_getch() */
#include "dlg.h"
#include "dialog.h"	/* For push_refresh() and pop_refresh() */
#include "layout.h"
#include "main.h"

/* This is the current frame, used to group Tk packings */
char *the_frame = "";

#define waddc(w,y1,x1,c) move (w->y+y1, w->x+x1); addch (c)

/* Primitive way to check if the the current dialog is our dialog */
/* This is needed by async routines like load_prompt */
Dlg_head *current_dlg = 0;

/* A hook list for idle events */
Hook *idle_hook = 0;

#ifndef PORT_HAS_SET_IDLE
#    define x_set_idle(d,x)
#endif

#ifndef PORT_HAS_DIALOG_STOP
#   define x_dialog_stop(d)
#endif

static void slow_box (Dlg_head *h, int y, int x, int ys, int xs)
{
    move (h->y+y, h->x+x);
    hline (' ', xs);
    vline (' ', ys);
    move (h->y+y, h->x+x+xs-1);
    vline (' ', ys);
    move (h->y+y+ys-1, h->x+x);
    hline (' ', xs);
}

/* draw box in window */
void draw_box (Dlg_head *h, int y, int x, int ys, int xs)
{
    extern int slow_terminal;

    if (slow_terminal){
	slow_box (h, y, x, ys, xs);
	return;
    }

#ifndef HAVE_SLANG
    waddc (h, y, x, ACS_ULCORNER);
    hline (ACS_HLINE, xs - 2);
    waddc (h, y + ys - 1, x, ACS_LLCORNER);
    hline (ACS_HLINE, xs - 2);

    waddc (h, y, x + xs - 1, ACS_URCORNER);
    waddc (h, y + ys - 1, x + xs - 1, ACS_LRCORNER);

    move (h->y+y+1, h->x+x);
    vline (ACS_VLINE, ys - 2);
    move (h->y+y+1, h->x+x+xs-1);
    vline (ACS_VLINE, ys - 2);
#else
    SLsmg_draw_box (h->y+y, h->x+x, ys, xs);
#endif
}

/* draw box in window */
void draw_double_box (Dlg_head *h, int y, int x, int ys, int xs)
{
#ifndef HAVE_SLANG
    draw_box (h, y, x, ys, xs);
#else
    SLsmg_draw_double_box (h->y+y, h->x+x, ys, xs);
#endif
}

void widget_erase (Widget *w)
{
    int x, y;

    for (y = 0; y < w->lines; y++){
	widget_move (w, y, 0);
	for (x = 0; x < w->cols; x++)
	    addch (' ');
    }
}

void dlg_erase (Dlg_head *h)
{
    int x, y;

    for (y = 0; y < h->lines; y++){
	move (y+h->y, h->x);	/* FIXME: should test if ERR */
	for (x = 0; x < h->cols; x++){
	    addch (' ');
	}
    }
}

void init_widget (Widget *w, int y, int x, int lines, int cols,
		  int (*callback)(Dlg_head *, void *, int, int),
		  destroy_fn destroy, mouse_h mouse_handler, char *tkname)
{
    w->x = x;
    w->y = y;
    w->cols = cols;
    w->lines = lines;
    w->color = -1;
    w->callback = callback;
    w->destroy  = destroy;
    w->mouse = mouse_handler;
    w->wdata = 0;
    w->wcontainer = 0;
    w->frame = "";
    w->parent = 0;
    w->tkname = tkname;

    if (tkname && *tkname == 0){
	fprintf (stderr, "Got a null string for the tkname\n");
	abort ();
    }
    /* Almost all widgets want to put the cursor in a suitable place */
    w->options = W_WANT_CURSOR;
}

int default_proc (Dlg_head *h, int Msg, int Par)
{
    switch (Msg){

    case WIDGET_HOTKEY:         /* Didn't use the key */
        return 0;

    case WIDGET_INIT:		/* We could tell if something went wrong */
	return 1;

    case WIDGET_KEY:
	return 0;		/* Didn't use the key */

    case WIDGET_FOCUS:		/* We accept FOCUSes */
	if (h->current)
	    x_focus_widget (h->current);
	return 1;

    case WIDGET_UNFOCUS:	/* We accept loose FOCUSes */
	if (h->current)
	    x_unfocus_widget (h->current);
	return 1;

    case WIDGET_DRAW:
	return 1;

    case WIDGET_DESTROY:
	return 1;

    case WIDGET_CURSOR:
	/* Move the cursor to the default widget position */
	return 1;

    case WIDGET_IDLE:
	return 1;
    }
    printf ("Internal error: unhandled message: %d\n", Msg);
    return 1;
}

int default_dlg_callback (Dlg_head *h, int id, int msg)
{
    if (msg == DLG_IDLE){
	dlg_broadcast_msg_to (h, WIDGET_IDLE, 0, W_WANT_IDLE);
    }
    return 0;
}

#ifdef HAVE_X
int midnight_callback (struct Dlg_head *h, int id, int msg);
#endif
Dlg_head *create_dlg (int y1, int x1, int lines, int cols,
		      int *color_set,
		      int (*callback) (struct Dlg_head *, int, int),
		      char *help_ctx, char *name,
		      int flags)
{
    Dlg_head *new_d;

    if (flags & DLG_CENTER){
	y1 = (LINES-lines)/2;
	x1 = (COLS-cols)/2;
    }
    if ((flags & DLG_TRYUP) && (y1 > 3))
	y1 -= 2;

    new_d = (Dlg_head *) malloc (sizeof (Dlg_head));
    new_d->current = NULL;
    new_d->count = 0;
    new_d->direction = DIR_FORWARD;
    new_d->color = color_set;
    new_d->help_ctx = help_ctx;
    new_d->callback = callback ? callback : default_dlg_callback;
    new_d->send_idle_msg = 0;
    new_d->x = x1;
    new_d->y = y1;
    new_d->title = 0;
    new_d->cols = cols;
    new_d->lines = lines;
    new_d->refresh_pushed = 0;
    new_d->has_menubar = 0;
    new_d->name = name;
    new_d->raw = 0;
    new_d->grided = 0;
    new_d->initfocus = NULL;
    new_d->running = 0;
#ifdef HAVE_X
    if (callback != midnight_callback)
        new_d->wdata = xtoolkit_create_dialog (new_d, flags);
    else
    	new_d->wdata = xtoolkit_get_main_dialog (new_d);
#endif
    return (new_d);
}

void set_idle_proc (Dlg_head *d, int state)
{
    d->send_idle_msg = state;
    x_set_idle (d, state);
}

/* add component to dialog buffer */
int add_widgetl (Dlg_head *where, void *what, WLay layout)
{
    Widget_Item *back;
    Widget      *widget = (Widget *) what;

    /* Only used by Tk */
    widget->frame = the_frame;

    widget->layout = layout;
    /* Don't accept 0 widgets, this could be from widgets that could not */
    /* initialize properly */
    if (!what)
	return 0;

    widget->x += where->x;
    widget->y += where->y;

    if (where->running){
	    Widget_Item *point = where->current;

	    where->current = (Widget_Item *) malloc (sizeof (Widget_Item));

	    if (point){
		    where->current->next = point->next;
		    where->current->prev = point;
		    point->next->prev = where->current;
		    point->next = where->current;
	    } else {
		    where->current->next = where->current;
		    where->first = where->current;
		    where->current->prev = where->first;
		    where->last = where->current;
		    where->first->next = where->last;
	    }
    } else {
	    back = where->current;
	    where->current = (Widget_Item *) malloc (sizeof (Widget_Item));
	    if (back){
		    back->prev = where->current;
		    where->current->next = back;
	    } else {
		    where->current->next = where->current;
		    where->first = where->current;
	    }

	    where->current->prev = where->first;
	    where->last = where->current;
	    where->first->next = where->last;

    }
    where->current->dlg_id = where->count;
    where->current->widget = what;
    where->current->widget->parent = where;

    where->count++;

    /* If the widget is inserted in a running dialog */
    if (where->running){
	send_message (where, widget, WIDGET_INIT, 0);
	send_message (where, widget, WIDGET_DRAW, 0);
#ifdef HAVE_GNOME
	x_add_widget (where, where->current);
#endif
    }
    return (where->count - 1);
}

int remove_widget (Dlg_head *h, void *what)
{
    Widget_Item *first, *p;

    first = p = h->current;

    do {
	if (p->widget == what){
	    /* Remove links to this Widget_Item */
	    p->prev->next = p->next;
	    p->next->prev = p->prev;

	    /* Make sure h->current is always valid */
	    if (p == h->current){
		h->current = h->current->next;
		if (h->current == p)
		    h->current = 0;
	    }
	    h->count--;
	    free (p);
	    return 1;
	}
	p = p->next;
    } while (p != first);
    return 0;
}

int destroy_widget (Widget *w)
{
    send_message (w->parent, w, WIDGET_DESTROY, 0);
    if (w->destroy)
	w->destroy (w);
    free (w);
    return 1;
}

int add_widget (Dlg_head *where, void *what)
{
    return add_widgetl (where, what, XV_WLAY_DONTCARE);
}

int send_message (Dlg_head *h, Widget *w, int msg, int par)
{
    return (*(w->callback))(h, w, msg, par);
}

/* broadcast a message to all the widgets in a dialog that have
 * the options set to flags.
 */
void dlg_broadcast_msg_to (Dlg_head *h, int message, int reverse, int flags)
{
    Widget_Item *p, *first;

    if (!h->current)
	    return;

    if (reverse)
	first = p = h->current->prev;
    else
	/* FIXME: On XView the layout for the widget->next widget is
	   invoked, and we should change the buttons order on query_dialog
	   in order to use the HAVE_X part of the statement */
#ifdef HAVE_X
	first = p = h->current;
#else
	first = p = h->current->next;
#endif
    do {
/*	if (p->widget->options & flags) */
	    send_message (h, p->widget, message, 0);

	if (reverse)
	    p = p->prev;
	else
	    p = p->next;
    } while (first != p);
}

/* broadcast a message to all the widgets in a dialog */
void dlg_broadcast_msg (Dlg_head *h, int message, int reverse)
{
    dlg_broadcast_msg_to (h, message, reverse, ~0);
}

int dlg_focus (Dlg_head *h)
{
    if (send_message (h, h->current->widget, WIDGET_FOCUS, 0)){
	(*h->callback) (h, h->current->dlg_id, DLG_FOCUS);
	return 1;
    }
    return 0;
}

int dlg_unfocus (Dlg_head *h)
{
    if (send_message (h, h->current->widget, WIDGET_UNFOCUS, 0)){
	(*h->callback) (h, h->current->dlg_id, DLG_UNFOCUS);
	return 1;
    }
    return 0;
}

static void select_a_widget (Dlg_head *h, int down)
{
    int direction = h->direction;

    if (!down)
	direction = !direction;

    do {
	if (direction)
	    h->current = h->current->next;
	else
	    h->current = h->current->prev;

	(*h->callback) (h, h->current->dlg_id, DLG_ONE_DOWN);
    } while (!dlg_focus (h));
}

/* Return true if the windows overlap */
int dlg_overlap (Widget *a, Widget *b)
{
    if ((b->x >= a->x + a->cols)
	|| (a->x >= b->x + b->cols)
	|| (b->y >= a->y + a->lines)
	|| (a->y >= b->y + b->lines))
	return 0;
    return 1;
}


/* Searches a widget, uses the callback as a signature in the dialog h */
Widget *find_widget_type (Dlg_head *h, callback_fn signature)
{
    Widget *w;
    Widget_Item *item;
    int i;

    if (!h)
	return 0;

    w = 0;
    for (i = 0, item = h->current; i < h->count; i++, item = item->next){
	if (item->widget->callback == signature){
	    w = item->widget;
	    break;
	}
    }
    return w;
}

void dlg_one_up (Dlg_head *h)
{
    Widget_Item *old;

    old = h->current;
    /* If it accepts unFOCUSion */
    if (!dlg_unfocus(h))
	return;

    select_a_widget (h, 0);
    if (dlg_overlap (old->widget, h->current->widget)){
	send_message (h, h->current->widget, WIDGET_DRAW, 0);
	send_message (h, h->current->widget, WIDGET_FOCUS, 0);
    }
}

void dlg_one_down (Dlg_head *h)
{
    Widget_Item *old;

    old = h->current;
    if (!dlg_unfocus (h))
	return;

    select_a_widget (h, 1);
    if (dlg_overlap (old->widget, h->current->widget)){
	send_message (h, h->current->widget, WIDGET_DRAW, 0);
	send_message (h, h->current->widget, WIDGET_FOCUS, 0);
    }
}

int dlg_select_widget (Dlg_head *h, void *w)
{
    if (dlg_unfocus (h)){
	while (h->current->widget != w)
	    h->current = h->current->next;
	while (!dlg_focus (h))
	    h->current = h->current->next;

	return 1;
    }
    return 0;
}

int send_message_to (Dlg_head *h, Widget *w, int msg, int par)
{
    Widget_Item *p = h->current;
    int v, i;

⌨️ 快捷键说明

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