You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

sidebar.patch 43KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476
  1. From: Antonio Radici <antonio@debian.org>
  2. Date: Tue, 4 Mar 2014 15:21:10 +0100
  3. Subject: sidebar
  4. When enabled, mutt will show a list of mailboxes with (new) message counts in a
  5. separate column on the left side of the screen.
  6. As this feature is still considered to be unstable, this patch is only applied
  7. in the "mutt-patched" package.
  8. * Configuration variables:
  9. sidebar_delim (string, default "|")
  10. This specifies the delimiter between the sidebar (if visible) and
  11. other screens.
  12. sidebar_visible (boolean, default no)
  13. This specifies whether or not to show sidebar (left-side list of folders).
  14. sidebar_width (integer, default 0)
  15. -
  16. The width of the sidebar.
  17. * Patch source:
  18. - http://www.lunar-linux.org/index.php?page=mutt-sidebar
  19. - http://lunar-linux.org/~tchan/mutt/patch-1.5.19.sidebar.20090522.txt
  20. * Changes made:
  21. - 2008-08-02 myon: Refreshed patch using quilt push -f to remove hunks we do
  22. not need (Makefile.in).
  23. - 2014-03-04 evgeni: refresh sidebar patch with the version from OpenBSD
  24. Source:
  25. ftp://ftp.openbsd.org/pub/OpenBSD/distfiles/mutt/sidebar-1.5.22.diff1.gz
  26. Signed-off-by: Matteo F. Vescovi <mfvescovi@gmail.com>
  27. Signed-off-by: Evgeni Golov <evgeni@debian.org>
  28. Gbp-Pq: Topic mutt-patched
  29. ---
  30. Makefile.am | 1 +
  31. OPS | 5 +
  32. buffy.c | 123 +++++++++++++++++++++
  33. buffy.h | 4 +
  34. color.c | 2 +
  35. compose.c | 26 ++---
  36. curs_main.c | 30 +++++-
  37. flags.c | 3 +
  38. functions.h | 10 ++
  39. globals.h | 4 +
  40. imap/command.c | 7 ++
  41. imap/imap.c | 2 +-
  42. init.h | 21 ++++
  43. mailbox.h | 1 +
  44. mbox.c | 2 +
  45. menu.c | 20 ++--
  46. mh.c | 22 ++++
  47. mutt.h | 4 +
  48. mutt_curses.h | 3 +
  49. muttlib.c | 48 +++++++++
  50. mx.c | 15 +++
  51. mx.h | 1 +
  52. pager.c | 30 ++++--
  53. sidebar.c | 333 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  54. sidebar.h | 36 +++++++
  55. 25 files changed, 719 insertions(+), 34 deletions(-)
  56. create mode 100644 sidebar.c
  57. create mode 100644 sidebar.h
  58. diff --git a/Makefile.am b/Makefile.am
  59. index 09dd64b..2fc6b1d 100644
  60. --- a/Makefile.am
  61. +++ b/Makefile.am
  62. @@ -32,6 +32,7 @@ mutt_SOURCES = \
  63. rfc822.c rfc1524.c rfc2047.c rfc2231.c rfc3676.c \
  64. score.c send.c sendlib.c signal.c sort.c \
  65. status.c system.c thread.c charset.c history.c lib.c \
  66. + sidebar.c \
  67. muttlib.c editmsg.c mbyte.c \
  68. url.c ascii.c crypt-mod.c crypt-mod.h safe_asprintf.c
  69. diff --git a/OPS b/OPS
  70. index 02cea8e..b036db9 100644
  71. --- a/OPS
  72. +++ b/OPS
  73. @@ -180,3 +180,8 @@ OP_WHAT_KEY "display the keycode for a key press"
  74. OP_MAIN_SHOW_LIMIT "show currently active limit pattern"
  75. OP_MAIN_COLLAPSE_THREAD "collapse/uncollapse current thread"
  76. OP_MAIN_COLLAPSE_ALL "collapse/uncollapse all threads"
  77. +OP_SIDEBAR_SCROLL_UP "scroll the mailbox pane up 1 page"
  78. +OP_SIDEBAR_SCROLL_DOWN "scroll the mailbox pane down 1 page"
  79. +OP_SIDEBAR_NEXT "go down to next mailbox"
  80. +OP_SIDEBAR_PREV "go to previous mailbox"
  81. +OP_SIDEBAR_OPEN "open hilighted mailbox"
  82. diff --git a/buffy.c b/buffy.c
  83. index e5a0f79..225104d 100644
  84. --- a/buffy.c
  85. +++ b/buffy.c
  86. @@ -161,6 +161,49 @@ void mutt_buffy_cleanup (const char *buf, struct stat *st)
  87. }
  88. }
  89. +static int buffy_compare_name(const void *a, const void *b) {
  90. + const BUFFY *b1 = * (BUFFY * const *) a;
  91. + const BUFFY *b2 = * (BUFFY * const *) b;
  92. +
  93. + return mutt_strcoll(b1->path, b2->path);
  94. +}
  95. +
  96. +static BUFFY *buffy_sort(BUFFY *b)
  97. +{
  98. + BUFFY *tmp = b;
  99. + int buffycount = 0;
  100. + BUFFY **ary;
  101. + int i;
  102. +
  103. + if (!option(OPTSIDEBARSORT))
  104. + return b;
  105. +
  106. + for (; tmp != NULL; tmp = tmp->next)
  107. + buffycount++;
  108. +
  109. + ary = (BUFFY **) safe_calloc(buffycount, sizeof (*ary));
  110. +
  111. + tmp = b;
  112. + for (i = 0; tmp != NULL; tmp = tmp->next, i++) {
  113. + ary[i] = tmp;
  114. + }
  115. +
  116. + qsort(ary, buffycount, sizeof(*ary), buffy_compare_name);
  117. +
  118. + for (i = 0; i < buffycount - 1; i++) {
  119. + ary[i]->next = ary[i+1];
  120. + }
  121. + ary[buffycount - 1]->next = NULL;
  122. + for (i = 1; i < buffycount; i++) {
  123. + ary[i]->prev = ary[i-1];
  124. + }
  125. + ary[0]->prev = NULL;
  126. +
  127. + tmp = ary[0];
  128. + free(ary);
  129. + return tmp;
  130. +}
  131. +
  132. BUFFY *mutt_find_mailbox (const char *path)
  133. {
  134. BUFFY *tmp = NULL;
  135. @@ -282,6 +325,7 @@ int mutt_parse_mailboxes (BUFFER *path, BUFFER *s, unsigned long data, BUFFER *e
  136. else
  137. (*tmp)->size = 0;
  138. }
  139. + Incoming = buffy_sort(Incoming);
  140. return 0;
  141. }
  142. @@ -340,6 +384,68 @@ static int buffy_maildir_hasnew (BUFFY* mailbox)
  143. return rc;
  144. }
  145. +/* update message counts for the sidebar */
  146. +void buffy_maildir_update (BUFFY* mailbox)
  147. +{
  148. + char path[_POSIX_PATH_MAX];
  149. + DIR *dirp;
  150. + struct dirent *de;
  151. + char *p;
  152. +
  153. + mailbox->msgcount = 0;
  154. + mailbox->msg_unread = 0;
  155. + mailbox->msg_flagged = 0;
  156. +
  157. + snprintf (path, sizeof (path), "%s/new", mailbox->path);
  158. +
  159. + if ((dirp = opendir (path)) == NULL)
  160. + {
  161. + mailbox->magic = 0;
  162. + return;
  163. + }
  164. +
  165. + while ((de = readdir (dirp)) != NULL)
  166. + {
  167. + if (*de->d_name == '.')
  168. + continue;
  169. +
  170. + if (!(p = strstr (de->d_name, ":2,")) || !strchr (p + 3, 'T')) {
  171. + mailbox->new = 1;
  172. + mailbox->msgcount++;
  173. + mailbox->msg_unread++;
  174. + }
  175. + }
  176. +
  177. + closedir (dirp);
  178. + snprintf (path, sizeof (path), "%s/cur", mailbox->path);
  179. +
  180. + if ((dirp = opendir (path)) == NULL)
  181. + {
  182. + mailbox->magic = 0;
  183. + return;
  184. + }
  185. +
  186. + while ((de = readdir (dirp)) != NULL)
  187. + {
  188. + if (*de->d_name == '.')
  189. + continue;
  190. +
  191. + if (!(p = strstr (de->d_name, ":2,")) || !strchr (p + 3, 'T')) {
  192. + mailbox->msgcount++;
  193. + if ((p = strstr (de->d_name, ":2,"))) {
  194. + if (!strchr (p + 3, 'T')) {
  195. + if (!strchr (p + 3, 'S'))
  196. + mailbox->msg_unread++;
  197. + if (strchr(p + 3, 'F'))
  198. + mailbox->msg_flagged++;
  199. + }
  200. + }
  201. + }
  202. + }
  203. +
  204. + closedir (dirp);
  205. +}
  206. +
  207. /* returns 1 if mailbox has new mail */
  208. static int buffy_mbox_hasnew (BUFFY* mailbox, struct stat *sb)
  209. {
  210. @@ -371,6 +477,20 @@ static int buffy_mbox_hasnew (BUFFY* mailbox, struct stat *sb)
  211. return rc;
  212. }
  213. +/* update message counts for the sidebar */
  214. +void buffy_mbox_update (BUFFY* mailbox)
  215. +{
  216. + CONTEXT *ctx = NULL;
  217. +
  218. + ctx = mx_open_mailbox(mailbox->path, M_READONLY | M_QUIET | M_NOSORT | M_PEEK, NULL);
  219. + if(ctx)
  220. + {
  221. + mailbox->msgcount = ctx->msgcount;
  222. + mailbox->msg_unread = ctx->unread;
  223. + mx_close_mailbox(ctx, 0);
  224. + }
  225. +}
  226. +
  227. int mutt_buffy_check (int force)
  228. {
  229. BUFFY *tmp;
  230. @@ -444,16 +564,19 @@ int mutt_buffy_check (int force)
  231. {
  232. case M_MBOX:
  233. case M_MMDF:
  234. + buffy_mbox_update (tmp);
  235. if (buffy_mbox_hasnew (tmp, &sb) > 0)
  236. BuffyCount++;
  237. break;
  238. case M_MAILDIR:
  239. + buffy_maildir_update (tmp);
  240. if (buffy_maildir_hasnew (tmp) > 0)
  241. BuffyCount++;
  242. break;
  243. case M_MH:
  244. + mh_buffy_update (tmp->path, &tmp->msgcount, &tmp->msg_unread, &tmp->msg_flagged);
  245. mh_buffy(tmp);
  246. if (tmp->new)
  247. BuffyCount++;
  248. diff --git a/buffy.h b/buffy.h
  249. index f9fc55a..672d178 100644
  250. --- a/buffy.h
  251. +++ b/buffy.h
  252. @@ -25,7 +25,11 @@ typedef struct buffy_t
  253. char path[_POSIX_PATH_MAX];
  254. off_t size;
  255. struct buffy_t *next;
  256. + struct buffy_t *prev;
  257. short new; /* mailbox has new mail */
  258. + int msgcount; /* total number of messages */
  259. + int msg_unread; /* number of unread messages */
  260. + int msg_flagged; /* number of flagged messages */
  261. short notified; /* user has been notified */
  262. short magic; /* mailbox type */
  263. short newly_created; /* mbox or mmdf just popped into existence */
  264. diff --git a/color.c b/color.c
  265. index ef97ca9..2112132 100644
  266. --- a/color.c
  267. +++ b/color.c
  268. @@ -93,6 +93,8 @@ static const struct mapping_t Fields[] =
  269. { "bold", MT_COLOR_BOLD },
  270. { "underline", MT_COLOR_UNDERLINE },
  271. { "index", MT_COLOR_INDEX },
  272. + { "sidebar_new", MT_COLOR_NEW },
  273. + { "sidebar_flagged", MT_COLOR_FLAGGED },
  274. { NULL, 0 }
  275. };
  276. diff --git a/compose.c b/compose.c
  277. index 9cfa2d4..5a14d70 100644
  278. --- a/compose.c
  279. +++ b/compose.c
  280. @@ -72,7 +72,7 @@ enum
  281. #define HDR_XOFFSET 10
  282. #define TITLE_FMT "%10s" /* Used for Prompts, which are ASCII */
  283. -#define W (COLS - HDR_XOFFSET)
  284. +#define W (COLS - HDR_XOFFSET - SidebarWidth)
  285. static const char * const Prompts[] =
  286. {
  287. @@ -110,7 +110,7 @@ static void snd_entry (char *b, size_t blen, MUTTMENU *menu, int num)
  288. static void redraw_crypt_lines (HEADER *msg)
  289. {
  290. - mvaddstr (HDR_CRYPT, 0, "Security: ");
  291. + mvaddstr (HDR_CRYPT, SidebarWidth, "Security: ");
  292. if ((WithCrypto & (APPLICATION_PGP | APPLICATION_SMIME)) == 0)
  293. {
  294. @@ -142,7 +142,7 @@ static void redraw_crypt_lines (HEADER *msg)
  295. }
  296. clrtoeol ();
  297. - move (HDR_CRYPTINFO, 0);
  298. + move (HDR_CRYPTINFO, SidebarWidth);
  299. clrtoeol ();
  300. if ((WithCrypto & APPLICATION_PGP)
  301. @@ -159,7 +159,7 @@ static void redraw_crypt_lines (HEADER *msg)
  302. && (msg->security & ENCRYPT)
  303. && SmimeCryptAlg
  304. && *SmimeCryptAlg) {
  305. - mvprintw (HDR_CRYPTINFO, 40, "%s%s", _("Encrypt with: "),
  306. + mvprintw (HDR_CRYPTINFO, SidebarWidth + 40, "%s%s", _("Encrypt with: "),
  307. NONULL(SmimeCryptAlg));
  308. }
  309. }
  310. @@ -172,7 +172,7 @@ static void redraw_mix_line (LIST *chain)
  311. int c;
  312. char *t;
  313. - mvaddstr (HDR_MIX, 0, " Mix: ");
  314. + mvaddstr (HDR_MIX, SidebarWidth, " Mix: ");
  315. if (!chain)
  316. {
  317. @@ -187,7 +187,7 @@ static void redraw_mix_line (LIST *chain)
  318. if (t && t[0] == '0' && t[1] == '\0')
  319. t = "<random>";
  320. - if (c + mutt_strlen (t) + 2 >= COLS)
  321. + if (c + mutt_strlen (t) + 2 >= COLS - SidebarWidth)
  322. break;
  323. addstr (NONULL(t));
  324. @@ -239,7 +239,7 @@ static void draw_envelope_addr (int line, ADDRESS *addr)
  325. buf[0] = 0;
  326. rfc822_write_address (buf, sizeof (buf), addr, 1);
  327. - mvprintw (line, 0, TITLE_FMT, Prompts[line - 1]);
  328. + mvprintw (line, SidebarWidth, TITLE_FMT, Prompts[line - 1]);
  329. mutt_paddstr (W, buf);
  330. }
  331. @@ -249,10 +249,10 @@ static void draw_envelope (HEADER *msg, char *fcc)
  332. draw_envelope_addr (HDR_TO, msg->env->to);
  333. draw_envelope_addr (HDR_CC, msg->env->cc);
  334. draw_envelope_addr (HDR_BCC, msg->env->bcc);
  335. - mvprintw (HDR_SUBJECT, 0, TITLE_FMT, Prompts[HDR_SUBJECT - 1]);
  336. + mvprintw (HDR_SUBJECT, SidebarWidth, TITLE_FMT, Prompts[HDR_SUBJECT - 1]);
  337. mutt_paddstr (W, NONULL (msg->env->subject));
  338. draw_envelope_addr (HDR_REPLYTO, msg->env->reply_to);
  339. - mvprintw (HDR_FCC, 0, TITLE_FMT, Prompts[HDR_FCC - 1]);
  340. + mvprintw (HDR_FCC, SidebarWidth, TITLE_FMT, Prompts[HDR_FCC - 1]);
  341. mutt_paddstr (W, fcc);
  342. if (WithCrypto)
  343. @@ -263,7 +263,7 @@ static void draw_envelope (HEADER *msg, char *fcc)
  344. #endif
  345. SETCOLOR (MT_COLOR_STATUS);
  346. - mvaddstr (HDR_ATTACH - 1, 0, _("-- Attachments"));
  347. + mvaddstr (HDR_ATTACH - 1, SidebarWidth, _("-- Attachments"));
  348. clrtoeol ();
  349. NORMAL_COLOR;
  350. @@ -299,7 +299,7 @@ static int edit_address_list (int line, ADDRESS **addr)
  351. /* redraw the expanded list so the user can see the result */
  352. buf[0] = 0;
  353. rfc822_write_address (buf, sizeof (buf), *addr, 1);
  354. - move (line, HDR_XOFFSET);
  355. + move (line, HDR_XOFFSET+SidebarWidth);
  356. mutt_paddstr (W, buf);
  357. return 0;
  358. @@ -544,7 +544,7 @@ int mutt_compose_menu (HEADER *msg, /* structure for new message */
  359. if (mutt_get_field ("Subject: ", buf, sizeof (buf), 0) == 0)
  360. {
  361. mutt_str_replace (&msg->env->subject, buf);
  362. - move (HDR_SUBJECT, HDR_XOFFSET);
  363. + move (HDR_SUBJECT, HDR_XOFFSET + SidebarWidth);
  364. if (msg->env->subject)
  365. mutt_paddstr (W, msg->env->subject);
  366. else
  367. @@ -562,7 +562,7 @@ int mutt_compose_menu (HEADER *msg, /* structure for new message */
  368. {
  369. strfcpy (fcc, buf, fcclen);
  370. mutt_pretty_mailbox (fcc, fcclen);
  371. - move (HDR_FCC, HDR_XOFFSET);
  372. + move (HDR_FCC, HDR_XOFFSET + SidebarWidth);
  373. mutt_paddstr (W, fcc);
  374. fccSet = 1;
  375. }
  376. diff --git a/curs_main.c b/curs_main.c
  377. index e7f11bd..7b81798 100644
  378. --- a/curs_main.c
  379. +++ b/curs_main.c
  380. @@ -26,7 +26,9 @@
  381. #include "mailbox.h"
  382. #include "mapping.h"
  383. #include "sort.h"
  384. +#include "buffy.h"
  385. #include "mx.h"
  386. +#include "sidebar.h"
  387. #ifdef USE_POP
  388. #include "pop.h"
  389. @@ -532,8 +534,12 @@ int mutt_index_menu (void)
  390. menu->redraw |= REDRAW_STATUS;
  391. if (do_buffy_notify)
  392. {
  393. - if (mutt_buffy_notify () && option (OPTBEEPNEW))
  394. - beep ();
  395. + if (mutt_buffy_notify ())
  396. + {
  397. + menu->redraw |= REDRAW_FULL;
  398. + if (option (OPTBEEPNEW))
  399. + beep ();
  400. + }
  401. }
  402. else
  403. do_buffy_notify = 1;
  404. @@ -545,6 +551,7 @@ int mutt_index_menu (void)
  405. if (menu->redraw & REDRAW_FULL)
  406. {
  407. menu_redraw_full (menu);
  408. + draw_sidebar(menu->menu);
  409. mutt_show_error ();
  410. }
  411. @@ -567,9 +574,12 @@ int mutt_index_menu (void)
  412. if (menu->redraw & REDRAW_STATUS)
  413. {
  414. + DrawFullLine = 1;
  415. menu_status_line (buf, sizeof (buf), menu, NONULL (Status));
  416. + DrawFullLine = 0;
  417. move (option (OPTSTATUSONTOP) ? 0 : LINES-2, 0);
  418. SETCOLOR (MT_COLOR_STATUS);
  419. + set_buffystats(Context);
  420. mutt_paddstr (COLS, buf);
  421. NORMAL_COLOR;
  422. menu->redraw &= ~REDRAW_STATUS;
  423. @@ -589,7 +599,7 @@ int mutt_index_menu (void)
  424. menu->oldcurrent = -1;
  425. if (option (OPTARROWCURSOR))
  426. - move (menu->current - menu->top + menu->offset, 2);
  427. + move (menu->current - menu->top + menu->offset, SidebarWidth + 2);
  428. else if (option (OPTBRAILLEFRIENDLY))
  429. move (menu->current - menu->top + menu->offset, 0);
  430. else
  431. @@ -1090,6 +1100,7 @@ int mutt_index_menu (void)
  432. menu->redraw = REDRAW_FULL;
  433. break;
  434. + case OP_SIDEBAR_OPEN:
  435. case OP_MAIN_CHANGE_FOLDER:
  436. case OP_MAIN_NEXT_UNREAD_MAILBOX:
  437. @@ -1121,7 +1132,11 @@ int mutt_index_menu (void)
  438. {
  439. mutt_buffy (buf, sizeof (buf));
  440. - if (mutt_enter_fname (cp, buf, sizeof (buf), &menu->redraw, 1) == -1)
  441. + if ( op == OP_SIDEBAR_OPEN ) {
  442. + if(!CurBuffy)
  443. + break;
  444. + strncpy( buf, CurBuffy->path, sizeof(buf) );
  445. + } else if (mutt_enter_fname (cp, buf, sizeof (buf), &menu->redraw, 1) == -1)
  446. {
  447. if (menu->menu == MENU_PAGER)
  448. {
  449. @@ -1139,6 +1154,7 @@ int mutt_index_menu (void)
  450. }
  451. mutt_expand_path (buf, sizeof (buf));
  452. + set_curbuffy(buf);
  453. if (mx_get_magic (buf) <= 0)
  454. {
  455. mutt_error (_("%s is not a mailbox."), buf);
  456. @@ -2242,6 +2258,12 @@ int mutt_index_menu (void)
  457. mutt_what_key();
  458. break;
  459. + case OP_SIDEBAR_SCROLL_UP:
  460. + case OP_SIDEBAR_SCROLL_DOWN:
  461. + case OP_SIDEBAR_NEXT:
  462. + case OP_SIDEBAR_PREV:
  463. + scroll_sidebar(op, menu->menu);
  464. + break;
  465. default:
  466. if (menu->menu == MENU_MAIN)
  467. km_error_key (MENU_MAIN);
  468. diff --git a/flags.c b/flags.c
  469. index 133fa35..48fb287 100644
  470. --- a/flags.c
  471. +++ b/flags.c
  472. @@ -22,8 +22,10 @@
  473. #include "mutt.h"
  474. #include "mutt_curses.h"
  475. +#include "mutt_menu.h"
  476. #include "sort.h"
  477. #include "mx.h"
  478. +#include "sidebar.h"
  479. void _mutt_set_flag (CONTEXT *ctx, HEADER *h, int flag, int bf, int upd_ctx)
  480. {
  481. @@ -290,6 +292,7 @@ void _mutt_set_flag (CONTEXT *ctx, HEADER *h, int flag, int bf, int upd_ctx)
  482. */
  483. if (h->searched && (changed != h->changed || deleted != ctx->deleted || tagged != ctx->tagged || flagged != ctx->flagged))
  484. h->searched = 0;
  485. + draw_sidebar(0);
  486. }
  487. void mutt_tag_set_flag (int flag, int bf)
  488. diff --git a/functions.h b/functions.h
  489. index 26171a0..ef8937a 100644
  490. --- a/functions.h
  491. +++ b/functions.h
  492. @@ -170,6 +170,11 @@ const struct binding_t OpMain[] = { /* map: index */
  493. { "decrypt-save", OP_DECRYPT_SAVE, NULL },
  494. + { "sidebar-scroll-up", OP_SIDEBAR_SCROLL_UP, NULL },
  495. + { "sidebar-scroll-down", OP_SIDEBAR_SCROLL_DOWN, NULL },
  496. + { "sidebar-next", OP_SIDEBAR_NEXT, NULL },
  497. + { "sidebar-prev", OP_SIDEBAR_PREV, NULL },
  498. + { "sidebar-open", OP_SIDEBAR_OPEN, NULL },
  499. { NULL, 0, NULL }
  500. };
  501. @@ -274,6 +279,11 @@ const struct binding_t OpPager[] = { /* map: pager */
  502. { "what-key", OP_WHAT_KEY, NULL },
  503. + { "sidebar-scroll-up", OP_SIDEBAR_SCROLL_UP, NULL },
  504. + { "sidebar-scroll-down", OP_SIDEBAR_SCROLL_DOWN, NULL },
  505. + { "sidebar-next", OP_SIDEBAR_NEXT, NULL },
  506. + { "sidebar-prev", OP_SIDEBAR_PREV, NULL },
  507. + { "sidebar-open", OP_SIDEBAR_OPEN, NULL },
  508. { NULL, 0, NULL }
  509. };
  510. diff --git a/globals.h b/globals.h
  511. index 5b6e56a..3f83328 100644
  512. --- a/globals.h
  513. +++ b/globals.h
  514. @@ -117,6 +117,7 @@ WHERE short SearchContext;
  515. WHERE char *SendCharset;
  516. WHERE char *Sendmail;
  517. WHERE char *Shell;
  518. +WHERE char *SidebarDelim;
  519. WHERE char *Signature;
  520. WHERE char *SimpleSearch;
  521. #if USE_SMTP
  522. @@ -211,6 +212,9 @@ WHERE short ScoreThresholdDelete;
  523. WHERE short ScoreThresholdRead;
  524. WHERE short ScoreThresholdFlag;
  525. +WHERE struct buffy_t *CurBuffy INITVAL(0);
  526. +WHERE short DrawFullLine INITVAL(0);
  527. +WHERE short SidebarWidth;
  528. #ifdef USE_IMAP
  529. WHERE short ImapKeepalive;
  530. WHERE short ImapPipelineDepth;
  531. diff --git a/imap/command.c b/imap/command.c
  532. index 32f8417..d68e3ab 100644
  533. --- a/imap/command.c
  534. +++ b/imap/command.c
  535. @@ -1012,6 +1012,13 @@ static void cmd_parse_status (IMAP_DATA* idata, char* s)
  536. opened */
  537. status->uidnext = oldun;
  538. + /* Added to make the sidebar show the correct numbers */
  539. + if (status->messages)
  540. + {
  541. + inc->msgcount = status->messages;
  542. + inc->msg_unread = status->unseen;
  543. + }
  544. +
  545. FREE (&value);
  546. return;
  547. }
  548. diff --git a/imap/imap.c b/imap/imap.c
  549. index 393d4ec..4b1ec86 100644
  550. --- a/imap/imap.c
  551. +++ b/imap/imap.c
  552. @@ -1520,7 +1520,7 @@ int imap_buffy_check (int force)
  553. imap_munge_mbox_name (munged, sizeof (munged), name);
  554. snprintf (command, sizeof (command),
  555. - "STATUS %s (UIDNEXT UIDVALIDITY UNSEEN RECENT)", munged);
  556. + "STATUS %s (UIDNEXT UIDVALIDITY UNSEEN RECENT MESSAGES)", munged);
  557. if (imap_exec (idata, command, IMAP_CMD_QUEUE) < 0)
  558. {
  559. diff --git a/init.h b/init.h
  560. index 08e004c..502f570 100644
  561. --- a/init.h
  562. +++ b/init.h
  563. @@ -1980,6 +1980,27 @@ struct option_t MuttVars[] = {
  564. ** not used.
  565. ** (PGP only)
  566. */
  567. + {"sidebar_delim", DT_STR, R_BOTH, UL &SidebarDelim, "|"},
  568. + /*
  569. + ** .pp
  570. + ** This specifies the delimiter between the sidebar (if visible) and
  571. + ** other screens.
  572. + */
  573. + { "sidebar_visible", DT_BOOL, R_BOTH, OPTSIDEBAR, 0 },
  574. + /*
  575. + ** .pp
  576. + ** This specifies whether or not to show sidebar (left-side list of folders).
  577. + */
  578. + { "sidebar_sort", DT_BOOL, R_BOTH, OPTSIDEBARSORT, 0 },
  579. + /*
  580. + ** .pp
  581. + ** This specifies whether or not to sort the sidebar alphabetically.
  582. + */
  583. + { "sidebar_width", DT_NUM, R_BOTH, UL &SidebarWidth, 0 },
  584. + /*
  585. + ** .pp
  586. + ** The width of the sidebar.
  587. + */
  588. { "pgp_use_gpg_agent", DT_BOOL, R_NONE, OPTUSEGPGAGENT, 0},
  589. /*
  590. ** .pp
  591. diff --git a/mailbox.h b/mailbox.h
  592. index 91e5dc7..b652628 100644
  593. --- a/mailbox.h
  594. +++ b/mailbox.h
  595. @@ -27,6 +27,7 @@
  596. #define M_NEWFOLDER (1<<4) /* create a new folder - same as M_APPEND, but uses
  597. * safe_fopen() for mbox-style folders.
  598. */
  599. +#define M_PEEK (1<<5) /* revert atime back after taking a look (if applicable) */
  600. /* mx_open_new_message() */
  601. #define M_ADD_FROM 1 /* add a From_ line */
  602. diff --git a/mbox.c b/mbox.c
  603. index 6d3b6bd..fa82eb3 100644
  604. --- a/mbox.c
  605. +++ b/mbox.c
  606. @@ -104,6 +104,7 @@ int mmdf_parse_mailbox (CONTEXT *ctx)
  607. mutt_perror (ctx->path);
  608. return (-1);
  609. }
  610. + ctx->atime = sb.st_atime;
  611. ctx->mtime = sb.st_mtime;
  612. ctx->size = sb.st_size;
  613. @@ -255,6 +256,7 @@ int mbox_parse_mailbox (CONTEXT *ctx)
  614. ctx->size = sb.st_size;
  615. ctx->mtime = sb.st_mtime;
  616. + ctx->atime = sb.st_atime;
  617. #ifdef NFS_ATTRIBUTE_HACK
  618. if (sb.st_mtime > sb.st_atime)
  619. diff --git a/menu.c b/menu.c
  620. index 27b5f8e..bc3a02f 100644
  621. --- a/menu.c
  622. +++ b/menu.c
  623. @@ -24,6 +24,7 @@
  624. #include "mutt_curses.h"
  625. #include "mutt_menu.h"
  626. #include "mbyte.h"
  627. +#include "sidebar.h"
  628. extern size_t UngetCount;
  629. @@ -186,7 +187,7 @@ static void menu_pad_string (char *s, size_t n)
  630. {
  631. char *scratch = safe_strdup (s);
  632. int shift = option (OPTARROWCURSOR) ? 3 : 0;
  633. - int cols = COLS - shift;
  634. + int cols = COLS - shift - SidebarWidth;
  635. mutt_format_string (s, n, cols, cols, FMT_LEFT, ' ', scratch, mutt_strlen (scratch), 1);
  636. s[n - 1] = 0;
  637. @@ -239,6 +240,7 @@ void menu_redraw_index (MUTTMENU *menu)
  638. int do_color;
  639. int attr;
  640. + draw_sidebar(1);
  641. for (i = menu->top; i < menu->top + menu->pagelen; i++)
  642. {
  643. if (i < menu->max)
  644. @@ -249,7 +251,7 @@ void menu_redraw_index (MUTTMENU *menu)
  645. menu_pad_string (buf, sizeof (buf));
  646. ATTRSET(attr);
  647. - move(i - menu->top + menu->offset, 0);
  648. + move(i - menu->top + menu->offset, SidebarWidth);
  649. do_color = 1;
  650. if (i == menu->current)
  651. @@ -272,7 +274,7 @@ void menu_redraw_index (MUTTMENU *menu)
  652. else
  653. {
  654. NORMAL_COLOR;
  655. - CLEARLINE(i - menu->top + menu->offset);
  656. + CLEARLINE_WIN(i - menu->top + menu->offset);
  657. }
  658. }
  659. NORMAL_COLOR;
  660. @@ -289,7 +291,7 @@ void menu_redraw_motion (MUTTMENU *menu)
  661. return;
  662. }
  663. - move (menu->oldcurrent + menu->offset - menu->top, 0);
  664. + move (menu->oldcurrent + menu->offset - menu->top, SidebarWidth);
  665. ATTRSET(menu->color (menu->oldcurrent));
  666. if (option (OPTARROWCURSOR))
  667. @@ -301,13 +303,13 @@ void menu_redraw_motion (MUTTMENU *menu)
  668. {
  669. menu_make_entry (buf, sizeof (buf), menu, menu->oldcurrent);
  670. menu_pad_string (buf, sizeof (buf));
  671. - move (menu->oldcurrent + menu->offset - menu->top, 3);
  672. + move (menu->oldcurrent + menu->offset - menu->top, SidebarWidth + 3);
  673. print_enriched_string (menu->color(menu->oldcurrent), (unsigned char *) buf, 1);
  674. }
  675. /* now draw it in the new location */
  676. SETCOLOR(MT_COLOR_INDICATOR);
  677. - mvaddstr(menu->current + menu->offset - menu->top, 0, "->");
  678. + mvaddstr(menu->current + menu->offset - menu->top, SidebarWidth, "->");
  679. }
  680. else
  681. {
  682. @@ -320,7 +322,7 @@ void menu_redraw_motion (MUTTMENU *menu)
  683. menu_make_entry (buf, sizeof (buf), menu, menu->current);
  684. menu_pad_string (buf, sizeof (buf));
  685. SETCOLOR(MT_COLOR_INDICATOR);
  686. - move(menu->current - menu->top + menu->offset, 0);
  687. + move(menu->current - menu->top + menu->offset, SidebarWidth);
  688. print_enriched_string (menu->color(menu->current), (unsigned char *) buf, 0);
  689. }
  690. menu->redraw &= REDRAW_STATUS;
  691. @@ -332,7 +334,7 @@ void menu_redraw_current (MUTTMENU *menu)
  692. char buf[LONG_STRING];
  693. int attr = menu->color (menu->current);
  694. - move (menu->current + menu->offset - menu->top, 0);
  695. + move (menu->current + menu->offset - menu->top, SidebarWidth);
  696. menu_make_entry (buf, sizeof (buf), menu, menu->current);
  697. menu_pad_string (buf, sizeof (buf));
  698. @@ -881,7 +883,7 @@ int mutt_menuLoop (MUTTMENU *menu)
  699. if (option (OPTARROWCURSOR))
  700. - move (menu->current - menu->top + menu->offset, 2);
  701. + move (menu->current - menu->top + menu->offset, SidebarWidth + 2);
  702. else if (option (OPTBRAILLEFRIENDLY))
  703. move (menu->current - menu->top + menu->offset, 0);
  704. else
  705. diff --git a/mh.c b/mh.c
  706. index 21e6491..48a16fb 100644
  707. --- a/mh.c
  708. +++ b/mh.c
  709. @@ -295,6 +295,28 @@ void mh_buffy(BUFFY *b)
  710. mhs_free_sequences (&mhs);
  711. }
  712. +void mh_buffy_update (const char *path, int *msgcount, int *msg_unread, int *msg_flagged)
  713. +{
  714. + int i;
  715. + struct mh_sequences mhs;
  716. + memset (&mhs, 0, sizeof (mhs));
  717. +
  718. + if (mh_read_sequences (&mhs, path) < 0)
  719. + return;
  720. +
  721. + msgcount = 0;
  722. + msg_unread = 0;
  723. + msg_flagged = 0;
  724. + for (i = 0; i <= mhs.max; i++)
  725. + msgcount++;
  726. + if (mhs_check (&mhs, i) & MH_SEQ_UNSEEN) {
  727. + msg_unread++;
  728. + }
  729. + if (mhs_check (&mhs, i) & MH_SEQ_FLAGGED)
  730. + msg_flagged++;
  731. + mhs_free_sequences (&mhs);
  732. +}
  733. +
  734. static int mh_mkstemp (CONTEXT * dest, FILE ** fp, char **tgt)
  735. {
  736. int fd;
  737. diff --git a/mutt.h b/mutt.h
  738. index 4db92a6..61a9612 100644
  739. --- a/mutt.h
  740. +++ b/mutt.h
  741. @@ -433,6 +433,8 @@ enum
  742. OPTSAVEEMPTY,
  743. OPTSAVENAME,
  744. OPTSCORE,
  745. + OPTSIDEBAR,
  746. + OPTSIDEBARSORT,
  747. OPTSIGDASHES,
  748. OPTSIGONTOP,
  749. OPTSORTRE,
  750. @@ -876,6 +878,7 @@ typedef struct _context
  751. {
  752. char *path;
  753. FILE *fp;
  754. + time_t atime;
  755. time_t mtime;
  756. off_t size;
  757. off_t vsize;
  758. @@ -916,6 +919,7 @@ typedef struct _context
  759. unsigned int quiet : 1; /* inhibit status messages? */
  760. unsigned int collapsed : 1; /* are all threads collapsed? */
  761. unsigned int closing : 1; /* mailbox is being closed */
  762. + unsigned int peekonly : 1; /* just taking a glance, revert atime */
  763. /* driver hooks */
  764. void *data; /* driver specific data */
  765. diff --git a/mutt_curses.h b/mutt_curses.h
  766. index f8d6f88..aee797e 100644
  767. --- a/mutt_curses.h
  768. +++ b/mutt_curses.h
  769. @@ -64,6 +64,7 @@
  770. #undef lines
  771. #endif /* lines */
  772. +#define CLEARLINE_WIN(x) move(x,SidebarWidth), clrtoeol()
  773. #define CLEARLINE(x) move(x,0), clrtoeol()
  774. #define CENTERLINE(x,y) move(y, (COLS-strlen(x))/2), addstr(x)
  775. #define BEEP() do { if (option (OPTBEEP)) beep(); } while (0)
  776. @@ -120,6 +121,8 @@ enum
  777. MT_COLOR_BOLD,
  778. MT_COLOR_UNDERLINE,
  779. MT_COLOR_INDEX,
  780. + MT_COLOR_NEW,
  781. + MT_COLOR_FLAGGED,
  782. MT_COLOR_MAX
  783. };
  784. diff --git a/muttlib.c b/muttlib.c
  785. index c0d2026..9086f07 100644
  786. --- a/muttlib.c
  787. +++ b/muttlib.c
  788. @@ -1284,6 +1284,8 @@ void mutt_FormatString (char *dest, /* output buffer */
  789. pl = pw = 1;
  790. /* see if there's room to add content, else ignore */
  791. + if ( DrawFullLine )
  792. + {
  793. if ((col < COLS && wlen < destlen) || soft)
  794. {
  795. int pad;
  796. @@ -1327,6 +1329,52 @@ void mutt_FormatString (char *dest, /* output buffer */
  797. col += wid;
  798. src += pl;
  799. }
  800. + }
  801. + else
  802. + {
  803. + if ((col < COLS-SidebarWidth && wlen < destlen) || soft)
  804. + {
  805. + int pad;
  806. +
  807. + /* get contents after padding */
  808. + mutt_FormatString (buf, sizeof (buf), 0, src + pl, callback, data, flags);
  809. + len = mutt_strlen (buf);
  810. + wid = mutt_strwidth (buf);
  811. +
  812. + /* try to consume as many columns as we can, if we don't have
  813. + * memory for that, use as much memory as possible */
  814. + pad = (COLS - SidebarWidth - col - wid) / pw;
  815. + if (pad > 0 && wlen + (pad * pl) + len > destlen)
  816. + pad = ((signed)(destlen - wlen - len)) / pl;
  817. + if (pad > 0)
  818. + {
  819. + while (pad--)
  820. + {
  821. + memcpy (wptr, src, pl);
  822. + wptr += pl;
  823. + wlen += pl;
  824. + col += pw;
  825. + }
  826. + }
  827. + else if (soft && pad < 0)
  828. + {
  829. + /* \0-terminate dest for length computation in mutt_wstr_trunc() */
  830. + *wptr = 0;
  831. + /* make sure right part is at most as wide as display */
  832. + len = mutt_wstr_trunc (buf, destlen, COLS, &wid);
  833. + /* truncate left so that right part fits completely in */
  834. + wlen = mutt_wstr_trunc (dest, destlen - len, col + pad, &col);
  835. + wptr = dest + wlen;
  836. + }
  837. + if (len + wlen > destlen)
  838. + len = mutt_wstr_trunc (buf, destlen - wlen, COLS - SidebarWidth - col, NULL);
  839. + memcpy (wptr, buf, len);
  840. + wptr += len;
  841. + wlen += len;
  842. + col += wid;
  843. + src += pl;
  844. + }
  845. + }
  846. break; /* skip rest of input */
  847. }
  848. else if (ch == '|')
  849. diff --git a/mx.c b/mx.c
  850. index 07dba0c..cbee47d 100644
  851. --- a/mx.c
  852. +++ b/mx.c
  853. @@ -595,6 +595,7 @@ static int mx_open_mailbox_append (CONTEXT *ctx, int flags)
  854. * M_APPEND open mailbox for appending
  855. * M_READONLY open mailbox in read-only mode
  856. * M_QUIET only print error messages
  857. + * M_PEEK revert atime where applicable
  858. * ctx if non-null, context struct to use
  859. */
  860. CONTEXT *mx_open_mailbox (const char *path, int flags, CONTEXT *pctx)
  861. @@ -617,6 +618,8 @@ CONTEXT *mx_open_mailbox (const char *path, int flags, CONTEXT *pctx)
  862. ctx->quiet = 1;
  863. if (flags & M_READONLY)
  864. ctx->readonly = 1;
  865. + if (flags & M_PEEK)
  866. + ctx->peekonly = 1;
  867. if (flags & (M_APPEND|M_NEWFOLDER))
  868. {
  869. @@ -721,9 +724,21 @@ CONTEXT *mx_open_mailbox (const char *path, int flags, CONTEXT *pctx)
  870. void mx_fastclose_mailbox (CONTEXT *ctx)
  871. {
  872. int i;
  873. +#ifndef BUFFY_SIZE
  874. + struct utimbuf ut;
  875. +#endif
  876. if(!ctx)
  877. return;
  878. +#ifndef BUFFY_SIZE
  879. + /* fix up the times so buffy won't get confused */
  880. + if (ctx->peekonly && ctx->path && ctx->mtime > ctx->atime)
  881. + {
  882. + ut.actime = ctx->atime;
  883. + ut.modtime = ctx->mtime;
  884. + utime (ctx->path, &ut);
  885. + }
  886. +#endif
  887. /* never announce that a mailbox we've just left has new mail. #3290
  888. * XXX: really belongs in mx_close_mailbox, but this is a nice hook point */
  889. diff --git a/mx.h b/mx.h
  890. index 2ef4ec7..4aabadf 100644
  891. --- a/mx.h
  892. +++ b/mx.h
  893. @@ -60,6 +60,7 @@ void mbox_reset_atime (CONTEXT *, struct stat *);
  894. int mh_read_dir (CONTEXT *, const char *);
  895. int mh_sync_mailbox (CONTEXT *, int *);
  896. int mh_check_mailbox (CONTEXT *, int *);
  897. +void mh_buffy_update (const char *, int *, int *, int *);
  898. int mh_check_empty (const char *);
  899. int maildir_read_dir (CONTEXT *);
  900. diff --git a/pager.c b/pager.c
  901. index 7b61266..469efe4 100644
  902. --- a/pager.c
  903. +++ b/pager.c
  904. @@ -29,6 +29,7 @@
  905. #include "pager.h"
  906. #include "attach.h"
  907. #include "mbyte.h"
  908. +#include "sidebar.h"
  909. #include "mutt_crypt.h"
  910. @@ -1095,6 +1096,7 @@ static int format_line (struct line_t **lineInfo, int n, unsigned char *buf,
  911. wchar_t wc;
  912. mbstate_t mbstate;
  913. int wrap_cols = mutt_term_width ((flags & M_PAGER_NOWRAP) ? 0 : Wrap);
  914. + wrap_cols -= SidebarWidth;
  915. if (check_attachment_marker ((char *)buf) == 0)
  916. wrap_cols = COLS;
  917. @@ -1746,7 +1748,7 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra)
  918. if ((redraw & REDRAW_BODY) || topline != oldtopline)
  919. {
  920. do {
  921. - move (bodyoffset, 0);
  922. + move (bodyoffset, SidebarWidth);
  923. curline = oldtopline = topline;
  924. lines = 0;
  925. force_redraw = 0;
  926. @@ -1759,6 +1761,7 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra)
  927. &QuoteList, &q_level, &force_redraw, &SearchRE) > 0)
  928. lines++;
  929. curline++;
  930. + move(lines + bodyoffset, SidebarWidth);
  931. }
  932. last_offset = lineInfo[curline].offset;
  933. } while (force_redraw);
  934. @@ -1771,6 +1774,7 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra)
  935. addch ('~');
  936. addch ('\n');
  937. lines++;
  938. + move(lines + bodyoffset, SidebarWidth);
  939. }
  940. NORMAL_COLOR;
  941. @@ -1794,22 +1798,22 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra)
  942. strfcpy(pager_progress_str, (topline == 0) ? "all" : "end", sizeof(pager_progress_str));
  943. /* print out the pager status bar */
  944. - move (statusoffset, 0);
  945. + move (statusoffset, SidebarWidth);
  946. SETCOLOR (MT_COLOR_STATUS);
  947. if (IsHeader (extra) || IsMsgAttach (extra))
  948. {
  949. - size_t l1 = COLS * MB_LEN_MAX;
  950. + size_t l1 = (COLS-SidebarWidth) * MB_LEN_MAX;
  951. size_t l2 = sizeof (buffer);
  952. hfi.hdr = (IsHeader (extra)) ? extra->hdr : extra->bdy->hdr;
  953. mutt_make_string_info (buffer, l1 < l2 ? l1 : l2, NONULL (PagerFmt), &hfi, M_FORMAT_MAKEPRINT);
  954. - mutt_paddstr (COLS, buffer);
  955. + mutt_paddstr (COLS-SidebarWidth, buffer);
  956. }
  957. else
  958. {
  959. char bn[STRING];
  960. snprintf (bn, sizeof (bn), "%s (%s)", banner, pager_progress_str);
  961. - mutt_paddstr (COLS, bn);
  962. + mutt_paddstr (COLS-SidebarWidth, bn);
  963. }
  964. NORMAL_COLOR;
  965. if (option(OPTXTERMSETTITLES))
  966. @@ -1826,16 +1830,21 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra)
  967. /* redraw the pager_index indicator, because the
  968. * flags for this message might have changed. */
  969. menu_redraw_current (index);
  970. + draw_sidebar(MENU_PAGER);
  971. /* print out the index status bar */
  972. menu_status_line (buffer, sizeof (buffer), index, NONULL(Status));
  973. - move (indexoffset + (option (OPTSTATUSONTOP) ? 0 : (indexlen - 1)), 0);
  974. + move (indexoffset + (option (OPTSTATUSONTOP) ? 0 : (indexlen - 1)), SidebarWidth);
  975. SETCOLOR (MT_COLOR_STATUS);
  976. - mutt_paddstr (COLS, buffer);
  977. + mutt_paddstr (COLS-SidebarWidth, buffer);
  978. NORMAL_COLOR;
  979. }
  980. + /* if we're not using the index, update every time */
  981. + if ( index == 0 )
  982. + draw_sidebar(MENU_PAGER);
  983. +
  984. redraw = 0;
  985. if (option(OPTBRAILLEFRIENDLY)) {
  986. @@ -2776,6 +2785,13 @@ search_next:
  987. mutt_what_key ();
  988. break;
  989. + case OP_SIDEBAR_SCROLL_UP:
  990. + case OP_SIDEBAR_SCROLL_DOWN:
  991. + case OP_SIDEBAR_NEXT:
  992. + case OP_SIDEBAR_PREV:
  993. + scroll_sidebar(ch, MENU_PAGER);
  994. + break;
  995. +
  996. default:
  997. ch = -1;
  998. break;
  999. diff --git a/sidebar.c b/sidebar.c
  1000. new file mode 100644
  1001. index 0000000..6098c2a
  1002. --- /dev/null
  1003. +++ b/sidebar.c
  1004. @@ -0,0 +1,333 @@
  1005. +/*
  1006. + * Copyright (C) ????-2004 Justin Hibbits <jrh29@po.cwru.edu>
  1007. + * Copyright (C) 2004 Thomer M. Gil <mutt@thomer.com>
  1008. + *
  1009. + * This program is free software; you can redistribute it and/or modify
  1010. + * it under the terms of the GNU General Public License as published by
  1011. + * the Free Software Foundation; either version 2 of the License, or
  1012. + * (at your option) any later version.
  1013. + *
  1014. + * This program is distributed in the hope that it will be useful,
  1015. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1016. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  1017. + * GNU General Public License for more details.
  1018. + *
  1019. + * You should have received a copy of the GNU General Public License
  1020. + * along with this program; if not, write to the Free Software
  1021. + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
  1022. + */
  1023. +
  1024. +
  1025. +#if HAVE_CONFIG_H
  1026. +# include "config.h"
  1027. +#endif
  1028. +
  1029. +#include "mutt.h"
  1030. +#include "mutt_menu.h"
  1031. +#include "mutt_curses.h"
  1032. +#include "sidebar.h"
  1033. +#include "buffy.h"
  1034. +#include <libgen.h>
  1035. +#include "keymap.h"
  1036. +#include <stdbool.h>
  1037. +
  1038. +/*BUFFY *CurBuffy = 0;*/
  1039. +static BUFFY *TopBuffy = 0;
  1040. +static BUFFY *BottomBuffy = 0;
  1041. +static int known_lines = 0;
  1042. +
  1043. +static int quick_log10(int n)
  1044. +{
  1045. + char string[32];
  1046. + sprintf(string, "%d", n);
  1047. + return strlen(string);
  1048. +}
  1049. +
  1050. +void calc_boundaries (int menu)
  1051. +{
  1052. + BUFFY *tmp = Incoming;
  1053. +
  1054. + if ( known_lines != LINES ) {
  1055. + TopBuffy = BottomBuffy = 0;
  1056. + known_lines = LINES;
  1057. + }
  1058. + for ( ; tmp->next != 0; tmp = tmp->next )
  1059. + tmp->next->prev = tmp;
  1060. +
  1061. + if ( TopBuffy == 0 && BottomBuffy == 0 )
  1062. + TopBuffy = Incoming;
  1063. + if ( BottomBuffy == 0 ) {
  1064. + int count = LINES - 2 - (menu != MENU_PAGER || option(OPTSTATUSONTOP));
  1065. + BottomBuffy = TopBuffy;
  1066. + while ( --count && BottomBuffy->next )
  1067. + BottomBuffy = BottomBuffy->next;
  1068. + }
  1069. + else if ( TopBuffy == CurBuffy->next ) {
  1070. + int count = LINES - 2 - (menu != MENU_PAGER);
  1071. + BottomBuffy = CurBuffy;
  1072. + tmp = BottomBuffy;
  1073. + while ( --count && tmp->prev)
  1074. + tmp = tmp->prev;
  1075. + TopBuffy = tmp;
  1076. + }
  1077. + else if ( BottomBuffy == CurBuffy->prev ) {
  1078. + int count = LINES - 2 - (menu != MENU_PAGER);
  1079. + TopBuffy = CurBuffy;
  1080. + tmp = TopBuffy;
  1081. + while ( --count && tmp->next )
  1082. + tmp = tmp->next;
  1083. + BottomBuffy = tmp;
  1084. + }
  1085. +}
  1086. +
  1087. +char *make_sidebar_entry(char *box, int size, int new, int flagged)
  1088. +{
  1089. + static char *entry = 0;
  1090. + char *c;
  1091. + int i = 0;
  1092. + int delim_len = strlen(SidebarDelim);
  1093. +
  1094. + c = realloc(entry, SidebarWidth - delim_len + 2);
  1095. + if ( c ) entry = c;
  1096. + entry[SidebarWidth - delim_len + 1] = 0;
  1097. + for (; i < SidebarWidth - delim_len + 1; entry[i++] = ' ' );
  1098. + i = strlen(box);
  1099. + strncpy( entry, box, i < (SidebarWidth - delim_len + 1) ? i : (SidebarWidth - delim_len + 1) );
  1100. +
  1101. + if (size == -1)
  1102. + sprintf(entry + SidebarWidth - delim_len - 3, "?");
  1103. + else if ( new ) {
  1104. + if (flagged > 0) {
  1105. + sprintf(
  1106. + entry + SidebarWidth - delim_len - 5 - quick_log10(size) - quick_log10(new) - quick_log10(flagged),
  1107. + "% d(%d)[%d]", size, new, flagged);
  1108. + } else {
  1109. + sprintf(
  1110. + entry + SidebarWidth - delim_len - 3 - quick_log10(size) - quick_log10(new),
  1111. + "% d(%d)", size, new);
  1112. + }
  1113. + } else if (flagged > 0) {
  1114. + sprintf( entry + SidebarWidth - delim_len - 3 - quick_log10(size) - quick_log10(flagged), "% d[%d]", size, flagged);
  1115. + } else {
  1116. + sprintf( entry + SidebarWidth - delim_len - 1 - quick_log10(size), "% d", size);
  1117. + }
  1118. + return entry;
  1119. +}
  1120. +
  1121. +void set_curbuffy(char buf[LONG_STRING])
  1122. +{
  1123. + BUFFY* tmp = CurBuffy = Incoming;
  1124. +
  1125. + if (!Incoming)
  1126. + return;
  1127. +
  1128. + while(1) {
  1129. + if(!strcmp(tmp->path, buf)) {
  1130. + CurBuffy = tmp;
  1131. + break;
  1132. + }
  1133. +
  1134. + if(tmp->next)
  1135. + tmp = tmp->next;
  1136. + else
  1137. + break;
  1138. + }
  1139. +}
  1140. +
  1141. +int draw_sidebar(int menu) {
  1142. +
  1143. + int lines = option(OPTHELP) ? 1 : 0;
  1144. + BUFFY *tmp;
  1145. +#ifndef USE_SLANG_CURSES
  1146. + attr_t attrs;
  1147. +#endif
  1148. + short delim_len = strlen(SidebarDelim);
  1149. + short color_pair;
  1150. +
  1151. + static bool initialized = false;
  1152. + static int prev_show_value;
  1153. + static short saveSidebarWidth;
  1154. +
  1155. + /* initialize first time */
  1156. + if(!initialized) {
  1157. + prev_show_value = option(OPTSIDEBAR);
  1158. + saveSidebarWidth = SidebarWidth;
  1159. + if(!option(OPTSIDEBAR)) SidebarWidth = 0;
  1160. + initialized = true;
  1161. + }
  1162. +
  1163. + /* save or restore the value SidebarWidth */
  1164. + if(prev_show_value != option(OPTSIDEBAR)) {
  1165. + if(prev_show_value && !option(OPTSIDEBAR)) {
  1166. + saveSidebarWidth = SidebarWidth;
  1167. + SidebarWidth = 0;
  1168. + } else if(!prev_show_value && option(OPTSIDEBAR)) {
  1169. + SidebarWidth = saveSidebarWidth;
  1170. + }
  1171. + prev_show_value = option(OPTSIDEBAR);
  1172. + }
  1173. +
  1174. +
  1175. +// if ( SidebarWidth == 0 ) return 0;
  1176. + if (SidebarWidth > 0 && option (OPTSIDEBAR)
  1177. + && delim_len >= SidebarWidth) {
  1178. + unset_option (OPTSIDEBAR);
  1179. + /* saveSidebarWidth = SidebarWidth; */
  1180. + if (saveSidebarWidth > delim_len) {
  1181. + SidebarWidth = saveSidebarWidth;
  1182. + mutt_error (_("Value for sidebar_delim is too long. Disabling sidebar."));
  1183. + sleep (2);
  1184. + } else {
  1185. + SidebarWidth = 0;
  1186. + mutt_error (_("Value for sidebar_delim is too long. Disabling sidebar. Please set your sidebar_width to a sane value."));
  1187. + sleep (4); /* the advise to set a sane value should be seen long enough */
  1188. + }
  1189. + saveSidebarWidth = 0;
  1190. + return (0);
  1191. + }
  1192. +
  1193. + if ( SidebarWidth == 0 || !option(OPTSIDEBAR)) {
  1194. + if (SidebarWidth > 0) {
  1195. + saveSidebarWidth = SidebarWidth;
  1196. + SidebarWidth = 0;
  1197. + }
  1198. + unset_option(OPTSIDEBAR);
  1199. + return 0;
  1200. + }
  1201. +
  1202. + /* get attributes for divider */
  1203. + SETCOLOR(MT_COLOR_STATUS);
  1204. +#ifndef USE_SLANG_CURSES
  1205. + attr_get(&attrs, &color_pair, 0);
  1206. +#else
  1207. + color_pair = attr_get();
  1208. +#endif
  1209. + SETCOLOR(MT_COLOR_NORMAL);
  1210. +
  1211. + /* draw the divider */
  1212. +
  1213. + for ( ; lines < LINES-1-(menu != MENU_PAGER || option(OPTSTATUSONTOP)); lines++ ) {
  1214. + move(lines, SidebarWidth - delim_len);
  1215. + addstr(NONULL(SidebarDelim));
  1216. +#ifndef USE_SLANG_CURSES
  1217. + mvchgat(lines, SidebarWidth - delim_len, delim_len, 0, color_pair, NULL);
  1218. +#endif
  1219. + }
  1220. +
  1221. + if ( Incoming == 0 ) return 0;
  1222. + lines = option(OPTHELP) ? 1 : 0; /* go back to the top */
  1223. +
  1224. + if ( known_lines != LINES || TopBuffy == 0 || BottomBuffy == 0 )
  1225. + calc_boundaries(menu);
  1226. + if ( CurBuffy == 0 ) CurBuffy = Incoming;
  1227. +
  1228. + tmp = TopBuffy;
  1229. +
  1230. + SETCOLOR(MT_COLOR_NORMAL);
  1231. +
  1232. + for ( ; tmp && lines < LINES-1 - (menu != MENU_PAGER || option(OPTSTATUSONTOP)); tmp = tmp->next ) {
  1233. + if ( tmp == CurBuffy )
  1234. + SETCOLOR(MT_COLOR_INDICATOR);
  1235. + else if ( tmp->msg_unread > 0 )
  1236. + SETCOLOR(MT_COLOR_NEW);
  1237. + else if ( tmp->msg_flagged > 0 )
  1238. + SETCOLOR(MT_COLOR_FLAGGED);
  1239. + else
  1240. + SETCOLOR(MT_COLOR_NORMAL);
  1241. +
  1242. + move( lines, 0 );
  1243. + if ( Context && !strcmp( tmp->path, Context->path ) ) {
  1244. + tmp->msg_unread = Context->unread;
  1245. + tmp->msgcount = Context->msgcount;
  1246. + tmp->msg_flagged = Context->flagged;
  1247. + }
  1248. + // check whether Maildir is a prefix of the current folder's path
  1249. + short maildir_is_prefix = 0;
  1250. + if ( (strlen(tmp->path) > strlen(Maildir)) &&
  1251. + (strncmp(Maildir, tmp->path, strlen(Maildir)) == 0) )
  1252. + maildir_is_prefix = 1;
  1253. + // calculate depth of current folder and generate its display name with indented spaces
  1254. + int sidebar_folder_depth = 0;
  1255. + char *sidebar_folder_name;
  1256. + sidebar_folder_name = basename(tmp->path);
  1257. + if ( maildir_is_prefix ) {
  1258. + char *tmp_folder_name;
  1259. + int i;
  1260. + tmp_folder_name = tmp->path + strlen(Maildir);
  1261. + for (i = 0; i < strlen(tmp->path) - strlen(Maildir); i++) {
  1262. + if (tmp_folder_name[i] == '/') sidebar_folder_depth++;
  1263. + }
  1264. + if (sidebar_folder_depth > 0) {
  1265. + sidebar_folder_name = malloc(strlen(basename(tmp->path)) + sidebar_folder_depth + 1);
  1266. + for (i=0; i < sidebar_folder_depth; i++)
  1267. + sidebar_folder_name[i]=' ';
  1268. + sidebar_folder_name[i]=0;
  1269. + strncat(sidebar_folder_name, basename(tmp->path), strlen(basename(tmp->path)) + sidebar_folder_depth);
  1270. + }
  1271. + }
  1272. + printw( "%.*s", SidebarWidth - delim_len + 1,
  1273. + make_sidebar_entry(sidebar_folder_name, tmp->msgcount,
  1274. + tmp->msg_unread, tmp->msg_flagged));
  1275. + if (sidebar_folder_depth > 0)
  1276. + free(sidebar_folder_name);
  1277. + lines++;
  1278. + }
  1279. + SETCOLOR(MT_COLOR_NORMAL);
  1280. + for ( ; lines < LINES-1 - (menu != MENU_PAGER || option(OPTSTATUSONTOP)); lines++ ) {
  1281. + int i = 0;
  1282. + move( lines, 0 );
  1283. + for ( ; i < SidebarWidth - delim_len; i++ )
  1284. + addch(' ');
  1285. + }
  1286. + return 0;
  1287. +}
  1288. +
  1289. +
  1290. +void set_buffystats(CONTEXT* Context)
  1291. +{
  1292. + BUFFY *tmp = Incoming;
  1293. + while(tmp) {
  1294. + if(Context && !strcmp(tmp->path, Context->path)) {
  1295. + tmp->msg_unread = Context->unread;
  1296. + tmp->msgcount = Context->msgcount;
  1297. + break;
  1298. + }
  1299. + tmp = tmp->next;
  1300. + }
  1301. +}
  1302. +
  1303. +void scroll_sidebar(int op, int menu)
  1304. +{
  1305. + if(!SidebarWidth) return;
  1306. + if(!CurBuffy) return;
  1307. +
  1308. + switch (op) {
  1309. + case OP_SIDEBAR_NEXT:
  1310. + if ( CurBuffy->next == NULL ) return;
  1311. + CurBuffy = CurBuffy->next;
  1312. + break;
  1313. + case OP_SIDEBAR_PREV:
  1314. + if ( CurBuffy->prev == NULL ) return;
  1315. + CurBuffy = CurBuffy->prev;
  1316. + break;
  1317. + case OP_SIDEBAR_SCROLL_UP:
  1318. + CurBuffy = TopBuffy;
  1319. + if ( CurBuffy != Incoming ) {
  1320. + calc_boundaries(menu);
  1321. + CurBuffy = CurBuffy->prev;
  1322. + }
  1323. + break;
  1324. + case OP_SIDEBAR_SCROLL_DOWN:
  1325. + CurBuffy = BottomBuffy;
  1326. + if ( CurBuffy->next ) {
  1327. + calc_boundaries(menu);
  1328. + CurBuffy = CurBuffy->next;
  1329. + }
  1330. + break;
  1331. + default:
  1332. + return;
  1333. + }
  1334. + calc_boundaries(menu);
  1335. + draw_sidebar(menu);
  1336. +}
  1337. +
  1338. diff --git a/sidebar.h b/sidebar.h
  1339. new file mode 100644
  1340. index 0000000..d195f11
  1341. --- /dev/null
  1342. +++ b/sidebar.h
  1343. @@ -0,0 +1,36 @@
  1344. +/*
  1345. + * Copyright (C) ????-2004 Justin Hibbits <jrh29@po.cwru.edu>
  1346. + * Copyright (C) 2004 Thomer M. Gil <mutt@thomer.com>
  1347. + *
  1348. + * This program is free software; you can redistribute it and/or modify
  1349. + * it under the terms of the GNU General Public License as published by
  1350. + * the Free Software Foundation; either version 2 of the License, or
  1351. + * (at your option) any later version.
  1352. + *
  1353. + * This program is distributed in the hope that it will be useful,
  1354. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1355. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  1356. + * GNU General Public License for more details.
  1357. + *
  1358. + * You should have received a copy of the GNU General Public License
  1359. + * along with this program; if not, write to the Free Software
  1360. + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
  1361. + */
  1362. +
  1363. +#ifndef SIDEBAR_H
  1364. +#define SIDEBAR_H
  1365. +
  1366. +struct MBOX_LIST {
  1367. + char *path;
  1368. + int msgcount;
  1369. + int new;
  1370. +} MBLIST;
  1371. +
  1372. +/* parameter is whether or not to go to the status line */
  1373. +/* used for omitting the last | that covers up the status bar in the index */
  1374. +int draw_sidebar(int);
  1375. +void scroll_sidebar(int, int);
  1376. +void set_curbuffy(char*);
  1377. +void set_buffystats(CONTEXT*);
  1378. +
  1379. +#endif /* SIDEBAR_H */