NeoMutt  2025-12-11-980-ge38c27
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
window.c
Go to the documentation of this file.
1
27
68
69#include "config.h"
70#include <stdbool.h>
71#include <string.h>
72#include "private.h"
73#include "mutt/lib.h"
74#include "config/lib.h"
75#include "email/lib.h"
76#include "core/lib.h"
77#include "gui/lib.h"
78#include "color/lib.h"
79#include "expando/lib.h"
80#include "index/lib.h"
81#include "expando.h"
82#include "module_data.h"
83
90static int imap_is_prefix(const char *folder, const char *mbox)
91{
92 int plen = 0;
93
94 struct Url *url_m = url_parse(mbox);
95 struct Url *url_f = url_parse(folder);
96 if (!url_m || !url_f)
97 goto done;
98
99 if (!mutt_istr_equal(url_m->host, url_f->host))
100 goto done;
101
102 if (url_m->user && url_f->user && !mutt_istr_equal(url_m->user, url_f->user))
103 goto done;
104
105 size_t mlen = mutt_str_len(url_m->path);
106 size_t flen = mutt_str_len(url_f->path);
107 if (flen > mlen)
108 goto done;
109
110 if (!mutt_strn_equal(url_m->path, url_f->path, flen))
111 goto done;
112
113 plen = strlen(mbox) - mlen + flen;
114
115done:
116 url_free(&url_m);
117 url_free(&url_f);
118
119 return plen;
120}
121
129static const char *abbrev_folder(const char *mbox, const char *folder, enum MailboxType type)
130{
131 if (!mbox || !folder)
132 return NULL;
133
134 if (type == MUTT_IMAP)
135 {
136 int prefix = imap_is_prefix(folder, mbox);
137 if (prefix == 0)
138 return NULL;
139 return mbox + prefix;
140 }
141
142 const char *const c_sidebar_delim_chars = cs_subset_string(NeoMutt->sub, "sidebar_delim_chars");
143 if (!c_sidebar_delim_chars)
144 return NULL;
145
146 size_t flen = mutt_str_len(folder);
147 if (flen == 0)
148 return NULL;
149 if (strchr(c_sidebar_delim_chars, folder[flen - 1])) // folder ends with a delimiter
150 flen--;
151
152 size_t mlen = mutt_str_len(mbox);
153 if (mlen < flen)
154 return NULL;
155
156 if (!mutt_strn_equal(folder, mbox, flen))
157 return NULL;
158
159 // After the match, check that mbox has a delimiter
160 if (!strchr(c_sidebar_delim_chars, mbox[flen]))
161 return NULL;
162
163 if (mlen > flen)
164 {
165 return mbox + flen + 1;
166 }
167
168 // mbox and folder are equal, use the chunk after the last delimiter
169 while (mlen--)
170 {
171 if (strchr(c_sidebar_delim_chars, mbox[mlen]))
172 {
173 return mbox + mlen + 1;
174 }
175 }
176
177 return NULL;
178}
179
193static const char *abbrev_url(const char *mbox, enum MailboxType type)
194{
195 /* This is large enough to skip `notmuch://`,
196 * but not so large that it will go past the host part. */
197 const int scheme_len = 10;
198
199 size_t len = mutt_str_len(mbox);
200 if ((len < scheme_len) || ((type != MUTT_NNTP) && (type != MUTT_IMAP) &&
201 (type != MUTT_NOTMUCH) && (type != MUTT_POP)))
202 {
203 return mbox;
204 }
205
206 const char split = (type == MUTT_NOTMUCH) ? '?' : '/';
207
208 // Skip over the scheme, e.g. `imaps://`, `notmuch://`
209 const char *last = strchr(mbox + scheme_len, split);
210 if (last)
211 mbox = last + 1;
212 return mbox;
213}
214
222static const struct AttrColor *calc_color(const struct Mailbox *m, bool current, bool highlight)
223{
224 const struct AttrColor *ac = NULL;
225
226 const char *const c_spool_file = cs_subset_string(NeoMutt->sub, "spool_file");
228 mutt_str_equal(mailbox_path(m), c_spool_file))
229 {
231 }
232
234 {
236 }
237
239 {
241 }
242
244 {
246 }
247
249 {
251 }
252
253 const struct AttrColor *ac_bg = simple_color_get(MT_COLOR_NORMAL);
255 ac = merged_color_overlay(ac_bg, ac);
256
257 if (current || highlight)
258 {
259 int color;
260 if (current)
261 {
264 else
265 color = MT_COLOR_INDICATOR;
266 }
267 else
268 {
270 }
271
272 ac = merged_color_overlay(ac, simple_color_get(color));
273 }
274
275 return ac;
276}
277
285static int calc_path_depth(const char *mbox, const char *delims, const char **last_part)
286{
287 if (!mbox || !delims || !last_part)
288 return 0;
289
290 int depth = 0;
291 const char *match = NULL;
292 while ((match = strpbrk(mbox, delims)))
293 {
294 depth++;
295 mbox = match + 1;
296 }
297
298 *last_part = mbox;
299 return depth;
300}
301
307{
308 const char *path = mailbox_path(entry->mailbox);
309
310 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
311 // Try to abbreviate the full path
312 const char *abbr = abbrev_folder(path, c_folder, entry->mailbox->type);
313 if (!abbr)
314 abbr = abbrev_url(path, entry->mailbox->type);
315 const char *short_path = abbr ? abbr : path;
316
317 /* Compute the depth */
318 const char *last_part = abbr;
319 const char *const c_sidebar_delim_chars = cs_subset_string(NeoMutt->sub, "sidebar_delim_chars");
320 entry->depth = calc_path_depth(abbr, c_sidebar_delim_chars, &last_part);
321
322 const bool short_path_is_abbr = (short_path == abbr);
323 const bool c_sidebar_short_path = cs_subset_bool(NeoMutt->sub, "sidebar_short_path");
324 if (c_sidebar_short_path)
325 {
326 short_path = last_part;
327 }
328
329 // Don't indent if we were unable to create an abbreviation.
330 // Otherwise, the full path will be indent, and it looks unusual.
331 const bool c_sidebar_folder_indent = cs_subset_bool(NeoMutt->sub, "sidebar_folder_indent");
332 if (c_sidebar_folder_indent && short_path_is_abbr)
333 {
334 const short c_sidebar_component_depth = cs_subset_number(NeoMutt->sub, "sidebar_component_depth");
335 if (c_sidebar_component_depth > 0)
336 entry->depth -= c_sidebar_component_depth;
337 }
338 else if (!c_sidebar_folder_indent)
339 {
340 entry->depth = 0;
341 }
342
343 mutt_str_copy(entry->box, short_path, sizeof(entry->box));
344}
345
360static void make_sidebar_entry(char *buf, size_t buflen, int width, struct SbEntry *sbe,
361 struct IndexSharedData *shared, int index)
362{
363 struct SidebarData sdata = { sbe, shared, index };
364
365 struct Buffer *tmp = buf_pool_get();
366 const struct Expando *c_sidebar_format = cs_subset_expando(NeoMutt->sub, "sidebar_format");
367 expando_filter(c_sidebar_format, SidebarRenderCallbacks, &sdata,
368 MUTT_FORMAT_NONE, width, NeoMutt->env, tmp);
369 mutt_str_copy(buf, buf_string(tmp), buflen);
370 buf_pool_release(&tmp);
371
372 /* Force string to be exactly the right width */
373 int w = mutt_strwidth(buf);
374 int s = mutt_str_len(buf);
375 width = MIN(buflen, width);
376 if (w < width)
377 {
378 /* Pad with spaces, capping to available buffer space */
379 int pad = width - w;
380 if ((s + pad) >= (int) buflen)
381 pad = (int) buflen - s - 1;
382 if (pad > 0)
383 {
384 memset(buf + s, ' ', pad);
385 buf[s + pad] = '\0';
386 }
387 }
388 else if (w > width)
389 {
390 /* Truncate to fit */
391 size_t len = mutt_wstr_trunc(buf, buflen, width, NULL);
392 buf[len] = '\0';
393 }
394}
395
409{
411 /* Aliases for readability */
412 const bool c_sidebar_new_mail_only = cs_subset_bool(NeoMutt->sub, "sidebar_new_mail_only");
413 const bool c_sidebar_non_empty_mailbox_only = cs_subset_bool(NeoMutt->sub, "sidebar_non_empty_mailbox_only");
414 struct SbEntry *sbe = NULL;
415
416 struct IndexSharedData *shared = wdata->shared;
417 struct SbEntry **sbep = NULL;
418 ARRAY_FOREACH(sbep, &wdata->entries)
419 {
420 int i = ARRAY_FOREACH_IDX_sbep;
421 sbe = *sbep;
422
423 sbe->is_hidden = false;
424
425 if (!sbe->mailbox->visible)
426 {
427 sbe->is_hidden = true;
428 continue;
429 }
430
431 if (shared->mailbox &&
433 {
434 /* Spool directories are always visible */
435 continue;
436 }
437
438 if (mutt_list_find(&mod_data->sidebar_pinned, mailbox_path(sbe->mailbox)) ||
439 mutt_list_find(&mod_data->sidebar_pinned, sbe->mailbox->name))
440 {
441 /* Explicitly asked to be visible */
442 continue;
443 }
444
445 if (c_sidebar_non_empty_mailbox_only && (i != wdata->opn_index) &&
446 (sbe->mailbox->msg_count == 0))
447 {
448 sbe->is_hidden = true;
449 }
450
451 if (c_sidebar_new_mail_only && (i != wdata->opn_index) &&
452 (sbe->mailbox->msg_unread == 0) && (sbe->mailbox->msg_flagged == 0) &&
453 !sbe->mailbox->has_new)
454 {
455 sbe->is_hidden = true;
456 }
457 }
458}
459
467static int sb_first_visible(struct SidebarWindowData *wdata, int index)
468{
469 if (index < 0)
470 index = 0;
471
472 struct SbEntry **sbep = NULL;
473 ARRAY_FOREACH_FROM(sbep, &wdata->entries, index)
474 {
475 if (!(*sbep)->is_hidden)
476 return ARRAY_FOREACH_IDX_sbep;
477 }
478
479 return -1;
480}
481
490static int sb_page_bottom(struct SidebarWindowData *wdata, int top, int page_size)
491{
492 if (top < 0)
493 return -1;
494
495 int row = 0;
496 int last = -1;
497
498 struct SbEntry **sbep = NULL;
499 ARRAY_FOREACH_FROM(sbep, &wdata->entries, top)
500 {
501 if (row >= page_size)
502 break;
503 if ((*sbep)->is_hidden)
504 continue;
505
506 last = ARRAY_FOREACH_IDX_sbep;
507 row++;
508 }
509
510 return last;
511}
512
526static bool prepare_sidebar(struct SidebarWindowData *wdata, int page_size)
527{
528 if (ARRAY_EMPTY(&wdata->entries) || (page_size <= 0))
529 return false;
530
531 struct SbEntry **sbep = NULL;
532
533 sbep = (wdata->opn_index >= 0) ? ARRAY_GET(&wdata->entries, wdata->opn_index) : NULL;
534 const struct SbEntry *opn_entry = sbep ? *sbep : NULL;
535 sbep = (wdata->hil_index >= 0) ? ARRAY_GET(&wdata->entries, wdata->hil_index) : NULL;
536 const struct SbEntry *hil_entry = sbep ? *sbep : NULL;
537 sbep = (wdata->top_index >= 0) ? ARRAY_GET(&wdata->entries, wdata->top_index) : NULL;
538 const struct SbEntry *top_entry = sbep ? *sbep : NULL;
539
541 const enum EmailSortType c_sidebar_sort = cs_subset_sort(NeoMutt->sub, "sidebar_sort");
542 sb_sort_entries(wdata, c_sidebar_sort);
543
544 if (opn_entry || hil_entry)
545 {
546 ARRAY_FOREACH(sbep, &wdata->entries)
547 {
548 if ((opn_entry == *sbep) && (*sbep)->mailbox->visible)
549 wdata->opn_index = ARRAY_FOREACH_IDX_sbep;
550 if ((hil_entry == *sbep) && (*sbep)->mailbox->visible)
551 wdata->hil_index = ARRAY_FOREACH_IDX_sbep;
552 }
553 }
554
555 if ((wdata->hil_index < 0) || (hil_entry && hil_entry->is_hidden) ||
556 (c_sidebar_sort != wdata->previous_sort))
557 {
558 if (wdata->opn_index >= 0)
559 {
560 wdata->hil_index = wdata->opn_index;
561 }
562 else
563 {
564 wdata->hil_index = 0;
565 /* Note is_hidden will only be set when `$sidebar_new_mail_only` */
566 if ((*ARRAY_GET(&wdata->entries, 0))->is_hidden && !sb_next(wdata))
567 wdata->hil_index = -1;
568 }
569 }
570
571 /* The viewport (top_index) is persistent: it is preserved across recalcs so
572 * that scrolling (<sidebar-scroll-*>) and recentring
573 * (<sidebar-scroll-selection-to-*>) survive a later repaint. Restore the
574 * remembered top entry after the re-sort, then snap it to a visible entry. */
575 if (top_entry)
576 {
577 ARRAY_FOREACH(sbep, &wdata->entries)
578 {
579 if ((top_entry == *sbep) && (*sbep)->mailbox->visible)
580 {
581 wdata->top_index = ARRAY_FOREACH_IDX_sbep;
582 break;
583 }
584 }
585 }
586 wdata->top_index = sb_first_visible(wdata, wdata->top_index);
587
588 /* Is the selection within the current viewport? */
589 int bot = sb_page_bottom(wdata, wdata->top_index, page_size);
590 const bool hil_in_view = (wdata->top_index >= 0) &&
591 (wdata->hil_index >= wdata->top_index) &&
592 (wdata->hil_index <= bot);
593
594 if (wdata->repage || !hil_in_view)
595 {
596 /* Reframe the view, paging so that the selection is visible. Entries may
597 * be hidden ($sidebar_new_mail_only, etc.) so we count visible entries. */
598 wdata->top_index = -1;
599 wdata->bot_index = -1;
600 while (wdata->bot_index < wdata->hil_index)
601 {
602 wdata->top_index = wdata->bot_index + 1;
603 int page_entries = 0;
604 while (page_entries < page_size)
605 {
606 wdata->bot_index++;
607 if (wdata->bot_index >= ARRAY_SIZE(&wdata->entries))
608 break;
609 if (!(*ARRAY_GET(&wdata->entries, wdata->bot_index))->is_hidden)
610 page_entries++;
611 }
612 }
613 wdata->repage = false;
614 }
615 else
616 {
617 /* Keep the persistent viewport, just recompute the bottom */
618 wdata->bot_index = bot;
619 }
620
621 if (wdata->bot_index > (ARRAY_SIZE(&wdata->entries) - 1))
622 wdata->bot_index = ARRAY_SIZE(&wdata->entries) - 1;
623
624 wdata->previous_sort = c_sidebar_sort;
625
626 return (wdata->hil_index >= 0);
627}
628
632int sb_recalc(struct MuttWindow *win)
633{
635 struct IndexSharedData *shared = wdata->shared;
636
637 if (ARRAY_EMPTY(&wdata->entries))
638 {
639 struct MailboxArray ma = neomutt_mailboxes_get(NeoMutt, MUTT_MAILBOX_ANY);
640 struct Mailbox **mp = NULL;
641 ARRAY_FOREACH(mp, &ma)
642 {
643 struct Mailbox *m = *mp;
644
645 if (m->visible)
646 sb_add_mailbox(wdata, m);
647 }
648 ARRAY_FREE(&ma); // Clean up the ARRAY, but not the Mailboxes
649 }
650
651 if (!prepare_sidebar(wdata, win->state.rows))
652 {
653 win->actions |= WA_REPAINT;
654 return 0;
655 }
656
657 int num_rows = win->state.rows;
658 int num_cols = win->state.cols;
659
660 if (ARRAY_EMPTY(&wdata->entries) || (num_rows <= 0))
661 return 0;
662
663 if (wdata->top_index < 0)
664 return 0;
665
666 int width = num_cols - wdata->divider_width;
667 int row = 0;
668 struct Mailbox *m_cur = shared->mailbox;
669 struct SbEntry **sbep = NULL;
670 ARRAY_FOREACH_FROM(sbep, &wdata->entries, wdata->top_index)
671 {
672 if (row >= num_rows)
673 break;
674
675 if ((*sbep)->is_hidden)
676 continue;
677
678 struct SbEntry *entry = (*sbep);
679 struct Mailbox *m = entry->mailbox;
680
681 const int entryidx = ARRAY_FOREACH_IDX_sbep;
682 entry->color = calc_color(m, (entryidx == wdata->opn_index),
683 (entryidx == wdata->hil_index));
684
685 if (m_cur && (m_cur->realpath[0] != '\0') &&
686 mutt_str_equal(m->realpath, m_cur->realpath))
687 {
688 m->msg_unread = m_cur->msg_unread;
689 m->msg_count = m_cur->msg_count;
690 m->msg_flagged = m_cur->msg_flagged;
691 }
692
694 make_sidebar_entry(entry->display, sizeof(entry->display), width, entry, shared, entryidx);
695 row++;
696 }
697
698 win->actions |= WA_REPAINT;
699 mutt_debug(LL_DEBUG5, "recalc done, request WA_REPAINT\n");
700 return 0;
701}
702
719static int draw_divider(struct SidebarWindowData *wdata, struct MuttWindow *win,
720 int num_rows, int num_cols)
721{
722 if ((num_rows < 1) || (num_cols < 1) || (wdata->divider_width > num_cols) ||
723 (wdata->divider_width == 0))
724 {
725 return 0;
726 }
727
728 const int width = wdata->divider_width;
729 const char *const c_sidebar_divider_char = cs_subset_string(NeoMutt->sub, "sidebar_divider_char");
730
731 const struct AttrColor *ac = simple_color_get(MT_COLOR_NORMAL);
735
736 const bool c_sidebar_on_right = cs_subset_bool(NeoMutt->sub, "sidebar_on_right");
737 const int col = c_sidebar_on_right ? 0 : (num_cols - width);
738
739 for (int i = 0; i < num_rows; i++)
740 {
741 mutt_window_move(win, i, col);
742
743 if (wdata->divider_type == SB_DIV_USER)
744 mutt_window_addstr(win, NONULL(c_sidebar_divider_char));
745 else
746 mutt_window_addch(win, '|');
747 }
748
750 return width;
751}
752
763static void fill_empty_space(struct MuttWindow *win, int first_row,
764 int num_rows, int div_width, int num_cols)
765{
766 /* Fill the remaining rows with blank space */
767 const struct AttrColor *ac = simple_color_get(MT_COLOR_NORMAL);
770
771 const bool c_sidebar_on_right = cs_subset_bool(NeoMutt->sub, "sidebar_on_right");
772 if (!c_sidebar_on_right)
773 div_width = 0;
774 for (int r = 0; r < num_rows; r++)
775 {
776 mutt_window_move(win, first_row + r, div_width);
778
779 for (int i = 0; i < num_cols; i++)
780 mutt_window_addch(win, ' ');
781 }
782}
783
787int sb_repaint(struct MuttWindow *win)
788{
790 const bool c_sidebar_on_right = cs_subset_bool(NeoMutt->sub, "sidebar_on_right");
791
792 int row = 0;
793 int num_rows = win->state.rows;
794 int num_cols = win->state.cols;
795
796 if (wdata->top_index >= 0)
797 {
798 int col = 0;
799 if (c_sidebar_on_right)
800 col = wdata->divider_width;
801
802 struct SbEntry **sbep = NULL;
803 ARRAY_FOREACH_FROM(sbep, &wdata->entries, wdata->top_index)
804 {
805 if (row >= num_rows)
806 break;
807
808 if ((*sbep)->is_hidden)
809 continue;
810
811 struct SbEntry *entry = (*sbep);
812 mutt_window_move(win, row, col);
814 mutt_window_printf(win, "%s", entry->display);
815 mutt_refresh();
816 row++;
817 }
818 }
819
820 fill_empty_space(win, row, num_rows - row, wdata->divider_width,
821 num_cols - wdata->divider_width);
822 draw_divider(wdata, win, num_rows, num_cols);
823
824 mutt_debug(LL_DEBUG5, "repaint done\n");
825 return 0;
826}
#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_SIZE(head)
The number of elements stored.
Definition array.h:87
#define ARRAY_FREE(head)
Release all memory.
Definition array.h:209
#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
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
Color and attribute parsing.
bool simple_color_is_set(enum ColorId cid)
Is the object coloured?
Definition simple.c:120
struct AttrColor * simple_color_get(enum ColorId cid)
Get the colour of an object by its ID.
Definition simple.c:98
@ MT_COLOR_SIDEBAR_SPOOL_FILE
$spool_file (Spool mailbox)
Definition color.h:75
@ MT_COLOR_SIDEBAR_DIVIDER
Line dividing sidebar from the index/pager.
Definition color.h:69
@ MT_COLOR_SIDEBAR_NEW
Mailbox with new mail.
Definition color.h:73
@ MT_COLOR_SIDEBAR_UNREAD
Mailbox with unread mail.
Definition color.h:76
@ MT_COLOR_INDICATOR
Selected item in list.
Definition color.h:49
@ MT_COLOR_SIDEBAR_ORDINARY
Mailbox with no new or flagged messages.
Definition color.h:74
@ MT_COLOR_SIDEBAR_BACKGROUND
Background colour for the Sidebar.
Definition color.h:68
@ MT_COLOR_NORMAL
Plain text.
Definition color.h:53
@ MT_COLOR_SIDEBAR_INDICATOR
Current open mailbox.
Definition color.h:72
@ MT_COLOR_SIDEBAR_HIGHLIGHT
Select cursor.
Definition color.h:71
@ MT_COLOR_SIDEBAR_FLAGGED
Mailbox with flagged messages.
Definition color.h:70
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition helpers.c:143
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition helpers.c:266
const struct Expando * cs_subset_expando(const struct ConfigSubset *sub, const char *name)
Get an Expando config item by name.
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition mailbox.h:216
MailboxType
Supported mailbox formats.
Definition mailbox.h:40
@ MUTT_NOTMUCH
'Notmuch' (virtual) Mailbox type
Definition mailbox.h:50
@ MUTT_POP
'POP3' Mailbox type
Definition mailbox.h:51
@ MUTT_NNTP
'NNTP' (Usenet) Mailbox type
Definition mailbox.h:48
@ MUTT_IMAP
'IMAP' Mailbox type
Definition mailbox.h:49
@ MUTT_MAILBOX_ANY
Match any Mailbox type.
Definition mailbox.h:41
size_t mutt_wstr_trunc(const char *src, size_t maxlen, size_t maxwid, size_t *width)
Work out how to truncate a widechar string.
Definition curs_lib.c:386
void mutt_refresh(void)
Force a refresh of the screen.
Definition curs_lib.c:78
size_t mutt_strwidth(const char *s)
Measure a string's width in screen cells.
Definition curs_lib.c:449
Structs that make up an email.
EmailSortType
Methods for sorting Emails.
Definition sort.h:53
int expando_filter(const struct Expando *exp, const struct ExpandoRenderCallback *erc, void *data, MuttFormatFlags flags, int max_cols, char **env_list, struct Buffer *buf)
Render an Expando and run the result through a filter.
Definition filter.c:139
Parse Expando string.
bool sb_next(struct SidebarWindowData *wdata)
Find the next unhidden Mailbox.
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
int sb_recalc(struct MuttWindow *win)
Recalculate the Sidebar display - Implements MuttWindow::recalc() -.
Definition window.c:632
int sb_repaint(struct MuttWindow *win)
Repaint the Sidebar display - Implements MuttWindow::repaint() -.
Definition window.c:787
Convenience wrapper for the gui headers.
GUI manage the main index (list of emails)
struct ListNode * mutt_list_find(const struct ListHead *h, const char *data)
Find a string in a List.
Definition list.c:103
@ LL_DEBUG5
Log at debug level 5.
Definition logging2.h:49
#define MIN(a, b)
Return the minimum of two values.
Definition memory.h:40
const struct AttrColor * merged_color_overlay(const struct AttrColor *base, const struct AttrColor *over)
Combine two colours.
Definition merged.c:110
@ MODULE_ID_SIDEBAR
ModuleSidebar, Sidebar
Definition module_api.h:93
Convenience wrapper for the library headers.
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition string.c:678
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:666
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
Definition string.c:429
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition string.c:503
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition string.c:587
const struct AttrColor * mutt_curses_set_color_by_id(enum ColorId cid)
Set the colour and attributes by the Colour ID.
Definition mutt_curses.c:79
void mutt_curses_set_color(const struct AttrColor *ac)
Set the colour and attributes for text.
Definition mutt_curses.c:38
int mutt_window_printf(struct MuttWindow *win, const char *fmt,...)
Write a formatted string to a Window.
int mutt_window_move(struct MuttWindow *win, int row, int col)
Move the cursor in a Window.
int mutt_window_addstr(struct MuttWindow *win, const char *str)
Write a string to a Window.
int mutt_window_addch(struct MuttWindow *win, int ch)
Write one character to a Window.
@ WA_REPAINT
Redraw the contents of the Window.
struct MailboxArray neomutt_mailboxes_get(struct NeoMutt *n, enum MailboxType type)
Get an Array of matching Mailboxes.
Definition neomutt.c:607
void * neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
Get the private data for a Module.
Definition neomutt.c:666
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
@ MUTT_FORMAT_NONE
No flags are set.
Definition render.h:37
const struct ExpandoRenderCallback SidebarRenderCallbacks[]
Callbacks for Sidebar Expandos.
Definition expando.c:312
Sidebar Expando definitions.
Sidebar private Module data.
GUI display the mailboxes in a side panel.
@ SB_DIV_USER
User configured using $sidebar_divider_char.
Definition private.h:82
void sb_sort_entries(struct SidebarWindowData *wdata, enum EmailSortType sort)
Sort the Sidebar entries.
Definition sort.c:161
void sb_add_mailbox(struct SidebarWindowData *wdata, struct Mailbox *m)
Add a Mailbox to the Sidebar.
Definition sidebar.c:98
struct SidebarWindowData * sb_wdata_get(struct MuttWindow *win)
Get the Sidebar data for this window.
Definition wdata.c:77
static const char * abbrev_url(const char *mbox, enum MailboxType type)
Abbreviate a url-style Mailbox path.
Definition window.c:193
static void fill_empty_space(struct MuttWindow *win, int first_row, int num_rows, int div_width, int num_cols)
Wipe the remaining Sidebar space.
Definition window.c:763
static void update_entries_visibility(struct SidebarWindowData *wdata)
Should a SbEntry be displayed in the sidebar?
Definition window.c:408
static int sb_page_bottom(struct SidebarWindowData *wdata, int top, int page_size)
Find the last entry visible on a page.
Definition window.c:490
static const struct AttrColor * calc_color(const struct Mailbox *m, bool current, bool highlight)
Calculate the colour of a Sidebar row.
Definition window.c:222
static int sb_first_visible(struct SidebarWindowData *wdata, int index)
Find the first visible entry at or after an index.
Definition window.c:467
static void make_sidebar_entry(char *buf, size_t buflen, int width, struct SbEntry *sbe, struct IndexSharedData *shared, int index)
Turn mailbox data into a sidebar string.
Definition window.c:360
static const char * abbrev_folder(const char *mbox, const char *folder, enum MailboxType type)
Abbreviate a Mailbox path using a folder.
Definition window.c:129
void sb_entry_set_display_name(struct SbEntry *entry)
Set the display name for an SbEntry.
Definition window.c:306
static int calc_path_depth(const char *mbox, const char *delims, const char **last_part)
Calculate the depth of a Mailbox path.
Definition window.c:285
static bool prepare_sidebar(struct SidebarWindowData *wdata, int page_size)
Prepare the list of SbEntry's for the sidebar display.
Definition window.c:526
static int imap_is_prefix(const char *folder, const char *mbox)
Check if folder matches the beginning of mbox.
Definition window.c:90
static int draw_divider(struct SidebarWindowData *wdata, struct MuttWindow *win, int num_rows, int num_cols)
Draw a line between the sidebar and the rest of neomutt.
Definition window.c:719
#define NONULL(x)
Definition string2.h:44
A curses colour and its attributes.
Definition attr.h:65
String manipulation buffer.
Definition buffer.h:36
Parsed Expando trees.
Definition expando.h:41
Data shared between Index, Pager and Sidebar.
Definition shared_data.h:37
struct Mailbox * mailbox
Current Mailbox.
Definition shared_data.h:41
A mailbox.
Definition mailbox.h:81
bool has_new
Mailbox has new mail.
Definition mailbox.h:87
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition mailbox.h:83
int msg_count
Total number of messages.
Definition mailbox.h:90
enum MailboxType type
Mailbox type.
Definition mailbox.h:104
char * name
A short name for the Mailbox.
Definition mailbox.h:84
bool visible
True if a result of "mailboxes".
Definition mailbox.h:132
int msg_flagged
Number of flagged messages.
Definition mailbox.h:92
int msg_unread
Number of unread messages.
Definition mailbox.h:91
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
char ** env
Private copy of the environment variables.
Definition neomutt.h:57
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
Info about folders in the sidebar.
Definition private.h:40
const struct AttrColor * color
Colour to use.
Definition private.h:46
int depth
Indentation depth.
Definition private.h:43
char display[256]
Formatted string to display.
Definition private.h:42
struct Mailbox * mailbox
Mailbox this represents.
Definition private.h:44
bool is_hidden
Don't show, e.g. $sidebar_new_mail_only.
Definition private.h:45
char box[256]
Mailbox path (possibly abbreviated)
Definition private.h:41
Data passed to sidebar_format_str()
Definition expando.h:34
struct IndexSharedData * shared
Shared Index Data.
Definition expando.h:36
int index
Index of the entry (0-based, absolute)
Definition expando.h:37
Sidebar private Module data.
Definition module_data.h:32
struct ListHead sidebar_pinned
List of mailboxes to always display in the sidebar.
Definition module_data.h:36
Sidebar private Window data -.
Definition private.h:90
short previous_sort
Old $sidebar_sort
Definition private.h:102
int top_index
First mailbox visible in sidebar.
Definition private.h:95
short divider_width
Width of the divider in screen columns.
Definition private.h:104
int bot_index
Last mailbox visible in sidebar.
Definition private.h:98
int hil_index
Highlighted mailbox.
Definition private.h:97
enum DivType divider_type
Type of divider to use, e.g. SB_DIV_ASCII.
Definition private.h:103
struct IndexSharedData * shared
Shared Index Data.
Definition private.h:92
int opn_index
Current (open) mailbox.
Definition private.h:96
struct MuttWindow * win
Sidebar Window.
Definition private.h:91
struct SbEntryArray entries
Items to display in the sidebar.
Definition private.h:93
bool repage
Force RECALC to recompute the paging used for the overlays.
Definition private.h:99
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition url.h:69
char * user
Username.
Definition url.h:71
char * host
Host.
Definition url.h:73
char * path
Path.
Definition url.h:75
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition mutt_window.h:60
short rows
Number of rows, can be MUTT_WIN_SIZE_UNLIMITED.
Definition mutt_window.h:61
struct Url * url_parse(const char *src)
Fill in Url.
Definition url.c:242
void url_free(struct Url **ptr)
Free the contents of a URL.
Definition url.c:124