Esempio n. 1
0
void
widget_replace (Widget * old_w, Widget * new_w)
{
    WDialog *h = old_w->owner;
    gboolean should_focus = FALSE;
    GList *holder;

    if (h->widgets == NULL)
        return;

    if (h->current == NULL)
        h->current = h->widgets;

    /* locate widget position in the list */
    if (old_w == h->current->data)
        holder = h->current;
    else
        holder = g_list_find (h->widgets, old_w);

    /* if old widget is focused, we should focus the new one... */
    if (widget_get_state (old_w, WST_FOCUSED))
        should_focus = TRUE;
    /* ...but if new widget isn't selectable, we cannot focus it */
    if (!widget_get_options (new_w, WOP_SELECTABLE))
        should_focus = FALSE;

    /* if new widget isn't selectable, select other widget before replace */
    if (!should_focus)
    {
        GList *l;

        for (l = dlg_get_widget_next_of (holder);
             !widget_get_options (WIDGET (l->data), WOP_SELECTABLE)
             && !widget_get_state (WIDGET (l->data), WST_DISABLED); l = dlg_get_widget_next_of (l))
            ;

        widget_select (WIDGET (l->data));
    }

    /* replace widget */
    new_w->owner = h;
    new_w->id = old_w->id;
    holder->data = new_w;

    send_message (old_w, NULL, MSG_DESTROY, 0, NULL);
    send_message (new_w, NULL, MSG_INIT, 0, NULL);

    if (should_focus)
        widget_select (new_w);
    else
        widget_redraw (new_w);
}
Esempio n. 2
0
static gboolean
learn_move (gboolean right)
{
    int i, totalcols;

    totalcols = (learn_total - 1) / ROWS + 1;
    for (i = 0; i < learn_total; i++)
        if (learnkeys[i].button == WIDGET (learn_dlg->current->data))
        {
            if (right)
            {
                if (i < learn_total - ROWS)
                    i += ROWS;
                else
                    i %= ROWS;
            }
            else
            {
                if (i / ROWS != 0)
                    i -= ROWS;
                else if (i + (totalcols - 1) * ROWS >= learn_total)
                    i += (totalcols - 2) * ROWS;
                else
                    i += (totalcols - 1) * ROWS;
            }
            widget_select (learnkeys[i].button);
            return TRUE;
        }

    return FALSE;
}
Esempio n. 3
0
unsigned long
add_widget_autopos (WDialog * h, void *w, widget_pos_flags_t pos_flags, const void *before)
{
    Widget *wh = WIDGET (h);
    Widget *widget;
    GList *new_current;

    /* Don't accept 0 widgets */
    if (w == NULL)
        abort ();

    widget = WIDGET (w);

    if ((pos_flags & WPOS_CENTER_HORZ) != 0)
        widget->x = (wh->cols - widget->cols) / 2;
    widget->x += wh->x;

    if ((pos_flags & WPOS_CENTER_VERT) != 0)
        widget->y = (wh->lines - widget->lines) / 2;
    widget->y += wh->y;

    widget->owner = h;
    widget->pos_flags = pos_flags;
    widget->id = h->widget_id++;

    if (h->widgets == NULL || before == NULL)
    {
        h->widgets = g_list_append (h->widgets, widget);
        new_current = g_list_last (h->widgets);
    }
    else
    {
        GList *b;

        b = g_list_find (h->widgets, before);

        /* don't accept widget not from dialog. This shouldn't happen */
        if (b == NULL)
            abort ();

        b = g_list_next (b);
        h->widgets = g_list_insert_before (h->widgets, b, widget);
        if (b != NULL)
            new_current = g_list_previous (b);
        else
            new_current = g_list_last (h->widgets);
    }

    /* widget has been added at runtime */
    if (widget_get_state (wh, WST_ACTIVE))
    {
        send_message (widget, NULL, MSG_INIT, 0, NULL);
        widget_select (widget);
    }
    else
        h->current = new_current;

    return widget->id;
}
Esempio n. 4
0
void
widget_toggle( Ewler_Widget *w )
{
	if( w->selected )
		widget_deselect(w);
	else
		widget_select(w);
}
Esempio n. 5
0
void
dlg_select_by_id (const WDialog * h, unsigned long id)
{
    Widget *w;

    w = dlg_find_by_id (h, id);
    if (w != NULL)
        widget_select (w);
}
Esempio n. 6
0
/**
 * Handle mouse events of editor screen.
 *
 * @param w Widget object (the editor)
 * @param msg mouse event message
 * @param event mouse event data
 */
static void
edit_dialog_mouse_callback (Widget * w, mouse_msg_t msg, mouse_event_t * event)
{
    gboolean unhandled = TRUE;

    if (msg == MSG_MOUSE_DOWN && event->y == 0)
    {
        WDialog *h = DIALOG (w);
        WMenuBar *b;

        b = find_menubar (h);

        if (!widget_get_state (WIDGET (b), WST_FOCUSED))
        {
            /* menubar */

            GList *l;
            GList *top = NULL;
            int x;

            /* Try find top fullscreen window */
            for (l = h->widgets; l != NULL; l = g_list_next (l))
                if (edit_widget_is_editor (CONST_WIDGET (l->data))
                    && ((WEdit *) l->data)->fullscreen)
                    top = l;

            /* Handle fullscreen/close buttons in the top line */
            x = w->cols - 6;

            if (top != NULL && event->x >= x)
            {
                WEdit *e = (WEdit *) top->data;

                if (top != h->current)
                {
                    /* Window is not active. Activate it */
                    widget_select (WIDGET (e));
                }

                /* Handle buttons */
                if (event->x - x <= 2)
                    edit_toggle_fullscreen (e);
                else
                    send_message (h, NULL, MSG_ACTION, CK_Close, NULL);

                unhandled = FALSE;
            }

            if (unhandled)
                menubar_activate (b, drop_menus, -1);
        }
    }

    /* Continue handling of unhandled event in window or menu */
    event->result.abort = unhandled;
}
Esempio n. 7
0
static int
learn_button (WButton * button, int action)
{
    WDialog *d;
    char *seq;

    (void) button;

    d = create_message (D_ERROR, _("Teach me a key"),
                        _("Please press the %s\n"
                          "and then wait until this message disappears.\n\n"
                          "Then, press it again to see if OK appears\n"
                          "next to its button.\n\n"
                          "If you want to escape, press a single Escape key\n"
                          "and wait as well."), _(key_name_conv_tab[action - B_USER].longname));
    mc_refresh ();
    if (learnkeys[action - B_USER].sequence != NULL)
        MC_PTR_FREE (learnkeys[action - B_USER].sequence);

    seq = learn_key ();
    if (seq != NULL)
    {
        /* Esc hides the dialog and do not allow definitions of
         * regular characters
         */
        gboolean seq_ok = FALSE;

        if (*seq != '\0' && strcmp (seq, "\\e") != 0 && strcmp (seq, "\\e\\e") != 0
            && strcmp (seq, "^m") != 0 && strcmp (seq, "^i") != 0
            && (seq[1] != '\0' || *seq < ' ' || *seq > '~'))
        {
            learnchanged = TRUE;
            learnkeys[action - B_USER].sequence = seq;
            seq = convert_controls (seq);
            seq_ok = define_sequence (key_name_conv_tab[action - B_USER].code, seq, MCKEY_NOACTION);
        }

        if (!seq_ok)
            message (D_NORMAL, _("Cannot accept this key"), _("You have entered \"%s\""), seq);

        g_free (seq);
    }

    dlg_run_done (d);
    dlg_destroy (d);

    widget_select (learnkeys[action - B_USER].button);

    return 0;                   /* Do not kill learn_dlg */
}
Esempio n. 8
0
static inline void
edit_quit (WDialog * h)
{
    GList *l;
    WEdit *e = NULL;
    GSList *m = NULL;
    GSList *me;

    /* don't stop the dialog before final decision */
    widget_set_state (WIDGET (h), WST_ACTIVE, TRUE);

    /* check window state and get modified files */
    for (l = h->widgets; l != NULL; l = g_list_next (l))
        if (edit_widget_is_editor (CONST_WIDGET (l->data)))
        {
            e = (WEdit *) l->data;

            if (e->drag_state != MCEDIT_DRAG_NONE)
            {
                edit_restore_size (e);
                g_slist_free (m);
                return;
            }

            /* create separate list because widget_select()
               changes the window position in Z order */
            if (e->modified)
                m = g_slist_prepend (m, l->data);
        }

    for (me = m; me != NULL; me = g_slist_next (me))
    {
        e = (WEdit *) me->data;

        widget_select (WIDGET (e));

        if (!edit_ok_to_exit (e))
            break;
    }

    /* if all files were checked, quit editor */
    if (me == NULL)
        dlg_stop (h);

    g_slist_free (m);
}
Esempio n. 9
0
static EWL_CALLBACK_DEFN(fg_realize)
{
	Ewler_Widget *ewler_w = user_data;

	if( ewler_w->selected )
		widget_select(ewler_w);
	else
		widget_deselect(ewler_w);

	edje_object_signal_callback_add(w->theme_object, "down", "top_left",
																	fg_part_down, user_data);
	edje_object_signal_callback_add(w->theme_object, "up", "top_left",
																	fg_part_up, user_data);
	edje_object_signal_callback_add(w->theme_object, "down", "top_middle",
																	fg_part_down, user_data);
	edje_object_signal_callback_add(w->theme_object, "up", "top_middle",
																	fg_part_up, user_data);
	edje_object_signal_callback_add(w->theme_object, "down", "top_right",
																	fg_part_down, user_data);
	edje_object_signal_callback_add(w->theme_object, "up", "top_right",
																	fg_part_up, user_data);

	edje_object_signal_callback_add(w->theme_object, "down", "middle_right",
																	fg_part_down, user_data);
	edje_object_signal_callback_add(w->theme_object, "up", "middle_right",
																	fg_part_up, user_data);
	
	edje_object_signal_callback_add(w->theme_object, "down", "bottom_right",
																	fg_part_down, user_data);
	edje_object_signal_callback_add(w->theme_object, "up", "bottom_right",
																	fg_part_up, user_data);
	edje_object_signal_callback_add(w->theme_object, "down", "bottom_middle",
																	fg_part_down, user_data);
	edje_object_signal_callback_add(w->theme_object, "up", "bottom_middle",
																	fg_part_up, user_data);
	edje_object_signal_callback_add(w->theme_object, "down", "bottom_left",
																	fg_part_down, user_data);
	edje_object_signal_callback_add(w->theme_object, "up", "bottom_left",
																	fg_part_up, user_data);

	edje_object_signal_callback_add(w->theme_object, "down", "middle_left",
																	fg_part_down, user_data);
	edje_object_signal_callback_add(w->theme_object, "up", "middle_left",
																	fg_part_up, user_data);
}
Esempio n. 10
0
static void
dlg_select_next_or_prev (WDialog * h, gboolean next)
{
    if (h->widgets != NULL && h->current != NULL)
    {
        GList *l = h->current;
        Widget *w;

        do
        {
            l = dlg_get_next_or_prev_of (l, next);
            w = WIDGET (l->data);
        }
        while ((widget_get_state (w, WST_DISABLED) || !widget_get_options (w, WOP_SELECTABLE))
               && l != h->current);

        widget_select (l->data);
    }
}
Esempio n. 11
0
static void
listbox_mouse_callback (Widget * w, mouse_msg_t msg, mouse_event_t * event)
{
    WListbox *l = LISTBOX (w);
    int old_pos;

    old_pos = l->pos;

    switch (msg)
    {
    case MSG_MOUSE_DOWN:
        widget_select (w);
        listbox_select_entry (l, listbox_y_pos (l, event->y));
        break;

    case MSG_MOUSE_SCROLL_UP:
        listbox_back (l, FALSE);
        break;

    case MSG_MOUSE_SCROLL_DOWN:
        listbox_fwd (l, FALSE);
        break;

    case MSG_MOUSE_DRAG:
        event->result.repeat = TRUE;    /* It'd be functional even without this. */
        listbox_select_entry (l, listbox_y_pos (l, event->y));
        break;

    case MSG_MOUSE_CLICK:
        /* We don't call listbox_select_entry() here: MSG_MOUSE_DOWN/DRAG did this already. */
        if (event->count == GPM_DOUBLE) /* Double click */
            listbox_do_action (l);
        break;

    default:
        break;
    }

    /* If the selection has changed, we redraw the widget and notify the dialog. */
    if (l->pos != old_pos)
        listbox_on_change (l);
}
Esempio n. 12
0
static void
edit_window_list (const WDialog * h)
{
    const size_t dlg_num = g_list_length (h->widgets) - 2;      /* 2 = skip menu and buttonbar */
    int lines, cols;
    Listbox *listbox;
    GList *w;
    WEdit *selected;
    int i = 0;

    lines = MIN ((size_t) (LINES * 2 / 3), dlg_num);
    cols = COLS * 2 / 3;

    listbox = create_listbox_window (lines, cols, _("Open files"), "[Open files]");

    for (w = h->widgets; w != NULL; w = g_list_next (w))
        if (edit_widget_is_editor (CONST_WIDGET (w->data)))
        {
            WEdit *e = (WEdit *) w->data;
            char *fname;

            if (e->filename_vpath == NULL)
                fname = g_strdup_printf ("%c [%s]", e->modified ? '*' : ' ', _("NoName"));
            else
                fname =
                    g_strdup_printf ("%c%s", e->modified ? '*' : ' ',
                                     vfs_path_as_str (e->filename_vpath));

            listbox_add_item (listbox->list, LISTBOX_APPEND_AT_END, get_hotkey (i++),
                              str_term_trim (fname, WIDGET (listbox->list)->cols - 2), e, FALSE);
            g_free (fname);
        }

    selected = run_listbox_with_data (listbox, h->current->data);
    if (selected != NULL)
        widget_select (WIDGET (selected));
}
Esempio n. 13
0
static void
init_panelize (void)
{
    struct
    {
        int ret_cmd;
        button_flags_t flags;
        const char *text;
    } panelize_but[] =
    {
        /* *INDENT-OFF* */
        { B_ENTER, DEFPUSH_BUTTON, N_("Pane&lize") },
        { B_REMOVE, NORMAL_BUTTON, N_("&Remove") },
        { B_ADD, NORMAL_BUTTON, N_("&Add new") },
        { B_CANCEL, NORMAL_BUTTON, N_("&Cancel") }
        /* *INDENT-ON* */
    };

    size_t i;
    int blen;
    int panelize_cols;
    struct panelize *current;
    int x, y;

    last_listitem = 0;

    do_refresh ();

    i = G_N_ELEMENTS (panelize_but);
    blen = i - 1;               /* gaps between buttons */
    while (i-- != 0)
    {
#ifdef ENABLE_NLS
        panelize_but[i].text = _(panelize_but[i].text);
#endif
        blen += str_term_width1 (panelize_but[i].text) + 3 + 1;
        if (panelize_but[i].flags == DEFPUSH_BUTTON)
            blen += 2;
    }

    panelize_cols = COLS - 6;
    panelize_cols = MAX (panelize_cols, blen + 4);

    panelize_dlg =
        dlg_create (TRUE, 0, 0, 20, panelize_cols, WPOS_CENTER, FALSE, dialog_colors,
                    panelize_callback, NULL, "[External panelize]", _("External panelize"));

    /* add listbox to the dialogs */
    y = UY;
    add_widget (panelize_dlg, groupbox_new (y++, UX, 12, panelize_cols - UX * 2, ""));

    l_panelize = listbox_new (y, UX + 1, 10, panelize_cols - UX * 2 - 2, FALSE, NULL);
    for (current = panelize; current != NULL; current = current->next)
        listbox_add_item (l_panelize, LISTBOX_APPEND_AT_END, 0, current->label, current, FALSE);
    listbox_select_entry (l_panelize, listbox_search_text (l_panelize, _("Other command")));
    add_widget (panelize_dlg, l_panelize);

    y += WIDGET (l_panelize)->lines + 1;
    add_widget (panelize_dlg, label_new (y++, UX, _("Command")));
    pname =
        input_new (y++, UX, input_colors, panelize_cols - UX * 2, "", "in",
                   INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_HOSTNAMES | INPUT_COMPLETE_COMMANDS |
                   INPUT_COMPLETE_VARIABLES | INPUT_COMPLETE_USERNAMES | INPUT_COMPLETE_CD |
                   INPUT_COMPLETE_SHELL_ESC);
    add_widget (panelize_dlg, pname);



    add_widget (panelize_dlg, hline_new (y++, -1, -1));

    x = (panelize_cols - blen) / 2;
    for (i = 0; i < G_N_ELEMENTS (panelize_but); i++)
    {
        WButton *b;

        b = button_new (y, x,
                        panelize_but[i].ret_cmd, panelize_but[i].flags, panelize_but[i].text, NULL);
        add_widget (panelize_dlg, b);

        x += button_get_len (b) + 1;
    }

    widget_select (WIDGET (l_panelize));
}
Esempio n. 14
0
/**
 * Handle mouse events of editor window
 *
 * @param w Widget object (the editor window)
 * @param msg mouse event message
 * @param event mouse event data
 */
