diff -urN mutt-1.6.1/buffy.c mutt-1.6.1-sidebar/buffy.c --- mutt-1.6.1/buffy.c 2016-05-02 03:02:12.397171385 +0100 +++ mutt-1.6.1-sidebar/buffy.c 2016-05-02 03:02:15.009212943 +0100 @@ -27,6 +27,10 @@ #include "mutt_curses.h" +#ifdef USE_SIDEBAR +#include "sidebar.h" +#endif + #ifdef USE_IMAP #include "imap.h" #endif @@ -196,9 +200,17 @@ static BUFFY *buffy_new (const char *path) { BUFFY* buffy; +#ifdef USE_SIDEBAR + char rp[PATH_MAX] = ""; + char *r = NULL; +#endif buffy = (BUFFY *) safe_calloc (1, sizeof (BUFFY)); strfcpy (buffy->path, path, sizeof (buffy->path)); +#ifdef USE_SIDEBAR + r = realpath (path, rp); + strfcpy (buffy->realpath, r ? rp : path, sizeof (buffy->realpath)); +#endif buffy->next = NULL; buffy->magic = 0; @@ -215,7 +227,10 @@ BUFFY **tmp,*tmp1; char buf[_POSIX_PATH_MAX]; struct stat sb; - char f1[PATH_MAX], f2[PATH_MAX]; + char f1[PATH_MAX]; +#ifndef USE_SIDEBAR + char f2[PATH_MAX]; +#endif char *p, *q; while (MoreArgs (s)) @@ -228,6 +243,9 @@ for (tmp = &Incoming; *tmp;) { tmp1=(*tmp)->next; +#ifdef USE_SIDEBAR + sb_notify_mailbox (*tmp, 0); +#endif buffy_free (tmp); *tmp=tmp1; } @@ -243,8 +261,13 @@ p = realpath (buf, f1); for (tmp = &Incoming; *tmp; tmp = &((*tmp)->next)) { +#ifdef USE_SIDEBAR + q = (*tmp)->realpath; + if (mutt_strcmp (p ? p : buf, q) == 0) +#else q = realpath ((*tmp)->path, f2); if (mutt_strcmp (p ? p : buf, q ? q : (*tmp)->path) == 0) +#endif { dprint(3,(debugfile,"mailbox '%s' already registered as '%s'\n", buf, (*tmp)->path)); break; @@ -256,14 +279,21 @@ if(*tmp) { tmp1=(*tmp)->next; +#ifdef USE_SIDEBAR + sb_notify_mailbox (*tmp, 0); +#endif buffy_free (tmp); *tmp=tmp1; } continue; } - if (!*tmp) + if (!*tmp) { *tmp = buffy_new (buf); +#ifdef USE_SIDEBAR + sb_notify_mailbox (*tmp, 1); +#endif + } (*tmp)->new = 0; (*tmp)->notified = 1; @@ -306,6 +336,13 @@ return 0; } +#ifdef USE_SIDEBAR + if (option (OPTSIDEBAR) && mailbox->msg_unread > 0) { + mailbox->new = 1; + return 1; + } +#endif + if ((dirp = opendir (path)) == NULL) { mailbox->magic = 0; @@ -357,6 +394,89 @@ return 0; } + +#ifdef USE_SIDEBAR +/** + * buffy_maildir_update_dir - Update counts for one directory + * @mailbox: BUFFY representing a maildir mailbox + * @dir: Which directory to search + * + * Look through one directory of a maildir mailbox. The directory could + * be either "new" or "cur". + * + * Count how many new, or flagged, messages there are. + */ +static void +buffy_maildir_update_dir (BUFFY *mailbox, const char *dir) +{ + char path[_POSIX_PATH_MAX] = ""; + DIR *dirp = NULL; + struct dirent *de = NULL; + char *p = NULL; + int read; + + snprintf (path, sizeof (path), "%s/%s", mailbox->path, dir); + + dirp = opendir (path); + if (!dirp) { + mailbox->magic = 0; + return; + } + + while ((de = readdir (dirp)) != NULL) { + if (*de->d_name == '.') + continue; + + /* Matches maildir_parse_flags logic */ + read = 0; + mailbox->msg_count++; + p = strstr (de->d_name, ":2,"); + if (p) { + p += 3; + if (strchr (p, 'S')) + read = 1; + if (strchr (p, 'F')) + mailbox->msg_flagged++; + } + if (!read) { + mailbox->msg_unread++; + } + } + + closedir (dirp); +} + +/** + * buffy_maildir_update - Update messages counts for a maildir mailbox + * @mailbox: BUFFY representing a maildir mailbox + * + * Open a mailbox directories and update our record of how many new, or + * flagged, messages there are. + */ +void +buffy_maildir_update (BUFFY *mailbox) +{ + if (!option (OPTSIDEBAR)) + return; + + mailbox->msg_count = 0; + mailbox->msg_unread = 0; + mailbox->msg_flagged = 0; + + buffy_maildir_update_dir (mailbox, "new"); + if (mailbox->msg_count) { + mailbox->new = 1; + } + buffy_maildir_update_dir (mailbox, "cur"); + + mailbox->sb_last_checked = time (NULL); + + /* make sure the updates are actually put on screen */ + sb_draw(); +} + +#endif + /* returns 1 if mailbox has new mail */ static int buffy_mbox_hasnew (BUFFY* mailbox, struct stat *sb) { @@ -368,7 +488,11 @@ else statcheck = sb->st_mtime > sb->st_atime || (mailbox->newly_created && sb->st_ctime == sb->st_mtime && sb->st_ctime == sb->st_atime); +#ifdef USE_SIDEBAR + if ((!option (OPTSIDEBAR) && statcheck) || (option (OPTSIDEBAR) && mailbox->msg_unread > 0)) +#else if (statcheck) +#endif { if (!option(OPTMAILCHECKRECENT) || sb->st_mtime > mailbox->last_visited) { @@ -388,6 +512,40 @@ return rc; } +#ifdef USE_SIDEBAR +/** + * buffy_mbox_update - Update messages counts for an mbox mailbox + * @mailbox: BUFFY representing an mbox mailbox + * @sb: stat(2) infomation about the mailbox file + * + * Open a mbox file and update our record of how many new, or flagged, + * messages there are. If the mailbox hasn't changed since the last call, + * the function does nothing. + */ +void +buffy_mbox_update (BUFFY *mailbox, struct stat *sb) +{ + CONTEXT *ctx = NULL; + + if (!option (OPTSIDEBAR)) + return; + if ((mailbox->sb_last_checked > sb->st_mtime) && (mailbox->msg_count != 0)) + return; /* no check necessary */ + + ctx = mx_open_mailbox (mailbox->path, M_READONLY | M_QUIET | M_NOSORT | M_PEEK, NULL); + if (ctx) { + mailbox->msg_count = ctx->msgcount; + mailbox->msg_unread = ctx->unread; + mailbox->msg_flagged = ctx->flagged; + mailbox->sb_last_checked = time (NULL); + mx_close_mailbox (ctx, 0); + } + + /* make sure the updates are actually put on screen */ + sb_draw(); +} +#endif + int mutt_buffy_check (int force) { BUFFY *tmp; @@ -428,6 +586,9 @@ contex_sb.st_ino=0; } +#ifdef USE_SIDEBAR + int should_refresh = sb_should_refresh(); +#endif for (tmp = Incoming; tmp; tmp = tmp->next) { if (tmp->magic != M_IMAP) @@ -461,16 +622,30 @@ { case M_MBOX: case M_MMDF: +#ifdef USE_SIDEBAR + if (should_refresh) + buffy_mbox_update (tmp, &sb); +#endif if (buffy_mbox_hasnew (tmp, &sb) > 0) BuffyCount++; break; case M_MAILDIR: +#ifdef USE_SIDEBAR + if (should_refresh) + buffy_maildir_update (tmp); +#endif if (buffy_maildir_hasnew (tmp) > 0) BuffyCount++; break; case M_MH: +#ifdef USE_SIDEBAR + if (sb_should_refresh()) { + mh_buffy_update (tmp); + sb_set_update_time(); + } +#endif mh_buffy(tmp); if (tmp->new) BuffyCount++; @@ -485,6 +660,10 @@ else if (!tmp->notified) BuffyNotify++; } +#ifdef USE_SIDEBAR + if (should_refresh) + sb_set_update_time(); +#endif BuffyDoneTime = BuffyTime; return (BuffyCount); diff -urN mutt-1.6.1/buffy.h mutt-1.6.1-sidebar/buffy.h --- mutt-1.6.1/buffy.h 2016-05-02 03:02:12.397171385 +0100 +++ mutt-1.6.1-sidebar/buffy.h 2016-05-02 03:02:15.010212959 +0100 @@ -16,6 +16,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#ifndef _BUFFY_H +#define _BUFFY_H + /*parameter to mutt_parse_mailboxes*/ #define M_MAILBOXES 1 #define M_UNMAILBOXES 2 @@ -23,13 +26,28 @@ typedef struct buffy_t { char path[_POSIX_PATH_MAX]; +#ifdef USE_SIDEBAR + char realpath[_POSIX_PATH_MAX]; +#endif off_t size; struct buffy_t *next; +#ifdef USE_SIDEBAR + struct buffy_t *prev; +#endif short new; /* mailbox has new mail */ +#ifdef USE_SIDEBAR + int msg_count; /* total number of messages */ + int msg_unread; /* number of unread messages */ + int msg_flagged; /* number of flagged messages */ + short is_hidden; /* is hidden from the sidebar */ +#endif short notified; /* user has been notified */ short magic; /* mailbox type */ short newly_created; /* mbox or mmdf just popped into existence */ time_t last_visited; /* time of last exit from this mailbox */ +#ifdef USE_SIDEBAR + time_t sb_last_checked; /* time of last buffy check from sidebar */ +#endif } BUFFY; @@ -49,3 +67,5 @@ void mutt_buffy_setnotified (const char *path); void mh_buffy (BUFFY *); + +#endif /* _BUFFY_H */ diff -urN mutt-1.6.1/color.c mutt-1.6.1-sidebar/color.c --- mutt-1.6.1/color.c 2016-05-02 03:02:12.397171385 +0100 +++ mutt-1.6.1-sidebar/color.c 2016-05-02 03:02:15.010212959 +0100 @@ -94,6 +94,14 @@ { "underline", MT_COLOR_UNDERLINE }, { "index", MT_COLOR_INDEX }, { "prompt", MT_COLOR_PROMPT }, +#ifdef USE_SIDEBAR + { "sidebar_divider", MT_COLOR_DIVIDER }, + { "sidebar_flagged", MT_COLOR_FLAGGED }, + { "sidebar_highlight",MT_COLOR_HIGHLIGHT }, + { "sidebar_indicator",MT_COLOR_SB_INDICATOR }, + { "sidebar_new", MT_COLOR_NEW }, + { "sidebar_spoolfile",MT_COLOR_SB_SPOOLFILE }, +#endif { NULL, 0 } }; @@ -146,6 +154,9 @@ ColorDefs[MT_COLOR_INDICATOR] = A_REVERSE; ColorDefs[MT_COLOR_SEARCH] = A_REVERSE; ColorDefs[MT_COLOR_MARKERS] = A_REVERSE; +#ifdef USE_SIDEBAR + ColorDefs[MT_COLOR_HIGHLIGHT] = A_UNDERLINE; +#endif /* special meaning: toggle the relevant attribute */ ColorDefs[MT_COLOR_BOLD] = 0; ColorDefs[MT_COLOR_UNDERLINE] = 0; diff -urN mutt-1.6.1/compose.c mutt-1.6.1-sidebar/compose.c --- mutt-1.6.1/compose.c 2016-05-02 03:02:12.398171401 +0100 +++ mutt-1.6.1-sidebar/compose.c 2016-05-02 03:02:15.010212959 +0100 @@ -32,6 +32,9 @@ #include "mailbox.h" #include "sort.h" #include "charset.h" +#ifdef USE_SIDEBAR +#include "sidebar.h" +#endif #ifdef MIXMASTER #include "remailer.h" @@ -72,7 +75,7 @@ #define HDR_XOFFSET 10 #define TITLE_FMT "%10s" /* Used for Prompts, which are ASCII */ -#define W (COLS - HDR_XOFFSET) +#define W (COLS - HDR_XOFFSET - SidebarWidth) static const char * const Prompts[] = { @@ -110,7 +113,7 @@ static void redraw_crypt_lines (HEADER *msg) { - mvaddstr (HDR_CRYPT, 0, "Security: "); + mvprintw (HDR_CRYPT, SidebarWidth, TITLE_FMT, "Security: "); if ((WithCrypto & (APPLICATION_PGP | APPLICATION_SMIME)) == 0) { @@ -145,7 +148,7 @@ addstr (_(" (OppEnc mode)")); clrtoeol (); - move (HDR_CRYPTINFO, 0); + move (HDR_CRYPTINFO, SidebarWidth); clrtoeol (); if ((WithCrypto & APPLICATION_PGP) @@ -162,7 +165,7 @@ && (msg->security & ENCRYPT) && SmimeCryptAlg && *SmimeCryptAlg) { - mvprintw (HDR_CRYPTINFO, 40, "%s%s", _("Encrypt with: "), + mvprintw (HDR_CRYPTINFO, SidebarWidth + 40, "%s%s", _("Encrypt with: "), NONULL(SmimeCryptAlg)); } } @@ -175,7 +178,7 @@ int c; char *t; - mvaddstr (HDR_MIX, 0, " Mix: "); + mvprintw (HDR_MIX, SidebarWidth, TITLE_FMT, "Mix: "); if (!chain) { @@ -190,7 +193,7 @@ if (t && t[0] == '0' && t[1] == '\0') t = ""; - if (c + mutt_strlen (t) + 2 >= COLS) + if (c + mutt_strlen (t) + 2 >= COLS - SidebarWidth) break; addstr (NONULL(t)); @@ -242,20 +245,23 @@ buf[0] = 0; rfc822_write_address (buf, sizeof (buf), addr, 1); - mvprintw (line, 0, TITLE_FMT, Prompts[line - 1]); + mvprintw (line, SidebarWidth, TITLE_FMT, Prompts[line - 1]); mutt_paddstr (W, buf); } static void draw_envelope (HEADER *msg, char *fcc) { +#ifdef USE_SIDEBAR + sb_draw(); +#endif draw_envelope_addr (HDR_FROM, msg->env->from); draw_envelope_addr (HDR_TO, msg->env->to); draw_envelope_addr (HDR_CC, msg->env->cc); draw_envelope_addr (HDR_BCC, msg->env->bcc); - mvprintw (HDR_SUBJECT, 0, TITLE_FMT, Prompts[HDR_SUBJECT - 1]); + mvprintw (HDR_SUBJECT, SidebarWidth, TITLE_FMT, Prompts[HDR_SUBJECT - 1]); mutt_paddstr (W, NONULL (msg->env->subject)); draw_envelope_addr (HDR_REPLYTO, msg->env->reply_to); - mvprintw (HDR_FCC, 0, TITLE_FMT, Prompts[HDR_FCC - 1]); + mvprintw (HDR_FCC, SidebarWidth, TITLE_FMT, Prompts[HDR_FCC - 1]); mutt_paddstr (W, fcc); if (WithCrypto) @@ -266,7 +272,7 @@ #endif SETCOLOR (MT_COLOR_STATUS); - mvaddstr (HDR_ATTACH - 1, 0, _("-- Attachments")); + mvaddstr (HDR_ATTACH - 1, SidebarWidth, _("-- Attachments")); clrtoeol (); NORMAL_COLOR; @@ -302,7 +308,7 @@ /* redraw the expanded list so the user can see the result */ buf[0] = 0; rfc822_write_address (buf, sizeof (buf), *addr, 1); - move (line, HDR_XOFFSET); + move (line, HDR_XOFFSET + SidebarWidth); mutt_paddstr (W, buf); return 0; @@ -564,7 +570,7 @@ if (mutt_get_field ("Subject: ", buf, sizeof (buf), 0) == 0) { mutt_str_replace (&msg->env->subject, buf); - move (HDR_SUBJECT, HDR_XOFFSET); + move (HDR_SUBJECT, HDR_XOFFSET + SidebarWidth); if (msg->env->subject) mutt_paddstr (W, msg->env->subject); else @@ -582,7 +588,7 @@ { strfcpy (fcc, buf, fcclen); mutt_pretty_mailbox (fcc, fcclen); - move (HDR_FCC, HDR_XOFFSET); + move (HDR_FCC, HDR_XOFFSET + SidebarWidth); mutt_paddstr (W, fcc); fccSet = 1; } diff -urN mutt-1.6.1/configure.ac mutt-1.6.1-sidebar/configure.ac --- mutt-1.6.1/configure.ac 2016-05-02 03:02:12.398171401 +0100 +++ mutt-1.6.1-sidebar/configure.ac 2016-05-02 03:02:15.011212974 +0100 @@ -175,6 +175,15 @@ SMIMEAUX_TARGET="smime_keys" fi +AC_ARG_ENABLE(sidebar, AC_HELP_STRING([--enable-sidebar], [Enable Sidebar support]), +[ if test x$enableval = xyes ; then + AC_DEFINE(USE_SIDEBAR,1,[ Define if you want support for the sidebar. ]) + OPS="$OPS \$(srcdir)/OPS.SIDEBAR" + need_sidebar="yes" + fi +]) +AM_CONDITIONAL(BUILD_SIDEBAR, test x$need_sidebar = xyes) + AC_ARG_WITH(mixmaster, AS_HELP_STRING([--with-mixmaster@<:@=PATH@:>@],[Include Mixmaster support]), [if test "$withval" != no then diff -urN mutt-1.6.1/copy.c mutt-1.6.1-sidebar/copy.c --- mutt-1.6.1/copy.c 2016-05-02 03:02:12.398171401 +0100 +++ mutt-1.6.1-sidebar/copy.c 2016-05-02 03:02:15.011212974 +0100 @@ -288,7 +288,7 @@ if (flags & (CH_DECODE|CH_PREFIX)) { if (mutt_write_one_header (out, 0, headers[x], - flags & CH_PREFIX ? prefix : 0, mutt_term_width (Wrap), flags) == -1) + flags & CH_PREFIX ? prefix : 0, mutt_term_width (Wrap) - SidebarWidth, flags) == -1) { error = TRUE; break; diff -urN mutt-1.6.1/curs_main.c mutt-1.6.1-sidebar/curs_main.c --- mutt-1.6.1/curs_main.c 2016-05-02 03:02:12.400171433 +0100 +++ mutt-1.6.1-sidebar/curs_main.c 2016-05-02 03:02:15.012212990 +0100 @@ -26,8 +26,13 @@ #include "mailbox.h" #include "mapping.h" #include "sort.h" +#include "buffy.h" #include "mx.h" +#ifdef USE_SIDEBAR +#include "sidebar.h" +#endif + #ifdef USE_POP #include "pop.h" #endif @@ -595,21 +600,39 @@ menu->redraw |= REDRAW_STATUS; if (do_buffy_notify) { - if (mutt_buffy_notify () && option (OPTBEEPNEW)) - beep (); + if (mutt_buffy_notify()) + { + menu->redraw |= REDRAW_STATUS; + if (option (OPTBEEPNEW)) + beep(); + } } else do_buffy_notify = 1; } +#ifdef USE_SIDEBAR + if (option (OPTSIDEBAR)) + menu->redraw |= REDRAW_SIDEBAR; +#endif + if (op != -1) mutt_curs_set (0); if (menu->redraw & REDRAW_FULL) { menu_redraw_full (menu); +#ifdef USE_SIDEBAR + sb_draw(); +#endif mutt_show_error (); } +#ifdef USE_SIDEBAR + else if (menu->redraw & REDRAW_SIDEBAR) { + sb_draw(); + menu->redraw &= ~REDRAW_SIDEBAR; + } +#endif if (menu->menu == MENU_MAIN) { @@ -630,9 +653,20 @@ if (menu->redraw & REDRAW_STATUS) { +#ifdef USE_SIDEBAR + /* Temporarily lie about the sidebar width */ + short sw = SidebarWidth; + SidebarWidth = 0; +#endif menu_status_line (buf, sizeof (buf), menu, NONULL (Status)); +#ifdef USE_SIDEBAR + SidebarWidth = sw; /* Restore the sidebar width */ +#endif move (option (OPTSTATUSONTOP) ? 0 : LINES-2, 0); SETCOLOR (MT_COLOR_STATUS); +#ifdef USE_SIDEBAR + sb_set_buffystats (Context); +#endif mutt_paddstr (COLS, buf); NORMAL_COLOR; menu->redraw &= ~REDRAW_STATUS; @@ -652,7 +686,7 @@ menu->oldcurrent = -1; if (option (OPTARROWCURSOR)) - move (menu->current - menu->top + menu->offset, 2); + move (menu->current - menu->top + menu->offset, SidebarWidth + 2); else if (option (OPTBRAILLEFRIENDLY)) move (menu->current - menu->top + menu->offset, 0); else @@ -1091,6 +1125,9 @@ break; CHECK_MSGCOUNT; +#ifdef USE_SIDEBAR + CHECK_VISIBLE; +#endif CHECK_READONLY; { int oldvcount = Context->vcount; @@ -1150,6 +1187,9 @@ menu->redraw = REDRAW_FULL; break; +#ifdef USE_SIDEBAR + case OP_SIDEBAR_OPEN: +#endif case OP_MAIN_CHANGE_FOLDER: case OP_MAIN_NEXT_UNREAD_MAILBOX: @@ -1181,6 +1221,14 @@ { mutt_buffy (buf, sizeof (buf)); +#ifdef USE_SIDEBAR + if (op == OP_SIDEBAR_OPEN) { + const char *path = sb_get_highlight(); + if (!path) + break; + strncpy (buf, path, sizeof (buf)); + } else +#endif if (mutt_enter_fname (cp, buf, sizeof (buf), &menu->redraw, 1) == -1) { if (menu->menu == MENU_PAGER) @@ -1199,6 +1247,9 @@ } mutt_expand_path (buf, sizeof (buf)); +#ifdef USE_SIDEBAR + sb_set_open_buffy (buf); +#endif if (mx_get_magic (buf) <= 0) { mutt_error (_("%s is not a mailbox."), buf); @@ -2310,6 +2361,21 @@ mutt_what_key(); break; +#ifdef USE_SIDEBAR + case OP_SIDEBAR_NEXT: + case OP_SIDEBAR_NEXT_NEW: + case OP_SIDEBAR_PAGE_DOWN: + case OP_SIDEBAR_PAGE_UP: + case OP_SIDEBAR_PREV: + case OP_SIDEBAR_PREV_NEW: + sb_change_mailbox (op); + break; + + case OP_SIDEBAR_TOGGLE_VISIBLE: + toggle_option (OPTSIDEBAR); + menu->redraw = REDRAW_FULL; + break; +#endif default: if (menu->menu == MENU_MAIN) km_error_key (MENU_MAIN); diff -urN mutt-1.6.1/doc/manual.xml.head mutt-1.6.1-sidebar/doc/manual.xml.head --- mutt-1.6.1/doc/manual.xml.head 2016-05-02 03:02:12.402171465 +0100 +++ mutt-1.6.1-sidebar/doc/manual.xml.head 2016-05-02 03:02:15.014213022 +0100 @@ -405,6 +405,623 @@ + + Sidebar + + The Sidebar shows a list of all your mailboxes. The list can be + turned on and off, it can be themed and the list style can be + configured. + + + This part of the manual is suitable for beginners. + If you already know Mutt you could skip ahead to the main + Sidebar guide. + If you just want to get started, you could use the sample + Sidebar muttrc. + + + This version of Sidebar is based on Terry Chan's + 2015-11-11 release. + It contains many + new features, + lots of + bugfixes + and a generous helping of + new documentation which you are already reading. + + + To check if Mutt supports Sidebar, look for the string + +USE_SIDEBAR in the mutt version. + + +mutt -v + + + Let's turn on the Sidebar: + + set sidebar_visible + + You will see something like this. + A list of mailboxes on the left. + A list of emails, from the selected mailbox, on the right. + + +Fruit [1] 3/8| 1 + Jan 24 Rhys Lee (192) Yew +Animals [1] 2/6| 2 + Feb 11 Grace Hall (167) Ilama +Cars 4| 3 Feb 23 Aimee Scott (450) Nectarine +Seas 1/7| 4 ! Feb 28 Summer Jackson (264) Lemon + | 5 Mar 07 Callum Harrison (464) Raspberry + | 6 N + Mar 24 Samuel Harris (353) Tangerine + | 7 N + Sep 05 Sofia Graham (335) Cherry + | 8 N Sep 16 Ewan Brown (105) Ugli + | + | + + + This user has four mailboxes: Fruit, + Cars, Animals and + Seas. + + + The current, open, mailbox is Fruit. We can + also see information about the other mailboxes. For example: + The Animals mailbox contains, 1 flagged email, 2 + new emails out of a total of 6 emails. + + + Navigation + + The Sidebar adds some new functions + to Mutt. + + + The user pressed the c key to + <change-folder> to the + Animals mailbox. The Sidebar automatically + updated the indicator to match. + + +Fruit [1] 3/8| 1 Jan 03 Tia Gibson (362) Caiman +Animals [1] 2/6| 2 + Jan 22 Rhys Lee ( 48) Dolphin +Cars 4| 3 ! Aug 16 Ewan Brown (333) Hummingbird +Seas 1/7| 4 Sep 25 Grace Hall ( 27) Capybara + | 5 N + Nov 12 Evelyn Rogers (453) Tapir + | 6 N + Nov 16 Callum Harrison (498) Hedgehog + | + | + | + | + + + Let's map some functions: + + +bind index,pager \CP sidebar-prev # Ctrl-Shift-P - Previous Mailbox +bind index,pager \CN sidebar-next # Ctrl-Shift-N - Next Mailbox +bind index,pager \CO sidebar-open # Ctrl-Shift-O - Open Highlighted Mailbox + + + Press Ctrl-Shift-N (Next mailbox) twice will + move the Sidebar highlight to + down to the Seas mailbox. + + +Fruit [1] 3/8| 1 Jan 03 Tia Gibson (362) Caiman +Animals [1] 2/6| 2 + Jan 22 Rhys Lee ( 48) Dolphin +Cars 4| 3 ! Aug 16 Ewan Brown (333) Hummingbird +Seas 1/7| 4 Sep 25 Grace Hall ( 27) Capybara + | 5 N + Nov 12 Evelyn Rogers (453) Tapir + | 6 N + Nov 16 Callum Harrison (498) Hedgehog + | + | + | + | + + + Functions <sidebar-next> and + <sidebar-prev> move the Sidebar + highlight. + They do not change the open + mailbox. + + + Press Ctrl-Shift-O + (<sidebar-open>) + to open the highlighted mailbox. + + +Fruit [1] 3/8| 1 ! Mar 07 Finley Jones (139) Molucca Sea +Animals [1] 2/6| 2 + Mar 24 Summer Jackson ( 25) Arafura Sea +Cars 4| 3 + Feb 28 Imogen Baker (193) Pechora Sea +Seas 1/7| 4 N + Feb 23 Isla Hussain (348) Balearic Sea + | + | + | + | + | + | + + + + Features + + The Sidebar shows a list of mailboxes in a panel. + + + Everything about the Sidebar can be configured. + + + <link linkend="intro-sidebar-basics">State of the Sidebar</link> + Visibility + Width + + + <link linkend="intro-sidebar-limit">Which mailboxes are displayed</link> + Display all + Limit to mailboxes with new mail + Whitelist mailboxes to display always + + + <link linkend="sidebar-sort">The order in which mailboxes are displayed</link> + + Unsorted (order of mailboxes commands) + Sorted alphabetically + Sorted by number of new mails + + + <link linkend="intro-sidebar-colors">Color</link> + Sidebar indicators and divider + Mailboxes depending on their type + Mailboxes depending on their contents + + + <link linkend="sidebar-functions">Key bindings</link> + Hide/Unhide the Sidebar + Select previous/next mailbox + Select previous/next mailbox with new mail + Page up/down through a list of mailboxes + + + Misc + Formatting string for mailbox + Wraparound searching + Flexible mailbox abbreviations + Support for Unicode mailbox names (utf-8) + + + + Display + + Everything about the Sidebar can be configured. + + + For a quick reference: + Sidebar variables to set + Sidebar colors to apply + Sidebar sort methods + + + Sidebar Basics + + The most important variable is $sidebar_visible. + You can set this in your muttrc, or bind a key to the + function <sidebar-toggle-visible>. + + +set sidebar_visible # Make the Sidebar visible by default +bind index,pager B sidebar-toggle-visible # Use 'B' to switch the Sidebar on and off + + + Next, decide how wide you want the Sidebar to be. 25 + characters might be enough for the mailbox name and some numbers. + Remember, you can hide/show the Sidebar at the press of button. + + + Finally, you might want to change the divider character. + By default, Sidebar draws an ASCII line between it and the Index panel + If your terminal supports it, you can use a Unicode line-drawing character. + + +set sidebar_width = 25 # Plenty of space +set sidebar_divider_char = '│' # Pretty line-drawing character + + + + Sidebar Format String + + $sidebar_format allows you to customize the Sidebar display. + For an introduction, read format strings + including the section about conditionals. + + + The default value is %B%?F? [%F]?%* %?N?%N/?%S + + + Which breaks down as: + %B - Mailbox name + %?F? [%F]? - If flagged emails [%F], otherwise nothing + %* - Pad with spaces + %?N?%N/? - If new emails %N/, otherwise nothing + %S - Total number of emails + + + sidebar_format + + + + Format + Notes + Description + + + + + %B + + Name of the mailbox + + + %S + * + Size of mailbox (total number of messages) + + + %N + * + Number of New messages in the mailbox + + + %F + * + Number of Flagged messages in the mailbox + + + %! + + + !: one flagged message; + !!: two flagged messages; + n!: n flagged messages (for n > 2). + Otherwise prints nothing. + + + + %d + * ‡ + Number of deleted messages + + + %L + * ‡ + Number of messages after limiting + + + %t + * ‡ + Number of tagged messages + + + %>X + + Right justify the rest of the string and pad with X + + + %|X + + Pad to the end of the line with + X + + + %*X + + Soft-fill with character Xas pad + + + +
+ + * = Can be optionally printed if nonzero + + + ‡ = Only applicable to the current folder + + + Here are some examples. + They show the number of (F)lagged, (N)ew and (S)ize. + + + sidebar_format + + + + Format + Example + + + + + %B%?F? [%F]?%* %?N?%N/?%S + mailbox [F] N/S + + + %B%* %F:%N:%S + mailbox F:N:S + + + %B %?N?(%N)?%* %S + mailbox (N) S + + + %B%* ?F?%F/?%N + mailbox F/S + + + +
+
+ + Abbreviating Mailbox Names + + $sidebar_delim_chars tells Sidebar + how to split up mailbox paths. For local directories + use /; for IMAP folders use . + + + Example 1 + + This example works well if your mailboxes have unique names + after the last separator. + + + Add some mailboxes of diffent depths. + + +set folder="~/mail" +mailboxes =fruit/apple =fruit/banana =fruit/cherry +mailboxes =water/sea/sicily =water/sea/archipelago =water/sea/sibuyan +mailboxes =water/ocean/atlantic =water/ocean/pacific =water/ocean/arctic + + + Shorten the names: + + +set sidebar_short_path # Shorten mailbox names +set sidebar_delim_chars="/" # Delete everything up to the last / character + + + The screenshot below shows what the Sidebar would look like + before and after shortening. + + +|fruit/apple |apple +|fruit/banana |banana +|fruit/cherry |cherry +|water/sea/sicily |sicily +|water/sea/archipelago |archipelago +|water/sea/sibuyan |sibuyan +|water/ocean/atlantic |atlantic +|water/ocean/pacific |pacific +|water/ocean/arctic |arctic + + + + Example 2 + + This example works well if you have lots of mailboxes which are arranged + in a tree. + + + Add some mailboxes of diffent depths. + + +set folder="~/mail" +mailboxes =fruit +mailboxes =fruit/apple =fruit/banana =fruit/cherry +mailboxes =water +mailboxes =water/sea +mailboxes =water/sea/sicily =water/sea/archipelago =water/sea/sibuyan +mailboxes =water/ocean +mailboxes =water/ocean/atlantic =water/ocean/pacific =water/ocean/arctic + + + Shorten the names: + + +set sidebar_short_path # Shorten mailbox names +set sidebar_delim_chars="/" # Delete everything up to the last / character +set sidebar_folder_indent # Indent folders whose names we've shortened +set sidebar_indent_string=" " # Indent with two spaces + + + The screenshot below shows what the Sidebar would look like + before and after shortening. + + +|fruit |fruit +|fruit/apple | apple +|fruit/banana | banana +|fruit/cherry | cherry +|water |water +|water/sea | sea +|water/sea/sicily | sicily +|water/sea/archipelago | archipelago +|water/sea/sibuyan | sibuyan +|water/ocean | ocean +|water/ocean/atlantic | atlantic +|water/ocean/pacific | pacific +|water/ocean/arctic | arctic + + + Sometimes, it will be necessary to add mailboxes, that you + don't use, to fill in part of the tree. This will trade + vertical space for horizonal space (but it looks good). + + + + + Limiting the Number of Mailboxes + + If you have a lot of mailboxes, sometimes it can be useful to hide + the ones you aren't using. $sidebar_new_mail_only + tells Sidebar to only show mailboxes that contain new, or flagged, email. + + + If you want some mailboxes to be always visible, then use the + sidebar_whitelist command. It takes a list of + mailboxes as parameters. + + +set sidebar_new_mail_only # Only mailboxes with new/flagged email +sidebar_whitelist fruit fruit/apple # Always display these two mailboxes + + +
+ + Colors + + Here is a sample color scheme: + + +color sidebar_indicator default color17 # Dark blue background +color sidebar_highlight white color238 # Grey background +color sidebar_spoolfile yellow default # Yellow +color sidebar_new green default # Green +color sidebar_flagged red default # Red +color sidebar_divider color8 default # Dark grey + + + There is a priority order when coloring Sidebar mailboxes. + e.g. If a mailbox has new mail it will have the + sidebar_new color, even if it also contains + flagged mails. + + + Sidebar Color Priority + + + + Priority + Color + Description + + + + + Highest + sidebar_indicator + Mailbox is open + + + + sidebar_highlight + Mailbox is highlighed + + + + sidebar_spoolfile + Mailbox is the spoolfile (receives incoming mail) + + + + sidebar_new + Mailbox contains new mail + + + + sidebar_flagged + Mailbox contains flagged mail + + + Lowest + (None) + Mailbox does not match above + + + +
+
+ + Bug-fixes + + If you haven't used Sidebar before, you can ignore this section. + + + These bugs have been fixed since the previous Sidebar release: 2015-11-11. + + + Fix bug when starting in compose mode + Fix bug with empty sidebar_divider_char string + Fix bug with header wrapping + Correctly handle utf8 character sequences + Fix a bug in mh_buffy_update + Fix refresh -- time overflowed short + Protect against empty format strings + Limit Sidebar width to COLS + Handle unmailboxes * safely + Refresh Sidebar after timeout + + + + Config Changes + + If you haven't used Sidebar before, you can ignore this section. + + + Some of the Sidebar config has been changed to make its meaning clearer. + These changes have been made since the previous Sidebar release: 2015-11-11. + + + Config Changes + + + + Old Name + New Name + + + + + $sidebar_delim + $sidebar_divider_char + + + $sidebar_folderindent + $sidebar_folder_indent + + + $sidebar_indentstr + $sidebar_indent_string + + + $sidebar_newmail_only + $sidebar_new_mail_only + + + $sidebar_refresh + $sidebar_refresh_time + + + $sidebar_shortpath + $sidebar_short_path + + + $sidebar_sort + $sidebar_sort_method + + + <sidebar-scroll-down> + <sidebar-page-down> + + + <sidebar-scroll-up> + <sidebar-page-up> + + + +
+
+
+ Help @@ -8081,6 +8698,469 @@ + + Sidebar Patch + Overview of mailboxes + + + Patch + + + To check if Mutt supports Sidebar, look for + +USE_SIDEBAR in the mutt version. + See: . + + + + Dependencies: + mutt-1.5.24 + + + This patch is part of the NeoMutt Project. + + + + Introduction + + + The Sidebar shows a list of all your mailboxes. The list can be + turned on and off, it can be themed and the list style can be + configured. + + + + This part of the manual is a reference guide. + If you want a simple introduction with examples see the + Sidebar Howto. + If you just want to get started, you could use the sample + Sidebar muttrc. + + + + This version of Sidebar is based on Terry Chan's + 2015-11-11 release. + It contains many + new features, + lots of + bugfixes. + + + + + Variables + + + Sidebar Variables + + + + Name + Type + Default + + + + + sidebar_delim_chars + string + /. + + + sidebar_divider_char + string + | + + + sidebar_folder_indent + boolean + no + + + sidebar_format + string + %B%?F? [%F]?%* %?N?%N/?%S + + + sidebar_indent_string + string +    (two spaces) + + + sidebar_new_mail_only + boolean + no + + + sidebar_next_new_wrap + boolean + no + + + sidebar_refresh_time + number + 60 + + + sidebar_short_path + boolean + no + + + sidebar_sort_method + enum + SORT_ORDER + + + sidebar_visible + boolean + no + + + sidebar_whitelist + list + (empty) + + + sidebar_width + number + 20 + + + +
+
+ + + Functions + + + Sidebar adds the following functions to Mutt. + By default, none of them are bound to keys. + + + + Sidebar Functions + + + + Menus + Function + Description + + + + + index,pager + <sidebar-next> + Move the highlight to next mailbox + + + index,pager + <sidebar-next-new> + Move the highlight to next mailbox with new mail + + + index,pager + <sidebar-open> + Open highlighted mailbox + + + index,pager + <sidebar-page-down> + Scroll the Sidebar down 1 page + + + index,pager + <sidebar-page-up> + Scroll the Sidebar up 1 page + + + index,pager + <sidebar-prev> + Move the highlight to previous mailbox + + + index,pager + <sidebar-prev-new> + Move the highlight to previous mailbox with new mail + + + index,pager + <sidebar-toggle-visible> + Make the Sidebar (in)visible + + + +
+
+ + + Commands + + sidebar_whitelist + + mailbox + + + mailbox + + + + + + Colors + + + Sidebar Colors + + + + Name + Default Color + Description + + + + + sidebar_divider + default + The dividing line between the Sidebar and the Index/Pager panels + + + sidebar_flagged + default + Mailboxes containing flagged mail + + + sidebar_highlight + underline + Cursor to select a mailbox + + + sidebar_indicator + mutt indicator + The mailbox open in the Index panel + + + sidebar_new + default + Mailboxes containing new mail + + + sidebar_spoolfile + default + Mailbox that receives incoming mail + + + +
+ + If the sidebar_indicator color isn't set, then the default Mutt + indicator color will be used (the color used in the index panel). +
+ + + Sort + + + Sidebar Sort + + + + Sort + Description + + + + + alpha + Alphabetically by path + + + count + Total number of messages + + + flagged + Number of flagged messages + + + name + Alphabetically by path + + + new + Number of new messages + + + path + Alphabetically by path + + + unsorted + Do not resort the paths + + + +
+
+ + + Muttrc + +# This is a complete list of sidebar-related configuration. + +# -------------------------------------------------------------------------- +# VARIABLES - shown with their default values +# -------------------------------------------------------------------------- + +# Should the Sidebar be shown? +set sidebar_visible = no + +# How wide should the Sidebar be in screen columns? +# Note: Some characters, e.g. Chinese, take up two columns each. +set sidebar_width = 20 + +# Should the mailbox paths be abbreviated? +set sidebar_short_path = no + +# When abbreviating mailbox path names, use any of these characters as path +# separators. Only the part after the last separators will be shown. +# For file folders '/' is good. For IMAP folders, often '.' is useful. +set sidebar_delim_chars = '/.' + +# If the mailbox path is abbreviated, should it be indented? +set sidebar_folder_indent = no + +# Indent mailbox paths with this string. +set sidebar_indent_string = ' ' + +# Make the Sidebar only display mailboxes that contain new, or flagged, +# mail. +set sidebar_new_mail_only = no + +# Any mailboxes that are whitelisted will always be visible, even if the +# sidebar_new_mail_only option is enabled. +sidebar_whitelist '/home/user/mailbox1' +sidebar_whitelist '/home/user/mailbox2' + +# When searching for mailboxes containing new mail, should the search wrap +# around when it reaches the end of the list? +set sidebar_next_new_wrap = no + +# The character to use as the divider between the Sidebar and the other Mutt +# panels. +# Note: Only the first character of this string is used. +set sidebar_divider_char = '|' + +# Display the Sidebar mailboxes using this format string. +set sidebar_format = '%B%?F? [%F]?%* %?N?%N/?%S' + +# Sidebar will not refresh its list of mailboxes any more frequently than +# this number of seconds. This will help reduce disk/network traffic. +set sidebar_refresh_time = 60 + +# Sort the mailboxes in the Sidebar using this method: +# count - total number of messages +# flagged - number of flagged messages +# new - number of new messages +# path - mailbox path +# unsorted - do not sort the mailboxes +set sidebar_sort_method = 'unsorted' + +# -------------------------------------------------------------------------- +# FUNCTIONS - shown with an example mapping +# -------------------------------------------------------------------------- + +# Move the highlight to the previous mailbox +bind index,pager \Cp sidebar-prev + +# Move the highlight to the next mailbox +bind index,pager \Cn sidebar-next + +# Open the highlighted mailbox +bind index,pager \Co sidebar-open + +# Move the highlight to the previous page +# This is useful if you have a LOT of mailboxes. +bind index,pager <F3> sidebar-page-up + +# Move the highlight to the next page +# This is useful if you have a LOT of mailboxes. +bind index,pager <F4> sidebar-page-down + +# Move the highlight to the previous mailbox containing new, or flagged, +# mail. +bind index,pager <F5> sidebar-prev-new + +# Move the highlight to the next mailbox containing new, or flagged, mail. +bind index,pager <F6> sidebar-next-new + +# Toggle the visibility of the Sidebar. +bind index,pager B sidebar-toggle-visible + +# -------------------------------------------------------------------------- +# COLORS - some unpleasant examples are given +# -------------------------------------------------------------------------- +# Note: All color operations are of the form: +# color OBJECT FOREGROUND BACKGROUND + +# Color of the current, open, mailbox +# Note: This is a general Mutt option which colors all selected items. +color indicator cyan black + +# Color of the highlighted, but not open, mailbox. +color sidebar_highlight black color8 + +# Color of the divider separating the Sidebar from Mutt panels +color sidebar_divider color8 black + +# Color to give mailboxes containing flagged mail +color sidebar_flagged red black + +# Color to give mailboxes containing new mail +color sidebar_new green black + +# -------------------------------------------------------------------------- + +# vim: syntax=muttrc + + + + + See Also + + + Regular Expressions + Patterns + Color command + notmuch patch + + + + + Known Bugs + Unsorted isn't + + + + Credits + + Justin Hibbits jrh29@po.cwru.edu + Thomer M. Gil mutt@thomer.com + David Sterba dsterba@suse.cz + Evgeni Golov evgeni@debian.org + Fabian Groffen grobian@gentoo.org + Jason DeTiberus jdetiber@redhat.com + Stefan Assmann sassmann@kpanic.de + Steve Kemp steve@steve.org.uk + Terry Chan tchan@lunar-linux.org + Tyler Earnest tylere@rne.st + Richard Russon rich@flatcap.org + + +
+ @@ -9237,6 +10317,17 @@ +sidebar_whitelist + +item + + +command + + + + + source filename diff -urN mutt-1.6.1/doc/muttrc.sidebar mutt-1.6.1-sidebar/doc/muttrc.sidebar --- mutt-1.6.1/doc/muttrc.sidebar 1970-01-01 01:00:00.000000000 +0100 +++ mutt-1.6.1-sidebar/doc/muttrc.sidebar 2016-05-02 03:02:14.932211718 +0100 @@ -0,0 +1,116 @@ +# This is a complete list of sidebar-related configuration. + +# -------------------------------------------------------------------------- +# VARIABLES - shown with their default values +# -------------------------------------------------------------------------- + +# Should the Sidebar be shown? +set sidebar_visible = no + +# How wide should the Sidebar be in screen columns? +# Note: Some characters, e.g. Chinese, take up two columns each. +set sidebar_width = 20 + +# Should the mailbox paths be abbreviated? +set sidebar_short_path = no + +# When abbreviating mailbox path names, use any of these characters as path +# separators. Only the part after the last separators will be shown. +# For file folders '/' is good. For IMAP folders, often '.' is useful. +set sidebar_delim_chars = '/.' + +# If the mailbox path is abbreviated, should it be indented? +set sidebar_folder_indent = no + +# Indent mailbox paths with this string. +set sidebar_indent_string = ' ' + +# Make the Sidebar only display mailboxes that contain new, or flagged, +# mail. +set sidebar_new_mail_only = no + +# Any mailboxes that are whitelisted will always be visible, even if the +# sidebar_new_mail_only option is enabled. +sidebar_whitelist '/home/user/mailbox1' +sidebar_whitelist '/home/user/mailbox2' + +# When searching for mailboxes containing new mail, should the search wrap +# around when it reaches the end of the list? +set sidebar_next_new_wrap = no + +# The character to use as the divider between the Sidebar and the other Mutt +# panels. +# Note: Only the first character of this string is used. +set sidebar_divider_char = '|' + +# Display the Sidebar mailboxes using this format string. +set sidebar_format = '%B%?F? [%F]?%* %?N?%N/?%S' + +# Sidebar will not refresh its list of mailboxes any more frequently than +# this number of seconds. This will help reduce disk/network traffic. +set sidebar_refresh_time = 60 + +# Sort the mailboxes in the Sidebar using this method: +# count - total number of messages +# flagged - number of flagged messages +# new - number of new messages +# path - mailbox path +# unsorted - do not sort the mailboxes +set sidebar_sort_method = 'unsorted' + +# -------------------------------------------------------------------------- +# FUNCTIONS - shown with an example mapping +# -------------------------------------------------------------------------- + +# Move the highlight to the previous mailbox +bind index,pager \Cp sidebar-prev + +# Move the highlight to the next mailbox +bind index,pager \Cn sidebar-next + +# Open the highlighted mailbox +bind index,pager \Co sidebar-open + +# Move the highlight to the previous page +# This is useful if you have a LOT of mailboxes. +bind index,pager sidebar-page-up + +# Move the highlight to the next page +# This is useful if you have a LOT of mailboxes. +bind index,pager sidebar-page-down + +# Move the highlight to the previous mailbox containing new, or flagged, +# mail. +bind index,pager sidebar-prev-new + +# Move the highlight to the next mailbox containing new, or flagged, mail. +bind index,pager sidebar-next-new + +# Toggle the visibility of the Sidebar. +bind index,pager B sidebar-toggle-visible + +# -------------------------------------------------------------------------- +# COLORS - some unpleasant examples are given +# -------------------------------------------------------------------------- +# Note: All color operations are of the form: +# color OBJECT FOREGROUND BACKGROUND + +# Color of the current, open, mailbox +# Note: This is a general Mutt option which colors all selected items. +color indicator cyan black + +# Color of the highlighted, but not open, mailbox. +color sidebar_highlight black color8 + +# Color of the divider separating the Sidebar from Mutt panels +color sidebar_divider color8 black + +# Color to give mailboxes containing flagged mail +color sidebar_flagged red black + +# Color to give mailboxes containing new mail +color sidebar_new green black + +# -------------------------------------------------------------------------- + +# vim: syntax=muttrc diff -urN mutt-1.6.1/doc/vimrc.sidebar mutt-1.6.1-sidebar/doc/vimrc.sidebar --- mutt-1.6.1/doc/vimrc.sidebar 1970-01-01 01:00:00.000000000 +0100 +++ mutt-1.6.1-sidebar/doc/vimrc.sidebar 2016-05-02 03:02:14.933211733 +0100 @@ -0,0 +1,35 @@ +" Vim syntax file for the mutt sidebar patch + +syntax keyword muttrcVarBool skipwhite contained sidebar_folder_indent nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr +syntax keyword muttrcVarBool skipwhite contained sidebar_new_mail_only nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr +syntax keyword muttrcVarBool skipwhite contained sidebar_next_new_wrap nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr +syntax keyword muttrcVarBool skipwhite contained sidebar_short_path nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr +syntax keyword muttrcVarBool skipwhite contained sidebar_visible nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr + +syntax keyword muttrcVarNum skipwhite contained sidebar_refresh_time nextgroup=muttrcSetNumAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr +syntax keyword muttrcVarNum skipwhite contained sidebar_width nextgroup=muttrcSetNumAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr + +syntax keyword muttrcVarStr contained skipwhite sidebar_divider_char nextgroup=muttrcVarEqualsIdxFmt +syntax keyword muttrcVarStr contained skipwhite sidebar_delim_chars nextgroup=muttrcVarEqualsIdxFmt +syntax keyword muttrcVarStr contained skipwhite sidebar_format nextgroup=muttrcVarEqualsIdxFmt +syntax keyword muttrcVarStr contained skipwhite sidebar_indent_string nextgroup=muttrcVarEqualsIdxFmt +syntax keyword muttrcVarStr contained skipwhite sidebar_sort_method nextgroup=muttrcVarEqualsIdxFmt + +syntax keyword muttrcCommand sidebar_whitelist + +syntax match muttrcFunction contained "\" +syntax match muttrcFunction contained "\" +syntax match muttrcFunction contained "\" +syntax match muttrcFunction contained "\" +syntax match muttrcFunction contained "\" +syntax match muttrcFunction contained "\" +syntax match muttrcFunction contained "\" +syntax match muttrcFunction contained "\" + +syntax keyword muttrcColorField contained sidebar_divider +syntax keyword muttrcColorField contained sidebar_flagged +syntax keyword muttrcColorField contained sidebar_highlight +syntax keyword muttrcColorField contained sidebar_indicator +syntax keyword muttrcColorField contained sidebar_new + +" vim: syntax=vim diff -urN mutt-1.6.1/flags.c mutt-1.6.1-sidebar/flags.c --- mutt-1.6.1/flags.c 2016-05-02 03:02:12.403171480 +0100 +++ mutt-1.6.1-sidebar/flags.c 2016-05-02 03:02:15.015213038 +0100 @@ -25,6 +25,10 @@ #include "sort.h" #include "mx.h" +#ifdef USE_SIDEBAR +#include "sidebar.h" +#endif + void _mutt_set_flag (CONTEXT *ctx, HEADER *h, int flag, int bf, int upd_ctx) { int changed = h->changed; @@ -263,6 +267,9 @@ */ if (h->searched && (changed != h->changed || deleted != ctx->deleted || tagged != ctx->tagged || flagged != ctx->flagged)) h->searched = 0; +#ifdef USE_SIDEBAR + sb_draw(); +#endif } void mutt_tag_set_flag (int flag, int bf) diff -urN mutt-1.6.1/functions.h mutt-1.6.1-sidebar/functions.h --- mutt-1.6.1/functions.h 2016-05-02 03:02:12.403171480 +0100 +++ mutt-1.6.1-sidebar/functions.h 2016-05-02 03:02:15.015213038 +0100 @@ -168,6 +168,16 @@ { "decrypt-copy", OP_DECRYPT_COPY, NULL }, { "decrypt-save", OP_DECRYPT_SAVE, NULL }, +#ifdef USE_SIDEBAR + { "sidebar-next", OP_SIDEBAR_NEXT, NULL }, + { "sidebar-next-new", OP_SIDEBAR_NEXT_NEW, NULL }, + { "sidebar-open", OP_SIDEBAR_OPEN, NULL }, + { "sidebar-page-down", OP_SIDEBAR_PAGE_DOWN, NULL }, + { "sidebar-page-up", OP_SIDEBAR_PAGE_UP, NULL }, + { "sidebar-prev", OP_SIDEBAR_PREV, NULL }, + { "sidebar-prev-new", OP_SIDEBAR_PREV_NEW, NULL }, + { "sidebar-toggle-visible", OP_SIDEBAR_TOGGLE_VISIBLE, NULL }, +#endif { NULL, 0, NULL } }; @@ -272,6 +282,17 @@ { "what-key", OP_WHAT_KEY, NULL }, +#ifdef USE_SIDEBAR + { "sidebar-next", OP_SIDEBAR_NEXT, NULL }, + { "sidebar-next-new", OP_SIDEBAR_NEXT_NEW, NULL }, + { "sidebar-open", OP_SIDEBAR_OPEN, NULL }, + { "sidebar-page-down", OP_SIDEBAR_PAGE_DOWN, NULL }, + { "sidebar-page-up", OP_SIDEBAR_PAGE_UP, NULL }, + { "sidebar-prev", OP_SIDEBAR_PREV, NULL }, + { "sidebar-prev-new", OP_SIDEBAR_PREV_NEW, NULL }, + { "sidebar-toggle-visible", OP_SIDEBAR_TOGGLE_VISIBLE, NULL }, +#endif + { NULL, 0, NULL } }; diff -urN mutt-1.6.1/globals.h mutt-1.6.1-sidebar/globals.h --- mutt-1.6.1/globals.h 2016-05-02 03:02:12.403171480 +0100 +++ mutt-1.6.1-sidebar/globals.h 2016-05-02 03:02:15.015213038 +0100 @@ -118,6 +118,12 @@ WHERE char *SendCharset; WHERE char *Sendmail; WHERE char *Shell; +#ifdef USE_SIDEBAR +WHERE char *SidebarDelimChars; +WHERE char *SidebarDividerChar; +WHERE char *SidebarFormat; +WHERE char *SidebarIndentString; +#endif WHERE char *Signature; WHERE char *SimpleSearch; #if USE_SMTP @@ -214,6 +220,14 @@ WHERE short ScoreThresholdRead; WHERE short ScoreThresholdFlag; +/* This isn't excluded from the build because it's too entwined in the code. + * For now. */ +WHERE short SidebarWidth; +#ifdef USE_SIDEBAR +WHERE short SidebarRefreshTime; +WHERE LIST *SidebarWhitelist INITVAL(0); +#endif + #ifdef USE_IMAP WHERE short ImapKeepalive; WHERE short ImapPipelineDepth; diff -urN mutt-1.6.1/imap/command.c mutt-1.6.1-sidebar/imap/command.c --- mutt-1.6.1/imap/command.c 2016-05-02 03:02:12.404171496 +0100 +++ mutt-1.6.1-sidebar/imap/command.c 2016-05-02 03:02:14.939211829 +0100 @@ -1016,6 +1016,14 @@ opened */ status->uidnext = oldun; +#ifdef USE_SIDEBAR + /* Make the sidebar show the correct numbers */ + if (status->messages) { + inc->msg_count = status->messages; + inc->msg_unread = status->unseen; + } +#endif + FREE (&value); return; } diff -urN mutt-1.6.1/imap/imap.c mutt-1.6.1-sidebar/imap/imap.c --- mutt-1.6.1/imap/imap.c 2016-05-02 03:02:12.404171496 +0100 +++ mutt-1.6.1-sidebar/imap/imap.c 2016-05-02 03:02:15.016213054 +0100 @@ -1535,7 +1535,11 @@ imap_munge_mbox_name (idata, munged, sizeof (munged), name); snprintf (command, sizeof (command), +#ifdef USE_SIDEBAR + "STATUS %s (UIDNEXT UIDVALIDITY UNSEEN RECENT MESSAGES)", munged); +#else "STATUS %s (UIDNEXT UIDVALIDITY UNSEEN RECENT)", munged); +#endif if (imap_exec (idata, command, IMAP_CMD_QUEUE) < 0) { diff -urN mutt-1.6.1/init.c mutt-1.6.1-sidebar/init.c --- mutt-1.6.1/init.c 2016-05-02 03:02:12.405171512 +0100 +++ mutt-1.6.1-sidebar/init.c 2016-05-02 03:02:15.017213070 +0100 @@ -2173,6 +2173,9 @@ case DT_SORT_AUX: map = SortAuxMethods; break; + case DT_SORT_SIDEBAR: + map = SortSidebarMethods; + break; default: map = SortMethods; break; diff -urN mutt-1.6.1/init.h mutt-1.6.1-sidebar/init.h --- mutt-1.6.1/init.h 2016-05-02 03:02:12.407171544 +0100 +++ mutt-1.6.1-sidebar/init.h 2016-05-02 03:02:15.018213086 +0100 @@ -42,11 +42,12 @@ #define DTYPE(x) ((x) & DT_MASK) /* subtypes */ -#define DT_SUBTYPE_MASK 0xf0 +#define DT_SUBTYPE_MASK 0xff0 #define DT_SORT_ALIAS 0x10 #define DT_SORT_BROWSER 0x20 #define DT_SORT_KEYS 0x40 #define DT_SORT_AUX 0x80 +#define DT_SORT_SIDEBAR 0x100 /* flags to parse_set() */ #define M_SET_INV (1<<0) /* default is to invert all vars */ @@ -2665,6 +2666,146 @@ ** Command to use when spawning a subshell. By default, the user's login ** shell from \fC/etc/passwd\fP is used. */ +#ifdef USE_SIDEBAR + { "sidebar_divider_char", DT_STR, R_BOTH, UL &SidebarDividerChar, UL "|" }, + /* + ** .pp + ** This specifies the characters to be drawn between the sidebar (when + ** visible) and the other Mutt panels. ASCII and Unicode line-drawing + ** characters are supported. + */ + { "sidebar_delim_chars", DT_STR, R_NONE, UL &SidebarDelimChars, UL "/." }, + /* + ** .pp + ** This contains the list of characters which you would like to treat + ** as folder separators for displaying paths in the sidebar. + ** .pp + ** Local mail is often arranged in directories: `dir1/dir2/mailbox'. + ** .ts + ** set sidebar_delim_chars='/' + ** .te + ** IMAP mailboxes are often named: `folder1.folder2.mailbox'. + ** .ts + ** set sidebar_delim_chars='.' + ** .te + ** .pp + ** \fBSee also:\fP $$sidebar_short_path, $$sidebar_folder_indent, $$sidebar_indent_string. + */ + { "sidebar_folder_indent", DT_BOOL, R_BOTH, OPTSIDEBARFOLDERINDENT, 0 }, + /* + ** .pp + ** Set this to indent mailboxes in the sidebar. + ** .pp + ** \fBSee also:\fP $$sidebar_short_path, $$sidebar_indent_string, $$sidebar_delim_chars. + */ + { "sidebar_format", DT_STR, R_NONE, UL &SidebarFormat, UL "%B%?F? [%F]?%* %?N?%N/?%S" }, + /* + ** .pp + ** This variable allows you to customize the sidebar display. This string is + ** similar to $$index_format, but has its own set of \fCprintf(3)\fP-like + ** sequences: + ** .dl + ** .dt %B .dd Name of the mailbox + ** .dt %S .dd * Size of mailbox (total number of messages) + ** .dt %N .dd * Number of New messages in the mailbox + ** .dt %F .dd * Number of Flagged messages in the mailbox + ** .dt %! .dd ``!'' : one flagged message; + ** ``!!'' : two flagged messages; + ** ``n!'' : n flagged messages (for n > 2). + ** Otherwise prints nothing. + ** .dt %d .dd * @ Number of deleted messages + ** .dt %L .dd * @ Number of messages after limiting + ** .dt %t .dd * @ Number of tagged messages + ** .dt %>X .dd right justify the rest of the string and pad with ``X'' + ** .dt %|X .dd pad to the end of the line with ``X'' + ** .dt %*X .dd soft-fill with character ``X'' as pad + ** .de + ** .pp + ** * = Can be optionally printed if nonzero + ** @ = Only applicable to the current folder + */ + { "sidebar_indent_string", DT_STR, R_BOTH, UL &SidebarIndentString, UL " " }, + /* + ** .pp + ** This specifies the string that is used to indent mailboxes in the sidebar. + ** It defaults to two spaces. + ** .pp + ** \fBSee also:\fP $$sidebar_short_path, $$sidebar_folder_indent, $$sidebar_delim_chars. + */ + { "sidebar_new_mail_only", DT_BOOL, R_BOTH, OPTSIDEBARNEWMAILONLY, 0 }, + /* + ** .pp + ** When set, the sidebar will only display mailboxes containing new, or + ** flagged, mail. + ** .pp + ** \fBSee also:\fP $sidebar_whitelist. + */ + { "sidebar_next_new_wrap", DT_BOOL, R_BOTH, UL OPTSIDEBARNEXTNEWWRAP, 0 }, + /* + ** .pp + ** When set, the \fC\fP command will not stop and the end of + ** the list of mailboxes, but wrap around to the beginning. The + ** \fC\fP command is similarly affected, wrapping around to + ** the end of the list. + */ + { "sidebar_refresh_time", DT_NUM, R_BOTH, UL &SidebarRefreshTime, 60 }, + /* + ** .pp + ** Set sidebar_refresh_time to the minimum number of seconds between refreshes. + ** This will reduced network traffic. + ** .pp + ** \fBNote:\fP Set to 0 to disable refreshing. + */ + { "sidebar_short_path", DT_BOOL, R_BOTH, OPTSIDEBARSHORTPATH, 0 }, + /* + ** .pp + ** By default the sidebar will show the mailbox's path, relative to the + ** $$folder variable. Setting \fCsidebar_shortpath=yes\fP will shorten the + ** names relative to the previous name. Here's an example: + ** .dl + ** .dt \fBshortpath=no\fP .dd \fBshortpath=yes\fP .dd \fBshortpath=yes, folderindent=yes, indentstr=".."\fP + ** .dt \fCfruit\fP .dd \fCfruit\fP .dd \fCfruit\fP + ** .dt \fCfruit.apple\fP .dd \fCapple\fP .dd \fC..apple\fP + ** .dt \fCfruit.banana\fP .dd \fCbanana\fP .dd \fC..banana\fP + ** .dt \fCfruit.cherry\fP .dd \fCcherry\fP .dd \fC..cherry\fP + ** .de + ** .pp + ** \fBSee also:\fP $$sidebar_delim_chars, $$sidebar_folder_indent, $$sidebar_indent_string. + */ + { "sidebar_sort_method", DT_SORT|DT_SORT_SIDEBAR, R_NONE, UL &SidebarSortMethod, SORT_ORDER }, + /* + ** .pp + ** Specifies how to sort entries in the file browser. By default, the + ** entries are sorted alphabetically. Valid values: + ** .il + ** .dd alpha (alphabetically) + ** .dd count (all message count) + ** .dd date + ** .dd desc (description) + ** .dd new (new message count) + ** .dd size + ** .dd unsorted + ** .ie + ** .pp + ** You may optionally use the ``reverse-'' prefix to specify reverse sorting + ** order (example: ``\fCset sort_browser=reverse-date\fP''). + */ + { "sidebar_visible", DT_BOOL, R_BOTH, OPTSIDEBAR, 0 }, + /* + ** .pp + ** This specifies whether or not to show sidebar. The sidebar shows a list of + ** all your mailboxes. + ** .pp + ** \fBSee also:\fP $$sidebar_format, $$sidebar_width + */ + { "sidebar_width", DT_NUM, R_BOTH, UL &SidebarWidth, 0 }, + /* + ** .pp + ** This controls the width of the sidebar. It is measured in screen columns. + ** For example: sidebar_width=20 could display 20 ASCII characters, or 10 + ** Chinese characters. + */ +#endif { "sig_dashes", DT_BOOL, R_NONE, OPTSIGDASHES, 1 }, /* ** .pp @@ -3652,6 +3793,19 @@ { NULL, 0 } }; +const struct mapping_t SortSidebarMethods[] = { + { "alpha", SORT_PATH }, + { "count", SORT_COUNT }, + { "desc", SORT_DESC }, + { "flagged", SORT_FLAGGED }, + { "mailbox-order", SORT_ORDER }, + { "name", SORT_PATH }, + { "new", SORT_COUNT_NEW }, + { "path", SORT_PATH }, + { "unsorted", SORT_ORDER }, + { NULL, 0 } +}; + /* functions used to parse commands in a rc file */ @@ -3741,6 +3895,9 @@ { "send-hook", mutt_parse_hook, M_SENDHOOK }, { "send2-hook", mutt_parse_hook, M_SEND2HOOK }, { "set", parse_set, 0 }, +#ifdef USE_SIDEBAR + { "sidebar_whitelist",parse_list, UL &SidebarWhitelist }, +#endif { "source", parse_source, 0 }, { "spam", parse_spam_list, M_SPAM }, { "nospam", parse_spam_list, M_NOSPAM }, diff -urN mutt-1.6.1/keymap.c mutt-1.6.1-sidebar/keymap.c --- mutt-1.6.1/keymap.c 2016-05-02 03:02:12.407171544 +0100 +++ mutt-1.6.1-sidebar/keymap.c 2016-05-02 03:02:14.946211940 +0100 @@ -453,6 +453,9 @@ } #endif + /* update sidebar stats */ + mutt_buffy_check(0); + timeout (i * 1000); tmp = mutt_getch(); timeout (-1); diff -urN mutt-1.6.1/mailbox.h mutt-1.6.1-sidebar/mailbox.h --- mutt-1.6.1/mailbox.h 2016-05-02 03:02:12.407171544 +0100 +++ mutt-1.6.1-sidebar/mailbox.h 2016-05-02 03:02:15.018213086 +0100 @@ -27,6 +27,9 @@ #define M_NEWFOLDER (1<<4) /* create a new folder - same as M_APPEND, but uses * safe_fopen() for mbox-style folders. */ +#ifdef USE_SIDEBAR +#define M_PEEK (1<<5) /* revert atime back after taking a look (if applicable) */ +#endif /* mx_open_new_message() */ #define M_ADD_FROM (1<<0) /* add a From_ line */ diff -urN mutt-1.6.1/main.c mutt-1.6.1-sidebar/main.c --- mutt-1.6.1/main.c 2016-05-02 03:02:12.408171560 +0100 +++ mutt-1.6.1-sidebar/main.c 2016-05-02 03:02:15.018213086 +0100 @@ -31,6 +31,9 @@ #include "url.h" #include "mutt_crypt.h" #include "mutt_idna.h" +#ifdef USE_SIDEBAR +#include "sidebar.h" +#endif #ifdef USE_SASL #include "mutt_sasl.h" @@ -485,6 +488,12 @@ "-USE_HCACHE " #endif +#ifdef USE_SIDEBAR + "+USE_SIDEBAR " +#else + "-USE_SIDEBAR " +#endif + ); #ifdef ISPELL @@ -557,7 +566,11 @@ int main (int argc, char **argv) { +#ifdef USE_SIDEBAR + char folder[PATH_MAX] = ""; +#else char folder[_POSIX_PATH_MAX] = ""; +#endif char *subject = NULL; char *includeFile = NULL; char *draftFile = NULL; @@ -828,6 +841,9 @@ clear (); mutt_error = mutt_curses_error; mutt_message = mutt_curses_message; +#ifdef USE_SIDEBAR + sb_init(); +#endif } /* Create the Maildir directory if it doesn't exist. */ @@ -1184,6 +1200,15 @@ strfcpy (folder, NONULL(Spoolfile), sizeof (folder)); mutt_expand_path (folder, sizeof (folder)); +#ifdef USE_SIDEBAR + { + char tmpfolder[PATH_MAX] = ""; + strfcpy (tmpfolder, folder, sizeof (tmpfolder)); + if (!realpath (tmpfolder, folder)) + strfcpy (folder, tmpfolder, sizeof (tmpfolder)); + } +#endif + mutt_str_replace (&CurrentFolder, folder); mutt_str_replace (&LastFolder, folder); @@ -1206,6 +1231,9 @@ if((Context = mx_open_mailbox (folder, ((flags & M_RO) || option (OPTREADONLY)) ? M_READONLY : 0, NULL)) || !explicit_folder) { +#ifdef USE_SIDEBAR + sb_set_open_buffy (folder); +#endif mutt_index_menu (); if (Context) FREE (&Context); diff -urN mutt-1.6.1/Makefile.am mutt-1.6.1-sidebar/Makefile.am --- mutt-1.6.1/Makefile.am 2016-05-02 03:02:12.392171305 +0100 +++ mutt-1.6.1-sidebar/Makefile.am 2016-05-02 03:02:15.005212879 +0100 @@ -77,6 +77,12 @@ EXTRA_SCRIPTS = smime_keys +if BUILD_SIDEBAR +mutt_SOURCES += sidebar.c sidebar.h +endif + +EXTRA_DIST += OPS.SIDEBAR + mutt_dotlock_SOURCES = mutt_dotlock.c mutt_dotlock_LDADD = $(LIBOBJS) mutt_dotlock_DEPENDENCIES = $(LIBOBJS) @@ -129,10 +135,10 @@ keymap_defs.h: $(OPS) $(srcdir)/gen_defs $(srcdir)/gen_defs $(OPS) > keymap_defs.h -keymap_alldefs.h: $(srcdir)/OPS $(srcdir)/OPS.PGP $(srcdir)/OPS.MIX $(srcdir)/OPS.CRYPT $(srcdir)/OPS.SMIME $(srcdir)/gen_defs +keymap_alldefs.h: $(srcdir)/OPS $(srcdir)/OPS.SIDEBAR $(srcdir)/OPS.PGP $(srcdir)/OPS.MIX $(srcdir)/OPS.CRYPT $(srcdir)/OPS.SMIME $(srcdir)/gen_defs rm -f $@ $(srcdir)/gen_defs $(srcdir)/OPS $(srcdir)/OPS.PGP \ - $(srcdir)/OPS.MIX $(srcdir)/OPS.CRYPT $(srcdir)/OPS.SMIME \ + $(srcdir)/OPS.SIDEBAR $(srcdir)/OPS.MIX $(srcdir)/OPS.CRYPT $(srcdir)/OPS.SMIME \ > keymap_alldefs.h reldate.h: $(srcdir)/ChangeLog diff -urN mutt-1.6.1/mbox.c mutt-1.6.1-sidebar/mbox.c --- mutt-1.6.1/mbox.c 2016-05-02 03:02:12.408171560 +0100 +++ mutt-1.6.1-sidebar/mbox.c 2016-05-02 03:02:14.948211972 +0100 @@ -100,6 +100,9 @@ mutt_perror (ctx->path); return (-1); } +#ifdef USE_SIDEBAR + ctx->atime = sb.st_atime; +#endif ctx->mtime = sb.st_mtime; ctx->size = sb.st_size; @@ -251,6 +254,9 @@ ctx->size = sb.st_size; ctx->mtime = sb.st_mtime; +#ifdef USE_SIDEBAR + ctx->atime = sb.st_atime; +#endif #ifdef NFS_ATTRIBUTE_HACK if (sb.st_mtime > sb.st_atime) diff -urN mutt-1.6.1/menu.c mutt-1.6.1-sidebar/menu.c --- mutt-1.6.1/menu.c 2016-05-02 03:02:12.408171560 +0100 +++ mutt-1.6.1-sidebar/menu.c 2016-05-02 03:02:15.019213102 +0100 @@ -24,6 +24,9 @@ #include "mutt_curses.h" #include "mutt_menu.h" #include "mbyte.h" +#ifdef USE_SIDEBAR +#include "sidebar.h" +#endif char* SearchBuffers[MENU_MAX]; @@ -184,7 +187,7 @@ { char *scratch = safe_strdup (s); int shift = option (OPTARROWCURSOR) ? 3 : 0; - int cols = COLS - shift; + int cols = COLS - shift - SidebarWidth; mutt_format_string (s, n, cols, cols, FMT_LEFT, ' ', scratch, mutt_strlen (scratch), 1); s[n - 1] = 0; @@ -237,6 +240,9 @@ int do_color; int attr; +#ifdef USE_SIDEBAR + sb_draw(); +#endif for (i = menu->top; i < menu->top + menu->pagelen; i++) { if (i < menu->max) @@ -247,7 +253,7 @@ menu_pad_string (buf, sizeof (buf)); ATTRSET(attr); - move(i - menu->top + menu->offset, 0); + move(i - menu->top + menu->offset, SidebarWidth); do_color = 1; if (i == menu->current) @@ -270,7 +276,11 @@ else { NORMAL_COLOR; +#ifdef USE_SIDEBAR + CLEARLINE_WIN(i - menu->top + menu->offset); +#else CLEARLINE(i - menu->top + menu->offset); +#endif } } NORMAL_COLOR; @@ -287,7 +297,7 @@ return; } - move (menu->oldcurrent + menu->offset - menu->top, 0); + move (menu->oldcurrent + menu->offset - menu->top, SidebarWidth); ATTRSET(menu->color (menu->oldcurrent)); if (option (OPTARROWCURSOR)) @@ -299,13 +309,13 @@ { menu_make_entry (buf, sizeof (buf), menu, menu->oldcurrent); menu_pad_string (buf, sizeof (buf)); - move (menu->oldcurrent + menu->offset - menu->top, 3); + move (menu->oldcurrent + menu->offset - menu->top, SidebarWidth + 3); print_enriched_string (menu->color(menu->oldcurrent), (unsigned char *) buf, 1); } /* now draw it in the new location */ SETCOLOR(MT_COLOR_INDICATOR); - mvaddstr(menu->current + menu->offset - menu->top, 0, "->"); + mvaddstr(menu->current + menu->offset - menu->top, SidebarWidth, "->"); } else { @@ -318,7 +328,7 @@ menu_make_entry (buf, sizeof (buf), menu, menu->current); menu_pad_string (buf, sizeof (buf)); SETCOLOR(MT_COLOR_INDICATOR); - move(menu->current - menu->top + menu->offset, 0); + move(menu->current - menu->top + menu->offset, SidebarWidth); print_enriched_string (menu->color(menu->current), (unsigned char *) buf, 0); } menu->redraw &= REDRAW_STATUS; @@ -330,7 +340,7 @@ char buf[LONG_STRING]; int attr = menu->color (menu->current); - move (menu->current + menu->offset - menu->top, 0); + move (menu->current + menu->offset - menu->top, SidebarWidth); menu_make_entry (buf, sizeof (buf), menu, menu->current); menu_pad_string (buf, sizeof (buf)); @@ -873,7 +883,7 @@ if (option (OPTARROWCURSOR)) - move (menu->current - menu->top + menu->offset, 2); + move (menu->current - menu->top + menu->offset, SidebarWidth + 2); else if (option (OPTBRAILLEFRIENDLY)) move (menu->current - menu->top + menu->offset, 0); else diff -urN mutt-1.6.1/mh.c mutt-1.6.1-sidebar/mh.c --- mutt-1.6.1/mh.c 2016-05-02 03:02:12.409171576 +0100 +++ mutt-1.6.1-sidebar/mh.c 2016-05-02 03:02:15.019213102 +0100 @@ -295,6 +295,49 @@ mhs_free_sequences (&mhs); } +#ifdef USE_SIDEBAR +/** + * mh_buffy_update - Update messages counts for an mh mailbox + * @mailbox: BUFFY representing a maildir mailbox + * + * Read through an mh mailbox and count messages. Save the number of new, + * flagged messages and a timestamp for now. + */ +void +mh_buffy_update (BUFFY *mailbox) +{ + if (!mailbox) + return; + + if (!option (OPTSIDEBAR)) + return; + + struct mh_sequences mhs; + memset (&mhs, 0, sizeof (mhs)); + + if (mh_read_sequences (&mhs, mailbox->path) < 0) + return; + + mailbox->msg_count = 0; + mailbox->msg_unread = 0; + mailbox->msg_flagged = 0; + + int i; + for (i = 0; i <= mhs.max; i++) { + mailbox->msg_count++; + } + if (mhs_check (&mhs, i) & MH_SEQ_UNSEEN) { + mailbox->msg_unread++; + } + if (mhs_check (&mhs, i) & MH_SEQ_FLAGGED) { + mailbox->msg_flagged++; + } + mhs_free_sequences (&mhs); + mailbox->sb_last_checked = time (NULL); +} + +#endif + static int mh_mkstemp (CONTEXT * dest, FILE ** fp, char **tgt) { int fd; diff -urN mutt-1.6.1/mutt_curses.h mutt-1.6.1-sidebar/mutt_curses.h --- mutt-1.6.1/mutt_curses.h 2016-05-02 03:02:12.409171576 +0100 +++ mutt-1.6.1-sidebar/mutt_curses.h 2016-05-02 03:02:15.019213102 +0100 @@ -64,6 +64,9 @@ #undef lines #endif /* lines */ +#ifdef USE_SIDEBAR +#define CLEARLINE_WIN(x) move (x,SidebarWidth), clrtoeol() +#endif #define CLEARLINE(x) move(x,0), clrtoeol() #define CENTERLINE(x,y) move(y, (COLS-strlen(x))/2), addstr(x) #define BEEP() do { if (option (OPTBEEP)) beep(); } while (0) @@ -124,6 +127,14 @@ MT_COLOR_UNDERLINE, MT_COLOR_INDEX, MT_COLOR_PROMPT, +#ifdef USE_SIDEBAR + MT_COLOR_DIVIDER, + MT_COLOR_FLAGGED, + MT_COLOR_HIGHLIGHT, + MT_COLOR_NEW, + MT_COLOR_SB_INDICATOR, + MT_COLOR_SB_SPOOLFILE, +#endif MT_COLOR_MAX }; diff -urN mutt-1.6.1/mutt.h mutt-1.6.1-sidebar/mutt.h --- mutt-1.6.1/mutt.h 2016-05-02 03:02:12.409171576 +0100 +++ mutt-1.6.1-sidebar/mutt.h 2016-05-02 03:02:15.019213102 +0100 @@ -428,6 +428,13 @@ OPTSAVEEMPTY, OPTSAVENAME, OPTSCORE, +#ifdef USE_SIDEBAR + OPTSIDEBAR, + OPTSIDEBARFOLDERINDENT, + OPTSIDEBARNEWMAILONLY, + OPTSIDEBARNEXTNEWWRAP, + OPTSIDEBARSHORTPATH, +#endif OPTSIGDASHES, OPTSIGONTOP, OPTSORTRE, @@ -872,6 +879,9 @@ { char *path; FILE *fp; +#ifdef USE_SIDEBAR + time_t atime; +#endif time_t mtime; off_t size; off_t vsize; @@ -906,6 +916,9 @@ unsigned int quiet : 1; /* inhibit status messages? */ unsigned int collapsed : 1; /* are all threads collapsed? */ unsigned int closing : 1; /* mailbox is being closed */ +#ifdef USE_SIDEBAR + unsigned int peekonly : 1; /* just taking a glance, revert atime */ +#endif /* driver hooks */ void *data; /* driver specific data */ diff -urN mutt-1.6.1/muttlib.c mutt-1.6.1-sidebar/muttlib.c --- mutt-1.6.1/muttlib.c 2016-05-02 03:02:12.410171592 +0100 +++ mutt-1.6.1-sidebar/muttlib.c 2016-05-02 03:02:15.020213118 +0100 @@ -1282,7 +1282,7 @@ pl = pw = 1; /* see if there's room to add content, else ignore */ - if ((col < COLS && wlen < destlen) || soft) + if ((col < (COLS - SidebarWidth) && (wlen < destlen)) || soft) { int pad; @@ -1293,7 +1293,7 @@ /* try to consume as many columns as we can, if we don't have * memory for that, use as much memory as possible */ - pad = (COLS - col - wid) / pw; + pad = (COLS - SidebarWidth - col - wid) / pw; if (pad > 0 && wlen + (pad * pl) + len > destlen) pad = ((signed)(destlen - wlen - len)) / pl; if (pad > 0) @@ -1312,13 +1312,13 @@ /* \0-terminate dest for length computation in mutt_wstr_trunc() */ *wptr = 0; /* make sure right part is at most as wide as display */ - len = mutt_wstr_trunc (buf, destlen, COLS-offset, &wid); + len = mutt_wstr_trunc (buf, destlen, COLS - offset - SidebarWidth, &wid); /* truncate left so that right part fits completely in */ wlen = mutt_wstr_trunc (dest, destlen - len, col + pad*pw -offset, &col); wptr = dest + wlen; } if (len + wlen > destlen) - len = mutt_wstr_trunc (buf, destlen - wlen, COLS - col, NULL); + len = mutt_wstr_trunc (buf, destlen - wlen, COLS - SidebarWidth - col, NULL); memcpy (wptr, buf, len); wptr += len; wlen += len; diff -urN mutt-1.6.1/mutt_menu.h mutt-1.6.1-sidebar/mutt_menu.h --- mutt-1.6.1/mutt_menu.h 2016-05-02 03:02:12.409171576 +0100 +++ mutt-1.6.1-sidebar/mutt_menu.h 2016-05-02 03:02:15.019213102 +0100 @@ -34,6 +34,9 @@ #define REDRAW_FULL (1<<5) #define REDRAW_BODY (1<<6) #define REDRAW_SIGWINCH (1<<7) +#ifdef USE_SIDEBAR +#define REDRAW_SIDEBAR (1<<8) +#endif #define M_MODEFMT "-- Mutt: %s" diff -urN mutt-1.6.1/mx.c mutt-1.6.1-sidebar/mx.c --- mutt-1.6.1/mx.c 2016-05-02 03:02:12.410171592 +0100 +++ mutt-1.6.1-sidebar/mx.c 2016-05-02 03:02:15.020213118 +0100 @@ -29,6 +29,9 @@ #include "copy.h" #include "keymap.h" #include "url.h" +#ifdef USE_SIDEBAR +#include "sidebar.h" +#endif #ifdef USE_IMAP #include "imap.h" @@ -580,6 +583,7 @@ * M_APPEND open mailbox for appending * M_READONLY open mailbox in read-only mode * M_QUIET only print error messages + * M_PEEK revert atime where applicable * ctx if non-null, context struct to use */ CONTEXT *mx_open_mailbox (const char *path, int flags, CONTEXT *pctx) @@ -602,6 +606,10 @@ ctx->quiet = 1; if (flags & M_READONLY) ctx->readonly = 1; +#ifdef USE_SIDEBAR + if (flags & M_PEEK) + ctx->peekonly = 1; +#endif if (flags & (M_APPEND|M_NEWFOLDER)) { @@ -705,8 +713,21 @@ if(!ctx) return; +#ifdef USE_SIDEBAR + /* fix up the times so buffy won't get confused */ + struct utimbuf ut; + if (ctx->peekonly && ctx->path && (ctx->mtime > ctx->atime)) { + ut.actime = ctx->atime; + ut.modtime = ctx->mtime; + utime (ctx->path, &ut); + } +#endif + /* never announce that a mailbox we've just left has new mail. #3290 * XXX: really belongs in mx_close_mailbox, but this is a nice hook point */ +#ifdef USE_SIDEBAR + if (!ctx->peekonly) +#endif mutt_buffy_setnotified(ctx->path); if (ctx->mx_close) @@ -719,6 +740,10 @@ mutt_clear_threads (ctx); for (i = 0; i < ctx->msgcount; i++) mutt_free_header (&ctx->hdrs[i]); +#ifdef USE_SIDEBAR + ctx->msgcount -= ctx->deleted; + sb_set_buffystats (ctx); +#endif FREE (&ctx->hdrs); FREE (&ctx->v2r); FREE (&ctx->path); @@ -812,6 +837,12 @@ if (!ctx->hdrs[i]->deleted && ctx->hdrs[i]->read && !(ctx->hdrs[i]->flagged && option (OPTKEEPFLAGGED))) read_msgs++; +#ifdef USE_SIDEBAR + if (ctx->hdrs[i]->deleted && !ctx->hdrs[i]->read) + ctx->unread--; + if (ctx->hdrs[i]->deleted && ctx->hdrs[i]->flagged) + ctx->flagged--; +#endif } if (read_msgs && quadoption (OPT_MOVE) != M_NO) diff -urN mutt-1.6.1/mx.h mutt-1.6.1-sidebar/mx.h --- mutt-1.6.1/mx.h 2016-05-02 03:02:12.410171592 +0100 +++ mutt-1.6.1-sidebar/mx.h 2016-05-02 03:02:15.020213118 +0100 @@ -26,6 +26,7 @@ #define _MX_H #include "mailbox.h" +#include "buffy.h" /* supported mailbox formats */ enum @@ -57,6 +58,9 @@ int mh_read_dir (CONTEXT *, const char *); int mh_sync_mailbox (CONTEXT *, int *); int mh_check_mailbox (CONTEXT *, int *); +#ifdef USE_SIDEBAR +void mh_buffy_update (BUFFY *mailbox); +#endif int mh_check_empty (const char *); int maildir_read_dir (CONTEXT *); diff -urN mutt-1.6.1/OPS.SIDEBAR mutt-1.6.1-sidebar/OPS.SIDEBAR --- mutt-1.6.1/OPS.SIDEBAR 1970-01-01 01:00:00.000000000 +0100 +++ mutt-1.6.1-sidebar/OPS.SIDEBAR 2016-05-02 03:02:15.005212879 +0100 @@ -0,0 +1,8 @@ +OP_SIDEBAR_NEXT "Move the highlight to next mailbox" +OP_SIDEBAR_NEXT_NEW "Move the highlight to next mailbox with new mail" +OP_SIDEBAR_OPEN "Open highlighted mailbox" +OP_SIDEBAR_PAGE_DOWN "Scroll the Sidebar down 1 page" +OP_SIDEBAR_PAGE_UP "Scroll the Sidebar up 1 page" +OP_SIDEBAR_PREV "Move the highlight to previous mailbox" +OP_SIDEBAR_PREV_NEW "Move the highlight to previous mailbox with new mail" +OP_SIDEBAR_TOGGLE_VISIBLE "Make the Sidebar (in)visible" diff -urN mutt-1.6.1/pager.c mutt-1.6.1-sidebar/pager.c --- mutt-1.6.1/pager.c 2016-05-02 03:02:12.411171608 +0100 +++ mutt-1.6.1-sidebar/pager.c 2016-05-02 03:02:15.021213134 +0100 @@ -29,6 +29,9 @@ #include "pager.h" #include "attach.h" #include "mbyte.h" +#ifdef USE_SIDEBAR +#include "sidebar.h" +#endif #include "mutt_crypt.h" @@ -1096,6 +1099,9 @@ wchar_t wc; mbstate_t mbstate; int wrap_cols = mutt_term_width ((flags & M_PAGER_NOWRAP) ? 0 : Wrap); +#ifdef USE_SIDEBAR + wrap_cols -= SidebarWidth; +#endif if (check_attachment_marker ((char *)buf) == 0) wrap_cols = COLS; @@ -1491,7 +1497,7 @@ * a newline (grr!). */ #ifndef USE_SLANG_CURSES - if (col < COLS) + if (col < (COLS - SidebarWidth)) #endif addch ('\n'); @@ -1573,6 +1579,7 @@ int bodyoffset = 1; /* offset of first line of real text */ int statusoffset = 0; /* offset for the status bar */ + int statuswidth = COLS; int helpoffset = LINES - 2; /* offset for the help bar. */ int bodylen = LINES - 2 - bodyoffset; /* length of displayable area */ @@ -1747,7 +1754,7 @@ if ((redraw & REDRAW_BODY) || topline != oldtopline) { do { - move (bodyoffset, 0); + move (bodyoffset, SidebarWidth); curline = oldtopline = topline; lines = 0; force_redraw = 0; @@ -1760,6 +1767,9 @@ &QuoteList, &q_level, &force_redraw, &SearchRE) > 0) lines++; curline++; +#ifdef USE_SIDEBAR + move (lines + bodyoffset, SidebarWidth); +#endif } last_offset = lineInfo[curline].offset; } while (force_redraw); @@ -1772,6 +1782,9 @@ addch ('~'); addch ('\n'); lines++; +#ifdef USE_SIDEBAR + move (lines + bodyoffset, SidebarWidth); +#endif } NORMAL_COLOR; @@ -1789,29 +1802,49 @@ hfi.ctx = Context; hfi.pager_progress = pager_progress_str; +#ifdef USE_SIDEBAR + statuswidth = COLS; + if (option (OPTSTATUSONTOP) && (PagerIndexLines > 0)) + statuswidth -= SidebarWidth; +#endif + if (last_pos < sb.st_size - 1) snprintf(pager_progress_str, sizeof(pager_progress_str), OFF_T_FMT "%%", (100 * last_offset / sb.st_size)); else strfcpy(pager_progress_str, (topline == 0) ? "all" : "end", sizeof(pager_progress_str)); /* print out the pager status bar */ - move (statusoffset, 0); + move (statusoffset, SidebarWidth); SETCOLOR (MT_COLOR_STATUS); +#ifdef USE_SIDEBAR + short sw = SidebarWidth; + if (option (OPTSTATUSONTOP) && PagerIndexLines > 0) { + CLEARLINE_WIN (statusoffset); + } else { + CLEARLINE (statusoffset); + /* Temporarily lie about the sidebar width */ + SidebarWidth = 0; + } +#endif if (IsHeader (extra) || IsMsgAttach (extra)) { - size_t l1 = COLS * MB_LEN_MAX; + size_t l1 = statuswidth * MB_LEN_MAX; size_t l2 = sizeof (buffer); hfi.hdr = (IsHeader (extra)) ? extra->hdr : extra->bdy->hdr; mutt_make_string_info (buffer, l1 < l2 ? l1 : l2, NONULL (PagerFmt), &hfi, M_FORMAT_MAKEPRINT); - mutt_paddstr (COLS, buffer); + mutt_paddstr (statuswidth, buffer); } else { char bn[STRING]; snprintf (bn, sizeof (bn), "%s (%s)", banner, pager_progress_str); - mutt_paddstr (COLS, bn); + mutt_paddstr (statuswidth, bn); } +#ifdef USE_SIDEBAR + if (!option (OPTSTATUSONTOP) || PagerIndexLines == 0) + SidebarWidth = sw; /* Restore the sidebar width */ +#endif NORMAL_COLOR; if (option(OPTTSENABLED) && TSSupported) { @@ -1827,16 +1860,26 @@ /* redraw the pager_index indicator, because the * flags for this message might have changed. */ menu_redraw_current (index); +#ifdef USE_SIDEBAR + sb_draw(); +#endif /* print out the index status bar */ menu_status_line (buffer, sizeof (buffer), index, NONULL(Status)); - move (indexoffset + (option (OPTSTATUSONTOP) ? 0 : (indexlen - 1)), 0); + move (indexoffset + (option (OPTSTATUSONTOP) ? 0 : (indexlen - 1)), + (option(OPTSTATUSONTOP) ? 0: SidebarWidth)); SETCOLOR (MT_COLOR_STATUS); - mutt_paddstr (COLS, buffer); + mutt_paddstr (COLS - (option(OPTSTATUSONTOP) ? 0 : SidebarWidth), buffer); NORMAL_COLOR; } +#ifdef USE_SIDEBAR + /* if we're not using the index, update every time */ + if (index == 0) + sb_draw(); +#endif + redraw = 0; if (option(OPTBRAILLEFRIENDLY)) { @@ -2498,8 +2541,12 @@ ch = 0; } - if (option (OPTFORCEREDRAWPAGER)) + if (option (OPTFORCEREDRAWPAGER)) { redraw = REDRAW_FULL; +#ifdef USE_SIDEBAR + sb_draw(); +#endif + } unset_option (OPTFORCEREDRAWINDEX); unset_option (OPTFORCEREDRAWPAGER); break; @@ -2777,6 +2824,22 @@ mutt_what_key (); break; +#ifdef USE_SIDEBAR + case OP_SIDEBAR_NEXT: + case OP_SIDEBAR_NEXT_NEW: + case OP_SIDEBAR_PAGE_DOWN: + case OP_SIDEBAR_PAGE_UP: + case OP_SIDEBAR_PREV: + case OP_SIDEBAR_PREV_NEW: + sb_change_mailbox (ch); + break; + + case OP_SIDEBAR_TOGGLE_VISIBLE: + toggle_option (OPTSIDEBAR); + redraw = REDRAW_FULL; + break; +#endif + default: ch = -1; break; diff -urN mutt-1.6.1/PATCHES mutt-1.6.1-sidebar/PATCHES --- mutt-1.6.1/PATCHES 2016-05-02 03:02:12.396171369 +0100 +++ mutt-1.6.1-sidebar/PATCHES 2016-05-02 03:02:15.008212927 +0100 @@ -0,0 +1 @@ +patch-sidebar-neo-20160502 diff -urN mutt-1.6.1/README.sidebar mutt-1.6.1-sidebar/README.sidebar --- mutt-1.6.1/README.sidebar 1970-01-01 01:00:00.000000000 +0100 +++ mutt-1.6.1-sidebar/README.sidebar 2016-05-02 03:02:15.008212927 +0100 @@ -0,0 +1,145 @@ +Sidebar Patch +============= + + Overview of mailboxes + + NOTES: + + If you haven't used the sidebar before, you might like to read the + Sidebar Introduction: + + http://www.neomutt.org/sidebar-intro.html + + If you have used an older version of the Sidebar, please note that some + of the configuration has changed. + + http://www.neomutt.org/sidebar-intro.html#intro-sidebar-config-changes + +Patch +----- + + To check if Mutt supports "Sidebar", look for "+USE_SIDEBAR" in the mutt + version. + + Dependencies + * mutt-1.5.24 + +Introduction +------------ + + The Sidebar shows a list of all your mailboxes. The list can be turned on + and off, it can be themed and the list style can be configured. + + This part of the manual is a reference guide. If you want a simple + introduction with examples see the Sidebar Howto. If you just want to get + started, you could use the sample Sidebar muttrc. + + This version of Sidebar is based on Terry Chan's [2015-11-11 + release](http://www.lunar-linux.org/mutt-sidebar/). It contains many new + features, lots of bugfixes. + +Variables +--------- + + Sidebar Variables + + | Name | Type | Default | + |-------------------------|---------|-----------------------------| + | 'sidebar_delim_chars' | string | '/.' | + | 'sidebar_divider_char' | string | '|' | + | 'sidebar_folder_indent' | boolean | 'no' | + | 'sidebar_format' | string | '%B%?F? [%F]?%* %?N?%N/?%S' | + | 'sidebar_indent_string' | string | '  ' (two spaces) | + | 'sidebar_new_mail_only' | boolean | 'no' | + | 'sidebar_next_new_wrap' | boolean | 'no' | + | 'sidebar_refresh_time' | number | '60' | + | 'sidebar_short_path' | boolean | 'no' | + | 'sidebar_sort_method' | enum | 'SORT_ORDER' | + | 'sidebar_visible' | boolean | 'no' | + | 'sidebar_whitelist' | list | (empty) | + | 'sidebar_width' | number | '20' | + +Functions +--------- + + Sidebar Functions + + Sidebar adds the following functions to Mutt. By default, none of them are + bound to keys. + + | Menus | Function | Description | + |-------------|----------------------------|------------------------------------------------------| + | index,pager | '' | Move the highlight to next mailbox | + | index,pager | '' | Move the highlight to next mailbox with new mail | + | index,pager | '' | Open highlighted mailbox | + | index,pager | '' | Scroll the Sidebar down 1 page | + | index,pager | '' | Scroll the Sidebar up 1 page | + | index,pager | '' | Move the highlight to previous mailbox | + | index,pager | '' | Move the highlight to previous mailbox with new mail | + | index,pager | '' | Make the Sidebar (in)visible | + +Commands +-------- + + sidebar_whitelist mailbox [ mailbox... ] + +Colors +------ + + Sidebar Colors + + | Name | Default Color | Description | + |---------------------|------------------|------------------------------------------------------------------| + | 'sidebar_divider' | default | The dividing line between the Sidebar and the Index/Pager panels | + | 'sidebar_flagged' | default | Mailboxes containing flagged mail | + | 'sidebar_highlight' | underline | Cursor to select a mailbox | + | 'sidebar_indicator' | mutt 'indicator' | The mailbox open in the Index panel | + | 'sidebar_new' | default | Mailboxes containing new mail | + | 'sidebar_spoolfile' | default | Mailbox that receives incoming mail | + + If the sidebar_indicator color isn't set, then the default Mutt indicator + color will be used (the color used in the index panel). + +Sort +---- + + Sidebar Sort + + | Sort | Description | + |------------|----------------------------| + | 'alpha' | Alphabetically by path | + | 'count' | Total number of messages | + | 'flagged' | Number of flagged messages | + | 'name' | Alphabetically by path | + | 'new' | Number of new messages | + | 'path' | Alphabetically by path | + | 'unsorted' | Do not resort the paths | + +See Also +-------- + + * Regular Expressions + * Patterns + * Color command + * notmuch patch + +Known Bugs +---------- + + Unsorted isn't + +Credits +------- + + * Justin Hibbits + * Thomer M. Gil + * David Sterba + * Evgeni Golov + * Fabian Groffen + * Jason DeTiberus + * Stefan Assmann + * Steve Kemp + * Terry Chan + * Tyler Earnest + * Richard Russon + diff -urN mutt-1.6.1/sidebar.c mutt-1.6.1-sidebar/sidebar.c --- mutt-1.6.1/sidebar.c 1970-01-01 01:00:00.000000000 +0100 +++ mutt-1.6.1-sidebar/sidebar.c 2016-05-02 03:02:15.023213165 +0100 @@ -0,0 +1,1069 @@ +/* Copyright (C) 2004 Justin Hibbits + * Copyright (C) 2004 Thomer M. Gil + * Copyright (C) 2015-2016 Richard Russon + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "mutt.h" +#include "buffy.h" +#include "keymap.h" +#include "mutt_curses.h" +#include "mutt_menu.h" +#include "sort.h" + +/* Previous values for some sidebar config */ +static short OldVisible; /* sidebar_visible */ +static short OldWidth; /* sidebar_width */ +static short PreviousSort; /* sidebar_sort_method */ +static time_t LastRefresh; /* Time of last refresh */ + +/* Keep track of various BUFFYs */ +static BUFFY *TopBuffy; /* First mailbox visible in sidebar */ +static BUFFY *OpnBuffy; /* Current (open) mailbox */ +static BUFFY *HilBuffy; /* Highlighted mailbox */ +static BUFFY *BotBuffy; /* Last mailbox visible in sidebar */ +static BUFFY *Outgoing; /* Last mailbox in the linked list */ + +/** + * struct sidebar_entry - Info about folders in the sidebar + * + * Used in the mutt_FormatString callback + */ +struct sidebar_entry { + char box[SHORT_STRING]; + BUFFY *buffy; +}; + + +/** + * find_next_new - Find the next folder that contains new mail + * @wrap: Wrap around to the beginning if the end is reached + * + * Search down the list of mail folders for one containing new mail. + * + * Returns: + * BUFFY*: Success + * NULL: Failure + */ +static BUFFY * +find_next_new (int wrap) +{ + BUFFY *b = HilBuffy; + if (!b) + return NULL; + + do { + b = b->next; + if (!b && wrap) { + b = Incoming; + } + if (!b || (b == HilBuffy)) { + break; + } + if (b->msg_unread > 0) { + return b; + } + } while (b); + + return NULL; +} + +/** + * find_prev_new - Find the previous folder that contains new mail + * @wrap: Wrap around to the beginning if the end is reached + * + * Search up the list of mail folders for one containing new mail. + * + * Returns: + * BUFFY*: Success + * NULL: Failure + */ +static BUFFY * +find_prev_new (int wrap) +{ + BUFFY *b = HilBuffy; + if (!b) + return NULL; + + do { + b = b->prev; + if (!b && wrap) { + b = Outgoing; + } + if (!b || (b == HilBuffy)) { + break; + } + if (b->msg_unread > 0) { + return b; + } + } while (b); + + return NULL; +} + +/** + * cb_format_str - Create the string to show in the sidebar + * @dest: Buffer in which to save string + * @destlen: Buffer length + * @col: Starting column, UNUSED + * @op: printf-like operator, e.g. 'B' + * @src: printf-like format string + * @prefix: Field formatting string, UNUSED + * @ifstring: If condition is met, display this string + * @elsestring: Otherwise, display this string + * @data: Pointer to our sidebar_entry + * @flags: Format flags, e.g. M_FORMAT_OPTIONAL + * + * cb_format_str is a callback function for mutt_FormatString. It understands + * five operators. '%B' : Mailbox name, '%F' : Number of flagged messages, + * '%N' : Number of new messages, '%S' : Size (total number of messages), + * '%!' : Icon denoting number of flagged messages. + * + * Returns: src (unchanged) + */ +static const char * +cb_format_str (char *dest, size_t destlen, size_t col, char op, const char *src, + const char *prefix, const char *ifstring, const char *elsestring, + unsigned long data, format_flag flags) +{ + struct sidebar_entry *sbe = (struct sidebar_entry *) data; + unsigned int optional; + char fmt[SHORT_STRING], buf[SHORT_STRING]; + + if (!sbe || !dest) + return src; + + dest[0] = 0; /* Just in case there's nothing to do */ + + BUFFY *b = sbe->buffy; + if (!b) + return src; + + int c = Context && (mutt_strcmp (Context->path, b->path) == 0); + + optional = flags & M_FORMAT_OPTIONAL; + + switch (op) { + case 'B': + mutt_format_s (dest, destlen, prefix, sbe->box); + break; + + case 'd': + if (!optional) { + snprintf (fmt, sizeof (fmt), "%%%sd", prefix); + snprintf (dest, destlen, fmt, c ? Context->deleted : 0); + } else if ((c && Context->deleted == 0) || !c) { + optional = 0; + } + break; + + case 'F': + if (!optional) { + snprintf (fmt, sizeof (fmt), "%%%sd", prefix); + snprintf (dest, destlen, fmt, b->msg_flagged); + } else if (b->msg_flagged == 0) { + optional = 0; + } + break; + + case 'L': + if (!optional) { + snprintf (fmt, sizeof (fmt), "%%%sd", prefix); + snprintf (dest, destlen, fmt, c ? Context->vcount : b->msg_count); + } else if ((c && Context->vcount == b->msg_count) || !c) { + optional = 0; + } + break; + + case 'N': + if (!optional) { + snprintf (fmt, sizeof (fmt), "%%%sd", prefix); + snprintf (dest, destlen, fmt, b->msg_unread); + } else if (b->msg_unread == 0) { + optional = 0; + } + break; + + case 'S': + if (!optional) { + snprintf (fmt, sizeof (fmt), "%%%sd", prefix); + snprintf (dest, destlen, fmt, b->msg_count); + } else if (b->msg_count == 0) { + optional = 0; + } + break; + + case 't': + if (!optional) { + snprintf (fmt, sizeof (fmt), "%%%sd", prefix); + snprintf (dest, destlen, fmt, c ? Context->tagged : 0); + } else if ((c && Context->tagged == 0) || !c) { + optional = 0; + } + break; + + case '!': + if (b->msg_flagged == 0) { + mutt_format_s (dest, destlen, prefix, ""); + } else if (b->msg_flagged == 1) { + mutt_format_s (dest, destlen, prefix, "!"); + } else if (b->msg_flagged == 2) { + mutt_format_s (dest, destlen, prefix, "!!"); + } else { + snprintf (buf, sizeof (buf), "%d!", b->msg_flagged); + mutt_format_s (dest, destlen, prefix, buf); + } + break; + } + + if (optional) + mutt_FormatString (dest, destlen, col, ifstring, cb_format_str, (unsigned long) sbe, flags); + else if (flags & M_FORMAT_OPTIONAL) + mutt_FormatString (dest, destlen, col, elsestring, cb_format_str, (unsigned long) sbe, flags); + + /* We return the format string, unchanged */ + return src; +} + +/** + * make_sidebar_entry - Turn mailbox data into a sidebar string + * @buf: Buffer in which to save string + * @buflen: Buffer length + * @width: Desired width in screen cells + * @box: Mailbox name + * @size: Size (total number of messages) + * @new: Number of new messages + * @flagged: Number of flagged messages + * + * Take all the relevant mailbox data and the desired screen width and then get + * mutt_FormatString to do the actual work. mutt_FormatString will callback to + * us using cb_format_str() for the sidebar specific formatting characters. + */ +static void +make_sidebar_entry (char *buf, unsigned int buflen, int width, char *box, + BUFFY *b) +{ + struct sidebar_entry sbe; + + if (!buf || !box || !b) + return; + + sbe.buffy = b; + strncpy (sbe.box, box, sizeof (sbe.box) - 1); + + int box_len = strlen (box); + sbe.box[box_len] = '\0'; + + /* Temporarily lie about the screen width */ + int oc = COLS; + COLS = width + SidebarWidth; + mutt_FormatString (buf, buflen, 0, NONULL(SidebarFormat), cb_format_str, (unsigned long) &sbe, 0); + COLS = oc; + + /* Force string to be exactly the right width */ + int w = mutt_strwidth (buf); + int s = strlen (buf); + if (w < width) { + /* Pad with spaces */ + memset (buf + s, ' ', width - w); + buf[s + width - w] = 0; + } else if (w > width) { + /* Truncate to fit */ + int len = mutt_wstr_trunc (buf, buflen, width, NULL); + buf[len] = 0; + } +} + +/** + * cb_qsort_buffy - qsort callback to sort BUFFYs + * @a: First BUFFY to compare + * @b: Second BUFFY to compare + * + * Compare the paths of two BUFFYs taking the locale into account. + * + * Returns: + * -1: a precedes b + * 0: a and b are identical + * 1: b precedes a + */ +static int +cb_qsort_buffy (const void *a, const void *b) +{ + const BUFFY *b1 = *(const BUFFY **) a; + const BUFFY *b2 = *(const BUFFY **) b; + + /* Special case -- move hidden BUFFYs to the end */ + if (b1->is_hidden != b2->is_hidden) { + if (b1->is_hidden) + return 1; + else + return -1; + } + + int result = 0; + + switch ((SidebarSortMethod & SORT_MASK)) { + case SORT_COUNT: + result = (b2->msg_count - b1->msg_count); + break; + case SORT_COUNT_NEW: + result = (b2->msg_unread - b1->msg_unread); + break; + case SORT_FLAGGED: + result = (b2->msg_flagged - b1->msg_flagged); + break; + case SORT_PATH: + result = mutt_strcasecmp (b1->path, b2->path); + break; + } + + if (SidebarSortMethod & SORT_REVERSE) + result = -result; + + return result; +} + +/** + * buffy_going - Prevent our pointers becoming invalid + * @b: BUFFY about to be deleted + * + * If we receive a delete-notification for a BUFFY, we need to change any + * pointers we have to reference a different BUFFY, or set them to NULL. + * + * We don't update the prev/next pointers, they'll be fixed on the next + * call to prepare_sidebar(). + * + * Returns: + * A valid alternative BUFFY, or NULL + */ +static BUFFY * +buffy_going (const BUFFY *b) +{ + if (!b) + return NULL; + + if (b->prev) { + b->prev->next = NULL; + } + + if (b->next) { + b->next->prev = NULL; + return b->next; + } + + return b->prev; +} + +/** + * update_buffy_visibility - Should a BUFFY be displayed in the sidebar + * @arr: array of BUFFYs + * @arr_len: number of BUFFYs in array + * + * For each BUFFY in the array, check whether we should display it. + * This is determined by several criteria. If the BUFFY: + * is the currently open mailbox + * is the currently highlighted mailbox + * has unread messages + * has flagged messages + * is whitelisted + */ +static void +update_buffy_visibility (BUFFY **arr, int arr_len) +{ + if (!arr) + return; + + short new_only = option (OPTSIDEBARNEWMAILONLY); + + BUFFY *b; + int i; + for (i = 0; i < arr_len; i++) { + b = arr[i]; + + b->is_hidden = 0; + + if (!new_only) + continue; + + if ((b == OpnBuffy) || (b->msg_unread > 0) || + (b == HilBuffy) || (b->msg_flagged > 0)) { + continue; + } + + if (Context && (strcmp (b->path, Context->path) == 0)) { + /* Spool directory */ + continue; + } + + if (mutt_find_list (SidebarWhitelist, b->path)) { + /* Explicitly asked to be visible */ + continue; + } + + b->is_hidden = 1; + } +} + +/** + * sort_buffy_array - Sort an array of BUFFY pointers + * @arr: array of BUFFYs + * @arr_len: number of BUFFYs in array + * + * Sort an array of BUFFY pointers according to the current sort config + * option "sidebar_sort_method". This calls qsort to do the work which calls our + * callback function "cb_qsort_buffy". + * + * Once sorted, the prev/next links will be reconstructed. + */ +static void +sort_buffy_array (BUFFY **arr, int arr_len) +{ + if (!arr) + return; + + /* These are the only sort methods we understand */ + short ssm = (SidebarSortMethod & SORT_MASK); + if ((ssm == SORT_COUNT) || + (ssm == SORT_COUNT_NEW) || + (ssm == SORT_DESC) || + (ssm == SORT_FLAGGED) || + (ssm == SORT_PATH)) { + qsort (arr, arr_len, sizeof (*arr), cb_qsort_buffy); + } + + int i; + for (i = 0; i < (arr_len - 1); i++) { + arr[i]->next = arr[i + 1]; + } + arr[arr_len - 1]->next = NULL; + + for (i = 1; i < arr_len; i++) { + arr[i]->prev = arr[i - 1]; + } + arr[0]->prev = NULL; +} + +/** + * prepare_sidebar - Prepare the list of BUFFYs for the sidebar display + * @page_size: The number of lines on a page + * + * Before painting the sidebar, we count the BUFFYs, 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. + * + * Returns: + * 0: No, don't draw the sidebar + * 1: Yes, draw the sidebar + */ +static int +prepare_sidebar (int page_size) +{ + BUFFY *b = Incoming; + if (!b) + return 0; + + int count = 0; + for (; b; b = b->next) + count++; + + BUFFY **arr = safe_malloc (count * sizeof (*arr)); + if (!arr) + return 0; + + int i = 0; + for (b = Incoming; b; b = b->next, i++) { + arr[i] = b; + } + + update_buffy_visibility (arr, count); + sort_buffy_array (arr, count); + + Incoming = arr[0]; + + int top_index = 0; + int opn_index = -1; + int hil_index = -1; + int bot_index = -1; + + for (i = 0; i < count; i++) { + if (OpnBuffy == arr[i]) + opn_index = i; + if (HilBuffy == arr[i]) + hil_index = i; + } + + if (!HilBuffy || (SidebarSortMethod != PreviousSort)) { + if (OpnBuffy) { + HilBuffy = OpnBuffy; + hil_index = opn_index; + } else { + HilBuffy = arr[0]; + hil_index = 0; + } + } + if (TopBuffy) { + top_index = (hil_index / page_size) * page_size; + } else { + top_index = hil_index; + } + TopBuffy = arr[top_index]; + + bot_index = top_index + page_size - 1; + if (bot_index > (count - 1)) { + bot_index = count - 1; + } + BotBuffy = arr[bot_index]; + + Outgoing = arr[count - 1]; + + PreviousSort = SidebarSortMethod; + free (arr); + return 1; +} + +/** + * visible - Should we display the sidebar? + * + * After validating the config options "sidebar_visible" and "sidebar_width", + * determine whether we should should display the sidebar. + * + * When not visible, set the global SidebarWidth to 0. + * + * Returns: + * Boolean + */ +static short +visible (void) +{ + short new_visible = option (OPTSIDEBAR); + short new_width = SidebarWidth; + + if (OldWidth != new_width) { + if (new_width > 0) { + OldWidth = new_width; + } + } + + if (OldVisible != new_visible) { + if (new_visible) { + set_option (OPTSIDEBAR); + } else { + unset_option (OPTSIDEBAR); + } + OldVisible = new_visible; + } else if (new_width == 0) { + unset_option (OPTSIDEBAR); + OldVisible = 0; + } + + if (!option (OPTSIDEBAR)) { + SidebarWidth = 0; + } else if (new_width == 0) { + SidebarWidth = OldWidth; + } else { + SidebarWidth = new_width; + } + + return new_visible; +} + +/** + * draw_divider - Draw a line between the sidebar and the rest of mutt + * @first_row: Screen line to start (0-based) + * @num_rows: Number of rows to fill + * + * Draw a divider using characters from the config option "sidebar_divider_char". + * This can be an ASCII or Unicode character. First we calculate this + * characters' width in screen columns, then subtract that from the config + * option "sidebar_width". + * + * Returns: + * -1: Error: bad character, etc + * 0: Error: 0 width character + * n: Success: character occupies n screen columns + */ +static int +draw_divider (int first_row, int num_rows) +{ + /* Calculate the width of the delimiter in screen cells */ + int delim_len = mutt_strwidth (SidebarDividerChar); + + if (delim_len < 1) + return delim_len; + + if ((SidebarWidth + delim_len) > (COLS + 1)) + return 0; + + if (delim_len > SidebarWidth) + return -1; + + SETCOLOR(MT_COLOR_DIVIDER); + + int i; + for (i = 0; i < num_rows; i++) { + move (first_row + i, SidebarWidth - delim_len); + addstr (NONULL(SidebarDividerChar)); + } + + return delim_len; +} + +/** + * fill_empty_space - Wipe the remaining sidebar space + * @first_row: Screen line to start (0-based) + * @num_rows: Number of rows to fill + * @width: Width of the sidebar (minus the divider) + * + * Write spaces over the area the sidebar isn't using. + */ +static void +fill_empty_space (int first_row, int num_rows, int width) +{ + /* Fill the remaining rows with blank space */ + SETCOLOR(MT_COLOR_NORMAL); + + int r; + for (r = 0; r < num_rows; r++) { + int i = 0; + move (first_row + r, 0); + for (; i < width; i++) + addch (' '); + } +} + +/** + * draw_sidebar - Write out a list of mailboxes, on the left + * @first_row: Screen line to start (0-based) + * @num_rows: Number of rows to fill + * @div_width: Width in screen characters taken by the divider + * + * Display a list of mailboxes in a panel on the left. What's displayed will + * depend on our index markers: TopBuffy, OpnBuffy, HilBuffy, BotBuffy. + * On the first run they'll be NULL, so we display the top of Mutt's list + * (Incoming). + * + * TopBuffy - first visible mailbox + * BotBuffy - last visible mailbox + * OpnBuffy - mailbox shown in Mutt's Index Panel + * HilBuffy - Unselected mailbox (the paging follows this) + * + * The entries are formatted using "sidebar_format" and may be abbreviated: + * "sidebar_short_path", indented: "sidebar_folder_indent", + * "sidebar_indent_string" and sorted: "sidebar_sort_method". Finally, they're + * trimmed to fit the available space. + */ +static void +draw_sidebar (int first_row, int num_rows, int div_width) +{ + BUFFY *b = TopBuffy; + if (!b) + return; + + int w = MIN(COLS, (SidebarWidth - div_width)); + int row = 0; + for (b = TopBuffy; b && (row < num_rows); b = b->next) { + if (b->is_hidden) { + continue; + } + + if (b == OpnBuffy) { + if ((ColorDefs[MT_COLOR_SB_INDICATOR] != 0)) { + SETCOLOR(MT_COLOR_SB_INDICATOR); + } else { + SETCOLOR(MT_COLOR_INDICATOR); + } + } else if (b == HilBuffy) { + SETCOLOR(MT_COLOR_HIGHLIGHT); + } else if ((ColorDefs[MT_COLOR_SB_SPOOLFILE] != 0) && + (mutt_strcmp (b->path, Spoolfile) == 0)) { + SETCOLOR(MT_COLOR_SB_SPOOLFILE); + } else if (b->msg_unread > 0) { + SETCOLOR(MT_COLOR_NEW); + } else if (b->msg_flagged > 0) { + SETCOLOR(MT_COLOR_FLAGGED); + } else { + SETCOLOR(MT_COLOR_NORMAL); + } + + move (first_row + row, 0); + if (Context && Context->path && + (!strcmp (b->path, Context->path)|| + !strcmp (b->realpath, Context->path))) { + b->msg_unread = Context->unread; + b->msg_count = Context->msgcount; + b->msg_flagged = Context->flagged; + } + + /* compute length of Maildir without trailing separator */ + size_t maildirlen = strlen (Maildir); + if (SidebarDelimChars && strchr (SidebarDelimChars, Maildir[maildirlen - 1])) { + maildirlen--; + } + + /* check whether Maildir is a prefix of the current folder's path */ + short maildir_is_prefix = 0; + if ((strlen (b->path) > maildirlen) && (strncmp (Maildir, b->path, maildirlen) == 0)) { + maildir_is_prefix = 1; + } + /* calculate depth of current folder and generate its display name with indented spaces */ + int sidebar_folder_depth = 0; + char *sidebar_folder_name; + int i; + if (option (OPTSIDEBARSHORTPATH)) { + /* disregard a trailing separator, so strlen() - 2 */ + sidebar_folder_name = b->path; + for (i = strlen (sidebar_folder_name) - 2; i >= 0; i--) { + if (SidebarDelimChars && + strchr (SidebarDelimChars, sidebar_folder_name[i])) { + sidebar_folder_name += (i + 1); + break; + } + } + } else { + sidebar_folder_name = b->path + maildir_is_prefix * (maildirlen + 1); + } + if (maildir_is_prefix && option (OPTSIDEBARFOLDERINDENT)) { + const char *tmp_folder_name; + int lastsep = 0; + tmp_folder_name = b->path + maildirlen + 1; + int tmplen = (int) strlen (tmp_folder_name) - 1; + for (i = 0; i < tmplen; i++) { + if (SidebarDelimChars && strchr (SidebarDelimChars, tmp_folder_name[i])) { + sidebar_folder_depth++; + lastsep = i + 1; + } + } + if (sidebar_folder_depth > 0) { + if (option (OPTSIDEBARSHORTPATH)) { + tmp_folder_name += lastsep; /* basename */ + } + sidebar_folder_name = malloc (strlen (tmp_folder_name) + sidebar_folder_depth*strlen (NONULL(SidebarIndentString)) + 1); + sidebar_folder_name[0]=0; + for (i=0; i < sidebar_folder_depth; i++) + strncat (sidebar_folder_name, NONULL(SidebarIndentString), strlen (NONULL(SidebarIndentString))); + strncat (sidebar_folder_name, tmp_folder_name, strlen (tmp_folder_name)); + } + } + char str[SHORT_STRING]; + make_sidebar_entry (str, sizeof (str), w, sidebar_folder_name, b); + printw ("%s", str); + if (sidebar_folder_depth > 0) + free (sidebar_folder_name); + row++; + } + + fill_empty_space (first_row + row, num_rows - row, w); +} + + +/** + * sb_init - Set some default values for the sidebar. + */ +void +sb_init (void) +{ + OldVisible = option (OPTSIDEBAR); + if (SidebarWidth > 0) { + OldWidth = SidebarWidth; + } else { + OldWidth = 20; + if (OldVisible) { + SidebarWidth = OldWidth; + } + } +} + +/** + * sb_draw - Completely redraw the sidebar + * + * Completely refresh the sidebar region. First draw the divider; then, for + * each BUFFY, call make_sidebar_entry; finally blank out any remaining space. + */ +void +sb_draw (void) +{ + if (!visible()) + return; + + /* XXX - if transitioning from invisible to visible */ + /* if (OldVisible == 0) */ + /* mutt_buffy_check (1); we probably have bad or no numbers */ + + int first_row = 0; + int num_rows = LINES - 2; + + if (option (OPTHELP) || option (OPTSTATUSONTOP)) + first_row++; + + if (option (OPTHELP)) + num_rows--; + + int div_width = draw_divider (first_row, num_rows); + if (div_width < 0) + return; + + if (!Incoming) { + int w = MIN(COLS, (SidebarWidth - div_width)); + fill_empty_space (first_row, num_rows, w); + return; + } + + if (!prepare_sidebar (num_rows)) + return; + + draw_sidebar (first_row, num_rows, div_width); +} + +/** + * sb_should_refresh - Check if the sidebar is due to be refreshed + * + * The "sidebar_refresh_time" config option allows the user to limit the frequency + * with which the sidebar is refreshed. + * + * Returns: + * 1 Yes, refresh is due + * 0 No, refresh happened recently + */ +int +sb_should_refresh (void) +{ + if (!option (OPTSIDEBAR)) + return 0; + + if (SidebarRefreshTime == 0) + return 0; + + time_t diff = (time (NULL) - LastRefresh); + + return (diff >= SidebarRefreshTime); +} + +/** + * sb_change_mailbox - Change the selected mailbox + * @op: Operation code + * + * Change the selected mailbox, e.g. "Next mailbox", "Previous Mailbox + * with new mail". The operations are listed OPS.SIDEBAR which is built + * into an enum in keymap_defs.h. + * + * If the operation is successful, HilBuffy will be set to the new mailbox. + * This function only *selects* the mailbox, doesn't *open* it. + * + * Allowed values are: OP_SIDEBAR_NEXT, OP_SIDEBAR_NEXT_NEW, + * OP_SIDEBAR_PAGE_DOWN, OP_SIDEBAR_PAGE_UP, OP_SIDEBAR_PREV, + * OP_SIDEBAR_PREV_NEW. + */ +void +sb_change_mailbox (int op) +{ + BUFFY *b; + if (!HilBuffy) /* It'll get reset on the next draw */ + return; + + switch (op) { + case OP_SIDEBAR_NEXT: + if (!HilBuffy->next) + return; + if (HilBuffy->next->is_hidden) + return; + HilBuffy = HilBuffy->next; + break; + case OP_SIDEBAR_NEXT_NEW: + b = find_next_new (option (OPTSIDEBARNEXTNEWWRAP)); + if (!b) { + return; + } else { + HilBuffy = b; + } + break; + case OP_SIDEBAR_PAGE_DOWN: + HilBuffy = BotBuffy; + if (HilBuffy->next) { + HilBuffy = HilBuffy->next; + } + break; + case OP_SIDEBAR_PAGE_UP: + HilBuffy = TopBuffy; + if (HilBuffy != Incoming) { + HilBuffy = HilBuffy->prev; + } + break; + case OP_SIDEBAR_PREV: + if (!HilBuffy->prev) + return; + if (HilBuffy->prev->is_hidden) /* Can't happen, we've sorted the hidden to the end */ + return; + HilBuffy = HilBuffy->prev; + break; + case OP_SIDEBAR_PREV_NEW: + b = find_prev_new (option (OPTSIDEBARNEXTNEWWRAP)); + if (!b) { + return; + } else { + HilBuffy = b; + } + break; + default: + return; + } + + /* We can change folder even if the sidebar is hidden */ + if (option (OPTSIDEBAR)) + sb_draw(); +} + +/** + * sb_set_buffystats - Update the BUFFY's message counts from the CONTEXT + * @ctx: A mailbox CONTEXT + * + * Given a mailbox CONTEXT, find a matching mailbox BUFFY and copy the message + * counts into it. + */ +void +sb_set_buffystats (const CONTEXT *ctx) +{ + /* Even if the sidebar's hidden, + * we should take note of the new data. */ + BUFFY *b = Incoming; + if (!ctx || !b) + return; + + for (; b; b = b->next) { + if (!strcmp (b->path, ctx->path) || + !strcmp (b->realpath, ctx->path)) { + b->msg_unread = ctx->unread; + b->msg_count = ctx->msgcount; + b->msg_flagged = ctx->flagged; + break; + } + } +} + +/** + * sb_get_highlight - Get the BUFFY that's highlighted in the sidebar + * + * Get the path of the mailbox that's highlighted in the sidebar. + * + * Returns: + * Mailbox path + */ +const char * +sb_get_highlight (void) +{ + if (!HilBuffy) + return NULL; + + return HilBuffy->path; +} + +/** + * sb_set_open_buffy - Set the OpnBuffy based on a mailbox path + * @path: Mailbox path + * + * Search through the list of mailboxes. If a BUFFY has a matching path, set + * OpnBuffy to it. + */ +BUFFY * +sb_set_open_buffy (const char *path) +{ + /* Even if the sidebar is hidden */ + + BUFFY *b = Incoming; + + if (!path || !b) + return NULL; + + OpnBuffy = NULL; + + for (; b; b = b->next) { + if (!strcmp (b->path, path) || + !strcmp (b->realpath, path)) { + OpnBuffy = b; + HilBuffy = b; + break; + } + } + + return OpnBuffy; +} + +/** + * sb_set_update_time - Note the time that the sidebar was updated + * + * Update the timestamp representing the last sidebar update. If the user + * configures "sidebar_refresh_time", this will help to reduce traffic. + */ +void +sb_set_update_time (void) +{ + /* XXX - should this be public? */ + + LastRefresh = time (NULL); +} + +/** + * sb_notify_mailbox - The state of a BUFFY is about to change + * + * We receive a notification: + * After a new BUFFY has been created + * Before a BUFFY is deleted + * + * Before a deletion, check that our pointers won't be invalidated. + */ +void +sb_notify_mailbox (BUFFY *b, int created) +{ + if (!b) + return; + + /* Any new/deleted mailboxes will cause a refresh. As long as + * they're valid, our pointers will be updated in prepare_sidebar() */ + + if (created) { + if (!TopBuffy) + TopBuffy = b; + if (!HilBuffy) + HilBuffy = b; + if (!BotBuffy) + BotBuffy = b; + if (!Outgoing) + Outgoing = b; + if (!OpnBuffy && Context) { + /* This might happen if the user "unmailboxes *", then + * "mailboxes" our current mailbox back again */ + if (mutt_strcmp (b->path, Context->path) == 0) { + OpnBuffy = b; + } + } + } else { + if (TopBuffy == b) + TopBuffy = buffy_going (TopBuffy); + if (OpnBuffy == b) + OpnBuffy = buffy_going (OpnBuffy); + if (HilBuffy == b) + HilBuffy = buffy_going (HilBuffy); + if (BotBuffy == b) + BotBuffy = buffy_going (BotBuffy); + if (Outgoing == b) + Outgoing = buffy_going (Outgoing); + } +} diff -urN mutt-1.6.1/sidebar.h mutt-1.6.1-sidebar/sidebar.h --- mutt-1.6.1/sidebar.h 1970-01-01 01:00:00.000000000 +0100 +++ mutt-1.6.1-sidebar/sidebar.h 2016-05-02 03:02:15.023213165 +0100 @@ -0,0 +1,36 @@ +/* Copyright (C) 2004 Justin Hibbits + * Copyright (C) 2004 Thomer M. Gil + * Copyright (C) 2015-2016 Richard Russon + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + */ + +#ifndef SIDEBAR_H +#define SIDEBAR_H + +#include "mutt.h" +#include "buffy.h" + +void sb_change_mailbox (int op); +void sb_draw (void); +const char * sb_get_highlight (void); +void sb_init (void); +void sb_notify_mailbox (BUFFY *b, int created); +void sb_set_buffystats (const CONTEXT *ctx); +BUFFY * sb_set_open_buffy (const char *path); +void sb_set_update_time (void); +int sb_should_refresh (void); + +#endif /* SIDEBAR_H */ diff -urN mutt-1.6.1/sort.h mutt-1.6.1-sidebar/sort.h --- mutt-1.6.1/sort.h 2016-05-02 03:02:12.440172071 +0100 +++ mutt-1.6.1-sidebar/sort.h 2016-05-02 03:02:15.023213165 +0100 @@ -31,6 +31,12 @@ #define SORT_KEYID 12 #define SORT_TRUST 13 #define SORT_SPAM 14 +#define SORT_COUNT 15 +#define SORT_COUNT_NEW 16 +#define SORT_DESC 17 +#define SORT_FLAGGED 18 +#define SORT_PATH 19 + /* dgc: Sort & SortAux are shorts, so I'm bumping these bitflags up from * bits 4 & 5 to bits 8 & 9 to make room for more sort keys in the future. */ #define SORT_MASK 0xff @@ -50,6 +56,7 @@ WHERE short Sort INITVAL (SORT_DATE); WHERE short SortAux INITVAL (SORT_DATE); /* auxiliary sorting method */ WHERE short SortAlias INITVAL (SORT_ALIAS); +WHERE short SidebarSortMethod INITVAL (SORT_ORDER); /* FIXME: This one does not belong to here */ WHERE short PgpSortKeys INITVAL (SORT_ADDRESS);