📄 dlg.c
字号:
v = 0;
for (i = 0; i < h->count; i++){
if (w == (void *) p->widget){
v = send_message (h, p->widget, msg, par);
break;
}
p = p->next;
}
return v;
}
#define callback(h) (h->current->widget->callback)
void update_cursor (Dlg_head *h)
{
if (!h->current)
return;
if (h->current->widget->options & W_WANT_CURSOR)
send_message (h, h->current->widget, WIDGET_CURSOR, 0);
else {
Widget_Item *p = h->current;
do {
if (p->widget->options & W_WANT_CURSOR)
if ((*p->widget->callback)(h, p->widget, WIDGET_CURSOR, 0)){
x_focus_widget (p);
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, 0, DLG_DRAW);
dlg_broadcast_msg (h, WIDGET_DRAW, 1);
update_cursor (h);
}
void dlg_refresh (void *parameter)
{
dlg_redraw ((Dlg_head *) parameter);
}
void dlg_stop (Dlg_head *h)
{
h->running = 0;
x_dialog_stop (h);
}
static INLINE void dialog_handle_key (Dlg_head *h, int d_key)
{
char *hlpfile;
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):
hlpfile = concat_dir_and_file (mc_home, "mc.hlp");
interactive_display (hlpfile, h->help_ctx);
free (hlpfile);
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
mc_refresh ();
doupdate ();
break;
case '\n':
case KEY_ENTER:
h->ret_value = B_ENTER;
h->running = 0;
x_dialog_stop (h);
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_Item *hot_cur;
Widget_Item *previous;
int handled, c;
extern input_event ();
/*
* Explanation: we don't send letter hotkeys to other widgets if
* the currently selected widget is an input line
*/
if (h->current->widget->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);
#ifdef _OS_NT
/* .ado: fix problem with file_permission under Win95 */
if (d_key == 0) return 0;
#endif
handled = 0;
if (h->current->widget->options & W_WANT_HOTKEY)
handled = callback (h) (h, h->current->widget, 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->widget->options & W_WANT_HOTKEY)
handled |= (*hot_cur->widget->callback)
(h, hot_cur->widget, WIDGET_HOTKEY, d_key);
if (!handled)
hot_cur = hot_cur->next;
} while (h->current != hot_cur && !handled);
if (!handled)
return 0;
(*h->callback) (h, 0, DLG_HOTKEY_HANDLED);
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;
}
void dlg_key_event (Dlg_head *h, int d_key)
{
int handled;
/* TAB used to cycle */
if (!h->raw && (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, d_key, DLG_KEY);
/* next try the hotkey */
if (!handled)
handled = dlg_try_hotkey (h, d_key);
/* not used - then try widget_callback */
if (!handled)
handled |= callback (h)(h, h->current->widget, WIDGET_KEY, d_key);
/* not used- try to use the unhandled case */
if (!handled)
handled |= (*h->callback) (h, d_key, DLG_UNHANDLED_KEY);
if (!handled)
dialog_handle_key (h, d_key);
(*h->callback) (h, d_key, DLG_POST_KEY);
}
}
static INLINE int dlg_mouse_event (Dlg_head *h, Gpm_Event *event)
{
Widget_Item *item;
Widget_Item *starting_widget = h->current;
Gpm_Event new_event;
int x = event->x;
int y = event->y;
int ret_value;
/* kludge for the menubar: start at h->first, not current */
/* Must be carefull in the insertion order to the dlg list */
if (y == 1 && h->has_menubar)
starting_widget = h->first;
item = starting_widget;
do {
Widget *widget = item->widget;
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;
ret_value = widget->mouse ? (*widget->mouse) (&new_event, widget) :
MOU_NORMAL;
return ret_value;
} while (item != starting_widget);
return 0;
}
/* Run dialog routines */
/* Init the process */
void init_dlg (Dlg_head *h)
{
int refresh_mode;
tk_end_frame ();
/* Initialize dialog manager and widgets */
(*h->callback) (h, 0, DLG_INIT);
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;
/* Initialize direction */
if (!h->direction)
h->current = h->first;
if (h->initfocus != NULL)
h->current = h->initfocus;
h->previous_dialog = current_dlg;
current_dlg = h;
/* Initialize the mouse status */
h->mouse_status = 0;
/* Redraw the screen */
dlg_redraw (h);
while (!dlg_focus (h))
h->current = h->current->next;
h->ret_value = 0;
h->running = 1;
x_init_dlg (h);
}
/* Shutdown the run_dlg */
void dlg_run_done (Dlg_head *h)
{
(*h->callback) (h, h->current->dlg_id, DLG_END);
current_dlg = (Dlg_head *) h->previous_dialog;
if (current_dlg)
x_focus_widget (current_dlg->current);
}
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);
}
#ifndef PORT_HAS_FRONTEND_RUN_DLG
static inline void
frontend_run_dlg (Dlg_head *h)
{
int d_key;
Gpm_Event event;
event.x = -1;
while (h->running) {
#if defined(HAVE_SLANG) || NCURSES_VERSION_MAJOR >= 4
/* It does not work with ncurses before 1.9.9g, it will break */
if (winch_flag)
change_screen_size ();
#endif
if (is_idle ()){
if (idle_hook)
execute_hooks (idle_hook);
while (h->send_idle_msg && is_idle ()){
(*h->callback) (h, 0, DLG_IDLE);
}
}
update_cursor (h);
(*h->callback)(h, 0, DLG_PRE_EVENT);
/* Clear interrupt flag */
got_interrupt ();
d_key = get_event (&event, h->mouse_status == MOU_REPEAT, 1);
dlg_process_event (h, d_key, &event);
}
}
#endif /* PORT_HAS_FRONTEND_RUN_DLG */
/* 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
*/
void run_dlg (Dlg_head *h)
{
init_dlg (h);
frontend_run_dlg (h);
dlg_run_done (h);
}
void
destroy_dlg (Dlg_head *h)
{
int i;
Widget_Item *c;
if (h->refresh_pushed)
pop_refresh ();
x_destroy_dlg_start (h);
dlg_broadcast_msg (h, WIDGET_DESTROY, 0);
c = h->current;
for (i = 0; i < h->count; i++){
if (c->widget->destroy)
c->widget->destroy (c->widget);
c = c->next;
free (h->current->widget);
free (h->current);
h->current = c;
}
if (h->title)
free (h->title);
x_destroy_dlg (h);
free (h);
if (refresh_list)
do_refresh ();
}
int std_callback (Dlg_head *h, int Msg, int Par)
{
return 0;
}
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 for widget new in the h dialog */
void dlg_replace_widget (Dlg_head *h, Widget *old, Widget *new)
{
Widget_Item *p = h->current;
int should_focus = 0;
do {
if (p->widget == old){
if (old == h->current->widget)
should_focus = 1;
/* We found the widget */
/* First kill the widget */
new->focused = old->focused;
new->parent = h;
send_message_to (h, old, WIDGET_DESTROY, 0);
(*old->destroy) (old);
/* We insert the new widget */
p->widget = new;
send_message_to (h, new, WIDGET_INIT, 0);
if (should_focus){
if (dlg_focus (h) == 0)
select_a_widget (h, 1);
}
send_message_to (h, new, WIDGET_DRAW, 0);
break;
}
p = p->next;
} while (p != h->current);
}
void widget_redraw (Dlg_head *h, Widget_Item *w)
{
Widget_Item *save = h->current;
h->current = w;
(*w->widget->callback)(h, h->current->widget, WIDGET_DRAW, 0);
h->current = save;
}
/* Returns the index of h->current from h->first */
int dlg_item_number (Dlg_head *h)
{
Widget_Item *p;
int i = 0;
p = h->first;
do {
if (p == h->current)
return i;
i++;
p = p->next;
} while (p != h->first);
fprintf (stderr, "Internal error: current not in dialog list\n\r");
exit (1);
}
int dlg_select_nth_widget (Dlg_head *h, int n)
{
Widget_Item *w;
int i;
w = h->first;
for (i = 0; i < n; i++)
w = w->next;
return dlg_select_widget (h, w->widget);
}
#ifdef HAVE_TK
/* Frames must include a trailing dot */
static void tk_frame_proc (Dlg_head *h, char *frame, int new_frame)
{
char *s = strdup (frame);
if (frame [strlen (frame)-1] != '.'){
fprintf (stderr, "Invalid frame name\n");
exit (1);
}
s [strlen (frame)-1] = 0;
the_frame = frame;
if (new_frame)
tk_evalf ("frame %s.%s", (char *)h->wdata, s);
}
/* If passed a null string, it returns */
void tk_new_frame (Dlg_head *h, char *frame)
{
if (!*frame)
return;
tk_frame_proc (h, frame, 1);
}
void tk_frame (Dlg_head *h, char *frame)
{
tk_frame_proc (h, frame, 0);
}
void tk_end_frame ()
{
the_frame = "";
}
#else
void tk_new_frame (Dlg_head *h, char *x)
{
}
void tk_frame (Dlg_head *h, char *x)
{
}
void tk_end_frame (void)
{
}
#endif
#ifndef PORT_HAS_DIALOG_TITLE
void
x_set_dialog_title (Dlg_head *h, char *title)
{
h->title = strdup(title);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -