diff --git a/lib/widget/dialog-switch.c b/lib/widget/dialog-switch.c index 45393d71f..7fe306002 100644 --- a/lib/widget/dialog-switch.c +++ b/lib/widget/dialog-switch.c @@ -220,9 +220,8 @@ dialog_switch_list (void) const size_t dlg_num = g_list_length (mc_dialogs); int lines, cols; Listbox *listbox; - GList *h; + GList *h, *selected; int i = 0; - int rv; if (mc_global.midnight_shutdown || mc_current == NULL) return; @@ -244,20 +243,14 @@ dialog_switch_list (void) else title = g_strdup (""); - listbox_add_item (listbox->list, LISTBOX_APPEND_BEFORE, get_hotkey (i++), title, NULL, - FALSE); + listbox_add_item (listbox->list, LISTBOX_APPEND_BEFORE, get_hotkey (i++), title, h, FALSE); g_free (title); } - listbox_select_entry (listbox->list, dlg_num - 1 - g_list_position (mc_dialogs, mc_current)); - rv = run_listbox (listbox); - - if (rv >= 0) - { - h = g_list_nth (mc_dialogs, dlg_num - 1 - rv); - dialog_switch_goto (h); - } + selected = run_listbox_with_data (listbox, mc_current); + if (selected != NULL) + dialog_switch_goto (selected); } /* --------------------------------------------------------------------------------------------- */ diff --git a/lib/widget/listbox-window.c b/lib/widget/listbox-window.c index 23f690c91..bbf1dc5fa 100644 --- a/lib/widget/listbox-window.c +++ b/lib/widget/listbox-window.c @@ -138,3 +138,38 @@ run_listbox (Listbox * l) } /* --------------------------------------------------------------------------------------------- */ + +/** + * A variant of run_listbox() which is more convenient to use when we + * need to select arbitrary 'data'. + * + * @param select the item to select initially, by its 'data'. Optional. + * @return the 'data' of the item selected, or NULL if none selected. + */ +void * +run_listbox_with_data (Listbox * l, const void *select) +{ + void *val = NULL; + + if (select != NULL) + listbox_select_entry (l->list, listbox_search_data (l->list, select)); + + if (dlg_run (l->dlg) != B_CANCEL) + { + WLEntry *e; + e = listbox_get_nth_item (l->list, l->list->pos); + if (e != NULL) + { + /* The assert guards against returning a soon-to-be deallocated + * pointer (as in listbox_add_item(..., TRUE)). */ + g_assert (!e->free_data); + val = e->data; + } + } + + dlg_destroy (l->dlg); + g_free (l); + return val; +} + +/* --------------------------------------------------------------------------------------------- */ diff --git a/lib/widget/listbox-window.h b/lib/widget/listbox-window.h index f1a3ece89..5a6082956 100644 --- a/lib/widget/listbox-window.h +++ b/lib/widget/listbox-window.h @@ -29,6 +29,7 @@ Listbox *create_listbox_window_centered (int center_y, int center_x, int lines, const char *title, const char *help); Listbox *create_listbox_window (int lines, int cols, const char *title, const char *help); int run_listbox (Listbox * l); +void *run_listbox_with_data (Listbox * l, const void *select); /*** inline functions ****************************************************************************/ diff --git a/lib/widget/listbox.c b/lib/widget/listbox.c index b9f294b91..378a3af8a 100644 --- a/lib/widget/listbox.c +++ b/lib/widget/listbox.c @@ -570,6 +570,9 @@ listbox_new (int y, int x, int height, int width, gboolean deletable, lcback_fn /* --------------------------------------------------------------------------------------------- */ +/** + * Finds item by its label. + */ int listbox_search_text (WListbox * l, const char *text) { @@ -592,6 +595,31 @@ listbox_search_text (WListbox * l, const char *text) /* --------------------------------------------------------------------------------------------- */ +/** + * Finds item by its 'data' slot. + */ +int +listbox_search_data (WListbox * l, const void *data) +{ + if (!listbox_is_empty (l)) + { + int i; + GList *le; + + for (i = 0, le = g_queue_peek_head_link (l->list); le != NULL; i++, le = g_list_next (le)) + { + WLEntry *e = LENTRY (le->data); + + if (e->data == data) + return i; + } + } + + return (-1); +} + +/* --------------------------------------------------------------------------------------------- */ + /* Selects the first entry and scrolls the list to the top */ void listbox_select_first (WListbox * l) diff --git a/lib/widget/listbox.h b/lib/widget/listbox.h index 6bb5269cf..396678736 100644 --- a/lib/widget/listbox.h +++ b/lib/widget/listbox.h @@ -64,6 +64,7 @@ extern const global_keymap_t *listbox_map; WListbox *listbox_new (int y, int x, int height, int width, gboolean deletable, lcback_fn callback); int listbox_search_text (WListbox * l, const char *text); +int listbox_search_data (WListbox * l, const void *data); void listbox_select_first (WListbox * l); void listbox_select_last (WListbox * l); void listbox_select_entry (WListbox * l, int dest); diff --git a/src/editor/editwidget.c b/src/editor/editwidget.c index 515a58674..732db41e8 100644 --- a/src/editor/editwidget.c +++ b/src/editor/editwidget.c @@ -319,13 +319,12 @@ get_hotkey (int n) static void edit_window_list (const WDialog * h) { - const size_t offset = 2; /* skip menu and buttonbar */ - const size_t dlg_num = g_list_length (h->widgets) - offset; + 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; - int rv; lines = MIN ((size_t) (LINES * 2 / 3), dlg_num); cols = COLS * 2 / 3; @@ -346,18 +345,13 @@ edit_window_list (const WDialog * h) 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), NULL, FALSE); + str_term_trim (fname, WIDGET (listbox->list)->cols - 2), e, FALSE); g_free (fname); } - rv = g_list_position (h->widgets, h->current) - offset; - listbox_select_entry (listbox->list, rv); - rv = run_listbox (listbox); - if (rv >= 0) - { - w = g_list_nth (h->widgets, rv + offset); - widget_select (w->data); - } + selected = run_listbox_with_data (listbox, h->current->data); + if (selected != NULL) + widget_select (WIDGET (selected)); } /* --------------------------------------------------------------------------------------------- */