static void
edit_mouse_callback (Widget * w, mouse_msg_t msg, mouse_event_t * event)
{
    WEdit *edit = (WEdit *) w;
    /* buttons' distance from right edge */
    int dx = edit->fullscreen ? 0 : 2;
    /* location of 'Close' and 'Toggle fullscreen' pictograms */
    int close_x, toggle_fullscreen_x;

    close_x = (w->cols - 1) - dx - 1;
    toggle_fullscreen_x = close_x - 3;

    if (edit->drag_state != MCEDIT_DRAG_NONE)
    {
        /* window is being resized/moved */
        edit_mouse_handle_move_resize (w, msg, event);
        return;
    }

    /* If it's the last line on the screen, we abort the event to make the
     * system channel it to the overlapping buttonbar instead. We have to do
     * this because a WEdit has the WOP_TOP_SELECT flag, which makes it above
     * the buttonbar in Z-order. */
    if (msg == MSG_MOUSE_DOWN && (event->y + w->y == LINES - 1))
    {
        event->result.abort = TRUE;
        return;
    }

    switch (msg)
    {
    case MSG_MOUSE_DOWN:
        widget_select (w);
        edit_update_curs_row (edit);
        edit_update_curs_col (edit);

        if (!edit->fullscreen)
        {
            if (event->y == 0)
            {
                if (event->x >= close_x - 1 && event->x <= close_x + 1)
                    ;           /* do nothing (see MSG_MOUSE_CLICK) */
                else if (event->x >= toggle_fullscreen_x - 1 && event->x <= toggle_fullscreen_x + 1)
                    ;           /* do nothing (see MSG_MOUSE_CLICK) */
                else
                {
                    /* start window move */
                    edit_execute_cmd (edit, CK_WindowMove, -1);
                    edit_update_screen (edit);  /* Paint the buttonbar over our possibly overlapping frame. */
                    edit->drag_state_start = event->x;
                }
                break;
            }

            if (event->y == w->lines - 1 && event->x == w->cols - 1)
            {
                /* bottom-right corner -- start window resize */
                edit_execute_cmd (edit, CK_WindowResize, -1);
                break;
            }
        }

        MC_FALLTHROUGH;         /* to start/stop text selection */

    case MSG_MOUSE_UP:
        edit_update_cursor (edit, event);
        edit_total_update (edit);
        break;

    case MSG_MOUSE_CLICK:
        if (event->y == 0)
        {
            if (event->x >= close_x - 1 && event->x <= close_x + 1)
                send_message (w->owner, NULL, MSG_ACTION, CK_Close, NULL);
            else if (event->x >= toggle_fullscreen_x - 1 && event->x <= toggle_fullscreen_x + 1)
                edit_toggle_fullscreen (edit);
            else if (!edit->fullscreen && event->count == GPM_DOUBLE)
                /* double click on top line (toggle fullscreen) */
                edit_toggle_fullscreen (edit);
        }
        else if (event->count == GPM_DOUBLE)
        {
            /* double click */
            edit_mark_current_word_cmd (edit);
            edit_total_update (edit);
        }
        else if (event->count == GPM_TRIPLE)
        {
            /* triple click: works in GPM only, not in xterm */
            edit_mark_current_line_cmd (edit);
            edit_total_update (edit);
        }
        break;

    case MSG_MOUSE_DRAG:
        edit_update_cursor (edit, event);
        edit_total_update (edit);
        break;

    case MSG_MOUSE_SCROLL_UP:
        edit_move_up (edit, 2, TRUE);
        edit_total_update (edit);
        break;

    case MSG_MOUSE_SCROLL_DOWN:
        edit_move_down (edit, 2, TRUE);
        edit_total_update (edit);
        break;

    default:
        break;
    }
}
Esempio n. 15
0
static gboolean
learn_check_key (int c)
{
    int i;

    for (i = 0; i < learn_total; i++)
    {
        if (key_name_conv_tab[i].code != c || learnkeys[i].ok)
            continue;

        widget_select (learnkeys[i].button);
        /* TRANSLATORS: This label appears near learned keys.  Keep it short.  */
        label_set_text (LABEL (learnkeys[i].label), _("OK"));
        learnkeys[i].ok = TRUE;
        learnok++;
        if (learnok >= learn_total)
        {
            learn_dlg->ret_value = B_CANCEL;
            if (learnchanged)
            {
                if (query_dialog (learn_title,
                                  _
                                  ("It seems that all your keys already\n"
                                   "work fine. That's great."), D_ERROR, 2,
                                  _("&Save"), _("&Discard")) == 0)
                    learn_dlg->ret_value = B_ENTER;
            }
            else
            {
                message (D_ERROR, learn_title, "%s",
                         _
                         ("Great! You have a complete terminal database!\n"
                          "All your keys work well."));
            }
            dlg_stop (learn_dlg);
        }
        return TRUE;
    }

    switch (c)
    {
    case KEY_LEFT:
    case 'h':
        return learn_move (FALSE);
    case KEY_RIGHT:
    case 'l':
        return learn_move (TRUE);
    case 'j':
        dlg_select_next_widget (learn_dlg);
        return TRUE;
    case 'k':
        dlg_select_prev_widget (learn_dlg);
        return TRUE;
    default:
        break;
    }

    /* Prevent from disappearing if a non-defined sequence is pressed
       and contains a button hotkey.  Only recognize hotkeys with ALT.  */
    return (c < 255 && g_ascii_isalnum (c));
}
Esempio n. 16
0
static EWL_CALLBACK_DEFN(realize)
{
	Ewler_Widget *ewler_w = user_data;
	Ecore_List *elems;
	Ewler_Widget_Elem *elem;
	char *name;
	void *args[4];
	int i, n;

	if( ewler_w->selected )
		widget_select(ewler_w);

	elems = ecore_hash_keys(ewler_w->elems);

	while( (name = ecore_list_next(elems)) ) {
		elem = ecore_hash_get(ewler_w->elems, name);

		if( elem->spec->get_func )
			switch( elem->spec->type ) {
				case EWLER_SPEC_ELEM_INT:
					elem->info.ivalue = (int) elem->spec->get_func(ewler_w->w);

					if( elem->entry ) {
						ewl_text_text_set(EWL_TEXT(elem->entry), "");
						ewl_text_text_append(EWL_TEXT(elem->entry), elem_to_s(elem));
					}
					break;
				case EWLER_SPEC_ELEM_STRING:
					IF_FREE(elem->info.svalue);
					elem->info.svalue = (char *) elem->spec->get_func(ewler_w->w);

					if( elem->entry )
						ewl_text_text_set(EWL_TEXT(elem->entry), elem_to_s(elem));
					break;
				case EWLER_SPEC_ELEM_STRUCT:
					n = elem->spec->info.children->nodes;
					for( i=0;i<n;i++ )
						args[i] = elem_at_index(elem->info.children, i);

					switch( n ) {
						case 1: elem->spec->get_func(ewler_w->w, args[0]); break;
						case 2: elem->spec->get_func(ewler_w->w, args[0], args[1]); break;
						case 3:
							elem->spec->get_func(ewler_w->w, args[0], args[1], args[2]);
							break;
						case 4:
							elem->spec->get_func(ewler_w->w,
																	 args[0], args[1], args[2], args[3]);
							break;
						/* haven't seen anything higher just yet */
					}
					break;
				case EWLER_SPEC_ELEM_ENUM:
					elem->info.evalue = (int) elem->spec->get_func(ewler_w->w);

					if( elem->entry ) {
						Ewl_Widget *item;

						item = ecore_hash_get(elem->items, (void *) elem->info.evalue);
						ewl_combo_selected_set(EWL_COMBO(elem->entry), item);
					}
					break;
				default: break;
			}
		else if(elem->spec->type == EWLER_SPEC_ELEM_STRUCT)
			/* iterate through children, since we don't have a mass get */;
	}

	ecore_list_destroy(elems);
}
Esempio n. 17
0
static cb_ret_t
dlg_try_hotkey (WDialog * h, int d_key)
{
    GList *hot_cur;
    Widget *current;
    cb_ret_t handled;
    int c;

    if (h->widgets == NULL)
        return MSG_NOT_HANDLED;

    if (h->current == NULL)
        h->current = h->widgets;

    /*
     * Explanation: we don't send letter hotkeys to other widgets if
     * the currently selected widget is an input line
     */

    current = WIDGET (h->current->data);

    if (widget_get_state (current, WST_DISABLED))
        return MSG_NOT_HANDLED;

    if (widget_get_options (current, WOP_IS_INPUT))
    {
        /* skip ascii control characters, anything else can valid character in
         * some encoding */
        if (d_key >= 32 && d_key < 256)
            return MSG_NOT_HANDLED;
    }

    /* If it's an alt key, send the message */
    c = d_key & ~ALT (0);
    if (d_key & ALT (0) && g_ascii_isalpha (c))
        d_key = g_ascii_tolower (c);

    handled = MSG_NOT_HANDLED;
    if (widget_get_options (current, WOP_WANT_HOTKEY))
        handled = send_message (current, NULL, MSG_HOTKEY, d_key, NULL);

    /* If not used, send hotkey to other widgets */
    if (handled == MSG_HANDLED)
        return MSG_HANDLED;

    hot_cur = dlg_get_widget_next_of (h->current);

    /* send it to all widgets */
    while (h->current != hot_cur && handled == MSG_NOT_HANDLED)
    {
        current = WIDGET (hot_cur->data);

        if (widget_get_options (current, WOP_WANT_HOTKEY)
            && !widget_get_state (current, WST_DISABLED))
            handled = send_message (current, NULL, MSG_HOTKEY, d_key, NULL);

        if (handled == MSG_NOT_HANDLED)
            hot_cur = dlg_get_widget_next_of (hot_cur);
    }

    if (handled == MSG_HANDLED)
        widget_select (WIDGET (hot_cur->data));

    return handled;
}