NeoMutt  2025-12-11-911-gd8d604
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
window.c File Reference

Sidebar Window. More...

#include "config.h"
#include <stdbool.h>
#include <string.h>
#include "private.h"
#include "mutt/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "gui/lib.h"
#include "color/lib.h"
#include "expando/lib.h"
#include "index/lib.h"
#include "expando.h"
#include "module_data.h"
+ Include dependency graph for window.c:

Go to the source code of this file.

Functions

static int imap_is_prefix (const char *folder, const char *mbox)
 Check if folder matches the beginning of mbox.
 
static const char * abbrev_folder (const char *mbox, const char *folder, enum MailboxType type)
 Abbreviate a Mailbox path using a folder.
 
static const char * abbrev_url (const char *mbox, enum MailboxType type)
 Abbreviate a url-style Mailbox path.
 
static const struct AttrColorcalc_color (const struct Mailbox *m, bool current, bool highlight)
 Calculate the colour of a Sidebar row.
 
static int calc_path_depth (const char *mbox, const char *delims, const char **last_part)
 Calculate the depth of a Mailbox path.
 
void sb_entry_set_display_name (struct SbEntry *entry)
 Set the display name for an SbEntry.
 
static void make_sidebar_entry (char *buf, size_t buflen, int width, struct SbEntry *sbe, struct IndexSharedData *shared)
 Turn mailbox data into a sidebar string.
 
static void update_entries_visibility (struct SidebarWindowData *wdata)
 Should a SbEntry be displayed in the sidebar?
 
static bool prepare_sidebar (struct SidebarWindowData *wdata, int page_size)
 Prepare the list of SbEntry's for the sidebar display.
 
int sb_recalc (struct MuttWindow *win)
 Recalculate the Sidebar display - Implements MuttWindow::recalc() -.
 
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.
 
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.
 
int sb_repaint (struct MuttWindow *win)
 Repaint the Sidebar display - Implements MuttWindow::repaint() -.
 

Detailed Description

Sidebar Window.

Authors
  • Kevin J. McCarthy
  • R Primus
  • Pietro Cerutti
  • Richard Russon
  • Ashish Panigrahi
  • Tóth János

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file window.c.

Function Documentation

◆ imap_is_prefix()

static int imap_is_prefix ( const char * folder,
const char * mbox )
static

Check if folder matches the beginning of mbox.

Parameters
folderFolder
mboxMailbox path
Return values
numLength of the prefix

Definition at line 90 of file window.c.

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}
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition string.c:677
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
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
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
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ abbrev_folder()

static const char * abbrev_folder ( const char * mbox,
const char * folder,
enum MailboxType type )
static

Abbreviate a Mailbox path using a folder.

Parameters
mboxMailbox path to shorten
folderFolder path to use
typeMailbox type
Return values
ptrPointer into the mbox param

Definition at line 129 of file window.c.

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}
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
@ MUTT_IMAP
'IMAP' Mailbox type
Definition mailbox.h:49
static int imap_is_prefix(const char *folder, const char *mbox)
Check if folder matches the beginning of mbox.
Definition window.c:90
Container for Accounts, Notifications.
Definition neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ abbrev_url()

static const char * abbrev_url ( const char * mbox,
enum MailboxType type )
static

Abbreviate a url-style Mailbox path.

Parameters
mboxMailbox path to shorten
typeMailbox type
Return values
ptrmbox unchanged

Use heuristics to shorten a non-local Mailbox path. Strip the host part (or database part for Notmuch).

e.g.

  • imap://user@host.com/apple/banana becomes apple/banana
  • notmuch:///home/user/db?query=hello becomes query=hello

Definition at line 193 of file window.c.

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}
@ 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
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ calc_color()

static const struct AttrColor * calc_color ( const struct Mailbox * m,
bool current,
bool highlight )
static

Calculate the colour of a Sidebar row.

