* dlg.h: Merge with ...

* dialog.h: ... this.  Adjust all dependencies.
* dlg.c: Merge with ...
* dialog.c: ... this.
* Makefile.am (SRCS): Remove dlg.h and dlg.c.
This commit is contained in:
Pavel Roskin 2003-10-24 23:20:30 +00:00
parent 0ee63c1450
commit 98950838b4
38 changed files with 1119 additions and 1150 deletions

View File

@ -1,7 +1,7 @@
#ifndef __EDIT_WIDGET_H
#define __EDIT_WIDGET_H
#include "src/dlg.h" /* Widget */
#include "src/dialog.h" /* Widget */
#define MAX_MACRO_LENGTH 1024
#define N_LINE_CACHES 32

View File

@ -22,7 +22,7 @@
#include <config.h>
#include "edit.h"
#include "src/dlg.h" /* B_CANCEL */
#include "src/dialog.h" /* B_CANCEL */
#include "src/wtools.h" /* QuickDialog */
#define OPT_DLG_H 17

View File

@ -1,5 +1,11 @@
2003-10-24 Pavel Roskin <proski@gnu.org>
* dlg.h: Merge with ...
* dialog.h: ... this. Adjust all dependencies.
* dlg.c: Merge with ...
* dialog.c: ... this.
* Makefile.am (SRCS): Remove dlg.h and dlg.c.
* dlg.h: Declare idle_hook here.
* dialog.c: Eliminate typedef Refresh, unneeded includes.

View File

@ -45,7 +45,7 @@ CHARSET_SRC = charsets.c charsets.h selcodepage.c selcodepage.h
SRCS = achown.c achown.h background.c background.h boxes.c boxes.h \
chmod.c chmod.h chown.c chown.h cmd.c cmd.h color.c color.h \
command.c command.h complete.c complete.h cons.handler.c \
cons.saver.h dialog.c dialog.h dir.c dir.h dlg.c dlg.h \
cons.saver.h dialog.c dialog.h dir.c dir.h \
eregex.h execute.c execute.h ext.c ext.h file.c filegui.c \
filegui.h file.h filenot.c fileopctx.c fileopctx.h find.c \
find.h findme.c findme.h fs.h fsusage.c fsusage.h \

View File

@ -31,9 +31,8 @@
#include "tty.h"
#include "win.h"
#include "color.h"
#include "dlg.h"
#include "dialog.h"
#include "widget.h"
#include "dialog.h" /* For do_refresh() */
#include "wtools.h" /* For init_box_colors() */
#include "key.h" /* XCTRL and ALT macros */

View File

@ -34,7 +34,7 @@
#include "global.h"
#include "tty.h"
#include "dlg.h"
#include "dialog.h"
#include "widget.h"
#include "wtools.h"
@ -45,7 +45,6 @@
#ifdef WITH_BACKGROUND
# include <sys/socket.h>
#endif
#include "dialog.h"
#include "fileopctx.h"
#include "key.h" /* For add_select_channel(), delete_select_channel() */
#include "eregex.h"

View File

@ -31,9 +31,8 @@
#include "tty.h"
#include "win.h" /* Our window tools */
#include "color.h" /* Color definitions */
#include "dlg.h" /* The nice dialog manager */
#include "dialog.h" /* The nice dialog manager */
#include "widget.h" /* The widgets for the nice dialog manager */
#include "dialog.h" /* For do_refresh() */
#include "wtools.h"
#include "setup.h" /* For profile_name */
#include "profile.h" /* Load/save user formats */

View File

@ -30,9 +30,8 @@
#include "global.h"
#include "tty.h" /* A_REVERSE */
#include "color.h" /* dialog_colors */
#include "dlg.h" /* add_widget() */
#include "dialog.h" /* add_widget() */
#include "widget.h" /* NORMAL_BUTTON */
#include "dialog.h" /* do_refresh() */
#include "wtools.h" /* message() */
#include "panel.h" /* do_file_mark() */
#include "main.h" /* update_panels() */

View File

@ -31,9 +31,8 @@
#include "tty.h"
#include "win.h"
#include "color.h"
#include "dlg.h"
#include "dialog.h"
#include "widget.h"
#include "dialog.h" /* For do_refresh() */
/* Needed for the extern declarations of integer parameters */
#include "dir.h"

View File

@ -48,13 +48,12 @@
#include "subshell.h" /* use_subshell */
#include "cons.saver.h" /* console_flag */
#include "tty.h" /* LINES */
#include "dlg.h" /* Widget */
#include "dialog.h" /* Widget */
#include "view.h" /* view() */
#include "wtools.h" /* message() */
#include "widget.h" /* push_history() */
#include "key.h" /* application_keypad_mode() */
#include "win.h" /* do_enter_ca_mode() */
#include "dialog.h" /* do_refresh() */
#include "main.h" /* change_panel() */
#include "panel.h" /* cpanel */
#include "help.h" /* interactive_display() */

View File

@ -33,9 +33,8 @@
#include "tty.h"
#include "win.h"
#include "color.h"
#include "dlg.h"
#include "widget.h"
#include "dialog.h"
#include "widget.h"
#include "wtools.h"
#include "complete.h"
#include "main.h"

View File

