NeoMutt  2025-12-11-1009-ga75d9e
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
functions_sidebar.c
Go to the documentation of this file.
1
23
29
30#include "config.h"
31#include <stdbool.h>
32#include <string.h>
33#include "private.h"
34#include "mutt/lib.h"
35#include "config/lib.h"
36#include "core/lib.h"
37#include "gui/lib.h"
38#include "functions_sidebar.h"
39#include "lib.h"
40#include "editor/lib.h"
41#include "history/lib.h"
42#include "index/lib.h"
43#include "key/lib.h"
44#include "menu/lib.h"
45#include "functions_fuzzy.h"
46#include "module_data.h"
47
48// clang-format off
52static const struct MenuFuncOp OpSidebar[] = { /* map: sidebar */
53 { "sidebar-first", OP_SIDEBAR_FIRST },
54 { "sidebar-last", OP_SIDEBAR_LAST },
55 { "sidebar-next", OP_SIDEBAR_NEXT },
56 { "sidebar-next-new", OP_SIDEBAR_NEXT_NEW },
57 { "sidebar-open", OP_SIDEBAR_OPEN },
58 { "sidebar-page-down", OP_SIDEBAR_PAGE_DOWN },
59 { "sidebar-page-up", OP_SIDEBAR_PAGE_UP },
60 { "sidebar-prev", OP_SIDEBAR_PREV },
61 { "sidebar-prev-new", OP_SIDEBAR_PREV_NEW },
62 { "sidebar-scroll-half-down", OP_SIDEBAR_SCROLL_HALF_DOWN },
63 { "sidebar-scroll-half-up", OP_SIDEBAR_SCROLL_HALF_UP },
64 { "sidebar-scroll-line-down", OP_SIDEBAR_SCROLL_LINE_DOWN },
65 { "sidebar-scroll-line-up", OP_SIDEBAR_SCROLL_LINE_UP },
66 { "sidebar-scroll-selection-to-bottom", OP_SIDEBAR_SCROLL_SELECTION_TO_BOTTOM },
67 { "sidebar-scroll-selection-to-middle", OP_SIDEBAR_SCROLL_SELECTION_TO_MIDDLE },
68 { "sidebar-scroll-selection-to-top", OP_SIDEBAR_SCROLL_SELECTION_TO_TOP },
69 { "sidebar-select-entry-by-number", OP_SIDEBAR_SELECT_ENTRY_BY_NUMBER },
70 { "sidebar-select-page-bottom", OP_SIDEBAR_SELECT_PAGE_BOTTOM },
71 { "sidebar-select-page-middle", OP_SIDEBAR_SELECT_PAGE_MIDDLE },
72 { "sidebar-select-page-top", OP_SIDEBAR_SELECT_PAGE_TOP },
73 { "sidebar-start-search", OP_SIDEBAR_START_SEARCH },
74 { "sidebar-toggle-virtual", OP_SIDEBAR_TOGGLE_VIRTUAL },
75 { "sidebar-toggle-visible", OP_SIDEBAR_TOGGLE_VISIBLE },
76 { NULL, 0 },
77};
78
82const struct MenuOpSeq SidebarDefaultBindings[] = { /* map: sidebar */
83 { 0, NULL },
84};
85// clang-format on
86
90void sidebar_init_keys(struct NeoMutt *n, struct SubMenu *sm_generic)
91{
93 ASSERT(mod_data);
94
95 struct MenuDefinition *md = NULL;
96 struct SubMenu *sm = NULL;
97 struct SubMenu *sm_editor = editor_get_submenu();
98 ASSERT(sm_editor);
99
101 md = km_register_menu(MENU_SIDEBAR, "sidebar");
102 km_menu_add_submenu(md, sm);
103 km_menu_add_submenu(md, sm_editor);
105
106 mod_data->md_sidebar = md;
107 mod_data->sm_sidebar = sm;
108}
109
115{
117 ASSERT(mod_data);
118
119 return mod_data->sm_sidebar;
120}
121
127bool sb_next(struct SidebarWindowData *wdata)
128{
129 struct SbEntry **sbep = NULL;
130 ARRAY_FOREACH_FROM(sbep, &wdata->entries, wdata->hil_index + 1)
131 {
132 if (!(*sbep)->is_hidden)
133 {
134 wdata->hil_index = ARRAY_FOREACH_IDX_sbep;
135 return true;
136 }
137 }
138
139 return false;
140}
141
149static bool sb_next_n(struct SidebarWindowData *wdata, int count)
150{
151 int orig = wdata->hil_index;
152 for (int i = 0; i < count; i++)
153 {
154 if (!sb_next(wdata))
155 break;
156 }
157 return (wdata->hil_index != orig);
158}
159
167static bool sb_prev_n(struct SidebarWindowData *wdata, int count)
168{
169 int orig = wdata->hil_index;
170 for (int i = 0; i < count; i++)
171 {
172 if (!sb_prev(wdata))
173 break;
174 }
175 return (wdata->hil_index != orig);
176}
177
186static struct SbEntry **sb_next_new(struct SidebarWindowData *wdata, size_t begin, size_t end)
187{
188 struct SbEntry **sbep = NULL;
189 ARRAY_FOREACH_FROM_TO(sbep, &wdata->entries, begin, end)
190 {
191 if ((*sbep)->mailbox->has_new || ((*sbep)->mailbox->msg_unread != 0))
192 return sbep;
193 }
194 return NULL;
195}
196
202bool sb_prev(struct SidebarWindowData *wdata)
203{
204 struct SbEntry **sbep = NULL, **prev = NULL;
205 ARRAY_FOREACH_TO(sbep, &wdata->entries, wdata->hil_index)
206 {
207 if (!(*sbep)->is_hidden)
208 prev = sbep;
209 }
210
211 if (prev)
212 {
213 wdata->hil_index = ARRAY_IDX(&wdata->entries, prev);
214 return true;
215 }
216
217 return false;
218}
219
228static struct SbEntry **sb_prev_new(struct SidebarWindowData *wdata, size_t begin, size_t end)
229{
230 struct SbEntry **sbep = NULL, **prev = NULL;
231 ARRAY_FOREACH_FROM_TO(sbep, &wdata->entries, begin, end)
232 {
233 if ((*sbep)->mailbox->has_new || ((*sbep)->mailbox->msg_unread != 0))
234 prev = sbep;
235 }
236
237 return prev;
238}
239
250static int sb_screen_row_index(struct SidebarWindowData *wdata, int wanted_row)
251{
252 if ((wdata->top_index < 0) || (wanted_row < 0))
253 return -1;
254
255 const int page_size = wdata->win->state.rows;
256 int row = 0;
257 int last = -1;
258
259 struct SbEntry **sbep = NULL;
260 ARRAY_FOREACH_FROM(sbep, &wdata->entries, wdata->top_index)
261 {
262 if (row >= page_size)
263 break;
264 if ((*sbep)->is_hidden)
265 continue;
266
267 last = ARRAY_FOREACH_IDX_sbep;
268 if (row == wanted_row)
269 return last;
270 row++;
271 }
272
273 return last; // clamp to the last visible entry on the page
274}
275
283static int sb_index_visible_before(struct SidebarWindowData *wdata, int index, int count)
284{
285 int top = index;
286 for (int i = 0; i < count; i++)
287 {
288 int prev = -1;
289 struct SbEntry **sbep = NULL;
290 ARRAY_FOREACH_TO(sbep, &wdata->entries, top)
291 {
292 if (!(*sbep)->is_hidden)
293 prev = ARRAY_FOREACH_IDX_sbep;
294 }
295
296 if (prev < 0)
297 break;
298 top = prev;
299 }
300
301 return top;
302}
303
311static int sb_index_visible_after(struct SidebarWindowData *wdata, int index, int count)
312{
313 int pos = index;
314 for (int i = 0; i < count; i++)
315 {
316 int next = -1;
317 struct SbEntry **sbep = NULL;
318 ARRAY_FOREACH_FROM(sbep, &wdata->entries, pos + 1)
319 {
320 if (!(*sbep)->is_hidden)
321 {
322 next = ARRAY_FOREACH_IDX_sbep;
323 break;
324 }
325 }
326
327 if (next < 0)
328 break;
329 pos = next;
330 }
331
332 return pos;
333}
334
341static int sb_last_visible(struct SidebarWindowData *wdata)
342{
343 int last = -1;
344 struct SbEntry **sbep = NULL;
345 ARRAY_FOREACH(sbep, &wdata->entries)
346 {
347 if (!(*sbep)->is_hidden)
348 last = ARRAY_FOREACH_IDX_sbep;
349 }
350
351 return last;
352}
353
364static int sb_scroll_view(struct SidebarFunctionData *fdata, int delta)
365{
366 struct SidebarWindowData *wdata = fdata->wdata;
367 if (!mutt_window_is_visible(wdata->win))
368 return FR_NO_ACTION;
369
370 if (ARRAY_EMPTY(&wdata->entries) || (wdata->hil_index < 0) || (wdata->top_index < 0))
371 return FR_NO_ACTION;
372
373 const int page_size = wdata->win->state.rows;
374
375 int new_top;
376 if (delta < 0)
377 new_top = sb_index_visible_before(wdata, wdata->top_index, -delta);
378 else
379 new_top = sb_index_visible_after(wdata, wdata->top_index, delta);
380
381 /* Tie the last entry to the bottom of the screen (don't scroll into space) */
382 const int last = sb_last_visible(wdata);
383 if (last >= 0)
384 {
385 const int max_top = sb_index_visible_before(wdata, last, page_size - 1);
386 if (new_top > max_top)
387 new_top = max_top;
388 }
389
390 if (new_top == wdata->top_index)
391 return FR_NO_ACTION;
392
393 wdata->top_index = new_top;
394
395 /* Drag the selection into the visible range */
396 const int first = sb_screen_row_index(wdata, 0);
397 const int bottom = sb_screen_row_index(wdata, page_size - 1);
398 if ((first >= 0) && (wdata->hil_index < first))
399 wdata->hil_index = first;
400 else if ((bottom >= 0) && (wdata->hil_index > bottom))
401 wdata->hil_index = bottom;
402
403 wdata->win->actions |= WA_RECALC;
404 return FR_SUCCESS;
405}
406
407// -----------------------------------------------------------------------------
408
412int op_sidebar_first(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
413{
414 struct SidebarWindowData *wdata = fdata->wdata;
415 if (!mutt_window_is_visible(wdata->win))
416 return FR_NO_ACTION;
417
418 if (ARRAY_EMPTY(&wdata->entries) || (wdata->hil_index < 0))
419 return FR_NO_ACTION;
420
421 int orig_hil_index = wdata->hil_index;
422
423 wdata->hil_index = 0;
424 if ((*ARRAY_GET(&wdata->entries, wdata->hil_index))->is_hidden)
425 if (!sb_next(wdata))
426 wdata->hil_index = orig_hil_index;
427
428 if (orig_hil_index == wdata->hil_index)
429 return FR_NO_ACTION;
430
431 wdata->win->actions |= WA_RECALC;
432 return FR_SUCCESS;
433}
434
439 const struct KeyEvent *event)
440{
441 struct SidebarWindowData *wdata = fdata->wdata;
442 if (!mutt_window_is_visible(wdata->win))
443 return FR_NO_ACTION;
444
445 if (ARRAY_EMPTY(&wdata->entries) || (wdata->hil_index < 0))
446 {
447 mutt_error(_("There are no mailboxes"));
448 return FR_ERROR;
449 }
450
451 const int count = ARRAY_SIZE(&wdata->entries);
452 struct Buffer *buf = buf_pool_get();
453 int rc = FR_ERROR;
454
455 int num = event->count;
456 if (num == 0)
457 {
458 if ((mw_get_field(_("Jump to: "), buf, MUTT_COMP_NONE, HC_OTHER, NULL, NULL) != 0) ||
459 buf_is_empty(buf))
460 {
461 rc = FR_NO_ACTION;
462 goto done;
463 }
464
465 if (!mutt_str_atoi_full(buf_string(buf), &num))
466 {
467 mutt_error(_("Invalid index number"));
468 goto done;
469 }
470 }
471
472 if ((num < 1) || (num > count))
473 {
474 mutt_error(_("Invalid index number"));
475 goto done;
476 }
477
478 if ((num - 1) == wdata->hil_index)
479 {
480 rc = FR_NO_ACTION;
481 goto done;
482 }
483
484 wdata->hil_index = num - 1; // entry numbers are 1-based
485 wdata->win->actions |= WA_RECALC;
486 rc = op_sidebar_open(fdata, event);
487
488done:
489 buf_pool_release(&buf);
490 return rc;
491}
492
496int op_sidebar_last(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
497{
498 struct SidebarWindowData *wdata = fdata->wdata;
499 if (!mutt_window_is_visible(wdata->win))
500 return FR_NO_ACTION;
501
502 if (ARRAY_EMPTY(&wdata->entries) || (wdata->hil_index < 0))
503 return FR_NO_ACTION;
504
505 int orig_hil_index = wdata->hil_index;
506
507 wdata->hil_index = ARRAY_SIZE(&wdata->entries);
508 if (!sb_prev(wdata))
509 wdata->hil_index = orig_hil_index;
510
511 if (orig_hil_index == wdata->hil_index)
512 return FR_NO_ACTION;
513
514 wdata->win->actions |= WA_RECALC;
515 return FR_SUCCESS;
516}
517
521int op_sidebar_next(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
522{
523 struct SidebarWindowData *wdata = fdata->wdata;
524 if (!mutt_window_is_visible(wdata->win))
525 return FR_NO_ACTION;
526
527 if (ARRAY_EMPTY(&wdata->entries) || (wdata->hil_index < 0))
528 return FR_NO_ACTION;
529
530 const int count = event->count;
531 if (count > 0)
532 {
533 if (!sb_next_n(wdata, count))
534 return FR_NO_ACTION;
535 }
536 else
537 {
538 if (!sb_next(wdata))
539 {
540 mutt_message(_("You are on the last entry"));
541 return FR_ERROR;
542 }
543 }
544
545 wdata->win->actions |= WA_RECALC;
546 return FR_SUCCESS;
547}
548
554static int op_sidebar_next_new(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
555{
556 struct SidebarWindowData *wdata = fdata->wdata;
557 if (!mutt_window_is_visible(wdata->win))
558 return FR_NO_ACTION;
559
560 const size_t max_entries = ARRAY_SIZE(&wdata->entries);
561 if ((max_entries == 0) || (wdata->hil_index < 0))
562 return FR_NO_ACTION;
563
564 const int count = MAX(event->count, 1);
565 const bool c_sidebar_next_new_wrap = cs_subset_bool(fdata->n->sub, "sidebar_next_new_wrap");
566 int orig_hil_index = wdata->hil_index;
567
568 for (int i = 0; i < count; i++)
569 {
570 struct SbEntry **sbep = NULL;
571 if ((sbep = sb_next_new(wdata, wdata->hil_index + 1, max_entries)) ||
572 (c_sidebar_next_new_wrap && (sbep = sb_next_new(wdata, 0, wdata->hil_index))))
573 {
574 wdata->hil_index = ARRAY_IDX(&wdata->entries, sbep);
575 }
576 else
577 {
578 break;
579 }
580 }
581
582 if (wdata->hil_index == orig_hil_index)
583 return FR_NO_ACTION;
584
585 wdata->win->actions |= WA_RECALC;
586 return FR_SUCCESS;
587}
588
592int op_sidebar_open(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
593{
594 struct SidebarWindowData *wdata = fdata->wdata;
595 struct MuttWindow *win_sidebar = wdata->win;
596 if (!mutt_window_is_visible(win_sidebar))
597 return FR_NO_ACTION;
598
599 struct MuttWindow *dlg = dialog_find(win_sidebar);
600 index_change_folder(dlg, sb_get_highlight(win_sidebar));
601 return FR_SUCCESS;
602}
603
607int op_sidebar_prev(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
608{
609 struct SidebarWindowData *wdata = fdata->wdata;
610 if (!mutt_window_is_visible(wdata->win))
611 return FR_NO_ACTION;
612
613 if (ARRAY_EMPTY(&wdata->entries) || (wdata->hil_index < 0))
614 return FR_NO_ACTION;
615
616 const int count = event->count;
617 if (count > 0)
618 {
619 if (!sb_prev_n(wdata, count))
620 return FR_NO_ACTION;
621 }
622 else
623 {
624 if (!sb_prev(wdata))
625 {
626 mutt_message(_("You are on the first entry"));
627 return FR_ERROR;
628 }
629 }
630
631 wdata->win->actions |= WA_RECALC;
632 return FR_SUCCESS;
633}
634
640static int op_sidebar_prev_new(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
641{
642 struct SidebarWindowData *wdata = fdata->wdata;
643 if (!mutt_window_is_visible(wdata->win))
644 return FR_NO_ACTION;
645
646 const size_t max_entries = ARRAY_SIZE(&wdata->entries);
647 if ((max_entries == 0) || (wdata->hil_index < 0))
648 return FR_NO_ACTION;
649
650 const int count = MAX(event->count, 1);
651 const bool c_sidebar_next_new_wrap = cs_subset_bool(fdata->n->sub, "sidebar_next_new_wrap");
652 int orig_hil_index = wdata->hil_index;
653
654 for (int i = 0; i < count; i++)
655 {
656 struct SbEntry **sbep = NULL;
657 if ((sbep = sb_prev_new(wdata, 0, wdata->hil_index)) ||
658 (c_sidebar_next_new_wrap &&
659 (sbep = sb_prev_new(wdata, wdata->hil_index + 1, max_entries))))
660 {
661 wdata->hil_index = ARRAY_IDX(&wdata->entries, sbep);
662 }
663 else
664 {
665 break;
666 }
667 }
668
669 if (wdata->hil_index == orig_hil_index)
670 return FR_NO_ACTION;
671
672 wdata->win->actions |= WA_RECALC;
673 return FR_SUCCESS;
674}
675
680 const struct KeyEvent *event)
681{
682 struct SidebarWindowData *wdata = fdata->wdata;
683 if (!mutt_window_is_visible(wdata->win))
684 return FR_NO_ACTION;
685
686 if (ARRAY_EMPTY(&wdata->entries) || (wdata->hil_index < 0) || (wdata->top_index < 0))
687 return FR_NO_ACTION;
688
689 const int index = sb_screen_row_index(wdata, 0);
690 if ((index < 0) || (index == wdata->hil_index))
691 return FR_NO_ACTION;
692
693 wdata->hil_index = index;
694 wdata->win->actions |= WA_RECALC;
695 return FR_SUCCESS;
696}
697
702 const struct KeyEvent *event)
703{
704 struct SidebarWindowData *wdata = fdata->wdata;
705 if (!mutt_window_is_visible(wdata->win))
706 return FR_NO_ACTION;
707
708 if (ARRAY_EMPTY(&wdata->entries) || (wdata->hil_index < 0) || (wdata->top_index < 0))
709 return FR_NO_ACTION;
710
711 const int index = sb_screen_row_index(wdata, wdata->win->state.rows / 2);
712 if ((index < 0) || (index == wdata->hil_index))
713 return FR_NO_ACTION;
714
715 wdata->hil_index = index;
716 wdata->win->actions |= WA_RECALC;
717 return FR_SUCCESS;
718}
719
724 const struct KeyEvent *event)
725{
726 struct SidebarWindowData *wdata = fdata->wdata;
727 if (!mutt_window_is_visible(wdata->win))
728 return FR_NO_ACTION;
729
730 if (ARRAY_EMPTY(&wdata->entries) || (wdata->hil_index < 0) || (wdata->top_index < 0))
731 return FR_NO_ACTION;
732
733 const int index = sb_screen_row_index(wdata, wdata->win->state.rows - 1);
734 if ((index < 0) || (index == wdata->hil_index))
735 return FR_NO_ACTION;
736
737 wdata->hil_index = index;
738 wdata->win->actions |= WA_RECALC;
739 return FR_SUCCESS;
740}
741
746 const struct KeyEvent *event)
747{
748 const int half_page = MAX(fdata->wdata->win->state.rows / 2, 1);
749 return sb_scroll_view(fdata, MAX(event->count, 1) * half_page);
750}
751
756 const struct KeyEvent *event)
757{
758 const int half_page = MAX(fdata->wdata->win->state.rows / 2, 1);
759 return sb_scroll_view(fdata, 0 - MAX(event->count, 1) * half_page);
760}
761
766 const struct KeyEvent *event)
767{
768 return sb_scroll_view(fdata, MAX(event->count, 1));
769}
770
775 const struct KeyEvent *event)
776{
777 return sb_scroll_view(fdata, 0 - MAX(event->count, 1));
778}
779
783int op_sidebar_scroll_page_down(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
784{
785 const int page = MAX(fdata->wdata->win->state.rows, 1);
786 return sb_scroll_view(fdata, MAX(event->count, 1) * page);
787}
788
792int op_sidebar_scroll_page_up(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
793{
794 const int page = MAX(fdata->wdata->win->state.rows, 1);
795 return sb_scroll_view(fdata, 0 - MAX(event->count, 1) * page);
796}
797
806static int sb_scroll_selection_to_row(struct SidebarFunctionData *fdata, int wanted_row)
807{
808 struct SidebarWindowData *wdata = fdata->wdata;
809 if (!mutt_window_is_visible(wdata->win))
810 return FR_NO_ACTION;
811
812 if (ARRAY_EMPTY(&wdata->entries) || (wdata->hil_index < 0))
813 return FR_NO_ACTION;
814
815 const int new_top = sb_index_visible_before(wdata, wdata->hil_index, wanted_row);
816 if (new_top == wdata->top_index)
817 return FR_NO_ACTION;
818
819 wdata->top_index = new_top;
820 wdata->win->actions |= WA_RECALC;
821 return FR_SUCCESS;
822}
823
828 const struct KeyEvent *event)
829{
830 return sb_scroll_selection_to_row(fdata, 0);
831}
832
837 const struct KeyEvent *event)
838{
839 return sb_scroll_selection_to_row(fdata, fdata->wdata->win->state.rows / 2);
840}
841
846 const struct KeyEvent *event)
847{
848 return sb_scroll_selection_to_row(fdata, fdata->wdata->win->state.rows - 1);
849}
850
855 const struct KeyEvent *event)
856{
857 bool_str_toggle(fdata->n->sub, "sidebar_visible", NULL);
858 mutt_window_reflow(NULL);
859 return FR_SUCCESS;
860}
861
866 const struct KeyEvent *event)
867{
868 return FR_SUCCESS;
869}
870
871// -----------------------------------------------------------------------------
872
876static const struct SidebarFunction SidebarFunctions[] = {
877 // clang-format off
878 { OP_SIDEBAR_FIRST, op_sidebar_first },
879 { OP_SIDEBAR_LAST, op_sidebar_last },
880 { OP_SIDEBAR_NEXT, op_sidebar_next },
881 { OP_SIDEBAR_NEXT_NEW, op_sidebar_next_new },
882 { OP_SIDEBAR_OPEN, op_sidebar_open },
883 { OP_SIDEBAR_PAGE_DOWN, op_sidebar_scroll_page_down },
884 { OP_SIDEBAR_PAGE_UP, op_sidebar_scroll_page_up },
885 { OP_SIDEBAR_PREV, op_sidebar_prev },
886 { OP_SIDEBAR_PREV_NEW, op_sidebar_prev_new },
887 { OP_SIDEBAR_SCROLL_HALF_DOWN, op_sidebar_scroll_half_down },
888 { OP_SIDEBAR_SCROLL_HALF_UP, op_sidebar_scroll_half_up },
889 { OP_SIDEBAR_SCROLL_LINE_DOWN, op_sidebar_scroll_line_down },
890 { OP_SIDEBAR_SCROLL_LINE_UP, op_sidebar_scroll_line_up },
891 { OP_SIDEBAR_SCROLL_SELECTION_TO_BOTTOM, op_sidebar_scroll_selection_to_bottom },
892 { OP_SIDEBAR_SCROLL_SELECTION_TO_MIDDLE, op_sidebar_scroll_selection_to_middle },
893 { OP_SIDEBAR_SCROLL_SELECTION_TO_TOP, op_sidebar_scroll_selection_to_top },
894 { OP_SIDEBAR_SELECT_ENTRY_BY_NUMBER, op_sidebar_select_entry_by_number },
895 { OP_SIDEBAR_SELECT_PAGE_BOTTOM, op_sidebar_select_page_bottom },
896 { OP_SIDEBAR_SELECT_PAGE_MIDDLE, op_sidebar_select_page_middle },
897 { OP_SIDEBAR_SELECT_PAGE_TOP, op_sidebar_select_page_top },
898 { OP_SIDEBAR_START_SEARCH, op_sidebar_start_search },
899 { OP_SIDEBAR_TOGGLE_VIRTUAL, op_sidebar_toggle_virtual },
900 { OP_SIDEBAR_TOGGLE_VISIBLE, op_sidebar_toggle_visible },
901 { 0, NULL },
902 // clang-format on
903};
904
908int sb_function_dispatcher(struct MuttWindow *win, const struct KeyEvent *event)
909{
910 if (!event || !win || !win->wdata)
911 return FR_UNKNOWN;
912
913 const int op = event->op;
914
916
917 struct SidebarFunctionData fdata = {
918 .n = NeoMutt,
919 .mod_data = mod_data,
920 .wdata = win->wdata,
921 };
922
923 int rc = FR_UNKNOWN;
924 for (size_t i = 0; SidebarFunctions[i].op != OP_NULL; i++)
925 {
926 const struct SidebarFunction *fn = &SidebarFunctions[i];
927 if (fn->op == op)
928 {
929 rc = fn->function(&fdata, event);
930 break;
931 }
932 }
933
934 if (rc == FR_UNKNOWN) // Not our function
935 return rc;
936
937 const char *result = dispatcher_get_retval_name(rc);
938 mutt_debug(LL_DEBUG1, "Handled %s (%d) -> %s\n", opcodes_get_name(op), op, NONULL(result));
939
941 return rc;
942}
#define ARRAY_IDX(head, elem)
Return the index of an element of the array.
Definition array.h:324
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:223
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition array.h:74
#define ARRAY_FOREACH_TO(elem, head, to)
Iterate from the beginning to an index.
Definition array.h:247
#define ARRAY_SIZE(head)
The number of elements stored.
Definition array.h:87
#define ARRAY_FOREACH_FROM(elem, head, from)
Iterate from an index to the end.
Definition array.h:235
#define ARRAY_GET(head, idx)
Return the element at index.
Definition array.h:109
#define ARRAY_FOREACH_FROM_TO(elem, head, from, to)
Iterate between two indexes.
Definition array.h:261
int bool_str_toggle(struct ConfigSubset *sub, const char *name, struct Buffer *err)
Toggle the value of a bool.
Definition bool.c:231
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:298
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
struct MuttWindow * dialog_find(struct MuttWindow *win)
Find the parent Dialog of a Window.
Definition dialog.c:89
const char * dispatcher_get_retval_name(int rv)
Get the name of a return value.
Definition dispatcher.c:55
void dispatcher_flush_on_error(int rv)
Flush pending keys after a dispatch error.
Definition dispatcher.c:65
@ FR_SUCCESS
Valid function - successfully performed.
Definition dispatcher.h:40
@ FR_UNKNOWN
Unknown function.
Definition dispatcher.h:34
@ FR_ERROR
Valid function - error occurred.
Definition dispatcher.h:39
@ FR_NO_ACTION
Valid function - no action performed.
Definition dispatcher.h:38
void index_change_folder(struct MuttWindow *dlg, struct Mailbox *m)
Change the current folder, cautiously.
Definition dlg_index.c:1490
struct SubMenu * editor_get_submenu(void)
Get the Editor SubMenu.
Definition functions.c:587
Edit a string.
@ MUTT_COMP_NONE
No flags are set.
Definition wdata.h:46
Sidebar fuzzy search functions.
static int sb_index_visible_after(struct SidebarWindowData *wdata, int index, int count)
Find the entry N unhidden entries after another.
static const struct SidebarFunction SidebarFunctions[]
All the NeoMutt functions that the Sidebar supports.
const struct MenuOpSeq SidebarDefaultBindings[]
Key bindings for the Sidebar Window.
bool sb_prev(struct SidebarWindowData *wdata)
Find the previous unhidden Mailbox.
static int sb_index_visible_before(struct SidebarWindowData *wdata, int index, int count)
Find the entry N unhidden entries before another.
void sidebar_init_keys(struct NeoMutt *n, struct SubMenu *sm_generic)
Initialise the Sidebar Keybindings - Implements init_keys_api.
static int sb_scroll_selection_to_row(struct SidebarFunctionData *fdata, int wanted_row)
Scroll the view so the selection is at a given row.
static struct SbEntry ** sb_prev_new(struct SidebarWindowData *wdata, size_t begin, size_t end)
Return the previous mailbox with new messages.
struct SubMenu * sidebar_get_submenu(void)
Get the Sidebar SubMenu.
static int sb_scroll_view(struct SidebarFunctionData *fdata, int delta)
Scroll the viewport, dragging the selection into view.
static int sb_screen_row_index(struct SidebarWindowData *wdata, int wanted_row)
Find the entry shown at a given row of the visible page.
static bool sb_next_n(struct SidebarWindowData *wdata, int count)
Move down N unhidden Mailboxes, capping at the last.
static int sb_last_visible(struct SidebarWindowData *wdata)
Find the last unhidden entry.
bool sb_next(struct SidebarWindowData *wdata)
Find the next unhidden Mailbox.
static bool sb_prev_n(struct SidebarWindowData *wdata, int count)
Move up N unhidden Mailboxes, capping at the first.
static const struct MenuFuncOp OpSidebar[]
Functions for the Sidebar Window.
static struct SbEntry ** sb_next_new(struct SidebarWindowData *wdata, size_t begin, size_t end)
Return the next mailbox with new messages.
Sidebar functions.
int sb_function_dispatcher(struct MuttWindow *win, const struct KeyEvent *event)
Perform a Sidebar function - Implements function_dispatcher_t -.
int mw_get_field(const char *prompt, struct Buffer *buf, CompletionFlags complete, enum HistoryClass hclass, const struct CompleteOps *comp_api, void *cdata)
Ask the user for a string -.
Definition window.c:502
#define mutt_error(...)
Definition logging2.h:94
#define mutt_message(...)
Definition logging2.h:93
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
int op_sidebar_start_search(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
Selects the last unhidden mailbox - Implements sidebar_function_t -.
static int op_sidebar_scroll_selection_to_middle(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
Scrolls so the selection is at the middle of the screen - Implements sidebar_function_t -.
int op_sidebar_open(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
Open highlighted mailbox - Implements sidebar_function_t -.
static int op_sidebar_scroll_selection_to_bottom(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
Scrolls so the selection is at the bottom of the screen - Implements sidebar_function_t -.
static int op_sidebar_scroll_half_up(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
Scrolls up by half a page - Implements sidebar_function_t -.
static int op_sidebar_select_page_middle(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
Selects the entry at the middle of the visible page - Implements sidebar_function_t -.
int op_sidebar_prev(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
Selects the previous unhidden mailbox - Implements sidebar_function_t -.
static int op_sidebar_toggle_visible(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
Make the sidebar (in)visible - Implements sidebar_function_t -.
int op_sidebar_scroll_page_down(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
Scrolls down by one page - Implements sidebar_function_t -.
static int op_sidebar_toggle_virtual(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
Deprecated - Implements sidebar_function_t -.
static int op_sidebar_select_page_top(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
Selects the entry at the top of the visible page - Implements sidebar_function_t -.
int op_sidebar_next(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
Selects the next unhidden mailbox - Implements sidebar_function_t -.
static int op_sidebar_scroll_line_down(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
Scrolls down by one line - Implements sidebar_function_t -.
int op_sidebar_first(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
Selects the first unhidden mailbox - Implements sidebar_function_t -.
static int op_sidebar_scroll_line_up(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
Scrolls up by one line - Implements sidebar_function_t -.
int op_sidebar_scroll_page_up(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
Scrolls up by one page - Implements sidebar_function_t -.
static int op_sidebar_scroll_selection_to_top(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
Scrolls so the selection is at the top of the screen - Implements sidebar_function_t -.
static int op_sidebar_scroll_half_down(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
Scrolls down by half a page - Implements sidebar_function_t -.
static int op_sidebar_next_new(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
Selects the next new mailbox - Implements sidebar_function_t -.
static int op_sidebar_prev_new(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
Selects the previous new mailbox - Implements sidebar_function_t -.
static int op_sidebar_select_page_bottom(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
Selects the entry at the bottom of the visible page - Implements sidebar_function_t -.
int op_sidebar_last(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
Selects the last unhidden mailbox - Implements sidebar_function_t -.
static int op_sidebar_select_entry_by_number(struct SidebarFunctionData *fdata, const struct KeyEvent *event)
Jump to a specific mailbox - Implements sidebar_function_t -.
Convenience wrapper for the gui headers.
Read/write command history from/to a file.
@ HC_OTHER
Miscellaneous strings.
Definition lib.h:61
GUI manage the main index (list of emails).
void km_menu_add_submenu(struct MenuDefinition *md, struct SubMenu *sm)
Add a SubMenu to a Menu Definition.
Definition init.c:123
struct SubMenu * km_register_submenu(const struct MenuFuncOp functions[])
Register a submenu.
Definition init.c:88
struct MenuDefinition * km_register_menu(int menu, const char *name)
Register a menu.
Definition init.c:105
void km_menu_add_bindings(struct MenuDefinition *md, const struct MenuOpSeq bindings[])
Add Keybindings to a Menu.
Definition init.c:136
Manage keymappings.
@ LL_DEBUG1
Log at debug level 1.
Definition logging2.h:45
#define MAX(a, b)
Return the maximum of two values.
Definition memory.h:38
GUI present the user with a selectable list.
@ MODULE_ID_SIDEBAR
ModuleSidebar, Sidebar
Definition module_api.h:93
Convenience wrapper for the library headers.
#define _(a)
Definition message.h:28
bool mutt_window_is_visible(struct MuttWindow *win)
Is the Window visible?
void mutt_window_reflow(struct MuttWindow *win)
Resize a Window and its children.
@ WA_RECALC
Recalculate the contents of the Window.
void * neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
Get the private data for a Module.
Definition neomutt.c:666
const char * opcodes_get_name(int op)
Get the name of an opcode.
Definition opcodes.c:48
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
GUI display the mailboxes in a side panel.
Sidebar private Module data.
GUI display the mailboxes in a side panel.
struct Mailbox * sb_get_highlight(struct MuttWindow *win)
Get the Mailbox that's highlighted in the sidebar.
Definition sidebar.c:73
#define ASSERT(COND)
Definition signal2.h:59
#define NONULL(x)
Definition string2.h:44
String manipulation buffer.
Definition buffer.h:36
An event such as a keypress.
Definition get.h:75
int count
Optional count prefix, e.g. 3 for 3j.
Definition get.h:78
Functions for a Dialog or Window.
Definition menudef.h:44
Mapping between a function and an operation.
Definition menu.h:37
Mapping between an operation and a key sequence.
Definition menu.h:47
struct WindowState state
Current state of the Window.
void * wdata
Private data.
WindowActionFlags actions
Actions to be performed, e.g. WA_RECALC.
Container for Accounts, Notifications.
Definition neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
Info about folders in the sidebar.
Definition private.h:40
Data passed to Sidebar worker functions.
struct SidebarWindowData * wdata
Sidebar window data.
struct NeoMutt * n
NeoMutt application data.
struct SidebarModuleData * mod_data
Sidebar module data.
A NeoMutt function.
int op
Op code, e.g. OP_SIDEBAR_NEXT.
sidebar_function_t function
Function to call.
Sidebar private Module data.
Definition module_data.h:32
struct MenuDefinition * md_sidebar
Sidebar Menu Definition.
Definition module_data.h:34
struct SubMenu * sm_sidebar
Sidebar functions.
Definition module_data.h:35
Sidebar private Window data -.
Definition private.h:90
int top_index
First mailbox visible in sidebar.
Definition private.h:95
int hil_index
Highlighted mailbox.
Definition private.h:97
struct MuttWindow * win
Sidebar Window.
Definition private.h:91
struct SbEntryArray entries
Items to display in the sidebar.
Definition private.h:93
Collection of related functions.
Definition menudef.h:33
short rows
Number of rows, can be MUTT_WIN_SIZE_UNLIMITED.
Definition mutt_window.h:61
@ MENU_SIDEBAR
Sidebar menu.
Definition type.h:51