Parameters
mMailbox
currenttrue, if this is the current Mailbox
highlighttrue, if this Mailbox has the highlight on it
Return values
enumColorId, e.g. MT_COLOR_SIDEBAR_NEW

Definition at line 222 of file window.c.

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}
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_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
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition mailbox.h:216
const struct AttrColor * merged_color_overlay(const struct AttrColor *base, const struct AttrColor *over)
Combine two colours.
Definition merged.c:110
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:665
A curses colour and its attributes.
Definition attr.h:65
bool has_new
Mailbox has new mail.
Definition mailbox.h:87
int msg_flagged
Number of flagged messages.
Definition mailbox.h:92
int msg_unread
Number of unread messages.
Definition mailbox.h:91
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ calc_path_depth()

static int calc_path_depth ( const char * mbox,
const char * delims,
const char ** last_part )
static

Calculate the depth of a Mailbox path.

Parameters
[in]mboxMailbox path to examine
[in]delimsDelimiter characters
[out]last_partLast path component
Return values
numDepth

Definition at line 285 of file window.c.

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}
+ Here is the caller graph for this function:

◆ sb_entry_set_display_name()

void sb_entry_set_display_name ( struct SbEntry * entry)

Set the display name for an SbEntry.

Parameters
entrySbEntry to update

Definition at line 306 of file window.c.

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}
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
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:586
static const char * abbrev_url(const char *mbox, enum MailboxType type)
Abbreviate a url-style Mailbox path.
Definition window.c:193
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
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
enum MailboxType type
Mailbox type.
Definition mailbox.h:104
int depth
Indentation depth.
Definition private.h:43
struct Mailbox * mailbox
Mailbox this represents.
Definition private.h:44
char box[256]
Mailbox path (possibly abbreviated)
Definition private.h:41
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ make_sidebar_entry()

static void make_sidebar_entry ( char * buf,
size_t buflen,
int width,
struct SbEntry * sbe,
struct IndexSharedData * shared )
static

Turn mailbox data into a sidebar string.

Parameters
[out]bufBuffer in which to save string
[in]buflenBuffer length
[in]widthDesired width in screen cells
[in]sbeMailbox object
[in]sharedShared Index Data

Take all the relevant mailbox data and the desired screen width and then get expando_render() to do the actual work.

See also
$sidebar_format

Definition at line 359 of file window.c.

361{
362 struct SidebarData sdata = { sbe, shared };
363
364 struct Buffer *tmp = buf_pool_get();
365 const struct Expando *c_sidebar_format = cs_subset_expando(NeoMutt->sub, "sidebar_format");
366 expando_filter(c_sidebar_format, SidebarRenderCallbacks, &sdata,
367 MUTT_FORMAT_NONE, width, NeoMutt->env, tmp);
368 mutt_str_copy(buf, buf_string(tmp), buflen);
369 buf_pool_release(&tmp);
370
371 /* Force string to be exactly the right width */
372 int w = mutt_strwidth(buf);
373 int s = mutt_str_len(buf);
374 width = MIN(buflen, width);
375 if (w < width)
376 {
377 /* Pad with spaces, capping to available buffer space */
378 int pad = width - w;
379 if ((s + pad) >= (int) buflen)
380 pad = (int) buflen - s - 1;
381 if (pad > 0)
382 {
383 memset(buf + s, ' ', pad);
384 buf[s + pad] = '\0';
385 }
386 }
387 else if (w > width)
388 {
389 /* Truncate to fit */
390 size_t len = mutt_wstr_trunc(buf, buflen, width, NULL);
391 buf[len] = '\0';
392 }
393}
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
const struct Expando * cs_subset_expando(const struct ConfigSubset *sub, const char *name)
Get an Expando config item by name.
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
size_t mutt_strwidth(const char *s)
Measure a string's width in screen cells.
Definition curs_lib.c:446
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
#define MIN(a, b)
Return the minimum of two values.
Definition memory.h:40
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:302
String manipulation buffer.
Definition buffer.h:36
Parsed Expando trees.
Definition expando.h:41
char ** env
Private copy of the environment variables.
Definition neomutt.h:57
Data passed to sidebar_format_str()
Definition expando.h:34
struct IndexSharedData * shared
Shared Index Data.
Definition expando.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ update_entries_visibility()

static void update_entries_visibility ( struct SidebarWindowData * wdata)
static

Should a SbEntry be displayed in the sidebar?

Parameters
wdataSidebar data

For each SbEntry in the entries array, check whether we should display it. This is determined by several criteria. If the Mailbox:

  • is the currently open mailbox
  • is the currently highlighted mailbox
  • has unread messages
  • has flagged messages
  • is pinned

Definition at line 407 of file window.c.

408{
410 /* Aliases for readability */
411 const bool c_sidebar_new_mail_only = cs_subset_bool(NeoMutt->sub, "sidebar_new_mail_only");
412 const bool c_sidebar_non_empty_mailbox_only = cs_subset_bool(NeoMutt->sub, "sidebar_non_empty_mailbox_only");
413 struct SbEntry *sbe = NULL;
414
415 struct IndexSharedData *shared = wdata->shared;
416 struct SbEntry **sbep = NULL;
417 ARRAY_FOREACH(sbep, &wdata->entries)
418 {
419 int i = ARRAY_FOREACH_IDX_sbep;
420 sbe = *sbep;
421
422 sbe->is_hidden = false;
423
424 if (!sbe->mailbox->visible)
425 {
426 sbe->is_hidden = true;
427 continue;
428 }
429
430 if (shared->mailbox &&
432 {
433 /* Spool directories are always visible */
434 continue;
435 }
436
437 if (mutt_list_find(&mod_data->sidebar_pinned, mailbox_path(sbe->mailbox)) ||
438 mutt_list_find(&mod_data->sidebar_pinned, sbe->mailbox->name))
439 {
440 /* Explicitly asked to be visible */
441 continue;
442 }
443
444 if (c_sidebar_non_empty_mailbox_only && (i != wdata->opn_index) &&
445 (sbe->mailbox->msg_count == 0))
446 {
447 sbe->is_hidden = true;
448 }
449
450 if (c_sidebar_new_mail_only && (i != wdata->opn_index) &&
451 (sbe->mailbox->msg_unread == 0) && (sbe->mailbox->msg_flagged == 0) &&
452 !sbe->mailbox->has_new)
453 {
454 sbe->is_hidden = true;
455 }
456 }
457}
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:223
struct ListNode * mutt_list_find(const struct ListHead *h, const char *data)
Find a string in a List.
Definition list.c:103
@ MODULE_ID_SIDEBAR
ModuleSidebar, Sidebar
Definition module_api.h:91
void * neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
Get the private data for a Module.
Definition neomutt.c:663
Data shared between Index, Pager and Sidebar.
Definition shared_data.h:37
struct Mailbox * mailbox
Current Mailbox.
Definition shared_data.h:41
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
char * name
A short name for the Mailbox.
Definition mailbox.h:84
bool visible
True if a result of "mailboxes".
Definition mailbox.h:132
Info about folders in the sidebar.
Definition private.h:40
bool is_hidden
Don't show, e.g. $sidebar_new_mail_only.
Definition private.h:45
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
struct IndexSharedData * shared
Shared Index Data.
Definition private.h:91
int opn_index
Current (open) mailbox.
Definition private.h:95
struct SbEntryArray entries
Items to display in the sidebar.
Definition private.h:92
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ prepare_sidebar()

static bool prepare_sidebar ( struct SidebarWindowData * wdata,
int page_size )
static

Prepare the list of SbEntry's for the sidebar display.

Parameters
wdataSidebar data
page_sizeNumber of lines on a page
Return values
falseNo, don't draw the sidebar
trueYes, draw the sidebar

Before painting the sidebar, we determine which are visible, sort them and set up our page pointers.

This is a lot of work to do each refresh, but there are many things that can change outside of the sidebar that we don't hear about.

Definition at line 472 of file window.c.

473{
474 if (ARRAY_EMPTY(&wdata->entries) || (page_size <= 0))
475 return false;
476
477 struct SbEntry **sbep = NULL;
478 const bool c_sidebar_new_mail_only = cs_subset_bool(NeoMutt->sub, "sidebar_new_mail_only");
479 const bool c_sidebar_non_empty_mailbox_only = cs_subset_bool(NeoMutt->sub, "sidebar_non_empty_mailbox_only");
480
481 sbep = (wdata->opn_index >= 0) ? ARRAY_GET(&wdata->entries, wdata->opn_index) : NULL;
482 const struct SbEntry *opn_entry = sbep ? *sbep : NULL;
483 sbep = (wdata->hil_index >= 0) ? ARRAY_GET(&wdata->entries, wdata->hil_index) : NULL;
484 const struct SbEntry *hil_entry = sbep ? *sbep : NULL;
485
487 const enum EmailSortType c_sidebar_sort = cs_subset_sort(NeoMutt->sub, "sidebar_sort");
488 sb_sort_entries(wdata, c_sidebar_sort);
489
490 if (opn_entry || hil_entry)
491 {
492 ARRAY_FOREACH(sbep, &wdata->entries)
493 {
494 if ((opn_entry == *sbep) && (*sbep)->mailbox->visible)
495 wdata->opn_index = ARRAY_FOREACH_IDX_sbep;
496 if ((hil_entry == *sbep) && (*sbep)->mailbox->visible)
497 wdata->hil_index = ARRAY_FOREACH_IDX_sbep;
498 }
499 }
500
501 if ((wdata->hil_index < 0) || (hil_entry && hil_entry->is_hidden) ||
502 (c_sidebar_sort != wdata->previous_sort))
503 {
504 if (wdata->opn_index >= 0)
505 {
506 wdata->hil_index = wdata->opn_index;
507 }
508 else
509 {
510 wdata->hil_index = 0;
511 /* Note is_hidden will only be set when `$sidebar_new_mail_only` */
512 if ((*ARRAY_GET(&wdata->entries, 0))->is_hidden && !sb_next(wdata))
513 wdata->hil_index = -1;
514 }
515 }
516
517 /* Set the Top and Bottom to frame the wdata->hil_index in groups of page_size */
518
519 /* If `$sidebar_new_mail_only` or `$sidebar_non_empty_mailbox_only` is set,
520 * some entries may be hidden so we need to scan for the framing interval */
521 if (c_sidebar_new_mail_only || c_sidebar_non_empty_mailbox_only || wdata->repage)
522 {
523 wdata->top_index = -1;
524 wdata->bot_index = -1;
525 while (wdata->bot_index < wdata->hil_index)
526 {
527 wdata->top_index = wdata->bot_index + 1;
528 int page_entries = 0;
529 while (page_entries < page_size)
530 {
531 wdata->bot_index++;
532 if (wdata->bot_index >= ARRAY_SIZE(&wdata->entries))
533 break;
534 if (!(*ARRAY_GET(&wdata->entries, wdata->bot_index))->is_hidden)
535 page_entries++;
536 }
537 }
538 }
539 else
540 {
541 /* Otherwise we can just calculate the interval */
542 wdata->top_index = (wdata->hil_index / page_size) * page_size;
543 wdata->bot_index = wdata->top_index + page_size - 1;
544 }
545
546 if (wdata->bot_index > (ARRAY_SIZE(&wdata->entries) - 1))
547 wdata->bot_index = ARRAY_SIZE(&wdata->entries) - 1;
548
549 wdata->previous_sort = c_sidebar_sort;
550
551 return (wdata->hil_index >= 0);
552}
#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_GET(head, idx)
Return the element at index.
Definition array.h:109
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition helpers.c:266
EmailSortType
Methods for sorting Emails.
Definition sort.h:53
bool sb_next(struct SidebarWindowData *wdata)
Find the next unhidden Mailbox.
Definition functions.c:119
void sb_sort_entries(struct SidebarWindowData *wdata, enum EmailSortType sort)
Sort the Sidebar entries.
Definition sort.c:161
static void update_entries_visibility(struct SidebarWindowData *wdata)
Should a SbEntry be displayed in the sidebar?
Definition window.c:407
short previous_sort
Old $sidebar_sort
Definition private.h:101
int top_index
First mailbox visible in sidebar.
Definition private.h:94
int bot_index
Last mailbox visible in sidebar.
Definition private.h:97
int hil_index
Highlighted mailbox.
Definition private.h:96
bool repage
Force RECALC to recompute the paging used for the overlays.
Definition private.h:98
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ draw_divider()

static int draw_divider ( struct SidebarWindowData * wdata,
struct MuttWindow * win,
int num_rows,
int num_cols )
static

Draw a line between the sidebar and the rest of neomutt.

Parameters
wdataSidebar data
winWindow to draw on
num_rowsHeight of the Sidebar
num_colsWidth of the Sidebar
Return values
0Empty string
numCharacter occupies n screen columns

Draw a divider using characters from the config option "sidebar_divider_char". This can be an ASCII or Unicode character. We calculate these characters' width in screen columns.

If the user hasn't set $sidebar_divider_char we pick a character for them, respecting the value of $ascii_chars.

Definition at line 644 of file window.c.

646{
647 if ((num_rows < 1) || (num_cols < 1) || (wdata->divider_width > num_cols) ||
648 (wdata->divider_width == 0))
649 {
650 return 0;
651 }
652
653 const int width = wdata->divider_width;
654 const char *const c_sidebar_divider_char = cs_subset_string(NeoMutt->sub, "sidebar_divider_char");
655
656 const struct AttrColor *ac = simple_color_get(MT_COLOR_NORMAL);
660
661 const bool c_sidebar_on_right = cs_subset_bool(NeoMutt->sub, "sidebar_on_right");
662 const int col = c_sidebar_on_right ? 0 : (num_cols - width);
663
664 for (int i = 0; i < num_rows; i++)
665 {
666 mutt_window_move(win, i, col);
667
668 if (wdata->divider_type == SB_DIV_USER)
669 mutt_window_addstr(win, NONULL(c_sidebar_divider_char));
670 else
671 mutt_window_addch(win, '|');
672 }
673
675 return width;
676}
@ MT_COLOR_SIDEBAR_DIVIDER
Line dividing sidebar from the index/pager.
Definition color.h:69
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_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.
@ SB_DIV_USER
User configured using $sidebar_divider_char.
Definition private.h:81
#define NONULL(x)
Definition string2.h:44
short divider_width
Width of the divider in screen columns.
Definition private.h:103
enum DivType divider_type
Type of divider to use, e.g. SB_DIV_ASCII.
Definition private.h:102
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fill_empty_space()

static void fill_empty_space ( struct MuttWindow * win,
int first_row,
int num_rows,
int div_width,
int num_cols )
static

Wipe the remaining Sidebar space.

Parameters
winWindow to draw on
first_rowWindow line to start (0-based)
num_rowsNumber of rows to fill
div_widthWidth in screen characters taken by the divider
num_colsNumber of columns to fill

Write spaces over the area the sidebar isn't using.

Definition at line 688 of file window.c.

690{
691 /* Fill the remaining rows with blank space */
692 const struct AttrColor *ac = simple_color_get(MT_COLOR_NORMAL);
695
696 const bool c_sidebar_on_right = cs_subset_bool(NeoMutt->sub, "sidebar_on_right");
697 if (!c_sidebar_on_right)
698 div_width = 0;
699 for (int r = 0; r < num_rows; r++)
700 {
701 mutt_window_move(win, first_row + r, div_width);
703
704 for (int i = 0; i < num_cols; i++)
705 mutt_window_addch(win, ' ');
706 }
707}
+ Here is the call graph for this function:
+ Here is the caller graph for this function: