summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Frankenau2016-05-19 20:26:32 +0200
committerJohannes Frankenau2016-05-19 20:26:32 +0200
commit3d86c55b30334efc5b70054590332ca1abdf72e9 (patch)
tree01e85204b20c65b8b557c59f2380a535546ba327
parentd76fa438b22aef0ccde36342da0c8759281aad18 (diff)
downloadaur-3d86c55b30334efc5b70054590332ca1abdf72e9.tar.gz
Update to 1.6.1 and use patches from NeoMutt
-rw-r--r--.SRCINFO32
-rw-r--r--.gitignore6
-rw-r--r--PKGBUILD88
-rw-r--r--sidebar-compose.patch38
-rw-r--r--sidebar-delimnullwide.patch44
-rw-r--r--sidebar-newonly.patch197
-rw-r--r--sidebar.patch4758
-rw-r--r--trash-folder.patch316
-rw-r--r--trash.patch780
9 files changed, 4358 insertions, 1901 deletions
diff --git a/.SRCINFO b/.SRCINFO
index 202bf96b56b1..89f7f4f04dcf 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,33 +1,31 @@
pkgbase = mutt-sidebar
- pkgdesc = Small but very powerful text-based mail client
- pkgver = 1.6.0
+ pkgdesc = Small but very powerful text-based mail client with sidebar and trash patches from NeoMutt
+ pkgver = 1.6.1
pkgrel = 1
url = http://www.mutt.org/
arch = i686
arch = x86_64
- arch = armv7h
- arch = armv7l
license = GPL
depends = gpgme
- depends = krb5
+ depends = ncurses
+ depends = openssl
+ depends = libsasl
+ depends = gdbm
depends = libidn
depends = mime-types
- optdepends = smtp-forwarder: to send mail
+ depends = krb5
provides = mutt
conflicts = mutt
- source = https://bitbucket.org/mutt/mutt/downloads/mutt-1.6.0.tar.gz
- source = trash-folder.patch
+ backup = etc/Muttrc
+ source = http://ftp.mutt.org/pub/mutt/mutt-1.6.1.tar.gz
+ source = http://ftp.mutt.org/pub/mutt/mutt-1.6.1.tar.gz.asc
source = sidebar.patch
- source = sidebar-delimnullwide.patch
- source = sidebar-newonly.patch
- source = sidebar-compose.patch
+ source = trash.patch
validpgpkeys = 8975A9B33AA37910385C5308ADEF768480316BDA
- sha512sums = 601d5f70c7cd30903799714cd85b80f9650a029e621d044075e123656411dde809d5cef24a40ba49860bc242cf4a0b914c703deb5a7125b3a24eeb93f4ae3c4c
- sha512sums = 13f2f6402d3bb407d5e0a04049f7be27c9dbc0ccb9681fe7640d060cc3c13d76a8cf9985da8daa680058603b317f9dbf1b2125aa9e103c625add0d8d530b2538
- sha512sums = 636309d514834c16ae51691aec757d35fb999404fd29ad41f80bd70f9b9370cb74a2ee84000599ffbd6f197a5316a89567ced9ac6dedaf6270b9aa4fbc90be71
- sha512sums = defb96553dd26e7909ec06964729217c75a1bbb88bb00b6c4a07703b4c64952d06bfe1cd9f1c1aa9a6bf6cfbc5b0cc3933002387ca3b55b6399b1445474bd929
- sha512sums = b0f9184564eb75c36c3f807a7088f2c83a72fcfc1b91feed94919e98bbbbcc74fb07776d730871ca4caa87a044fbd00f906dfbb1928b8fd5f23d1526d6375dbd
- sha512sums = c7c1df28937b64777e66ef86a198bb168532093066c00c8aa349d76aa7a7d7f799fcc1fe0d7eb5e59a73223a43cdb4c38ab1881d644fd5ae5467844f44cb2dd9
+ sha1sums = ff1c76209a5c299018fc72b9e2e1ab98bf5138dd
+ sha1sums = SKIP
+ sha1sums = 4303a9aa21265e5fc52da8624b165c80849d15a5
+ sha1sums = 44e6bf580c9e4495c2f81fc23878ad139c4c73a2
pkgname = mutt-sidebar
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 000000000000..3970036a55e6
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+pkg
+src
+*.tar.gz
+*.tar.gz.asc
+*.pkg.tar
+*.pkg.tar.xz
diff --git a/PKGBUILD b/PKGBUILD
index d66dc4db177e..55b926ba23ff 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -1,68 +1,58 @@
-# Maintainer: Alessio Sergi <asergi at archlinux dot us>
-# Contributor: tobias [tobias [at] archlinux.org]
-# Contributor: Gaetan Bisson <bisson@archlinux.org>
-
pkgname=mutt-sidebar
-pkgver=1.6.0
+_pkgname=mutt
+pkgver=1.6.1
pkgrel=1
-pkgdesc='Small but very powerful text-based mail client'
-arch=('i686' 'x86_64' 'armv7h' 'armv7l')
+pkgdesc='Small but very powerful text-based mail client with sidebar and trash patches from NeoMutt'
url='http://www.mutt.org/'
license=('GPL')
-depends=('gpgme' 'krb5' 'libidn' 'mime-types')
-optdepends=('smtp-forwarder: to send mail')
+backup=('etc/Muttrc')
+arch=('i686' 'x86_64')
conflicts=('mutt')
provides=('mutt')
-source=("https://bitbucket.org/mutt/mutt/downloads/mutt-${pkgver}.tar.gz"
- "trash-folder.patch"
+depends=('gpgme' 'ncurses' 'openssl' 'libsasl' 'gdbm' 'libidn' 'mime-types' 'krb5')
+source=("http://ftp.mutt.org/pub/mutt/${_pkgname}-${pkgver}.tar.gz"{,.asc}
"sidebar.patch"
- "sidebar-delimnullwide.patch"
- "sidebar-newonly.patch"
- "sidebar-compose.patch"
- )
+ "trash.patch")
+sha1sums=('ff1c76209a5c299018fc72b9e2e1ab98bf5138dd'
+ 'SKIP'
+ '4303a9aa21265e5fc52da8624b165c80849d15a5'
+ '44e6bf580c9e4495c2f81fc23878ad139c4c73a2')
validpgpkeys=('8975A9B33AA37910385C5308ADEF768480316BDA')
prepare() {
- cd "$srcdir/mutt-$pkgver"
-
- # patch to add trash folder support
- # patch -Np1 -i "$srcdir"/trashfolder-1.5.22.diff0
- patch -Np1 -i "$srcdir"/trash-folder.patch
-
- # patch to add sidebar support
- patch -p 1 -i "$srcdir"/sidebar.patch
- patch -p 1 -i "$srcdir"/sidebar-delimnullwide.patch
- patch -p 1 -i "$srcdir"/sidebar-newonly.patch
- patch -p 1 -i "$srcdir"/sidebar-compose.patch
-
- # fix automake issue
- autoreconf -vfi
+ cd "${srcdir}/${_pkgname}-${pkgver}"
+ patch -Np1 -i "${srcdir}/sidebar.patch"
+ patch -Np1 -i "${srcdir}/trash.patch"
}
build() {
- cd "$srcdir/mutt-$pkgver"
- ./configure --prefix=/usr --sysconfdir=/etc \
- --enable-gpgme --enable-pop \
- --enable-imap --enable-smtp \
- --enable-hcache --with-curses=/usr \
- --with-regex --with-gss=/usr \
- --with-ssl=/usr --with-sasl \
- --with-idn
+ cd "${srcdir}/${_pkgname}-${pkgver}"
+
+ ./configure \
+ --prefix=/usr \
+ --sysconfdir=/etc \
+ --enable-gpgme \
+ --enable-pop \
+ --enable-imap \
+ --enable-smtp \
+ --enable-hcache \
+ --with-curses=/usr \
+ --with-regex \
+ --with-gss=/usr \
+ --with-ssl=/usr \
+ --with-sasl \
+ --with-idn \
+ --enable-sidebar \
+
make
}
package() {
- cd "$srcdir/mutt-$pkgver"
- make DESTDIR="$pkgdir" install
+ cd "${srcdir}/${_pkgname}-${pkgver}"
+ make DESTDIR="${pkgdir}" install
- # remove unneeded or conflicting files
- rm "$pkgdir"/etc/mime.types{,.dist}
- rm "$pkgdir"/usr/bin/{flea,muttbug}
- rm "$pkgdir"/usr/share/man/man1/{flea,muttbug}.1
+ rm "${pkgdir}"/etc/mime.types{,.dist}
+ rm "${pkgdir}"/usr/bin/{flea,muttbug}
+ rm "${pkgdir}"/usr/share/man/man1/{flea,muttbug}.1
+ install -Dm644 contrib/gpg.rc "${pkgdir}"/etc/Muttrc.gpg.dist
}
-sha512sums=('601d5f70c7cd30903799714cd85b80f9650a029e621d044075e123656411dde809d5cef24a40ba49860bc242cf4a0b914c703deb5a7125b3a24eeb93f4ae3c4c'
- '13f2f6402d3bb407d5e0a04049f7be27c9dbc0ccb9681fe7640d060cc3c13d76a8cf9985da8daa680058603b317f9dbf1b2125aa9e103c625add0d8d530b2538'
- '636309d514834c16ae51691aec757d35fb999404fd29ad41f80bd70f9b9370cb74a2ee84000599ffbd6f197a5316a89567ced9ac6dedaf6270b9aa4fbc90be71'
- 'defb96553dd26e7909ec06964729217c75a1bbb88bb00b6c4a07703b4c64952d06bfe1cd9f1c1aa9a6bf6cfbc5b0cc3933002387ca3b55b6399b1445474bd929'
- 'b0f9184564eb75c36c3f807a7088f2c83a72fcfc1b91feed94919e98bbbbcc74fb07776d730871ca4caa87a044fbd00f906dfbb1928b8fd5f23d1526d6375dbd'
- 'c7c1df28937b64777e66ef86a198bb168532093066c00c8aa349d76aa7a7d7f799fcc1fe0d7eb5e59a73223a43cdb4c38ab1881d644fd5ae5467844f44cb2dd9')
diff --git a/sidebar-compose.patch b/sidebar-compose.patch
deleted file mode 100644
index 225139239137..000000000000
--- a/sidebar-compose.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From: Evgeni Golov <evgeni@debian.org>
-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
----
- compose.c | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/compose.c b/compose.c
-index 7ff2996..42bdb46 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/sidebar-delimnullwide.patch b/sidebar-delimnullwide.patch
deleted file mode 100644
index cd684020b236..000000000000
--- a/sidebar-delimnullwide.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-From: Evgeni Golov <evgeni@debian.org>
-Date: Fri, 25 Dec 2015 12:02:08 +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
----
- sidebar.c | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
-diff --git a/sidebar.c b/sidebar.c
-index e9d9eba..b75a0e3 100644
---- a/sidebar.c
-+++ b/sidebar.c
-@@ -30,6 +30,7 @@
- #include <libgen.h>
- #include "keymap.h"
- #include <stdbool.h>
-+#include <wchar.h>
-
- /*BUFFY *CurBuffy = 0;*/
- static BUFFY *TopBuffy = 0;
-@@ -150,7 +151,7 @@ char *make_sidebar_entry(char *box, unsigned int size, unsigned int new, unsigne
- struct sidebar_entry sbe;
- int SBvisual;
-
-- SBvisual = SidebarWidth - strlen(SidebarDelim);
-+ SBvisual = SidebarWidth - mbstowcs(NULL, NONULL(SidebarDelim), 0);
- if (SBvisual < 1)
- return NULL;
-
-@@ -193,7 +194,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/sidebar-newonly.patch b/sidebar-newonly.patch
deleted file mode 100644
index 2219c0ae4f97..000000000000
--- a/sidebar-newonly.patch
+++ /dev/null
@@ -1,197 +0,0 @@
-From: Steve Kemp <steve@steve.org.uk>
-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
----
- OPS | 2 ++
- curs_main.c | 2 ++
- functions.h | 4 ++++
- init.h | 6 +++++-
- mutt.h | 2 ++
- pager.c | 2 ++
- sidebar.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
- 7 files changed, 70 insertions(+), 3 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 7583eba..3ad22c4 100644
---- a/curs_main.c
-+++ b/curs_main.c
-@@ -2429,6 +2429,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 2e7371c..b7aff80 100644
---- a/init.h
-+++ b/init.h
-@@ -2108,7 +2108,11 @@ struct option_t MuttVars[] = {
- ** .pp
- ** Should folders be indented in the sidebar.
- */
--
-+ {"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 91e58e9..2a9f1e0 100644
---- a/mutt.h
-+++ b/mutt.h
-@@ -538,6 +538,8 @@ enum
- OPTDONTHANDLEPGPKEYS, /* (pseudo) used to extract PGP keys */
- OPTIGNOREMACROEVENTS, /* (pseudo) don't process macro/push/exec events while set */
-
-+ OPTSIDEBARNEWMAILONLY,
-+
- OPTMAX
- };
-
-diff --git a/pager.c b/pager.c
-index 676fd39..9a2b269 100644
---- a/pager.c
-+++ b/pager.c
-@@ -2808,6 +2808,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 b75a0e3..c298599 100644
---- a/sidebar.c
-+++ b/sidebar.c
-@@ -297,8 +297,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 && Context->path &&
-@@ -358,6 +371,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)
- {
-@@ -376,18 +412,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/sidebar.patch b/sidebar.patch
index 54bb94eb4320..6371a66d774c 100644
--- a/sidebar.patch
+++ b/sidebar.patch
@@ -1,406 +1,393 @@
-From: Antonio Radici <antonio@debian.org>
-Date: Sat, 19 Sep 2015 13:19:55 +0200
-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_folderindent (boolean, default no)
-
- Should folders be indented in the sidebar.
-
- sidebar_format (string, default "%B%?F? [%F]?%* %?N?%N/?%4S")
-
- Format string for the sidebar. The sequences `%N', `%F' and `%S'
- will be replaced by the number of new or flagged messages or the total
- size of them mailbox. `%B' will be replaced with the name of the mailbox.
- The `%!' sequence will be expanded to `!' if there is one flagged message;
- to `!!' if there are two flagged messages; and to `n!' for n flagged
- messages, n>2.
-
- sidebar_indentstr (string, default " ")
-
- This specifies the string that is used to indent items
- with sidebar_folderindent= yes
-
- sidebar_shortpath (boolean, default no)
-
- Should the sidebar shorten the path showed.
-
- sidebar_sort (boolean, default no)
-
- This specifies whether or not to sort the sidebar alphabetically.
-
- 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/mutt-sidebar/
- - http://lunar-linux.org/~tchan/mutt/patch-1.5.24.sidebar.20151111.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
-
- - 2015-12-24 evgeni: refresh sidebar patch to the 20151111 version
-
-Signed-off-by: Evgeni Golov <evgeni@debian.org>
-Signed-off-by: Matteo F. Vescovi <mfv@debian.org>
----
- Makefile.am | 1 +
- OPS | 5 +
- buffy.c | 152 ++++++++++++++++++++-
- buffy.h | 6 +
- color.c | 2 +
- compose.c | 26 ++--
- configure.ac | 2 +
- curs_main.c | 37 +++++-
- doc/Muttrc | 20 +++
- flags.c | 3 +
- functions.h | 10 ++
- globals.h | 6 +
- handler.c | 30 ++++-
- imap/command.c | 7 +
- imap/imap.c | 2 +-
- init.h | 48 +++++++
- mailbox.h | 1 +
- main.c | 11 +-
- mbox.c | 2 +
- menu.c | 20 +--
- mh.c | 26 ++++
- mutt.h | 6 +
- mutt_curses.h | 3 +
- mutt_menu.h | 1 +
- muttlib.c | 48 +++++++
- mx.c | 24 +++-
- mx.h | 1 +
- pager.c | 42 +++++-
- pattern.c | 38 ++++++
- protos.h | 7 +
- sidebar.c | 410 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- sidebar.h | 36 +++++
- 32 files changed, 992 insertions(+), 41 deletions(-)
- create mode 100644 sidebar.c
- create mode 100644 sidebar.h
-
-diff --git a/Makefile.am b/Makefile.am
-index 9475381..c593f4f 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 --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 c713d16..d34e6f5 100644
---- a/buffy.c
-+++ b/buffy.c
-@@ -161,6 +161,49 @@ void mutt_buffy_cleanup (const char *buf, struct stat *st)
- }
- }
+diff -urN mutt-1.6.1/buffy.c mutt-1.6.1-sidebar/buffy.c
+--- mutt-1.6.1/buffy.c 2016-05-02 03:02:12.397171385 +0100
++++ mutt-1.6.1-sidebar/buffy.c 2016-05-02 03:02:15.009212943 +0100
+@@ -27,6 +27,10 @@
-+static int buffy_compare_name(const void *a, const void *b) {
-+ const BUFFY *b1 = * (BUFFY * const *) a;
-+ const BUFFY *b2 = * (BUFFY * const *) b;
-+
-+ 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;
-+}
+ #include "mutt_curses.h"
+
++#ifdef USE_SIDEBAR
++#include "sidebar.h"
++#endif
+
- BUFFY *mutt_find_mailbox (const char *path)
- {
- BUFFY *tmp = NULL;
-@@ -196,9 +239,13 @@ void mutt_update_mailbox (BUFFY * b)
+ #ifdef USE_IMAP
+ #include "imap.h"
+ #endif
+@@ -196,9 +200,17 @@
static BUFFY *buffy_new (const char *path)
{
BUFFY* buffy;
-+ char rp[PATH_MAX];
-+ char *r;
++#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));
-+ r = realpath(path, rp);
++#ifdef USE_SIDEBAR
++ r = realpath (path, rp);
+ strfcpy (buffy->realpath, r ? rp : path, sizeof (buffy->realpath));
++#endif
buffy->next = NULL;
buffy->magic = 0;
-@@ -243,8 +290,8 @@ int mutt_parse_mailboxes (BUFFER *path, BUFFER *s, unsigned long data, BUFFER *e
+@@ -215,7 +227,10 @@
+ BUFFY **tmp,*tmp1;
+ char buf[_POSIX_PATH_MAX];
+ struct stat sb;
+- char f1[PATH_MAX], f2[PATH_MAX];
++ char f1[PATH_MAX];
++#ifndef USE_SIDEBAR
++ char f2[PATH_MAX];
++#endif
+ char *p, *q;
+
+ while (MoreArgs (s))
+@@ -228,6 +243,9 @@
+ for (tmp = &Incoming; *tmp;)
+ {
+ tmp1=(*tmp)->next;
++#ifdef USE_SIDEBAR
++ sb_notify_mailbox (*tmp, 0);
++#endif
+ buffy_free (tmp);
+ *tmp=tmp1;
+ }
+@@ -243,8 +261,13 @@
p = realpath (buf, f1);
for (tmp = &Incoming; *tmp; tmp = &((*tmp)->next))
{
-- q = realpath ((*tmp)->path, f2);
-- if (mutt_strcmp (p ? p : buf, q ? q : (*tmp)->path) == 0)
++#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;
-@@ -282,6 +329,7 @@ int mutt_parse_mailboxes (BUFFER *path, BUFFER *s, unsigned long data, BUFFER *e
- else
- (*tmp)->size = 0;
- }
-+ Incoming = buffy_sort(Incoming);
- return 0;
- }
+@@ -256,14 +279,21 @@
+ if(*tmp)
+ {
+ tmp1=(*tmp)->next;
++#ifdef USE_SIDEBAR
++ sb_notify_mailbox (*tmp, 0);
++#endif
+ buffy_free (tmp);
+ *tmp=tmp1;
+ }
+ continue;
+ }
+
+- if (!*tmp)
++ if (!*tmp) {
+ *tmp = buffy_new (buf);
++#ifdef USE_SIDEBAR
++ sb_notify_mailbox (*tmp, 1);
++#endif
++ }
-@@ -306,6 +354,11 @@ static int buffy_maildir_dir_hasnew(BUFFY* mailbox, const char *dir_name)
+ (*tmp)->new = 0;
+ (*tmp)->notified = 1;
+@@ -306,6 +336,13 @@
return 0;
}
-+ if (option(OPTSIDEBAR) && mailbox->msg_unread > 0) {
-+ mailbox->new = 1;
-+ return 1;
++#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 +410,73 @@ static int buffy_maildir_hasnew (BUFFY* mailbox)
+@@ -357,6 +394,89 @@
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;
-+
-+ if(!option(OPTSIDEBAR))
-+ return;
-+
-+ mailbox->msgcount = 0;
-+ mailbox->msg_unread = 0;
-+ mailbox->msg_flagged = 0;
-+
-+ snprintf (path, sizeof (path), "%s/new", 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->new = 1;
-+ mailbox->msgcount++;
-+ 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++;
-+ }
-+ }
-+ }
-+ }
++ char path[_POSIX_PATH_MAX] = "";
++ DIR *dirp = NULL;
++ struct dirent *de = NULL;
++ char *p = NULL;
++ int read;
++
++ snprintf (path, sizeof (path), "%s/%s", mailbox->path, dir);
++
++ dirp = opendir (path);
++ if (!dirp) {
++ mailbox->magic = 0;
++ return;
++ }
++
++ while ((de = readdir (dirp)) != NULL) {
++ if (*de->d_name == '.')
++ continue;
++
++ /* Matches maildir_parse_flags logic */
++ read = 0;
++ mailbox->msg_count++;
++ p = strstr (de->d_name, ":2,");
++ if (p) {
++ p += 3;
++ if (strchr (p, 'S'))
++ read = 1;
++ if (strchr (p, 'F'))
++ mailbox->msg_flagged++;
++ }
++ if (!read) {
++ mailbox->msg_unread++;
++ }
++ }
+
-+ mailbox->sb_last_checked = time(NULL);
-+ closedir (dirp);
++ closedir (dirp);
+}
+
++/**
++ * buffy_maildir_update - Update messages counts for a maildir mailbox
++ * @mailbox: BUFFY representing a maildir mailbox
++ *
++ * Open a mailbox directories and update our record of how many new, or
++ * flagged, messages there are.
++ */
++void
++buffy_maildir_update (BUFFY *mailbox)
++{
++ if (!option (OPTSIDEBAR))
++ return;
++
++ mailbox->msg_count = 0;
++ mailbox->msg_unread = 0;
++ mailbox->msg_flagged = 0;
++
++ buffy_maildir_update_dir (mailbox, "new");
++ if (mailbox->msg_count) {
++ mailbox->new = 1;
++ }
++ buffy_maildir_update_dir (mailbox, "cur");
++
++ mailbox->sb_last_checked = time (NULL);
++
++ /* make sure the updates are actually put on screen */
++ sb_draw();
++}
++
++#endif
++
/* returns 1 if mailbox has new mail */
static int buffy_mbox_hasnew (BUFFY* mailbox, struct stat *sb)
{
-@@ -368,7 +488,7 @@ static int buffy_mbox_hasnew (BUFFY* mailbox, struct stat *sb)
+@@ -368,7 +488,11 @@
else
statcheck = sb->st_mtime > sb->st_atime
|| (mailbox->newly_created && sb->st_ctime == sb->st_mtime && sb->st_ctime == sb->st_atime);
-- if (statcheck)
-+ if ((!option(OPTSIDEBAR) && statcheck) || (option(OPTSIDEBAR) && mailbox->msg_unread > 0))
++#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 +508,27 @@ static int buffy_mbox_hasnew (BUFFY* mailbox, struct stat *sb)
+@@ -388,6 +512,40 @@
return rc;
}
-+/* update message counts for the sidebar */
-+void buffy_mbox_update (BUFFY* mailbox, struct stat *sb)
++#ifdef USE_SIDEBAR
++/**
++ * buffy_mbox_update - Update messages counts for an mbox mailbox
++ * @mailbox: BUFFY representing an mbox mailbox
++ * @sb: stat(2) infomation about the mailbox file
++ *
++ * Open a mbox file and update our record of how many new, or flagged,
++ * messages there are. If the mailbox hasn't changed since the last call,
++ * the function does nothing.
++ */
++void
++buffy_mbox_update (BUFFY *mailbox, struct stat *sb)
+{
-+ CONTEXT *ctx = NULL;
-+
-+ if(!option(OPTSIDEBAR))
-+ return;
-+ if(mailbox->sb_last_checked > sb->st_mtime && mailbox->msgcount != 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;
-+ mailbox->msg_flagged = ctx->flagged;
-+ mailbox->sb_last_checked = time(NULL);
-+ mx_close_mailbox(ctx, 0);
-+ }
++ CONTEXT *ctx = NULL;
++
++ if (!option (OPTSIDEBAR))
++ return;
++ if ((mailbox->sb_last_checked > sb->st_mtime) && (mailbox->msg_count != 0))
++ return; /* no check necessary */
++
++ ctx = mx_open_mailbox (mailbox->path, M_READONLY | M_QUIET | M_NOSORT | M_PEEK, NULL);
++ if (ctx) {
++ mailbox->msg_count = ctx->msgcount;
++ mailbox->msg_unread = ctx->unread;
++ mailbox->msg_flagged = ctx->flagged;
++ mailbox->sb_last_checked = time (NULL);
++ mx_close_mailbox (ctx, 0);
++ }
++
++ /* make sure the updates are actually put on screen */
++ sb_draw();
+}
++#endif
+
int mutt_buffy_check (int force)
{
BUFFY *tmp;
-@@ -461,17 +602,20 @@ int mutt_buffy_check (int force)
+@@ -428,6 +586,9 @@
+ contex_sb.st_ino=0;
+ }
+
++#ifdef USE_SIDEBAR
++ int should_refresh = sb_should_refresh();
++#endif
+ for (tmp = Incoming; tmp; tmp = tmp->next)
+ {
+ if (tmp->magic != M_IMAP)
+@@ -461,16 +622,30 @@
{
case M_MBOX:
case M_MMDF:
-+ buffy_mbox_update (tmp, &sb);
++#ifdef USE_SIDEBAR
++ if (should_refresh)
++ buffy_mbox_update (tmp, &sb);
++#endif
if (buffy_mbox_hasnew (tmp, &sb) > 0)
BuffyCount++;
break;
case M_MAILDIR:
-+ buffy_maildir_update (tmp);
++#ifdef USE_SIDEBAR
++ if (should_refresh)
++ buffy_maildir_update (tmp);
++#endif
if (buffy_maildir_hasnew (tmp) > 0)
BuffyCount++;
break;
case M_MH:
-- mh_buffy(tmp);
-+ mh_buffy_update (tmp->path, &tmp->msgcount, &tmp->msg_unread, &tmp->msg_flagged, &tmp->sb_last_checked);
-+ mh_buffy(tmp);
++#ifdef USE_SIDEBAR
++ if (sb_should_refresh()) {
++ mh_buffy_update (tmp);
++ sb_set_update_time();
++ }
++#endif
+ mh_buffy(tmp);
if (tmp->new)
BuffyCount++;
- break;
-diff --git a/buffy.h b/buffy.h
-index 9aa8e51..03c37df 100644
---- a/buffy.h
-+++ b/buffy.h
-@@ -23,13 +23,19 @@
+@@ -485,6 +660,10 @@
+ else if (!tmp->notified)
+ BuffyNotify++;
+ }
++#ifdef USE_SIDEBAR
++ if (should_refresh)
++ sb_set_update_time();
++#endif
+
+ BuffyDoneTime = BuffyTime;
+ return (BuffyCount);
+diff -urN mutt-1.6.1/buffy.h mutt-1.6.1-sidebar/buffy.h
+--- mutt-1.6.1/buffy.h 2016-05-02 03:02:12.397171385 +0100
++++ mutt-1.6.1-sidebar/buffy.h 2016-05-02 03:02:15.010212959 +0100
+@@ -16,6 +16,9 @@
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
++#ifndef _BUFFY_H
++#define _BUFFY_H
++
+ /*parameter to mutt_parse_mailboxes*/
+ #define M_MAILBOXES 1
+ #define M_UNMAILBOXES 2
+@@ -23,13 +26,28 @@
typedef struct buffy_t
{
char path[_POSIX_PATH_MAX];
++#ifdef USE_SIDEBAR
+ char realpath[_POSIX_PATH_MAX];
++#endif
off_t size;
struct buffy_t *next;
++#ifdef USE_SIDEBAR
+ struct buffy_t *prev;
++#endif
short new; /* mailbox has new mail */
-+ 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 */
time_t last_visited; /* time of last exit from this mailbox */
-+ time_t sb_last_checked; /* time of last buffy check from sidebar */
++#ifdef USE_SIDEBAR
++ time_t sb_last_checked; /* time of last buffy check from sidebar */
++#endif
}
BUFFY;
-diff --git a/color.c b/color.c
-index 6e29603..3731c37 100644
---- a/color.c
-+++ b/color.c
-@@ -94,6 +94,8 @@ static const struct mapping_t Fields[] =
+@@ -49,3 +67,5 @@
+ void mutt_buffy_setnotified (const char *path);
+
+ void mh_buffy (BUFFY *);
++
++#endif /* _BUFFY_H */
+diff -urN mutt-1.6.1/color.c mutt-1.6.1-sidebar/color.c
+--- mutt-1.6.1/color.c 2016-05-02 03:02:12.397171385 +0100
++++ mutt-1.6.1-sidebar/color.c 2016-05-02 03:02:15.010212959 +0100
+@@ -94,6 +94,14 @@
{ "underline", MT_COLOR_UNDERLINE },
{ "index", MT_COLOR_INDEX },
{ "prompt", MT_COLOR_PROMPT },
-+ { "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 6af817f..7ff2996 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-05-02 03:02:12.398171401 +0100
++++ mutt-1.6.1-sidebar/compose.c 2016-05-02 03:02:15.010212959 +0100
+@@ -32,6 +32,9 @@
+ #include "mailbox.h"
+ #include "sort.h"
+ #include "charset.h"
++#ifdef USE_SIDEBAR
++#include "sidebar.h"
++#endif
+
+ #ifdef MIXMASTER
+ #include "remailer.h"
+@@ -72,7 +75,7 @@
#define HDR_XOFFSET 10
#define TITLE_FMT "%10s" /* Used for Prompts, which are ASCII */
@@ -409,16 +396,16 @@ index 6af817f..7ff2996 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,7 +148,7 @@
addstr (_(" (OppEnc mode)"));
clrtoeol ();
@@ -427,7 +414,7 @@ index 6af817f..7ff2996 100644
clrtoeol ();
if ((WithCrypto & APPLICATION_PGP)
-@@ -162,7 +162,7 @@ static void redraw_crypt_lines (HEADER *msg)
+@@ -162,7 +165,7 @@
&& (msg->security & ENCRYPT)
&& SmimeCryptAlg
&& *SmimeCryptAlg) {
@@ -436,16 +423,16 @@ index 6af817f..7ff2996 100644
NONULL(SmimeCryptAlg));
}
}
-@@ -175,7 +175,7 @@ static void redraw_mix_line (LIST *chain)
+@@ -175,7 +178,7 @@
int c;
char *t;
- mvaddstr (HDR_MIX, 0, " Mix: ");
-+ mvaddstr (HDR_MIX, SidebarWidth, " Mix: ");
++ mvprintw (HDR_MIX, SidebarWidth, TITLE_FMT, "Mix: ");
if (!chain)
{
-@@ -190,7 +190,7 @@ static void redraw_mix_line (LIST *chain)
+@@ -190,7 +193,7 @@
if (t && t[0] == '0' && t[1] == '\0')
t = "<random>";
@@ -454,7 +441,7 @@ index 6af817f..7ff2996 100644
break;
addstr (NONULL(t));
-@@ -242,7 +242,7 @@ static void draw_envelope_addr (int line, ADDRESS *addr)
+@@ -242,20 +245,23 @@
buf[0] = 0;
rfc822_write_address (buf, sizeof (buf), addr, 1);
@@ -463,7 +450,12 @@ index 6af817f..7ff2996 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
++ 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);
@@ -476,7 +468,7 @@ index 6af817f..7ff2996 100644
mutt_paddstr (W, fcc);
if (WithCrypto)
-@@ -266,7 +266,7 @@ static void draw_envelope (HEADER *msg, char *fcc)
+@@ -266,7 +272,7 @@
#endif
SETCOLOR (MT_COLOR_STATUS);
@@ -485,16 +477,16 @@ index 6af817f..7ff2996 100644
clrtoeol ();
NORMAL_COLOR;
-@@ -302,7 +302,7 @@ static int edit_address_list (int line, ADDRESS **addr)
+@@ -302,7 +308,7 @@
/* redraw the expanded list so the user can see the result */
buf[0] = 0;
rfc822_write_address (buf, sizeof (buf), *addr, 1);
- move (line, HDR_XOFFSET);
-+ move (line, HDR_XOFFSET+SidebarWidth);
++ move (line, HDR_XOFFSET + SidebarWidth);
mutt_paddstr (W, buf);
return 0;
-@@ -564,7 +564,7 @@ int mutt_compose_menu (HEADER *msg, /* structure for new message */
+@@ -564,7 +570,7 @@
if (mutt_get_field ("Subject: ", buf, sizeof (buf), 0) == 0)
{
mutt_str_replace (&msg->env->subject, buf);
@@ -503,7 +495,7 @@ index 6af817f..7ff2996 100644
if (msg->env->subject)
mutt_paddstr (W, msg->env->subject);
else
-@@ -582,7 +582,7 @@ int mutt_compose_menu (HEADER *msg, /* structure for new message */
+@@ -582,7 +588,7 @@
{
strfcpy (fcc, buf, fcclen);
mutt_pretty_mailbox (fcc, fcclen);
@@ -512,52 +504,75 @@ index 6af817f..7ff2996 100644
mutt_paddstr (W, fcc);
fccSet = 1;
}
-diff --git a/configure.ac b/configure.ac
-index 6c579dd..8c833fa 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -1306,6 +1306,8 @@ if test $mutt_cv_langinfo_yesexpr = yes; then
- AC_DEFINE(HAVE_LANGINFO_YESEXPR,1,[ Define if you have <langinfo.h> and nl_langinfo(YESEXPR). ])
+diff -urN mutt-1.6.1/configure.ac mutt-1.6.1-sidebar/configure.ac
+--- mutt-1.6.1/configure.ac 2016-05-02 03:02:12.398171401 +0100
++++ mutt-1.6.1-sidebar/configure.ac 2016-05-02 03:02:15.011212974 +0100
+@@ -175,6 +175,15 @@
+ SMIMEAUX_TARGET="smime_keys"
fi
-+AC_CHECK_FUNCS(fmemopen open_memstream)
++AC_ARG_ENABLE(sidebar, AC_HELP_STRING([--enable-sidebar], [Enable Sidebar support]),
++[ if test x$enableval = xyes ; then
++ AC_DEFINE(USE_SIDEBAR,1,[ Define if you want support for the sidebar. ])
++ OPS="$OPS \$(srcdir)/OPS.SIDEBAR"
++ need_sidebar="yes"
++ fi
++])
++AM_CONDITIONAL(BUILD_SIDEBAR, test x$need_sidebar = xyes)
+
- dnl Documentation tools
- have_openjade="no"
- AC_PATH_PROG([OSPCAT], [ospcat], [none])
-diff --git a/curs_main.c b/curs_main.c
-index f418f67..7583eba 100644
---- a/curs_main.c
-+++ b/curs_main.c
-@@ -26,7 +26,9 @@
+ AC_ARG_WITH(mixmaster, AS_HELP_STRING([--with-mixmaster@<:@=PATH@:>@],[Include Mixmaster support]),
+ [if test "$withval" != no
+ then
+diff -urN mutt-1.6.1/copy.c mutt-1.6.1-sidebar/copy.c
+--- mutt-1.6.1/copy.c 2016-05-02 03:02:12.398171401 +0100
++++ mutt-1.6.1-sidebar/copy.c 2016-05-02 03:02:15.011212974 +0100
+@@ -288,7 +288,7 @@
+ if (flags & (CH_DECODE|CH_PREFIX))
+ {
+ if (mutt_write_one_header (out, 0, headers[x],
+- flags & CH_PREFIX ? prefix : 0, mutt_term_width (Wrap), flags) == -1)
++ flags & CH_PREFIX ? prefix : 0, mutt_term_width (Wrap) - SidebarWidth, flags) == -1)
+ {
+ error = TRUE;
+ break;
+diff -urN mutt-1.6.1/curs_main.c mutt-1.6.1-sidebar/curs_main.c
+--- mutt-1.6.1/curs_main.c 2016-05-02 03:02:12.400171433 +0100
++++ mutt-1.6.1-sidebar/curs_main.c 2016-05-02 03:02:15.012212990 +0100
+@@ -26,8 +26,13 @@
#include "mailbox.h"
#include "mapping.h"
#include "sort.h"
+#include "buffy.h"
#include "mx.h"
-+#include "sidebar.h"
++#ifdef USE_SIDEBAR
++#include "sidebar.h"
++#endif
++
#ifdef USE_POP
#include "pop.h"
-@@ -672,20 +674,31 @@ 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_STATUS;
+ if (option (OPTBEEPNEW))
-+ beep ();
++ beep();
+ }
}
else
do_buffy_notify = 1;
}
-+ if(option(OPTSIDEBAR))
++#ifdef USE_SIDEBAR
++ if (option (OPTSIDEBAR))
+ menu->redraw |= REDRAW_SIDEBAR;
++#endif
+
if (op != -1)
mutt_curs_set (0);
@@ -565,28 +580,42 @@ index f418f67..7583eba 100644
if (menu->redraw & REDRAW_FULL)
{
menu_redraw_full (menu);
-+ draw_sidebar(menu->menu);
++#ifdef USE_SIDEBAR
++ sb_draw();
++#endif
mutt_show_error ();
-+ } else if(menu->redraw & REDRAW_SIDEBAR) {
-+ draw_sidebar(menu->menu);
-+ menu->redraw &= ~REDRAW_SIDEBAR;
}
++#ifdef USE_SIDEBAR
++ else if (menu->redraw & REDRAW_SIDEBAR) {
++ sb_draw();
++ menu->redraw &= ~REDRAW_SIDEBAR;
++ }
++#endif
if (menu->menu == MENU_MAIN)
-@@ -707,9 +720,12 @@ int mutt_index_menu (void)
+ {
+@@ -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
++ sb_set_buffystats (Context);
++#endif
mutt_paddstr (COLS, buf);
NORMAL_COLOR;
menu->redraw &= ~REDRAW_STATUS;
-@@ -729,7 +745,7 @@ int mutt_index_menu (void)
+@@ -652,7 +686,7 @@
menu->oldcurrent = -1;
if (option (OPTARROWCURSOR))
@@ -595,411 +624,1846 @@ index f418f67..7583eba 100644
else if (option (OPTBRAILLEFRIENDLY))
move (menu->current - menu->top + menu->offset, 0);
else
-@@ -1170,6 +1186,7 @@ int mutt_index_menu (void)
+@@ -1091,6 +1125,9 @@
break;
CHECK_MSGCOUNT;
-+ CHECK_VISIBLE;
++#ifdef USE_SIDEBAR
++ CHECK_VISIBLE;
++#endif
CHECK_READONLY;
{
int oldvcount = Context->vcount;
-@@ -1229,6 +1246,7 @@ int mutt_index_menu (void)
+@@ -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:
-@@ -1260,7 +1278,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 = 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)
- {
-@@ -1278,6 +1300,7 @@ int mutt_index_menu (void)
+@@ -1199,6 +1247,9 @@
}
mutt_expand_path (buf, sizeof (buf));
-+ set_curbuffy(buf);
++#ifdef USE_SIDEBAR
++ sb_set_open_buffy (buf);
++#endif
if (mx_get_magic (buf) <= 0)
{
mutt_error (_("%s is not a mailbox."), buf);
-@@ -2402,6 +2425,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:
++ 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/doc/Muttrc b/doc/Muttrc
-index c8689d0..01272c7 100644
---- a/doc/Muttrc
-+++ b/doc/Muttrc
-@@ -657,6 +657,26 @@ attachments -I message/external-body
- # $crypt_autosign, $crypt_replysign and $smime_is_default.
- #
- #
-+# set sidebar_visible=no
-+#
-+# Name: sidebar_visible
-+# Type: boolean
-+# Default: no
-+#
-+#
-+# This specifies whether or not to show sidebar (left-side list of folders).
-+#
-+#
-+# set sidebar_width=0
-+#
-+# Name: sidebar_width
-+# Type: number
-+# Default: 0
-+#
-+#
-+# The width of the sidebar.
-+#
-+#
- # set crypt_autosign=no
- #
- # Name: crypt_autosign
-diff --git a/flags.c b/flags.c
-index 5309bb7..8776b18 100644
---- a/flags.c
-+++ b/flags.c
-@@ -22,8 +22,10 @@
-
- #include "mutt.h"
- #include "mutt_curses.h"
-+#include "mutt_menu.h"
+diff -urN mutt-1.6.1/doc/manual.xml.head mutt-1.6.1-sidebar/doc/manual.xml.head
+--- mutt-1.6.1/doc/manual.xml.head 2016-05-02 03:02:12.402171465 +0100
++++ mutt-1.6.1-sidebar/doc/manual.xml.head 2016-05-02 03:02:15.014213022 +0100
+@@ -405,6 +405,623 @@
+
+ </sect2>
+
++<sect2 id="intro-sidebar">
++ <title>Sidebar</title>
++ <para>
++ 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.
++ </para>
++ <para>
++ This part of the manual is suitable for beginners.
++ If you already know Mutt you could skip ahead to the main
++ <link linkend="sidebar">Sidebar guide</link>.
++ If you just want to get started, you could use the sample
++ <link linkend="sidebar-muttrc">Sidebar muttrc</link>.
++ </para>
++ <para>
++ This version of Sidebar is based on Terry Chan's
++ <ulink url="http://www.lunar-linux.org/mutt-sidebar/">2015-11-11 release</ulink>.
++ It contains many
++ <emphasis role="bold"><link linkend="intro-sidebar-features">new features</link></emphasis>,
++ lots of
++ <emphasis role="bold"><link linkend="intro-sidebar-bugfixes">bugfixes</link></emphasis>
++ and a generous helping of
++ <emphasis role="bold">new documentation</emphasis> which you are already reading.
++ </para>
++ <para>
++ To check if Mutt supports <quote>Sidebar</quote>, look for the string
++ <literal>+USE_SIDEBAR</literal> in the mutt version.
++ </para>
++<screen>
++mutt -v
++</screen>
++ <para>
++ <emphasis role="bold">Let's turn on the Sidebar:</emphasis>
++ </para>
++ <screen>set sidebar_visible</screen>
++ <para>
++ You will see something like this.
++ A list of mailboxes on the left.
++ A list of emails, from the selected mailbox, on the right.
++ </para>
++<screen>
++<emphasis role="indicator">Fruit [1] 3/8</emphasis>| 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
++ |<emphasis role="indicator"> 6 N + Mar 24 Samuel Harris (353) Tangerine </emphasis>
++ | 7 N + Sep 05 Sofia Graham (335) Cherry
++ | 8 N Sep 16 Ewan Brown (105) Ugli
++ |
++ |
++</screen>
++<para>
++ This user has four mailboxes: <quote>Fruit</quote>,
++ <quote>Cars</quote>, <quote>Animals</quote> and
++ <quote>Seas</quote>.
++</para>
++<para>
++ The current, open, mailbox is <quote>Fruit</quote>. We can
++ also see information about the other mailboxes. For example:
++ The <quote>Animals</quote> mailbox contains, 1 flagged email, 2
++ new emails out of a total of 6 emails.
++</para>
++ <sect3 id="intro-sidebar-navigation">
++ <title>Navigation</title>
++ <para>
++ The Sidebar adds some new <link linkend="sidebar-functions">functions</link>
++ to Mutt.
++ </para>
++ <para>
++ The user pressed the <quote>c</quote> key to
++ <literal>&lt;change-folder&gt;</literal> to the
++ <quote>Animals</quote> mailbox. The Sidebar automatically
++ updated the indicator to match.
++ </para>
++<screen>
++Fruit [1] 3/8| 1 Jan 03 Tia Gibson (362) Caiman
++<emphasis role="indicator">Animals [1] 2/6</emphasis>| 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
++ |<emphasis role="indicator"> 5 N + Nov 12 Evelyn Rogers (453) Tapir </emphasis>
++ | 6 N + Nov 16 Callum Harrison (498) Hedgehog
++ |
++ |
++ |
++ |
++</screen>
++ <para>
++ Let's map some functions:
++ </para>
++<screen>
++bind index,pager \CP sidebar-prev <emphasis role="comment"># Ctrl-Shift-P - Previous Mailbox</emphasis>
++bind index,pager \CN sidebar-next <emphasis role="comment"># Ctrl-Shift-N - Next Mailbox</emphasis>
++bind index,pager \CO sidebar-open <emphasis role="comment"># Ctrl-Shift-O - Open Highlighted Mailbox</emphasis>
++</screen>
++ <para>
++ Press <quote>Ctrl-Shift-N</quote> (Next mailbox) twice will
++ move the Sidebar <emphasis role="bold">highlight</emphasis> to
++ down to the <quote>Seas</quote> mailbox.
++ </para>
++<screen>
++Fruit [1] 3/8| 1 Jan 03 Tia Gibson (362) Caiman
++<emphasis role="indicator">Animals [1] 2/6</emphasis>| 2 + Jan 22 Rhys Lee ( 48) Dolphin
++Cars 4| 3 ! Aug 16 Ewan Brown (333) Hummingbird
++<emphasis role="highlight">Seas 1/7</emphasis>| 4 Sep 25 Grace Hall ( 27) Capybara
++ |<emphasis role="indicator"> 5 N + Nov 12 Evelyn Rogers (453) Tapir </emphasis>
++ | 6 N + Nov 16 Callum Harrison (498) Hedgehog
++ |
++ |
++ |
++ |
++</screen>
++ <note>
++ Functions <literal>&lt;sidebar-next&gt;</literal> and
++ <literal>&lt;sidebar-prev&gt;</literal> move the Sidebar
++ <emphasis role="bold">highlight</emphasis>.
++ They <emphasis role="bold">do not</emphasis> change the open
++ mailbox.
++ </note>
++ <para>
++ Press <quote>Ctrl-Shift-O</quote>
++ (<literal>&lt;sidebar-open&gt;</literal>)
++ to open the highlighted mailbox.
++ </para>
++<screen>
++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
++<emphasis role="indicator">Seas 1/7</emphasis>|<emphasis role="indicator"> 4 N + Feb 23 Isla Hussain (348) Balearic Sea </emphasis>
++ |
++ |
++ |
++ |
++ |
++ |
++</screen>
++ </sect3>
++ <sect3 id="intro-sidebar-features">
++ <title>Features</title>
++ <para>
++ The Sidebar shows a list of mailboxes in a panel.
++ <para>
++ </para>
++ Everything about the Sidebar can be configured.
++ </para>
++ <itemizedlist>
++ <title><link linkend="intro-sidebar-basics">State of the Sidebar</link></title>
++ <listitem><para>Visibility</para></listitem>
++ <listitem><para>Width</para></listitem>
++ </itemizedlist>
++ <itemizedlist>
++ <title><link linkend="intro-sidebar-limit">Which mailboxes are displayed</link></title>
++ <listitem><para>Display all</para></listitem>
++ <listitem><para>Limit to mailboxes with new mail</para></listitem>
++ <listitem><para>Whitelist mailboxes to display always</para></listitem>
++ </itemizedlist>
++ <itemizedlist>
++ <title><link linkend="sidebar-sort">The order in which mailboxes are displayed</link></title>
++ <title></title>
++ <listitem><para>Unsorted (order of mailboxes commands)</para></listitem>
++ <listitem><para>Sorted alphabetically</para></listitem>
++ <listitem><para>Sorted by number of new mails</para></listitem>
++ </itemizedlist>
++ <itemizedlist>
++ <title><link linkend="intro-sidebar-colors">Color</link></title>
++ <listitem><para>Sidebar indicators and divider</para></listitem>
++ <listitem><para>Mailboxes depending on their type</para></listitem>
++ <listitem><para>Mailboxes depending on their contents</para></listitem>
++ </itemizedlist>
++ <itemizedlist>
++ <title><link linkend="sidebar-functions">Key bindings</link></title>
++ <listitem><para>Hide/Unhide the Sidebar</para></listitem>
++ <listitem><para>Select previous/next mailbox</para></listitem>
++ <listitem><para>Select previous/next mailbox with new mail</para></listitem>
++ <listitem><para>Page up/down through a list of mailboxes</para></listitem>
++ </itemizedlist>
++ <itemizedlist>
++ <title>Misc</title>
++ <listitem><para><link linkend="intro-sidebar-format">Formatting string for mailbox</link></para></listitem>
++ <listitem><para><link linkend="sidebar-next-new-wrap">Wraparound searching</link></para></listitem>
++ <listitem><para><link linkend="intro-sidebar-abbrev">Flexible mailbox abbreviations</link></para></listitem>
++ <listitem><para>Support for Unicode mailbox names (utf-8)</para></listitem>
++ </itemizedlist>
++ </sect3>
++ <sect3 id="intro-sidebar-display">
++ <title>Display</title>
++ <para>
++ Everything about the Sidebar can be configured.
++ </para>
++ <itemizedlist>
++ <title>For a quick reference:</title>
++ <listitem><para><link linkend="sidebar-variables">Sidebar variables to set</link> </para></listitem>
++ <listitem><para><link linkend="sidebar-colors">Sidebar colors to apply</link></para></listitem>
++ <listitem><para><link linkend="sidebar-sort">Sidebar sort methods</link></para></listitem>
++ </itemizedlist>
++ <sect4 id="intro-sidebar-basics">
++ <title>Sidebar Basics</title>
++ <para>
++ The most important variable is <literal>$sidebar_visible</literal>.
++ You can set this in your <quote>muttrc</quote>, or bind a key to the
++ function <literal>&lt;sidebar-toggle-visible&gt;</literal>.
++ </para>
++<screen>
++set sidebar_visible <emphasis role="comment"># Make the Sidebar visible by default</emphasis>
++bind index,pager B sidebar-toggle-visible <emphasis role="comment"># Use 'B' to switch the Sidebar on and off</emphasis>
++</screen>
++ <para>
++ 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.
++ </para>
++ <para>
++ 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.
++ </para>
++<screen>
++set sidebar_width = 25 <emphasis role="comment"># Plenty of space</emphasis>
++set sidebar_divider_char = '│' <emphasis role="comment"># Pretty line-drawing character</emphasis>
++</screen>
++ </sect4>
++ <sect4 id="intro-sidebar-format">
++ <title>Sidebar Format String</title>
++ <para>
++ <literal>$sidebar_format</literal> allows you to customize the Sidebar display.
++ For an introduction, read <link linkend="index-format">format strings</link>
++ including the section about <link linkend="formatstrings-conditionals">conditionals</link>.
++ </para>
++ <para>
++ The default value is <literal>%B%?F? [%F]?%* %?N?%N/?%S</literal>
++ </para>
++ <itemizedlist>
++ <title>Which breaks down as:</title>
++ <listitem><para><literal>%B</literal> - Mailbox name</para></listitem>
++ <listitem><para><literal>%?F? [%F]?</literal> - If flagged emails <literal>[%F]</literal>, otherwise nothing</para></listitem>
++ <listitem><para><literal>%* </literal> - Pad with spaces</para></listitem>
++ <listitem><para><literal>%?N?%N/?</literal> - If new emails <literal>%N/</literal>, otherwise nothing</para></listitem>
++ <listitem><para><literal>%S</literal> - Total number of emails</para></listitem>
++ </itemizedlist>
++ <table>
++ <title>sidebar_format</title>
++ <tgroup cols="3">
++ <thead>
++ <row>
++ <entry>Format</entry>
++ <entry>Notes</entry>
++ <entry>Description</entry>
++ </row>
++ </thead>
++ <tbody>
++ <row>
++ <entry>%B</entry>
++ <entry></entry>
++ <entry>Name of the mailbox</entry>
++ </row>
++ <row>
++ <entry>%S</entry>
++ <entry>*</entry>
++ <entry>Size of mailbox (total number of messages)</entry>
++ </row>
++ <row>
++ <entry>%N</entry>
++ <entry>*</entry>
++ <entry>Number of New messages in the mailbox</entry>
++ </row>
++ <row>
++ <entry>%F</entry>
++ <entry>*</entry>
++ <entry>Number of Flagged messages in the mailbox</entry>
++ </row>
++ <row>
++ <entry>%!</entry>
++ <entry></entry>
++ <entry>
++ <quote>!</quote>: one flagged message;
++ <quote>!!</quote>: two flagged messages;
++ <quote>n!</quote>: n flagged messages (for n &gt; 2).
++ Otherwise prints nothing.
++ </entry>
++ </row>
++ <row>
++ <entry>%d</entry>
++ <entry>* ‡</entry>
++ <entry>Number of deleted messages</entry>
++ </row>
++ <row>
++ <entry>%L</entry>
++ <entry>* ‡</entry>
++ <entry>Number of messages after limiting</entry>
++ </row>
++ <row>
++ <entry>%t</entry>
++ <entry>* ‡</entry>
++ <entry>Number of tagged messages</entry>
++ </row>
++ <row>
++ <entry>%&gt;X</entry>
++ <entry></entry>
++ <entry>Right justify the rest of the string and pad with <quote>X</quote></entry>
++ </row>
++ <row>
++ <entry>%|X</entry>
++ <entry></entry>
++ <entry>Pad to the end of the line with
++ <quote>X</quote></entry>
++ </row>
++ <row>
++ <entry>%*X</entry>
++ <entry></entry>
++ <entry>Soft-fill with character <quote>X</quote>as pad</entry>
++ </row>
++ </tbody>
++ </tgroup>
++ </table>
++ <para>
++ * = Can be optionally printed if nonzero
++ </para>
++ <para>
++ ‡ = Only applicable to the current folder
++ </para>
++ <para>
++ Here are some examples.
++ They show the number of (F)lagged, (N)ew and (S)ize.
++ </para>
++ <table>
++ <title>sidebar_format</title>
++ <tgroup cols="2">
++ <thead>
++ <row>
++ <entry>Format</entry>
++ <entry>Example</entry>
++ </row>
++ </thead>
++ <tbody>
++ <row>
++ <entry><literal>%B%?F? [%F]?%* %?N?%N/?%S</literal></entry>
++ <entry><screen>mailbox [F] N/S</screen></entry>
++ </row>
++ <row>
++ <entry><literal>%B%* %F:%N:%S</literal></entry>
++ <entry><screen>mailbox F:N:S</screen></entry>
++ </row>
++ <row>
++ <entry><literal>%B %?N?(%N)?%* %S</literal></entry>
++ <entry><screen>mailbox (N) S</screen></entry>
++ </row>
++ <row>
++ <entry><literal>%B%* ?F?%F/?%N</literal></entry>
++ <entry><screen>mailbox F/S</screen></entry>
++ </row>
++ </tbody>
++ </tgroup>
++ </table>
++ </sect4>
++ <sect4 id="intro-sidebar-abbrev">
++ <title>Abbreviating Mailbox Names</title>
++ <para>
++ <literal>$sidebar_delim_chars</literal> tells Sidebar
++ how to split up mailbox paths. For local directories
++ use <quote>/</quote>; for IMAP folders use <quote>.</quote>
++ </para>
++ <sect5 id="intro-sidebar-abbrev-ex1">
++ <title>Example 1</title>
++ <para>
++ This example works well if your mailboxes have unique names
++ after the last separator.
++ </para>
++ <para>
++ Add some mailboxes of diffent depths.
++ </para>
++<screen>
++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
++</screen>
++ <para>
++ Shorten the names:
++ </para>
++<screen>
++set sidebar_short_path <emphasis role="comment"># Shorten mailbox names</emphasis>
++set sidebar_delim_chars="/" <emphasis role="comment"># Delete everything up to the last / character</emphasis>
++</screen>
++ <para>
++ The screenshot below shows what the Sidebar would look like
++ before and after shortening.
++ </para>
++<screen>
++|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
++</screen>
++ </sect5>
++ <sect5 id="intro-sidebar-abbrev-ex2">
++ <title>Example 2</title>
++ <para>
++ This example works well if you have lots of mailboxes which are arranged
++ in a tree.
++ </para>
++ <para>
++ Add some mailboxes of diffent depths.
++ </para>
++<screen>
++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
++</screen>
++ <para>
++ Shorten the names:
++ </para>
++<screen>
++set sidebar_short_path <emphasis role="comment"># Shorten mailbox names</emphasis>
++set sidebar_delim_chars="/" <emphasis role="comment"># Delete everything up to the last / character</emphasis>
++set sidebar_folder_indent <emphasis role="comment"># Indent folders whose names we've shortened</emphasis>
++set sidebar_indent_string=" " <emphasis role="comment"># Indent with two spaces</emphasis>
++</screen>
++ <para>
++ The screenshot below shows what the Sidebar would look like
++ before and after shortening.
++ </para>
++<screen>
++|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
++</screen>
++ <para>
++ 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).
++ </para>
++ </sect5>
++ </sect4>
++ <sect4 id="intro-sidebar-limit">
++ <title>Limiting the Number of Mailboxes</title>
++ <para>
++ If you have a lot of mailboxes, sometimes it can be useful to hide
++ the ones you aren't using. <literal>$sidebar_new_mail_only</literal>
++ tells Sidebar to only show mailboxes that contain new, or flagged, email.
++ </para>
++ <para>
++ If you want some mailboxes to be always visible, then use the
++ <literal>sidebar_whitelist</literal> command. It takes a list of
++ mailboxes as parameters.
++ </para>
++<screen>
++set sidebar_new_mail_only <emphasis role="comment"># Only mailboxes with new/flagged email</emphasis>
++sidebar_whitelist fruit fruit/apple <emphasis role="comment"># Always display these two mailboxes</emphasis>
++</screen>
++ </sect4>
++ </sect3>
++ <sect3 id="intro-sidebar-colors">
++ <title>Colors</title>
++ <para>
++ Here is a sample color scheme:
++ </para>
++<screen>
++color sidebar_indicator default color17 <emphasis role="comment"># Dark blue background</emphasis>
++color sidebar_highlight white color238 <emphasis role="comment"># Grey background</emphasis>
++color sidebar_spoolfile yellow default <emphasis role="comment"># Yellow</emphasis>
++color sidebar_new green default <emphasis role="comment"># Green</emphasis>
++color sidebar_flagged red default <emphasis role="comment"># Red</emphasis>
++color sidebar_divider color8 default <emphasis role="comment"># Dark grey</emphasis>
++</screen>
++ <para>
++ There is a priority order when coloring Sidebar mailboxes.
++ e.g. If a mailbox has new mail it will have the
++ <literal>sidebar_new</literal> color, even if it also contains
++ flagged mails.
++ </para>
++ <table id="table-intro-sidebar-colors">
++ <title>Sidebar Color Priority</title>
++ <tgroup cols="3">
++ <thead>
++ <row>
++ <entry>Priority</entry>
++ <entry>Color</entry>
++ <entry>Description</entry>
++ </row>
++ </thead>
++ <tbody>
++ <row>
++ <entry>Highest</entry>
++ <entry><literal>sidebar_indicator</literal></entry>
++ <entry>Mailbox is open</entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry><literal>sidebar_highlight</literal></entry>
++ <entry>Mailbox is highlighed</entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry><literal>sidebar_spoolfile</literal></entry>
++ <entry>Mailbox is the spoolfile (receives incoming mail)</entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry><literal>sidebar_new</literal></entry>
++ <entry>Mailbox contains new mail</entry>
++ </row>
++ <row>
++ <entry></entry>
++ <entry><literal>sidebar_flagged</literal></entry>
++ <entry>Mailbox contains flagged mail</entry>
++ </row>
++ <row>
++ <entry>Lowest</entry>
++ <entry>(None)</entry>
++ <entry>Mailbox does not match above</entry>
++ </row>
++ </tbody>
++ </tgroup>
++ </table>
++ </sect3>
++ <sect3 id="intro-sidebar-bugfixes">
++ <title>Bug-fixes</title>
++ <para>
++ If you haven't used Sidebar before, you can ignore this section.
++ </para>
++ <para>
++ These bugs have been fixed since the previous Sidebar release: 2015-11-11.
++ </para>
++ <itemizedlist>
++ <listitem><para>Fix bug when starting in compose mode</para></listitem>
++ <listitem><para>Fix bug with empty sidebar_divider_char string</para></listitem>
++ <listitem><para>Fix bug with header wrapping</para></listitem>
++ <listitem><para>Correctly handle utf8 character sequences</para></listitem>
++ <listitem><para>Fix a bug in mh_buffy_update</para></listitem>
++ <listitem><para>Fix refresh -- time overflowed short</para></listitem>
++ <listitem><para>Protect against empty format strings</para></listitem>
++ <listitem><para>Limit Sidebar width to COLS</para></listitem>
++ <listitem><para>Handle unmailboxes * safely</para></listitem>
++ <listitem><para>Refresh Sidebar after timeout</para></listitem>
++ </itemizedlist>
++ </sect3>
++ <sect3 id="intro-sidebar-config-changes">
++ <title>Config Changes</title>
++ <para>
++ If you haven't used Sidebar before, you can ignore this section.
++ </para>
++ <para>
++ 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.
++ </para>
++ <table id="table-intro-sidebar-config-changes">
++ <title>Config Changes</title>
++ <tgroup cols="2">
++ <thead>
++ <row>
++ <entry>Old Name</entry>
++ <entry>New Name</entry>
++ </row>
++ </thead>
++ <tbody>
++ <row>
++ <entry><literal>$sidebar_delim</literal></entry>
++ <entry><literal>$sidebar_divider_char</literal></entry>
++ </row>
++ <row>
++ <entry><literal>$sidebar_folderindent</literal></entry>
++ <entry><literal>$sidebar_folder_indent</literal></entry>
++ </row>
++ <row>
++ <entry><literal>$sidebar_indentstr</literal></entry>
++ <entry><literal>$sidebar_indent_string</literal></entry>
++ </row>
++ <row>
++ <entry><literal>$sidebar_newmail_only</literal></entry>
++ <entry><literal>$sidebar_new_mail_only</literal></entry>
++ </row>
++ <row>
++ <entry><literal>$sidebar_refresh</literal></entry>
++ <entry><literal>$sidebar_refresh_time</literal></entry>
++ </row>
++ <row>
++ <entry><literal>$sidebar_shortpath</literal></entry>
++ <entry><literal>$sidebar_short_path</literal></entry>
++ </row>
++ <row>
++ <entry><literal>$sidebar_sort</literal></entry>
++ <entry><literal>$sidebar_sort_method</literal></entry>
++ </row>
++ <row>
++ <entry><literal>&lt;sidebar-scroll-down&gt;</literal></entry>
++ <entry><literal>&lt;sidebar-page-down&gt;</literal></entry>
++ </row>
++ <row>
++ <entry><literal>&lt;sidebar-scroll-up&gt;</literal></entry>
++ <entry><literal>&lt;sidebar-page-up&gt;</literal></entry>
++ </row>
++ </tbody>
++ </tgroup>
++ </table>
++ </sect3>
++</sect2>
++
+ <sect2 id="intro-help">
+ <title>Help</title>
+
+@@ -8081,6 +8698,469 @@
+
+ </sect1>
+
++<sect1 id="sidebar">
++ <title>Sidebar Patch</title>
++ <subtitle>Overview of mailboxes</subtitle>
++
++ <sect2 id="sidebar-patch">
++ <title>Patch</title>
++
++ <para>
++ To check if Mutt supports <quote>Sidebar</quote>, look for
++ <quote>+USE_SIDEBAR</quote> in the mutt version.
++ See: <xref linkend="compile-time-features"/>.
++ </para>
++
++ <itemizedlist>
++ <title>Dependencies:</title>
++ <listitem><para>mutt-1.5.24</para></listitem>
++ </itemizedlist>
++
++ <para>This patch is part of the <ulink url="http://www.neomutt.org/">NeoMutt Project</ulink>.</para>
++ </sect2>
++
++ <sect2 id="sidebar-intro">
++ <title>Introduction</title>
++
++ <para>
++ 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.
++ </para>
++
++ <para>
++ This part of the manual is a reference guide.
++ If you want a simple introduction with examples see the
++ <link linkend="intro-sidebar">Sidebar Howto</link>.
++ If you just want to get started, you could use the sample
++ <link linkend="sidebar-muttrc">Sidebar muttrc</link>.
++ </para>
++
++ <para>
++ This version of Sidebar is based on Terry Chan's
++ <ulink url="http://www.lunar-linux.org/mutt-sidebar/">2015-11-11 release</ulink>.
++ It contains many
++ <emphasis role="bold"><link linkend="intro-sidebar-features">new features</link></emphasis>,
++ lots of
++ <emphasis role="bold"><link linkend="intro-sidebar-bugfixes">bugfixes</link></emphasis>.
++ </para>
++ </sect2>
++
++ <sect2 id="sidebar-variables">
++ <title>Variables</title>
++
++ <table id="table-sidebar-variables">
++ <title>Sidebar Variables</title>
++ <tgroup cols="3">
++ <thead>
++ <row>
++ <entry>Name</entry>
++ <entry>Type</entry>
++ <entry>Default</entry>
++ </row>
++ </thead>
++ <tbody>
++ <row>
++ <entry><literal>sidebar_delim_chars</literal></entry>
++ <entry>string</entry>
++ <entry><literal>/.</literal></entry>
++ </row>
++ <row>
++ <entry><literal>sidebar_divider_char</literal></entry>
++ <entry>string</entry>
++ <entry><literal>|</literal></entry>
++ </row>
++ <row>
++ <entry><literal>sidebar_folder_indent</literal></entry>
++ <entry>boolean</entry>
++ <entry><literal>no</literal></entry>
++ </row>
++ <row>
++ <entry><literal>sidebar_format</literal></entry>
++ <entry>string</entry>
++ <entry><literal>%B%?F? [%F]?%* %?N?%N/?%S</literal></entry>
++ </row>
++ <row>
++ <entry><literal>sidebar_indent_string</literal></entry>
++ <entry>string</entry>
++ <entry><literal>&nbsp;&nbsp;</literal> (two spaces)</entry>
++ </row>
++ <row>
++ <entry><literal>sidebar_new_mail_only</literal></entry>
++ <entry>boolean</entry>
++ <entry><literal>no</literal></entry>
++ </row>
++ <row>
++ <entry><literal>sidebar_next_new_wrap</literal></entry>
++ <entry>boolean</entry>
++ <entry><literal>no</literal></entry>
++ </row>
++ <row>
++ <entry><literal>sidebar_refresh_time</literal></entry>
++ <entry>number</entry>
++ <entry><literal>60</literal></entry>
++ </row>
++ <row>
++ <entry><literal>sidebar_short_path</literal></entry>
++ <entry>boolean</entry>
++ <entry><literal>no</literal></entry>
++ </row>
++ <row>
++ <entry><literal>sidebar_sort_method</literal></entry>
++ <entry>enum</entry>
++ <entry><literal>SORT_ORDER</literal></entry>
++ </row>
++ <row>
++ <entry><literal>sidebar_visible</literal></entry>
++ <entry>boolean</entry>
++ <entry><literal>no</literal></entry>
++ </row>
++ <row>
++ <entry><literal>sidebar_whitelist</literal></entry>
++ <entry>list</entry>
++ <entry>(empty)</entry>
++ </row>
++ <row>
++ <entry><literal>sidebar_width</literal></entry>
++ <entry>number</entry>
++ <entry><literal>20</literal></entry>
++ </row>
++ </tbody>
++ </tgroup>
++ </table>
++ </sect2>
++
++ <sect2 id="sidebar-functions">
++ <title>Functions</title>
++
++ <para>
++ Sidebar adds the following functions to Mutt.
++ By default, none of them are bound to keys.
++ </para>
++
++ <table id="table-sidebar-functions">
++ <title>Sidebar Functions</title>
++ <tgroup cols="3">
++ <thead>
++ <row>
++ <entry>Menus</entry>
++ <entry>Function</entry>
++ <entry>Description</entry>
++ </row>
++ </thead>
++ <tbody>
++ <row>
++ <entry>index,pager</entry>
++ <entry><literal>&lt;sidebar-next&gt;</literal></entry>
++ <entry>Move the highlight to next mailbox</entry>
++ </row>
++ <row>
++ <entry>index,pager</entry>
++ <entry><literal>&lt;sidebar-next-new&gt;</literal></entry>
++ <entry>Move the highlight to next mailbox with new mail</entry>
++ </row>
++ <row>
++ <entry>index,pager</entry>
++ <entry><literal>&lt;sidebar-open&gt;</literal></entry>
++ <entry>Open highlighted mailbox</entry>
++ </row>
++ <row>
++ <entry>index,pager</entry>
++ <entry><literal>&lt;sidebar-page-down&gt;</literal></entry>
++ <entry>Scroll the Sidebar down 1 page</entry>
++ </row>
++ <row>
++ <entry>index,pager</entry>
++ <entry><literal>&lt;sidebar-page-up&gt;</literal></entry>
++ <entry>Scroll the Sidebar up 1 page</entry>
++ </row>
++ <row>
++ <entry>index,pager</entry>
++ <entry><literal>&lt;sidebar-prev&gt;</literal></entry>
++ <entry>Move the highlight to previous mailbox</entry>
++ </row>
++ <row>
++ <entry>index,pager</entry>
++ <entry><literal>&lt;sidebar-prev-new&gt;</literal></entry>
++ <entry>Move the highlight to previous mailbox with new mail</entry>
++ </row>
++ <row>
++ <entry>index,pager</entry>
++ <entry><literal>&lt;sidebar-toggle-visible&gt;</literal></entry>
++ <entry>Make the Sidebar (in)visible</entry>
++ </row>
++ </tbody>
++ </tgroup>
++ </table>
++ </sect2>
++
++ <sect2 id="sidebar-commands">
++ <title>Commands</title>
++ <cmdsynopsis>
++ <command>sidebar_whitelist</command>
++ <arg choice="plain">
++ <replaceable class="parameter">mailbox</replaceable>
++ </arg>
++ <arg choice="opt" rep="repeat">
++ <replaceable class="parameter">mailbox</replaceable>
++ </arg>
++ </cmdsynopsis>
++ </sect2>
++
++ <sect2 id="sidebar-colors">
++ <title>Colors</title>
++
++ <table id="table-sidebar-colors">
++ <title>Sidebar Colors</title>
++ <tgroup cols="3">
++ <thead>
++ <row>
++ <entry>Name</entry>
++ <entry>Default Color</entry>
++ <entry>Description</entry>
++ </row>
++ </thead>
++ <tbody>
++ <row>
++ <entry><literal>sidebar_divider</literal></entry>
++ <entry>default</entry>
++ <entry>The dividing line between the Sidebar and the Index/Pager panels</entry>
++ </row>
++ <row>
++ <entry><literal>sidebar_flagged</literal></entry>
++ <entry>default</entry>
++ <entry>Mailboxes containing flagged mail</entry>
++ </row>
++ <row>
++ <entry><literal>sidebar_highlight</literal></entry>
++ <entry>underline</entry>
++ <entry>Cursor to select a mailbox</entry>
++ </row>
++ <row>
++ <entry><literal>sidebar_indicator</literal></entry>
++ <entry>mutt <literal>indicator</literal></entry>
++ <entry>The mailbox open in the Index panel</entry>
++ </row>
++ <row>
++ <entry><literal>sidebar_new</literal></entry>
++ <entry>default</entry>
++ <entry>Mailboxes containing new mail</entry>
++ </row>
++ <row>
++ <entry><literal>sidebar_spoolfile</literal></entry>
++ <entry>default</entry>
++ <entry>Mailbox that receives incoming mail</entry>
++ </row>
++ </tbody>
++ </tgroup>
++ </table>
++
++ If the <literal>sidebar_indicator</literal> color isn't set, then the default Mutt
++ indicator color will be used (the color used in the index panel).
++ </sect2>
++
++ <sect2 id="sidebar-sort">
++ <title>Sort</title>
++
++ <table id="table-sidebar-sort">
++ <title>Sidebar Sort</title>
++ <tgroup cols="2">
++ <thead>
++ <row>
++ <entry>Sort</entry>
++ <entry>Description</entry>
++ </row>
++ </thead>
++ <tbody>
++ <row>
++ <entry><literal>alpha</literal></entry>
++ <entry>Alphabetically by path</entry>
++ </row>
++ <row>
++ <entry><literal>count</literal></entry>
++ <entry>Total number of messages</entry>
++ </row>
++ <row>
++ <entry><literal>flagged</literal></entry>
++ <entry>Number of flagged messages</entry>
++ </row>
++ <row>
++ <entry><literal>name</literal></entry>
++ <entry>Alphabetically by path</entry>
++ </row>
++ <row>
++ <entry><literal>new</literal></entry>
++ <entry>Number of new messages</entry>
++ </row>
++ <row>
++ <entry><literal>path</literal></entry>
++ <entry>Alphabetically by path</entry>
++ </row>
++ <row>
++ <entry><literal>unsorted</literal></entry>
++ <entry>Do not resort the paths</entry>
++ </row>
++ </tbody>
++ </tgroup>
++ </table>
++ </sect2>
++
++ <sect2 id="sidebar-muttrc">
++ <title>Muttrc</title>
++<screen>
++<emphasis role="comment"># This is a complete list of sidebar-related configuration.
++
++# --------------------------------------------------------------------------
++# VARIABLES - shown with their default values
++# --------------------------------------------------------------------------
++
++# Should the Sidebar be shown?</emphasis>
++set sidebar_visible = no
++
++<emphasis role="comment"># How wide should the Sidebar be in screen columns?
++# Note: Some characters, e.g. Chinese, take up two columns each.</emphasis>
++set sidebar_width = 20
++
++<emphasis role="comment"># Should the mailbox paths be abbreviated?</emphasis>
++set sidebar_short_path = no
++
++<emphasis role="comment"># 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.</emphasis>
++set sidebar_delim_chars = '/.'
++
++<emphasis role="comment"># If the mailbox path is abbreviated, should it be indented?</emphasis>
++set sidebar_folder_indent = no
++
++<emphasis role="comment"># Indent mailbox paths with this string.</emphasis>
++set sidebar_indent_string = ' '
++
++<emphasis role="comment"># Make the Sidebar only display mailboxes that contain new, or flagged,
++# mail.</emphasis>
++set sidebar_new_mail_only = no
++
++<emphasis role="comment"># Any mailboxes that are whitelisted will always be visible, even if the
++# sidebar_new_mail_only option is enabled.</emphasis>
++sidebar_whitelist '/home/user/mailbox1'
++sidebar_whitelist '/home/user/mailbox2'
++
++<emphasis role="comment"># When searching for mailboxes containing new mail, should the search wrap
++# around when it reaches the end of the list?</emphasis>
++set sidebar_next_new_wrap = no
++
++<emphasis role="comment"># 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.</emphasis>
++set sidebar_divider_char = '|'
++
++<emphasis role="comment"># Display the Sidebar mailboxes using this format string.</emphasis>
++set sidebar_format = '%B%?F? [%F]?%* %?N?%N/?%S'
++
++<emphasis role="comment"># Sidebar will not refresh its list of mailboxes any more frequently than
++# this number of seconds. This will help reduce disk/network traffic.</emphasis>
++set sidebar_refresh_time = 60
++
++<emphasis role="comment"># 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</emphasis>
++set sidebar_sort_method = 'unsorted'
++
++<emphasis role="comment"># --------------------------------------------------------------------------
++# FUNCTIONS - shown with an example mapping
++# --------------------------------------------------------------------------
++
++# Move the highlight to the previous mailbox</emphasis>
++bind index,pager \Cp sidebar-prev
++
++<emphasis role="comment"># Move the highlight to the next mailbox</emphasis>
++bind index,pager \Cn sidebar-next
++
++<emphasis role="comment"># Open the highlighted mailbox</emphasis>
++bind index,pager \Co sidebar-open
++
++<emphasis role="comment"># Move the highlight to the previous page
++# This is useful if you have a LOT of mailboxes.</emphasis>
++bind index,pager &lt;F3&gt; sidebar-page-up
++
++<emphasis role="comment"># Move the highlight to the next page
++# This is useful if you have a LOT of mailboxes.</emphasis>
++bind index,pager &lt;F4&gt; sidebar-page-down
++
++<emphasis role="comment"># Move the highlight to the previous mailbox containing new, or flagged,
++# mail.</emphasis>
++bind index,pager &lt;F5&gt; sidebar-prev-new
++
++<emphasis role="comment"># Move the highlight to the next mailbox containing new, or flagged, mail.</emphasis>
++bind index,pager &lt;F6&gt; sidebar-next-new
++
++<emphasis role="comment"># Toggle the visibility of the Sidebar.</emphasis>
++bind index,pager B sidebar-toggle-visible
++
++<emphasis role="comment"># --------------------------------------------------------------------------
++# 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.</emphasis>
++color indicator cyan black
++
++<emphasis role="comment"># Color of the highlighted, but not open, mailbox.</emphasis>
++color sidebar_highlight black color8
++
++<emphasis role="comment"># Color of the divider separating the Sidebar from Mutt panels</emphasis>
++color sidebar_divider color8 black
++
++<emphasis role="comment"># Color to give mailboxes containing flagged mail</emphasis>
++color sidebar_flagged red black
++
++<emphasis role="comment"># Color to give mailboxes containing new mail</emphasis>
++color sidebar_new green black
++
++<emphasis role="comment"># --------------------------------------------------------------------------
++
++# vim: syntax=muttrc</emphasis>
++</screen>
++ </sect2>
++
++ <sect2 id="sidebar-see-also">
++ <title>See Also</title>
++
++ <itemizedlist>
++ <listitem><para><link linkend="regexp">Regular Expressions</link></para></listitem>
++ <listitem><para><link linkend="patterns">Patterns</link></para></listitem>
++ <listitem><para><link linkend="color">Color command</link></para></listitem>
++ <listitem><para><link linkend="notmuch">notmuch patch</link></para></listitem>
++ </itemizedlist>
++ </sect2>
++
++ <sect2 id="sidebar-known-bugs">
++ <title>Known Bugs</title>
++ Unsorted isn't
++ </sect2>
++
++ <sect2 id="sidebar-credits">
++ <title>Credits</title>
++ <itemizedlist>
++ <listitem><para>Justin Hibbits <email>jrh29@po.cwru.edu</email></para></listitem>
++ <listitem><para>Thomer M. Gil <email>mutt@thomer.com</email></para></listitem>
++ <listitem><para>David Sterba <email>dsterba@suse.cz</email></para></listitem>
++ <listitem><para>Evgeni Golov <email>evgeni@debian.org</email></para></listitem>
++ <listitem><para>Fabian Groffen <email>grobian@gentoo.org</email></para></listitem>
++ <listitem><para>Jason DeTiberus <email>jdetiber@redhat.com</email></para></listitem>
++ <listitem><para>Stefan Assmann <email>sassmann@kpanic.de</email></para></listitem>
++ <listitem><para>Steve Kemp <email>steve@steve.org.uk</email></para></listitem>
++ <listitem><para>Terry Chan <email>tchan@lunar-linux.org</email></para></listitem>
++ <listitem><para>Tyler Earnest <email>tylere@rne.st</email></para></listitem>
++ <listitem><para>Richard Russon <email>rich@flatcap.org</email></para></listitem>
++ </itemizedlist>
++ </sect2>
++</sect1>
++
+ </chapter>
+
+ <chapter id="security">
+@@ -9237,6 +10317,17 @@
+
+ <listitem>
+ <cmdsynopsis>
++<command>sidebar_whitelist</command>
++<arg choice="plain">
++<replaceable class="parameter">item</replaceable>
++</arg>
++<arg choice="plain">
++<replaceable class="parameter">command</replaceable>
++</arg>
++</cmdsynopsis>
++</listitem>
++<listitem>
++<cmdsynopsis>
+ <command><link linkend="source">source</link></command>
+ <arg choice="plain">
+ <replaceable class="parameter">filename</replaceable>
+diff -urN mutt-1.6.1/doc/muttrc.sidebar mutt-1.6.1-sidebar/doc/muttrc.sidebar
+--- mutt-1.6.1/doc/muttrc.sidebar 1970-01-01 01:00:00.000000000 +0100
++++ mutt-1.6.1-sidebar/doc/muttrc.sidebar 2016-05-02 03:02:14.932211718 +0100
+@@ -0,0 +1,116 @@
++# This is a complete list of sidebar-related configuration.
++
++# --------------------------------------------------------------------------
++# VARIABLES - shown with their default values
++# --------------------------------------------------------------------------
++
++# Should the Sidebar be shown?
++set sidebar_visible = no
++
++# How wide should the Sidebar be in screen columns?
++# Note: Some characters, e.g. Chinese, take up two columns each.
++set sidebar_width = 20
++
++# Should the mailbox paths be abbreviated?
++set sidebar_short_path = no
++
++# When abbreviating mailbox path names, use any of these characters as path
++# separators. Only the part after the last separators will be shown.
++# For file folders '/' is good. For IMAP folders, often '.' is useful.
++set sidebar_delim_chars = '/.'
++
++# If the mailbox path is abbreviated, should it be indented?
++set sidebar_folder_indent = no
++
++# Indent mailbox paths with this string.
++set sidebar_indent_string = ' '
++
++# Make the Sidebar only display mailboxes that contain new, or flagged,
++# mail.
++set sidebar_new_mail_only = no
++
++# Any mailboxes that are whitelisted will always be visible, even if the
++# sidebar_new_mail_only option is enabled.
++sidebar_whitelist '/home/user/mailbox1'
++sidebar_whitelist '/home/user/mailbox2'
++
++# When searching for mailboxes containing new mail, should the search wrap
++# around when it reaches the end of the list?
++set sidebar_next_new_wrap = no
++
++# The character to use as the divider between the Sidebar and the other Mutt
++# panels.
++# Note: Only the first character of this string is used.
++set sidebar_divider_char = '|'
++
++# Display the Sidebar mailboxes using this format string.
++set sidebar_format = '%B%?F? [%F]?%* %?N?%N/?%S'
++
++# Sidebar will not refresh its list of mailboxes any more frequently than
++# this number of seconds. This will help reduce disk/network traffic.
++set sidebar_refresh_time = 60
++
++# Sort the mailboxes in the Sidebar using this method:
++# count - total number of messages
++# flagged - number of flagged messages
++# new - number of new messages
++# path - mailbox path
++# unsorted - do not sort the mailboxes
++set sidebar_sort_method = 'unsorted'
++
++# --------------------------------------------------------------------------
++# FUNCTIONS - shown with an example mapping
++# --------------------------------------------------------------------------
++
++# Move the highlight to the previous mailbox
++bind index,pager \Cp sidebar-prev
++
++# Move the highlight to the next mailbox
++bind index,pager \Cn sidebar-next
++
++# Open the highlighted mailbox
++bind index,pager \Co sidebar-open
++
++# Move the highlight to the previous page
++# This is useful if you have a LOT of mailboxes.
++bind index,pager <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
+diff -urN mutt-1.6.1/doc/vimrc.sidebar mutt-1.6.1-sidebar/doc/vimrc.sidebar
+--- mutt-1.6.1/doc/vimrc.sidebar 1970-01-01 01:00:00.000000000 +0100
++++ mutt-1.6.1-sidebar/doc/vimrc.sidebar 2016-05-02 03:02:14.933211733 +0100
+@@ -0,0 +1,35 @@
++" Vim syntax file for the mutt sidebar patch
++
++syntax keyword muttrcVarBool skipwhite contained sidebar_folder_indent nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr
++syntax keyword muttrcVarBool skipwhite contained sidebar_new_mail_only nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr
++syntax keyword muttrcVarBool skipwhite contained sidebar_next_new_wrap nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr
++syntax keyword muttrcVarBool skipwhite contained sidebar_short_path nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr
++syntax keyword muttrcVarBool skipwhite contained sidebar_visible nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr
++
++syntax keyword muttrcVarNum skipwhite contained sidebar_refresh_time nextgroup=muttrcSetNumAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr
++syntax keyword muttrcVarNum skipwhite contained sidebar_width nextgroup=muttrcSetNumAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr
++
++syntax keyword muttrcVarStr contained skipwhite sidebar_divider_char nextgroup=muttrcVarEqualsIdxFmt
++syntax keyword muttrcVarStr contained skipwhite sidebar_delim_chars nextgroup=muttrcVarEqualsIdxFmt
++syntax keyword muttrcVarStr contained skipwhite sidebar_format nextgroup=muttrcVarEqualsIdxFmt
++syntax keyword muttrcVarStr contained skipwhite sidebar_indent_string nextgroup=muttrcVarEqualsIdxFmt
++syntax keyword muttrcVarStr contained skipwhite sidebar_sort_method nextgroup=muttrcVarEqualsIdxFmt
++
++syntax keyword muttrcCommand sidebar_whitelist
++
++syntax match muttrcFunction contained "\<sidebar-next\>"
++syntax match muttrcFunction contained "\<sidebar-next-new\>"
++syntax match muttrcFunction contained "\<sidebar-open\>"
++syntax match muttrcFunction contained "\<sidebar-page-down\>"
++syntax match muttrcFunction contained "\<sidebar-page-up\>"
++syntax match muttrcFunction contained "\<sidebar-prev\>"
++syntax match muttrcFunction contained "\<sidebar-prev-new\>"
++syntax match muttrcFunction contained "\<sidebar-toggle-visible\>"
++
++syntax keyword muttrcColorField contained sidebar_divider
++syntax keyword muttrcColorField contained sidebar_flagged
++syntax keyword muttrcColorField contained sidebar_highlight
++syntax keyword muttrcColorField contained sidebar_indicator
++syntax keyword muttrcColorField contained sidebar_new
++
++" vim: syntax=vim
+diff -urN mutt-1.6.1/flags.c mutt-1.6.1-sidebar/flags.c
+--- mutt-1.6.1/flags.c 2016-05-02 03:02:12.403171480 +0100
++++ mutt-1.6.1-sidebar/flags.c 2016-05-02 03:02:15.015213038 +0100
+@@ -25,6 +25,10 @@
#include "sort.h"
#include "mx.h"
-+#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
++ 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-05-02 03:02:12.403171480 +0100
++++ mutt-1.6.1-sidebar/functions.h 2016-05-02 03:02:15.015213038 +0100
+@@ -168,6 +168,16 @@
+ { "decrypt-copy", OP_DECRYPT_COPY, NULL },
{ "decrypt-save", OP_DECRYPT_SAVE, NULL },
++#ifdef USE_SIDEBAR
++ { "sidebar-next", OP_SIDEBAR_NEXT, NULL },
++ { "sidebar-next-new", OP_SIDEBAR_NEXT_NEW, NULL },
++ { "sidebar-open", OP_SIDEBAR_OPEN, NULL },
++ { "sidebar-page-down", OP_SIDEBAR_PAGE_DOWN, NULL },
++ { "sidebar-page-up", OP_SIDEBAR_PAGE_UP, NULL },
++ { "sidebar-prev", OP_SIDEBAR_PREV, NULL },
++ { "sidebar-prev-new", OP_SIDEBAR_PREV_NEW, NULL },
++ { "sidebar-toggle-visible", OP_SIDEBAR_TOGGLE_VISIBLE, NULL },
++#endif
-+ { "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 241758d..92de9db 100644
---- a/globals.h
-+++ b/globals.h
-@@ -118,6 +118,9 @@ 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-05-02 03:02:12.403171480 +0100
++++ mutt-1.6.1-sidebar/globals.h 2016-05-02 03:02:15.015213038 +0100
+@@ -118,6 +118,12 @@
WHERE char *SendCharset;
WHERE char *Sendmail;
WHERE char *Shell;
-+WHERE char *SidebarDelim;
++#ifdef USE_SIDEBAR
++WHERE char *SidebarDelimChars;
++WHERE char *SidebarDividerChar;
+WHERE char *SidebarFormat;
-+WHERE char *SidebarIndentStr;
++WHERE char *SidebarIndentString;
++#endif
WHERE char *Signature;
WHERE char *SimpleSearch;
#if USE_SMTP
-@@ -215,6 +218,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/handler.c b/handler.c
-index 4944d49..d7fde34 100644
---- a/handler.c
-+++ b/handler.c
-@@ -1603,6 +1603,11 @@ static int run_decode_and_handler (BODY *b, STATE *s, handler_t handler, int pla
-
- fseeko (s->fpin, b->offset, 0);
-
-+#ifdef HAVE_FMEMOPEN
-+ char *temp;
-+ size_t tempsize;
-+#endif
-+
- /* see if we need to decode this part before processing it */
- if (b->encoding == ENCBASE64 || b->encoding == ENCQUOTEDPRINTABLE ||
- b->encoding == ENCUUENCODED || plaintext ||
-@@ -1618,6 +1623,14 @@ static int run_decode_and_handler (BODY *b, STATE *s, handler_t handler, int pla
- {
- /* decode to a tempfile, saving the original destination */
- fp = s->fpout;
-+#ifdef HAVE_FMEMOPEN
-+ if ((s->fpout = open_memstream(&temp, &tempsize)) == NULL)
-+ {
-+ mutt_error _("Unable to open memory stream!");
-+ dprint (1, (debugfile, "Can't open memory stream.\n"));
-+ return -1;
-+ }
-+#else
- mutt_mktemp (tempfile, sizeof (tempfile));
- if ((s->fpout = safe_fopen (tempfile, "w")) == NULL)
- {
-@@ -1625,6 +1638,7 @@ static int run_decode_and_handler (BODY *b, STATE *s, handler_t handler, int pla
- dprint (1, (debugfile, "Can't open %s.\n", tempfile));
- return -1;
- }
-+#endif
- /* decoding the attachment changes the size and offset, so save a copy
- * of the "real" values now, and restore them after processing
- */
-@@ -1653,9 +1667,19 @@ static int run_decode_and_handler (BODY *b, STATE *s, handler_t handler, int pla
- /* restore final destination and substitute the tempfile for input */
- s->fpout = fp;
- fp = s->fpin;
-+#ifdef HAVE_FMEMOPEN
-+ if(tempsize)
-+ s->fpin = fmemopen(temp, tempsize, "r");
-+ else /* fmemopen cannot handle zero-length buffers */
-+ s->fpin = safe_fopen ("/dev/null", "r");
-+ if(s->fpin == NULL) {
-+ mutt_perror("failed to re-open memstream!");
-+ return (-1);
-+ }
-+#else
- s->fpin = fopen (tempfile, "r");
- unlink (tempfile);
--
-+#endif
- /* restore the prefix */
- s->prefix = savePrefix;
- }
-@@ -1680,6 +1704,10 @@ static int run_decode_and_handler (BODY *b, STATE *s, handler_t handler, int pla
-
- /* restore the original source stream */
- safe_fclose (&s->fpin);
-+#ifdef HAVE_FMEMOPEN
-+ if(tempsize)
-+ FREE(&temp);
-+#endif
- s->fpin = fp;
- }
- }
-diff --git a/imap/command.c b/imap/command.c
-index d99a99a..5068fca 100644
---- a/imap/command.c
-+++ b/imap/command.c
-@@ -1016,6 +1016,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-05-02 03:02:12.404171496 +0100
++++ mutt-1.6.1-sidebar/imap/command.c 2016-05-02 03:02:14.939211829 +0100
+@@ -1016,6 +1016,14 @@
opened */
status->uidnext = oldun;
-+ /* 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 a8476a4..5dab152 100644
---- a/imap/imap.c
-+++ b/imap/imap.c
-@@ -1541,7 +1541,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-05-02 03:02:12.404171496 +0100
++++ mutt-1.6.1-sidebar/imap/imap.c 2016-05-02 03:02:15.016213054 +0100
+@@ -1535,7 +1535,11 @@
imap_munge_mbox_name (idata, munged, sizeof (munged), name);
snprintf (command, sizeof (command),
-- "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 246020b..2e7371c 100644
---- a/init.h
-+++ b/init.h
-@@ -2061,6 +2061,54 @@ 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-05-02 03:02:12.405171512 +0100
++++ mutt-1.6.1-sidebar/init.c 2016-05-02 03:02:15.017213070 +0100
+@@ -2173,6 +2173,9 @@
+ case DT_SORT_AUX:
+ map = SortAuxMethods;
+ break;
++ case DT_SORT_SIDEBAR:
++ map = SortSidebarMethods;
++ break;
+ default:
+ map = SortMethods;
+ break;
+diff -urN mutt-1.6.1/init.h mutt-1.6.1-sidebar/init.h
+--- mutt-1.6.1/init.h 2016-05-02 03:02:12.407171544 +0100
++++ mutt-1.6.1-sidebar/init.h 2016-05-02 03:02:15.018213086 +0100
+@@ -42,11 +42,12 @@
+ #define DTYPE(x) ((x) & DT_MASK)
+
+ /* subtypes */
+-#define DT_SUBTYPE_MASK 0xf0
++#define DT_SUBTYPE_MASK 0xff0
+ #define DT_SORT_ALIAS 0x10
+ #define DT_SORT_BROWSER 0x20
+ #define DT_SORT_KEYS 0x40
+ #define DT_SORT_AUX 0x80
++#define DT_SORT_SIDEBAR 0x100
+
+ /* flags to parse_set() */
+ #define M_SET_INV (1<<0) /* default is to invert all vars */
+@@ -2665,6 +2666,146 @@
+ ** Command to use when spawning a subshell. By default, the user's login
+ ** shell from \fC/etc/passwd\fP is used.
*/
-+ {"sidebar_delim", DT_STR, R_BOTH, UL &SidebarDelim, UL "|"},
++#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_indentstr", DT_STR, R_BOTH, UL &SidebarIndentStr, UL " "},
++ { "sidebar_delim_chars", DT_STR, R_NONE, UL &SidebarDelimChars, UL "/." },
+ /*
+ ** .pp
-+ ** This specifies the string that is used to indent items
-+ ** with sidebar_folderindent= yes
++ ** This contains the list of characters which you would like to treat
++ ** as folder separators for displaying paths in the sidebar.
++ ** .pp
++ ** Local mail is often arranged in directories: `dir1/dir2/mailbox'.
++ ** .ts
++ ** set sidebar_delim_chars='/'
++ ** .te
++ ** IMAP mailboxes are often named: `folder1.folder2.mailbox'.
++ ** .ts
++ ** set sidebar_delim_chars='.'
++ ** .te
++ ** .pp
++ ** \fBSee also:\fP $$sidebar_short_path, $$sidebar_folder_indent, $$sidebar_indent_string.
+ */
-+ { "sidebar_visible", DT_BOOL, R_BOTH, OPTSIDEBAR, 0 },
++ { "sidebar_folder_indent", DT_BOOL, R_BOTH, OPTSIDEBARFOLDERINDENT, 0 },
+ /*
+ ** .pp
-+ ** This specifies whether or not to show sidebar (left-side list of folders).
++ ** Set this to indent mailboxes in the sidebar.
++ ** .pp
++ ** \fBSee also:\fP $$sidebar_short_path, $$sidebar_indent_string, $$sidebar_delim_chars.
+ */
-+ { "sidebar_sort", DT_BOOL, R_BOTH, OPTSIDEBARSORT, 0 },
++ { "sidebar_format", DT_STR, R_NONE, UL &SidebarFormat, UL "%B%?F? [%F]?%* %?N?%N/?%S" },
+ /*
+ ** .pp
-+ ** This specifies whether or not to sort the sidebar alphabetically.
++ ** 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_width", DT_NUM, R_BOTH, UL &SidebarWidth, 0 },
++ { "sidebar_indent_string", DT_STR, R_BOTH, UL &SidebarIndentString, UL " " },
+ /*
+ ** .pp
-+ ** The width of the sidebar.
++ ** 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_shortpath", DT_BOOL, R_BOTH, OPTSIDEBARSHORTPATH, 0 },
++ { "sidebar_new_mail_only", DT_BOOL, R_BOTH, OPTSIDEBARNEWMAILONLY, 0 },
+ /*
+ ** .pp
-+ ** Should the sidebar shorten the path showed.
++ ** When set, the sidebar will only display mailboxes containing new, or
++ ** flagged, mail.
++ ** .pp
++ ** \fBSee also:\fP $sidebar_whitelist.
+ */
-+ {"sidebar_format", DT_STR, R_NONE, UL &SidebarFormat, UL "%B%?F? [%F]?%* %?N?%N/?%4S"},
++ { "sidebar_next_new_wrap", DT_BOOL, R_BOTH, UL OPTSIDEBARNEXTNEWWRAP, 0 },
+ /*
+ ** .pp
-+ ** Format string for the sidebar. The sequences `%N', `%F' and `%S'
-+ ** will be replaced by the number of new or flagged messages or the total
-+ ** size of them mailbox. `%B' will be replaced with the name of the mailbox.
-+ ** The `%!' sequence will be expanded to `!' if there is one flagged message;
-+ ** to `!!' if there are two flagged messages; and to `n!' for n flagged
-+ ** messages, n>2.
++ ** When set, the \fC<sidebar-next-new>\fP command will not stop and the end of
++ ** the list of mailboxes, but wrap around to the beginning. The
++ ** \fC<sidebar-prev-new>\fP command is similarly affected, wrapping around to
++ ** the end of the list.
+ */
-+ { "sidebar_folderindent", DT_BOOL, R_BOTH, OPTSIDEBARFOLDERINDENT, 0 },
++ { "sidebar_refresh_time", DT_NUM, R_BOTH, UL &SidebarRefreshTime, 60 },
+ /*
+ ** .pp
-+ ** Should folders be indented in the sidebar.
++ ** Set sidebar_refresh_time to the minimum number of seconds between refreshes.
++ ** This will reduced network traffic.
++ ** .pp
++ ** \fBNote:\fP Set to 0 to disable refreshing.
+ */
-+
- { "pgp_use_gpg_agent", DT_BOOL, R_NONE, OPTUSEGPGAGENT, 0},
++ { "sidebar_short_path", DT_BOOL, R_BOTH, OPTSIDEBARSHORTPATH, 0 },
++ /*
++ ** .pp
++ ** By default the sidebar will show the mailbox's path, relative to the
++ ** $$folder variable. Setting \fCsidebar_shortpath=yes\fP will shorten the
++ ** names relative to the previous name. Here's an example:
++ ** .dl
++ ** .dt \fBshortpath=no\fP .dd \fBshortpath=yes\fP .dd \fBshortpath=yes, folderindent=yes, indentstr=".."\fP
++ ** .dt \fCfruit\fP .dd \fCfruit\fP .dd \fCfruit\fP
++ ** .dt \fCfruit.apple\fP .dd \fCapple\fP .dd \fC..apple\fP
++ ** .dt \fCfruit.banana\fP .dd \fCbanana\fP .dd \fC..banana\fP
++ ** .dt \fCfruit.cherry\fP .dd \fCcherry\fP .dd \fC..cherry\fP
++ ** .de
++ ** .pp
++ ** \fBSee also:\fP $$sidebar_delim_chars, $$sidebar_folder_indent, $$sidebar_indent_string.
++ */
++ { "sidebar_sort_method", DT_SORT|DT_SORT_SIDEBAR, R_NONE, UL &SidebarSortMethod, SORT_ORDER },
++ /*
++ ** .pp
++ ** Specifies how to sort entries in the file browser. By default, the
++ ** entries are sorted alphabetically. Valid values:
++ ** .il
++ ** .dd alpha (alphabetically)
++ ** .dd count (all message count)
++ ** .dd date
++ ** .dd desc (description)
++ ** .dd new (new message count)
++ ** .dd size
++ ** .dd unsorted
++ ** .ie
++ ** .pp
++ ** You may optionally use the ``reverse-'' prefix to specify reverse sorting
++ ** order (example: ``\fCset sort_browser=reverse-date\fP'').
++ */
++ { "sidebar_visible", DT_BOOL, R_BOTH, OPTSIDEBAR, 0 },
++ /*
++ ** .pp
++ ** This specifies whether or not to show sidebar. The sidebar shows a list of
++ ** all your mailboxes.
++ ** .pp
++ ** \fBSee also:\fP $$sidebar_format, $$sidebar_width
++ */
++ { "sidebar_width", DT_NUM, R_BOTH, UL &SidebarWidth, 0 },
++ /*
++ ** .pp
++ ** This controls the width of the sidebar. It is measured in screen columns.
++ ** For example: sidebar_width=20 could display 20 ASCII characters, or 10
++ ** Chinese characters.
++ */
++#endif
+ { "sig_dashes", DT_BOOL, R_NONE, OPTSIGDASHES, 1 },
/*
** .pp
-diff --git a/mailbox.h b/mailbox.h
-index 2b2c9a1..000503d 100644
---- a/mailbox.h
-+++ b/mailbox.h
-@@ -27,6 +27,7 @@
+@@ -3652,6 +3793,19 @@
+ { NULL, 0 }
+ };
+
++const struct mapping_t SortSidebarMethods[] = {
++ { "alpha", SORT_PATH },
++ { "count", SORT_COUNT },
++ { "desc", SORT_DESC },
++ { "flagged", SORT_FLAGGED },
++ { "mailbox-order", SORT_ORDER },
++ { "name", SORT_PATH },
++ { "new", SORT_COUNT_NEW },
++ { "path", SORT_PATH },
++ { "unsorted", SORT_ORDER },
++ { NULL, 0 }
++};
++
+
+ /* functions used to parse commands in a rc file */
+
+@@ -3741,6 +3895,9 @@
+ { "send-hook", mutt_parse_hook, M_SENDHOOK },
+ { "send2-hook", mutt_parse_hook, M_SEND2HOOK },
+ { "set", parse_set, 0 },
++#ifdef USE_SIDEBAR
++ { "sidebar_whitelist",parse_list, UL &SidebarWhitelist },
++#endif
+ { "source", parse_source, 0 },
+ { "spam", parse_spam_list, M_SPAM },
+ { "nospam", parse_spam_list, M_NOSPAM },
+diff -urN mutt-1.6.1/keymap.c mutt-1.6.1-sidebar/keymap.c
+--- mutt-1.6.1/keymap.c 2016-05-02 03:02:12.407171544 +0100
++++ mutt-1.6.1-sidebar/keymap.c 2016-05-02 03:02:14.946211940 +0100
+@@ -453,6 +453,9 @@
+ }
+ #endif
+
++ /* update sidebar stats */
++ mutt_buffy_check(0);
++
+ timeout (i * 1000);
+ tmp = mutt_getch();
+ timeout (-1);
+diff -urN mutt-1.6.1/mailbox.h mutt-1.6.1-sidebar/mailbox.h
+--- mutt-1.6.1/mailbox.h 2016-05-02 03:02:12.407171544 +0100
++++ mutt-1.6.1-sidebar/mailbox.h 2016-05-02 03:02:15.018213086 +0100
+@@ -27,6 +27,9 @@
#define M_NEWFOLDER (1<<4) /* create a new folder - same as M_APPEND, but uses
* safe_fopen() for mbox-style folders.
*/
++#ifdef USE_SIDEBAR
+#define M_PEEK (1<<5) /* revert atime back after taking a look (if applicable) */
++#endif
/* mx_open_new_message() */
#define M_ADD_FROM (1<<0) /* add a From_ line */
-diff --git a/main.c b/main.c
-index 0b60d85..0e11dc5 100644
---- a/main.c
-+++ b/main.c
-@@ -50,6 +50,7 @@
- #include <unistd.h>
- #include <errno.h>
- #include <sys/stat.h>
-+#include <limits.h>
- #include <sys/utsname.h>
-
- #ifdef HAVE_GETOPT_H
-@@ -563,7 +564,7 @@ init_extended_keys();
+diff -urN mutt-1.6.1/main.c mutt-1.6.1-sidebar/main.c
+--- mutt-1.6.1/main.c 2016-05-02 03:02:12.408171560 +0100
++++ mutt-1.6.1-sidebar/main.c 2016-05-02 03:02:15.018213086 +0100
+@@ -31,6 +31,9 @@
+ #include "url.h"
+ #include "mutt_crypt.h"
+ #include "mutt_idna.h"
++#ifdef USE_SIDEBAR
++#include "sidebar.h"
++#endif
+
+ #ifdef USE_SASL
+ #include "mutt_sasl.h"
+@@ -485,6 +488,12 @@
+ "-USE_HCACHE "
+ #endif
+
++#ifdef USE_SIDEBAR
++ "+USE_SIDEBAR "
++#else
++ "-USE_SIDEBAR "
++#endif
++
+ );
+
+ #ifdef ISPELL
+@@ -557,7 +566,11 @@
int main (int argc, char **argv)
{
-- char folder[_POSIX_PATH_MAX] = "";
++#ifdef USE_SIDEBAR
+ char folder[PATH_MAX] = "";
++#else
+ char folder[_POSIX_PATH_MAX] = "";
++#endif
char *subject = NULL;
char *includeFile = NULL;
char *draftFile = NULL;
-@@ -1204,6 +1205,13 @@ int main (int argc, char **argv)
+@@ -828,6 +841,9 @@
+ clear ();
+ mutt_error = mutt_curses_error;
+ mutt_message = mutt_curses_message;
++#ifdef USE_SIDEBAR
++ sb_init();
++#endif
+ }
+
+ /* Create the Maildir directory if it doesn't exist. */
+@@ -1184,6 +1200,15 @@
strfcpy (folder, NONULL(Spoolfile), sizeof (folder));
mutt_expand_path (folder, sizeof (folder));
++#ifdef USE_SIDEBAR
+ {
-+ char tmpfolder[PATH_MAX];
++ char tmpfolder[PATH_MAX] = "";
+ strfcpy (tmpfolder, folder, sizeof (tmpfolder));
-+ if(!realpath(tmpfolder, folder))
-+ strfcpy (folder, tmpfolder, sizeof (tmpfolder));
++ if (!realpath (tmpfolder, folder))
++ strfcpy (folder, tmpfolder, sizeof (tmpfolder));
+ }
++#endif
+
mutt_str_replace (&CurrentFolder, folder);
mutt_str_replace (&LastFolder, folder);
-@@ -1226,6 +1234,7 @@ int main (int argc, char **argv)
+@@ -1206,6 +1231,9 @@
if((Context = mx_open_mailbox (folder, ((flags & M_RO) || option (OPTREADONLY)) ? M_READONLY : 0, NULL))
|| !explicit_folder)
{
-+ set_curbuffy(folder);
++#ifdef USE_SIDEBAR
++ sb_set_open_buffy (folder);
++#endif
mutt_index_menu ();
if (Context)
FREE (&Context);
-diff --git a/mbox.c b/mbox.c
-index 9ff8512..e2818a5 100644
---- a/mbox.c
-+++ b/mbox.c
-@@ -104,6 +104,7 @@ int mmdf_parse_mailbox (CONTEXT *ctx)
+diff -urN mutt-1.6.1/Makefile.am mutt-1.6.1-sidebar/Makefile.am
+--- mutt-1.6.1/Makefile.am 2016-05-02 03:02:12.392171305 +0100
++++ mutt-1.6.1-sidebar/Makefile.am 2016-05-02 03:02:15.005212879 +0100
+@@ -77,6 +77,12 @@
+
+ EXTRA_SCRIPTS = smime_keys
+
++if BUILD_SIDEBAR
++mutt_SOURCES += sidebar.c sidebar.h
++endif
++
++EXTRA_DIST += OPS.SIDEBAR
++
+ mutt_dotlock_SOURCES = mutt_dotlock.c
+ mutt_dotlock_LDADD = $(LIBOBJS)
+ mutt_dotlock_DEPENDENCIES = $(LIBOBJS)
+@@ -129,10 +135,10 @@
+ keymap_defs.h: $(OPS) $(srcdir)/gen_defs
+ $(srcdir)/gen_defs $(OPS) > keymap_defs.h
+
+-keymap_alldefs.h: $(srcdir)/OPS $(srcdir)/OPS.PGP $(srcdir)/OPS.MIX $(srcdir)/OPS.CRYPT $(srcdir)/OPS.SMIME $(srcdir)/gen_defs
++keymap_alldefs.h: $(srcdir)/OPS $(srcdir)/OPS.SIDEBAR $(srcdir)/OPS.PGP $(srcdir)/OPS.MIX $(srcdir)/OPS.CRYPT $(srcdir)/OPS.SMIME $(srcdir)/gen_defs
+ rm -f $@
+ $(srcdir)/gen_defs $(srcdir)/OPS $(srcdir)/OPS.PGP \
+- $(srcdir)/OPS.MIX $(srcdir)/OPS.CRYPT $(srcdir)/OPS.SMIME \
++ $(srcdir)/OPS.SIDEBAR $(srcdir)/OPS.MIX $(srcdir)/OPS.CRYPT $(srcdir)/OPS.SMIME \
+ > keymap_alldefs.h
+
+ reldate.h: $(srcdir)/ChangeLog
+diff -urN mutt-1.6.1/mbox.c mutt-1.6.1-sidebar/mbox.c
+--- mutt-1.6.1/mbox.c 2016-05-02 03:02:12.408171560 +0100
++++ mutt-1.6.1-sidebar/mbox.c 2016-05-02 03:02:14.948211972 +0100
+@@ -100,6 +100,9 @@
mutt_perror (ctx->path);
return (-1);
}
++#ifdef USE_SIDEBAR
+ ctx->atime = sb.st_atime;
++#endif
ctx->mtime = sb.st_mtime;
ctx->size = sb.st_size;
-@@ -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 4b13e7c..379b94c 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-05-02 03:02:12.408171560 +0100
++++ mutt-1.6.1-sidebar/menu.c 2016-05-02 03:02:15.019213102 +0100
+@@ -24,6 +24,9 @@
#include "mutt_curses.h"
#include "mutt_menu.h"
#include "mbyte.h"
++#ifdef USE_SIDEBAR
+#include "sidebar.h"
++#endif
char* SearchBuffers[MENU_MAX];
-@@ -184,7 +185,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;
@@ -1008,15 +2472,17 @@ index 4b13e7c..379b94c 100644
mutt_format_string (s, n, cols, cols, FMT_LEFT, ' ', scratch, mutt_strlen (scratch), 1);
s[n - 1] = 0;
-@@ -237,6 +238,7 @@ void menu_redraw_index (MUTTMENU *menu)
+@@ -237,6 +240,9 @@
int do_color;
int attr;
-+ draw_sidebar(1);
++#ifdef USE_SIDEBAR
++ sb_draw();
++#endif
for (i = menu->top; i < menu->top + menu->pagelen; i++)
{
if (i < menu->max)
-@@ -247,7 +249,7 @@ void menu_redraw_index (MUTTMENU *menu)
+@@ -247,7 +253,7 @@
menu_pad_string (buf, sizeof (buf));
ATTRSET(attr);
@@ -1025,16 +2491,19 @@ index 4b13e7c..379b94c 100644
do_color = 1;
if (i == menu->current)
-@@ -270,7 +272,7 @@ void menu_redraw_index (MUTTMENU *menu)
+@@ -270,7 +276,11 @@
else
{
NORMAL_COLOR;
-- CLEARLINE(i - menu->top + menu->offset);
-+ CLEARLINE_WIN (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;
-@@ -287,7 +289,7 @@ void menu_redraw_motion (MUTTMENU *menu)
+@@ -287,7 +297,7 @@
return;
}
@@ -1043,7 +2512,7 @@ index 4b13e7c..379b94c 100644
ATTRSET(menu->color (menu->oldcurrent));
if (option (OPTARROWCURSOR))
-@@ -299,13 +301,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));
@@ -1059,7 +2528,7 @@ index 4b13e7c..379b94c 100644
}
else
{
-@@ -318,7 +320,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);
@@ -1068,7 +2537,7 @@ index 4b13e7c..379b94c 100644
print_enriched_string (menu->color(menu->current), (unsigned char *) buf, 0);
}
menu->redraw &= REDRAW_STATUS;
-@@ -330,7 +332,7 @@ void menu_redraw_current (MUTTMENU *menu)
+@@ -330,7 +340,7 @@
char buf[LONG_STRING];
int attr = menu->color (menu->current);
@@ -1077,7 +2546,7 @@ index 4b13e7c..379b94c 100644
menu_make_entry (buf, sizeof (buf), menu, menu->current);
menu_pad_string (buf, sizeof (buf));
-@@ -882,7 +884,7 @@ int mutt_menuLoop (MUTTMENU *menu)
+@@ -873,7 +883,7 @@
if (option (OPTARROWCURSOR))
@@ -1086,178 +2555,188 @@ index 4b13e7c..379b94c 100644
else if (option (OPTBRAILLEFRIENDLY))
move (menu->current - menu->top + menu->offset, 0);
else
-diff --git a/mh.c b/mh.c
-index bc87660..3121fca 100644
---- a/mh.c
-+++ b/mh.c
-@@ -295,6 +295,32 @@ 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-05-02 03:02:12.409171576 +0100
++++ mutt-1.6.1-sidebar/mh.c 2016-05-02 03:02:15.019213102 +0100
+@@ -295,6 +295,49 @@
mhs_free_sequences (&mhs);
}
-+void mh_buffy_update (const char *path, int *msgcount, int *msg_unread, int *msg_flagged, time_t *sb_last_checked)
++#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(!option(OPTSIDEBAR))
-+ return;
-+
-+ if (mh_read_sequences (&mhs, path) < 0)
-+ return;
-+
-+ msgcount = 0;
-+ msg_unread = 0;
-+ msg_flagged = 0;
-+ for (i = 0; i <= mhs.max; i++)
-+ msgcount++;
-+ if (mhs_check (&mhs, i) & MH_SEQ_UNSEEN) {
-+ msg_unread++;
-+ }
-+ if (mhs_check (&mhs, i) & MH_SEQ_FLAGGED)
-+ msg_flagged++;
-+ mhs_free_sequences (&mhs);
-+ *sb_last_checked = time(NULL);
++ if (!mailbox)
++ return;
++
++ if (!option (OPTSIDEBAR))
++ return;
++
++ struct mh_sequences mhs;
++ memset (&mhs, 0, sizeof (mhs));
++
++ if (mh_read_sequences (&mhs, mailbox->path) < 0)
++ return;
++
++ mailbox->msg_count = 0;
++ mailbox->msg_unread = 0;
++ mailbox->msg_flagged = 0;
++
++ int i;
++ for (i = 0; i <= mhs.max; i++) {
++ mailbox->msg_count++;
++ }
++ if (mhs_check (&mhs, i) & MH_SEQ_UNSEEN) {
++ mailbox->msg_unread++;
++ }
++ if (mhs_check (&mhs, i) & MH_SEQ_FLAGGED) {
++ mailbox->msg_flagged++;
++ }
++ mhs_free_sequences (&mhs);
++ mailbox->sb_last_checked = time (NULL);
+}
+
++#endif
++
static int mh_mkstemp (CONTEXT * dest, FILE ** fp, char **tgt)
{
int fd;
-diff --git a/mutt.h b/mutt.h
-index 26f260e..91e58e9 100644
---- a/mutt.h
-+++ b/mutt.h
-@@ -441,6 +441,10 @@ enum
+diff -urN mutt-1.6.1/mutt_curses.h mutt-1.6.1-sidebar/mutt_curses.h
+--- mutt-1.6.1/mutt_curses.h 2016-05-02 03:02:12.409171576 +0100
++++ mutt-1.6.1-sidebar/mutt_curses.h 2016-05-02 03:02:15.019213102 +0100
+@@ -64,6 +64,9 @@
+ #undef lines
+ #endif /* lines */
+
++#ifdef USE_SIDEBAR
++#define CLEARLINE_WIN(x) move (x,SidebarWidth), clrtoeol()
++#endif
+ #define CLEARLINE(x) move(x,0), clrtoeol()
+ #define CENTERLINE(x,y) move(y, (COLS-strlen(x))/2), addstr(x)
+ #define BEEP() do { if (option (OPTBEEP)) beep(); } while (0)
+@@ -124,6 +127,14 @@
+ MT_COLOR_UNDERLINE,
+ MT_COLOR_INDEX,
+ MT_COLOR_PROMPT,
++#ifdef USE_SIDEBAR
++ MT_COLOR_DIVIDER,
++ MT_COLOR_FLAGGED,
++ MT_COLOR_HIGHLIGHT,
++ MT_COLOR_NEW,
++ MT_COLOR_SB_INDICATOR,
++ MT_COLOR_SB_SPOOLFILE,
++#endif
+ MT_COLOR_MAX
+ };
+
+diff -urN mutt-1.6.1/mutt.h mutt-1.6.1-sidebar/mutt.h
+--- mutt-1.6.1/mutt.h 2016-05-02 03:02:12.409171576 +0100
++++ mutt-1.6.1-sidebar/mutt.h 2016-05-02 03:02:15.019213102 +0100
+@@ -428,6 +428,13 @@
OPTSAVEEMPTY,
OPTSAVENAME,
OPTSCORE,
++#ifdef USE_SIDEBAR
+ OPTSIDEBAR,
-+ OPTSIDEBARSHORTPATH,
-+ OPTSIDEBARSORT,
+ OPTSIDEBARFOLDERINDENT,
++ OPTSIDEBARNEWMAILONLY,
++ OPTSIDEBARNEXTNEWWRAP,
++ OPTSIDEBARSHORTPATH,
++#endif
OPTSIGDASHES,
OPTSIGONTOP,
OPTSORTRE,
-@@ -887,6 +891,7 @@ typedef struct _context
+@@ -872,6 +879,9 @@
{
char *path;
FILE *fp;
++#ifdef USE_SIDEBAR
+ time_t atime;
++#endif
time_t mtime;
off_t size;
off_t vsize;
-@@ -927,6 +932,7 @@ typedef struct _context
+@@ -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 --git a/mutt_curses.h b/mutt_curses.h
-index 93d9aea..888aa1c 100644
---- a/mutt_curses.h
-+++ b/mutt_curses.h
-@@ -64,6 +64,7 @@
- #undef lines
- #endif /* lines */
+diff -urN mutt-1.6.1/muttlib.c mutt-1.6.1-sidebar/muttlib.c
+--- mutt-1.6.1/muttlib.c 2016-05-02 03:02:12.410171592 +0100
++++ mutt-1.6.1-sidebar/muttlib.c 2016-05-02 03:02:15.020213118 +0100
+@@ -1282,7 +1282,7 @@
+ pl = pw = 1;
-+#define CLEARLINE_WIN(x) move(x,SidebarWidth), clrtoeol()
- #define CLEARLINE(x) move(x,0), clrtoeol()
- #define CENTERLINE(x,y) move(y, (COLS-strlen(x))/2), addstr(x)
- #define BEEP() do { if (option (OPTBEEP)) beep(); } while (0)
-@@ -124,6 +125,8 @@ enum
- MT_COLOR_UNDERLINE,
- MT_COLOR_INDEX,
- MT_COLOR_PROMPT,
-+ MT_COLOR_NEW,
-+ MT_COLOR_FLAGGED,
- MT_COLOR_MAX
- };
+ /* see if there's room to add content, else ignore */
+- if ((col < COLS && wlen < destlen) || soft)
++ if ((col < (COLS - SidebarWidth) && (wlen < destlen)) || soft)
+ {
+ int pad;
+
+@@ -1293,7 +1293,7 @@
-diff --git a/mutt_menu.h b/mutt_menu.h
-index bbcd722..4999748 100644
---- a/mutt_menu.h
-+++ b/mutt_menu.h
-@@ -34,6 +34,7 @@
+ /* try to consume as many columns as we can, if we don't have
+ * memory for that, use as much memory as possible */
+- pad = (COLS - col - wid) / pw;
++ pad = (COLS - SidebarWidth - col - wid) / pw;
+ if (pad > 0 && wlen + (pad * pl) + len > destlen)
+ pad = ((signed)(destlen - wlen - len)) / pl;
+ if (pad > 0)
+@@ -1312,13 +1312,13 @@
+ /* \0-terminate dest for length computation in mutt_wstr_trunc() */
+ *wptr = 0;
+ /* make sure right part is at most as wide as display */
+- len = mutt_wstr_trunc (buf, destlen, COLS-offset, &wid);
++ len = mutt_wstr_trunc (buf, destlen, COLS - offset - SidebarWidth, &wid);
+ /* truncate left so that right part fits completely in */
+ wlen = mutt_wstr_trunc (dest, destlen - len, col + pad*pw -offset, &col);
+ wptr = dest + wlen;
+ }
+ if (len + wlen > destlen)
+- len = mutt_wstr_trunc (buf, destlen - wlen, COLS - col, NULL);
++ len = mutt_wstr_trunc (buf, destlen - wlen, COLS - SidebarWidth - col, NULL);
+ memcpy (wptr, buf, len);
+ wptr += len;
+ wlen += len;
+diff -urN mutt-1.6.1/mutt_menu.h mutt-1.6.1-sidebar/mutt_menu.h
+--- mutt-1.6.1/mutt_menu.h 2016-05-02 03:02:12.409171576 +0100
++++ mutt-1.6.1-sidebar/mutt_menu.h 2016-05-02 03:02:15.019213102 +0100
+@@ -34,6 +34,9 @@
#define REDRAW_FULL (1<<5)
#define REDRAW_BODY (1<<6)
#define REDRAW_SIGWINCH (1<<7)
++#ifdef USE_SIDEBAR
+#define REDRAW_SIDEBAR (1<<8)
++#endif
#define M_MODEFMT "-- Mutt: %s"
-diff --git a/muttlib.c b/muttlib.c
-index 53cb4a3..3c4e768 100644
---- a/muttlib.c
-+++ b/muttlib.c
-@@ -1282,6 +1282,8 @@ void mutt_FormatString (char *dest, /* output buffer */
- pl = pw = 1;
+diff -urN mutt-1.6.1/mx.c mutt-1.6.1-sidebar/mx.c
+--- mutt-1.6.1/mx.c 2016-05-02 03:02:12.410171592 +0100
++++ mutt-1.6.1-sidebar/mx.c 2016-05-02 03:02:15.020213118 +0100
+@@ -29,6 +29,9 @@
+ #include "copy.h"
+ #include "keymap.h"
+ #include "url.h"
++#ifdef USE_SIDEBAR
++#include "sidebar.h"
++#endif
- /* see if there's room to add content, else ignore */
-+ if ( DrawFullLine )
-+ {
- if ((col < COLS && wlen < destlen) || soft)
- {
- int pad;
-@@ -1325,6 +1327,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 */
-+ 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)
-+ 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 be2d0e9..16fcdf4 100644
---- a/mx.c
-+++ b/mx.c
-@@ -595,6 +595,7 @@ static int mx_open_mailbox_append (CONTEXT *ctx, int flags)
+ #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
@@ -1265,104 +2744,137 @@ index be2d0e9..16fcdf4 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,13 +724,26 @@ 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 */
-- mutt_buffy_setnotified(ctx->path);
-+ if(!ctx->peekonly)
-+ mutt_buffy_setnotified(ctx->path);
++#ifdef USE_SIDEBAR
++ if (!ctx->peekonly)
++#endif
+ mutt_buffy_setnotified(ctx->path);
if (ctx->mx_close)
- ctx->mx_close (ctx);
-@@ -739,6 +755,8 @@ void mx_fastclose_mailbox (CONTEXT *ctx)
+@@ -719,6 +740,10 @@
mutt_clear_threads (ctx);
for (i = 0; i < ctx->msgcount; i++)
mutt_free_header (&ctx->hdrs[i]);
++#ifdef USE_SIDEBAR
+ ctx->msgcount -= ctx->deleted;
-+ set_buffystats(ctx);
++ sb_set_buffystats (ctx);
++#endif
FREE (&ctx->hdrs);
FREE (&ctx->v2r);
- #ifdef USE_COMPRESSED
-@@ -895,6 +913,10 @@ int mx_close_mailbox (CONTEXT *ctx, int *index_hint)
+ FREE (&ctx->path);
+@@ -812,6 +837,12 @@
if (!ctx->hdrs[i]->deleted && ctx->hdrs[i]->read
&& !(ctx->hdrs[i]->flagged && option (OPTKEEPFLAGGED)))
read_msgs++;
++#ifdef USE_SIDEBAR
+ if (ctx->hdrs[i]->deleted && !ctx->hdrs[i]->read)
+ ctx->unread--;
+ if (ctx->hdrs[i]->deleted && ctx->hdrs[i]->flagged)
+ ctx->flagged--;
++#endif
}
if (read_msgs && quadoption (OPT_MOVE) != M_NO)
-diff --git a/mx.h b/mx.h
-index d926cf6..ab398cb 100644
---- a/mx.h
-+++ b/mx.h
-@@ -60,6 +60,7 @@ void mbox_reset_atime (CONTEXT *, struct stat *);
+diff -urN mutt-1.6.1/mx.h mutt-1.6.1-sidebar/mx.h
+--- mutt-1.6.1/mx.h 2016-05-02 03:02:12.410171592 +0100
++++ mutt-1.6.1-sidebar/mx.h 2016-05-02 03:02:15.020213118 +0100
+@@ -26,6 +26,7 @@
+ #define _MX_H
+
+ #include "mailbox.h"
++#include "buffy.h"
+
+ /* supported mailbox formats */
+ enum
+@@ -57,6 +58,9 @@
int mh_read_dir (CONTEXT *, const char *);
int mh_sync_mailbox (CONTEXT *, int *);
int mh_check_mailbox (CONTEXT *, int *);
-+void mh_buffy_update (const char *, int *, int *, int *, time_t *);
++#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 b9f72c2..676fd39 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-05-02 03:02:15.005212879 +0100
+@@ -0,0 +1,8 @@
++OP_SIDEBAR_NEXT "Move the highlight to next mailbox"
++OP_SIDEBAR_NEXT_NEW "Move the highlight to next mailbox with new mail"
++OP_SIDEBAR_OPEN "Open highlighted mailbox"
++OP_SIDEBAR_PAGE_DOWN "Scroll the Sidebar down 1 page"
++OP_SIDEBAR_PAGE_UP "Scroll the Sidebar up 1 page"
++OP_SIDEBAR_PREV "Move the highlight to previous mailbox"
++OP_SIDEBAR_PREV_NEW "Move the highlight to previous mailbox with new mail"
++OP_SIDEBAR_TOGGLE_VISIBLE "Make the Sidebar (in)visible"
+diff -urN mutt-1.6.1/pager.c mutt-1.6.1-sidebar/pager.c
+--- mutt-1.6.1/pager.c 2016-05-02 03:02:12.411171608 +0100
++++ mutt-1.6.1-sidebar/pager.c 2016-05-02 03:02:15.021213134 +0100
+@@ -29,6 +29,9 @@
#include "pager.h"
#include "attach.h"
#include "mbyte.h"
++#ifdef USE_SIDEBAR
+#include "sidebar.h"
++#endif
#include "mutt_crypt.h"
-@@ -1096,6 +1097,7 @@ static int format_line (struct line_t **lineInfo, int n, unsigned char *buf,
+@@ -1096,6 +1099,9 @@
wchar_t wc;
mbstate_t mbstate;
int wrap_cols = mutt_term_width ((flags & M_PAGER_NOWRAP) ? 0 : Wrap);
++#ifdef USE_SIDEBAR
+ wrap_cols -= SidebarWidth;
++#endif
if (check_attachment_marker ((char *)buf) == 0)
wrap_cols = COLS;
-@@ -1573,6 +1575,7 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra)
+@@ -1491,7 +1497,7 @@
+ * a newline (grr!).
+ */
+ #ifndef USE_SLANG_CURSES
+- if (col < COLS)
++ if (col < (COLS - SidebarWidth))
+ #endif
+ addch ('\n');
+
+@@ -1573,6 +1579,7 @@
int bodyoffset = 1; /* offset of first line of real text */
int statusoffset = 0; /* offset for the status bar */
-+ int statuswidth;
++ int statuswidth = COLS;
int helpoffset = LINES - 2; /* offset for the help bar. */
int bodylen = LINES - 2 - bodyoffset; /* length of displayable area */
-@@ -1747,7 +1750,7 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra)
+@@ -1747,7 +1754,7 @@
if ((redraw & REDRAW_BODY) || topline != oldtopline)
{
do {
@@ -1371,27 +2883,35 @@ index b9f72c2..676fd39 100644
curline = oldtopline = topline;
lines = 0;
force_redraw = 0;
-@@ -1760,6 +1763,7 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra)
+@@ -1760,6 +1767,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);
-@@ -1772,6 +1776,7 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra)
+@@ -1772,6 +1782,9 @@
addch ('~');
addch ('\n');
lines++;
-+ move(lines + bodyoffset, SidebarWidth);
++#ifdef USE_SIDEBAR
++ move (lines + bodyoffset, SidebarWidth);
++#endif
}
NORMAL_COLOR;
-@@ -1789,29 +1794,39 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra)
+@@ -1789,29 +1802,49 @@
hfi.ctx = Context;
hfi.pager_progress = pager_progress_str;
-+ statuswidth = COLS - (option(OPTSTATUSONTOP) && PagerIndexLines > 0 ? SidebarWidth : 0);
++#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));
@@ -1402,12 +2922,16 @@ index b9f72c2..676fd39 100644
- move (statusoffset, 0);
+ move (statusoffset, SidebarWidth);
SETCOLOR (MT_COLOR_STATUS);
-+ if(option(OPTSTATUSONTOP) && PagerIndexLines > 0) {
-+ CLEARLINE_WIN (statusoffset);
++#ifdef USE_SIDEBAR
++ short sw = SidebarWidth;
++ if (option (OPTSTATUSONTOP) && PagerIndexLines > 0) {
++ CLEARLINE_WIN (statusoffset);
+ } else {
-+ CLEARLINE (statusoffset);
-+ DrawFullLine = 1; /* for mutt_make_string_info */
++ CLEARLINE (statusoffset);
++ /* Temporarily lie about the sidebar width */
++ SidebarWidth = 0;
+ }
++#endif
if (IsHeader (extra) || IsMsgAttach (extra))
{
@@ -1426,16 +2950,20 @@ index b9f72c2..676fd39 100644
- mutt_paddstr (COLS, bn);
+ mutt_paddstr (statuswidth, bn);
}
-+ if(!option(OPTSTATUSONTOP) || PagerIndexLines == 0)
-+ DrawFullLine = 0; /* reset */
++#ifdef USE_SIDEBAR
++ if (!option (OPTSTATUSONTOP) || PagerIndexLines == 0)
++ SidebarWidth = sw; /* Restore the sidebar width */
++#endif
NORMAL_COLOR;
if (option(OPTTSENABLED) && TSSupported)
{
-@@ -1827,16 +1842,22 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra)
+@@ -1827,16 +1860,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
++ sb_draw();
++#endif
/* print out the index status bar */
menu_status_line (buffer, sizeof (buffer), index, NONULL(Status));
@@ -1449,590 +2977,1340 @@ index b9f72c2..676fd39 100644
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)
++ sb_draw();
++#endif
+
redraw = 0;
if (option(OPTBRAILLEFRIENDLY)) {
-@@ -2783,6 +2804,13 @@ search_next:
+@@ -2498,8 +2541,12 @@
+ ch = 0;
+ }
+
+- if (option (OPTFORCEREDRAWPAGER))
++ if (option (OPTFORCEREDRAWPAGER)) {
+ redraw = REDRAW_FULL;
++#ifdef USE_SIDEBAR
++ sb_draw();
++#endif
++ }
+ unset_option (OPTFORCEREDRAWINDEX);
+ unset_option (OPTFORCEREDRAWPAGER);
+ break;
+@@ -2777,6 +2824,22 @@
mutt_what_key ();
break;
-+ 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:
++ 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/pattern.c b/pattern.c
-index aeef591..406fd84 100644
---- a/pattern.c
-+++ b/pattern.c
-@@ -154,6 +154,10 @@ msg_search (CONTEXT *ctx, pattern_t* pat, int msgno)
- HEADER *h = ctx->hdrs[msgno];
- char *buf;
- size_t blen;
-+#ifdef HAVE_FMEMOPEN
-+ char *temp;
-+ size_t tempsize;
-+#endif
-
- if ((msg = mx_open_message (ctx, msgno)) != NULL)
- {
-@@ -163,12 +167,20 @@ msg_search (CONTEXT *ctx, pattern_t* pat, int msgno)
- memset (&s, 0, sizeof (s));
- s.fpin = msg->fp;
- s.flags = M_CHARCONV;
-+#ifdef HAVE_FMEMOPEN
-+ if((s.fpout = open_memstream(&temp, &tempsize)) == NULL)
-+ {
-+ mutt_perror ("Error opening memstream");
-+ return (0);
-+ }
-+#else
- mutt_mktemp (tempfile, sizeof (tempfile));
- if ((s.fpout = safe_fopen (tempfile, "w+")) == NULL)
- {
- mutt_perror (tempfile);
- return (0);
- }
-+#endif
-
- if (pat->op != M_BODY)
- mutt_copy_header (msg->fp, h, s.fpout, CH_FROM | CH_DECODE, NULL);
-@@ -184,7 +196,11 @@ msg_search (CONTEXT *ctx, pattern_t* pat, int msgno)
- if (s.fpout)
- {
- safe_fclose (&s.fpout);
-+#ifdef HAVE_FMEMOPEN
-+ FREE(&temp);
-+#else
- unlink (tempfile);
-+#endif
- }
- return (0);
- }
-@@ -193,11 +209,28 @@ msg_search (CONTEXT *ctx, pattern_t* pat, int msgno)
- mutt_body_handler (h->content, &s);
- }
-
-+#ifdef HAVE_FMEMOPEN
-+ fclose(s.fpout);
-+ lng = tempsize;
-+
-+ if(tempsize) {
-+ if ((fp = fmemopen(temp, tempsize, "r")) == NULL) {
-+ mutt_perror ("Error re-opening memstream");
-+ return (0);
-+ }
-+ } else { /* fmemopen cannot handle empty buffers */
-+ if ((fp = safe_fopen ("/dev/null", "r")) == NULL) {
-+ mutt_perror ("Error opening /dev/null");
-+ return (0);
-+ }
-+ }
-+#else
- fp = s.fpout;
- fflush (fp);
- fseek (fp, 0, 0);
- fstat (fileno (fp), &st);
- lng = (long) st.st_size;
-+#endif
- }
- else
- {
-@@ -244,7 +277,12 @@ msg_search (CONTEXT *ctx, pattern_t* pat, int msgno)
- if (option (OPTTHOROUGHSRC))
- {
- safe_fclose (&fp);
-+#ifdef HAVE_FMEMOPEN
-+ if(tempsize)
-+ FREE (&temp);
-+#else
- unlink (tempfile);
-+#endif
- }
- }
-
-diff --git a/protos.h b/protos.h
-index 98a207a..5c83f82 100644
---- a/protos.h
-+++ b/protos.h
-@@ -36,6 +36,13 @@ struct hdr_format_info
- const char *pager_progress;
- };
-
-+struct sidebar_entry {
-+ char box[SHORT_STRING];
-+ unsigned int size;
-+ unsigned int new;
-+ unsigned int flagged;
-+};
+diff -urN mutt-1.6.1/PATCHES mutt-1.6.1-sidebar/PATCHES
+--- mutt-1.6.1/PATCHES 2016-05-02 03:02:12.396171369 +0100
++++ mutt-1.6.1-sidebar/PATCHES 2016-05-02 03:02:15.008212927 +0100
+@@ -0,0 +1 @@
++patch-sidebar-neo-20160502
+diff -urN mutt-1.6.1/README.sidebar mutt-1.6.1-sidebar/README.sidebar
+--- mutt-1.6.1/README.sidebar 1970-01-01 01:00:00.000000000 +0100
++++ mutt-1.6.1-sidebar/README.sidebar 2016-05-02 03:02:15.008212927 +0100
+@@ -0,0 +1,145 @@
++Sidebar Patch
++=============
++
++ Overview of mailboxes
++
++ NOTES:
++
++ If you haven't used the sidebar before, you might like to read the
++ Sidebar Introduction:
++
++ http://www.neomutt.org/sidebar-intro.html
++
++ If you have used an older version of the Sidebar, please note that some
++ of the configuration has changed.
++
++ http://www.neomutt.org/sidebar-intro.html#intro-sidebar-config-changes
++
++Patch
++-----
++
++ To check if Mutt supports "Sidebar", look for "+USE_SIDEBAR" in the mutt
++ version.
++
++ Dependencies
++ * mutt-1.5.24
++
++Introduction
++------------
++
++ The Sidebar shows a list of all your mailboxes. The list can be turned on
++ and off, it can be themed and the list style can be configured.
++
++ This part of the manual is a reference guide. If you want a simple
++ introduction with examples see the Sidebar Howto. If you just want to get
++ started, you could use the sample Sidebar muttrc.
++
++ This version of Sidebar is based on Terry Chan's [2015-11-11
++ release](http://www.lunar-linux.org/mutt-sidebar/). It contains many new
++ features, lots of bugfixes.
++
++Variables
++---------
++
++ Sidebar Variables
++
++ | Name | Type | Default |
++ |-------------------------|---------|-----------------------------|
++ | 'sidebar_delim_chars' | string | '/.' |
++ | 'sidebar_divider_char' | string | '|' |
++ | 'sidebar_folder_indent' | boolean | 'no' |
++ | 'sidebar_format' | string | '%B%?F? [%F]?%* %?N?%N/?%S' |
++ | 'sidebar_indent_string' | string | '  ' (two spaces) |
++ | 'sidebar_new_mail_only' | boolean | 'no' |
++ | 'sidebar_next_new_wrap' | boolean | 'no' |
++ | 'sidebar_refresh_time' | number | '60' |
++ | 'sidebar_short_path' | boolean | 'no' |
++ | 'sidebar_sort_method' | enum | 'SORT_ORDER' |
++ | 'sidebar_visible' | boolean | 'no' |
++ | 'sidebar_whitelist' | list | (empty) |
++ | 'sidebar_width' | number | '20' |
++
++Functions
++---------
++
++ Sidebar Functions
+
- void mutt_make_string_info (char *, size_t, const char *, struct hdr_format_info *, format_flag);
-
- int mutt_extract_token (BUFFER *, BUFFER *, int);
-diff --git a/sidebar.c b/sidebar.c
-new file mode 100644
-index 0000000..e9d9eba
---- /dev/null
-+++ b/sidebar.c
-@@ -0,0 +1,410 @@
-+/*
-+ * Copyright (C) ????-2004 Justin Hibbits <jrh29@po.cwru.edu>
++ Sidebar adds the following functions to Mutt. By default, none of them are
++ bound to keys.
++
++ | 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 |
++
++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>
++
+diff -urN mutt-1.6.1/sidebar.c mutt-1.6.1-sidebar/sidebar.c
+--- mutt-1.6.1/sidebar.c 1970-01-01 01:00:00.000000000 +0100
++++ mutt-1.6.1-sidebar/sidebar.c 2016-05-02 03:02:15.023213165 +0100
+@@ -0,0 +1,1069 @@
++/* Copyright (C) 2004 Justin Hibbits <jrh29@po.cwru.edu>
+ * Copyright (C) 2004 Thomer M. Gil <mutt@thomer.com>
-+ *
++ * Copyright (C) 2015-2016 Richard Russon <rich@flatcap.org>
++ *
+ * 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 <libgen.h>
+#include "keymap.h"
-+#include <stdbool.h>
++#include "mutt_curses.h"
++#include "mutt_menu.h"
++#include "sort.h"
++
++/* Previous values for some sidebar config */
++static short OldVisible; /* sidebar_visible */
++static short OldWidth; /* sidebar_width */
++static short PreviousSort; /* sidebar_sort_method */
++static time_t LastRefresh; /* Time of last refresh */
++
++/* Keep track of various BUFFYs */
++static BUFFY *TopBuffy; /* First mailbox visible in sidebar */
++static BUFFY *OpnBuffy; /* Current (open) mailbox */
++static BUFFY *HilBuffy; /* Highlighted mailbox */
++static BUFFY *BotBuffy; /* Last mailbox visible in sidebar */
++static BUFFY *Outgoing; /* Last mailbox in the linked list */
++
++/**
++ * struct sidebar_entry - Info about folders in the sidebar
++ *
++ * Used in the mutt_FormatString callback
++ */
++struct sidebar_entry {
++ char box[SHORT_STRING];
++ BUFFY *buffy;
++};
++
++
++/**
++ * find_next_new - Find the next folder that contains new mail
++ * @wrap: Wrap around to the beginning if the end is reached
++ *
++ * Search down the list of mail folders for one containing new mail.
++ *
++ * Returns:
++ * BUFFY*: Success
++ * NULL: Failure
++ */
++static BUFFY *
++find_next_new (int wrap)
++{
++ BUFFY *b = HilBuffy;
++ if (!b)
++ return NULL;
++
++ do {
++ b = b->next;
++ if (!b && wrap) {
++ b = Incoming;
++ }
++ if (!b || (b == HilBuffy)) {
++ break;
++ }
++ if (b->msg_unread > 0) {
++ return b;
++ }
++ } while (b);
+
-+/*BUFFY *CurBuffy = 0;*/
-+static BUFFY *TopBuffy = 0;
-+static BUFFY *BottomBuffy = 0;
-+static int known_lines = 0;
++ return NULL;
++}
+
-+void calc_boundaries() {
++/**
++ * find_prev_new - Find the previous folder that contains new mail
++ * @wrap: Wrap around to the beginning if the end is reached
++ *
++ * Search up the list of mail folders for one containing new mail.
++ *
++ * Returns:
++ * BUFFY*: Success
++ * NULL: Failure
++ */
++static BUFFY *
++find_prev_new (int wrap)
++{
++ BUFFY *b = HilBuffy;
++ if (!b)
++ return NULL;
+
-+ BUFFY *tmp = Incoming;
++ do {
++ b = b->prev;
++ if (!b && wrap) {
++ b = Outgoing;
++ }
++ if (!b || (b == HilBuffy)) {
++ break;
++ }
++ if (b->msg_unread > 0) {
++ return b;
++ }
++ } while (b);
+
-+ int count = LINES - 2 - (option(OPTHELP) ? 1 : 0);
++ return NULL;
++}
+
-+ if ( known_lines != LINES ) {
-+ TopBuffy = BottomBuffy = 0;
-+ known_lines = LINES;
++/**
++ * cb_format_str - Create the string to show in the sidebar
++ * @dest: Buffer in which to save string
++ * @destlen: Buffer length
++ * @col: Starting column, UNUSED
++ * @op: printf-like operator, e.g. 'B'
++ * @src: printf-like format string
++ * @prefix: Field formatting string, UNUSED
++ * @ifstring: If condition is met, display this string
++ * @elsestring: Otherwise, display this string
++ * @data: Pointer to our sidebar_entry
++ * @flags: Format flags, e.g. M_FORMAT_OPTIONAL
++ *
++ * cb_format_str is a callback function for mutt_FormatString. It understands
++ * five operators. '%B' : Mailbox name, '%F' : Number of flagged messages,
++ * '%N' : Number of new messages, '%S' : Size (total number of messages),
++ * '%!' : Icon denoting number of flagged messages.
++ *
++ * Returns: src (unchanged)
++ */
++static const char *
++cb_format_str (char *dest, size_t destlen, size_t col, char op, const char *src,
++ const char *prefix, const char *ifstring, const char *elsestring,
++ unsigned long data, format_flag flags)
++{
++ struct sidebar_entry *sbe = (struct sidebar_entry *) data;
++ unsigned int optional;
++ char fmt[SHORT_STRING], buf[SHORT_STRING];
++
++ if (!sbe || !dest)
++ return src;
++
++ dest[0] = 0; /* Just in case there's nothing to do */
++
++ BUFFY *b = sbe->buffy;
++ if (!b)
++ return src;
++
++ int c = Context && (mutt_strcmp (Context->path, b->path) == 0);
++
++ optional = flags & M_FORMAT_OPTIONAL;
++
++ switch (op) {
++ case 'B':
++ mutt_format_s (dest, destlen, prefix, sbe->box);
++ break;
++
++ case 'd':
++ if (!optional) {
++ snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
++ snprintf (dest, destlen, fmt, c ? Context->deleted : 0);
++ } else if ((c && Context->deleted == 0) || !c) {
++ optional = 0;
++ }
++ break;
++
++ case 'F':
++ if (!optional) {
++ snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
++ snprintf (dest, destlen, fmt, b->msg_flagged);
++ } else if (b->msg_flagged == 0) {
++ optional = 0;
++ }
++ break;
++
++ case 'L':
++ if (!optional) {
++ snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
++ snprintf (dest, destlen, fmt, c ? Context->vcount : b->msg_count);
++ } else if ((c && Context->vcount == b->msg_count) || !c) {
++ optional = 0;
++ }
++ break;
++
++ case 'N':
++ if (!optional) {
++ snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
++ snprintf (dest, destlen, fmt, b->msg_unread);
++ } else if (b->msg_unread == 0) {
++ optional = 0;
++ }
++ break;
++
++ case 'S':
++ if (!optional) {
++ snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
++ snprintf (dest, destlen, fmt, b->msg_count);
++ } else if (b->msg_count == 0) {
++ optional = 0;
++ }
++ break;
++
++ case 't':
++ if (!optional) {
++ snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
++ snprintf (dest, destlen, fmt, c ? Context->tagged : 0);
++ } else if ((c && Context->tagged == 0) || !c) {
++ optional = 0;
++ }
++ break;
++
++ case '!':
++ if (b->msg_flagged == 0) {
++ mutt_format_s (dest, destlen, prefix, "");
++ } else if (b->msg_flagged == 1) {
++ mutt_format_s (dest, destlen, prefix, "!");
++ } else if (b->msg_flagged == 2) {
++ mutt_format_s (dest, destlen, prefix, "!!");
++ } else {
++ snprintf (buf, sizeof (buf), "%d!", b->msg_flagged);
++ mutt_format_s (dest, destlen, prefix, buf);
++ }
++ break;
++ }
++
++ if (optional)
++ mutt_FormatString (dest, destlen, col, ifstring, cb_format_str, (unsigned long) sbe, flags);
++ else if (flags & M_FORMAT_OPTIONAL)
++ mutt_FormatString (dest, destlen, col, elsestring, cb_format_str, (unsigned long) sbe, flags);
++
++ /* We return the format string, unchanged */
++ return src;
++}
++
++/**
++ * make_sidebar_entry - Turn mailbox data into a sidebar string
++ * @buf: Buffer in which to save string
++ * @buflen: Buffer length
++ * @width: Desired width in screen cells
++ * @box: Mailbox name
++ * @size: Size (total number of messages)
++ * @new: Number of new messages
++ * @flagged: Number of flagged messages
++ *
++ * Take all the relevant mailbox data and the desired screen width and then get
++ * mutt_FormatString to do the actual work. mutt_FormatString will callback to
++ * us using cb_format_str() for the sidebar specific formatting characters.
++ */
++static void
++make_sidebar_entry (char *buf, unsigned int buflen, int width, char *box,
++ BUFFY *b)
++{
++ struct sidebar_entry sbe;
++
++ if (!buf || !box || !b)
++ return;
++
++ sbe.buffy = b;
++ strncpy (sbe.box, box, sizeof (sbe.box) - 1);
++
++ int box_len = strlen (box);
++ sbe.box[box_len] = '\0';
++
++ /* Temporarily lie about the screen width */
++ int oc = COLS;
++ COLS = width + SidebarWidth;
++ mutt_FormatString (buf, buflen, 0, NONULL(SidebarFormat), cb_format_str, (unsigned long) &sbe, 0);
++ COLS = oc;
++
++ /* Force string to be exactly the right width */
++ int w = mutt_strwidth (buf);
++ int s = strlen (buf);
++ if (w < width) {
++ /* Pad with spaces */
++ memset (buf + s, ' ', width - w);
++ buf[s + width - w] = 0;
++ } else if (w > width) {
++ /* Truncate to fit */
++ int len = mutt_wstr_trunc (buf, buflen, width, NULL);
++ buf[len] = 0;
++ }
++}
++
++/**
++ * cb_qsort_buffy - qsort callback to sort BUFFYs
++ * @a: First BUFFY to compare
++ * @b: Second BUFFY to compare
++ *
++ * Compare the paths of two BUFFYs taking the locale into account.
++ *
++ * Returns:
++ * -1: a precedes b
++ * 0: a and b are identical
++ * 1: b precedes a
++ */
++static int
++cb_qsort_buffy (const void *a, const void *b)
++{
++ const BUFFY *b1 = *(const BUFFY **) a;
++ const BUFFY *b2 = *(const BUFFY **) b;
++
++ /* Special case -- move hidden BUFFYs to the end */
++ if (b1->is_hidden != b2->is_hidden) {
++ if (b1->is_hidden)
++ return 1;
++ else
++ return -1;
+ }
-+ for ( ; tmp->next != 0; tmp = tmp->next )
-+ tmp->next->prev = tmp;
-+
-+ if ( TopBuffy == 0 && BottomBuffy == 0 )
-+ TopBuffy = Incoming;
-+ if ( BottomBuffy == 0 ) {
-+ BottomBuffy = TopBuffy;
-+ while ( --count && BottomBuffy->next )
-+ BottomBuffy = BottomBuffy->next;
++
++ int result = 0;
++
++ switch ((SidebarSortMethod & SORT_MASK)) {
++ case SORT_COUNT:
++ result = (b2->msg_count - b1->msg_count);
++ break;
++ case SORT_COUNT_NEW:
++ result = (b2->msg_unread - b1->msg_unread);
++ break;
++ case SORT_FLAGGED:
++ result = (b2->msg_flagged - b1->msg_flagged);
++ break;
++ case SORT_PATH:
++ result = mutt_strcasecmp (b1->path, b2->path);
++ break;
+ }
-+ else if ( TopBuffy == CurBuffy->next ) {
-+ BottomBuffy = CurBuffy;
-+ tmp = BottomBuffy;
-+ while ( --count && tmp->prev)
-+ tmp = tmp->prev;
-+ TopBuffy = tmp;
++
++ if (SidebarSortMethod & SORT_REVERSE)
++ result = -result;
++
++ return result;
++}
++
++/**
++ * buffy_going - Prevent our pointers becoming invalid
++ * @b: BUFFY about to be deleted
++ *
++ * If we receive a delete-notification for a BUFFY, we need to change any
++ * pointers we have to reference a different BUFFY, or set them to NULL.
++ *
++ * We don't update the prev/next pointers, they'll be fixed on the next
++ * call to prepare_sidebar().
++ *
++ * Returns:
++ * A valid alternative BUFFY, or NULL
++ */
++static BUFFY *
++buffy_going (const BUFFY *b)
++{
++ if (!b)
++ return NULL;
++
++ if (b->prev) {
++ b->prev->next = NULL;
+ }
-+ else if ( BottomBuffy == CurBuffy->prev ) {
-+ TopBuffy = CurBuffy;
-+ tmp = TopBuffy;
-+ while ( --count && tmp->next )
-+ tmp = tmp->next;
-+ BottomBuffy = tmp;
++
++ if (b->next) {
++ b->next->prev = NULL;
++ return b->next;
+ }
++
++ return b->prev;
+}
+
-+static const char *
-+sidebar_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)
++/**
++ * 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)
+{
-+/* casting from unsigned long - srsly?! */
-+struct sidebar_entry *sbe = (struct sidebar_entry *) data;
-+unsigned int optional;
-+char fmt[SHORT_STRING], buf[SHORT_STRING];
-+
-+optional = flags & M_FORMAT_OPTIONAL;
-+
-+switch(op) {
-+ case 'F':
-+ if(!optional) {
-+ snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
-+ snprintf (dest, destlen, fmt, sbe->flagged);
-+ } else if(sbe->flagged == 0) {
-+ optional = 0;
++ 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;
+ }
-+ break;
-+
-+ case '!':
-+ if(sbe->flagged == 0)
-+ mutt_format_s(dest, destlen, prefix, "");
-+ if(sbe->flagged == 1)
-+ mutt_format_s(dest, destlen, prefix, "!");
-+ if(sbe->flagged == 2)
-+ mutt_format_s(dest, destlen, prefix, "!!");
-+ if(sbe->flagged > 2) {
-+ snprintf (buf, sizeof (buf), "%d!", sbe->flagged);
-+ mutt_format_s(dest, destlen, prefix, buf);
++
++ if (Context && (strcmp (b->path, Context->path) == 0)) {
++ /* Spool directory */
++ continue;
+ }
-+ break;
-+
-+ case 'S':
-+ if(!optional) {
-+ snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
-+ snprintf (dest, destlen, fmt, sbe->size);
-+ } else if (sbe->size == 0) {
-+ optional = 0;
-+ }
-+ break;
-+
-+ case 'N':
-+ if(!optional) {
-+ snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
-+ snprintf (dest, destlen, fmt, sbe->new);
-+ } else if(sbe->new == 0) {
-+ optional = 0;
++
++ if (mutt_find_list (SidebarWhitelist, b->path)) {
++ /* Explicitly asked to be visible */
++ continue;
+ }
-+ break;
+
-+ case 'B':
-+ mutt_format_s(dest, destlen, prefix, sbe->box);
-+ break;
++ b->is_hidden = 1;
+ }
++}
+
-+ if(optional)
-+ mutt_FormatString (dest, destlen, col, ifstring, sidebar_format_str, (unsigned long) sbe, flags);
-+ else if (flags & M_FORMAT_OPTIONAL)
-+ mutt_FormatString (dest, destlen, col, elsestring, sidebar_format_str, (unsigned long) sbe, flags);
++/**
++ * 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;
+
-+ return (src);
++ for (i = 1; i < arr_len; i++) {
++ arr[i]->prev = arr[i - 1];
++ }
++ arr[0]->prev = NULL;
+}
+
-+char *make_sidebar_entry(char *box, unsigned int size, unsigned int new, unsigned int flagged) {
-+ static char *entry = 0;
-+ struct sidebar_entry sbe;
-+ int SBvisual;
++/**
++ * prepare_sidebar - Prepare the list of BUFFYs for the sidebar display
++ * @page_size: The number of lines on a page
++ *
++ * Before painting the sidebar, we count the BUFFYs, determine which are
++ * visible, sort them and set up our page pointers.
++ *
++ * This is a lot of work to do each refresh, but there are many things that
++ * can change outside of the sidebar that we don't hear about.
++ *
++ * Returns:
++ * 0: No, don't draw the sidebar
++ * 1: Yes, draw the sidebar
++ */
++static int
++prepare_sidebar (int page_size)
++{
++ BUFFY *b = Incoming;
++ if (!b)
++ return 0;
++
++ int count = 0;
++ for (; b; b = b->next)
++ count++;
++
++ BUFFY **arr = safe_malloc (count * sizeof (*arr));
++ if (!arr)
++ return 0;
+
-+ SBvisual = SidebarWidth - strlen(SidebarDelim);
-+ if (SBvisual < 1)
-+ return NULL;
++ int i = 0;
++ for (b = Incoming; b; b = b->next, i++) {
++ arr[i] = b;
++ }
+
-+ sbe.new = new;
-+ sbe.flagged = flagged;
-+ sbe.size = size;
-+ strncpy(sbe.box, box, 31);
++ update_buffy_visibility (arr, count);
++ sort_buffy_array (arr, count);
+
-+ safe_realloc(&entry, SBvisual + 2);
-+ entry[SBvisual + 1] = '\0';
++ Incoming = arr[0];
+
-+ mutt_FormatString (entry, SBvisual+1, 0, SidebarFormat, sidebar_format_str, (unsigned long) &sbe, 0);
++ int top_index = 0;
++ int opn_index = -1;
++ int hil_index = -1;
++ int bot_index = -1;
+
-+ return entry;
++ 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;
+}
+
-+void set_curbuffy(char buf[LONG_STRING])
++/**
++ * 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)
+{
-+ BUFFY* tmp = CurBuffy = Incoming;
++ short new_visible = option (OPTSIDEBAR);
++ short new_width = SidebarWidth;
+
-+ if (!Incoming)
-+ return;
++ if (OldWidth != new_width) {
++ if (new_width > 0) {
++ OldWidth = new_width;
++ }
++ }
+
-+ while(1) {
-+ if(!strcmp(tmp->path, buf) || !strcmp(tmp->realpath, buf)) {
-+ CurBuffy = tmp;
-+ break;
-+ }
++ 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(tmp->next)
-+ tmp = tmp->next;
-+ else
-+ break;
-+ }
++ if (!option (OPTSIDEBAR)) {
++ SidebarWidth = 0;
++ } else if (new_width == 0) {
++ SidebarWidth = OldWidth;
++ } else {
++ SidebarWidth = new_width;
++ }
++
++ return new_visible;
+}
+
-+int draw_sidebar(int menu) {
-+
-+ BUFFY *tmp;
-+#ifndef USE_SLANG_CURSES
-+ attr_t attrs;
-+#endif
-+ short delim_len = strlen(SidebarDelim);
-+ short color_pair;
-+
-+ static bool initialized = false;
-+ static int prev_show_value;
-+ static short saveSidebarWidth;
-+ int lines = 0;
-+ int SidebarHeight;
-+
-+ if(option(OPTSTATUSONTOP) || option(OPTHELP))
-+ lines++; /* either one will occupy the first line */
-+
-+ /* initialize first time */
-+ if(!initialized) {
-+ prev_show_value = option(OPTSIDEBAR);
-+ saveSidebarWidth = SidebarWidth;
-+ if(!option(OPTSIDEBAR)) SidebarWidth = 0;
-+ initialized = true;
-+ }
-+
-+ /* 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)) {
-+ mutt_buffy_check(1); /* we probably have bad or no numbers */
-+ SidebarWidth = saveSidebarWidth;
-+ }
-+ prev_show_value = option(OPTSIDEBAR);
-+ }
-+
-+
-+/* 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);
-+ }
++/**
++ * 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 ( SidebarWidth == 0 || !option(OPTSIDEBAR)) {
-+ if (SidebarWidth > 0) {
-+ saveSidebarWidth = SidebarWidth;
-+ SidebarWidth = 0;
-+ }
-+ unset_option(OPTSIDEBAR);
-+ return 0;
-+ }
++ if (delim_len < 1)
++ return delim_len;
+
-+ /* 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);
++ if ((SidebarWidth + delim_len) > (COLS + 1))
++ return 0;
+
-+ /* draw the divider */
++ if (delim_len > SidebarWidth)
++ return -1;
+
-+ SidebarHeight = LINES - 1;
-+ if(option(OPTHELP) || !option(OPTSTATUSONTOP))
-+ SidebarHeight--;
++ SETCOLOR(MT_COLOR_DIVIDER);
+
-+ for ( ; lines < SidebarHeight; 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
++ int i;
++ for (i = 0; i < num_rows; i++) {
++ move (first_row + i, SidebarWidth - delim_len);
++ addstr (NONULL(SidebarDividerChar));
+ }
+
-+ if ( Incoming == 0 ) return 0;
-+ lines = 0;
-+ if(option(OPTSTATUSONTOP) || option(OPTHELP))
-+ lines++; /* either one will occupy the first line */
++ return delim_len;
++}
+
-+ if ( known_lines != LINES || TopBuffy == 0 || BottomBuffy == 0 )
-+ calc_boundaries(menu);
-+ if ( CurBuffy == 0 ) CurBuffy = Incoming;
++/**
++ * 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);
+
-+ tmp = TopBuffy;
++ int r;
++ for (r = 0; r < num_rows; r++) {
++ int i = 0;
++ move (first_row + r, 0);
++ for (; i < width; i++)
++ addch (' ');
++ }
++}
+
-+ SETCOLOR(MT_COLOR_NORMAL);
++/**
++ * 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;
+
-+ for ( ; tmp && lines < SidebarHeight; tmp = tmp->next ) {
-+ if ( tmp == CurBuffy )
-+ SETCOLOR(MT_COLOR_INDICATOR);
-+ else if ( tmp->msg_unread > 0 )
++ 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 ( tmp->msg_flagged > 0 )
-+ SETCOLOR(MT_COLOR_FLAGGED);
-+ else
++ } 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;
++ }
+
-+ move( lines, 0 );
-+ if ( Context && Context->path &&
-+ (!strcmp(tmp->path, Context->path)||
-+ !strcmp(tmp->realpath, Context->path)) ) {
-+ tmp->msg_unread = Context->unread;
-+ tmp->msgcount = Context->msgcount;
-+ tmp->msg_flagged = Context->flagged;
++ /* compute length of Maildir without trailing separator */
++ size_t maildirlen = strlen (Maildir);
++ if (SidebarDelimChars && strchr (SidebarDelimChars, Maildir[maildirlen - 1])) {
++ maildirlen--;
+ }
++
+ /* check whether Maildir is a prefix of the current folder's path */
+ short maildir_is_prefix = 0;
-+ if ( (strlen(tmp->path) > strlen(Maildir)) &&
-+ (strncmp(Maildir, tmp->path, strlen(Maildir)) == 0) )
-+ maildir_is_prefix = 1;
++ if ((strlen (b->path) > maildirlen) && (strncmp (Maildir, b->path, maildirlen) == 0)) {
++ maildir_is_prefix = 1;
++ }
+ /* calculate depth of current folder and generate its display name with indented spaces */
+ int sidebar_folder_depth = 0;
+ char *sidebar_folder_name;
-+ sidebar_folder_name = option(OPTSIDEBARSHORTPATH) ? mutt_basename(tmp->path) : tmp->path + maildir_is_prefix*(strlen(Maildir) + 1);
-+ if ( maildir_is_prefix && option(OPTSIDEBARFOLDERINDENT) ) {
-+ char *tmp_folder_name;
-+ int i;
-+ tmp_folder_name = tmp->path + strlen(Maildir) + 1;
-+ for (i = 0; i < strlen(tmp->path) - strlen(Maildir); i++) {
-+ if (tmp_folder_name[i] == '/' || tmp_folder_name[i] == '.') sidebar_folder_depth++;
-+ }
++ 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 = strrchr(tmp->path, '.');
-+ if (tmp_folder_name == NULL)
-+ tmp_folder_name = mutt_basename(tmp->path);
-+ else
-+ tmp_folder_name++;
-+ }
-+ else
-+ tmp_folder_name = tmp->path + strlen(Maildir) + 1;
-+ sidebar_folder_name = malloc(strlen(tmp_folder_name) + sidebar_folder_depth*strlen(NONULL(SidebarIndentStr)) + 1);
++ 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(SidebarIndentStr), strlen(NONULL(SidebarIndentStr)));
-+ strncat(sidebar_folder_name, tmp_folder_name, strlen(tmp_folder_name));
++ strncat (sidebar_folder_name, NONULL(SidebarIndentString), strlen (NONULL(SidebarIndentString)));
++ strncat (sidebar_folder_name, tmp_folder_name, strlen (tmp_folder_name));
+ }
+ }
-+ printw( "%.*s", SidebarWidth - delim_len + 1,
-+ make_sidebar_entry(sidebar_folder_name, tmp->msgcount,
-+ tmp->msg_unread, tmp->msg_flagged));
++ char str[SHORT_STRING];
++ make_sidebar_entry (str, sizeof (str), w, sidebar_folder_name, b);
++ printw ("%s", str);
+ if (sidebar_folder_depth > 0)
-+ free(sidebar_folder_name);
-+ lines++;
++ free (sidebar_folder_name);
++ row++;
+ }
-+ SETCOLOR(MT_COLOR_NORMAL);
-+ for ( ; lines < SidebarHeight; lines++ ) {
-+ int i = 0;
-+ move( lines, 0 );
-+ for ( ; i < SidebarWidth - delim_len; i++ )
-+ addch(' ');
++
++ fill_empty_space (first_row + row, num_rows - row, w);
++}
++
++
++/**
++ * sb_init - Set some default values for the sidebar.
++ */
++void
++sb_init (void)
++{
++ OldVisible = option (OPTSIDEBAR);
++ if (SidebarWidth > 0) {
++ OldWidth = SidebarWidth;
++ } else {
++ OldWidth = 20;
++ if (OldVisible) {
++ SidebarWidth = OldWidth;
++ }
+ }
-+ return 0;
+}
+
++/**
++ * sb_draw - Completely redraw the sidebar
++ *
++ * Completely refresh the sidebar region. First draw the divider; then, for
++ * each BUFFY, call make_sidebar_entry; finally blank out any remaining space.
++ */
++void
++sb_draw (void)
++{
++ if (!visible())
++ return;
++
++ /* XXX - if transitioning from invisible to visible */
++ /* if (OldVisible == 0) */
++ /* mutt_buffy_check (1); we probably have bad or no numbers */
++
++ int first_row = 0;
++ int num_rows = LINES - 2;
++
++ if (option (OPTHELP) || option (OPTSTATUSONTOP))
++ first_row++;
++
++ if (option (OPTHELP))
++ num_rows--;
+
-+void set_buffystats(CONTEXT* Context)
++ int div_width = draw_divider (first_row, num_rows);
++ if (div_width < 0)
++ return;
++
++ if (!Incoming) {
++ int w = MIN(COLS, (SidebarWidth - div_width));
++ fill_empty_space (first_row, num_rows, w);
++ return;
++ }
++
++ if (!prepare_sidebar (num_rows))
++ return;
++
++ draw_sidebar (first_row, num_rows, div_width);
++}
++
++/**
++ * sb_should_refresh - Check if the sidebar is due to be refreshed
++ *
++ * The "sidebar_refresh_time" config option allows the user to limit the frequency
++ * with which the sidebar is refreshed.
++ *
++ * Returns:
++ * 1 Yes, refresh is due
++ * 0 No, refresh happened recently
++ */
++int
++sb_should_refresh (void)
+{
-+ BUFFY *tmp = Incoming;
-+ while(tmp) {
-+ if(Context && (!strcmp(tmp->path, Context->path) ||
-+ !strcmp(tmp->realpath, Context->path))) {
-+ tmp->msg_unread = Context->unread;
-+ tmp->msgcount = Context->msgcount;
-+ tmp->msg_flagged = Context->flagged;
-+ break;
-+ }
-+ tmp = tmp->next;
-+ }
++ if (!option (OPTSIDEBAR))
++ return 0;
++
++ if (SidebarRefreshTime == 0)
++ return 0;
++
++ time_t diff = (time (NULL) - LastRefresh);
++
++ return (diff >= SidebarRefreshTime);
+}
+
-+void scroll_sidebar(int op, int menu)
++/**
++ * sb_change_mailbox - Change the selected mailbox
++ * @op: Operation code
++ *
++ * Change the selected mailbox, e.g. "Next mailbox", "Previous Mailbox
++ * with new mail". The operations are listed OPS.SIDEBAR which is built
++ * into an enum in keymap_defs.h.
++ *
++ * If the operation is successful, HilBuffy will be set to the new mailbox.
++ * This function only *selects* the mailbox, doesn't *open* it.
++ *
++ * Allowed values are: OP_SIDEBAR_NEXT, OP_SIDEBAR_NEXT_NEW,
++ * OP_SIDEBAR_PAGE_DOWN, OP_SIDEBAR_PAGE_UP, OP_SIDEBAR_PREV,
++ * OP_SIDEBAR_PREV_NEW.
++ */
++void
++sb_change_mailbox (int op)
+{
-+ if(!SidebarWidth) return;
-+ if(!CurBuffy) return;
++ BUFFY *b;
++ if (!HilBuffy) /* It'll get reset on the next draw */
++ return;
+
+ switch (op) {
+ case OP_SIDEBAR_NEXT:
-+ if ( CurBuffy->next == NULL ) return;
-+ CurBuffy = CurBuffy->next;
++ if (!HilBuffy->next)
++ return;
++ if (HilBuffy->next->is_hidden)
++ return;
++ HilBuffy = HilBuffy->next;
+ break;
-+ case OP_SIDEBAR_PREV:
-+ if ( CurBuffy->prev == NULL ) return;
-+ CurBuffy = CurBuffy->prev;
++ 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_SCROLL_UP:
-+ CurBuffy = TopBuffy;
-+ if ( CurBuffy != Incoming ) {
-+ calc_boundaries(menu);
-+ CurBuffy = CurBuffy->prev;
++ case OP_SIDEBAR_PAGE_UP:
++ HilBuffy = TopBuffy;
++ if (HilBuffy != Incoming) {
++ HilBuffy = HilBuffy->prev;
+ }
+ break;
-+ case OP_SIDEBAR_SCROLL_DOWN:
-+ CurBuffy = BottomBuffy;
-+ if ( CurBuffy->next ) {
-+ calc_boundaries(menu);
-+ CurBuffy = CurBuffy->next;
++ 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;
+ }
-+ calc_boundaries(menu);
-+ draw_sidebar(menu);
++
++ /* We can change folder even if the sidebar is hidden */
++ if (option (OPTSIDEBAR))
++ sb_draw();
++}
++
++/**
++ * sb_set_buffystats - Update the BUFFY's message counts from the CONTEXT
++ * @ctx: A mailbox CONTEXT
++ *
++ * Given a mailbox CONTEXT, find a matching mailbox BUFFY and copy the message
++ * counts into it.
++ */
++void
++sb_set_buffystats (const CONTEXT *ctx)
++{
++ /* Even if the sidebar's hidden,
++ * we should take note of the new data. */
++ BUFFY *b = Incoming;
++ if (!ctx || !b)
++ return;
++
++ for (; b; b = b->next) {
++ if (!strcmp (b->path, ctx->path) ||
++ !strcmp (b->realpath, ctx->path)) {
++ b->msg_unread = ctx->unread;
++ b->msg_count = ctx->msgcount;
++ b->msg_flagged = ctx->flagged;
++ break;
++ }
++ }
++}
++
++/**
++ * sb_get_highlight - Get the BUFFY that's highlighted in the sidebar
++ *
++ * Get the path of the mailbox that's highlighted in the sidebar.
++ *
++ * Returns:
++ * Mailbox path
++ */
++const char *
++sb_get_highlight (void)
++{
++ if (!HilBuffy)
++ return NULL;
++
++ return HilBuffy->path;
+}
+
-diff --git a/sidebar.h b/sidebar.h
-new file mode 100644
-index 0000000..d195f11
---- /dev/null
-+++ b/sidebar.h
++/**
++ * sb_set_open_buffy - Set the OpnBuffy based on a mailbox path
++ * @path: Mailbox path
++ *
++ * Search through the list of mailboxes. If a BUFFY has a matching path, set
++ * OpnBuffy to it.
++ */
++BUFFY *
++sb_set_open_buffy (const char *path)
++{
++ /* Even if the sidebar is hidden */
++
++ BUFFY *b = Incoming;
++
++ if (!path || !b)
++ return NULL;
++
++ OpnBuffy = NULL;
++
++ for (; b; b = b->next) {
++ if (!strcmp (b->path, path) ||
++ !strcmp (b->realpath, path)) {
++ OpnBuffy = b;
++ HilBuffy = b;
++ break;
++ }
++ }
++
++ return OpnBuffy;
++}
++
++/**
++ * sb_set_update_time - Note the time that the sidebar was updated
++ *
++ * Update the timestamp representing the last sidebar update. If the user
++ * configures "sidebar_refresh_time", this will help to reduce traffic.
++ */
++void
++sb_set_update_time (void)
++{
++ /* XXX - should this be public? */
++
++ LastRefresh = time (NULL);
++}
++
++/**
++ * sb_notify_mailbox - The state of a BUFFY is about to change
++ *
++ * We receive a notification:
++ * After a new BUFFY has been created
++ * Before a BUFFY is deleted
++ *
++ * Before a deletion, check that our pointers won't be invalidated.
++ */
++void
++sb_notify_mailbox (BUFFY *b, int created)
++{
++ if (!b)
++ return;
++
++ /* Any new/deleted mailboxes will cause a refresh. As long as
++ * they're valid, our pointers will be updated in prepare_sidebar() */
++
++ if (created) {
++ if (!TopBuffy)
++ TopBuffy = b;
++ if (!HilBuffy)
++ HilBuffy = b;
++ if (!BotBuffy)
++ BotBuffy = b;
++ if (!Outgoing)
++ Outgoing = b;
++ if (!OpnBuffy && Context) {
++ /* This might happen if the user "unmailboxes *", then
++ * "mailboxes" our current mailbox back again */
++ if (mutt_strcmp (b->path, Context->path) == 0) {
++ OpnBuffy = b;
++ }
++ }
++ } else {
++ if (TopBuffy == b)
++ TopBuffy = buffy_going (TopBuffy);
++ if (OpnBuffy == b)
++ OpnBuffy = buffy_going (OpnBuffy);
++ if (HilBuffy == b)
++ HilBuffy = buffy_going (HilBuffy);
++ if (BotBuffy == b)
++ BotBuffy = buffy_going (BotBuffy);
++ if (Outgoing == b)
++ Outgoing = buffy_going (Outgoing);
++ }
++}
+diff -urN mutt-1.6.1/sidebar.h mutt-1.6.1-sidebar/sidebar.h
+--- mutt-1.6.1/sidebar.h 1970-01-01 01:00:00.000000000 +0100
++++ mutt-1.6.1-sidebar/sidebar.h 2016-05-02 03:02:15.023213165 +0100
@@ -0,0 +1,36 @@
-+/*
-+ * Copyright (C) ????-2004 Justin Hibbits <jrh29@po.cwru.edu>
++/* Copyright (C) 2004 Justin Hibbits <jrh29@po.cwru.edu>
+ * Copyright (C) 2004 Thomer M. Gil <mutt@thomer.com>
-+ *
++ * Copyright (C) 2015-2016 Richard Russon <rich@flatcap.org>
++ *
+ * 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 sb_change_mailbox (int op);
++void sb_draw (void);
++const char * sb_get_highlight (void);
++void sb_init (void);
++void sb_notify_mailbox (BUFFY *b, int created);
++void sb_set_buffystats (const CONTEXT *ctx);
++BUFFY * sb_set_open_buffy (const char *path);
++void sb_set_update_time (void);
++int sb_should_refresh (void);
+
+#endif /* SIDEBAR_H */
+diff -urN mutt-1.6.1/sort.h mutt-1.6.1-sidebar/sort.h
+--- mutt-1.6.1/sort.h 2016-05-02 03:02:12.440172071 +0100
++++ mutt-1.6.1-sidebar/sort.h 2016-05-02 03:02:15.023213165 +0100
+@@ -31,6 +31,12 @@
+ #define SORT_KEYID 12
+ #define SORT_TRUST 13
+ #define SORT_SPAM 14
++#define SORT_COUNT 15
++#define SORT_COUNT_NEW 16
++#define SORT_DESC 17
++#define SORT_FLAGGED 18
++#define SORT_PATH 19
++
+ /* dgc: Sort & SortAux are shorts, so I'm bumping these bitflags up from
+ * bits 4 & 5 to bits 8 & 9 to make room for more sort keys in the future. */
+ #define SORT_MASK 0xff
+@@ -50,6 +56,7 @@
+ WHERE short Sort INITVAL (SORT_DATE);
+ WHERE short SortAux INITVAL (SORT_DATE); /* auxiliary sorting method */
+ WHERE short SortAlias INITVAL (SORT_ALIAS);
++WHERE short SidebarSortMethod INITVAL (SORT_ORDER);
+
+ /* FIXME: This one does not belong to here */
+ WHERE short PgpSortKeys INITVAL (SORT_ADDRESS);
diff --git a/trash-folder.patch b/trash-folder.patch
deleted file mode 100644
index ce47b0c30e5d..000000000000
--- a/trash-folder.patch
+++ /dev/null
@@ -1,316 +0,0 @@
-From: Cedric Duval <cedricduval@free.fr>
-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 <mfvescovi@gmail.com>
-
-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/trash.patch b/trash.patch
new file mode 100644
index 000000000000..4b252003110c
--- /dev/null
+++ b/trash.patch
@@ -0,0 +1,780 @@
+diff -urN mutt-1.6.1/commands.c mutt-1.6.1-trash/commands.c
+--- mutt-1.6.1/commands.c 2016-05-02 03:02:12.398171401 +0100
++++ mutt-1.6.1-trash/commands.c 2016-05-02 03:02:15.950227914 +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-05-02 03:02:12.400171433 +0100
++++ mutt-1.6.1-trash/curs_main.c 2016-05-02 03:02:15.953227962 +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-05-02 03:02:12.402171465 +0100
++++ mutt-1.6.1-trash/doc/manual.xml.head 2016-05-02 03:02:15.955227994 +0100
+@@ -8081,6 +8081,175 @@
+
+ </sect1>
+
++<sect1 id="trash-folder">
++ <title>Trash Folder Patch</title>
++ <subtitle>Automatically move "deleted" emails to a trash bin</subtitle>
++
++ <sect2 id="trash-folder-patch">
++ <title>Patch</title>
++
++ <para>
++ To check if Mutt supports <quote>Trash Folder</quote>, look for
++ <quote>patch-trash</quote> in the mutt version.
++ See: <xref linkend="mutt-patches"/>.
++ </para>
++
++ If IMAP is enabled, this patch will use it
++
++ <itemizedlist>
++ <title>Dependencies:</title>
++ <listitem><para>mutt-1.5.24</para></listitem>
++ <listitem><para>IMAP support</para></listitem>
++ </itemizedlist>
++
++ <para>This patch is part of the <ulink url="http://www.neomutt.org/">NeoMutt Project</ulink>.</para>
++ </sect2>
++
++ <sect2 id="trash-folder-intro">
++ <title>Introduction</title>
++
++ <para>
++ In Mutt, when you <quote>delete</quote> an email it is first marked
++ deleted. The email isn't really gone until
++ <link linkend="index-map">&lt;sync-mailbox&gt;</link> is called.
++ This happens when the user leaves the folder, or the function is called
++ manually.
++ </para>
++
++ <para>
++ After <literal>&lt;sync-mailbox&gt;</literal> has been called the email is gone forever.
++ </para>
++
++ <para>
++ The <link linkend="trash">$trash</link> variable defines a folder in
++ which to keep old emails. As before, first you mark emails for
++ deletion. When &lt;sync-mailbox&gt; is called the emails are moved to
++ the trash folder.
++ </para>
++
++ <para>
++ The <literal>$trash</literal> path can be either a full directory,
++ or be relative to the <link linkend="folder">$folder</link>
++ variable, like the <literal>mailboxes</literal> command.
++ </para>
++
++ <note>
++ Emails deleted from the trash folder are gone forever.
++ </note>
++ </sect2>
++
++ <sect2 id="trash-folder-variables">
++ <title>Variables</title>
++ <table id="table-trash-variables">
++ <title>Trash Variables</title>
++ <tgroup cols="3">
++ <thead>
++ <row>
++ <entry>Name</entry>
++ <entry>Type</entry>
++ <entry>Default</entry>
++ </row>
++ </thead>
++ <tbody>
++ <row>
++ <entry>trash</entry>
++ <entry>string</entry>
++ <entry>(none)</entry>
++ </row>
++ </tbody>
++ </tgroup>
++ </table>
++ </sect2>
++
++ <sect2 id="trash-folder-functions">
++ <title>Functions</title>
++ <table id="table-trash-functions">
++ <title>Trash Functions</title>
++ <tgroup cols="4">
++ <thead>
++ <row>
++ <entry>Menus</entry>
++ <entry>Default Key</entry>
++ <entry>Function</entry>
++ <entry>Description</entry>
++ </row>
++ </thead>
++ <tbody>
++ <row>
++ <entry>index,pager</entry>
++ <entry>(none)</entry>
++ <entry><literal>&lt;purge-message&gt;</literal></entry>
++ <entry>really delete the current entry, bypassing the trash folder</entry>
++ </row>
++ </tbody>
++ </tgroup>
++ </table>
++ </sect2>
++
++<!--
++ <sect2 id="trash-folder-commands">
++ <title>Commands</title>
++ <para>None</para>
++ </sect2>
++
++ <sect2 id="trash-folder-colors">
++ <title>Colors</title>
++ <para>None</para>
++ </sect2>
++
++ <sect2 id="trash-folder-sort">
++ <title>Sort</title>
++ <para>None</para>
++ </sect2>
++-->
++
++ <sect2 id="trash-folder-muttrc">
++ <title>Muttrc</title>
++<screen>
++<emphasis role="comment"># 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</emphasis>
++set trash='+Trash'
++set trash='/home/flatcap/Mail/Trash'
++
++<emphasis role="comment"># The default delete key 'd' will move an email to the 'trash' folder
++# Bind 'D' to REALLY delete an email</emphasis>
++bind index D purge-message
++
++<emphasis role="comment"># Note: Deleting emails from the 'trash' folder will REALLY delete them.
++
++# vim: syntax=muttrc</emphasis>
++</screen>
++ </sect2>
++
++ <sect2 id="trash-folder-see-also">
++ <title>See Also</title>
++
++ <itemizedlist>
++ <listitem><para><ulink url="http://www.neomutt.org/">NeoMutt Project</ulink></para></listitem>
++ <listitem><para><link linkend="folder-hook">folder-hook</link></para></listitem>
++ </itemizedlist>
++ </sect2>
++
++ <sect2 id="trash-folder-known-bugs">
++ <title>Known Bugs</title>
++ <para>None</para>
++ </sect2>
++
++ <sect2 id="trash-folder-credits">
++ <title>Credits</title>
++ <itemizedlist>
++ <listitem><para>Cedric Duval <email>cedricduval@free.fr</email></para></listitem>
++ <listitem><para>Benjamin Kuperman <email>kuperman@acm.org</email></para></listitem>
++ <listitem><para>Paul Miller <email>paul@voltar.org</email></para></listitem>
++ <listitem><para>Richard Russon <email>rich@flatcap.org</email></para></listitem>
++ </itemizedlist>
++ </sect2>
++</sect1>
++
+ </chapter>
+
+ <chapter id="security">
+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-05-02 03:02:15.862226514 +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-05-02 03:02:15.863226530 +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 "\<purge-message\>"
++
++" 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-05-02 03:02:12.403171480 +0100
++++ mutt-1.6.1-trash/flags.c 2016-05-02 03:02:15.956228010 +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-05-02 03:02:12.403171480 +0100
++++ mutt-1.6.1-trash/functions.h 2016-05-02 03:02:15.956228010 +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-05-02 03:02:12.403171480 +0100
++++ mutt-1.6.1-trash/globals.h 2016-05-02 03:02:15.956228010 +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-05-02 03:02:12.404171496 +0100
++++ mutt-1.6.1-trash/imap/imap.c 2016-05-02 03:02:15.957228026 +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-05-02 03:02:12.404171496 +0100
++++ mutt-1.6.1-trash/imap/imap.h 2016-05-02 03:02:15.867226594 +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-05-02 03:02:12.405171512 +0100
++++ mutt-1.6.1-trash/imap/message.c 2016-05-02 03:02:15.867226594 +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-05-02 03:02:12.407171544 +0100
++++ mutt-1.6.1-trash/init.h 2016-05-02 03:02:15.960228073 +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-05-02 03:02:12.409171576 +0100
++++ mutt-1.6.1-trash/mutt.h 2016-05-02 03:02:15.961228089 +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-05-02 03:02:12.410171592 +0100
++++ mutt-1.6.1-trash/muttlib.c 2016-05-02 03:02:15.962228105 +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-05-02 03:02:12.410171592 +0100
++++ mutt-1.6.1-trash/mx.c 2016-05-02 03:02:15.962228105 +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-05-02 03:02:12.392171305 +0100
++++ mutt-1.6.1-trash/OPS 2016-05-02 03:02:15.945227835 +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-05-02 03:02:12.411171608 +0100
++++ mutt-1.6.1-trash/pager.c 2016-05-02 03:02:15.963228121 +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-05-02 03:02:12.396171369 +0100
++++ mutt-1.6.1-trash/PATCHES 2016-05-02 03:02:15.949227898 +0100
+@@ -0,0 +1 @@
++patch-trash-neo-20160502
+diff -urN mutt-1.6.1/pattern.c mutt-1.6.1-trash/pattern.c
+--- mutt-1.6.1/pattern.c 2016-05-02 03:02:12.411171608 +0100
++++ mutt-1.6.1-trash/pattern.c 2016-05-02 03:02:15.963228121 +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-05-02 03:02:12.411171608 +0100
++++ mutt-1.6.1-trash/postpone.c 2016-05-02 03:02:15.905227198 +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-05-02 03:02:15.949227898 +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.5.24
++ * IMAP support
++
++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.
++
++ > 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) | '<purge-message>' | really delete the current entry, bypassing the trash folder |
++
++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>
++