@ -1,5 +1,5 @@
/* Dialog managing.
Copyright (C) 1994 Miguel de Icaza.
/* Dialog 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
@ -13,15 +13,262 @@
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <config.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <stdarg.h>
#include "global.h"
#include "tty.h"
#include "menu.h"
#include "win.h"
#include "color.h"
#include "mouse.h"
#include "help.h"
#include "key.h" /* For mi_getch() */
#include "dialog.h"
#include "key.h" /* we_are_background */
#include "main.h" /* fast_refresh */
#include "layout.h"
#include "execute.h"
#include "main.h"
#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;
static void dlg_broadcast_msg_to (Dlg_head * h, widget_msg_t message,
int reverse, int flags);
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)
{
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 /* HAVE_SLANG */
}
/* 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 /* HAVE_SLANG */
}
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,
callback_fn callback, mouse_h mouse_handler)
{
w->x = x;
w->y = y;
w->cols = cols;
w->lines = lines;
w->callback = callback;
w->mouse = mouse_handler;
w->parent = 0;
/* Almost all widgets want to put the cursor in a suitable place */
w->options = W_WANT_CURSOR;
}
/* Default callback for widgets */
cb_ret_t
default_proc (widget_msg_t msg, int parm)
{
switch (msg) {
case WIDGET_INIT:
case WIDGET_FOCUS:
case WIDGET_UNFOCUS:
case WIDGET_DRAW:
case WIDGET_DESTROY:
case WIDGET_CURSOR:
case WIDGET_IDLE:
return MSG_HANDLED;
default:
return MSG_NOT_HANDLED;
}
}
/* Clean the dialog area, draw the frame and the title */
void
common_dialog_repaint (struct Dlg_head *h)
{
int space;
space = (h->flags & DLG_COMPACT) ? 0 : 1;
attrset (NORMALC);
dlg_erase (h);
draw_box (h, space, space, h->lines - 2 * space, h->cols - 2 * space);
if (h->title) {
attrset (HOT_NORMALC);
dlg_move (h, space, (h->cols - strlen (h->title)) / 2);
addstr (h->title);
}
}
/* Default dialog callback */
cb_ret_t default_dlg_callback (Dlg_head *h, dlg_msg_t msg, int parm)
{
if (msg == DLG_DRAW && h->color) {
common_dialog_repaint (h);
return MSG_HANDLED;
}
if (msg == DLG_IDLE){
dlg_broadcast_msg_to (h, WIDGET_IDLE, 0, W_WANT_IDLE);
return MSG_HANDLED;
}
return MSG_NOT_HANDLED;
}
Dlg_head *
create_dlg (int y1, int x1, int lines, int cols, const int *color_set,
dlg_cb_fn callback, char *help_ctx, const char *title,
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 = g_new0 (Dlg_head, 1);
new_d->color = color_set;
new_d->help_ctx = help_ctx;
new_d->callback = callback ? callback : default_dlg_callback;
new_d->x = x1;
new_d->y = y1;
new_d->cols = cols;
new_d->lines = lines;
new_d->flags = flags;
/* Strip existing spaces, add one space before and after the title */
if (title) {
char *t;
t = g_strstrip (g_strdup (title));
new_d->title = g_strconcat (" ", t, " ", NULL);
g_free (t);
}
return (new_d);
}
void
set_idle_proc (Dlg_head *d, int enable)
{
if (enable)
d->flags |= DLG_WANT_IDLE;
else
d->flags &= ~DLG_WANT_IDLE;
}
/*
* Insert widget to dialog before current widget. For dialogs populated
* from the bottom, make the widget current. Return widget number.
*/
int
add_widget (Dlg_head *h, void *w)
{
Widget *widget = (Widget *) w;
/* Don't accept 0 widgets, and running dialogs */
if (!widget || h->running)
abort ();
widget->x += h->x;
widget->y += h->y;
widget->parent = h;
widget->dlg_id = h->count++;
if (h->current) {
widget->next = h->current;
widget->prev = h->current->prev;
h->current->prev->next = widget;
h->current->prev = widget;
} else {
widget->prev = widget;
widget->next = widget;
}
if ((h->flags & DLG_REVERSE) || !h->current)
h->current = widget;
return widget->dlg_id;
}
enum {
REFRESH_COVERS_PART, /* If the refresh fn convers only a part */
REFRESH_COVERS_ALL /* If the refresh fn convers all the screen */
};
typedef void (*refresh_fn) (void *);
/* The refresh stack */
struct Refresh {
@ -33,7 +280,7 @@ struct Refresh {
static struct Refresh *refresh_list;
void
static void
push_refresh (refresh_fn new_refresh, void *parameter, int flags)
{
struct Refresh *new;
@ -46,7 +293,7 @@ push_refresh (refresh_fn new_refresh, void *parameter, int flags)
refresh_list = new;
}
void
static void
pop_refresh (void)
{
struct Refresh *old;
@ -84,3 +331,601 @@ do_refresh (void)
do_complete_refresh (refresh_list);
}
}
/* broadcast a message to all the widgets in a dialog that have
* the options set to flags.
*/
static void
dlg_broadcast_msg_to (Dlg_head *h, widget_msg_t message, int reverse,
int flags)
{
Widget *p, *first, *wi;
if (!h->current)
return;
if (reverse)
first = p = h->current->prev;
else
first = p = h->current->next;
do {
wi = p;
if (reverse)
p = p->prev;
else
p = p->next;
send_message (wi, message, 0);
} while (first != p);
}
/* broadcast a message to all the widgets in a dialog */
void
dlg_broadcast_msg (Dlg_head *h, widget_msg_t message, int reverse)
{
dlg_broadcast_msg_to (h, message, reverse, ~0);
}
int dlg_focus (Dlg_head *h)
{
if (!h->current)
return 0;
if (send_message (h->current, WIDGET_FOCUS, 0)){
(*h->callback) (h, DLG_FOCUS, 0);
return 1;
}
return 0;
}
static int
dlg_unfocus (Dlg_head *h)
{
if (!h->current)
return 0;
if (send_message (h->current, WIDGET_UNFOCUS, 0)){
(*h->callback) (h, DLG_UNFOCUS, 0);
return 1;
}
return 0;
}
static void
select_a_widget (Dlg_head *h, int down)
{
if (!h->current)
return;
do {
if (down)
h->current = h->current->next;
else
h->current = h->current->prev;
} 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;
}
/* Find the widget with the given callback in the dialog h */
Widget *
find_widget_type (Dlg_head *h, void *callback)
{
Widget *w;
Widget *item;
int i;
if (!h)
return 0;
if (!h->current)
return 0;
w = 0;
for (i = 0, item = h->current; i < h->count; i++, item = item->next) {
if (item->callback == callback) {
w = item;
break;
}
}
return w;
}
/* Find the widget with the given dialog id in the dialog h and select it */
void
dlg_select_by_id (Dlg_head *h, int id)
{
Widget *w, *w_found;
if (!h->current)
return;
w = h->current;
w_found = NULL;
do {
if (w->dlg_id == id) {
w_found = w;
break;
}
w = w->next;
} while (w != h->current);
if (w_found)
dlg_select_widget(h, w_found);
}
void dlg_one_up (Dlg_head *h)
{
Widget *old;
old = h->current;
if (!old)
return;
/* If it accepts unFOCUSion */
if (!dlg_unfocus(h))
return;
select_a_widget (h, 0);
if (dlg_overlap (old, h->current)){
send_message (h->current, WIDGET_DRAW, 0);
send_message (h->current, WIDGET_FOCUS, 0);
}
}
void dlg_one_down (Dlg_head *h)
{
Widget *old;
old = h->current;
if (!old)
return;
if (!dlg_unfocus (h))
return;
select_a_widget (h, 1);
if (dlg_overlap (old, h->current)){
send_message (h->current, WIDGET_DRAW, 0);
send_message (h->current, WIDGET_FOCUS, 0);
}
}
int dlg_select_widget (Dlg_head *h, void *w)
{
if (!h->current)
return 0;
if (dlg_unfocus (h)){
while (h->current != w)
h->current = h->current->next;
while (!dlg_focus (h))
h->current = h->current->next;
return 1;
}
return 0;
}
#define callback(h) (h->current->callback)
void update_cursor (Dlg_head *h)
{
if (!h->current)
return;
if (h->current->options & W_WANT_CURSOR)
send_message (h->current, WIDGET_CURSOR, 0);
else {
Widget *p = h->current;
do {
if (p->options & W_WANT_CURSOR)
if ((*p->callback)(p, WIDGET_CURSOR, 0)){
break;
}
p = p->next;
} while (h->current != p);
}
}
/* Redraw the widgets in reverse order, leaving the current widget
* as the last one
*/
void dlg_redraw (Dlg_head *h)
{
(h->callback)(h, DLG_DRAW, 0);
dlg_broadcast_msg (h, WIDGET_DRAW, 1);
update_cursor (h);
}
static void
dlg_refresh (void *parameter)
{
dlg_redraw ((Dlg_head *) parameter);
}
void dlg_stop (Dlg_head *h)
{
h->running = 0;
}
static inline void dialog_handle_key (Dlg_head *h, int d_key)
{
switch (d_key){
case KEY_LEFT:
case KEY_UP:
dlg_one_up (h);
break;
case KEY_RIGHT:
case KEY_DOWN:
dlg_one_down (h);
break;
case KEY_F(1):
interactive_display (NULL, h->help_ctx);
do_refresh ();
break;
case XCTRL('z'):
suspend_cmd ();
/* Fall through */
case XCTRL('l'):
#ifndef HAVE_SLANG
/* Use this if the refreshes fail */
clr_scr ();
do_refresh ();
#else
touchwin (stdscr);
#endif /* HAVE_SLANG */
mc_refresh ();
doupdate ();
break;
case '\n':
case KEY_ENTER:
h->ret_value = B_ENTER;
h->running = 0;
break;
case ESC_CHAR:
case KEY_F (10):
case XCTRL ('c'):
case XCTRL ('g'):
h->ret_value = B_CANCEL;
dlg_stop (h);
break;
}
}
static int
dlg_try_hotkey (Dlg_head *h, int d_key)
{
Widget *hot_cur;
Widget *previous;
int handled, c;
if (!h->current)
return 0;
/*
* Explanation: we don't send letter hotkeys to other widgets if
* the currently selected widget is an input line
*/
if (h->current->options & W_IS_INPUT) {
if (d_key < 255 && isalpha (d_key))
return 0;
}
/* If it's an alt key, send the message */
c = d_key & ~ALT (0);
if (d_key & ALT (0) && c < 255 && isalpha (c))
d_key = tolower (c);
handled = 0;
if (h->current->options & W_WANT_HOTKEY)
handled = callback (h) (h->current, WIDGET_HOTKEY, d_key);
/* If not used, send hotkey to other widgets */
if (handled)
return handled;
hot_cur = h->current;
/* send it to all widgets */
do {
if (hot_cur->options & W_WANT_HOTKEY)
handled |=
(*hot_cur->callback) (hot_cur, WIDGET_HOTKEY, d_key);
if (!handled)
hot_cur = hot_cur->next;
} while (h->current != hot_cur && !handled);
if (!handled)
return 0;
previous = h->current;
if (!dlg_unfocus (h))
return handled;
h->current = hot_cur;
if (!dlg_focus (h)) {
h->current = previous;
dlg_focus (h);
}
return handled;
}
static int
dlg_key_event (Dlg_head *h, int d_key)
{
int handled;
if (!h->current)
return 0;
/* TAB used to cycle */
if (!(h->flags & DLG_WANT_TAB)
&& (d_key == '\t' || d_key == KEY_BTAB)) {
if (d_key == '\t')
dlg_one_down (h);
else
dlg_one_up (h);
} else {
/* first can dlg_callback handle the key */
handled = (*h->callback) (h, DLG_KEY, d_key);
/* next try the hotkey */
if (!handled)
handled = dlg_try_hotkey (h, d_key);
if (handled)
(*h->callback) (h, DLG_HOTKEY_HANDLED, 0);
/* not used - then try widget_callback */
if (!handled)
handled = callback (h) (h->current, WIDGET_KEY, d_key);
/* not used- try to use the unhandled case */
if (!handled)
handled = (*h->callback) (h, DLG_UNHANDLED_KEY, d_key);
if (!handled)
dialog_handle_key (h, d_key);
(*h->callback) (h, DLG_POST_KEY, d_key);
return handled;
}
return 1;
}
static inline int
dlg_mouse_event (Dlg_head * h, Gpm_Event * event)
{
Widget *item;
Widget *starting_widget = h->current;
Gpm_Event new_event;
int x = event->x;
int y = event->y;
item = starting_widget;
do {
Widget *widget = item;
item = item->next;
if (!((x > widget->x) && (x <= widget->x + widget->cols)
&& (y > widget->y) && (y <= widget->y + widget->lines)))
continue;
new_event = *event;
new_event.x -= widget->x;
new_event.y -= widget->y;
if (!widget->mouse)
return MOU_NORMAL;
return (*widget->mouse) (&new_event, widget);
} while (item != starting_widget);
return MOU_NORMAL;
}
/* Run dialog routines */
/* Init the process */
void init_dlg (Dlg_head *h)
{
int refresh_mode;
/* Initialize dialog manager and widgets */
(*h->callback) (h, DLG_INIT, 0);
dlg_broadcast_msg (h, WIDGET_INIT, 0);
if (h->x == 0 && h->y == 0 && h->cols == COLS && h->lines == LINES)
refresh_mode = REFRESH_COVERS_ALL;
else
refresh_mode = REFRESH_COVERS_PART;
push_refresh (dlg_refresh, h, refresh_mode);
h->refresh_pushed = 1;
h->previous_dialog = current_dlg;
current_dlg = h;
/* Initialize the mouse status */
h->mouse_status = MOU_NORMAL;
/* Select the first widget that takes focus */
while (!dlg_focus (h) && h->current)
h->current = h->current->next;
/* Redraw the screen */
dlg_redraw (h);
h->ret_value = 0;
h->running = 1;
}
/* Shutdown the run_dlg */
void dlg_run_done (Dlg_head *h)
{
if (h->current)
(*h->callback) (h, DLG_END, 0);
current_dlg = (Dlg_head *) h->previous_dialog;
}
void dlg_process_event (Dlg_head *h, int key, Gpm_Event *event)
{
if (key == EV_NONE){
if (got_interrupt ())
key = XCTRL('g');
else
return;
}
if (key == EV_MOUSE)
h->mouse_status = dlg_mouse_event (h, event);
else
dlg_key_event (h, key);
}
static inline void
frontend_run_dlg (Dlg_head *h)
{
int d_key;
Gpm_Event event;
event.x = -1;
while (h->running) {
if (winch_flag)
change_screen_size ();
if (is_idle ()) {
if (idle_hook)
execute_hooks (idle_hook);
while ((h->flags & DLG_WANT_IDLE) && is_idle ())
(*h->callback) (h, DLG_IDLE, 0);
/* Allow terminating the dialog from the idle handler */
if (!h->running)
break;
}
update_cursor (h);
/* Clear interrupt flag */
got_interrupt ();
d_key = get_event (&event, h->mouse_status == MOU_REPEAT, 1);
dlg_process_event (h, d_key, &event);
if (!h->running)
(*h->callback) (h, DLG_VALIDATE, 0);
}
}
/* Standard run dialog routine
* We have to keep this routine small so that we can duplicate it's
* behavior on complex routines like the file routines, this way,
* they can call the dlg_process_event without rewriting all the code
*/
int run_dlg (Dlg_head *h)
{
init_dlg (h);
frontend_run_dlg (h);
dlg_run_done (h);
return h->ret_value;
}
void
destroy_dlg (Dlg_head *h)
{
int i;
Widget *c;
if (h->refresh_pushed)
pop_refresh ();
dlg_broadcast_msg (h, WIDGET_DESTROY, 0);
c = h->current;
for (i = 0; i < h->count; i++) {
c = c->next;
if (h->current) {
g_free (h->current);
}
h->current = c;
}
g_free (h->title);
g_free (h);
do_refresh ();
}
void widget_set_size (Widget *widget, int y, int x, int lines, int cols)
{
widget->x = x;
widget->y = y;
widget->cols = cols;
widget->lines = lines;
}
/* Replace widget old_w for widget new_w in the dialog h */
void
dlg_replace_widget (Dlg_head *h, Widget *old_w, Widget *new_w)
{
int should_focus = 0;
if (!h->current)
return;
if (old_w == h->current)
should_focus = 1;
new_w->parent = h;
new_w->dlg_id = old_w->dlg_id;
if (old_w == old_w->next) {
/* just one widget */
new_w->prev = new_w;
new_w->next = new_w;
} else {
new_w->prev = old_w->prev;
new_w->next = old_w->next;
old_w->prev->next = new_w;
old_w->next->prev = new_w;
}
if (should_focus)
h->current = new_w;
send_message (old_w, WIDGET_DESTROY, 0);
send_message (new_w, WIDGET_INIT, 0);
if (should_focus) {
if (!dlg_focus (h)) {
select_a_widget (h, 1);
}
}
send_message (new_w, WIDGET_DRAW, 0);
}

View File

@ -1,18 +1,232 @@
#ifndef __DIALOG_H
#define __DIALOG_H
/* Dialog box features module for the Midnight Commander
Copyright (C) 1994, 1995 Radek Doulik, Miguel de Icaza
/* We search under the stack until we find a refresh function that covers */
/* the complete screen, and from this point we go up refreshing the */
/* individual regions */
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.
enum {
REFRESH_COVERS_PART, /* If the refresh fn convers only a part */
REFRESH_COVERS_ALL /* If the refresh fn convers all the screen */
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef MC_DLG_H
#define MC_DLG_H
#include "mouse.h"
/* Color constants */
#define FOCUSC h->color[1]
#define NORMALC h->color[0]
#define HOT_NORMALC h->color[2]
#define HOT_FOCUSC h->color[3]
/* Common return values */
#define B_EXIT 0
#define B_CANCEL 1
#define B_ENTER 2
#define B_HELP 3
#define B_USER 100
/* Widget messages */
typedef enum {
WIDGET_INIT, /* Initialize widget */
WIDGET_FOCUS, /* Draw widget in focused state */
WIDGET_UNFOCUS, /* Draw widget in unfocused state */
WIDGET_DRAW, /* Sent to widget to draw themselves */
WIDGET_KEY, /* Sent to widgets on key press */
WIDGET_HOTKEY, /* Sent to widget to catch preprocess key */
WIDGET_DESTROY, /* Sent to widget at destruction time */
WIDGET_CURSOR, /* Sent to widget to position the cursor */
WIDGET_IDLE, /* Send to widgets with options & W_WANT_IDLE*/
} widget_msg_t;
typedef enum {
MSG_NOT_HANDLED,
MSG_HANDLED
} cb_ret_t;
/* Widgets are expected to answer to the following messages:
WIDGET_FOCUS: 1 if the accept the focus, 0 if they do not.
WIDGET_UNFOCUS: 1 if they accept to release the focus, 0 if they don't.
WIDGET_KEY: 1 if they actually used the key, 0 if not.
WIDGET_HOTKEY: 1 if they actually used the key, 0 if not.
*/
/* Dialog messages */
typedef enum {
DLG_KEY, /* Key before sending to widget */
DLG_INIT, /* Initialize dialog */
DLG_END, /* Shut down dialog */
DLG_ACTION, /* State of check- and radioboxes has changed */
DLG_DRAW, /* Draw dialog on screen */
DLG_FOCUS, /* A widget has got focus */
DLG_UNFOCUS, /* A widget has been unfocused */
DLG_RESIZE, /* Window size has changed */
DLG_POST_KEY, /* The key has been handled */
DLG_IDLE, /* The idle state is active */
DLG_UNHANDLED_KEY, /* Key that no widget handled */
DLG_HOTKEY_HANDLED, /* A widget has got the hotkey */
DLG_VALIDATE /* Dialog is to be closed */
} dlg_msg_t;
/* Dialog callback */
struct Dlg_head;
typedef cb_ret_t (*dlg_cb_fn)(struct Dlg_head *h, dlg_msg_t msg, int parm);
typedef struct Dlg_head {
/* Set by the user */
int flags; /* User flags */
char *help_ctx; /* Name of the help entry */
const int *color; /* Color set */
char *title; /* Title of the dialog */
/* Set and received by the user */
int ret_value; /* Result of run_dlg() */
/* Geometry */
int x, y; /* Position relative to screen origin */
int cols, lines; /* Width and height of the window */
/* Internal flags */
int running;
int mouse_status; /* For the autorepeat status of the mouse */
int refresh_pushed; /* Did the dialog actually run? */
/* Internal variables */
int count; /* Number of widgets */
struct Widget *current; /* Curently active widget */
dlg_cb_fn callback;
void *previous_dialog; /* Pointer to the previously running Dlg_head */
} Dlg_head;
typedef struct Widget Widget;
/* Widget callback */
typedef cb_ret_t (*callback_fn) (Widget *widget, widget_msg_t msg, int parm);
/* Every Widget must have this as it's first element */
struct Widget {
int x, y;
int cols, lines;
int options;
int dlg_id; /* Number of the widget, starting with 0 */
struct Widget *next;
struct Widget *prev;
callback_fn callback; /* The callback function */
mouse_h mouse;
struct Dlg_head *parent;
};
typedef void (*refresh_fn) (void *);
void push_refresh (refresh_fn new_refresh, void *parameter, int flags);
void pop_refresh (void);
/* The options for the widgets */
#define W_WANT_HOTKEY 2
#define W_WANT_CURSOR 4
#define W_WANT_IDLE 8
#define W_IS_INPUT 16
/* draw box in window */
void draw_box (Dlg_head *h, int y, int x, int ys, int xs);
/* doubled line if possible */
void draw_double_box (Dlg_head *h, int y, int x, int ys, int xs);
/* Creates a dialog head */
Dlg_head *create_dlg (int y1, int x1, int lines, int cols,
const int *color_set, dlg_cb_fn callback,
char *help_ctx, const char *title, int flags);
/* The flags: */
#define DLG_REVERSE 32 /* Tab order is opposite to the add order */
#define DLG_WANT_TAB 16 /* Should the tab key be sent to the dialog? */
#define DLG_WANT_IDLE 8 /* Dialog wants idle events */
#define DLG_COMPACT 4 /* Suppress spaces around the frame */
#define DLG_TRYUP 2 /* Try to move two lines up the dialog */
#define DLG_CENTER 1 /* Center the dialog */
#define DLG_NONE 0 /* No options */
int add_widget (Dlg_head *dest, void *Widget);
/* Runs dialog d */
int run_dlg (Dlg_head *d);
void dlg_run_done (Dlg_head *h);
void dlg_process_event (Dlg_head *h, int key, Gpm_Event *event);
void init_dlg (Dlg_head *h);
/* To activate/deactivate the idle message generation */
void set_idle_proc (Dlg_head *d, int enable);
void dlg_redraw (Dlg_head *h);
void destroy_dlg (Dlg_head *h);
void widget_set_size (Widget *widget, int x1, int y1, int x2, int y2);
void dlg_broadcast_msg (Dlg_head *h, widget_msg_t message, int reverse);
void init_widget (Widget *w, int y, int x, int lines, int cols,
callback_fn callback, mouse_h mouse_handler);
/* Default callback for dialogs */
cb_ret_t default_dlg_callback (Dlg_head *h, dlg_msg_t msg, int parm);
/* Default callback for widgets */
cb_ret_t default_proc (widget_msg_t msg, int parm);
/* Default paint routine for dialogs */
void common_dialog_repaint (struct Dlg_head *h);
#define widget_move(w, _y, _x) move(((Widget *)(w))->y + _y, \
((Widget *)(w))->x + _x)
#define dlg_move(h, _y, _x) move(((Dlg_head *)(h))->y + _y, \
((Dlg_head *)(h))->x + _x)
extern Dlg_head *current_dlg;
/* A hook list for idle events */
extern Hook *idle_hook;
static inline cb_ret_t
send_message (Widget *w, widget_msg_t msg, int parm)
{
return (*(w->callback)) (w, msg, parm);
}
void dlg_replace_widget (Dlg_head *h, Widget *old, Widget *new);
int dlg_overlap (Widget *a, Widget *b);
void widget_erase (Widget *);
void dlg_erase (Dlg_head *h);
void dlg_stop (Dlg_head *h);
/* Widget selection */
int dlg_select_widget (Dlg_head *h, void *widget);
void dlg_one_up (Dlg_head *h);
void dlg_one_down (Dlg_head *h);
int dlg_focus (Dlg_head *h);
Widget *find_widget_type (Dlg_head *h, void *callback);
void dlg_select_by_id (Dlg_head *h, int id);
/* Redraw all dialogs */
void do_refresh (void);
#endif /* __DIALOG_H */
/* Sets/clear the specified flag in the options field */
#define widget_option(w,f,i) \
w.options = ((i) ? (w.options | (f)) : (w.options & (~(f))))
#define widget_want_cursor(w,i) widget_option(w, W_WANT_CURSOR, i)
#define widget_want_hotkey(w,i) widget_option(w, W_WANT_HOTKEY, i)
/* Used in load_prompt() */
void update_cursor (Dlg_head *h);
#endif /* MC_DLG_H */

863
src/dlg.c
View File

@ -1,863 +0,0 @@
/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <config.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <stdarg.h>
#include "global.h"
#include "tty.h"
#include "menu.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 "execute.h"
#include "main.h"
#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;
static void dlg_broadcast_msg_to (Dlg_head * h, widget_msg_t message,
int reverse, int flags);
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)
{
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 /* HAVE_SLANG */
}
/* 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 /* HAVE_SLANG */
}
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,
callback_fn callback, mouse_h mouse_handler)
{
w->x = x;
w->y = y;
w->cols = cols;
w->lines = lines;
w->callback = callback;
w->mouse = mouse_handler;
w->parent = 0;
/* Almost all widgets want to put the cursor in a suitable place */
w->options = W_WANT_CURSOR;
}
/* Default callback for widgets */
cb_ret_t
default_proc (widget_msg_t msg, int parm)
{
switch (msg) {
case WIDGET_INIT:
case WIDGET_FOCUS:
case WIDGET_UNFOCUS:
case WIDGET_DRAW:
case WIDGET_DESTROY:
case WIDGET_CURSOR:
case WIDGET_IDLE:
return MSG_HANDLED;
default:
return MSG_NOT_HANDLED;
}
}
/* Clean the dialog area, draw the frame and the title */
void
common_dialog_repaint (struct Dlg_head *h)
{
int space;
space = (h->flags & DLG_COMPACT) ? 0 : 1;
attrset (NORMALC);
dlg_erase (h);
draw_box (h, space, space, h->lines - 2 * space, h->cols - 2 * space);
if (h->title) {
attrset (HOT_NORMALC);
dlg_move (h, space, (h->cols - strlen (h->title)) / 2);
addstr (h->title);
}
}
/* Default dialog callback */
cb_ret_t default_dlg_callback (Dlg_head *h, dlg_msg_t msg, int parm)
{
if (msg == DLG_DRAW && h->color) {
common_dialog_repaint (h);
return MSG_HANDLED;
}
if (msg == DLG_IDLE){
dlg_broadcast_msg_to (h, WIDGET_IDLE, 0, W_WANT_IDLE);
return MSG_HANDLED;
}
return MSG_NOT_HANDLED;
}
Dlg_head *
create_dlg (int y1, int x1, int lines, int cols, const int *color_set,
dlg_cb_fn callback, char *help_ctx, const char *title,
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 = g_new0 (Dlg_head, 1);
new_d->color = color_set;
new_d->help_ctx = help_ctx;
new_d->callback = callback ? callback : default_dlg_callback;
new_d->x = x1;
new_d->y = y1;
new_d->cols = cols;
new_d->lines = lines;
new_d->flags = flags;
/* Strip existing spaces, add one space before and after the title */
if (title) {
char *t;
t = g_strstrip (g_strdup (title));
new_d->title = g_strconcat (" ", t, " ", NULL);
g_free (t);
}
return (new_d);
}
void
set_idle_proc (Dlg_head *d, int enable)
{
if (enable)
d->flags |= DLG_WANT_IDLE;
else
d->flags &= ~DLG_WANT_IDLE;
}
/*
* Insert widget to dialog before current widget. For dialogs populated
* from the bottom, make the widget current. Return widget number.
*/
int
add_widget (Dlg_head *h, void *w)
{
Widget *widget = (Widget *) w;
/* Don't accept 0 widgets, and running dialogs */
if (!widget || h->running)
abort ();
widget->x += h->x;
widget->y += h->y;
widget->parent = h;
widget->dlg_id = h->count++;
if (h->current) {
widget->next = h->current;
widget->prev = h->current->prev;
h->current->prev->next = widget;
h->current->prev = widget;
} else {
widget->prev = widget;
widget->next = widget;
}
if ((h->flags & DLG_REVERSE) || !h->current)
h->current = widget;
return widget->dlg_id;
}
/* broadcast a message to all the widgets in a dialog that have
* the options set to flags.
*/
static void
dlg_broadcast_msg_to (Dlg_head *h, widget_msg_t message, int reverse,
int flags)
{
Widget *p, *first, *wi;
if (!h->current)
return;
if (reverse)
first = p = h->current->prev;
else
first = p = h->current->next;
do {
wi = p;
if (reverse)
p = p->prev;
else
p = p->next;
send_message (wi, message, 0);
} while (first != p);
}
/* broadcast a message to all the widgets in a dialog */
void
dlg_broadcast_msg (Dlg_head *h, widget_msg_t message, int reverse)
{
dlg_broadcast_msg_to (h, message, reverse, ~0);
}
int dlg_focus (Dlg_head *h)
{
if (!h->current)
return 0;
if (send_message (h->current, WIDGET_FOCUS, 0)){
(*h->callback) (h, DLG_FOCUS, 0);
return 1;
}
return 0;
}
static int
dlg_unfocus (Dlg_head *h)
{
if (!h->current)
return 0;
if (send_message (h->current, WIDGET_UNFOCUS, 0)){
(*h->callback) (h, DLG_UNFOCUS, 0);
return 1;
}
return 0;
}
static void
select_a_widget (Dlg_head *h, int down)
{
if (!h->current)
return;
do {
if (down)
h->current = h->current->next;
else
h->current = h->current->prev;
} 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;
}
/* Find the widget with the given callback in the dialog h */
Widget *
find_widget_type (Dlg_head *h, void *callback)
{
Widget *w;
Widget *item;
int i;
if (!h)
return 0;
if (!h->current)
return 0;
w = 0;
for (i = 0, item = h->current; i < h->count; i++, item = item->next) {
if (item->callback == callback) {
w = item;
break;
}
}
return w;
}
/* Find the widget with the given dialog id in the dialog h and select it */
void
dlg_select_by_id (Dlg_head *h, int id)
{
Widget *w, *w_found;
if (!h->current)
return;
w = h->current;
w_found = NULL;
do {
if (w->dlg_id == id) {
w_found = w;
break;
}
w = w->next;
} while (w != h->current);
if (w_found)
dlg_select_widget(h, w_found);
}
void dlg_one_up (Dlg_head *h)
{
Widget *old;
old = h->current;
if (!old)
return;
/* If it accepts unFOCUSion */
if (!dlg_unfocus(h))
return;
select_a_widget (h, 0);
if (dlg_overlap (old, h->current)){
send_message (h->current, WIDGET_DRAW, 0);
send_message (h->current, WIDGET_FOCUS, 0);
}
}
void dlg_one_down (Dlg_head *h)
{
Widget *old;
old = h->current;
if (!old)
return;
if (!dlg_unfocus (h))
return;
select_a_widget (h, 1);
if (dlg_overlap (old, h->current)){
send_message (h->current, WIDGET_DRAW, 0);
send_message (h->current, WIDGET_FOCUS, 0);
}
}
int dlg_select_widget (Dlg_head *h, void *w)
{
if (!h->current)
return 0;
if (dlg_unfocus (h)){
while (h->current != w)
h->current = h->current->next;
while (!dlg_focus (h))
h->current = h->current->next;
return 1;
}
return 0;
}
#define callback(h) (h->current->callback)
void update_cursor (Dlg_head *h)
{
if (!h->current)
return;
if (h->current->options & W_WANT_CURSOR)
send_message (h->current, WIDGET_CURSOR, 0);
else {
Widget *p = h->current;
do {
if (p->options & W_WANT_CURSOR)
if ((*p->callback)(p, WIDGET_CURSOR, 0)){
break;
}
p = p->next;
} while (h->current != p);
}
}
/* Redraw the widgets in reverse order, leaving the current widget
* as the last one
*/
void dlg_redraw (Dlg_head *h)
{
(h->callback)(h, DLG_DRAW, 0);
dlg_broadcast_msg (h, WIDGET_DRAW, 1);
update_cursor (h);
}
static void
dlg_refresh (void *parameter)
{
dlg_redraw ((Dlg_head *) parameter);
}
void dlg_stop (Dlg_head *h)
{
h->running = 0;
}
static inline void dialog_handle_key (Dlg_head *h, int d_key)
{
switch (d_key){
case KEY_LEFT:
case KEY_UP:
dlg_one_up (h);
break;
case KEY_RIGHT:
case KEY_DOWN:
dlg_one_down (h);
break;
case KEY_F(1):
interactive_display (NULL, h->help_ctx);
do_refresh ();
break;
case XCTRL('z'):
suspend_cmd ();
/* Fall through */
case XCTRL('l'):
#ifndef HAVE_SLANG
/* Use this if the refreshes fail */
clr_scr ();
do_refresh ();
#else
touchwin (stdscr);
#endif /* HAVE_SLANG */
mc_refresh ();
doupdate ();
break;
case '\n':
case KEY_ENTER:
h->ret_value = B_ENTER;
h->running = 0;
break;
case ESC_CHAR:
case KEY_F (10):
case XCTRL ('c'):
case XCTRL ('g'):
h->ret_value = B_CANCEL;
dlg_stop (h);
break;
}
}
static int
dlg_try_hotkey (Dlg_head *h, int d_key)
{
Widget *hot_cur;
Widget *previous;
int handled, c;
if (!h->current)
return 0;
/*
* Explanation: we don't send letter hotkeys to other widgets if
* the currently selected widget is an input line
*/
if (h->current->options & W_IS_INPUT) {
if (d_key < 255 && isalpha (d_key))
return 0;
}
/* If it's an alt key, send the message */
c = d_key & ~ALT (0);
if (d_key & ALT (0) && c < 255 && isalpha (c))
d_key = tolower (c);
handled = 0;
if (h->current->options & W_WANT_HOTKEY)
handled = callback (h) (h->current, WIDGET_HOTKEY, d_key);
/* If not used, send hotkey to other widgets */
if (handled)
return handled;
hot_cur = h->current;
/* send it to all widgets */
do {
if (hot_cur->options & W_WANT_HOTKEY)
handled |=
(*hot_cur->callback) (hot_cur, WIDGET_HOTKEY, d_key);
if (!handled)
hot_cur = hot_cur->next;
} while (h->current != hot_cur && !handled);
if (!handled)
return 0;
previous = h->current;
if (!dlg_unfocus (h))
return handled;
h->current = hot_cur;
if (!dlg_focus (h)) {
h->current = previous;
dlg_focus (h);
}
return handled;
}
static int
dlg_key_event (Dlg_head *h, int d_key)
{
int handled;
if (!h->current)
return 0;
/* TAB used to cycle */
if (!(h->flags & DLG_WANT_TAB)
&& (d_key == '\t' || d_key == KEY_BTAB)) {
if (d_key == '\t')
dlg_one_down (h);
else
dlg_one_up (h);
} else {
/* first can dlg_callback handle the key */
handled = (*h->callback) (h, DLG_KEY, d_key);
/* next try the hotkey */
if (!handled)
handled = dlg_try_hotkey (h, d_key);
if (handled)
(*h->callback) (h, DLG_HOTKEY_HANDLED, 0);
/* not used - then try widget_callback */
if (!handled)
handled = callback (h) (h->current, WIDGET_KEY, d_key);
/* not used- try to use the unhandled case */
if (!handled)
handled = (*h->callback) (h, DLG_UNHANDLED_KEY, d_key);
if (!handled)
dialog_handle_key (h, d_key);
(*h->callback) (h, DLG_POST_KEY, d_key);
return handled;
}
return 1;
}
static inline int
dlg_mouse_event (Dlg_head * h, Gpm_Event * event)
{
Widget *item;
Widget *starting_widget = h->current;
Gpm_Event new_event;
int x = event->x;
int y = event->y;
item = starting_widget;
do {
Widget *widget = item;
item = item->next;
if (!((x > widget->x) && (x <= widget->x + widget->cols)
&& (y > widget->y) && (y <= widget->y + widget->lines)))
continue;
new_event = *event;
new_event.x -= widget->x;
new_event.y -= widget->y;
if (!widget->mouse)
return MOU_NORMAL;
return (*widget->mouse) (&new_event, widget);
} while (item != starting_widget);
return MOU_NORMAL;
}
/* Run dialog routines */
/* Init the process */
void init_dlg (Dlg_head *h)
{
int refresh_mode;
/* Initialize dialog manager and widgets */
(*h->callback) (h, DLG_INIT, 0);
dlg_broadcast_msg (h, WIDGET_INIT, 0);
if (h->x == 0 && h->y == 0 && h->cols == COLS && h->lines == LINES)
refresh_mode = REFRESH_COVERS_ALL;
else
refresh_mode = REFRESH_COVERS_PART;
push_refresh (dlg_refresh, h, refresh_mode);
h->refresh_pushed = 1;
h->previous_dialog = current_dlg;
current_dlg = h;
/* Initialize the mouse status */
h->mouse_status = MOU_NORMAL;
/* Select the first widget that takes focus */
while (!dlg_focus (h) && h->current)
h->current = h->current->next;
/* Redraw the screen */
dlg_redraw (h);
h->ret_value = 0;
h->running = 1;
}
/* Shutdown the run_dlg */
void dlg_run_done (Dlg_head *h)
{
if (h->current)
(*h->callback) (h, DLG_END, 0);
current_dlg = (Dlg_head *) h->previous_dialog;
}
void dlg_process_event (Dlg_head *h, int key, Gpm_Event *event)
{
if (key == EV_NONE){
if (got_interrupt ())
key = XCTRL('g');
else
return;
}
if (key == EV_MOUSE)
h->mouse_status = dlg_mouse_event (h, event);
else
dlg_key_event (h, key);
}
static inline void
frontend_run_dlg (Dlg_head *h)
{
int d_key;
Gpm_Event event;
event.x = -1;
while (h->running) {
if (winch_flag)
change_screen_size ();
if (is_idle ()) {
if (idle_hook)
execute_hooks (idle_hook);
while ((h->flags & DLG_WANT_IDLE) && is_idle ())
(*h->callback) (h, DLG_IDLE, 0);
/* Allow terminating the dialog from the idle handler */
if (!h->running)
break;
}
update_cursor (h);
/* Clear interrupt flag */
got_interrupt ();
d_key = get_event (&event, h->mouse_status == MOU_REPEAT, 1);
dlg_process_event (h, d_key, &event);
if (!h->running)
(*h->callback) (h, DLG_VALIDATE, 0);
}
}
/* Standard run dialog routine
* We have to keep this routine small so that we can duplicate it's
* behavior on complex routines like the file routines, this way,
* they can call the dlg_process_event without rewriting all the code
*/
int run_dlg (Dlg_head *h)
{
init_dlg (h);
frontend_run_dlg (h);
dlg_run_done (h);
return h->ret_value;
}
void
destroy_dlg (Dlg_head *h)
{
int i;
Widget *c;
if (h->refresh_pushed)
pop_refresh ();
dlg_broadcast_msg (h, WIDGET_DESTROY, 0);
c = h->current;
for (i = 0; i < h->count; i++) {
c = c->next;
if (h->current) {
g_free (h->current);
}
h->current = c;
}
g_free (h->title);
g_free (h);
do_refresh ();
}
void widget_set_size (Widget *widget, int y, int x, int lines, int cols)
{
widget->x = x;
widget->y = y;
widget->cols = cols;
widget->lines = lines;
}
/* Replace widget old_w for widget new_w in the dialog h */
void
dlg_replace_widget (Dlg_head *h, Widget *old_w, Widget *new_w)
{
int should_focus = 0;
if (!h->current)
return;
if (old_w == h->current)
should_focus = 1;
new_w->parent = h;
new_w->dlg_id = old_w->dlg_id;
if (old_w == old_w->next) {
/* just one widget */
new_w->prev = new_w;
new_w->next = new_w;
} else {
new_w->prev = old_w->prev;
new_w->next = old_w->next;
old_w->prev->next = new_w;
old_w->next->prev = new_w;
}
if (should_focus)
h->current = new_w;
send_message (old_w, WIDGET_DESTROY, 0);
send_message (new_w, WIDGET_INIT, 0);
if (should_focus) {
if (!dlg_focus (h)) {
select_a_widget (h, 1);
}
}
send_message (new_w, WIDGET_DRAW, 0);
}

211
src/dlg.h
View File

@ -1,211 +0,0 @@
#ifndef MC_DLG_H
#define MC_DLG_H
#include "mouse.h"
/* Color constants */
#define FOCUSC h->color[1]
#define NORMALC h->color[0]
#define HOT_NORMALC h->color[2]
#define HOT_FOCUSC h->color[3]
/* Common return values */
#define B_EXIT 0
#define B_CANCEL 1
#define B_ENTER 2
#define B_HELP 3
#define B_USER 100
/* Widget messages */
typedef enum {
WIDGET_INIT, /* Initialize widget */
WIDGET_FOCUS, /* Draw widget in focused state */
WIDGET_UNFOCUS, /* Draw widget in unfocused state */
WIDGET_DRAW, /* Sent to widget to draw themselves */
WIDGET_KEY, /* Sent to widgets on key press */
WIDGET_HOTKEY, /* Sent to widget to catch preprocess key */
WIDGET_DESTROY, /* Sent to widget at destruction time */
WIDGET_CURSOR, /* Sent to widget to position the cursor */
WIDGET_IDLE, /* Send to widgets with options & W_WANT_IDLE*/
} widget_msg_t;
typedef enum {
MSG_NOT_HANDLED,
MSG_HANDLED
} cb_ret_t;
/* Widgets are expected to answer to the following messages:
WIDGET_FOCUS: 1 if the accept the focus, 0 if they do not.
WIDGET_UNFOCUS: 1 if they accept to release the focus, 0 if they don't.
WIDGET_KEY: 1 if they actually used the key, 0 if not.
WIDGET_HOTKEY: 1 if they actually used the key, 0 if not.
*/
/* Dialog messages */
typedef enum {
DLG_KEY, /* Key before sending to widget */
DLG_INIT, /* Initialize dialog */
DLG_END, /* Shut down dialog */
DLG_ACTION, /* State of check- and radioboxes has changed */
DLG_DRAW, /* Draw dialog on screen */
DLG_FOCUS, /* A widget has got focus */
DLG_UNFOCUS, /* A widget has been unfocused */
DLG_RESIZE, /* Window size has changed */
DLG_POST_KEY, /* The key has been handled */
DLG_IDLE, /* The idle state is active */
DLG_UNHANDLED_KEY, /* Key that no widget handled */
DLG_HOTKEY_HANDLED, /* A widget has got the hotkey */
DLG_VALIDATE /* Dialog is to be closed */
} dlg_msg_t;
/* Dialog callback */
struct Dlg_head;
typedef cb_ret_t (*dlg_cb_fn)(struct Dlg_head *h, dlg_msg_t msg, int parm);
typedef struct Dlg_head {
/* Set by the user */
int flags; /* User flags */
char *help_ctx; /* Name of the help entry */
const int *color; /* Color set */
char *title; /* Title of the dialog */
/* Set and received by the user */
int ret_value; /* Result of run_dlg() */
/* Geometry */
int x, y; /* Position relative to screen origin */
int cols, lines; /* Width and height of the window */
/* Internal flags */
int running;
int mouse_status; /* For the autorepeat status of the mouse */
int refresh_pushed; /* Did the dialog actually run? */
/* Internal variables */
int count; /* Number of widgets */
struct Widget *current; /* Curently active widget */
dlg_cb_fn callback;
void *previous_dialog; /* Pointer to the previously running Dlg_head */
} Dlg_head;
typedef struct Widget Widget;
/* Widget callback */
typedef cb_ret_t (*callback_fn) (Widget *widget, widget_msg_t msg, int parm);
/* Every Widget must have this as it's first element */
struct Widget {
int x, y;
int cols, lines;
int options;
int dlg_id; /* Number of the widget, starting with 0 */
struct Widget *next;
struct Widget *prev;
callback_fn callback; /* The callback function */
mouse_h mouse;
struct Dlg_head *parent;
};
/* The options for the widgets */
#define W_WANT_HOTKEY 2
#define W_WANT_CURSOR 4
#define W_WANT_IDLE 8
#define W_IS_INPUT 16
/* draw box in window */
void draw_box (Dlg_head *h, int y, int x, int ys, int xs);
/* doubled line if possible */
void draw_double_box (Dlg_head *h, int y, int x, int ys, int xs);
/* Creates a dialog head */
Dlg_head *create_dlg (int y1, int x1, int lines, int cols,
const int *color_set, dlg_cb_fn callback,
char *help_ctx, const char *title, int flags);
/* The flags: */
#define DLG_REVERSE 32 /* Tab order is opposite to the add order */
#define DLG_WANT_TAB 16 /* Should the tab key be sent to the dialog? */
#define DLG_WANT_IDLE 8 /* Dialog wants idle events */
#define DLG_COMPACT 4 /* Suppress spaces around the frame */
#define DLG_TRYUP 2 /* Try to move two lines up the dialog */
#define DLG_CENTER 1 /* Center the dialog */
#define DLG_NONE 0 /* No options */
int add_widget (Dlg_head *dest, void *Widget);
/* Runs dialog d */
int run_dlg (Dlg_head *d);
void dlg_run_done (Dlg_head *h);
void dlg_process_event (Dlg_head *h, int key, Gpm_Event *event);
void init_dlg (Dlg_head *h);
/* To activate/deactivate the idle message generation */
void set_idle_proc (Dlg_head *d, int enable);
void dlg_redraw (Dlg_head *h);
void destroy_dlg (Dlg_head *h);
void widget_set_size (Widget *widget, int x1, int y1, int x2, int y2);
void dlg_broadcast_msg (Dlg_head *h, widget_msg_t message, int reverse);
void init_widget (Widget *w, int y, int x, int lines, int cols,
callback_fn callback, mouse_h mouse_handler);
/* Default callback for dialogs */
cb_ret_t default_dlg_callback (Dlg_head *h, dlg_msg_t msg, int parm);
/* Default callback for widgets */
cb_ret_t default_proc (widget_msg_t msg, int parm);
/* Default paint routine for dialogs */
void common_dialog_repaint (struct Dlg_head *h);
#define widget_move(w, _y, _x) move(((Widget *)(w))->y + _y, \
((Widget *)(w))->x + _x)
#define dlg_move(h, _y, _x) move(((Dlg_head *)(h))->y + _y, \
((Dlg_head *)(h))->x + _x)
extern Dlg_head *current_dlg;
/* A hook list for idle events */
extern Hook *idle_hook;
static inline cb_ret_t
send_message (Widget *w, widget_msg_t msg, int parm)
{
return (*(w->callback)) (w, msg, parm);
}
void dlg_replace_widget (Dlg_head *h, Widget *old, Widget *new);
int dlg_overlap (Widget *a, Widget *b);
void widget_erase (Widget *);
void dlg_erase (Dlg_head *h);
void dlg_stop (Dlg_head *h);
/* Widget selection */
int dlg_select_widget (Dlg_head *h, void *widget);
void dlg_one_up (Dlg_head *h);
void dlg_one_down (Dlg_head *h);
int dlg_focus (Dlg_head *h);
Widget *find_widget_type (Dlg_head *h, void *callback);
void dlg_select_by_id (Dlg_head *h, int id);
/* Sets/clear the specified flag in the options field */
#define widget_option(w,f,i) \
w.options = ((i) ? (w.options | (f)) : (w.options & (~(f))))
#define widget_want_cursor(w,i) widget_option(w, W_WANT_CURSOR, i)
#define widget_want_hotkey(w,i) widget_option(w, W_WANT_HOTKEY, i)
/* Used in load_prompt() */
void update_cursor (Dlg_head *h);
#endif /* MC_DLG_H */

View File

@ -71,12 +71,10 @@
#include "global.h"
#include "tty.h"
#include "eregex.h"
#include "dialog.h"
#include "setup.h"
/* Needed by query_replace */
#include "color.h"
#include "win.h"
#include "dlg.h"
#include "dialog.h"
#include "widget.h"
#define WANT_WIDGETS
#include "main.h" /* WANT_WIDGETS-> we get the the_hint def */

View File

@ -73,9 +73,8 @@
#include "global.h"
#include "setup.h" /* verbose */
#include "dialog.h" /* do_refresh */
#include "dialog.h" /* do_refresh() */
#include "color.h" /* dialog_colors */
#include "dlg.h" /* B_ENTER */
#include "background.h" /* message_3s */
#include "widget.h" /* WLabel */
#define WANT_WIDGETS

View File

@ -32,10 +32,9 @@
#include "find.h"
/* Dialog manager and widgets */
#include "dlg.h"
#include "dialog.h"
#include "widget.h"
#include "dialog.h" /* For do_refresh() */
#include "dir.h"
#include "panel.h" /* current_panel */
#include "main.h" /* do_cd, try_to_select */

View File

@ -45,12 +45,11 @@
#include "global.h"
#include "tty.h"
#include "color.h"
#include "dialog.h"
#include "win.h"
#include "mouse.h"
#include "key.h" /* For mi_getch() */
#include "key.h" /* For mi_getch() */
#include "help.h"
#include "dlg.h" /* For Dlg_head */
#include "dialog.h" /* For Dlg_head */
#include "widget.h" /* For Widget */
#include "wtools.h" /* For common_dialog_repaint() */

View File

@ -39,9 +39,8 @@
#include "global.h"
#include "tty.h" /* COLS */
#include "color.h" /* dialog_colors */
#include "dlg.h"
#include "dialog.h"
#include "widget.h"
#include "dialog.h" /* do_refresh() */
#include "setup.h" /* For profile_bname */
#include "profile.h" /* Load/save directories hotlist */
#include "wtools.h" /* QuickDialog */

View File

@ -25,7 +25,7 @@
#include "tty.h"
#include "mouse.h" /* Gpm_Event */
#include "color.h"
#include "dlg.h"
#include "dialog.h"
#include "info.h"
#include "dir.h" /* required by panel */
#include "panel.h" /* for the panel structure */

View File

@ -45,10 +45,9 @@
#include "win.h"
#include "color.h"
#include "key.h"
#include "dlg.h"
#include "dialog.h"
#include "widget.h"
#include "command.h"
#include "dialog.h" /* For do_refresh() */
#include "profile.h" /* For sync_profiles() */
#include "mouse.h"
#define WANT_WIDGETS

View File

@ -1,7 +1,7 @@
#ifndef __LAYOUT_H
#define __LAYOUT_H
#include "dlg.h"
#include "dialog.h"
void layout_cmd (void);
void init_curses (void);

View File

@ -32,9 +32,8 @@
#include "tty.h"
#include "win.h"
#include "color.h"
#include "dlg.h"
#include "dialog.h"
#include "widget.h"
#include "dialog.h" /* For do_refresh() */
#include "profile.h" /* Save profile */
#include "key.h"
#include "setup.h"

View File

@ -35,9 +35,8 @@
#include "tty.h"
#include "win.h"
#include "color.h"
#include "dlg.h"
#include "dialog.h"
#include "widget.h"
#include "dialog.h" /* For do_refresh() */
#include "wtools.h"
/* Needed for the extern declarations of integer parameters */

View File

@ -1,7 +1,7 @@
#ifndef __MENU_H
#define __MENU_H
#include "dlg.h"
#include "dialog.h"
#include "widget.h"
typedef void (*callfn) (void);

View File

@ -30,10 +30,9 @@
#include "tty.h"
#include "win.h"
#include "color.h"
#include "dlg.h"
#include "dialog.h"
#include "widget.h"
#include "setup.h" /* For save_setup() */
#include "dialog.h" /* For do_refresh() */
#include "main.h"
#include "profile.h" /* For sync_profiles */

View File

@ -2,7 +2,7 @@
#define __PANEL_H
#include "dir.h" /* dir_list */
#include "dlg.h" /* Widget */
#include "dialog.h" /* Widget */
#define selection(p) (&(p->dir.list[p->selected]))
#define other_panel get_other_panel()

View File

@ -33,9 +33,8 @@
#include "tty.h" /* attrset() */
#include "win.h"
#include "color.h"
#include "dlg.h"
#include "dialog.h"
#include "widget.h"
#include "dialog.h" /* For do_refresh() */
#include "wtools.h" /* For common_dialog_repaint() */
#include "setup.h" /* For profile_bname */
#include "profile.h" /* Load/save directories panelize */

View File

@ -24,7 +24,6 @@
#include <stdio.h>
#include "global.h"
#include "dlg.h"
#include "dialog.h"
#include "widget.h"
#include "wtools.h"

View File

@ -36,7 +36,7 @@
#include "color.h"
#include "wtools.h" /* message() */
#include "dir.h"
#include "dlg.h"
#include "dialog.h"
#include "widget.h"
#include "panel.h"
#include "mouse.h"

View File

@ -1,7 +1,7 @@
#ifndef __TREE_H
#define __TREE_H
#include "dlg.h"
#include "dialog.h"
struct WTree;
typedef struct WTree WTree;

View File

@ -23,7 +23,6 @@
#include "global.h"
#include "tty.h"
#include "dialog.h"
#include "color.h"
#include "dir.h"
#include "panel.h"
@ -38,7 +37,7 @@
#include "edit/edit-widget.h" /* WEdit */
/* For the simple listbox manager */
#include "dlg.h"
#include "dialog.h"
#include "widget.h"
#include "wtools.h"

View File

@ -39,10 +39,9 @@
#include "global.h"
#include "tty.h"
#include "cmd.h" /* For view_other_cmd */
#include "dlg.h" /* Needed by widget.h */
#include "dialog.h" /* Needed by widget.h */
#include "widget.h" /* Needed for buttonbar_new */
#include "color.h"
#include "dialog.h"
#include "mouse.h"
#include "help.h"
#include "key.h" /* For mi_getch() */

View File

@ -35,7 +35,7 @@
#include "tty.h"
#include "color.h"
#include "mouse.h"
#include "dlg.h"
#include "dialog.h"
#include "widget.h"
#include "win.h"
#include "complete.h"

View File

@ -1,7 +1,7 @@
#ifndef __WIDGET_H
#define __WIDGET_H
#include "dlg.h" /* Widget */
#include "dialog.h" /* Widget */
#define C_BOOL 1
#define C_CHANGE 2

View File

@ -26,7 +26,7 @@
#include "tty.h"
#include "color.h"
#include "mouse.h"
#include "dlg.h"
#include "dialog.h"
#include "widget.h"
#include "win.h"
#include "key.h" /* XCTRL and ALT macros */

View File

@ -38,12 +38,11 @@
#include "win.h"
#include "color.h"
#include "mouse.h"
#include "dlg.h"
#include "dialog.h"
#include "widget.h"
#include "menu.h"
#include "wtools.h"
#include "key.h" /* For mi_getch() */
#include "dialog.h" /* For do_refresh() */
#include "complete.h" /* INPUT_COMPLETE_CD */
/* }}} */