From 8745e479091f21975d5777df9a8013d8e7d02cfd Mon Sep 17 00:00:00 2001 From: rnhmjoj Date: Sat, 9 Jul 2016 05:13:52 +0200 Subject: [PATCH] mutt: 1.6.0 -> 1.6.2 --- .../networking/mailreaders/mutt/default.nix | 86 +- .../mailreaders/mutt/sidebar-compose.patch | 40 - .../mutt/sidebar-delimnullwide.patch | 38 - .../mailreaders/mutt/sidebar-dotpathsep.patch | 98 - .../mailreaders/mutt/sidebar-new.patch | 97 - .../mailreaders/mutt/sidebar-newonly.patch | 198 - .../mailreaders/mutt/sidebar-utf8.patch | 132 - .../networking/mailreaders/mutt/sidebar.patch | 4657 ++++++++++++++--- .../mailreaders/mutt/trash-folder.patch | 316 -- .../networking/mailreaders/mutt/trash.patch | 797 +++ 10 files changed, 4652 insertions(+), 1807 deletions(-) delete mode 100644 pkgs/applications/networking/mailreaders/mutt/sidebar-compose.patch delete mode 100644 pkgs/applications/networking/mailreaders/mutt/sidebar-delimnullwide.patch delete mode 100644 pkgs/applications/networking/mailreaders/mutt/sidebar-dotpathsep.patch delete mode 100644 pkgs/applications/networking/mailreaders/mutt/sidebar-new.patch delete mode 100644 pkgs/applications/networking/mailreaders/mutt/sidebar-newonly.patch delete mode 100644 pkgs/applications/networking/mailreaders/mutt/sidebar-utf8.patch delete mode 100644 pkgs/applications/networking/mailreaders/mutt/trash-folder.patch create mode 100644 pkgs/applications/networking/mailreaders/mutt/trash.patch diff --git a/pkgs/applications/networking/mailreaders/mutt/default.nix b/pkgs/applications/networking/mailreaders/mutt/default.nix index 1964faf2f5c..31ead22e1fd 100644 --- a/pkgs/applications/networking/mailreaders/mutt/default.nix +++ b/pkgs/applications/networking/mailreaders/mutt/default.nix @@ -1,43 +1,51 @@ { stdenv, fetchurl, ncurses, which, perl, autoreconfHook -, sslSupport ? true -, imapSupport ? true -, headerCache ? true -, saslSupport ? true -, gpgmeSupport ? true , gdbm ? null , openssl ? null , cyrus_sasl ? null , gpgme ? null -, withSidebar ? false +, aclocal ? null +, headerCache ? true +, sslSupport ? true +, saslSupport ? true +, gpgmeSupport ? true +, imapSupport ? true +, withSidebar ? false +, withTrash ? false }: -assert headerCache -> gdbm != null; -assert sslSupport -> openssl != null; -assert saslSupport -> cyrus_sasl != null; -assert gpgmeSupport -> gpgme != null; +assert headerCache -> gdbm != null; +assert sslSupport -> openssl != null; +assert saslSupport -> cyrus_sasl != null; +assert gpgmeSupport -> gpgme != null; + +with stdenv.lib; -let - version = "1.6.0"; -in stdenv.mkDerivation rec { - name = "mutt${stdenv.lib.optionalString withSidebar "-with-sidebar"}-${version}"; + name = "mutt-${version}"; + version = "1.6.2"; src = fetchurl { - url = "http://ftp.mutt.org/pub/mutt/mutt-${version}.tar.gz"; - sha256 = "06bc2drbgalkk68rzg7hq2v5m5qgjxff5357wg0419dpi8ivdbr9"; + url = "http://ftp.mutt.org/pub/mutt/${name}.tar.gz"; + sha256 = "13hxmji7v9m2agmvzrs7gzx8s3c9jiwrv7pbkr7z1kc6ckq2xl65"; }; - buildInputs = with stdenv.lib; + buildInputs = [ ncurses which perl ] - ++ optional headerCache gdbm - ++ optional sslSupport openssl - ++ optional saslSupport cyrus_sasl - ++ optional gpgmeSupport gpgme; - - nativeBuildInputs = stdenv.lib.optional withSidebar autoreconfHook; + ++ optional headerCache gdbm + ++ optional sslSupport openssl + ++ optional saslSupport cyrus_sasl + ++ optional gpgmeSupport gpgme + ++ optional withSidebar autoreconfHook; configureFlags = [ - "--with-mailpath=" "--enable-smtp" + (enableFeature headerCache "hcache") + (enableFeature gpgmeSupport "gpgme") + (enableFeature imapSupport "imap") + (enableFeature withSidebar "sidebar") + "--enable-smtp" + "--enable-pop" + "--enable-imap" + "--with-mailpath=" # Look in $PATH at runtime, instead of hardcoding /usr/bin/sendmail "ac_cv_path_SENDMAIL=sendmail" @@ -45,36 +53,22 @@ stdenv.mkDerivation rec { # This allows calls with "-d N", that output debug info into ~/.muttdebug* "--enable-debug" - "--enable-pop" "--enable-imap" - # The next allows building mutt without having anything setgid # set by the installer, and removing the need for the group 'mail' # I set the value 'mailbox' because it is a default in the configure script "--with-homespool=mailbox" - (if headerCache then "--enable-hcache" else "--disable-hcache") - (if sslSupport then "--with-ssl" else "--without-ssl") - (if imapSupport then "--enable-imap" else "--disable-imap") - (if saslSupport then "--with-sasl" else "--without-sasl") - (if gpgmeSupport then "--enable-gpgme" else "--disable-gpgme") - ]; + ] ++ optional sslSupport "--with-ssl" + ++ optional saslSupport "--with-sasl"; - # Adding the sidebar - patches = stdenv.lib.optional withSidebar [ - ./trash-folder.patch - ./sidebar.patch - ./sidebar-dotpathsep.patch - ./sidebar-utf8.patch - ./sidebar-newonly.patch - ./sidebar-delimnullwide.patch - ./sidebar-compose.patch - ./sidebar-new.patch - ]; + patches = + optional withTrash ./trash.patch ++ + optional withSidebar ./sidebar.patch; - meta = with stdenv.lib; { + meta = { description = "A small but very powerful text-based mail client"; homepage = http://www.mutt.org; - license = stdenv.lib.licenses.gpl2Plus; + license = licenses.gpl2Plus; platforms = platforms.unix; - maintainers = with maintainers; [ the-kenny ]; + maintainers = with maintainers; [ the-kenny rnhmjoj ]; }; } diff --git a/pkgs/applications/networking/mailreaders/mutt/sidebar-compose.patch b/pkgs/applications/networking/mailreaders/mutt/sidebar-compose.patch deleted file mode 100644 index 90d815b841d..00000000000 --- a/pkgs/applications/networking/mailreaders/mutt/sidebar-compose.patch +++ /dev/null @@ -1,40 +0,0 @@ -From: Evgeni Golov -Date: Fri, 14 Mar 2014 08:54:47 +0100 -Subject: sidebar-compose - -draw_sidebar sets SidebarWidth to 0 when sidebar_visible is false. -However, if you start mutt in compose mode, draw_sidebar won't be -called until the next redraw and your header lines will be off by -the width of the sidebar, even when you did not want a sidebar at -all. - -Can be tested with: - HOME=/ LC_ALL=C mutt -e 'unset sidebar_visible' -s test recipient - -Closes: #502627 - -Gbp-Pq: Topic mutt-patched ---- - compose.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/compose.c b/compose.c -index b63695f..0fa6df2 100644 ---- a/compose.c -+++ b/compose.c -@@ -32,6 +32,7 @@ - #include "mailbox.h" - #include "sort.h" - #include "charset.h" -+#include "sidebar.h" - - #ifdef MIXMASTER - #include "remailer.h" -@@ -248,6 +249,7 @@ static void draw_envelope_addr (int line, ADDRESS *addr) - - static void draw_envelope (HEADER *msg, char *fcc) - { -+ draw_sidebar (MENU_COMPOSE); - draw_envelope_addr (HDR_FROM, msg->env->from); - draw_envelope_addr (HDR_TO, msg->env->to); - draw_envelope_addr (HDR_CC, msg->env->cc); diff --git a/pkgs/applications/networking/mailreaders/mutt/sidebar-delimnullwide.patch b/pkgs/applications/networking/mailreaders/mutt/sidebar-delimnullwide.patch deleted file mode 100644 index 11d2ced5a0c..00000000000 --- a/pkgs/applications/networking/mailreaders/mutt/sidebar-delimnullwide.patch +++ /dev/null @@ -1,38 +0,0 @@ -From: Evgeni Golov -Date: Wed, 5 Mar 2014 17:46:07 +0100 -Subject: sidebar-delimnullwide - -SidebarDelim can be NULL and strlen(NULL) is a bad idea, as it will segfault. -Wrap it with NONULL(). - -While at it, change strlen to mbstowcs for better utf8 support. - -Closes: #696145, #663883 - -Gbp-Pq: Topic mutt-patched ---- - sidebar.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/sidebar.c b/sidebar.c -index 51a25ca..c3ea338 100644 ---- a/sidebar.c -+++ b/sidebar.c -@@ -88,7 +88,7 @@ char *make_sidebar_entry(char *box, int size, int new, int flagged) - int box_len, box_bytes; - int int_len; - int right_offset = 0; -- int delim_len = strlen(SidebarDelim); -+ int delim_len = mbstowcs(NULL, NONULL(SidebarDelim), 0); - static char *entry; - - right_width = left_width = 0; -@@ -178,7 +178,7 @@ int draw_sidebar(int menu) { - #ifndef USE_SLANG_CURSES - attr_t attrs; - #endif -- short delim_len = strlen(SidebarDelim); -+ short delim_len = mbstowcs(NULL, NONULL(SidebarDelim), 0); - short color_pair; - - static bool initialized = false; diff --git a/pkgs/applications/networking/mailreaders/mutt/sidebar-dotpathsep.patch b/pkgs/applications/networking/mailreaders/mutt/sidebar-dotpathsep.patch deleted file mode 100644 index 315fa1649bc..00000000000 --- a/pkgs/applications/networking/mailreaders/mutt/sidebar-dotpathsep.patch +++ /dev/null @@ -1,98 +0,0 @@ -From: Fabian Groffen -Date: Tue, 4 Mar 2014 21:12:15 +0100 -Subject: sidebar-dotpathsep - -Make path separators for sidebar folders configurable. - -When using IMAP, a '.' is often used as path separator, hence make the -path separators configurable through sidebar_delim_chars variable. -It defaults to "/." to work for both mboxes as well as IMAP folders. It -can be set to only "/" or "." or whichever character desired as needed. - -Gbp-Pq: Topic mutt-patched ---- - globals.h | 1 + - init.h | 8 ++++++++ - sidebar.c | 31 ++++++++++++++++++++++++------- - 3 files changed, 33 insertions(+), 7 deletions(-) - -diff --git a/globals.h b/globals.h -index 004c795..602f932 100644 ---- a/globals.h -+++ b/globals.h -@@ -119,6 +119,7 @@ WHERE char *SendCharset; - WHERE char *Sendmail; - WHERE char *Shell; - WHERE char *SidebarDelim; -+WHERE char *SidebarDelimChars INITVAL (NULL); - WHERE char *Signature; - WHERE char *SimpleSearch; - #if USE_SMTP -diff --git a/init.h b/init.h -index c664e5f..166671b 100644 ---- a/init.h -+++ b/init.h -@@ -2051,6 +2051,14 @@ struct option_t MuttVars[] = { - ** .pp - ** The width of the sidebar. - */ -+ { "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. If -+ ** you're not using IMAP folders, you probably prefer setting this to "/" -+ ** alone. -+ */ - { "pgp_use_gpg_agent", DT_BOOL, R_NONE, OPTUSEGPGAGENT, 0}, - /* - ** .pp -diff --git a/sidebar.c b/sidebar.c -index 6098c2a..4356ffc 100644 ---- a/sidebar.c -+++ b/sidebar.c -@@ -249,20 +249,37 @@ int draw_sidebar(int menu) { - // calculate depth of current folder and generate its display name with indented spaces - int sidebar_folder_depth = 0; - char *sidebar_folder_name; -- sidebar_folder_name = basename(tmp->path); -+ int i; -+ sidebar_folder_name = tmp->path; -+ /* disregard a trailing separator, so strlen() - 2 -+ * https://bugs.gentoo.org/show_bug.cgi?id=373197#c16 */ -+ for (i = strlen(sidebar_folder_name) - 2; i >= 0; i--) { -+ if (SidebarDelimChars && -+ strchr(SidebarDelimChars, sidebar_folder_name[i])) -+ { -+ sidebar_folder_name += i + 1; -+ break; -+ } -+ } - if ( maildir_is_prefix ) { - char *tmp_folder_name; -- int i; -+ int lastsep = 0; - tmp_folder_name = tmp->path + strlen(Maildir); -- for (i = 0; i < strlen(tmp->path) - strlen(Maildir); i++) { -- if (tmp_folder_name[i] == '/') sidebar_folder_depth++; -- } -+ for (i = 0; i < strlen(tmp_folder_name) - 1; i++) { -+ if (SidebarDelimChars && -+ strchr(SidebarDelimChars, tmp_folder_name[i])) -+ { -+ sidebar_folder_depth++; -+ lastsep = i + 1; -+ } -+ } - if (sidebar_folder_depth > 0) { -- sidebar_folder_name = malloc(strlen(basename(tmp->path)) + sidebar_folder_depth + 1); -+ tmp_folder_name += lastsep; /* basename */ -+ sidebar_folder_name = malloc(strlen(tmp_folder_name) + sidebar_folder_depth + 1); - for (i=0; i < sidebar_folder_depth; i++) - sidebar_folder_name[i]=' '; - sidebar_folder_name[i]=0; -- strncat(sidebar_folder_name, basename(tmp->path), strlen(basename(tmp->path)) + sidebar_folder_depth); -+ strncat(sidebar_folder_name, tmp_folder_name, strlen(tmp_folder_name) + sidebar_folder_depth); - } - } - printw( "%.*s", SidebarWidth - delim_len + 1, diff --git a/pkgs/applications/networking/mailreaders/mutt/sidebar-new.patch b/pkgs/applications/networking/mailreaders/mutt/sidebar-new.patch deleted file mode 100644 index fb265346361..00000000000 --- a/pkgs/applications/networking/mailreaders/mutt/sidebar-new.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 355399bde98203af59d20821f9e840fc056bd383 Mon Sep 17 00:00:00 2001 -From: Julius Haertl -Date: Tue, 9 Sep 2014 22:31:49 +0200 -Subject: Patch for sidebar iteration functionality - -sidebar-new will move the selected folder to the next with new messages. -If the end is reached, it will start at the top. - -Useful macros would be: - - macro index a "" - macro pager a "" ---- - OPS | 1 + - curs_main.c | 1 + - functions.h | 2 ++ - pager.c | 1 + - sidebar.c | 10 ++++++++++ - 5 files changed, 15 insertions(+) - -diff --git a/OPS b/OPS -index 1ed9c96..3ffb82a 100644 ---- a/OPS -+++ b/OPS -@@ -187,3 +187,4 @@ OP_SIDEBAR_PREV "go to previous mailbox" - OP_SIDEBAR_OPEN "open hilighted mailbox" - OP_SIDEBAR_NEXT_NEW "go down to next mailbox with new mail" - OP_SIDEBAR_PREV_NEW "go to previous mailbox with new mail" -+OP_SIDEBAR_NEW "iterate though mailboxes with new mail" -diff --git a/curs_main.c b/curs_main.c -index acb106d..2e35f90 100644 ---- a/curs_main.c -+++ b/curs_main.c -@@ -2328,6 +2328,7 @@ int mutt_index_menu (void) - case OP_SIDEBAR_PREV: - case OP_SIDEBAR_NEXT_NEW: - case OP_SIDEBAR_PREV_NEW: -+ case OP_SIDEBAR_NEW: - scroll_sidebar(op, menu->menu); - break; - default: -diff --git a/functions.h b/functions.h -index 363b4d5..1485080 100644 ---- a/functions.h -+++ b/functions.h -@@ -176,6 +176,7 @@ const struct binding_t OpMain[] = { /* map: index */ - { "sidebar-prev", OP_SIDEBAR_PREV, NULL }, - { "sidebar-next-new", OP_SIDEBAR_NEXT_NEW, NULL}, - { "sidebar-prev-new", OP_SIDEBAR_PREV_NEW, NULL}, -+ { "sidebar-new", OP_SIDEBAR_NEW, NULL }, - { "sidebar-open", OP_SIDEBAR_OPEN, NULL }, - { NULL, 0, NULL } - }; -@@ -287,6 +288,7 @@ const struct binding_t OpPager[] = { /* map: pager */ - { "sidebar-prev", OP_SIDEBAR_PREV, NULL }, - { "sidebar-next-new", OP_SIDEBAR_NEXT_NEW, NULL}, - { "sidebar-prev-new", OP_SIDEBAR_PREV_NEW, NULL}, -+ { "sidebar-new", OP_SIDEBAR_NEW, NULL }, - { "sidebar-open", OP_SIDEBAR_OPEN, NULL }, - { NULL, 0, NULL } - }; -diff --git a/pager.c b/pager.c -index 8d64fe1..696e55c 100644 ---- a/pager.c -+++ b/pager.c -@@ -2791,6 +2791,7 @@ search_next: - case OP_SIDEBAR_PREV: - case OP_SIDEBAR_NEXT_NEW: - case OP_SIDEBAR_PREV_NEW: -+ case OP_SIDEBAR_NEW: - scroll_sidebar(ch, MENU_PAGER); - break; - -diff --git a/sidebar.c b/sidebar.c -index c3ea338..eb8ecd2 100644 ---- a/sidebar.c -+++ b/sidebar.c -@@ -429,6 +429,16 @@ void scroll_sidebar(int op, int menu) - CurBuffy = CurBuffy->next; - } - break; -+ case OP_SIDEBAR_NEW: -+ if ( (tmp = exist_next_new()) == NULL) -+ tmp = TopBuffy; -+ if ( tmp->msg_unread == 0 ) { -+ CurBuffy = tmp; -+ tmp = exist_next_new(); -+ } -+ if ( tmp != NULL ) -+ CurBuffy = tmp; -+ break; - default: - return; - } --- -2.6.0.rc0.2.g7662973.dirty - diff --git a/pkgs/applications/networking/mailreaders/mutt/sidebar-newonly.patch b/pkgs/applications/networking/mailreaders/mutt/sidebar-newonly.patch deleted file mode 100644 index d206848026b..00000000000 --- a/pkgs/applications/networking/mailreaders/mutt/sidebar-newonly.patch +++ /dev/null @@ -1,198 +0,0 @@ -From: Steve Kemp -Date: Tue, 4 Mar 2014 22:07:06 +0100 -Subject: sidebar-newonly - -patches written by Steve Kemp, it adds two new functionalities to the sidebar, -so only the mailbox with new messages will be shown (and/or) selected -See Debian bug http://bugs.debian.org/532510 - -Gbp-Pq: Topic mutt-patched ---- - OPS | 2 ++ - curs_main.c | 2 ++ - functions.h | 4 ++++ - init.h | 5 +++++ - mutt.h | 2 ++ - pager.c | 2 ++ - sidebar.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- - 7 files changed, 70 insertions(+), 2 deletions(-) - -diff --git a/OPS b/OPS -index b036db9..1ed9c96 100644 ---- a/OPS -+++ b/OPS -@@ -185,3 +185,5 @@ OP_SIDEBAR_SCROLL_DOWN "scroll the mailbox pane down 1 page" - OP_SIDEBAR_NEXT "go down to next mailbox" - OP_SIDEBAR_PREV "go to previous mailbox" - OP_SIDEBAR_OPEN "open hilighted mailbox" -+OP_SIDEBAR_NEXT_NEW "go down to next mailbox with new mail" -+OP_SIDEBAR_PREV_NEW "go to previous mailbox with new mail" -diff --git a/curs_main.c b/curs_main.c -index ea530a6..acb106d 100644 ---- a/curs_main.c -+++ b/curs_main.c -@@ -2326,6 +2326,8 @@ int mutt_index_menu (void) - case OP_SIDEBAR_SCROLL_DOWN: - case OP_SIDEBAR_NEXT: - case OP_SIDEBAR_PREV: -+ case OP_SIDEBAR_NEXT_NEW: -+ case OP_SIDEBAR_PREV_NEW: - scroll_sidebar(op, menu->menu); - break; - default: -diff --git a/functions.h b/functions.h -index ef8937a..363b4d5 100644 ---- a/functions.h -+++ b/functions.h -@@ -174,6 +174,8 @@ const struct binding_t OpMain[] = { /* map: index */ - { "sidebar-scroll-down", OP_SIDEBAR_SCROLL_DOWN, NULL }, - { "sidebar-next", OP_SIDEBAR_NEXT, NULL }, - { "sidebar-prev", OP_SIDEBAR_PREV, NULL }, -+ { "sidebar-next-new", OP_SIDEBAR_NEXT_NEW, NULL}, -+ { "sidebar-prev-new", OP_SIDEBAR_PREV_NEW, NULL}, - { "sidebar-open", OP_SIDEBAR_OPEN, NULL }, - { NULL, 0, NULL } - }; -@@ -283,6 +285,8 @@ const struct binding_t OpPager[] = { /* map: pager */ - { "sidebar-scroll-down", OP_SIDEBAR_SCROLL_DOWN, NULL }, - { "sidebar-next", OP_SIDEBAR_NEXT, NULL }, - { "sidebar-prev", OP_SIDEBAR_PREV, NULL }, -+ { "sidebar-next-new", OP_SIDEBAR_NEXT_NEW, NULL}, -+ { "sidebar-prev-new", OP_SIDEBAR_PREV_NEW, NULL}, - { "sidebar-open", OP_SIDEBAR_OPEN, NULL }, - { NULL, 0, NULL } - }; -diff --git a/init.h b/init.h -index 166671b..a5d4238 100644 ---- a/init.h -+++ b/init.h -@@ -2059,6 +2059,11 @@ struct option_t MuttVars[] = { - ** you're not using IMAP folders, you probably prefer setting this to "/" - ** alone. - */ -+ {"sidebar_newmail_only", DT_BOOL, R_BOTH, OPTSIDEBARNEWMAILONLY, 0 }, -+ /* -+ ** .pp -+ ** Show only new mail in the sidebar. -+ */ - { "pgp_use_gpg_agent", DT_BOOL, R_NONE, OPTUSEGPGAGENT, 0}, - /* - ** .pp -diff --git a/mutt.h b/mutt.h -index 5f25406..d73e514 100644 ---- a/mutt.h -+++ b/mutt.h -@@ -529,6 +529,8 @@ enum - OPTDONTHANDLEPGPKEYS, /* (pseudo) used to extract PGP keys */ - OPTUNBUFFEREDINPUT, /* (pseudo) don't use key buffer */ - -+ OPTSIDEBARNEWMAILONLY, -+ - OPTMAX - }; - -diff --git a/pager.c b/pager.c -index 5cfcb75..8d64fe1 100644 ---- a/pager.c -+++ b/pager.c -@@ -2789,6 +2789,8 @@ search_next: - case OP_SIDEBAR_SCROLL_DOWN: - case OP_SIDEBAR_NEXT: - case OP_SIDEBAR_PREV: -+ case OP_SIDEBAR_NEXT_NEW: -+ case OP_SIDEBAR_PREV_NEW: - scroll_sidebar(ch, MENU_PAGER); - break; - -diff --git a/sidebar.c b/sidebar.c -index 8f58f85..51a25ca 100644 ---- a/sidebar.c -+++ b/sidebar.c -@@ -269,8 +269,21 @@ int draw_sidebar(int menu) { - SETCOLOR(MT_COLOR_NEW); - else if ( tmp->msg_flagged > 0 ) - SETCOLOR(MT_COLOR_FLAGGED); -- else -- SETCOLOR(MT_COLOR_NORMAL); -+ else { -+ /* make sure the path is either: -+ 1. Containing new mail. -+ 2. The inbox. -+ 3. The current box. -+ */ -+ if ((option (OPTSIDEBARNEWMAILONLY)) && -+ ( (tmp->msg_unread <= 0) && -+ ( tmp != Incoming ) && -+ Context && -+ ( strcmp( tmp->path, Context->path ) != 0 ) ) ) -+ continue; -+ else -+ SETCOLOR(MT_COLOR_NORMAL); -+ } - - move( lines, 0 ); - if ( Context && !strcmp( tmp->path, Context->path ) ) { -@@ -336,6 +349,29 @@ int draw_sidebar(int menu) { - return 0; - } - -+BUFFY * exist_next_new() -+{ -+ BUFFY *tmp = CurBuffy; -+ if(tmp == NULL) return NULL; -+ while (tmp->next != NULL) -+ { -+ tmp = tmp->next; -+ if(tmp->msg_unread) return tmp; -+ } -+ return NULL; -+} -+ -+BUFFY * exist_prev_new() -+{ -+ BUFFY *tmp = CurBuffy; -+ if(tmp == NULL) return NULL; -+ while (tmp->prev != NULL) -+ { -+ tmp = tmp->prev; -+ if(tmp->msg_unread) return tmp; -+ } -+ return NULL; -+} - - void set_buffystats(CONTEXT* Context) - { -@@ -352,18 +388,33 @@ void set_buffystats(CONTEXT* Context) - - void scroll_sidebar(int op, int menu) - { -+ BUFFY *tmp; - if(!SidebarWidth) return; - if(!CurBuffy) return; - - switch (op) { - case OP_SIDEBAR_NEXT: -+ if (!option (OPTSIDEBARNEWMAILONLY)) { - if ( CurBuffy->next == NULL ) return; - CurBuffy = CurBuffy->next; - break; -+ } -+ case OP_SIDEBAR_NEXT_NEW: -+ if ( (tmp = exist_next_new()) == NULL) -+ return; -+ else CurBuffy = tmp; -+ break; - case OP_SIDEBAR_PREV: -+ if (!option (OPTSIDEBARNEWMAILONLY)) { - if ( CurBuffy->prev == NULL ) return; - CurBuffy = CurBuffy->prev; - break; -+ } -+ case OP_SIDEBAR_PREV_NEW: -+ if ( (tmp = exist_prev_new()) == NULL) -+ return; -+ else CurBuffy = tmp; -+ break; - case OP_SIDEBAR_SCROLL_UP: - CurBuffy = TopBuffy; - if ( CurBuffy != Incoming ) { diff --git a/pkgs/applications/networking/mailreaders/mutt/sidebar-utf8.patch b/pkgs/applications/networking/mailreaders/mutt/sidebar-utf8.patch deleted file mode 100644 index d67e43c24b6..00000000000 --- a/pkgs/applications/networking/mailreaders/mutt/sidebar-utf8.patch +++ /dev/null @@ -1,132 +0,0 @@ -From: Antonio Radici -Date: Tue, 4 Mar 2014 15:39:14 +0100 -Subject: sidebar-utf8 - -This patch fixes a problem with utf-8 strings and the sidebar, -it rewrites entirely make_sidebar_entry so it also fixes some -segfaults due to misallocations and overflows. - -See: - http://bugs.debian.org/584581 - http://bugs.debian.org/603287 - -Gbp-Pq: Topic mutt-patched ---- - sidebar.c | 97 +++++++++++++++++++++++++++++++++++++++++++-------------------- - 1 file changed, 67 insertions(+), 30 deletions(-) - -diff --git a/sidebar.c b/sidebar.c -index 4356ffc..8f58f85 100644 ---- a/sidebar.c -+++ b/sidebar.c -@@ -30,6 +30,7 @@ - #include - #include "keymap.h" - #include -+#include - - /*BUFFY *CurBuffy = 0;*/ - static BUFFY *TopBuffy = 0; -@@ -82,36 +83,72 @@ void calc_boundaries (int menu) - - char *make_sidebar_entry(char *box, int size, int new, int flagged) - { -- static char *entry = 0; -- char *c; -- int i = 0; -- int delim_len = strlen(SidebarDelim); -- -- c = realloc(entry, SidebarWidth - delim_len + 2); -- if ( c ) entry = c; -- entry[SidebarWidth - delim_len + 1] = 0; -- for (; i < SidebarWidth - delim_len + 1; entry[i++] = ' ' ); -- i = strlen(box); -- strncpy( entry, box, i < (SidebarWidth - delim_len + 1) ? i : (SidebarWidth - delim_len + 1) ); -- -- if (size == -1) -- sprintf(entry + SidebarWidth - delim_len - 3, "?"); -- else if ( new ) { -- if (flagged > 0) { -- sprintf( -- entry + SidebarWidth - delim_len - 5 - quick_log10(size) - quick_log10(new) - quick_log10(flagged), -- "% d(%d)[%d]", size, new, flagged); -- } else { -- sprintf( -- entry + SidebarWidth - delim_len - 3 - quick_log10(size) - quick_log10(new), -- "% d(%d)", size, new); -- } -- } else if (flagged > 0) { -- sprintf( entry + SidebarWidth - delim_len - 3 - quick_log10(size) - quick_log10(flagged), "% d[%d]", size, flagged); -- } else { -- sprintf( entry + SidebarWidth - delim_len - 1 - quick_log10(size), "% d", size); -- } -- return entry; -+ char int_store[20]; // up to 64 bits integers -+ int right_width, left_width; -+ int box_len, box_bytes; -+ int int_len; -+ int right_offset = 0; -+ int delim_len = strlen(SidebarDelim); -+ static char *entry; -+ -+ right_width = left_width = 0; -+ box_len = box_bytes = 0; -+ -+ // allocate an entry big enough to contain SidebarWidth wide chars -+ entry = malloc((SidebarWidth*4)+1); // TODO: error check -+ -+ // determine the right space (i.e.: how big are the numbers that we want to print) -+ if ( size > 0 ) { -+ int_len = snprintf(int_store, sizeof(int_store), "%d", size); -+ right_width += int_len; -+ } else { -+ right_width = 1; // to represent 0 -+ } -+ if ( new > 0 ) { -+ int_len = snprintf(int_store, sizeof(int_store), "%d", new); -+ right_width += int_len + 2; // 2 is for () -+ } -+ if ( flagged > 0 ) { -+ int_len = snprintf(int_store, sizeof(int_store), "%d", flagged); -+ right_width += int_len + 2; // 2 is for [] -+ } -+ -+ // determine how much space we have for *box and its padding (if any) -+ left_width = SidebarWidth - right_width - 1 - delim_len; // 1 is for the space -+ //fprintf(stdout, "left_width: %d right_width: %d\n", left_width, right_width); -+ // right side overflow case -+ if ( left_width <= 0 ) { -+ snprintf(entry, SidebarWidth*4, "%-*.*s ...", SidebarWidth-4-delim_len, SidebarWidth-4-delim_len, box); -+ return entry; -+ } -+ right_width -= delim_len; -+ -+ // to support utf-8 chars we need to add enough space padding in case there -+ // are less chars than bytes in *box -+ box_len = mbstowcs(NULL, box, 0); -+ box_bytes = strlen(box); -+ // debug -+ //fprintf(stdout, "box_len: %d box_bytes: %d (diff: %d)\n", box_len, box_bytes, (box_bytes-box_len)); -+ // if there is less string than the space we allow, then we will add the -+ // spaces -+ if ( box_len != -1 && box_len < left_width ) { -+ left_width += (box_bytes - box_len); -+ } -+ // otherwise sprintf will truncate the string for us (therefore, no else case) -+ -+ // print the sidebar entry (without new and flagged messages, at the moment) -+ //fprintf(stdout, "left_width: %d right_width: %d\n", left_width, right_width); -+ right_offset = snprintf(entry, SidebarWidth*4, "%-*.*s %d", left_width, left_width, box, size); -+ -+ // then pad new and flagged messages if any -+ if ( new > 0 ) { -+ right_offset += snprintf(entry+right_offset, SidebarWidth*4-right_offset, "(%d)", new); -+ } -+ if ( flagged > 0 ) { -+ right_offset += snprintf(entry+right_offset, SidebarWidth*4-right_offset, "[%d]", flagged); -+ } -+ -+ return entry; - } - - void set_curbuffy(char buf[LONG_STRING]) diff --git a/pkgs/applications/networking/mailreaders/mutt/sidebar.patch b/pkgs/applications/networking/mailreaders/mutt/sidebar.patch index bac1b4ab83b..218de7a0c46 100644 --- a/pkgs/applications/networking/mailreaders/mutt/sidebar.patch +++ b/pkgs/applications/networking/mailreaders/mutt/sidebar.patch @@ -1,306 +1,373 @@ -From: Antonio Radici -Date: Tue, 4 Mar 2014 15:21:10 +0100 -Subject: sidebar - -When enabled, mutt will show a list of mailboxes with (new) message counts in a -separate column on the left side of the screen. - -As this feature is still considered to be unstable, this patch is only applied -in the "mutt-patched" package. - -* Configuration variables: - - sidebar_delim (string, default "|") - - This specifies the delimiter between the sidebar (if visible) and - other screens. - - sidebar_visible (boolean, default no) - - This specifies whether or not to show sidebar (left-side list of folders). - - sidebar_width (integer, default 0) -- - The width of the sidebar. - -* Patch source: - - http://www.lunar-linux.org/index.php?page=mutt-sidebar - - http://lunar-linux.org/~tchan/mutt/patch-1.5.19.sidebar.20090522.txt - -* Changes made: - - 2008-08-02 myon: Refreshed patch using quilt push -f to remove hunks we do - not need (Makefile.in). - - - 2014-03-04 evgeni: refresh sidebar patch with the version from OpenBSD - Source: - ftp://ftp.openbsd.org/pub/OpenBSD/distfiles/mutt/sidebar-1.5.22.diff1.gz - -Signed-off-by: Matteo F. Vescovi -Signed-off-by: Evgeni Golov - -Gbp-Pq: Topic mutt-patched ---- - Makefile.am | 1 + - OPS | 5 + - buffy.c | 124 +++++++++++++++++++++ - buffy.h | 4 + - color.c | 2 + - compose.c | 26 ++--- - curs_main.c | 30 +++++- - flags.c | 3 + - functions.h | 10 ++ - globals.h | 4 + - imap/command.c | 7 ++ - imap/imap.c | 2 +- - init.h | 21 ++++ - mailbox.h | 1 + - mbox.c | 2 + - menu.c | 20 ++-- - mh.c | 22 ++++ - mutt.h | 4 + - mutt_curses.h | 3 + - muttlib.c | 48 +++++++++ - mx.c | 15 +++ - mx.h | 1 + - pager.c | 30 ++++-- - sidebar.c | 333 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - sidebar.h | 36 +++++++ - 25 files changed, 720 insertions(+), 34 deletions(-) - create mode 100644 sidebar.c - create mode 100644 sidebar.h - -diff --git a/Makefile.am b/Makefile.am -index 5dfeff6..cf1ac98 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -33,6 +33,7 @@ mutt_SOURCES = \ - rfc822.c rfc1524.c rfc2047.c rfc2231.c rfc3676.c \ - score.c send.c sendlib.c signal.c sort.c \ - status.c system.c thread.c charset.c history.c lib.c \ -+ sidebar.c \ - muttlib.c editmsg.c mbyte.c mutt_idna.c \ - url.c ascii.c crypt-mod.c crypt-mod.h safe_asprintf.c +diff -urN mutt-1.6.1/buffy.c mutt-1.6.1-sidebar/buffy.c +--- mutt-1.6.1/buffy.c 2016-06-12 18:43:00.397447512 +0100 ++++ mutt-1.6.1-sidebar/buffy.c 2016-06-12 18:43:03.951502935 +0100 +@@ -27,6 +27,10 @@ -diff --git a/OPS b/OPS -index 02cea8e..b036db9 100644 ---- a/OPS -+++ b/OPS -@@ -180,3 +180,8 @@ OP_WHAT_KEY "display the keycode for a key press" - OP_MAIN_SHOW_LIMIT "show currently active limit pattern" - OP_MAIN_COLLAPSE_THREAD "collapse/uncollapse current thread" - OP_MAIN_COLLAPSE_ALL "collapse/uncollapse all threads" -+OP_SIDEBAR_SCROLL_UP "scroll the mailbox pane up 1 page" -+OP_SIDEBAR_SCROLL_DOWN "scroll the mailbox pane down 1 page" -+OP_SIDEBAR_NEXT "go down to next mailbox" -+OP_SIDEBAR_PREV "go to previous mailbox" -+OP_SIDEBAR_OPEN "open hilighted mailbox" -diff --git a/buffy.c b/buffy.c -index 12a16d1..90ca6db 100644 ---- a/buffy.c -+++ b/buffy.c -@@ -161,6 +161,49 @@ void mutt_buffy_cleanup (const char *buf, struct stat *st) - } - } + #include "mutt_curses.h" -+static int buffy_compare_name(const void *a, const void *b) { -+ const BUFFY *b1 = * (BUFFY * const *) a; -+ const BUFFY *b2 = * (BUFFY * const *) b; ++#ifdef USE_SIDEBAR ++#include "sidebar.h" ++#endif + -+ return mutt_strcoll(b1->path, b2->path); -+} -+ -+static BUFFY *buffy_sort(BUFFY *b) -+{ -+ BUFFY *tmp = b; -+ int buffycount = 0; -+ BUFFY **ary; -+ int i; -+ -+ if (!option(OPTSIDEBARSORT)) -+ return b; -+ -+ for (; tmp != NULL; tmp = tmp->next) -+ buffycount++; -+ -+ ary = (BUFFY **) safe_calloc(buffycount, sizeof (*ary)); -+ -+ tmp = b; -+ for (i = 0; tmp != NULL; tmp = tmp->next, i++) { -+ ary[i] = tmp; -+ } -+ -+ qsort(ary, buffycount, sizeof(*ary), buffy_compare_name); -+ -+ for (i = 0; i < buffycount - 1; i++) { -+ ary[i]->next = ary[i+1]; -+ } -+ ary[buffycount - 1]->next = NULL; -+ for (i = 1; i < buffycount; i++) { -+ ary[i]->prev = ary[i-1]; -+ } -+ ary[0]->prev = NULL; -+ -+ tmp = ary[0]; -+ free(ary); -+ return tmp; -+} -+ - BUFFY *mutt_find_mailbox (const char *path) + #ifdef USE_IMAP + #include "imap.h" + #endif +@@ -196,9 +200,17 @@ + static BUFFY *buffy_new (const char *path) { - BUFFY *tmp = NULL; -@@ -282,6 +325,7 @@ int mutt_parse_mailboxes (BUFFER *path, BUFFER *s, unsigned long data, BUFFER *e - else - (*tmp)->size = 0; + 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 ++ mutt_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 ++ mutt_sb_notify_mailbox (*tmp, 0); ++#endif + buffy_free (tmp); + *tmp=tmp1; + } + continue; + } + +- if (!*tmp) ++ if (!*tmp) { + *tmp = buffy_new (buf); ++#ifdef USE_SIDEBAR ++ mutt_sb_notify_mailbox (*tmp, 1); ++#endif ++ } + + (*tmp)->new = 0; + (*tmp)->notified = 1; +@@ -306,6 +336,13 @@ + return 0; } -+ Incoming = buffy_sort(Incoming); - return 0; - } -@@ -357,6 +401,69 @@ static int buffy_maildir_hasnew (BUFFY* mailbox) ++#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,93 @@ return 0; } + -+/* update message counts for the sidebar */ -+void buffy_maildir_update (BUFFY* mailbox) ++#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; -+ struct dirent *de; -+ char *p; ++ char path[_POSIX_PATH_MAX] = ""; ++ DIR *dirp = NULL; ++ struct dirent *de = NULL; ++ char *p = NULL; ++ int read; + -+ mailbox->msgcount = 0; -+ mailbox->msg_unread = 0; -+ mailbox->msg_flagged = 0; ++ snprintf (path, sizeof (path), "%s/%s", mailbox->path, dir); + -+ snprintf (path, sizeof (path), "%s/new", mailbox->path); -+ -+ if ((dirp = opendir (path)) == NULL) -+ { ++ dirp = opendir (path); ++ if (!dirp) ++ { + mailbox->magic = 0; + return; -+ } -+ ++ } ++ + while ((de = readdir (dirp)) != NULL) + { + if (*de->d_name == '.') + continue; + -+ if (!(p = strstr (de->d_name, ":2,")) || !strchr (p + 3, 'T')) { -+ mailbox->new = 1; -+ mailbox->msgcount++; ++ /* 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); -+ snprintf (path, sizeof (path), "%s/cur", mailbox->path); -+ -+ if ((dirp = opendir (path)) == NULL) -+ { -+ mailbox->magic = 0; -+ return; -+ } -+ -+ while ((de = readdir (dirp)) != NULL) -+ { -+ if (*de->d_name == '.') -+ continue; -+ -+ if (!(p = strstr (de->d_name, ":2,")) || !strchr (p + 3, 'T')) { -+ mailbox->msgcount++; -+ if ((p = strstr (de->d_name, ":2,"))) { -+ if (!strchr (p + 3, 'T')) { -+ if (!strchr (p + 3, 'S')) -+ mailbox->msg_unread++; -+ if (strchr(p + 3, 'F')) -+ mailbox->msg_flagged++; -+ } -+ } -+ } -+ } -+ -+ 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 */ ++ if (SidebarWidth) ++ mutt_sb_draw(); ++} ++ ++#endif + /* returns 1 if mailbox has new mail */ static int buffy_mbox_hasnew (BUFFY* mailbox, struct stat *sb) { -@@ -388,6 +495,20 @@ static int buffy_mbox_hasnew (BUFFY* mailbox, struct stat *sb) +@@ -368,7 +491,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 +515,42 @@ return rc; } -+/* update message counts for the sidebar */ -+void buffy_mbox_update (BUFFY* mailbox) ++#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; + -+ ctx = mx_open_mailbox(mailbox->path, M_READONLY | M_QUIET | M_NOSORT | M_PEEK, NULL); -+ if(ctx) ++ 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->msgcount = ctx->msgcount; -+ mailbox->msg_unread = ctx->unread; -+ mx_close_mailbox(ctx, 0); ++ 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 */ ++ if (SidebarWidth) ++ mutt_sb_draw(); +} ++#endif + int mutt_buffy_check (int force) { BUFFY *tmp; -@@ -461,16 +582,19 @@ int mutt_buffy_check (int force) +@@ -461,16 +623,25 @@ { case M_MBOX: case M_MMDF: -+ buffy_mbox_update (tmp); ++#ifdef USE_SIDEBAR ++ buffy_mbox_update (tmp, &sb); ++#endif if (buffy_mbox_hasnew (tmp, &sb) > 0) BuffyCount++; break; case M_MAILDIR: ++#ifdef USE_SIDEBAR + buffy_maildir_update (tmp); ++#endif if (buffy_maildir_hasnew (tmp) > 0) BuffyCount++; break; case M_MH: -+ mh_buffy_update (tmp->path, &tmp->msgcount, &tmp->msg_unread, &tmp->msg_flagged); ++#ifdef USE_SIDEBAR ++ mh_buffy_update (tmp); ++#endif mh_buffy(tmp); if (tmp->new) BuffyCount++; -diff --git a/buffy.h b/buffy.h -index f9fc55a..672d178 100644 ---- a/buffy.h -+++ b/buffy.h -@@ -25,7 +25,11 @@ typedef struct buffy_t +diff -urN mutt-1.6.1/buffy.h mutt-1.6.1-sidebar/buffy.h +--- mutt-1.6.1/buffy.h 2016-06-12 18:43:00.397447512 +0100 ++++ mutt-1.6.1-sidebar/buffy.h 2016-06-12 18:43:03.951502935 +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 */ -+ int msgcount; /* total number of messages */ ++#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 */ -diff --git a/color.c b/color.c -index 64a46dc..d6f9198 100644 ---- a/color.c -+++ b/color.c -@@ -94,6 +94,8 @@ static const struct mapping_t Fields[] = + 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-06-12 18:43:00.397447512 +0100 ++++ mutt-1.6.1-sidebar/color.c 2016-06-12 18:43:03.951502935 +0100 +@@ -94,6 +94,14 @@ { "underline", MT_COLOR_UNDERLINE }, { "index", MT_COLOR_INDEX }, { "prompt", MT_COLOR_PROMPT }, -+ { "sidebar_new", MT_COLOR_NEW }, ++#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 } }; -diff --git a/compose.c b/compose.c -index 9d87060..b63695f 100644 ---- a/compose.c -+++ b/compose.c -@@ -72,7 +72,7 @@ enum +@@ -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-06-12 18:43:00.398447528 +0100 ++++ mutt-1.6.1-sidebar/compose.c 2016-06-12 18:43:03.952502951 +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 */ @@ -309,16 +376,16 @@ index 9d87060..b63695f 100644 static const char * const Prompts[] = { -@@ -110,7 +110,7 @@ static void snd_entry (char *b, size_t blen, MUTTMENU *menu, int num) +@@ -110,7 +113,7 @@ static void redraw_crypt_lines (HEADER *msg) { - mvaddstr (HDR_CRYPT, 0, "Security: "); -+ mvaddstr (HDR_CRYPT, SidebarWidth, "Security: "); ++ mvprintw (HDR_CRYPT, SidebarWidth, TITLE_FMT, "Security: "); if ((WithCrypto & (APPLICATION_PGP | APPLICATION_SMIME)) == 0) { -@@ -145,7 +145,7 @@ static void redraw_crypt_lines (HEADER *msg) +@@ -145,16 +148,16 @@ addstr (_(" (OppEnc mode)")); clrtoeol (); @@ -327,7 +394,18 @@ index 9d87060..b63695f 100644 clrtoeol (); if ((WithCrypto & APPLICATION_PGP) -@@ -162,7 +162,7 @@ static void redraw_crypt_lines (HEADER *msg) + && (msg->security & APPLICATION_PGP) && (msg->security & SIGN)) +- printw ("%s%s", _(" sign as: "), PgpSignAs ? PgpSignAs : _("")); ++ printw (TITLE_FMT "%s", _("sign as: "), PgpSignAs ? PgpSignAs : _("")); + + if ((WithCrypto & APPLICATION_SMIME) + && (msg->security & APPLICATION_SMIME) && (msg->security & SIGN)) { +- printw ("%s%s", _(" sign as: "), SmimeDefaultKey ? SmimeDefaultKey : _("")); ++ printw (TITLE_FMT "%s", _("sign as: "), SmimeDefaultKey ? SmimeDefaultKey : _("")); + } + + if ((WithCrypto & APPLICATION_SMIME) +@@ -162,7 +165,7 @@ && (msg->security & ENCRYPT) && SmimeCryptAlg && *SmimeCryptAlg) { @@ -336,16 +414,17 @@ index 9d87060..b63695f 100644 NONULL(SmimeCryptAlg)); } } -@@ -175,7 +175,7 @@ static void redraw_mix_line (LIST *chain) +@@ -175,7 +178,8 @@ int c; char *t; - mvaddstr (HDR_MIX, 0, " Mix: "); -+ mvaddstr (HDR_MIX, SidebarWidth, " Mix: "); ++ /* L10N: "Mix" refers to the MixMaster chain for anonymous email */ ++ mvprintw (HDR_MIX, SidebarWidth, TITLE_FMT, _("Mix: ")); if (!chain) { -@@ -190,7 +190,7 @@ static void redraw_mix_line (LIST *chain) +@@ -190,7 +194,7 @@ if (t && t[0] == '0' && t[1] == '\0') t = ""; @@ -354,7 +433,7 @@ index 9d87060..b63695f 100644 break; addstr (NONULL(t)); -@@ -242,7 +242,7 @@ static void draw_envelope_addr (int line, ADDRESS *addr) +@@ -242,20 +246,23 @@ buf[0] = 0; rfc822_write_address (buf, sizeof (buf), addr, 1); @@ -363,7 +442,12 @@ index 9d87060..b63695f 100644 mutt_paddstr (W, buf); } -@@ -252,10 +252,10 @@ static void draw_envelope (HEADER *msg, char *fcc) + static void draw_envelope (HEADER *msg, char *fcc) + { ++#ifdef USE_SIDEBAR ++ mutt_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); @@ -376,7 +460,7 @@ index 9d87060..b63695f 100644 mutt_paddstr (W, fcc); if (WithCrypto) -@@ -266,7 +266,7 @@ static void draw_envelope (HEADER *msg, char *fcc) +@@ -266,7 +273,7 @@ #endif SETCOLOR (MT_COLOR_STATUS); @@ -385,16 +469,25 @@ index 9d87060..b63695f 100644 clrtoeol (); NORMAL_COLOR; -@@ -302,7 +302,7 @@ static int edit_address_list (int line, ADDRESS **addr) +@@ -302,7 +309,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); ++ move (line, HDR_XOFFSET + SidebarWidth); mutt_paddstr (W, buf); return 0; -@@ -562,7 +562,7 @@ int mutt_compose_menu (HEADER *msg, /* structure for new message */ +@@ -515,7 +522,7 @@ + menu->tag = mutt_tag_attach; + menu->data = idx; + menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_COMPOSE, ComposeHelp); +- ++ + while (loop) + { + switch (op = mutt_menuLoop (menu)) +@@ -564,7 +571,7 @@ if (mutt_get_field ("Subject: ", buf, sizeof (buf), 0) == 0) { mutt_str_replace (&msg->env->subject, buf); @@ -403,7 +496,7 @@ index 9d87060..b63695f 100644 if (msg->env->subject) mutt_paddstr (W, msg->env->subject); else -@@ -580,7 +580,7 @@ int mutt_compose_menu (HEADER *msg, /* structure for new message */ +@@ -582,7 +589,7 @@ { strfcpy (fcc, buf, fcclen); mutt_pretty_mailbox (fcc, fcclen); @@ -412,57 +505,118 @@ index 9d87060..b63695f 100644 mutt_paddstr (W, fcc); fccSet = 1; } -diff --git a/curs_main.c b/curs_main.c -index 9d718ee..ea530a6 100644 ---- a/curs_main.c -+++ b/curs_main.c -@@ -26,7 +26,9 @@ +diff -urN mutt-1.6.1/configure.ac mutt-1.6.1-sidebar/configure.ac +--- mutt-1.6.1/configure.ac 2016-06-12 18:43:00.398447528 +0100 ++++ mutt-1.6.1-sidebar/configure.ac 2016-06-12 18:43:03.952502951 +0100 +@@ -175,6 +175,14 @@ + 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" ++ MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS sidebar.o" ++ fi ++]) ++ + 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-06-12 18:43:00.398447528 +0100 ++++ mutt-1.6.1-sidebar/copy.c 2016-06-12 18:43:03.952502951 +0100 +@@ -288,7 +288,8 @@ + 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), 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-06-12 18:43:00.399447544 +0100 ++++ mutt-1.6.1-sidebar/curs_main.c 2016-06-12 18:43:03.953502966 +0100 +@@ -26,8 +26,13 @@ #include "mailbox.h" #include "mapping.h" #include "sort.h" +#include "buffy.h" #include "mx.h" -+#include "sidebar.h" ++#ifdef USE_SIDEBAR ++#include "sidebar.h" ++#endif ++ #ifdef USE_POP #include "pop.h" -@@ -596,8 +598,12 @@ int mutt_index_menu (void) + #endif +@@ -595,21 +600,39 @@ menu->redraw |= REDRAW_STATUS; if (do_buffy_notify) { - if (mutt_buffy_notify () && option (OPTBEEPNEW)) - beep (); -+ if (mutt_buffy_notify ()) ++ if (mutt_buffy_notify()) + { -+ menu->redraw |= REDRAW_FULL; ++ menu->redraw |= REDRAW_STATUS; + if (option (OPTBEEPNEW)) -+ beep (); ++ beep(); + } } else do_buffy_notify = 1; -@@ -609,6 +615,7 @@ int mutt_index_menu (void) + } + ++#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); -+ draw_sidebar(menu->menu); ++#ifdef USE_SIDEBAR ++ mutt_sb_draw(); ++#endif mutt_show_error (); } ++#ifdef USE_SIDEBAR ++ else if (menu->redraw & REDRAW_SIDEBAR) { ++ mutt_sb_draw(); ++ menu->redraw &= ~REDRAW_SIDEBAR; ++ } ++#endif -@@ -631,9 +638,12 @@ int mutt_index_menu (void) + if (menu->menu == MENU_MAIN) + { +@@ -630,9 +653,20 @@ if (menu->redraw & REDRAW_STATUS) { -+ DrawFullLine = 1; ++#ifdef USE_SIDEBAR ++ /* Temporarily lie about the sidebar width */ ++ short sw = SidebarWidth; ++ SidebarWidth = 0; ++#endif menu_status_line (buf, sizeof (buf), menu, NONULL (Status)); -+ DrawFullLine = 0; ++#ifdef USE_SIDEBAR ++ SidebarWidth = sw; /* Restore the sidebar width */ ++#endif move (option (OPTSTATUSONTOP) ? 0 : LINES-2, 0); SETCOLOR (MT_COLOR_STATUS); -+ set_buffystats(Context); ++#ifdef USE_SIDEBAR ++ mutt_sb_set_buffystats (Context); ++#endif mutt_paddstr (COLS, buf); NORMAL_COLOR; menu->redraw &= ~REDRAW_STATUS; -@@ -653,7 +663,7 @@ int mutt_index_menu (void) +@@ -652,7 +686,7 @@ menu->oldcurrent = -1; if (option (OPTARROWCURSOR)) @@ -471,229 +625,1948 @@ index 9d718ee..ea530a6 100644 else if (option (OPTBRAILLEFRIENDLY)) move (menu->current - menu->top + menu->offset, 0); else -@@ -1154,6 +1164,7 @@ int mutt_index_menu (void) +@@ -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: -@@ -1185,7 +1196,11 @@ int mutt_index_menu (void) +@@ -1181,6 +1221,14 @@ { mutt_buffy (buf, sizeof (buf)); -- if (mutt_enter_fname (cp, buf, sizeof (buf), &menu->redraw, 1) == -1) -+ if ( op == OP_SIDEBAR_OPEN ) { -+ if(!CurBuffy) -+ break; -+ strncpy( buf, CurBuffy->path, sizeof(buf) ); -+ } else if (mutt_enter_fname (cp, buf, sizeof (buf), &menu->redraw, 1) == -1) ++#ifdef USE_SIDEBAR ++ if (op == OP_SIDEBAR_OPEN) { ++ const char *path = mutt_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) - { -@@ -1203,6 +1218,7 @@ int mutt_index_menu (void) +@@ -1199,6 +1247,9 @@ } mutt_expand_path (buf, sizeof (buf)); -+ set_curbuffy(buf); ++#ifdef USE_SIDEBAR ++ mutt_sb_set_open_buffy (buf); ++#endif if (mx_get_magic (buf) <= 0) { mutt_error (_("%s is not a mailbox."), buf); -@@ -2306,6 +2322,12 @@ int mutt_index_menu (void) +@@ -2310,6 +2361,21 @@ mutt_what_key(); break; -+ case OP_SIDEBAR_SCROLL_UP: -+ case OP_SIDEBAR_SCROLL_DOWN: ++#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: -+ scroll_sidebar(op, menu->menu); ++ case OP_SIDEBAR_PREV_NEW: ++ mutt_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 --git a/flags.c b/flags.c -index 133fa35..48fb287 100644 ---- a/flags.c -+++ b/flags.c -@@ -22,8 +22,10 @@ +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-06-12 18:43:00.402447590 +0100 ++++ mutt-1.6.1-sidebar/doc/manual.xml.head 2016-06-12 18:43:03.955502998 +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 + +@@ -6773,6 +7390,17 @@ + + + ++Mutt will set the COLUMNS environment variable to ++the width of the pager. Some programs make use of this environment ++variable automatically. Others provide a command line argument that ++can use this to set the output width: ++ ++ ++ ++text/html; lynx -dump -width ${COLUMNS:-80} %s; copiousoutput ++ ++ ++ + Note that when using the built-in pager, only + entries with this flag will be considered a handler for a MIME type + — all other entries will be ignored. +@@ -7467,6 +8095,16 @@ + + + ++ ++Mutt Patches ++ ++Mutt may also be patched to support smaller features. ++These patches should add a free-form string to the end Mutt's version string. ++Running mutt -v might show: ++patch-1.6.1.sidebar.20160502 ++ ++ ++ + + URL Syntax + +@@ -8081,6 +8719,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.6.1 ++ ++ ++ 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 +10338,17 @@ + + + ++sidebar_whitelist ++ ++item ++ ++ ++command ++ ++ ++ ++ ++ + source + + filename +diff -urN mutt-1.6.1/doc/mutt.css mutt-1.6.1-sidebar/doc/mutt.css +--- mutt-1.6.1/doc/mutt.css 2016-06-12 18:43:00.402447590 +0100 ++++ mutt-1.6.1-sidebar/doc/mutt.css 2016-06-12 18:43:03.811500752 +0100 +@@ -9,17 +9,24 @@ + div.table-contents table th, div.informaltable table th { + font-family:sans-serif; + background:#d0d0d0; +- font-weight:normal; ++ font-weight:bold; + vertical-align:top; + } +-div.cmdsynopsis { border-left:1px solid #707070; padding-left:5px; } ++div.cmdsynopsis { border-left:1px solid #707070; padding-left: 1em; } + li div.cmdsynopsis { border-left:none; padding-left:0px; } +-pre.screen, div.note { background:#f0f0f0; border:1px solid #c0c0c0; padding:5px; margin-left:2%; margin-right:2%; } ++li p { margin: 0; } ++pre.screen, div.note { border:1px solid #c0c0c0; margin-left:2%; margin-right:2%; } ++pre.screen { color: #ffffff; background:#000000; padding: 0.5em; } ++div.note { background:#ffff80; padding: 0.5em; } + div.example p.title { margin-left:2%; } + div.note h3 { font-size:small; font-style:italic; font-variant: small-caps; } + div.note h3:after { content: ":" } + div.note { margin-bottom: 5px; } +-.command { font-family: monospace; font-weight: normal; } ++div.literallayout, .command { font-family: monospace; font-weight: normal; } + .command strong { font-weight: normal; } + tr { vertical-align: top; } +-.comment { color:#707070; } ++.comment { color:#00c000; } ++code.literal { background: #f0f0f0; color: #000000; } ++span.indicator { background: #000060; color: #ffffff; } ++span.highlight { background: #404040; color: #ffffff; } ++span.reverse { background: #ffffff; color: #000000; } +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-06-12 18:43:03.812500768 +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-06-12 18:43:03.813500783 +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/filter.c mutt-1.6.1-sidebar/filter.c +--- mutt-1.6.1/filter.c 2016-06-12 18:43:00.403447606 +0100 ++++ mutt-1.6.1-sidebar/filter.c 2016-06-12 18:43:03.835501127 +0100 +@@ -21,6 +21,7 @@ + #endif #include "mutt.h" - #include "mutt_curses.h" -+#include "mutt_menu.h" ++#include "mutt_curses.h" + + #include + #include +@@ -34,6 +35,7 @@ + int fdin, int fdout, int fderr) + { + int pin[2], pout[2], perr[2], thepid; ++ char columns[11]; + + if (in) + { +@@ -117,6 +119,9 @@ + close (fderr); + } + ++ snprintf (columns, sizeof (columns), "%d", COLS - SidebarWidth); ++ setenv ("COLUMNS", columns, 1); ++ + execl (EXECSHELL, "sh", "-c", cmd, NULL); + _exit (127); + } +diff -urN mutt-1.6.1/flags.c mutt-1.6.1-sidebar/flags.c +--- mutt-1.6.1/flags.c 2016-06-12 18:43:00.403447606 +0100 ++++ mutt-1.6.1-sidebar/flags.c 2016-06-12 18:43:03.956503013 +0100 +@@ -25,6 +25,10 @@ #include "sort.h" #include "mx.h" -+#include "sidebar.h" ++#ifdef USE_SIDEBAR ++#include "sidebar.h" ++#endif ++ void _mutt_set_flag (CONTEXT *ctx, HEADER *h, int flag, int bf, int upd_ctx) { -@@ -290,6 +292,7 @@ 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; -+ draw_sidebar(0); ++#ifdef USE_SIDEBAR ++ mutt_sb_draw(); ++#endif } void mutt_tag_set_flag (int flag, int bf) -diff --git a/functions.h b/functions.h -index 26171a0..ef8937a 100644 ---- a/functions.h -+++ b/functions.h -@@ -170,6 +170,11 @@ const struct binding_t OpMain[] = { /* map: index */ +diff -urN mutt-1.6.1/functions.h mutt-1.6.1-sidebar/functions.h +--- mutt-1.6.1/functions.h 2016-06-12 18:43:00.403447606 +0100 ++++ mutt-1.6.1-sidebar/functions.h 2016-06-12 18:43:03.956503013 +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 -+ { "sidebar-scroll-up", OP_SIDEBAR_SCROLL_UP, NULL }, -+ { "sidebar-scroll-down", OP_SIDEBAR_SCROLL_DOWN, NULL }, -+ { "sidebar-next", OP_SIDEBAR_NEXT, NULL }, -+ { "sidebar-prev", OP_SIDEBAR_PREV, NULL }, -+ { "sidebar-open", OP_SIDEBAR_OPEN, NULL }, { NULL, 0, NULL } }; - -@@ -274,6 +279,11 @@ const struct binding_t OpPager[] = { /* map: pager */ +@@ -272,6 +282,17 @@ { "what-key", OP_WHAT_KEY, NULL }, -+ { "sidebar-scroll-up", OP_SIDEBAR_SCROLL_UP, NULL }, -+ { "sidebar-scroll-down", OP_SIDEBAR_SCROLL_DOWN, NULL }, -+ { "sidebar-next", OP_SIDEBAR_NEXT, NULL }, -+ { "sidebar-prev", OP_SIDEBAR_PREV, NULL }, -+ { "sidebar-open", OP_SIDEBAR_OPEN, 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 --git a/globals.h b/globals.h -index 282fde3..004c795 100644 ---- a/globals.h -+++ b/globals.h -@@ -118,6 +118,7 @@ WHERE short SearchContext; +diff -urN mutt-1.6.1/globals.h mutt-1.6.1-sidebar/globals.h +--- mutt-1.6.1/globals.h 2016-06-12 18:43:00.403447606 +0100 ++++ mutt-1.6.1-sidebar/globals.h 2016-06-12 18:43:03.956503013 +0100 +@@ -118,6 +118,12 @@ WHERE char *SendCharset; WHERE char *Sendmail; WHERE char *Shell; -+WHERE char *SidebarDelim; ++#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 +215,9 @@ WHERE short ScoreThresholdDelete; +@@ -214,6 +220,14 @@ WHERE short ScoreThresholdRead; WHERE short ScoreThresholdFlag; -+WHERE struct buffy_t *CurBuffy INITVAL(0); -+WHERE short DrawFullLine INITVAL(0); ++/* 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 --git a/imap/command.c b/imap/command.c -index 32f8417..d68e3ab 100644 ---- a/imap/command.c -+++ b/imap/command.c -@@ -1012,6 +1012,13 @@ static void cmd_parse_status (IMAP_DATA* idata, char* s) +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-06-12 18:43:00.405447637 +0100 ++++ mutt-1.6.1-sidebar/imap/command.c 2016-06-12 18:43:03.839501189 +0100 +@@ -1016,6 +1016,14 @@ opened */ status->uidnext = oldun; -+ /* Added to make the sidebar show the correct numbers */ -+ if (status->messages) -+ { -+ inc->msgcount = status->messages; -+ inc->msg_unread = status->unseen; -+ } ++#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 --git a/imap/imap.c b/imap/imap.c -index f476873..af3ac3d 100644 ---- a/imap/imap.c -+++ b/imap/imap.c -@@ -1529,7 +1529,7 @@ int imap_buffy_check (int force) +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-06-12 18:43:00.405447637 +0100 ++++ mutt-1.6.1-sidebar/imap/imap.c 2016-06-12 18:43:03.958503044 +0100 +@@ -1535,7 +1535,11 @@ - imap_munge_mbox_name (munged, sizeof (munged), name); + imap_munge_mbox_name (idata, munged, sizeof (munged), name); snprintf (command, sizeof (command), -- "STATUS %s (UIDNEXT UIDVALIDITY UNSEEN RECENT)", munged); ++#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 --git a/init.h b/init.h -index 35224c1..c664e5f 100644 ---- a/init.h -+++ b/init.h -@@ -2030,6 +2030,27 @@ struct option_t MuttVars[] = { - ** not used. - ** (PGP only) +diff -urN mutt-1.6.1/init.c mutt-1.6.1-sidebar/init.c +--- mutt-1.6.1/init.c 2016-06-12 18:43:00.406447652 +0100 ++++ mutt-1.6.1-sidebar/init.c 2016-06-12 18:43:03.959503060 +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-06-12 18:43:00.408447684 +0100 ++++ mutt-1.6.1-sidebar/init.h 2016-06-12 18:43:03.960503075 +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,147 @@ + ** Command to use when spawning a subshell. By default, the user's login + ** shell from \fC/etc/passwd\fP is used. */ -+ {"sidebar_delim", DT_STR, R_BOTH, UL &SidebarDelim, "|"}, ++#ifdef USE_SIDEBAR ++ { "sidebar_divider_char", DT_STR, R_BOTH, UL &SidebarDividerChar, UL "|" }, + /* + ** .pp -+ ** This specifies the delimiter between the sidebar (if visible) and -+ ** other screens. ++ ** 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 ++ ** .pp ++ ** 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 reduce 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 (left-side list of folders). -+ */ -+ { "sidebar_sort", DT_BOOL, R_BOTH, OPTSIDEBARSORT, 0 }, -+ /* ++ ** This specifies whether or not to show sidebar. The sidebar shows a list of ++ ** all your mailboxes. + ** .pp -+ ** This specifies whether or not to sort the sidebar alphabetically. ++ ** \fBSee also:\fP $$sidebar_format, $$sidebar_width + */ + { "sidebar_width", DT_NUM, R_BOTH, UL &SidebarWidth, 0 }, + /* + ** .pp -+ ** The width of the sidebar. ++ ** 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. + */ - { "pgp_use_gpg_agent", DT_BOOL, R_NONE, OPTUSEGPGAGENT, 0}, ++#endif + { "sig_dashes", DT_BOOL, R_NONE, OPTSIGDASHES, 1 }, /* ** .pp -diff --git a/mailbox.h b/mailbox.h -index 2b2c9a1..000503d 100644 ---- a/mailbox.h -+++ b/mailbox.h -@@ -27,6 +27,7 @@ +@@ -3652,6 +3794,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 +3896,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-06-12 18:43:00.408447684 +0100 ++++ mutt-1.6.1-sidebar/keymap.c 2016-06-12 18:43:03.960503075 +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-06-12 18:43:00.408447684 +0100 ++++ mutt-1.6.1-sidebar/mailbox.h 2016-06-12 18:43:03.960503075 +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 --git a/mbox.c b/mbox.c -index 6d3b6bd..fa82eb3 100644 ---- a/mbox.c -+++ b/mbox.c -@@ -104,6 +104,7 @@ int mmdf_parse_mailbox (CONTEXT *ctx) +diff -urN mutt-1.6.1/main.c mutt-1.6.1-sidebar/main.c +--- mutt-1.6.1/main.c 2016-06-12 18:43:00.409447699 +0100 ++++ mutt-1.6.1-sidebar/main.c 2016-06-12 18:43:03.961503091 +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 ++ mutt_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 ++ mutt_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-06-12 18:43:00.389447388 +0100 ++++ mutt-1.6.1-sidebar/Makefile.am 2016-06-12 18:43:03.944502826 +0100 +@@ -56,7 +56,7 @@ + mutt_idna.c mutt_sasl.c mutt_socket.c mutt_ssl.c mutt_ssl_gnutls.c \ + mutt_tunnel.c pgp.c pgpinvoke.c pgpkey.c pgplib.c pgpmicalg.c \ + pgppacket.c pop.c pop_auth.c pop_lib.c remailer.c resize.c sha1.c \ +- smime.c smtp.c utf8.c wcwidth.c \ ++ sidebar.c smime.c smtp.c utf8.c wcwidth.c \ + bcache.h browser.h hcache.h mbyte.h mutt_idna.h remailer.h url.h + + EXTRA_DIST = COPYRIGHT GPL OPS OPS.PGP OPS.CRYPT OPS.SMIME TODO UPDATING \ +@@ -71,7 +71,7 @@ + mbyte.h lib.h extlib.c pgpewrap.c smime_keys.pl pgplib.h \ + README.SSL smime.h group.h \ + muttbug pgppacket.h depcomp ascii.h BEWARE PATCHES patchlist.sh \ +- ChangeLog mkchangelog.sh mutt_idna.h \ ++ ChangeLog mkchangelog.sh mutt_idna.h sidebar.h OPS.sidebar \ + snprintf.c regex.c crypt-gpgme.h hcachever.sh.in sys_socket.h \ + txt2c.c txt2c.sh version.sh check_sec.sh + +@@ -129,9 +129,9 @@ + 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)/gen_defs $(srcdir)/OPS $(srcdir)/OPS.SIDEBAR $(srcdir)/OPS.PGP \ + $(srcdir)/OPS.MIX $(srcdir)/OPS.CRYPT $(srcdir)/OPS.SMIME \ + > keymap_alldefs.h + +diff -urN mutt-1.6.1/mbox.c mutt-1.6.1-sidebar/mbox.c +--- mutt-1.6.1/mbox.c 2016-06-12 18:43:00.409447699 +0100 ++++ mutt-1.6.1-sidebar/mbox.c 2016-06-12 18:43:03.961503091 +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; -@@ -255,6 +256,7 @@ int mbox_parse_mailbox (CONTEXT *ctx) +@@ -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 --git a/menu.c b/menu.c -index 27b5f8e..bc3a02f 100644 ---- a/menu.c -+++ b/menu.c -@@ -24,6 +24,7 @@ +diff -urN mutt-1.6.1/menu.c mutt-1.6.1-sidebar/menu.c +--- mutt-1.6.1/menu.c 2016-06-12 18:43:00.409447699 +0100 ++++ mutt-1.6.1-sidebar/menu.c 2016-06-12 18:43:03.961503091 +0100 +@@ -24,6 +24,9 @@ #include "mutt_curses.h" #include "mutt_menu.h" #include "mbyte.h" ++#ifdef USE_SIDEBAR +#include "sidebar.h" ++#endif - extern size_t UngetCount; + char* SearchBuffers[MENU_MAX]; -@@ -186,7 +187,7 @@ static void menu_pad_string (char *s, size_t n) +@@ -184,7 +187,7 @@ { char *scratch = safe_strdup (s); int shift = option (OPTARROWCURSOR) ? 3 : 0; @@ -702,15 +2575,17 @@ index 27b5f8e..bc3a02f 100644 mutt_format_string (s, n, cols, cols, FMT_LEFT, ' ', scratch, mutt_strlen (scratch), 1); s[n - 1] = 0; -@@ -239,6 +240,7 @@ void menu_redraw_index (MUTTMENU *menu) +@@ -237,6 +240,9 @@ int do_color; int attr; -+ draw_sidebar(1); ++#ifdef USE_SIDEBAR ++ mutt_sb_draw(); ++#endif for (i = menu->top; i < menu->top + menu->pagelen; i++) { if (i < menu->max) -@@ -249,7 +251,7 @@ void menu_redraw_index (MUTTMENU *menu) +@@ -247,7 +253,7 @@ menu_pad_string (buf, sizeof (buf)); ATTRSET(attr); @@ -719,16 +2594,19 @@ index 27b5f8e..bc3a02f 100644 do_color = 1; if (i == menu->current) -@@ -272,7 +274,7 @@ void menu_redraw_index (MUTTMENU *menu) +@@ -270,7 +276,11 @@ else { NORMAL_COLOR; -- CLEARLINE(i - menu->top + menu->offset); ++#ifdef USE_SIDEBAR + CLEARLINE_WIN(i - menu->top + menu->offset); ++#else + CLEARLINE(i - menu->top + menu->offset); ++#endif } } NORMAL_COLOR; -@@ -289,7 +291,7 @@ void menu_redraw_motion (MUTTMENU *menu) +@@ -287,7 +297,7 @@ return; } @@ -737,7 +2615,7 @@ index 27b5f8e..bc3a02f 100644 ATTRSET(menu->color (menu->oldcurrent)); if (option (OPTARROWCURSOR)) -@@ -301,13 +303,13 @@ void menu_redraw_motion (MUTTMENU *menu) +@@ -299,13 +309,13 @@ { menu_make_entry (buf, sizeof (buf), menu, menu->oldcurrent); menu_pad_string (buf, sizeof (buf)); @@ -753,7 +2631,7 @@ index 27b5f8e..bc3a02f 100644 } else { -@@ -320,7 +322,7 @@ void menu_redraw_motion (MUTTMENU *menu) +@@ -318,7 +328,7 @@ menu_make_entry (buf, sizeof (buf), menu, menu->current); menu_pad_string (buf, sizeof (buf)); SETCOLOR(MT_COLOR_INDICATOR); @@ -762,7 +2640,7 @@ index 27b5f8e..bc3a02f 100644 print_enriched_string (menu->color(menu->current), (unsigned char *) buf, 0); } menu->redraw &= REDRAW_STATUS; -@@ -332,7 +334,7 @@ void menu_redraw_current (MUTTMENU *menu) +@@ -330,7 +340,7 @@ char buf[LONG_STRING]; int attr = menu->color (menu->current); @@ -771,7 +2649,7 @@ index 27b5f8e..bc3a02f 100644 menu_make_entry (buf, sizeof (buf), menu, menu->current); menu_pad_string (buf, sizeof (buf)); -@@ -881,7 +883,7 @@ int mutt_menuLoop (MUTTMENU *menu) +@@ -873,7 +883,7 @@ if (option (OPTARROWCURSOR)) @@ -780,160 +2658,207 @@ index 27b5f8e..bc3a02f 100644 else if (option (OPTBRAILLEFRIENDLY)) move (menu->current - menu->top + menu->offset, 0); else -diff --git a/mh.c b/mh.c -index 63e12d2..4a84a99 100644 ---- a/mh.c -+++ b/mh.c -@@ -295,6 +295,28 @@ void mh_buffy(BUFFY *b) +diff -urN mutt-1.6.1/mh.c mutt-1.6.1-sidebar/mh.c +--- mutt-1.6.1/mh.c 2016-06-12 18:43:00.410447715 +0100 ++++ mutt-1.6.1-sidebar/mh.c 2016-06-12 18:43:03.962503107 +0100 +@@ -295,6 +295,48 @@ mhs_free_sequences (&mhs); } -+void mh_buffy_update (const char *path, int *msgcount, int *msg_unread, int *msg_flagged) ++#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) +{ + int i; + struct mh_sequences mhs; -+ memset (&mhs, 0, sizeof (mhs)); + -+ if (mh_read_sequences (&mhs, path) < 0) ++ if (!mailbox) + return; + -+ msgcount = 0; -+ msg_unread = 0; -+ msg_flagged = 0; ++ if (!option (OPTSIDEBAR)) ++ return; ++ ++ 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; ++ + for (i = 0; i <= mhs.max; i++) -+ msgcount++; -+ if (mhs_check (&mhs, i) & MH_SEQ_UNSEEN) { -+ msg_unread++; ++ { ++ 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++; + } -+ if (mhs_check (&mhs, i) & MH_SEQ_FLAGGED) -+ 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 --git a/mutt.h b/mutt.h -index 01d47de..5f25406 100644 ---- a/mutt.h -+++ b/mutt.h -@@ -435,6 +435,8 @@ enum - OPTSAVEEMPTY, - OPTSAVENAME, - OPTSCORE, -+ OPTSIDEBAR, -+ OPTSIDEBARSORT, - OPTSIGDASHES, - OPTSIGONTOP, - OPTSORTRE, -@@ -880,6 +882,7 @@ typedef struct _context - { - char *path; - FILE *fp; -+ time_t atime; - time_t mtime; - off_t size; - off_t vsize; -@@ -920,6 +923,7 @@ typedef struct _context - unsigned int quiet : 1; /* inhibit status messages? */ - unsigned int collapsed : 1; /* are all threads collapsed? */ - unsigned int closing : 1; /* mailbox is being closed */ -+ unsigned int peekonly : 1; /* just taking a glance, revert atime */ - - /* driver hooks */ - void *data; /* driver specific data */ -diff --git a/mutt_curses.h b/mutt_curses.h -index f8bc47c..ef9884e 100644 ---- a/mutt_curses.h -+++ b/mutt_curses.h -@@ -64,6 +64,7 @@ +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-06-12 18:43:00.410447715 +0100 ++++ mutt-1.6.1-sidebar/mutt_curses.h 2016-06-12 18:43:03.962503107 +0100 +@@ -64,6 +64,9 @@ #undef lines #endif /* lines */ -+#define CLEARLINE_WIN(x) move(x,SidebarWidth), clrtoeol() ++#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) -@@ -121,6 +122,8 @@ enum +@@ -124,6 +127,14 @@ MT_COLOR_UNDERLINE, MT_COLOR_INDEX, MT_COLOR_PROMPT, -+ MT_COLOR_NEW, ++#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 --git a/muttlib.c b/muttlib.c -index c1d565f..039e7c3 100644 ---- a/muttlib.c -+++ b/muttlib.c -@@ -1279,6 +1279,8 @@ void mutt_FormatString (char *dest, /* output buffer */ +@@ -163,12 +174,16 @@ + + static inline int mutt_term_width(short wrap) + { ++ int cols = COLS; ++#ifdef USE_SIDEBAR ++ cols -= SidebarWidth; ++#endif + if (wrap < 0) +- return COLS > -wrap ? COLS + wrap : COLS; ++ return cols > -wrap ? cols + wrap : cols; + else if (wrap) +- return wrap < COLS ? wrap : COLS; ++ return wrap < cols ? wrap : cols; + else +- return COLS; ++ return cols; + } + + extern int *ColorQuote; +diff -urN mutt-1.6.1/mutt.h mutt-1.6.1-sidebar/mutt.h +--- mutt-1.6.1/mutt.h 2016-06-12 18:43:00.410447715 +0100 ++++ mutt-1.6.1-sidebar/mutt.h 2016-06-12 18:43:03.962503107 +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-06-12 18:43:00.411447731 +0100 ++++ mutt-1.6.1-sidebar/muttlib.c 2016-06-12 18:43:03.963503122 +0100 +@@ -1282,7 +1282,7 @@ pl = pw = 1; /* see if there's room to add content, else ignore */ -+ if ( DrawFullLine ) -+ { - if ((col < COLS && wlen < destlen) || soft) +- if ((col < COLS && wlen < destlen) || soft) ++ if ((col < (COLS - SidebarWidth) && (wlen < destlen)) || soft) { int pad; -@@ -1322,6 +1324,52 @@ void mutt_FormatString (char *dest, /* output buffer */ - col += wid; - src += pl; - } -+ } -+ else -+ { -+ if ((col < COLS-SidebarWidth && wlen < destlen) || soft) -+ { -+ int pad; -+ -+ /* get contents after padding */ -+ mutt_FormatString (buf, sizeof (buf), 0, src + pl, callback, data, flags); -+ len = mutt_strlen (buf); -+ wid = mutt_strwidth (buf); -+ -+ /* try to consume as many columns as we can, if we don't have -+ * memory for that, use as much memory as possible */ + +@@ -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) -+ { -+ while (pad--) -+ { -+ memcpy (wptr, src, pl); -+ wptr += pl; -+ wlen += pl; -+ col += pw; -+ } -+ } -+ else if (soft && pad < 0) -+ { -+ /* \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, &wid); -+ /* truncate left so that right part fits completely in */ -+ wlen = mutt_wstr_trunc (dest, destlen - len, col + pad, &col); -+ wptr = dest + wlen; -+ } -+ if (len + wlen > destlen) + 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; -+ col += wid; -+ src += pl; -+ } -+ } - break; /* skip rest of input */ - } - else if (ch == '|') -diff --git a/mx.c b/mx.c -index 0a1a80e..e80b8ff 100644 ---- a/mx.c -+++ b/mx.c -@@ -595,6 +595,7 @@ static int mx_open_mailbox_append (CONTEXT *ctx, int flags) + 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-06-12 18:43:00.410447715 +0100 ++++ mutt-1.6.1-sidebar/mutt_menu.h 2016-06-12 18:43:03.962503107 +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-06-12 18:43:00.411447731 +0100 ++++ mutt-1.6.1-sidebar/mx.c 2016-06-12 18:43:03.963503122 +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 @@ -941,70 +2866,128 @@ index 0a1a80e..e80b8ff 100644 * ctx if non-null, context struct to use */ CONTEXT *mx_open_mailbox (const char *path, int flags, CONTEXT *pctx) -@@ -617,6 +618,8 @@ 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)) { -@@ -721,9 +724,21 @@ CONTEXT *mx_open_mailbox (const char *path, int flags, CONTEXT *pctx) - void mx_fastclose_mailbox (CONTEXT *ctx) - { - int i; -+#ifndef BUFFY_SIZE -+ struct utimbuf ut; -+#endif - +@@ -705,8 +713,21 @@ if(!ctx) return; -+#ifndef BUFFY_SIZE + ++#ifdef USE_SIDEBAR + /* fix up the times so buffy won't get confused */ -+ if (ctx->peekonly && ctx->path && ctx->mtime > ctx->atime) -+ { -+ ut.actime = ctx->atime; ++ struct utimbuf ut; ++ if (ctx->peekonly && ctx->path && (ctx->mtime > ctx->atime)) { ++ ut.actime = ctx->atime; + ut.modtime = ctx->mtime; -+ utime (ctx->path, &ut); ++ 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 */ -diff --git a/mx.h b/mx.h -index 2ef4ec7..4aabadf 100644 ---- a/mx.h -+++ b/mx.h -@@ -60,6 +60,7 @@ void mbox_reset_atime (CONTEXT *, struct stat *); ++#ifdef USE_SIDEBAR ++ if (!ctx->peekonly) ++#endif + mutt_buffy_setnotified(ctx->path); + + if (ctx->mx_close) +@@ -812,6 +833,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) +@@ -981,6 +1008,11 @@ + !mutt_is_spool(ctx->path) && !option (OPTSAVEEMPTY)) + mx_unlink_empty (ctx->path); + ++#ifdef USE_SIDEBAR ++ ctx->msgcount -= ctx->deleted; ++ mutt_sb_set_buffystats (ctx); ++#endif ++ + mx_fastclose_mailbox (ctx); + + return 0; +diff -urN mutt-1.6.1/mx.h mutt-1.6.1-sidebar/mx.h +--- mutt-1.6.1/mx.h 2016-06-12 18:43:00.411447731 +0100 ++++ mutt-1.6.1-sidebar/mx.h 2016-06-12 18:43:03.963503122 +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 *); -+void mh_buffy_update (const char *, int *, int *, int *); ++#ifdef USE_SIDEBAR ++void mh_buffy_update (BUFFY *mailbox); ++#endif int mh_check_empty (const char *); int maildir_read_dir (CONTEXT *); -diff --git a/pager.c b/pager.c -index c99f1e4..5cfcb75 100644 ---- a/pager.c -+++ b/pager.c -@@ -29,6 +29,7 @@ +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-06-12 18:43:03.944502826 +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-06-12 18:43:00.412447746 +0100 ++++ mutt-1.6.1-sidebar/pager.c 2016-06-12 18:43:03.964503138 +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" -@@ -1095,6 +1096,7 @@ static int format_line (struct line_t **lineInfo, int n, unsigned char *buf, - wchar_t wc; - mbstate_t mbstate; - int wrap_cols = mutt_term_width ((flags & M_PAGER_NOWRAP) ? 0 : Wrap); -+ wrap_cols -= SidebarWidth; +@@ -1491,7 +1494,7 @@ + * a newline (grr!). + */ + #ifndef USE_SLANG_CURSES +- if (col < COLS) ++ if (col < (COLS - SidebarWidth)) + #endif + addch ('\n'); - if (check_attachment_marker ((char *)buf) == 0) - wrap_cols = COLS; -@@ -1746,7 +1748,7 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) +@@ -1573,6 +1576,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 +1751,7 @@ if ((redraw & REDRAW_BODY) || topline != oldtopline) { do { @@ -1013,465 +2996,1455 @@ index c99f1e4..5cfcb75 100644 curline = oldtopline = topline; lines = 0; force_redraw = 0; -@@ -1759,6 +1761,7 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) +@@ -1760,6 +1764,9 @@ &QuoteList, &q_level, &force_redraw, &SearchRE) > 0) lines++; curline++; -+ move(lines + bodyoffset, SidebarWidth); ++#ifdef USE_SIDEBAR ++ move (lines + bodyoffset, SidebarWidth); ++#endif } last_offset = lineInfo[curline].offset; } while (force_redraw); -@@ -1771,6 +1774,7 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) +@@ -1772,6 +1779,9 @@ addch ('~'); addch ('\n'); lines++; -+ move(lines + bodyoffset, SidebarWidth); ++#ifdef USE_SIDEBAR ++ move (lines + bodyoffset, SidebarWidth); ++#endif } NORMAL_COLOR; -@@ -1794,22 +1798,22 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) +@@ -1789,29 +1799,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 = (COLS-SidebarWidth) * 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 (COLS-SidebarWidth, 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 (COLS-SidebarWidth, 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) -@@ -1826,16 +1830,21 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) + { +@@ -1827,16 +1857,26 @@ /* redraw the pager_index indicator, because the * flags for this message might have changed. */ menu_redraw_current (index); -+ draw_sidebar(MENU_PAGER); ++#ifdef USE_SIDEBAR ++ mutt_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)), SidebarWidth); ++ move (indexoffset + (option (OPTSTATUSONTOP) ? 0 : (indexlen - 1)), ++ (option(OPTSTATUSONTOP) ? 0: SidebarWidth)); SETCOLOR (MT_COLOR_STATUS); - mutt_paddstr (COLS, buffer); -+ mutt_paddstr (COLS-SidebarWidth, 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 ) -+ draw_sidebar(MENU_PAGER); ++ if (index == 0) ++ mutt_sb_draw(); ++#endif + redraw = 0; if (option(OPTBRAILLEFRIENDLY)) { -@@ -2776,6 +2785,13 @@ search_next: +@@ -2498,8 +2538,12 @@ + ch = 0; + } + +- if (option (OPTFORCEREDRAWPAGER)) ++ if (option (OPTFORCEREDRAWPAGER)) { + redraw = REDRAW_FULL; ++#ifdef USE_SIDEBAR ++ mutt_sb_draw(); ++#endif ++ } + unset_option (OPTFORCEREDRAWINDEX); + unset_option (OPTFORCEREDRAWPAGER); + break; +@@ -2777,6 +2821,22 @@ mutt_what_key (); break; -+ case OP_SIDEBAR_SCROLL_UP: -+ case OP_SIDEBAR_SCROLL_DOWN: ++#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: -+ scroll_sidebar(ch, MENU_PAGER); -+ break; ++ case OP_SIDEBAR_PREV_NEW: ++ mutt_sb_change_mailbox (ch); ++ break; ++ ++ case OP_SIDEBAR_TOGGLE_VISIBLE: ++ toggle_option (OPTSIDEBAR); ++ redraw = REDRAW_FULL; ++ break; ++#endif + default: ch = -1; break; -diff --git a/sidebar.c b/sidebar.c -new file mode 100644 -index 0000000..6098c2a ---- /dev/null -+++ b/sidebar.c -@@ -0,0 +1,333 @@ -+/* -+ * Copyright (C) ????-2004 Justin Hibbits +diff -urN mutt-1.6.1/PATCHES mutt-1.6.1-sidebar/PATCHES +--- mutt-1.6.1/PATCHES 2016-06-12 18:43:00.395447481 +0100 ++++ mutt-1.6.1-sidebar/PATCHES 2016-06-12 18:43:03.949502904 +0100 +@@ -0,0 +1 @@ ++patch-sidebar-neo-20160612 +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-06-12 18:43:03.792500456 +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.6.1 ++ ++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-06-14 18:46:00.000000000 +0100 +@@ -0,0 +1,1090 @@ ++/* 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 "mutt_menu.h" -+#include "mutt_curses.h" -+#include "sidebar.h" +#include "buffy.h" -+#include +#include "keymap.h" -+#include ++#include "mutt_curses.h" ++#include "mutt_menu.h" ++#include "sort.h" + -+/*BUFFY *CurBuffy = 0;*/ -+static BUFFY *TopBuffy = 0; -+static BUFFY *BottomBuffy = 0; -+static int known_lines = 0; ++/* 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 */ + -+static int quick_log10(int n) ++/* 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 string[32]; -+ sprintf(string, "%d", n); -+ return strlen(string); ++ char box[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; +} + -+void calc_boundaries (int menu) ++/** ++ * 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 *tmp = Incoming; ++ BUFFY *b = HilBuffy; ++ if (!b) ++ return NULL; + -+ if ( known_lines != LINES ) { -+ TopBuffy = BottomBuffy = 0; -+ known_lines = LINES; -+ } -+ for ( ; tmp->next != 0; tmp = tmp->next ) -+ tmp->next->prev = tmp; ++ do ++ { ++ b = b->prev; ++ if (!b && wrap) ++ b = Outgoing; ++ if (!b || (b == HilBuffy)) ++ break; ++ if (b->msg_unread > 0) ++ return b; ++ } while (b); + -+ if ( TopBuffy == 0 && BottomBuffy == 0 ) -+ TopBuffy = Incoming; -+ if ( BottomBuffy == 0 ) { -+ int count = LINES - 2 - (menu != MENU_PAGER || option(OPTSTATUSONTOP)); -+ BottomBuffy = TopBuffy; -+ while ( --count && BottomBuffy->next ) -+ BottomBuffy = BottomBuffy->next; -+ } -+ else if ( TopBuffy == CurBuffy->next ) { -+ int count = LINES - 2 - (menu != MENU_PAGER); -+ BottomBuffy = CurBuffy; -+ tmp = BottomBuffy; -+ while ( --count && tmp->prev) -+ tmp = tmp->prev; -+ TopBuffy = tmp; -+ } -+ else if ( BottomBuffy == CurBuffy->prev ) { -+ int count = LINES - 2 - (menu != MENU_PAGER); -+ TopBuffy = CurBuffy; -+ tmp = TopBuffy; -+ while ( --count && tmp->next ) -+ tmp = tmp->next; -+ BottomBuffy = tmp; -+ } ++ return NULL; +} + -+char *make_sidebar_entry(char *box, int size, int new, int flagged) ++/** ++ * 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) +{ -+ static char *entry = 0; -+ char *c; -+ int i = 0; -+ int delim_len = strlen(SidebarDelim); ++ struct sidebar_entry *sbe = (struct sidebar_entry *) data; ++ unsigned int optional; ++ char fmt[STRING]; + -+ c = realloc(entry, SidebarWidth - delim_len + 2); -+ if ( c ) entry = c; -+ entry[SidebarWidth - delim_len + 1] = 0; -+ for (; i < SidebarWidth - delim_len + 1; entry[i++] = ' ' ); -+ i = strlen(box); -+ strncpy( entry, box, i < (SidebarWidth - delim_len + 1) ? i : (SidebarWidth - delim_len + 1) ); ++ if (!sbe || !dest) ++ return src; + -+ if (size == -1) -+ sprintf(entry + SidebarWidth - delim_len - 3, "?"); -+ else if ( new ) { -+ if (flagged > 0) { -+ sprintf( -+ entry + SidebarWidth - delim_len - 5 - quick_log10(size) - quick_log10(new) - quick_log10(flagged), -+ "% d(%d)[%d]", size, new, flagged); -+ } else { -+ sprintf( -+ entry + SidebarWidth - delim_len - 3 - quick_log10(size) - quick_log10(new), -+ "% d(%d)", size, new); -+ } -+ } else if (flagged > 0) { -+ sprintf( entry + SidebarWidth - delim_len - 3 - quick_log10(size) - quick_log10(flagged), "% d[%d]", size, flagged); -+ } else { -+ sprintf( entry + SidebarWidth - delim_len - 1 - quick_log10(size), "% d", size); -+ } -+ return entry; ++ 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 (fmt, sizeof (fmt), "%d!", b->msg_flagged); ++ mutt_format_s (dest, destlen, prefix, fmt); ++ } ++ 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; +} + -+void set_curbuffy(char buf[LONG_STRING]) ++/** ++ * 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) +{ -+ BUFFY* tmp = CurBuffy = Incoming; ++ struct sidebar_entry sbe; + -+ if (!Incoming) ++ if (!buf || !box || !b) + return; + -+ while(1) { -+ if(!strcmp(tmp->path, buf)) { -+ CurBuffy = tmp; -+ break; -+ } ++ sbe.buffy = b; ++ strfcpy (sbe.box, box, sizeof (sbe.box)); + -+ if(tmp->next) -+ tmp = tmp->next; -+ else -+ break; ++ /* 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); ++ width = MIN(buflen, width); ++ 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; + } +} + -+int draw_sidebar(int menu) { ++/** ++ * 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; + -+ int lines = option(OPTHELP) ? 1 : 0; -+ BUFFY *tmp; -+#ifndef USE_SLANG_CURSES -+ attr_t attrs; -+#endif -+ short delim_len = strlen(SidebarDelim); -+ short color_pair; ++ /* Special case -- move hidden BUFFYs to the end */ ++ if (b1->is_hidden != b2->is_hidden) ++ { ++ if (b1->is_hidden) ++ return 1; ++ else ++ return -1; ++ } + -+ static bool initialized = false; -+ static int prev_show_value; -+ static short saveSidebarWidth; ++ int result = 0; + -+ /* initialize first time */ -+ if(!initialized) { -+ prev_show_value = option(OPTSIDEBAR); -+ saveSidebarWidth = SidebarWidth; -+ if(!option(OPTSIDEBAR)) SidebarWidth = 0; -+ initialized = true; -+ } ++ 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; ++ } + -+ /* save or restore the value SidebarWidth */ -+ if(prev_show_value != option(OPTSIDEBAR)) { -+ if(prev_show_value && !option(OPTSIDEBAR)) { -+ saveSidebarWidth = SidebarWidth; -+ SidebarWidth = 0; -+ } else if(!prev_show_value && option(OPTSIDEBAR)) { -+ SidebarWidth = saveSidebarWidth; -+ } -+ prev_show_value = option(OPTSIDEBAR); -+ } ++ if (SidebarSortMethod & SORT_REVERSE) ++ result = -result; + ++ return result; ++} + -+// if ( SidebarWidth == 0 ) return 0; -+ if (SidebarWidth > 0 && option (OPTSIDEBAR) -+ && delim_len >= SidebarWidth) { -+ unset_option (OPTSIDEBAR); -+ /* saveSidebarWidth = SidebarWidth; */ -+ if (saveSidebarWidth > delim_len) { -+ SidebarWidth = saveSidebarWidth; -+ mutt_error (_("Value for sidebar_delim is too long. Disabling sidebar.")); -+ sleep (2); -+ } else { -+ SidebarWidth = 0; -+ mutt_error (_("Value for sidebar_delim is too long. Disabling sidebar. Please set your sidebar_width to a sane value.")); -+ sleep (4); /* the advise to set a sane value should be seen long enough */ -+ } -+ saveSidebarWidth = 0; -+ return (0); -+ } ++/** ++ * 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 ( SidebarWidth == 0 || !option(OPTSIDEBAR)) { -+ if (SidebarWidth > 0) { -+ saveSidebarWidth = SidebarWidth; -+ SidebarWidth = 0; -+ } -+ unset_option(OPTSIDEBAR); -+ return 0; ++ 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)); ++ ++ 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; + } + -+ /* get attributes for divider */ -+ SETCOLOR(MT_COLOR_STATUS); -+#ifndef USE_SLANG_CURSES -+ attr_get(&attrs, &color_pair, 0); -+#else -+ color_pair = attr_get(); -+#endif -+ SETCOLOR(MT_COLOR_NORMAL); ++ /* compute length of Maildir without trailing separator */ ++ size_t maildirlen = strlen (Maildir); ++ if (SidebarDelimChars && strchr (SidebarDelimChars, Maildir[maildirlen - 1])) ++ maildirlen--; + -+ /* draw the divider */ ++ /* 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; + -+ for ( ; lines < LINES-1-(menu != MENU_PAGER || option(OPTSTATUSONTOP)); lines++ ) { -+ move(lines, SidebarWidth - delim_len); -+ addstr(NONULL(SidebarDelim)); -+#ifndef USE_SLANG_CURSES -+ mvchgat(lines, SidebarWidth - delim_len, delim_len, 0, color_pair, NULL); -+#endif -+ } -+ -+ if ( Incoming == 0 ) return 0; -+ lines = option(OPTHELP) ? 1 : 0; /* go back to the top */ -+ -+ if ( known_lines != LINES || TopBuffy == 0 || BottomBuffy == 0 ) -+ calc_boundaries(menu); -+ if ( CurBuffy == 0 ) CurBuffy = Incoming; -+ -+ tmp = TopBuffy; -+ -+ SETCOLOR(MT_COLOR_NORMAL); -+ -+ for ( ; tmp && lines < LINES-1 - (menu != MENU_PAGER || option(OPTSTATUSONTOP)); tmp = tmp->next ) { -+ if ( tmp == CurBuffy ) -+ SETCOLOR(MT_COLOR_INDICATOR); -+ else if ( tmp->msg_unread > 0 ) -+ SETCOLOR(MT_COLOR_NEW); -+ else if ( tmp->msg_flagged > 0 ) -+ SETCOLOR(MT_COLOR_FLAGGED); -+ else -+ SETCOLOR(MT_COLOR_NORMAL); -+ -+ move( lines, 0 ); -+ if ( Context && !strcmp( tmp->path, Context->path ) ) { -+ tmp->msg_unread = Context->unread; -+ tmp->msgcount = Context->msgcount; -+ tmp->msg_flagged = Context->flagged; -+ } -+ // check whether Maildir is a prefix of the current folder's path -+ short maildir_is_prefix = 0; -+ if ( (strlen(tmp->path) > strlen(Maildir)) && -+ (strncmp(Maildir, tmp->path, strlen(Maildir)) == 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; -+ sidebar_folder_name = basename(tmp->path); -+ if ( maildir_is_prefix ) { -+ char *tmp_folder_name; -+ int i; -+ tmp_folder_name = tmp->path + strlen(Maildir); -+ for (i = 0; i < strlen(tmp->path) - strlen(Maildir); i++) { -+ if (tmp_folder_name[i] == '/') sidebar_folder_depth++; -+ } -+ if (sidebar_folder_depth > 0) { -+ sidebar_folder_name = malloc(strlen(basename(tmp->path)) + sidebar_folder_depth + 1); -+ for (i=0; i < sidebar_folder_depth; i++) -+ sidebar_folder_name[i]=' '; -+ sidebar_folder_name[i]=0; -+ strncat(sidebar_folder_name, basename(tmp->path), strlen(basename(tmp->path)) + sidebar_folder_depth); -+ } -+ } -+ printw( "%.*s", SidebarWidth - delim_len + 1, -+ make_sidebar_entry(sidebar_folder_name, tmp->msgcount, -+ tmp->msg_unread, tmp->msg_flagged)); -+ if (sidebar_folder_depth > 0) -+ free(sidebar_folder_name); -+ lines++; -+ } -+ SETCOLOR(MT_COLOR_NORMAL); -+ for ( ; lines < LINES-1 - (menu != MENU_PAGER || option(OPTSTATUSONTOP)); lines++ ) { -+ int i = 0; -+ move( lines, 0 ); -+ for ( ; i < SidebarWidth - delim_len; i++ ) -+ addch(' '); -+ } -+ return 0; -+} -+ -+ -+void set_buffystats(CONTEXT* Context) -+{ -+ BUFFY *tmp = Incoming; -+ while(tmp) { -+ if(Context && !strcmp(tmp->path, Context->path)) { -+ tmp->msg_unread = Context->unread; -+ tmp->msgcount = Context->msgcount; -+ break; -+ } -+ tmp = tmp->next; ++ /* 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[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); +} + -+void scroll_sidebar(int op, int menu) ++ ++/** ++ * mutt_sb_init - Set some default values for the sidebar. ++ */ ++void ++mutt_sb_init (void) +{ -+ if(!SidebarWidth) return; -+ if(!CurBuffy) return; -+ -+ switch (op) { -+ case OP_SIDEBAR_NEXT: -+ if ( CurBuffy->next == NULL ) return; -+ CurBuffy = CurBuffy->next; -+ break; -+ case OP_SIDEBAR_PREV: -+ if ( CurBuffy->prev == NULL ) return; -+ CurBuffy = CurBuffy->prev; -+ break; -+ case OP_SIDEBAR_SCROLL_UP: -+ CurBuffy = TopBuffy; -+ if ( CurBuffy != Incoming ) { -+ calc_boundaries(menu); -+ CurBuffy = CurBuffy->prev; -+ } -+ break; -+ case OP_SIDEBAR_SCROLL_DOWN: -+ CurBuffy = BottomBuffy; -+ if ( CurBuffy->next ) { -+ calc_boundaries(menu); -+ CurBuffy = CurBuffy->next; -+ } -+ break; -+ default: -+ return; -+ } -+ calc_boundaries(menu); -+ draw_sidebar(menu); ++ OldVisible = option (OPTSIDEBAR); ++ if (SidebarWidth > 0) ++ { ++ OldWidth = SidebarWidth; ++ } ++ else ++ { ++ OldWidth = 20; ++ if (OldVisible) ++ { ++ SidebarWidth = OldWidth; ++ } ++ } +} + -diff --git a/sidebar.h b/sidebar.h -new file mode 100644 -index 0000000..d195f11 ---- /dev/null -+++ b/sidebar.h ++/** ++ * mutt_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 mutt_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 x = getcurx (stdscr); ++ int y = getcury (stdscr); ++ ++ 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); ++ move (y, x); ++} ++ ++/** ++ * mutt_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 mutt_sb_should_refresh (void) ++{ ++ if (!option (OPTSIDEBAR)) ++ return 0; ++ ++ if (SidebarRefreshTime == 0) ++ return 0; ++ ++ time_t diff = (time (NULL) - LastRefresh); ++ ++ return (diff >= SidebarRefreshTime); ++} ++ ++/** ++ * mutt_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 mutt_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)) ++ mutt_sb_draw(); ++} ++ ++/** ++ * mutt_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 mutt_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; ++ } ++ } ++} ++ ++/** ++ * mutt_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 *mutt_sb_get_highlight (void) ++{ ++ if (!HilBuffy) ++ return NULL; ++ ++ return HilBuffy->path; ++} ++ ++/** ++ * mutt_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 *mutt_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; ++} ++ ++/** ++ * mutt_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 mutt_sb_set_update_time (void) ++{ ++ /* XXX - should this be public? */ ++ ++ LastRefresh = time (NULL); ++} ++ ++/** ++ * mutt_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 mutt_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 ++ { ++ BUFFY *replacement = buffy_going (b); ++ if (TopBuffy == b) ++ TopBuffy = replacement; ++ if (OpnBuffy == b) ++ OpnBuffy = NULL; ++ if (HilBuffy == b) ++ HilBuffy = replacement; ++ if (BotBuffy == b) ++ BotBuffy = replacement; ++ if (Outgoing == b) ++ Outgoing = replacement; ++ } ++} +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-06-12 18:43:03.967503185 +0100 @@ -0,0 +1,36 @@ -+/* -+ * Copyright (C) ????-2004 Justin Hibbits ++/* 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 + -+struct MBOX_LIST { -+ char *path; -+ int msgcount; -+ int new; -+} MBLIST; ++#include "mutt.h" ++#include "buffy.h" + -+/* parameter is whether or not to go to the status line */ -+/* used for omitting the last | that covers up the status bar in the index */ -+int draw_sidebar(int); -+void scroll_sidebar(int, int); -+void set_curbuffy(char*); -+void set_buffystats(CONTEXT*); ++void mutt_sb_change_mailbox (int op); ++void mutt_sb_draw (void); ++const char * mutt_sb_get_highlight (void); ++void mutt_sb_init (void); ++void mutt_sb_notify_mailbox (BUFFY *b, int created); ++void mutt_sb_set_buffystats (const CONTEXT *ctx); ++BUFFY * mutt_sb_set_open_buffy (const char *path); ++void mutt_sb_set_update_time (void); ++int mutt_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-06-12 18:43:00.415447793 +0100 ++++ mutt-1.6.1-sidebar/sort.h 2016-06-12 18:43:03.968503200 +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); diff --git a/pkgs/applications/networking/mailreaders/mutt/trash-folder.patch b/pkgs/applications/networking/mailreaders/mutt/trash-folder.patch deleted file mode 100644 index ce47b0c30e5..00000000000 --- a/pkgs/applications/networking/mailreaders/mutt/trash-folder.patch +++ /dev/null @@ -1,316 +0,0 @@ -From: Cedric Duval -Date: Thu, 27 Feb 2014 12:27:41 +0100 -Subject: trash-folder - -With this patch, if the trash variable is set to a path (unset by default), the -deleted mails will be moved to a trash folder instead of being irremediably -purged when syncing the mailbox. - -For instance, set trash="~/Mail/trash" will cause every deleted mail to go to -this folder. - -Note that the append to the trash folder doesn't occur until the resync is -done. This allows you to change your mind and undo deletes, and thus the moves -to the trash folder are unnecessary. - -Notes - - * You might also want to have a look at the purge message feature below - which is related to this patch. - * IMAP is now supported. To retain the previous behavior, add this to your - muttrc: - folder-hook ^imap:// 'unset trash' - -FAQ - -Every once in a while, someone asks what are the advantages of this patch over -a macro based solution. Here's an attempt to answer this question: - - * The folder history doesn't clutter up with unwanted trash entries. - * Delayed move to the trash allows to change one's mind. - * No need to treat the case of "normal folders" and trash folders - separately with folder-hooks, and to create two sets of macros (one for - the index, one for the pager). - * Works not only with delete-message, but also with every deletion - functions like delete-pattern, delete-thread or delete-subthread. - -To sum up, it's more integrated and transparent to the user. - -* Patch last synced with upstream: - - Date: 2007-02-15 - - File: http://cedricduval.free.fr/mutt/patches/download/patch-1.5.5.1.cd.trash_folder.3.4 - -* Changes made: - - Updated to 1.5.13: - - structure of _mutt_save_message changed (commands.c) - - context of option (OPTCONFIRMAPPEND) changed (muttlib.c) - - Fixed indentation of "appended" in mutt.h. - -Signed-off-by: Matteo F. Vescovi - -Gbp-Pq: Topic features ---- - commands.c | 1 + - flags.c | 19 +++++++++++++++++- - globals.h | 1 + - imap/message.c | 2 ++ - init.h | 10 ++++++++++ - mutt.h | 3 +++ - muttlib.c | 4 +++- - mx.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - postpone.c | 3 +++ - 9 files changed, 103 insertions(+), 2 deletions(-) - -diff --git a/commands.c b/commands.c -index 5dbd100..7fd014b 100644 ---- a/commands.c -+++ b/commands.c -@@ -720,6 +720,7 @@ int _mutt_save_message (HEADER *h, CONTEXT *ctx, int delete, int decode, int dec - if (option (OPTDELETEUNTAG)) - mutt_set_flag (Context, h, M_TAG, 0); - } -+ mutt_set_flag (Context, h, M_APPENDED, 1); - - return 0; - } -diff --git a/flags.c b/flags.c -index f0f3d81..dfa6a50 100644 ---- a/flags.c -+++ b/flags.c -@@ -65,7 +65,13 @@ void _mutt_set_flag (CONTEXT *ctx, HEADER *h, int flag, int bf, int upd_ctx) - { - h->deleted = 0; - update = 1; -- if (upd_ctx) ctx->deleted--; -+ if (upd_ctx) -+ { -+ ctx->deleted--; -+ if (h->appended) -+ ctx->appended--; -+ } -+ h->appended = 0; /* when undeleting, also reset the appended flag */ - #ifdef USE_IMAP - /* see my comment above */ - if (ctx->magic == M_IMAP) -@@ -87,6 +93,17 @@ void _mutt_set_flag (CONTEXT *ctx, HEADER *h, int flag, int bf, int upd_ctx) - } - break; - -+ case M_APPENDED: -+ if (bf) -+ { -+ if (!h->appended) -+ { -+ h->appended = 1; -+ if (upd_ctx) ctx->appended++; -+ } -+ } -+ break; -+ - case M_NEW: - - if (!mutt_bit_isset(ctx->rights,M_ACL_SEEN)) -diff --git a/globals.h b/globals.h -index e77030c..6a1b8da 100644 ---- a/globals.h -+++ b/globals.h -@@ -144,6 +144,7 @@ WHERE char *Tochars; - WHERE char *TSStatusFormat; - WHERE char *TSIconFormat; - WHERE short TSSupported; -+WHERE char *TrashPath; - WHERE char *Username; - WHERE char *Visual; - -diff --git a/imap/message.c b/imap/message.c -index 3877381..039fda6 100644 ---- a/imap/message.c -+++ b/imap/message.c -@@ -884,6 +884,7 @@ int imap_copy_messages (CONTEXT* ctx, HEADER* h, char* dest, int delete) - if (ctx->hdrs[n]->tagged) - { - mutt_set_flag (ctx, ctx->hdrs[n], M_DELETE, 1); -+ mutt_set_flag (ctx, ctx->hdrs[n], M_APPENDED, 1); - if (option (OPTDELETEUNTAG)) - mutt_set_flag (ctx, ctx->hdrs[n], M_TAG, 0); - } -@@ -891,6 +892,7 @@ int imap_copy_messages (CONTEXT* ctx, HEADER* h, char* dest, int delete) - else - { - mutt_set_flag (ctx, h, M_DELETE, 1); -+ mutt_set_flag (ctx, h, M_APPENDED, 1); - if (option (OPTDELETEUNTAG)) - mutt_set_flag (ctx, h, M_TAG, 0); - } -diff --git a/init.h b/init.h -index 6b49341..d3206f9 100644 ---- a/init.h -+++ b/init.h -@@ -3341,6 +3341,16 @@ struct option_t MuttVars[] = { - ** provided that ``$$ts_enabled'' has been set. This string is identical in - ** formatting to the one used by ``$$status_format''. - */ -+ { "trash", DT_PATH, R_NONE, UL &TrashPath, 0 }, -+ /* -+ ** .pp -+ ** If set, this variable specifies the path of the trash folder where the -+ ** mails marked for deletion will be moved, instead of being irremediably -+ ** purged. -+ ** .pp -+ ** NOTE: When you delete a message in the trash folder, it is really -+ ** deleted, so that you have a way to clean the trash. -+ */ - #ifdef USE_SOCKET - { "tunnel", DT_STR, R_NONE, UL &Tunnel, UL 0 }, - /* -diff --git a/mutt.h b/mutt.h -index f8565fa..29bb6c2 100644 ---- a/mutt.h -+++ b/mutt.h -@@ -185,6 +185,7 @@ enum - M_DELETE, - M_UNDELETE, - M_DELETED, -+ M_APPENDED, - M_FLAG, - M_TAG, - M_UNTAG, -@@ -713,6 +714,7 @@ typedef struct header - unsigned int mime : 1; /* has a MIME-Version header? */ - unsigned int flagged : 1; /* marked important? */ - unsigned int tagged : 1; -+ unsigned int appended : 1; /* has been saved */ - unsigned int deleted : 1; - unsigned int changed : 1; - unsigned int attach_del : 1; /* has an attachment marked for deletion */ -@@ -885,6 +887,7 @@ typedef struct _context - int new; /* how many new messages? */ - int unread; /* how many unread messages? */ - int deleted; /* how many deleted messages */ -+ int appended; /* how many saved messages? */ - int flagged; /* how many flagged messages */ - int msgnotreadyet; /* which msg "new" in pager, -1 if none */ - -diff --git a/muttlib.c b/muttlib.c -index 02067cc..0fd9766 100644 ---- a/muttlib.c -+++ b/muttlib.c -@@ -1505,7 +1505,9 @@ int mutt_save_confirm (const char *s, struct stat *st) - - if (magic > 0 && !mx_access (s, W_OK)) - { -- if (option (OPTCONFIRMAPPEND)) -+ if (option (OPTCONFIRMAPPEND) && -+ (!TrashPath || (mutt_strcmp (s, TrashPath) != 0))) -+ /* if we're appending to the trash, there's no point in asking */ - { - snprintf (tmp, sizeof (tmp), _("Append messages to %s?"), s); - if ((rc = mutt_yesorno (tmp, M_YES)) == M_NO) -diff --git a/mx.c b/mx.c -index 4c5cb07..c0a6d30 100644 ---- a/mx.c -+++ b/mx.c -@@ -776,6 +776,53 @@ static int sync_mailbox (CONTEXT *ctx, int *index_hint) - return rc; - } - -+/* move deleted mails to the trash folder */ -+static int trash_append (CONTEXT *ctx) -+{ -+ CONTEXT *ctx_trash; -+ int i = 0; -+ struct stat st, stc; -+ -+ if (!TrashPath || !ctx->deleted || -+ (ctx->magic == M_MAILDIR && option (OPTMAILDIRTRASH))) -+ return 0; -+ -+ for (;i < ctx->msgcount && (!ctx->hdrs[i]->deleted || -+ ctx->hdrs[i]->appended); i++); -+ if (i == ctx->msgcount) -+ return 0; /* nothing to be done */ -+ -+ if (mutt_save_confirm (TrashPath, &st) != 0) -+ { -+ mutt_error _("message(s) not deleted"); -+ return -1; -+ } -+ -+ if (lstat (ctx->path, &stc) == 0 && stc.st_ino == st.st_ino -+ && stc.st_dev == st.st_dev && stc.st_rdev == st.st_rdev) -+ return 0; /* we are in the trash folder: simple sync */ -+ -+ if ((ctx_trash = mx_open_mailbox (TrashPath, M_APPEND, NULL)) != NULL) -+ { -+ for (i = 0 ; i < ctx->msgcount ; i++) -+ if (ctx->hdrs[i]->deleted && !ctx->hdrs[i]->appended -+ && mutt_append_message (ctx_trash, ctx, ctx->hdrs[i], 0, 0) == -1) -+ { -+ mx_close_mailbox (ctx_trash, NULL); -+ return -1; -+ } -+ -+ mx_close_mailbox (ctx_trash, NULL); -+ } -+ else -+ { -+ mutt_error _("Can't open trash folder"); -+ return -1; -+ } -+ -+ return 0; -+} -+ - /* save changes and close mailbox */ - int mx_close_mailbox (CONTEXT *ctx, int *index_hint) - { -@@ -912,6 +959,7 @@ int mx_close_mailbox (CONTEXT *ctx, int *index_hint) - if (mutt_append_message (&f, ctx, ctx->hdrs[i], 0, CH_UPDATE_LEN) == 0) - { - mutt_set_flag (ctx, ctx->hdrs[i], M_DELETE, 1); -+ mutt_set_flag (ctx, ctx->hdrs[i], M_APPENDED, 1); - } - else - { -@@ -936,6 +984,14 @@ int mx_close_mailbox (CONTEXT *ctx, int *index_hint) - return 0; - } - -+ /* copy mails to the trash before expunging */ -+ if (purge && ctx->deleted && mutt_strcmp(ctx->path, TrashPath)) -+ if (trash_append (ctx) != 0) -+ { -+ ctx->closing = 0; -+ return -1; -+ } -+ - #ifdef USE_IMAP - /* allow IMAP to preserve the deleted flag across sessions */ - if (ctx->magic == M_IMAP) -@@ -1133,6 +1189,12 @@ int mx_sync_mailbox (CONTEXT *ctx, int *index_hint) - msgcount = ctx->msgcount; - deleted = ctx->deleted; - -+ if (purge && ctx->deleted && mutt_strcmp(ctx->path, TrashPath)) -+ { -+ if (trash_append (ctx) == -1) -+ return -1; -+ } -+ - #ifdef USE_IMAP - if (ctx->magic == M_IMAP) - rc = imap_sync_mailbox (ctx, purge, index_hint); -diff --git a/postpone.c b/postpone.c -index a703161..7a4cbb1 100644 ---- a/postpone.c -+++ b/postpone.c -@@ -277,6 +277,9 @@ int mutt_get_postponed (CONTEXT *ctx, HEADER *hdr, HEADER **cur, char *fcc, size - /* finished with this message, so delete it. */ - mutt_set_flag (PostContext, h, M_DELETE, 1); - -+ /* and consider it saved, so that it won't be moved to the trash folder */ -+ mutt_set_flag (PostContext, h, M_APPENDED, 1); -+ - /* update the count for the status display */ - PostCount = PostContext->msgcount - PostContext->deleted; - diff --git a/pkgs/applications/networking/mailreaders/mutt/trash.patch b/pkgs/applications/networking/mailreaders/mutt/trash.patch new file mode 100644 index 00000000000..a7bda4c4c8b --- /dev/null +++ b/pkgs/applications/networking/mailreaders/mutt/trash.patch @@ -0,0 +1,797 @@ +diff -urN mutt-1.6.1/commands.c mutt-1.6.1-trash/commands.c +--- mutt-1.6.1/commands.c 2016-06-12 18:43:00.397447512 +0100 ++++ mutt-1.6.1-trash/commands.c 2016-06-12 18:43:04.892517610 +0100 +@@ -720,6 +720,7 @@ + if (option (OPTDELETEUNTAG)) + mutt_set_flag (Context, h, M_TAG, 0); + } ++ mutt_set_flag (Context, h, M_APPENDED, 1); + + return 0; + } +diff -urN mutt-1.6.1/curs_main.c mutt-1.6.1-trash/curs_main.c +--- mutt-1.6.1/curs_main.c 2016-06-12 18:43:00.399447544 +0100 ++++ mutt-1.6.1-trash/curs_main.c 2016-06-12 18:43:04.895517656 +0100 +@@ -1919,6 +1919,7 @@ + MAYBE_REDRAW (menu->redraw); + break; + ++ case OP_PURGE_MESSAGE: + case OP_DELETE: + + CHECK_MSGCOUNT; +@@ -1930,6 +1931,7 @@ + if (tag) + { + mutt_tag_set_flag (M_DELETE, 1); ++ mutt_tag_set_flag (M_PURGED, (op != OP_PURGE_MESSAGE) ? 0 : 1); + if (option (OPTDELETEUNTAG)) + mutt_tag_set_flag (M_TAG, 0); + menu->redraw = REDRAW_INDEX; +@@ -1937,6 +1939,8 @@ + else + { + mutt_set_flag (Context, CURHDR, M_DELETE, 1); ++ mutt_set_flag (Context, CURHDR, M_PURGED, ++ (op != OP_PURGE_MESSAGE) ? 0 : 1); + if (option (OPTDELETEUNTAG)) + mutt_set_flag (Context, CURHDR, M_TAG, 0); + if (option (OPTRESOLVE)) +@@ -2242,11 +2246,13 @@ + if (tag) + { + mutt_tag_set_flag (M_DELETE, 0); ++ mutt_tag_set_flag (M_PURGED, 0); + menu->redraw = REDRAW_INDEX; + } + else + { + mutt_set_flag (Context, CURHDR, M_DELETE, 0); ++ mutt_set_flag (Context, CURHDR, M_PURGED, 0); + if (option (OPTRESOLVE) && menu->current < Context->vcount - 1) + { + menu->current++; +@@ -2268,9 +2274,11 @@ + CHECK_ACL(M_ACL_DELETE, _("Cannot undelete message(s)")); + + rc = mutt_thread_set_flag (CURHDR, M_DELETE, 0, +- op == OP_UNDELETE_THREAD ? 0 : 1); ++ op == OP_UNDELETE_THREAD ? 0 : 1) ++ + mutt_thread_set_flag (CURHDR, M_PURGED, 0, ++ (op == OP_UNDELETE_THREAD) ? 0 : 1); + +- if (rc != -1) ++ if (rc > -1) + { + if (option (OPTRESOLVE)) + { +diff -urN mutt-1.6.1/doc/manual.xml.head mutt-1.6.1-trash/doc/manual.xml.head +--- mutt-1.6.1/doc/manual.xml.head 2016-06-12 18:43:00.402447590 +0100 ++++ mutt-1.6.1-trash/doc/manual.xml.head 2016-06-12 18:43:04.901517750 +0100 +@@ -7467,6 +7467,16 @@ + +
+ ++ ++Mutt Patches ++ ++Mutt may also be patched to support smaller features. ++These patches should add a free-form string to the end Mutt's version string. ++Running mutt -v might show: ++patch-1.6.1.sidebar.20160502 ++ ++ ++ + + URL Syntax + +@@ -8081,6 +8091,175 @@ + + + ++ ++ Trash Folder Patch ++ Automatically move "deleted" emails to a trash bin ++ ++ ++ Patch ++ ++ ++ To check if Mutt supports Trash Folder, look for ++ patch-trash in the mutt version. ++ See: . ++ ++ ++ If IMAP is enabled, this patch will use it ++ ++ ++ Dependencies: ++ mutt-1.6.1 ++ IMAP support ++ ++ ++ This patch is part of the NeoMutt Project. ++ ++ ++ ++ Introduction ++ ++ ++ In Mutt, when you delete an email it is first marked ++ deleted. The email isn't really gone until ++ <sync-mailbox> is called. ++ This happens when the user leaves the folder, or the function is called ++ manually. ++ ++ ++ ++ After <sync-mailbox> has been called the email is gone forever. ++ ++ ++ ++ The $trash variable defines a folder in ++ which to keep old emails. As before, first you mark emails for ++ deletion. When <sync-mailbox> is called the emails are moved to ++ the trash folder. ++ ++ ++ ++ The $trash path can be either a full directory, ++ or be relative to the $folder ++ variable, like the mailboxes command. ++ ++ ++ ++ Emails deleted from the trash folder are gone forever. ++ ++ ++ ++ ++ Variables ++ ++ Trash Variables ++ ++ ++ ++ Name ++ Type ++ Default ++ ++ ++ ++ ++ trash ++ string ++ (none) ++ ++ ++ ++
++
++ ++ ++ Functions ++ ++ Trash Functions ++ ++ ++ ++ Menus ++ Default Key ++ Function ++ Description ++ ++ ++ ++ ++ index,pager ++ (none) ++ <purge-message> ++ really delete the current entry, bypassing the trash folder ++ ++ ++ ++
++
++ ++ ++ ++ ++ Muttrc ++ ++# Example Mutt config file for the 'trash' feature. ++ ++# This feature defines a new 'trash' folder. ++# When mail is deleted it will be moved to this folder. ++ ++# Folder in which to put deleted emails ++set trash='+Trash' ++set trash='/home/flatcap/Mail/Trash' ++ ++# The default delete key 'd' will move an email to the 'trash' folder ++# Bind 'D' to REALLY delete an email ++bind index D purge-message ++ ++# Note: Deleting emails from the 'trash' folder will REALLY delete them. ++ ++# vim: syntax=muttrc ++ ++ ++ ++ ++ See Also ++ ++ ++ NeoMutt Project ++ folder-hook ++ ++ ++ ++ ++ Known Bugs ++ None ++ ++ ++ ++ Credits ++ ++ Cedric Duval cedricduval@free.fr ++ Benjamin Kuperman kuperman@acm.org ++ Paul Miller paul@voltar.org ++ Richard Russon rich@flatcap.org ++ ++ ++
++ + + + +diff -urN mutt-1.6.1/doc/muttrc.trash mutt-1.6.1-trash/doc/muttrc.trash +--- mutt-1.6.1/doc/muttrc.trash 1970-01-01 01:00:00.000000000 +0100 ++++ mutt-1.6.1-trash/doc/muttrc.trash 2016-06-12 18:43:04.768515676 +0100 +@@ -0,0 +1,16 @@ ++# Example Mutt config file for the 'trash' feature. ++ ++# This feature defines a new 'trash' folder. ++# When mail is deleted it will be moved to this folder. ++ ++# Folder in which to put deleted emails ++set trash='+Trash' ++set trash='/home/flatcap/Mail/Trash' ++ ++# The default delete key 'd' will move an email to the 'trash' folder ++# Bind 'D' to REALLY delete an email ++bind index D purge-message ++ ++# Note: Deleting emails from the 'trash' folder will REALLY delete them. ++ ++# vim: syntax=muttrc +diff -urN mutt-1.6.1/doc/vimrc.trash mutt-1.6.1-trash/doc/vimrc.trash +--- mutt-1.6.1/doc/vimrc.trash 1970-01-01 01:00:00.000000000 +0100 ++++ mutt-1.6.1-trash/doc/vimrc.trash 2016-06-12 18:43:04.769515692 +0100 +@@ -0,0 +1,7 @@ ++" Vim syntax file for the mutt trash patch ++ ++syntax keyword muttrcVarStr contained skipwhite trash nextgroup=muttrcVarEqualsIdxFmt ++ ++syntax match muttrcFunction contained "\" ++ ++" vim: syntax=vim +diff -urN mutt-1.6.1/flags.c mutt-1.6.1-trash/flags.c +--- mutt-1.6.1/flags.c 2016-06-12 18:43:00.403447606 +0100 ++++ mutt-1.6.1-trash/flags.c 2016-06-12 18:43:04.902517766 +0100 +@@ -65,7 +65,13 @@ + { + h->deleted = 0; + update = 1; +- if (upd_ctx) ctx->deleted--; ++ if (upd_ctx) { ++ ctx->deleted--; ++ if (h->appended) { ++ ctx->appended--; ++ } ++ } ++ h->appended = 0; /* when undeleting, also reset the appended flag */ + #ifdef USE_IMAP + /* see my comment above */ + if (ctx->magic == M_IMAP) +@@ -87,6 +93,27 @@ + } + break; + ++ case M_APPENDED: ++ if (bf) { ++ if (!h->appended) { ++ h->appended = 1; ++ if (upd_ctx) { ++ ctx->appended++; ++ } ++ } ++ } ++ break; ++ ++ case M_PURGED: ++ if (bf) { ++ if (!h->purged) { ++ h->purged = 1; ++ } ++ } else if (h->purged) { ++ h->purged = 0; ++ } ++ break; ++ + case M_NEW: + + if (!mutt_bit_isset(ctx->rights,M_ACL_SEEN)) +diff -urN mutt-1.6.1/functions.h mutt-1.6.1-trash/functions.h +--- mutt-1.6.1/functions.h 2016-06-12 18:43:00.403447606 +0100 ++++ mutt-1.6.1-trash/functions.h 2016-06-12 18:43:04.902517766 +0100 +@@ -121,6 +121,7 @@ + { "toggle-write", OP_TOGGLE_WRITE, "%" }, + { "next-thread", OP_MAIN_NEXT_THREAD, "\016" }, + { "next-subthread", OP_MAIN_NEXT_SUBTHREAD, "\033n" }, ++ { "purge-message", OP_PURGE_MESSAGE, NULL }, + { "query", OP_QUERY, "Q" }, + { "quit", OP_QUIT, "q" }, + { "reply", OP_REPLY, "r" }, +@@ -213,6 +214,7 @@ + { "print-message", OP_PRINT, "p" }, + { "previous-thread", OP_MAIN_PREV_THREAD, "\020" }, + { "previous-subthread",OP_MAIN_PREV_SUBTHREAD, "\033p" }, ++ { "purge-message", OP_PURGE_MESSAGE, NULL }, + { "quit", OP_QUIT, "Q" }, + { "exit", OP_EXIT, "q" }, + { "reply", OP_REPLY, "r" }, +diff -urN mutt-1.6.1/globals.h mutt-1.6.1-trash/globals.h +--- mutt-1.6.1/globals.h 2016-06-12 18:43:00.403447606 +0100 ++++ mutt-1.6.1-trash/globals.h 2016-06-12 18:43:04.903517781 +0100 +@@ -141,6 +141,7 @@ + WHERE char *Status; + WHERE char *Tempdir; + WHERE char *Tochars; ++WHERE char *TrashPath; + WHERE char *TSStatusFormat; + WHERE char *TSIconFormat; + WHERE short TSSupported; +diff -urN mutt-1.6.1/imap/imap.c mutt-1.6.1-trash/imap/imap.c +--- mutt-1.6.1/imap/imap.c 2016-06-12 18:43:00.405447637 +0100 ++++ mutt-1.6.1-trash/imap/imap.c 2016-06-12 18:43:04.905517812 +0100 +@@ -888,6 +888,12 @@ + if (hdrs[n]->deleted != HEADER_DATA(hdrs[n])->deleted) + match = invert ^ hdrs[n]->deleted; + break; ++ case M_EXPIRED: /* imap_fast_trash version of M_DELETED */ ++ if (hdrs[n]->purged) ++ break; ++ if (hdrs[n]->deleted != HEADER_DATA(hdrs[n])->deleted) ++ match = invert ^ (hdrs[n]->deleted && !hdrs[n]->appended); ++ break; + case M_FLAG: + if (hdrs[n]->flagged != HEADER_DATA(hdrs[n])->flagged) + match = invert ^ hdrs[n]->flagged; +@@ -2038,3 +2044,53 @@ + + return -1; + } ++ ++/** ++ * imap_fast_trash - XXX ++ */ ++int ++imap_fast_trash (void) ++{ ++ if ((Context->magic == M_IMAP) && mx_is_imap (TrashPath)) { ++ IMAP_MBOX mx; ++ IMAP_DATA *idata = (IMAP_DATA *) Context->data; ++ char mbox[LONG_STRING]; ++ char mmbox[LONG_STRING]; ++ int rc; ++ dprint (1, (debugfile, "[itf] trashcan seems to be on imap.\n")); ++ ++ if (imap_parse_path (TrashPath, &mx) == 0) { ++ if (mutt_account_match (&(idata->conn->account), &(mx.account))) { ++ dprint (1, (debugfile, "[itf] trashcan seems to be on the same account.\n")); ++ ++ imap_fix_path (idata, mx.mbox, mbox, sizeof (mbox)); ++ if (!*mbox) ++ strfcpy (mbox, "INBOX", sizeof (mbox)); ++ imap_munge_mbox_name (idata, mmbox, sizeof (mmbox), mbox); ++ ++ rc = imap_exec_msgset (idata, "UID COPY", mmbox, M_EXPIRED, 0, 0); ++ if (rc == 0) { ++ dprint (1, (debugfile, "imap_copy_messages: No messages del-tagged\n")); ++ rc = -1; ++ goto old_way; ++ } else if (rc < 0) { ++ dprint (1, (debugfile, "could not queue copy\n")); ++ goto old_way; ++ } else { ++ mutt_message (_("Copying %d messages to %s..."), rc, mbox); ++ return 0; ++ } ++ } else { ++ dprint (1, (debugfile, "[itf] trashcan seems to be on a different account.\n")); ++ } ++old_way: ++ FREE(&mx.mbox); /* we probably only need to free this when the parse works */ ++ } else { ++ dprint (1, (debugfile, "[itf] failed to parse TrashPath.\n")); ++ } ++ ++ dprint (1, (debugfile, "[itf] giving up and trying old fasioned way.\n")); ++ } ++ ++ return 1; ++} +diff -urN mutt-1.6.1/imap/imap.h mutt-1.6.1-trash/imap/imap.h +--- mutt-1.6.1/imap/imap.h 2016-06-12 18:43:00.405447637 +0100 ++++ mutt-1.6.1-trash/imap/imap.h 2016-06-12 18:43:04.774515769 +0100 +@@ -72,4 +72,7 @@ + + int imap_account_match (const ACCOUNT* a1, const ACCOUNT* a2); + ++/* trash */ ++int imap_fast_trash (void); ++ + #endif +diff -urN mutt-1.6.1/imap/message.c mutt-1.6.1-trash/imap/message.c +--- mutt-1.6.1/imap/message.c 2016-06-12 18:43:00.406447652 +0100 ++++ mutt-1.6.1-trash/imap/message.c 2016-06-12 18:43:04.906517828 +0100 +@@ -886,6 +886,7 @@ + if (ctx->hdrs[n]->tagged) + { + mutt_set_flag (ctx, ctx->hdrs[n], M_DELETE, 1); ++ mutt_set_flag (ctx, ctx->hdrs[n], M_APPENDED, 1); + if (option (OPTDELETEUNTAG)) + mutt_set_flag (ctx, ctx->hdrs[n], M_TAG, 0); + } +@@ -893,6 +894,7 @@ + else + { + mutt_set_flag (ctx, h, M_DELETE, 1); ++ mutt_set_flag (ctx, h, M_APPENDED, 1); + if (option (OPTDELETEUNTAG)) + mutt_set_flag (ctx, h, M_TAG, 0); + } +diff -urN mutt-1.6.1/init.h mutt-1.6.1-trash/init.h +--- mutt-1.6.1/init.h 2016-06-12 18:43:00.408447684 +0100 ++++ mutt-1.6.1-trash/init.h 2016-06-12 18:43:04.909517875 +0100 +@@ -3419,6 +3419,16 @@ + ** provided that ``$$ts_enabled'' has been set. This string is identical in + ** formatting to the one used by ``$$status_format''. + */ ++ { "trash", DT_PATH, R_NONE, UL &TrashPath, 0 }, ++ /* ++ ** .pp ++ ** If set, this variable specifies the path of the trash folder where the ++ ** mails marked for deletion will be moved, instead of being irremediably ++ ** purged. ++ ** .pp ++ ** NOTE: When you delete a message in the trash folder, it is really ++ ** deleted, so that you have a way to clean the trash. ++ */ + #ifdef USE_SOCKET + { "tunnel", DT_STR, R_NONE, UL &Tunnel, UL 0 }, + /* +diff -urN mutt-1.6.1/mutt.h mutt-1.6.1-trash/mutt.h +--- mutt-1.6.1/mutt.h 2016-06-12 18:43:00.410447715 +0100 ++++ mutt-1.6.1-trash/mutt.h 2016-06-12 18:43:04.912517922 +0100 +@@ -182,6 +182,8 @@ + M_DELETE, + M_UNDELETE, + M_DELETED, ++ M_APPENDED, ++ M_PURGED, + M_FLAG, + M_TAG, + M_UNTAG, +@@ -719,6 +721,8 @@ + unsigned int mime : 1; /* has a MIME-Version header? */ + unsigned int flagged : 1; /* marked important? */ + unsigned int tagged : 1; ++ unsigned int appended : 1; /* has been saved */ ++ unsigned int purged : 1; /* bypassing the trash folder */ + unsigned int deleted : 1; + unsigned int changed : 1; + unsigned int attach_del : 1; /* has an attachment marked for deletion */ +@@ -891,6 +895,7 @@ + int new; /* how many new messages? */ + int unread; /* how many unread messages? */ + int deleted; /* how many deleted messages */ ++ int appended; /* how many saved messages? */ + int flagged; /* how many flagged messages */ + int msgnotreadyet; /* which msg "new" in pager, -1 if none */ + +diff -urN mutt-1.6.1/muttlib.c mutt-1.6.1-trash/muttlib.c +--- mutt-1.6.1/muttlib.c 2016-06-12 18:43:00.411447731 +0100 ++++ mutt-1.6.1-trash/muttlib.c 2016-06-12 18:43:04.913517937 +0100 +@@ -1511,7 +1511,9 @@ + + if (magic > 0 && !mx_access (s, W_OK)) + { +- if (option (OPTCONFIRMAPPEND)) ++ if (option (OPTCONFIRMAPPEND) && ++ (!TrashPath || (mutt_strcmp (s, TrashPath) != 0))) ++ /* if we're appending to the trash, there's no point in asking */ + { + snprintf (tmp, sizeof (tmp), _("Append messages to %s?"), s); + if ((rc = mutt_yesorno (tmp, M_YES)) == M_NO) +diff -urN mutt-1.6.1/mx.c mutt-1.6.1-trash/mx.c +--- mutt-1.6.1/mx.c 2016-06-12 18:43:00.411447731 +0100 ++++ mutt-1.6.1-trash/mx.c 2016-06-12 18:43:04.914517953 +0100 +@@ -776,6 +776,62 @@ + return rc; + } + ++/** ++ * trash_append - XXX ++ * ++ * move deleted mails to the trash folder ++ */ ++static int trash_append (CONTEXT *ctx) ++{ ++ CONTEXT *ctx_trash; ++ int i = 0; ++ struct stat st, stc; ++ ++ if (!TrashPath || !ctx->deleted || ++ ((ctx->magic == M_MAILDIR) && option (OPTMAILDIRTRASH))) { ++ return 0; ++ } ++ ++ for (; i < ctx->msgcount && (!ctx->hdrs[i]->deleted || ctx->hdrs[i]->appended); i++); ++ /* nothing */ ++ ++ if (i == ctx->msgcount) ++ return 0; /* nothing to be done */ ++ ++ if (mutt_save_confirm (TrashPath, &st) != 0) { ++ mutt_error _("message(s) not deleted"); ++ return -1; ++ } ++ ++ if (lstat (ctx->path, &stc) == 0 && stc.st_ino == st.st_ino ++ && stc.st_dev == st.st_dev && stc.st_rdev == st.st_rdev) { ++ return 0; /* we are in the trash folder: simple sync */ ++ } ++ ++#ifdef USE_IMAP ++ if (!imap_fast_trash()) ++ return 0; ++#endif ++ ++ if ((ctx_trash = mx_open_mailbox (TrashPath, M_APPEND, NULL)) != NULL) { ++ for (i = 0 ; i < ctx->msgcount ; i++) { ++ if (ctx->hdrs[i]->deleted && !ctx->hdrs[i]->appended ++ && !ctx->hdrs[i]->purged ++ && mutt_append_message (ctx_trash, ctx, ctx->hdrs[i], 0, 0) == -1) { ++ mx_close_mailbox (ctx_trash, NULL); ++ return -1; ++ } ++ } ++ ++ mx_close_mailbox (ctx_trash, NULL); ++ } else { ++ mutt_error _("Can't open trash folder"); ++ return -1; ++ } ++ ++ return 0; ++} ++ + /* save changes and close mailbox */ + int mx_close_mailbox (CONTEXT *ctx, int *index_hint) + { +@@ -912,6 +968,7 @@ + if (mutt_append_message (&f, ctx, ctx->hdrs[i], 0, CH_UPDATE_LEN) == 0) + { + mutt_set_flag (ctx, ctx->hdrs[i], M_DELETE, 1); ++ mutt_set_flag (ctx, ctx->hdrs[i], M_APPENDED, 1); + } + else + { +@@ -936,6 +993,14 @@ + return 0; + } + ++ /* copy mails to the trash before expunging */ ++ if (purge && ctx->deleted && mutt_strcmp (ctx->path, TrashPath)) { ++ if (trash_append (ctx) != 0) { ++ ctx->closing = 0; ++ return -1; ++ } ++ } ++ + #ifdef USE_IMAP + /* allow IMAP to preserve the deleted flag across sessions */ + if (ctx->magic == M_IMAP) +@@ -1140,6 +1205,12 @@ + msgcount = ctx->msgcount; + deleted = ctx->deleted; + ++ if (purge && ctx->deleted && mutt_strcmp (ctx->path, TrashPath)) { ++ if (trash_append (ctx) == -1) { ++ return -1; ++ } ++ } ++ + #ifdef USE_IMAP + if (ctx->magic == M_IMAP) + rc = imap_sync_mailbox (ctx, purge, index_hint); +diff -urN mutt-1.6.1/OPS mutt-1.6.1-trash/OPS +--- mutt-1.6.1/OPS 2016-06-12 18:43:00.389447388 +0100 ++++ mutt-1.6.1-trash/OPS 2016-06-12 18:43:04.883517469 +0100 +@@ -142,6 +142,7 @@ + OP_PREV_LINE "scroll up one line" + OP_PREV_PAGE "move to the previous page" + OP_PRINT "print the current entry" ++OP_PURGE_MESSAGE "really delete the current entry, bypassing the trash folder" + OP_QUERY "query external program for addresses" + OP_QUERY_APPEND "append new query results to current results" + OP_QUIT "save changes to mailbox and quit" +diff -urN mutt-1.6.1/pager.c mutt-1.6.1-trash/pager.c +--- mutt-1.6.1/pager.c 2016-06-12 18:43:00.412447746 +0100 ++++ mutt-1.6.1-trash/pager.c 2016-06-12 18:43:04.915517968 +0100 +@@ -2351,6 +2351,7 @@ + MAYBE_REDRAW (redraw); + break; + ++ case OP_PURGE_MESSAGE: + case OP_DELETE: + CHECK_MODE(IsHeader (extra)); + CHECK_READONLY; +@@ -2358,6 +2359,8 @@ + CHECK_ACL(M_ACL_DELETE, _("Cannot delete message")); + + mutt_set_flag (Context, extra->hdr, M_DELETE, 1); ++ mutt_set_flag (Context, extra->hdr, M_PURGED, ++ ch != OP_PURGE_MESSAGE ? 0 : 1); + if (option (OPTDELETEUNTAG)) + mutt_set_flag (Context, extra->hdr, M_TAG, 0); + redraw = REDRAW_STATUS | REDRAW_INDEX; +@@ -2688,6 +2691,7 @@ + CHECK_ACL(M_ACL_DELETE, _("Cannot undelete message")); + + mutt_set_flag (Context, extra->hdr, M_DELETE, 0); ++ mutt_set_flag (Context, extra->hdr, M_PURGED, 0); + redraw = REDRAW_STATUS | REDRAW_INDEX; + if (option (OPTRESOLVE)) + { +@@ -2704,9 +2708,11 @@ + CHECK_ACL(M_ACL_DELETE, _("Cannot undelete message(s)")); + + r = mutt_thread_set_flag (extra->hdr, M_DELETE, 0, ++ ch == OP_UNDELETE_THREAD ? 0 : 1) ++ + mutt_thread_set_flag (extra->hdr, M_PURGED, 0, + ch == OP_UNDELETE_THREAD ? 0 : 1); + +- if (r != -1) ++ if (r > -1) + { + if (option (OPTRESOLVE)) + { +diff -urN mutt-1.6.1/PATCHES mutt-1.6.1-trash/PATCHES +--- mutt-1.6.1/PATCHES 2016-06-12 18:43:00.395447481 +0100 ++++ mutt-1.6.1-trash/PATCHES 2016-06-12 18:43:04.889517563 +0100 +@@ -0,0 +1 @@ ++patch-trash-neo-20160612 +diff -urN mutt-1.6.1/pattern.c mutt-1.6.1-trash/pattern.c +--- mutt-1.6.1/pattern.c 2016-06-12 18:43:00.413447762 +0100 ++++ mutt-1.6.1-trash/pattern.c 2016-06-12 18:43:04.916517984 +0100 +@@ -1367,8 +1367,9 @@ + { + switch (op) + { +- case M_DELETE: + case M_UNDELETE: ++ mutt_set_flag (Context, Context->hdrs[Context->v2r[i]], M_PURGED, 0); ++ case M_DELETE: + mutt_set_flag (Context, Context->hdrs[Context->v2r[i]], M_DELETE, + (op == M_DELETE)); + break; +diff -urN mutt-1.6.1/postpone.c mutt-1.6.1-trash/postpone.c +--- mutt-1.6.1/postpone.c 2016-06-12 18:43:00.414447777 +0100 ++++ mutt-1.6.1-trash/postpone.c 2016-06-12 18:43:04.917518000 +0100 +@@ -277,6 +277,9 @@ + /* finished with this message, so delete it. */ + mutt_set_flag (PostContext, h, M_DELETE, 1); + ++ /* and consider it saved, so that it won't be moved to the trash folder */ ++ mutt_set_flag (PostContext, h, M_APPENDED, 1); ++ + /* update the count for the status display */ + PostCount = PostContext->msgcount - PostContext->deleted; + +diff -urN mutt-1.6.1/README.trash mutt-1.6.1-trash/README.trash +--- mutt-1.6.1/README.trash 1970-01-01 01:00:00.000000000 +0100 ++++ mutt-1.6.1-trash/README.trash 2016-06-12 18:43:04.748515364 +0100 +@@ -0,0 +1,74 @@ ++Trash Folder Patch ++================== ++ ++ Automatically move "deleted" emails to a trash bin ++ ++Patch ++----- ++ ++ To check if Mutt supports "Trash Folder", look for "patch-trash" in the ++ mutt version. ++ ++ If IMAP is enabled, this patch will use it ++ ++ Dependencies ++ * mutt-1.6.1 ++ * IMAP support ++ ++Introduction ++------------ ++ ++ In Mutt, when you "delete" an email it is first marked deleted. The email ++ isn't really gone until is called. This happens when the ++ user leaves the folder, or the function is called manually. ++ ++ After '' has been called the email is gone forever. ++ ++ The $trash variable defines a folder in which to keep old emails. As ++ before, first you mark emails for deletion. When is called ++ the emails are moved to the trash folder. ++ ++ The '$trash' path can be either a full directory, or be relative to the ++ $folder variable, like the 'mailboxes' command. ++ ++ > Note ++ > ++ > Emails deleted from the trash folder are gone forever. ++ ++Variables ++--------- ++ ++ Trash Variables ++ ++ | Name | Type | Default | ++ |-------|--------|---------| ++ | trash | string | (none) | ++ ++Functions ++--------- ++ ++ Trash Functions ++ ++ | Menus | Default Key | Function | Description | ++ |-------------|-------------|-------------------|-------------------------------------------------------------| ++ | index,pager | (none) | '' | really delete the current entry, bypassing the trash folder | ++ ++See Also ++-------- ++ ++ * NeoMutt project ++ * folder-hook ++ ++Known Bugs ++---------- ++ ++ None ++ ++Credits ++------- ++ ++ * Cedric Duval ++ * Benjamin Kuperman ++ * Paul Miller ++ * Richard Russon ++