Ticket #4165: MultiSearch_5.3-1_final.patch
File MultiSearch_5.3-1_final.patch, 72.9 KB (added by psprint, 4 years ago) |
---|
-
lib/keybind.c
From ab01125b00e5f1c831efc97c4235acc64d8fd0e1 Mon Sep 17 00:00:00 2001 From: Sebastian Gniazdowski <sgniazdowski@gmail.com> Date: Wed, 20 Jan 2021 13:59:46 -0600 Subject: =?UTF-8?q?MultiSearch=20=E2=80=93=C2=A0an=20AND-chained=20multi-w?= =?UTF-8?q?ord=20searching=20in=20any=20listbox.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/keybind.c | 1 + lib/keybind.h | 1 + lib/widget.h | 2 + lib/widget/Makefile.am | 2 + lib/widget/dialog-switch.c | 3 +- lib/widget/dialog.c | 49 ++-- lib/widget/dialog.h | 1 + lib/widget/filtering_listbox.c | 462 +++++++++++++++++++++++++++++++++ lib/widget/filtering_listbox.h | 46 ++++ lib/widget/forwarding_input.c | 160 ++++++++++++ lib/widget/forwarding_input.h | 36 +++ lib/widget/group.c | 11 +- lib/widget/history.c | 97 ++++--- lib/widget/history.h | 4 +- lib/widget/input.c | 60 +++-- lib/widget/input.h | 2 + lib/widget/input_complete.c | 73 ++++-- lib/widget/listbox-window.c | 24 +- lib/widget/listbox-window.h | 4 +- lib/widget/listbox.c | 75 +++++- lib/widget/listbox.h | 8 + lib/widget/widget-common.c | 2 + lib/widget/widget-common.h | 15 +- src/editor/choosesyntax.c | 2 +- src/editor/editcmd_dialogs.c | 14 +- src/editor/editwidget.c | 8 +- src/file_history.c | 3 +- src/keybind-defaults.c | 5 +- src/selcodepage.c | 2 +- src/usermenu.c | 2 +- 30 files changed, 1029 insertions(+), 145 deletions(-) create mode 100644 lib/widget/filtering_listbox.c create mode 100644 lib/widget/filtering_listbox.h create mode 100644 lib/widget/forwarding_input.c create mode 100644 lib/widget/forwarding_input.h diff --git a/lib/keybind.c b/lib/keybind.c index abd44d3e2..df3cbf110 100644
a b static name_keymap_t command_names[] = { 93 93 ADD_KEYMAP_NAME (SearchContinue), 94 94 ADD_KEYMAP_NAME (Replace), 95 95 ADD_KEYMAP_NAME (ReplaceContinue), 96 ADD_KEYMAP_NAME (MultiSearch), 96 97 ADD_KEYMAP_NAME (Help), 97 98 ADD_KEYMAP_NAME (Shell), 98 99 ADD_KEYMAP_NAME (Edit), -
lib/keybind.h
diff --git a/lib/keybind.h b/lib/keybind.h index af019df09..817158412 100644
a b enum 82 82 CK_SearchContinue, 83 83 CK_Replace, 84 84 CK_ReplaceContinue, 85 CK_MultiSearch, 85 86 CK_SearchStop, 86 87 CK_Help, 87 88 CK_Edit, -
lib/widget.h
diff --git a/lib/widget.h b/lib/widget.h index e3bb5cac2..cfe556891 100644
a b typedef struct WGroup WGroup; 30 30 #include "lib/widget/groupbox.h" 31 31 #include "lib/widget/label.h" 32 32 #include "lib/widget/listbox.h" 33 #include "lib/widget/filtering_listbox.h" 33 34 #include "lib/widget/menu.h" 34 35 #include "lib/widget/radio.h" 35 36 #include "lib/widget/input.h" 37 #include "lib/widget/forwarding_input.h" 36 38 #include "lib/widget/listbox-window.h" 37 39 #include "lib/widget/quick.h" 38 40 #include "lib/widget/wtools.h" -
lib/widget/Makefile.am
diff --git a/lib/widget/Makefile.am b/lib/widget/Makefile.am index 90f023bbc..9a4616c38 100644
a b libmcwidget_la_SOURCES = \ 16 16 history.c history.h \ 17 17 input.c input.h \ 18 18 input_complete.c \ 19 forwarding_input.c forwarding_input.h \ 19 20 listbox-window.c listbox-window.h \ 20 21 listbox.c listbox.h \ 22 filtering_listbox.c filtering_listbox.h \ 21 23 label.c label.h \ 22 24 menu.c menu.h \ 23 25 mouse.c mouse.h \ -
lib/widget/dialog-switch.c
diff --git a/lib/widget/dialog-switch.c b/lib/widget/dialog-switch.c index 93868b19d..a9a51ce0d 100644
a b dialog_switch_list (void) 241 241 else 242 242 title = g_strdup (""); 243 243 244 listbox_add_item (listbox->list, LISTBOX_APPEND_BEFORE, get_hotkey (i++), title, h, FALSE); 244 listbox_add_item (LISTBOX (listbox->list), LISTBOX_APPEND_BEFORE, get_hotkey (i++), title, 245 h, FALSE); 245 246 246 247 g_free (title); 247 248 } -
lib/widget/dialog.c
diff --git a/lib/widget/dialog.c b/lib/widget/dialog.c index b8a08f029..c8d940be9 100644
a b dlg_default_get_colors (const Widget * w) 87 87 return CONST_DIALOG (w)->colors; 88 88 } 89 89 90 /* --------------------------------------------------------------------------------------------- */91 /**92 * Read histories from the ${XDG_CACHE_HOME}/mc/history file93 */94 static void95 dlg_read_history (WDialog * h)96 {97 char *profile;98 ev_history_load_save_t event_data;99 100 if (num_history_items_recorded == 0) /* this is how to disable */101 return;102 103 profile = mc_config_get_full_path (MC_HISTORY_FILE);104 event_data.cfg = mc_config_init (profile, TRUE);105 event_data.receiver = NULL;106 107 /* create all histories in dialog */108 mc_event_raise (h->event_group, MCEVENT_HISTORY_LOAD, &event_data);109 110 mc_config_deinit (event_data.cfg);111 g_free (profile);112 }113 114 90 /* --------------------------------------------------------------------------------------------- */ 115 91 116 92 static void … … do_refresh (void) 473 449 474 450 /* --------------------------------------------------------------------------------------------- */ 475 451 452 /** 453 * Read histories from the ${XDG_CACHE_HOME}/mc/history file 454 */ 455 void 456 dlg_read_history (WDialog * h) 457 { 458 char *profile; 459 ev_history_load_save_t event_data; 460 461 if (num_history_items_recorded == 0) /* this is how to disable */ 462 return; 463 464 profile = mc_config_get_full_path (MC_HISTORY_FILE); 465 event_data.cfg = mc_config_init (profile, TRUE); 466 event_data.receiver = NULL; 467 468 /* create all histories in dialog */ 469 mc_event_raise (h->event_group, MCEVENT_HISTORY_LOAD, &event_data); 470 471 mc_config_deinit (event_data.cfg); 472 g_free (profile); 473 } 474 475 /* --------------------------------------------------------------------------------------------- */ 476 476 477 void 477 478 dlg_stop (WDialog * h) 478 479 { -
lib/widget/dialog.h
diff --git a/lib/widget/dialog.h b/lib/widget/dialog.h index 1d08b8e1a..d67735e71 100644
a b int dlg_run (WDialog * d); 109 109 void dlg_destroy (WDialog * h); 110 110 111 111 void dlg_run_done (WDialog * h); 112 void dlg_read_history (WDialog * h); 112 113 void dlg_save_history (WDialog * h); 113 114 void dlg_process_event (WDialog * h, int key, Gpm_Event * event); 114 115 -
new file lib/widget/filtering_listbox.c
diff --git a/lib/widget/filtering_listbox.c b/lib/widget/filtering_listbox.c new file mode 100644 index 000000000..b5ce2ab1c
- + 1 /* 2 A class extending WListbox with dynamic filtering (i.e.: removal) of entries. 3 4 Copyright (C) <2021> 5 Free Software Foundation, Inc. 6 7 Written by: 8 Sebastian Gniazdowski <sgniazdowski@gmail.com>, 2021. 9 10 This file is part of the Midnight Commander. 11 12 The Midnight Commander is free software: you can redistribute it 13 and/or modify it under the terms of the GNU General Public License as 14 published by the Free Software Foundation, either version 3 of the License, 15 or (at your option) any later version. 16 17 The Midnight Commander is distributed in the hope that it will be useful, 18 but WITHOUT ANY WARRANTY; without even the implied warranty of 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 GNU General Public License for more details. 21 22 You should have received a copy of the GNU General Public License 23 along with this program. If not, see <http://www.gnu.org/licenses/>. 24 */ 25 26 /** \file filtering_listbox.c 27 * \brief A WListbox inheriting class that adds dynamic filtering of entries. 28 * \author Sebastian Gniazdowski 29 * \date 2021 30 * 31 * In order to enable/disable (i.e.: toggle) MultiSearch on an listbox you can send a message: 32 * send_message (listbox, NULL, MSG_ACTION, CK_MultiSearch, NULL); 33 * 34 * It'll extend owning dialog with a new MultiSearch input and pair it up with the listbox, so that 35 * some of keys (basically all that aren't in input's keymap) are forwarded to listbox. 36 */ 37 38 #include <config.h> 39 40 #include "lib/global.h" 41 #include "lib/widget.h" 42 #include "lib/tty/tty.h" 43 44 /*** global variables ****************************************************************************/ 45 46 /*** file scope macro definitions ****************************************************************/ 47 48 /*** file scope type declarations ****************************************************************/ 49 50 /*** file scope variables ************************************************************************/ 51 52 /*** file scope functions ************************************************************************/ 53 /* --------------------------------------------------------------------------------------------- */ 54 55 static WLEntry * 56 filt_listbox_shallow_copy_entry (WLEntry * src, gboolean take_ownership) 57 { 58 WLEntry *copy; 59 copy = g_new (WLEntry, 1); 60 *copy = *src; 61 62 /* Who has the ownership of the data? */ 63 src->free_text = src->free_text && !take_ownership; 64 src->free_data = src->free_data && !take_ownership; 65 copy->free_text = copy->free_text && take_ownership; 66 copy->free_data = copy->free_data && take_ownership; 67 68 return copy; 69 } 70 71 /* --------------------------------------------------------------------------------------------- */ 72 73 static void 74 filt_listbox_make_one_line_room (WFilteringListbox * sl, gboolean should_add_free_room) 75 { 76 WListbox *l = LISTBOX (sl); 77 Widget *w = WIDGET (l), *owner = WIDGET (WIDGET (w)->owner); 78 WRect r_dialog, r_listbox; 79 int new_dialog_height, new_dialog_ypos, new_listbox_height, take_give_from_to_owner = 1; 80 81 /* 82 * IF the enlarged dialog won't fit the screen, don't resize it but the listbox instead. 83 * Do it also when requested if the listbox is large (for small listboxes always try to 84 * enlarge the dialog). 85 */ 86 if ((sl->resize_strategy == FILT_LIST_DIALOG_AUTO_RESIZE && LINES <= owner->lines + 2) || 87 (sl->resize_strategy == FILT_LIST_KEEP_DIALOG_SIZE && owner->lines > 7)) 88 take_give_from_to_owner = 0; 89 90 /* Increase the height of the dialog by 1, so that the new input fits. */ 91 if (should_add_free_room) 92 { 93 new_dialog_height = owner->lines + take_give_from_to_owner; 94 new_listbox_height = w->lines + (-1 + take_give_from_to_owner); 95 new_dialog_ypos = owner->y - take_give_from_to_owner; 96 } 97 else 98 { 99 new_dialog_height = owner->lines - take_give_from_to_owner; 100 new_listbox_height = w->lines - (-1 + take_give_from_to_owner); 101 new_dialog_ypos = owner->y + take_give_from_to_owner; 102 } 103 rect_init (&r_dialog, new_dialog_ypos, owner->x, new_dialog_height, owner->cols); 104 rect_init (&r_listbox, w->y, w->x, new_listbox_height, w->cols); 105 106 /* 107 * Doing widget_set_size_rect(w, &r_listbox) causes problems as it invokes 108 * drawing of the widget owner. 109 */ 110 send_message (w, NULL, MSG_RESIZE, 0, &r_listbox); 111 send_message (owner, NULL, MSG_RESIZE, 0, &r_dialog); 112 } 113 114 /* --------------------------------------------------------------------------------------------- */ 115 116 static void 117 filt_listbox_show_multi_search_widget (WFilteringListbox * sl) 118 { 119 WListbox *l = LISTBOX (sl); 120 Widget *w = WIDGET (l), *owner = WIDGET (WIDGET (l)->owner); 121 WForwardingInput *multi_search_in; 122 int distance_y = owner->y + owner->lines - (w->y + w->lines) + 1; 123 int distance_x = w->cols > 40 ? 5 : 1, small = w->cols <= 15 ? 1 : 0; 124 125 filt_listbox_make_one_line_room (sl, 1); 126 multi_search_in = forwarding_input_new (owner->lines - distance_y, distance_x, 127 input_colors, w->cols - 2 - distance_x + small, "", 128 "multi_search", INPUT_COMPLETE_NONE, w); 129 group_add_widget_autopos (GROUP (owner), multi_search_in, WPOS_KEEP_TOP | WPOS_CENTER_HORZ, 130 NULL); 131 /* Initialize input widget. */ 132 send_message (WIDGET (multi_search_in), w, MSG_INIT, 0, NULL); 133 dlg_read_history (DIALOG (w->owner)); 134 135 /* Draw dialog and listbox, and then input. */ 136 widget_draw (WIDGET (w->owner)); 137 widget_draw (w); 138 widget_draw (WIDGET (multi_search_in)); 139 } 140 141 /* --------------------------------------------------------------------------------------------- */ 142 143 static void 144 filt_listbox_hide_multi_search_widget (WFilteringListbox * sl) 145 { 146 WListbox *l = LISTBOX (sl); 147 Widget *w = WIDGET (sl); 148 Widget *in; 149 in = widget_find_by_type (WIDGET (WIDGET (l)->owner), forw_input_callback); 150 if (in != NULL) 151 { 152 group_remove_widget (in); 153 filt_listbox_make_one_line_room (sl, 0); 154 group_select_next_widget (WIDGET (l)->owner); 155 156 /* 157 * Repainting is needed because some part of the resized dialog can be left on the 158 * background. 159 */ 160 if (sl->resize_strategy != FILT_LIST_KEEP_DIALOG_SIZE || w->lines <= 7) 161 repaint_screen (); 162 163 widget_draw (WIDGET (w->owner)); 164 widget_draw (w); 165 widget_destroy (in); 166 } 167 } 168 169 /* --------------------------------------------------------------------------------------------- */ 170 171 /* Return TRUE if given listbox is in WST_FILTER state. */ 172 static gboolean 173 filt_listbox_is_filter_state (WFilteringListbox * sl) 174 { 175 return widget_get_state (WIDGET (sl), WST_FILTER); 176 } 177 178 /* --------------------------------------------------------------------------------------------- */ 179 180 static void 181 filt_listbox_filter_list (WFilteringListbox * sl, const char *text) 182 { 183 WListbox *l = LISTBOX (sl); 184 int i, size; 185 GList *le; 186 char **query_terms; 187 188 /* 189 * Remove the list and allocate a new one. The elements are only shallowly freed because the 190 * internal data is still used (and kept in list_keep field). 191 */ 192 if (l->list != NULL) 193 g_queue_free_full (l->list, g_free); 194 l->list = g_queue_new (); 195 196 /* Split the query into space delimeted strings. */ 197 query_terms = g_strsplit (text, " ", 10); 198 199 /* 200 * Get the size of the listbox and iterate over it testing each element against «all» words in 201 * query_terms. 202 */ 203 size = g_queue_get_length (sl->list_keep); 204 le = g_queue_peek_head_link (sl->list_keep); 205 for (i = 0; i < size; i++, le = g_list_next (le)) 206 { 207 WLEntry *e = LENTRY (le->data); 208 gboolean match = TRUE; 209 210 /* Test the query against the list entry. */ 211 for (gchar ** p = query_terms; *p != NULL; p++) 212 { 213 if (**p != '\0' && !strcasestr (e->text, *p)) 214 { 215 match = FALSE; 216 break; 217 } 218 } 219 220 /* If all the terms matched, then add the element to the list. */ 221 if (match) 222 g_queue_push_tail (l->list, filt_listbox_shallow_copy_entry (e, FALSE)); 223 } 224 if (listbox_is_empty (l)) 225 { 226 listbox_add_item (l, LISTBOX_APPEND_AT_END, 0, "<no search results>", NULL, FALSE); 227 LENTRY (g_queue_peek_head_link (l->list)->data)->index = -2; 228 } 229 size = g_queue_get_length (l->list); 230 if (l->pos >= size) 231 listbox_select_entry (l, size - 1); 232 else 233 listbox_select_entry (l, l->pos); 234 235 g_strfreev (query_terms); 236 } 237 238 /* --------------------------------------------------------------------------------------------- */ 239 240 /* Restores original elements of the list (from sl->list_keep) and turns off the WST_FILTER state. */ 241 static gboolean 242 filt_listbox_set_to_normal_state (WFilteringListbox * sl) 243 { 244 WListbox *l = LISTBOX (sl); 245 /* The listbox is already in non-filter state? */ 246 if (!widget_get_state (WIDGET (l), WST_FILTER)) 247 { 248 /* Return doing no change, just signal the error. */ 249 return FALSE; 250 } 251 252 /* The keep-list must be allocated (even if it's empty). */ 253 g_assert (sl->list_keep != NULL); 254 255 /* Mark the new state. */ 256 widget_set_state (WIDGET (l), WST_FILTER, FALSE); 257 258 /* Release the filtered list and replace it with the original, complete list (it owns the 259 * internal data, hence the release is a shallow one). */ 260 g_queue_free_full (l->list, g_free); 261 l->list = sl->list_keep; 262 sl->list_keep = NULL; 263 return TRUE; 264 } 265 266 /* --------------------------------------------------------------------------------------------- */ 267 268 /* 269 * Sets the listbox into «filter» state. In this state, there's a separate copy of all list 270 * entries, while the original (and displayed) field ->list is being a filtered version of the 271 * full copy. 272 */ 273 static gboolean 274 filt_listbox_set_to_filter_state (WFilteringListbox * sl) 275 { 276 WListbox *l = LISTBOX (sl); 277 GList *le; 278 279 /* The listbox is already in filter state? */ 280 if (widget_get_state (WIDGET (l), WST_FILTER)) 281 { 282 /* Return doing no change, just signal the error. */ 283 return FALSE; 284 } 285 286 /* Mark the new state. */ 287 widget_set_state (WIDGET (l), WST_FILTER, TRUE); 288 289 /* No list copy when entering filter mode. */ 290 g_assert (sl->list_keep == NULL); 291 sl->list_keep = g_queue_new (); 292 293 /* Skip empty lists. */ 294 if (listbox_is_empty (l)) 295 return TRUE; 296 297 /* 298 * Remember the original position in the list in the field. It'll be used to determine the 299 * virtual_pos field. 300 */ 301 listbox_init_indices (l); 302 303 /* Perform a shallow copy of the original list. */ 304 for (le = g_queue_peek_head_link (l->list); le != NULL; le = g_list_next (le)) 305 { 306 WLEntry *copy; 307 copy = filt_listbox_shallow_copy_entry (LENTRY (le->data), TRUE); 308 g_queue_push_tail (sl->list_keep, copy); 309 } 310 311 return TRUE; 312 } 313 314 /* --------------------------------------------------------------------------------------------- */ 315 316 /* 317 * If the list is filtered it replaces from the back list (list_keep). It returns whether such 318 * change occurred – FALSE means that the list was already unfiltered. 319 */ 320 gboolean 321 filt_listbox_ensure_unfiltered_state (WFilteringListbox * sl) 322 { 323 gboolean ret = FALSE; 324 if (filt_listbox_is_filter_state (sl)) 325 ret = filt_listbox_set_to_normal_state (sl); 326 return ret; 327 } 328 329 /* --------------------------------------------------------------------------------------------- */ 330 331 gboolean 332 filt_listbox_conditionally_enable_multi_search_init (WFilteringListbox * sl) 333 { 334 gboolean start_with_multi_search_active; 335 336 /* Option of starting the listbox with MultiSearch pre-activated. */ 337 start_with_multi_search_active = 338 mc_config_get_bool (mc_global.main_config, CONFIG_APP_SECTION, 339 "multi_search_active_by_default", 1); 340 341 /* CK_MultiSearch toggles the state. */ 342 if (start_with_multi_search_active) 343 send_message (WIDGET (sl), NULL, MSG_ACTION, CK_MultiSearch, NULL); 344 else 345 /* Only init embedded position indices. */ 346 listbox_init_indices (LISTBOX (sl)); 347 348 /* Return if did enable MultiSearch. */ 349 return start_with_multi_search_active; 350 } 351 352 /* --------------------------------------------------------------------------------------------- */ 353 /*** public functions ****************************************************************************/ 354 /* --------------------------------------------------------------------------------------------- */ 355 356 WFilteringListbox * 357 filtering_listbox_new (int y, int x, int height, int width, 358 gboolean deletable, lcback_fn callback, 359 filt_listbox_resize_strategy_t resize) 360 { 361 WFilteringListbox *object; 362 Widget *w_ref; 363 364 /* Allocate memory for the object body. */ 365 object = g_new (WFilteringListbox, 1); 366 367 /* Forward the call to construct the inherited object. */ 368 listbox_init (&object->base, y, x, height, width, deletable, callback); 369 370 /* Alter fields of base class. */ 371 w_ref = WIDGET (object); 372 w_ref->callback = filt_listbox_callback; /* Set custom callback handler */ 373 374 /* Set extending fields of this class. */ 375 object->list_keep = NULL; /* No back buffer at startup */ 376 object->resize_strategy = resize; /* Save resize strategy */ 377 object->initialized = FALSE; 378 379 return object; 380 } 381 382 /* --------------------------------------------------------------------------------------------- */ 383 384 cb_ret_t 385 filt_listbox_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data) 386 { 387 WFilteringListbox *sl = FILT_LISTBOX (w); /* s* - from `screen`, a "screened" listbox */ 388 cb_ret_t ret = MSG_NOT_HANDLED; 389 long activity; 390 391 switch (msg) 392 { 393 case MSG_INIT: 394 if (!sl->initialized) 395 { 396 filt_listbox_conditionally_enable_multi_search_init (sl); 397 sl->initialized = TRUE; 398 } 399 /* WListbox doesn't have MSG_INIT, so don't forward. */ 400 ret = MSG_HANDLED; 401 break; 402 case MSG_ACTION: 403 if (parm == CK_MultiSearch) 404 { 405 gboolean retval; 406 /* Toggle the multi term searching of any listbox. */ 407 if (filt_listbox_is_filter_state (sl)) 408 { 409 /* Remove the input widget from the dialog. */ 410 filt_listbox_hide_multi_search_widget (sl); 411 /* Restore original (unfiltered) listbox contents. */ 412 retval = filt_listbox_set_to_normal_state (sl); 413 } 414 else 415 { 416 /* Add input widget for the filter query at the bottom of the dialog window. */ 417 filt_listbox_show_multi_search_widget (sl); 418 /* ... and then turn on the filter state. */ 419 retval = filt_listbox_set_to_filter_state (sl); 420 } 421 if (!retval) 422 message (D_ERROR | D_CENTER, MSG_ERROR, 423 "An internal error #3 occurred (filtered listbox support)."); 424 425 ret = MSG_HANDLED; 426 } 427 break; 428 429 case MSG_KEY: 430 activity = widget_lookup_key (WIDGET (sl), parm); 431 if (activity == CK_MultiSearch) 432 ret = send_message (w, NULL, MSG_ACTION, CK_MultiSearch, NULL); 433 break; 434 435 case MSG_NOTIFY: 436 if (widget_get_state (w, WST_FILTER)) 437 { 438 filt_listbox_filter_list (sl, (char *) data); 439 ret = MSG_HANDLED; 440 } 441 widget_draw (w); 442 /* Protect against normal, non ForwardingInput messages, which might not have sender set. */ 443 if (sender) 444 widget_draw (sender); 445 break; 446 447 case MSG_DESTROY: 448 filt_listbox_ensure_unfiltered_state (sl); 449 /* ret is unhandled -> the message will be forwarded to base class. */ 450 break; 451 default: 452 break; 453 } 454 455 /* Forward action to base class in case it's not yet handled. */ 456 if (ret == MSG_NOT_HANDLED) 457 ret = listbox_callback (w, sender, msg, parm, data); 458 459 return ret; 460 } 461 462 /* --------------------------------------------------------------------------------------------- */ -
new file lib/widget/filtering_listbox.h
diff --git a/lib/widget/filtering_listbox.h b/lib/widget/filtering_listbox.h new file mode 100644 index 000000000..636e75819
- + 1 #ifndef MC__FILTERING_LISTBOX_H 2 #define MC__FILTERING_LISTBOX_H 3 4 /*** typedefs(not structures) and defined constants **********************************************/ 5 6 /* Casting macros. */ 7 #define FILT_LISTBOX(x) ((WFilteringListbox *)(x)) 8 #define CONST_FILT_LISTBOX(x) ((const WFilteringListbox *)(x)) 9 10 /*** enums ***************************************************************************************/ 11 12 typedef enum filt_listbox_resize_strategy_e 13 { 14 FILT_LIST_EXTEND_DIALOG = 0, 15 FILT_LIST_KEEP_DIALOG_SIZE, 16 FILT_LIST_DIALOG_AUTO_RESIZE 17 } filt_listbox_resize_strategy_t; 18 19 /*** structures declarations (and typedefs of structures)*****************************************/ 20 21 typedef struct WFilteringListbox_s 22 { 23 WListbox base; 24 gboolean initialized; /* Whether MSG_INIT has been received. */ 25 26 /* Fields for new logic. */ 27 GQueue *list_keep; /* Unfiltered list (used in WST_FILTER state). */ 28 filt_listbox_resize_strategy_t resize_strategy; 29 } WFilteringListbox; 30 31 /*** global variables defined in .c file *********************************************************/ 32 33 /*** declarations of public functions ************************************************************/ 34 35 WFilteringListbox *filtering_listbox_new (int y, int x, int height, int width, 36 gboolean deletable, lcback_fn callback, 37 filt_listbox_resize_strategy_t resize); 38 gboolean filt_listbox_ensure_unfiltered_state (WFilteringListbox * l); 39 gboolean filt_listbox_conditionally_enable_multi_search_init (WFilteringListbox * l); 40 void filt_listbox_select_entry (WFilteringListbox * sl, int dest); 41 cb_ret_t filt_listbox_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, 42 void *data); 43 44 /*** inline functions ****************************************************************************/ 45 46 #endif /* MC__FILTERING_LISTBOX_H */ -
new file lib/widget/forwarding_input.c
diff --git a/lib/widget/forwarding_input.c b/lib/widget/forwarding_input.c new file mode 100644 index 000000000..f69440a10
- + 1 /* 2 A key forwarding extended input class. 3 4 Copyright (C) 2021 5 Free Software Foundation, Inc. 6 7 Written by: 8 Sebastian Gniazdowski <sgniazdowski@gmail.com>, 2021. 9 10 This file is part of the Midnight Commander. 11 12 The Midnight Commander is free software: you can redistribute it 13 and/or modify it under the terms of the GNU General Public License as 14 published by the Free Software Foundation, either version 3 of the License, 15 or (at your option) any later version. 16 17 The Midnight Commander is distributed in the hope that it will be useful, 18 but WITHOUT ANY WARRANTY; without even the implied warranty of 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 GNU General Public License for more details. 21 22 You should have received a copy of the GNU General Public License 23 along with this program. If not, see <http://www.gnu.org/licenses/>. 24 */ 25 26 /** \file forwarding-input.c 27 * \brief This input class has a feature of forwarding unrecognized keys to a widget passed at 28 * creation. 29 * \author Sebastian Gniazdowski 30 * \date 2021 31 * 32 * It's being used by MultiSearch to allow moving across listbox while typing to the input. 33 */ 34 35 #include <config.h> 36 37 #include "lib/global.h" 38 #include "lib/widget.h" 39 40 /*** global variables ****************************************************************************/ 41 42 /*** file scope macro definitions ****************************************************************/ 43 44 /*** file scope type declarations ****************************************************************/ 45 46 /*** file scope variables ************************************************************************/ 47 48 /*** file scope functions ************************************************************************/ 49 /* --------------------------------------------------------------------------------------------- */ 50 51 /* --------------------------------------------------------------------------------------------- */ 52 /*** public functions ****************************************************************************/ 53 /* --------------------------------------------------------------------------------------------- */ 54 55 WForwardingInput * 56 forwarding_input_new (int y, int x, const int *colors, 57 int len, const char *text, const char *histname, 58 input_complete_t completion_flags, Widget * forward_to_widget) 59 { 60 WForwardingInput *object; 61 Widget *w_ref; 62 63 /* Allocate memory for the object body. */ 64 object = g_new (WForwardingInput, 1); 65 66 /* Call upper constructor to initialize the inherited object. */ 67 input_init (&object->base, y, x, colors, len, text, histname, completion_flags); 68 69 /* Alter fields of base class. */ 70 w_ref = WIDGET (object); 71 w_ref->callback = forw_input_callback; /* Set custom callback handler */ 72 73 /* Set extending fields of this class. */ 74 object->forward_to_widget = forward_to_widget; 75 return object; 76 } 77 78 /* --------------------------------------------------------------------------------------------- */ 79 80 cb_ret_t 81 forw_input_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data) 82 { 83 WForwardingInput *in = FORW_INPUT (w); 84 gboolean key_message = FALSE; 85 cb_ret_t ret; 86 87 switch (msg) 88 { 89 case MSG_KEY: 90 ret = forw_input_handle_char (in, parm); 91 key_message = TRUE; 92 break; 93 default: 94 break; 95 } 96 97 /* 98 * Simply pass on all messages to the base class (except for MSG_KEY, which might have 99 * been possibly already sent from forw_input_handle_char() function). 100 */ 101 102 if (!key_message) 103 ret = input_callback (WIDGET (in), sender, msg, parm, data); 104 105 return ret; 106 } 107 108 /* --------------------------------------------------------------------------------------------- */ 109 110 cb_ret_t 111 forw_input_handle_char (WForwardingInput * in, int key) 112 { 113 cb_ret_t ret = MSG_NOT_HANDLED; 114 gboolean sent_to_base = FALSE; 115 long activity; 116 char *str_cp; 117 118 /* Save to detect if a change happened. */ 119 str_cp = g_strdup (in->base.buffer); 120 121 /* Is this key recognized by the base object? */ 122 activity = widget_lookup_key (WIDGET (in), key); 123 if (activity != CK_IgnoreKey && activity != CK_Complete) 124 { 125 /* Yes -> send the key to the upper class. */ 126 ret = input_callback (WIDGET (in), WIDGET (in), MSG_KEY, key, NULL); 127 sent_to_base = TRUE; 128 } 129 /* Should we try to forward the key to any paired widget? */ 130 if (in->forward_to_widget != NULL && ret == MSG_NOT_HANDLED) 131 { 132 /* Is it maybe recognized by forward_to_widget paired object? */ 133 activity = widget_lookup_key (WIDGET (in->forward_to_widget), key); 134 if (activity != CK_IgnoreKey) 135 { 136 /* Yes - forward the key to the paired widget (most probably WListbox). */ 137 ret = send_message (WIDGET (in->forward_to_widget), NULL, MSG_KEY, key, NULL); 138 } 139 } 140 141 /* 142 * If not handled yet, then send the key to the base object for general recognition (if 143 * not already done that). 144 */ 145 146 if (!sent_to_base && ret == MSG_NOT_HANDLED) 147 { 148 ret = input_callback (WIDGET (in), WIDGET (in), MSG_KEY, key, NULL); 149 sent_to_base = TRUE; /* currently unused */ 150 } 151 152 /* Send update signal to paired widget «iff» input's text has changed. */ 153 if (in->forward_to_widget != NULL && g_strcmp0 (str_cp, in->base.buffer) != 0) 154 send_message (WIDGET (in->forward_to_widget), NULL, MSG_NOTIFY, key, in->base.buffer); 155 g_free (str_cp); 156 157 return ret; 158 } 159 160 /* --------------------------------------------------------------------------------------------- */ -
new file lib/widget/forwarding_input.h
diff --git a/lib/widget/forwarding_input.h b/lib/widget/forwarding_input.h new file mode 100644 index 000000000..dc4e49423
- + 1 #ifndef MC__FORWARDING_INPUT_H 2 #define MC__FORWARDING_INPUT_H 3 4 /*** typedefs(not structures) and defined constants **********************************************/ 5 6 /* Casting macros. */ 7 #define FORW_INPUT(x) ((WForwardingInput *)(x)) 8 #define CONST_FORW_INPUT(x) ((const WForwardingInput *)(x)) 9 10 typedef struct 11 { 12 WInput base; 13 14 /* Fields for new logic. */ 15 Widget *forward_to_widget; /* The paired widget to receive unhandled keys */ 16 } WForwardingInput; 17 18 /*** enums ***************************************************************************************/ 19 20 /*** structures declarations (and typedefs of structures)*****************************************/ 21 22 /*** global variables defined in .c file *********************************************************/ 23 24 /*** declarations of public functions ************************************************************/ 25 26 WForwardingInput *forwarding_input_new (int y, int x, const int *colors, 27 int len, const char *text, const char *histname, 28 input_complete_t completion_flags, 29 Widget * forward_to_widget); 30 31 cb_ret_t forw_input_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data); 32 cb_ret_t forw_input_handle_char (WForwardingInput * in, int key); 33 34 /*** inline functions ****************************************************************************/ 35 36 #endif /* MC__FORWARDING_INPUT_H */ -
lib/widget/group.c
diff --git a/lib/widget/group.c b/lib/widget/group.c index f8e318bd9..f16de833f 100644
a b group_add_widget_autopos (WGroup * g, void *w, widget_pos_flags_t pos_flags, con 749 749 * @param w Widget object 750 750 */ 751 751 void 752 group_remove_widget (void *w )752 group_remove_widget (void *wid) 753 753 { 754 Widget *w = WIDGET (wid); 754 755 WGroup *g; 755 756 GList *d; 756 757 757 758 /* Don't accept NULL widget. This shouldn't happen */ 758 759 assert (w != NULL); 759 760 760 g = WIDGET (w)->owner; 761 /* Invoke widget's pre unlink callback. */ 762 if (w->pre_unlink_func != NULL) 763 w->pre_unlink_func (w); 764 765 g = w->owner; 761 766 762 767 d = g_list_find (g->widgets, w); 763 768 if (d == g->current) … … group_remove_widget (void *w) 774 779 group_select_current_widget (g); 775 780 } 776 781 777 WIDGET (w)->owner = NULL;782 w->owner = NULL; 778 783 } 779 784 780 785 /* --------------------------------------------------------------------------------------------- */ -
lib/widget/history.c
diff --git a/lib/widget/history.c b/lib/widget/history.c index 775d02b1b..2ee719ca7 100644
a b typedef struct 66 66 /*** file scope functions ************************************************************************/ 67 67 68 68 static cb_ret_t 69 history_dlg_reposition (WDialog * dlg_head )69 history_dlg_reposition (WDialog * dlg_head, WRect * resize) 70 70 { 71 history_dlg_data *data;72 int x = 0, y, he, wi;73 71 WRect r; 74 72 75 /* guard checks */ 76 if ((dlg_head == NULL) || (dlg_head->data == NULL)) 77 return MSG_NOT_HANDLED; 78 79 data = (history_dlg_data *) dlg_head->data; 80 81 y = data->y; 82 he = data->count + 2; 83 84 if (he <= y || y > (LINES - 6)) 73 if (resize == NULL) 85 74 { 86 he = MIN (he, y - 1); 87 y -= he; 75 history_dlg_data *data; 76 int x = 0, y, he, wi; 77 78 /* guard checks */ 79 if ((dlg_head == NULL) || (dlg_head->data == NULL)) 80 return MSG_NOT_HANDLED; 81 82 data = (history_dlg_data *) dlg_head->data; 83 84 y = data->y; 85 he = data->count + 2; 86 87 if (he <= y || y > (LINES - 6)) 88 { 89 he = MIN (he, y - 1); 90 y -= he; 91 } 92 else 93 { 94 y++; 95 he = MIN (he, LINES - y); 96 } 97 98 if (data->x > 2) 99 x = data->x - 2; 100 101 wi = data->max_width + 4; 102 103 if ((wi + x) > COLS) 104 { 105 wi = MIN (wi, COLS); 106 x = COLS - wi; 107 } 108 rect_init (&r, y, x, he, wi); 88 109 } 89 110 else 90 111 { 91 y++;92 he = MIN (he, LINES - y);112 /* A resize from some other code (currently from the listbox filter). */ 113 r = *resize; 93 114 } 94 115 95 if (data->x > 2)96 x = data->x - 2;97 98 wi = data->max_width + 4;99 100 if ((wi + x) > COLS)101 {102 wi = MIN (wi, COLS);103 x = COLS - wi;104 }105 106 rect_init (&r, y, x, he, wi);107 116 108 117 return dlg_default_callback (WIDGET (dlg_head), NULL, MSG_RESIZE, 0, &r); 109 118 } … … history_dlg_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, v 116 125 switch (msg) 117 126 { 118 127 case MSG_RESIZE: 119 return history_dlg_reposition (DIALOG (w) );128 return history_dlg_reposition (DIALOG (w), data); 120 129 121 130 case MSG_NOTIFY: 122 131 { … … history_create_item (history_descriptor_t * hd, void *data) 158 167 width = str_term_width1 (text); 159 168 hd->max_width = MAX (width, hd->max_width); 160 169 161 listbox_add_item ( hd->listbox, LISTBOX_APPEND_AT_END, 0, text, NULL, TRUE);170 listbox_add_item (LISTBOX (hd->listbox), LISTBOX_APPEND_AT_END, 0, text, NULL, TRUE); 162 171 } 163 172 164 173 /* --------------------------------------------------------------------------------------------- */ … … history_descriptor_init (history_descriptor_t * hd, int y, int x, GList * histor 190 199 hd->action = CK_IgnoreKey; 191 200 hd->text = NULL; 192 201 hd->max_width = 0; 193 hd->listbox = listbox_new (1, 1, 2, 2, TRUE, NULL);202 hd->listbox = filtering_listbox_new (1, 1, 2, 2, TRUE, NULL, FILT_LIST_KEEP_DIALOG_SIZE); 194 203 /* in most cases history list contains string only and no any other data */ 195 204 hd->create = history_create_item; 196 205 hd->release = history_release_item; … … history_show (history_descriptor_t * hd) 205 214 GList *z, *hi; 206 215 size_t count; 207 216 WDialog *query_dlg; 217 WListbox *lw; 208 218 history_dlg_data hist_data; 209 219 int dlg_ret; 210 220 … … history_show (history_descriptor_t * hd) 217 227 hd->create (hd, z->data); 218 228 /* after this, the order of history items is following: recent at begin, oldest at end */ 219 229 220 count = listbox_get_length (hd->listbox); 230 /* Get the WListbox pointer for convenience. */ 231 lw = LISTBOX (hd->listbox); 232 count = listbox_get_length (lw); 221 233 222 234 hist_data.y = hd->y; 223 235 hist_data.x = hd->x; … … history_show (history_descriptor_t * hd) 244 256 { 245 257 /* history is above base widget -- revert order to place recent item at bottom */ 246 258 /* revert history direction */ 247 g_queue_reverse ( hd->listbox->list);259 g_queue_reverse (lw->list); 248 260 if (hd->current < 0 || (size_t) hd->current >= count) 249 listbox_select_last ( hd->listbox);261 listbox_select_last (lw); 250 262 else 251 listbox_select_entry ( hd->listbox, count - 1 - (size_t) hd->current);263 listbox_select_entry (lw, count - 1 - (size_t) hd->current); 252 264 } 253 265 else 254 266 { 255 267 /* history is below base widget -- keep order to place recent item on top */ 256 268 if (hd->current > 0) 257 listbox_select_entry ( hd->listbox, hd->current);269 listbox_select_entry (lw, hd->current); 258 270 } 259 271 260 272 dlg_ret = dlg_run (query_dlg); … … history_show (history_descriptor_t * hd) 274 286 hd->action = CK_Enter; 275 287 } 276 288 277 listbox_get_current (hd->listbox, &q, NULL); 278 hd->text = g_strdup (q); 289 listbox_get_current (lw, &q, NULL); 290 /* Can still be 0 if special entry "<no search results>" will be selected. */ 291 if (q != NULL) 292 hd->text = g_strdup (q); 279 293 } 280 294 295 /* If needed, restore normal listbox state, with no backlist (list_keep). */ 296 filt_listbox_ensure_unfiltered_state (hd->listbox); 297 281 298 /* get modified history from dialog */ 282 299 z = NULL; 283 for (hi = listbox_get_first_link ( hd->listbox); hi != NULL; hi = g_list_next (hi))300 for (hi = listbox_get_first_link (lw); hi != NULL; hi = g_list_next (hi)) 284 301 /* history is being reverted here again */ 285 302 z = g_list_prepend (z, hd->release (hd, LENTRY (hi->data))); 286 303 -
lib/widget/history.h
diff --git a/lib/widget/history.h b/lib/widget/history.h index 9c4b403d1..23f4d403d 100644
a b 11 11 /* forward declarations */ 12 12 struct history_descriptor_t; 13 13 struct WLEntry; 14 struct WListbox;14 typedef struct WFilteringListbox_s WFilteringListbox; 15 15 16 16 typedef void (*history_create_item_func) (struct history_descriptor_t * hd, void *data); 17 17 typedef void *(*history_release_item_func) (struct history_descriptor_t * hd, struct WLEntry * le); … … typedef struct history_descriptor_t 30 30 char *text; /**< return text of selected item */ 31 31 32 32 size_t max_width; /**< maximum width of sring in history */ 33 struct WListbox *listbox; /**< listbox widget to draw history */33 WFilteringListbox *listbox; /**< listbox widget to draw history */ 34 34 35 35 history_create_item_func create; /**< function to create item of @list */ 36 36 history_release_item_func release; /**< function to release item of @list */ -
lib/widget/input.c
diff --git a/lib/widget/input.c b/lib/widget/input.c index 471715c25..0069a765f 100644
a b input_save_history (const gchar * event_group_name, const gchar * event_name, 871 871 (void) event_group_name; 872 872 (void) event_name; 873 873 874 if (!in->is_password && (DIALOG (WIDGET (in)->owner)->ret_value != B_CANCEL)) 874 if (!in->is_password && WIDGET (in)->owner != NULL 875 && (DIALOG (WIDGET (in)->owner)->ret_value != B_CANCEL)) 875 876 { 876 877 ev_history_load_save_t *ev = (ev_history_load_save_t *) data; 877 878 … … input_mouse_callback (Widget * w, mouse_msg_t msg, mouse_event_t * event) 970 971 } 971 972 } 972 973 974 /* --------------------------------------------------------------------------------------------- */ 975 /* a callback used when removing the widget from its WGroup */ 976 977 static void 978 input_unregister_history_events_cb (Widget * wid_ptr) 979 { 980 WDialog *h = DIALOG (wid_ptr->owner); 981 982 /* unsubscribe from "history_load" event */ 983 mc_event_del (h->event_group, MCEVENT_HISTORY_LOAD, input_load_history, wid_ptr); 984 /* unsubscribe from "history_save" event */ 985 mc_event_del (h->event_group, MCEVENT_HISTORY_SAVE, input_save_history, wid_ptr); 986 } 987 973 988 /* --------------------------------------------------------------------------------------------- */ 974 989 /*** public functions ****************************************************************************/ 975 990 /* --------------------------------------------------------------------------------------------- */ 976 991 992 WInput * 993 input_new (int y, int x, const int *colors, int width, const char *def_text, 994 const char *histname, input_complete_t completion_flags) 995 { 996 WInput *in; 997 998 in = g_new (WInput, 1); 999 input_init (in, y, x, colors, width, def_text, histname, completion_flags); 1000 return in; 1001 } 1002 1003 /* --------------------------------------------------------------------------------------------- */ 1004 977 1005 /** Create new instance of WInput object. 978 1006 * @param y Y coordinate 979 1007 * @param x X coordinate … … input_mouse_callback (Widget * w, mouse_msg_t msg, mouse_event_t * event) 984 1012 * @param completion_flags Flags for specify type of completions 985 1013 * @return WInput object 986 1014 */ 987 WInput * 988 input_ new (int y, int x, const int *colors, int width, const char *def_text,989 const char *histname, input_complete_t completion_flags)1015 void 1016 input_init (WInput * in, int y, int x, const int *colors, int width, const char *def_text, 1017 const char *histname, input_complete_t completion_flags) 990 1018 { 991 WInput *in; 992 Widget *w; 1019 Widget *w = WIDGET (in); 993 1020 994 in = g_new (WInput, 1);995 w = WIDGET (in);996 1021 widget_init (w, y, x, 1, width, input_callback, input_mouse_callback); 997 1022 w->options |= WOP_SELECTABLE | WOP_IS_INPUT | WOP_WANT_CURSOR; 998 1023 w->keymap = input_map; … … input_new (int y, int x, const int *colors, int width, const char *def_text, 1028 1053 if ((histname != NULL) && (*histname != '\0')) 1029 1054 in->history.name = g_strdup (histname); 1030 1055 /* history will be loaded later */ 1031 1032 1056 in->label = NULL; 1033 1034 return in;1035 1057 } 1036 1058 1037 1059 /* --------------------------------------------------------------------------------------------- */ … … input_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *d 1050 1072 mc_event_add (h->event_group, MCEVENT_HISTORY_LOAD, input_load_history, w, NULL); 1051 1073 /* subscribe to "history_save" event */ 1052 1074 mc_event_add (h->event_group, MCEVENT_HISTORY_SAVE, input_save_history, w, NULL); 1075 /* unregister (via the func) above events in case of removal from dialog */ 1076 w->pre_unlink_func = input_unregister_history_events_cb; 1053 1077 if (in->label != NULL) 1054 1078 widget_set_state (WIDGET (in->label), WST_DISABLED, widget_get_state (w, WST_DISABLED)); 1055 1079 return MSG_HANDLED; … … input_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *d 1063 1087 return v; 1064 1088 } 1065 1089 1066 /* Keys we want others to handle */1090 /* Keys we want others to handle. */ 1067 1091 if (parm == KEY_UP || parm == KEY_DOWN || parm == ESC_CHAR 1068 1092 || parm == KEY_F (10) || parm == '\n') 1069 1093 return MSG_NOT_HANDLED; … … input_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *d 1097 1121 return MSG_HANDLED; 1098 1122 1099 1123 case MSG_DESTROY: 1100 /* unsubscribe from "history_load" event */ 1101 mc_event_del (h->event_group, MCEVENT_HISTORY_LOAD, input_load_history, w); 1102 /* unsubscribe from "history_save" event */ 1103 mc_event_del (h->event_group, MCEVENT_HISTORY_SAVE, input_save_history, w); 1124 /* Only, if there is an owner WGroup. */ 1125 if (h != NULL) 1126 { 1127 /* unsubscribe from "history_load" event */ 1128 mc_event_del (h->event_group, MCEVENT_HISTORY_LOAD, input_load_history, w); 1129 /* unsubscribe from "history_save" event */ 1130 mc_event_del (h->event_group, MCEVENT_HISTORY_SAVE, input_save_history, w); 1131 } 1104 1132 input_destroy (in); 1105 1133 return MSG_HANDLED; 1106 1134 -
lib/widget/input.h
diff --git a/lib/widget/input.h b/lib/widget/input.h index a753e6160..792bb7f28 100644
a b extern input_colors_t input_colors; 83 83 84 84 /*** declarations of public functions ************************************************************/ 85 85 86 void input_init (WInput * in, int y, int x, const int *colors, int width, const char *def_text, 87 const char *histname, input_complete_t completion_flags); 86 88 WInput *input_new (int y, int x, const int *colors, 87 89 int len, const char *text, const char *histname, 88 90 input_complete_t completion_flags); -
lib/widget/input_complete.c
diff --git a/lib/widget/input_complete.c b/lib/widget/input_complete.c index c23fe6063..d4f9c423a 100644
a b complete_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void 1017 1017 { 1018 1018 static int bl = 0; 1019 1019 1020 WGroup *g = GROUP (w);1021 1020 WDialog *h = DIALOG (w); 1021 WFilteringListbox *slw; 1022 cb_ret_t ret = MSG_NOT_HANDLED; 1023 1024 /* Find the listbox in dialog's group. */ 1025 slw = FILT_LISTBOX (WIDGET (h)->find_by_type (WIDGET (h), filt_listbox_callback)); 1022 1026 1023 1027 switch (msg) 1024 1028 { … … complete_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void 1027 1031 { 1028 1032 case KEY_LEFT: 1029 1033 case KEY_RIGHT: 1034 /* MultiSearch (list filtering) is allowing for left/right movement in query input. */ 1035 if (widget_get_state (WIDGET (slw), WST_FILTER)) 1036 break; 1030 1037 bl = 0; 1031 1038 h->ret_value = 0; 1032 1039 dlg_stop (h); 1033 return MSG_HANDLED; 1040 ret = MSG_HANDLED; 1041 break; 1034 1042 1035 1043 case KEY_BACKSPACE: 1044 /* MultiSearch is exclusive with completion widening. */ 1045 if (widget_get_state (WIDGET (slw), WST_FILTER)) 1046 break; 1036 1047 bl = 0; 1037 1048 /* exit from completion list if input line is empty */ 1038 1049 if (end == 0) … … complete_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void 1056 1067 1057 1068 new_end = str_get_prev_char (&input->buffer[end]) - input->buffer; 1058 1069 1059 for (i = 0, e = listbox_get_first_link (LISTBOX ( g->current->data));1070 for (i = 0, e = listbox_get_first_link (LISTBOX (slw)); 1060 1071 e != NULL; i++, e = g_list_next (e)) 1061 1072 { 1062 1073 WLEntry *le = LENTRY (e->data); 1063 1074 1064 1075 if (strncmp (input->buffer + start, le->text, new_end - start) == 0) 1065 1076 { 1066 listbox_select_entry (LISTBOX ( g->current->data), i);1077 listbox_select_entry (LISTBOX (slw), i); 1067 1078 end = new_end; 1068 1079 input_handle_char (input, parm); 1069 widget_draw (WIDGET ( g->current->data));1080 widget_draw (WIDGET (slw)); 1070 1081 break; 1071 1082 } 1072 1083 } 1073 1084 } 1074 return MSG_HANDLED; 1085 ret = MSG_HANDLED; 1086 break; 1075 1087 1076 1088 default: 1077 1089 if (parm < 32 || parm > 255) 1078 1090 { 1079 1091 bl = 0; 1080 if (widget_lookup_key (WIDGET (input), parm) != CK_Complete) 1081 return MSG_NOT_HANDLED; 1082 1083 if (end == min_end) 1084 return MSG_HANDLED; 1085 1086 /* This means we want to refill the list box and start again */ 1087 h->ret_value = B_USER; 1088 dlg_stop (h); 1092 /* CK_Complete -> Is completion up to date? */ 1093 if ((widget_lookup_key (WIDGET (input), parm) == CK_Complete) && (end != min_end)) 1094 { 1095 /* This means we want to refill the list box and start again. */ 1096 h->ret_value = B_USER; 1097 dlg_stop (h); 1098 } 1099 /* 1100 * else - key will be ignored by this function, so leave ret unchanged - allow other 1101 * widgets to process it. 1102 */ 1089 1103 } 1090 else 1104 1105 /* 1106 * Do standard live entry lookup only when not filtering list via MultiSearch – it is 1107 * a feature that to a great extent replaces old engine. It can be still used as MultiSearch 1108 * can be dynamically enabled and disabled (by default with: Alt-space and Ctrl-space). 1109 */ 1110 else if (!widget_get_state (WIDGET (slw), WST_FILTER)) 1091 1111 { 1092 1112 static char buff[MB_LEN_MAX] = ""; 1093 1113 GList *e; … … complete_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void 1110 1130 break; 1111 1131 } 1112 1132 1113 for (i = 0, e = listbox_get_first_link (LISTBOX ( g->current->data));1133 for (i = 0, e = listbox_get_first_link (LISTBOX (slw)); 1114 1134 e != NULL; i++, e = g_list_next (e)) 1115 1135 { 1116 1136 WLEntry *le = LENTRY (e->data); … … complete_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void 1121 1141 if (need_redraw == 0) 1122 1142 { 1123 1143 need_redraw = 1; 1124 listbox_select_entry (LISTBOX ( g->current->data), i);1144 listbox_select_entry (LISTBOX (slw), i); 1125 1145 last_text = le->text; 1126 1146 } 1127 1147 else … … complete_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void 1172 1192 if (need_redraw == 2) 1173 1193 { 1174 1194 insert_text (input, last_text, low); 1175 widget_draw (WIDGET ( g->current->data));1195 widget_draw (WIDGET (slw)); 1176 1196 } 1177 1197 else if (need_redraw == 1) 1178 1198 { … … complete_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void 1180 1200 dlg_stop (h); 1181 1201 } 1182 1202 bl = 0; 1203 ret = MSG_HANDLED; 1183 1204 } 1184 1205 } 1185 return MSG_HANDLED;1206 break; 1186 1207 1187 1208 default: 1188 1209 return dlg_default_callback (w, sender, msg, parm, data); 1189 1210 } 1211 return ret; 1190 1212 } 1191 1213 1192 1214 /* --------------------------------------------------------------------------------------------- */ … … complete_engine (WInput * in, int what_to_do) 1223 1245 int start_x, start_y; 1224 1246 char **p, *q; 1225 1247 WDialog *complete_dlg; 1226 W Listbox *complete_list;1248 WFilteringListbox *complete_list; 1227 1249 1228 1250 for (p = in->completions + 1; *p != NULL; count++, p++) 1229 1251 { … … complete_engine (WInput * in, int what_to_do) 1266 1288 complete_dlg = 1267 1289 dlg_create (TRUE, y, x, complete_height, complete_width, WPOS_KEEP_DEFAULT, TRUE, 1268 1290 dialog_colors, complete_callback, NULL, "[Completion]", NULL); 1269 complete_list = listbox_new (1, 1, h - 2, w - 2, FALSE, NULL); 1291 complete_list = filtering_listbox_new (1, 1, h - 2, w - 2, FALSE, NULL, 1292 FILT_LIST_KEEP_DIALOG_SIZE); 1270 1293 group_add_widget (GROUP (complete_dlg), complete_list); 1271 1294 1272 1295 for (p = in->completions + 1; *p != NULL; p++) 1273 listbox_add_item (complete_list, LISTBOX_APPEND_AT_END, 0, *p, NULL, FALSE); 1296 listbox_add_item (LISTBOX (complete_list), LISTBOX_APPEND_AT_END, 0, *p, NULL, 1297 FALSE); 1274 1298 1275 1299 i = dlg_run (complete_dlg); 1276 1300 q = NULL; 1277 1301 if (i == B_ENTER) 1278 1302 { 1279 listbox_get_current ( complete_list, &q, NULL);1303 listbox_get_current (LISTBOX (complete_list), &q, NULL); 1280 1304 if (q != NULL) 1281 1305 insert_text (in, q, strlen (q)); 1282 1306 } 1283 1307 if (q != NULL || end != min_end) 1284 1308 input_complete_free (in); 1309 1285 1310 dlg_destroy (complete_dlg); 1286 1311 1287 1312 /* B_USER if user wants to start over again */ -
lib/widget/listbox-window.c
diff --git a/lib/widget/listbox-window.c b/lib/widget/listbox-window.c index 44548b485..447ba1328 100644
a b create_listbox_window_centered (int center_y, int center_x, int lines, int cols, 108 108 dlg_create (TRUE, ypos, xpos, lines + space, cols + space, pos_flags, FALSE, listbox_colors, 109 109 NULL, NULL, help, title); 110 110 111 listbox->list = listbox_new (2, 2, lines, cols, FALSE, NULL); 112 group_add_widget (GROUP (listbox->dlg), listbox->list); 111 listbox->list = 112 filtering_listbox_new (2, 2, lines, cols, FALSE, NULL, FILT_LIST_DIALOG_AUTO_RESIZE); 113 group_add_widget (GROUP (listbox->dlg), WIDGET (listbox->list)); 113 114 114 115 return listbox; 115 116 } … … create_listbox_window (int lines, int cols, const char *title, const char *help) 128 129 int 129 130 run_listbox (Listbox * l) 130 131 { 132 WListbox *lw = LISTBOX (l->list); 131 133 int val = -1; 132 134 133 135 if (dlg_run (l->dlg) != B_CANCEL) 134 val = l->list->pos; 136 { 137 /* Get the virtual index first, to support filtered listboxes. */ 138 val = lw->virtual_pos; 139 140 /* No virtual position -> get pos. */ 141 if (val == -1) 142 val = lw->pos; 143 } 144 135 145 dlg_destroy (l->dlg); 136 146 g_free (l); 137 147 return val; … … run_listbox (Listbox * l) 149 159 void * 150 160 run_listbox_with_data (Listbox * l, const void *select) 151 161 { 162 WListbox *lw = LISTBOX (l->list); 152 163 void *val = NULL; 153 164 154 165 if (select != NULL) 155 listbox_select_entry (l ->list, listbox_search_data (l->list, select));166 listbox_select_entry (lw, listbox_search_data (lw, select)); 156 167 157 168 if (dlg_run (l->dlg) != B_CANCEL) 158 169 { 159 170 WLEntry *e; 160 e = listbox_get_nth_item (l->list, l->list->pos); 161 if (e != NULL) 171 e = listbox_get_nth_item (lw, lw->pos); 172 /* -2 means that "<no search results>" has been selected. */ 173 if (e != NULL && e->index != -2) 162 174 { 163 175 /* The assert guards against returning a soon-to-be deallocated 164 176 * pointer (as in listbox_add_item(..., TRUE)). */ -
lib/widget/listbox-window.h
diff --git a/lib/widget/listbox-window.h b/lib/widget/listbox-window.h index 5a6082956..dc20cee13 100644
a b 8 8 /*** typedefs(not structures) and defined constants **********************************************/ 9 9 10 10 #define LISTBOX_APPEND_TEXT(l,h,t,d,f) \ 11 listbox_add_item ( l->list, LISTBOX_APPEND_AT_END, h, t, d, f)11 listbox_add_item (LISTBOX(l->list), LISTBOX_APPEND_AT_END, h, t, d, f) 12 12 13 13 /*** enums ***************************************************************************************/ 14 14 … … 17 17 typedef struct 18 18 { 19 19 WDialog *dlg; 20 W Listbox *list;20 WFilteringListbox *list; 21 21 } Listbox; 22 22 23 23 /*** global variables defined in .c file *********************************************************/ -
lib/widget/listbox.c
diff --git a/lib/widget/listbox.c b/lib/widget/listbox.c index e20c1a82d..a284cc2e4 100644
a b listbox_entry_free (void *data) 77 77 { 78 78 WLEntry *e = data; 79 79 80 g_free (e->text); 80 if (e->free_text) 81 g_free (e->text); 81 82 if (e->free_data) 82 83 g_free (e->data); 83 84 g_free (e); … … listbox_key (WListbox * l, int key) 358 359 359 360 /* --------------------------------------------------------------------------------------------- */ 360 361 362 /* When called via g_queue_foreach it assigns the index field with an incremented int. */ 363 static void 364 listbox_foreach_apply_index (gpointer data, gpointer user_data) 365 { 366 WLEntry *e = data; 367 int *cur_idx = user_data; 368 369 /* Set the index and increment it. */ 370 e->index = *cur_idx; 371 *cur_idx = *cur_idx + 1; 372 } 373 374 /* --------------------------------------------------------------------------------------------- */ 375 361 376 /* Listbox item adding function */ 362 377 static inline void 363 378 listbox_append_item (WListbox * l, WLEntry * e, listbox_append_t pos) … … listbox_destroy (WListbox * l) 445 460 446 461 /* --------------------------------------------------------------------------------------------- */ 447 462 448 staticcb_ret_t463 cb_ret_t 449 464 listbox_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data) 450 465 { 451 466 WListbox *l = LISTBOX (w); … … listbox_mouse_callback (Widget * w, mouse_msg_t msg, mouse_event_t * event) 544 559 /*** public functions ****************************************************************************/ 545 560 /* --------------------------------------------------------------------------------------------- */ 546 561 547 WListbox * 548 listbox_new (int y, int x, int height, int width, gboolean deletable, lcback_fn callback) 562 void 563 listbox_init (WListbox * l, int y, int x, int height, int width, gboolean deletable, 564 lcback_fn callback) 549 565 { 550 WListbox *l; 551 Widget *w; 566 Widget *w = WIDGET (l); 552 567 553 568 if (height <= 0) 554 569 height = 1; 555 570 556 l = g_new (WListbox, 1);557 w = WIDGET (l);558 571 widget_init (w, y, x, height, width, listbox_callback, listbox_mouse_callback); 559 w->options |= WOP_SELECTABLE | WOP_WANT_HOTKEY;572 w->options |= WOP_SELECTABLE; 560 573 w->keymap = listbox_map; 561 574 562 575 l->list = NULL; 563 l->top = l->pos = 0;576 l->top = l->pos = l->virtual_pos = 0; 564 577 l->deletable = deletable; 565 578 l->callback = callback; 566 579 l->allow_duplicates = TRUE; 567 580 l->scrollbar = !mc_global.tty.slow_terminal; 581 } 568 582 583 /* --------------------------------------------------------------------------------------------- */ 584 585 WListbox * 586 listbox_new (int y, int x, int height, int width, gboolean deletable, lcback_fn callback) 587 { 588 WListbox *l; 589 590 l = g_new (WListbox, 1); 591 listbox_init (l, y, x, height, width, deletable, callback); 569 592 return l; 570 593 } 571 594 … … listbox_select_last (WListbox * l) 648 671 void 649 672 listbox_select_entry (WListbox * l, int dest) 650 673 { 674 WLEntry *e; 651 675 GList *le; 652 676 int pos; 653 677 gboolean top_seen = FALSE; 654 678 655 679 if (listbox_is_empty (l) || dest < 0) 680 { 681 /* Reset position to a minimal one. */ 682 l->pos = 0; 683 l->virtual_pos = 0; 656 684 return; 685 } 657 686 658 687 /* Special case */ 659 688 for (pos = 0, le = g_queue_peek_head_link (l->list); le != NULL; pos++, le = g_list_next (le)) … … listbox_select_entry (WListbox * l, int dest) 673 702 if (l->pos - l->top >= lines) 674 703 l->top = l->pos - lines + 1; 675 704 } 705 /* 706 * Set the virtual position, i.e.: a position in the initial, unfiltered list if the 707 * same element would be selected. 708 */ 709 e = LENTRY (le->data); 710 l->virtual_pos = e->index; 676 711 return; 677 712 } 678 713 } … … listbox_get_current (WListbox * l, char **string, void **extra) 701 736 if (l != NULL) 702 737 e = listbox_get_nth_item (l, l->pos); 703 738 704 ok = (e != NULL );739 ok = (e != NULL && e->index != -2); 705 740 706 741 if (string != NULL) 707 742 *string = ok ? e->text : NULL; … … listbox_get_nth_item (const WListbox * l, int pos) 720 755 GList *item; 721 756 722 757 item = g_queue_peek_nth_link (l->list, (guint) pos); 723 if (item != NULL )758 if (item != NULL && LENTRY (item->data)->index != -2) 724 759 return LENTRY (item->data); 725 760 } 726 761 … … listbox_remove_list (WListbox * l) 802 837 803 838 /* --------------------------------------------------------------------------------------------- */ 804 839 840 /* 841 * Initializes the listbox elements with their position index. This allows to alter (filter, in 842 * particular) the listbox elements order and still get the original index (when selecting an 843 * element). 844 */ 845 void 846 listbox_init_indices (WListbox * l) 847 { 848 int index = 0; 849 g_queue_foreach (l->list, listbox_foreach_apply_index, &index); 850 } 851 852 /* --------------------------------------------------------------------------------------------- */ 853 805 854 char * 806 855 listbox_add_item (WListbox * l, listbox_append_t pos, int hotkey, const char *text, void *data, 807 856 gboolean free_data) … … listbox_add_item (WListbox * l, listbox_append_t pos, int hotkey, const char *te 815 864 return NULL; 816 865 817 866 entry = g_new (WLEntry, 1); 867 entry->index = -1; /* Will be initialized when switching to the filter state */ 818 868 entry->text = g_strdup (text); 869 entry->free_text = 1; 819 870 entry->data = data; 820 871 entry->free_data = free_data; 821 872 entry->hotkey = hotkey; -
lib/widget/listbox.h
diff --git a/lib/widget/listbox.h b/lib/widget/listbox.h index 8b2236eff..263d2c06e 100644
a b typedef lcback_ret_t (*lcback_fn) (struct WListbox * l); 35 35 36 36 typedef struct WLEntry 37 37 { 38 int index; /* The location in the list (used when it's filtered) */ 38 39 char *text; /* Text to display */ 40 gboolean free_text; /* Whether to free the text on entry's removal */ 39 41 int hotkey; 40 42 void *data; /* Client information */ 41 43 gboolean free_data; /* Whether to free the data on entry's removal */ … … typedef struct WListbox 46 48 Widget widget; 47 49 GQueue *list; /* Pointer to the list of WLEntry */ 48 50 int pos; /* The current element displayed */ 51 int virtual_pos; /* The initial index of the current element, works also for filtered listbox */ 49 52 int top; /* The first element displayed */ 50 53 gboolean allow_duplicates; /* Do we allow duplicates on the list? */ 51 54 gboolean scrollbar; /* Draw a scrollbar? */ … … extern const global_keymap_t *listbox_map; 60 63 61 64 /*** declarations of public functions ************************************************************/ 62 65 66 void listbox_init (WListbox * l, int y, int x, int height, int width, gboolean deletable, 67 lcback_fn callback); 63 68 WListbox *listbox_new (int y, int x, int height, int width, gboolean deletable, lcback_fn callback); 69 cb_ret_t listbox_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data); 70 64 71 int listbox_search_text (WListbox * l, const char *text); 65 72 int listbox_search_data (WListbox * l, const void *data); 66 73 void listbox_select_first (WListbox * l); … … void listbox_remove_current (WListbox * l); 74 81 gboolean listbox_is_empty (const WListbox * l); 75 82 void listbox_set_list (WListbox * l, GQueue * list); 76 83 void listbox_remove_list (WListbox * l); 84 void listbox_init_indices (WListbox * l); 77 85 char *listbox_add_item (WListbox * l, listbox_append_t pos, int hotkey, const char *text, 78 86 void *data, gboolean free_data); 79 87 -
lib/widget/widget-common.c
diff --git a/lib/widget/widget-common.c b/lib/widget/widget-common.c index e2fcd1222..8dd4a0d30 100644
a b widget_init (Widget * w, int y, int x, int lines, int cols, 338 338 w->find_by_type = widget_default_find_by_type; 339 339 w->find_by_id = widget_default_find_by_id; 340 340 341 w->pre_unlink_func = NULL; 342 341 343 w->set_state = widget_default_set_state; 342 344 w->get_colors = widget_default_get_colors; 343 345 } -
lib/widget/widget-common.h
diff --git a/lib/widget/widget-common.h b/lib/widget/widget-common.h index a20bcd671..28abfba39 100644
a b typedef enum 42 42 MSG_POST_KEY, /* The key has been handled */ 43 43 MSG_ACTION, /* Send to widget to handle command */ 44 44 MSG_NOTIFY, /* Typically sent to dialog to inform it of state-change 45 * of listboxes, check- and radiobuttons. */ 45 * of listboxes, check- and radiobuttons. Also from input 46 * to paired listbox when query of MultiSearch changes. */ 46 47 MSG_CURSOR, /* Sent to widget to position the cursor */ 47 48 MSG_IDLE, /* The idle state is active */ 48 49 MSG_RESIZE, /* Screen size has changed */ … … typedef enum 88 89 WST_CONSTRUCT = (1 << 15), /* Widget has been constructed but not run yet */ 89 90 WST_ACTIVE = (1 << 16), /* Dialog is visible and active */ 90 91 WST_SUSPENDED = (1 << 17), /* Dialog is suspended */ 91 WST_CLOSED = (1 << 18) /* Dialog is closed */ 92 WST_CLOSED = (1 << 18), /* Dialog is closed */ 93 94 WST_FILTER = (1 << 19) /* Listbox is filtering its contents */ 92 95 } widget_state_t; 93 96 94 97 /* Flags for widget repositioning on dialog resize */ … … typedef cb_ret_t (*widget_cb_fn) (Widget * widget, Widget * sender, widget_msg_t 125 128 typedef void (*widget_mouse_cb_fn) (Widget * w, mouse_msg_t msg, mouse_event_t * event); 126 129 /* translate mouse event and process it */ 127 130 typedef int (*widget_mouse_handle_fn) (Widget * w, Gpm_Event * event); 131 /* Pre unlinking (removing from a WGroup) callback. */ 132 typedef void (*pre_widget_unlink_cb) (Widget * w); 128 133 129 134 /* Every Widget must have this as its first element */ 130 135 struct Widget … … struct Widget 165 170 cb_ret_t (*set_state) (Widget * w, widget_state_t state, gboolean enable); 166 171 /* *INDENT-ON* */ 167 172 173 pre_widget_unlink_cb pre_unlink_func; /* a function invoked right before removing from a WGroup by 174 * group_remove_widget; it can unregister any events, which 175 * is an operation that depends on the `event_group` field of 176 * the group, so it cannot be done «after» widget has been 177 * removed from it (i.e.: when w.owner has been set to 0) */ 178 168 179 const int *(*get_colors) (const Widget * w); 169 180 }; 170 181 -
src/editor/choosesyntax.c
diff --git a/src/editor/choosesyntax.c b/src/editor/choosesyntax.c index 09b6d75d5..71ec44e12 100644
a b exec_edit_syntax_dialog (const GPtrArray * names, const char *current_syntax) 84 84 name = g_ptr_array_index (names, i); 85 85 LISTBOX_APPEND_TEXT (syntaxlist, 0, name, NULL, FALSE); 86 86 if (current_syntax != NULL && strcmp (name, current_syntax) == 0) 87 listbox_select_entry ( syntaxlist->list, i + N_DFLT_ENTRIES);87 listbox_select_entry (LISTBOX (syntaxlist->list), i + N_DFLT_ENTRIES); 88 88 } 89 89 90 90 return run_listbox (syntaxlist); -
src/editor/editcmd_dialogs.c
diff --git a/src/editor/editcmd_dialogs.c b/src/editor/editcmd_dialogs.c index 8b3634f23..2bfb71900 100644
a b editcmd_dialog_completion_show (const WEdit * edit, int max_len, GString ** comp 351 351 int start_x, start_y, offset, i; 352 352 char *curr = NULL; 353 353 WDialog *compl_dlg; 354 WListbox *compl_list; 354 WFilteringListbox *compl_list; 355 WListbox *lw; 355 356 int compl_dlg_h; /* completion dialog height */ 356 357 int compl_dlg_w; /* completion dialog width */ 357 358 … … editcmd_dialog_completion_show (const WEdit * edit, int max_len, GString ** comp 384 385 dialog_colors, NULL, NULL, "[Completion]", NULL); 385 386 386 387 /* create the listbox */ 387 compl_list = listbox_new (1, 1, compl_dlg_h - 2, compl_dlg_w - 2, FALSE, NULL); 388 compl_list = filtering_listbox_new (1, 1, compl_dlg_h - 2, compl_dlg_w - 2, FALSE, NULL, 389 FILT_LIST_DIALOG_AUTO_RESIZE); 390 391 /* Save WListbox pointer for convenience. */ 392 lw = LISTBOX (compl_list); 388 393 389 394 /* add the dialog */ 390 395 group_add_widget (GROUP (compl_dlg), compl_list); 391 396 392 397 /* fill the listbox with the completions */ 393 398 for (i = num_compl - 1; i >= 0; i--) /* reverse order */ 394 listbox_add_item (compl_list, LISTBOX_APPEND_AT_END, 0, (char *) compl[i]->str, NULL, 395 FALSE); 399 listbox_add_item (lw, LISTBOX_APPEND_AT_END, 0, (char *) compl[i]->str, NULL, FALSE); 396 400 397 401 /* pop up the dialog and apply the chosen completion */ 398 402 if (dlg_run (compl_dlg) == B_ENTER) 399 403 { 400 listbox_get_current ( compl_list, &curr, NULL);404 listbox_get_current (lw, &curr, NULL); 401 405 curr = g_strdup (curr); 402 406 } 403 407 -
src/editor/editwidget.c
diff --git a/src/editor/editwidget.c b/src/editor/editwidget.c index 18ac00e66..f1989114a 100644
a b edit_window_list (const WDialog * h) 302 302 Listbox *listbox; 303 303 GList *w; 304 304 WEdit *selected; 305 WListbox *lw; 305 306 int i = 0; 306 307 307 308 lines = MIN ((size_t) (LINES * 2 / 3), dlg_num); … … edit_window_list (const WDialog * h) 309 310 310 311 listbox = create_listbox_window (lines, cols, _("Open files"), "[Open files]"); 311 312 313 /* Convenience variable. */ 314 lw = LISTBOX (listbox->list); 315 312 316 for (w = g->widgets; w != NULL; w = g_list_next (w)) 313 317 if (edit_widget_is_editor (CONST_WIDGET (w->data))) 314 318 { … … edit_window_list (const WDialog * h) 322 326 g_strdup_printf ("%c%s", e->modified ? '*' : ' ', 323 327 vfs_path_as_str (e->filename_vpath)); 324 328 325 listbox_add_item (l istbox->list, LISTBOX_APPEND_AT_END, get_hotkey (i++),326 str_term_trim (fname, WIDGET (l istbox->list)->cols - 2), e, FALSE);329 listbox_add_item (lw, LISTBOX_APPEND_AT_END, get_hotkey (i++), 330 str_term_trim (fname, WIDGET (lw)->cols - 2), e, FALSE); 327 331 g_free (fname); 328 332 } 329 333 -
src/file_history.c
diff --git a/src/file_history.c b/src/file_history.c index 4304655aa..e5751ab8a 100644
a b file_history_create_item (history_descriptor_t * hd, void *data) 155 155 width = str_term_width1 (fhd->file_name); 156 156 hd->max_width = MAX (width, hd->max_width); 157 157 158 listbox_add_item (hd->listbox, LISTBOX_APPEND_AT_END, 0, fhd->file_name, fhd->file_pos, TRUE); 158 listbox_add_item (LISTBOX (hd->listbox), LISTBOX_APPEND_AT_END, 0, fhd->file_name, 159 fhd->file_pos, TRUE); 159 160 /* fhd->file_pos is not copied, NULLize it to prevent double free */ 160 161 fhd->file_pos = NULL; 161 162 } -
src/keybind-defaults.c
diff --git a/src/keybind-defaults.c b/src/keybind-defaults.c index 7b87c2f5a..2972e5bbf 100644
a b static const global_keymap_ini_t default_listbox_keymap[] = { 293 293 {"Bottom", "end; alt-gt; c1"}, 294 294 {"PageUp", "pgup; alt-v"}, 295 295 {"PageDown", "pgdn; ctrl-v"}, 296 {"Delete", "delete ; d"},297 {"Clear", "shift-delete ; shift-d"},296 {"Delete", "delete"}, 297 {"Clear", "shift-delete"}, 298 298 {"View", "f3"}, 299 299 {"Edit", "f4"}, 300 {"MultiSearch", "alt-space; ctrl-space"}, 300 301 {"Enter", "enter"}, 301 302 {NULL, NULL} 302 303 }; -
src/selcodepage.c
diff --git a/src/selcodepage.c b/src/selcodepage.c index eba9d25bb..9ce48325b 100644
a b select_charset (int center_y, int center_x, int current_charset, gboolean seldis 107 107 ? ((current_charset < 0) ? codepages->len : (size_t) current_charset) 108 108 : ((size_t) current_charset + 1); 109 109 110 listbox_select_entry ( listbox->list, i);110 listbox_select_entry (LISTBOX (listbox->list), i); 111 111 112 112 listbox_result = run_listbox (listbox); 113 113 -
src/usermenu.c
diff --git a/src/usermenu.c b/src/usermenu.c index 1fecbeaac..ba10634ab 100644
a b user_menu_cmd (const WEdit * edit_widget, const char *menu_file, int selected_en 1122 1122 extract_line (p, p + MAX_ENTRY_LEN), p, FALSE); 1123 1123 } 1124 1124 /* Select the default entry */ 1125 listbox_select_entry ( listbox->list, selected);1125 listbox_select_entry (LISTBOX (listbox->list), selected); 1126 1126 1127 1127 selected = run_listbox (listbox); 1128 1128 }