2 * Copyright notice from original mutt:
3 * Copyright (C) ????-2004 Justin Hibbits <jrh29@po.cwru.edu>
4 * Copyright (C) 2004 Thomer M. Gil <mutt@thomer.com>
6 * Parts were written/modified by:
7 * Rocco Rutte <pdmef@cs.tu-berlin.de>
8 * Nico Golde <nico@ngolde.de>
10 * This file is part of mutt-ng, see http://www.muttng.org/.
11 * It's licensed under the GNU General Public License,
12 * please see the file GPL in the top level source directory.
15 #include <lib-lib/mem.h>
18 #include "mutt_menu.h"
19 #include "mutt_curses.h"
31 static int TopBuffy = 0;
32 static int CurBuffy = 0;
33 static int known_lines = 0;
34 static short initialized = 0;
35 static short prev_show_value;
37 /* computes first entry to be shown */
38 static void calc_boundaries (void) {
39 if (list_empty(Incoming))
41 if (CurBuffy < 0 || CurBuffy >= Incoming->length)
43 if (TopBuffy < 0 || TopBuffy >= Incoming->length)
46 if (option (OPTSIDEBARNEWMAILONLY)) {
48 TopBuffy = CurBuffy - 1;
50 if (((BUFFY*) Incoming->data[i])->new > 0)
54 } else if (known_lines>0)
55 TopBuffy = CurBuffy - (CurBuffy % known_lines);
60 static char *shortened_hierarchy (char *box, int maxlen)
63 char *last_dot = NULL;
64 int i, j, len = str_len (box);
67 if (!SidebarBoundary || !*SidebarBoundary)
68 return (str_dup (box));
70 for (i = 0; i < len; ++i) {
71 if (strchr (SidebarBoundary, box[i])) {
79 new_box = p_new(char, maxlen + 1);
81 for (i = 1, j = 1; j < maxlen && i < len; ++i) {
82 if (strchr (SidebarBoundary, box[i])) {
83 new_box[j++] = box[i];
85 if (&box[i + 1] != last_dot || j + str_len (last_dot) > maxlen) {
86 new_box[j++] = box[i + 1];
89 strcat (&new_box[j], last_dot);
99 static const char* sidebar_number_format (char* dest, size_t destlen, char op,
100 const char* src, const char* fmt,
101 const char* ifstr, const char* elstr,
102 unsigned long data, format_flag flags) {
103 char tmp[SHORT_STRING];
104 BUFFY* b = (BUFFY*) Incoming->data[data];
105 int opt = flags & M_FORMAT_OPTIONAL;
106 int c = Context && str_eq (Context->path, b->path);
112 snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
113 snprintf (dest, destlen, tmp, c ? Context->deleted : 0);
114 } else if ((c && Context->deleted == 0) || !c)
119 case 'f': /* for compatibility */
121 snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
122 snprintf (dest, destlen, tmp, c ? Context->flagged : b->msg_flagged);
123 } else if ((c && Context->flagged == 0) || (!c && b->msg_flagged == 0))
127 case 'c': /* for compatibility */
130 snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
131 snprintf (dest, destlen, tmp, c ? Context->msgcount : b->msgcount);
132 } else if ((c && Context->msgcount == 0) || (!c && b->msgcount == 0))
135 /* total shown, i.e. not hidden by limit */
138 snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
139 snprintf (dest, destlen, tmp, c ? Context->vcount : 0);
140 } else if ((c && Context->vcount == 0) || !c)
146 snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
147 snprintf (dest, destlen, tmp, c ? Context->new : b->new);
148 } else if ((c && Context->new == 0) || (!c && b->new == 0))
154 snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
155 snprintf (dest, destlen, tmp, c ? Context->unread : b->msg_unread);
156 } else if ((c && Context->unread == 0) || (!c && b->msg_unread == 0))
162 snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
163 snprintf (dest, destlen, tmp, c ? Context->tagged : 0);
164 } else if ((c && Context->tagged == 0) || !c)
170 mutt_FormatString (dest, destlen, ifstr, sidebar_number_format,
171 data, M_FORMAT_OPTIONAL);
172 else if (flags & M_FORMAT_OPTIONAL)
173 mutt_FormatString (dest, destlen, elstr, sidebar_number_format,
174 data, M_FORMAT_OPTIONAL);
178 int sidebar_need_count (void) {
179 if (!option (OPTMBOXPANE) || SidebarWidth == 0 ||
180 !SidebarNumberFormat || !*SidebarNumberFormat)
187 * 0 item was not printed ('cause of $sidebar_newmail_only)
190 int make_sidebar_entry (char* box, int idx, size_t len)
192 int shortened = 0, lencnt = 0;
193 char no[SHORT_STRING], entry[SHORT_STRING];
195 int l = str_len (ImapHomeNamespace);
197 int l_m = str_len (Maildir);
199 if (SidebarWidth > COLS)
202 if (option (OPTSIDEBARNEWMAILONLY) && box && Context && Context->path &&
203 !str_eq (Context->path, box) && ((BUFFY*) Incoming->data[idx])->new == 0)
204 /* if $sidebar_newmail_only is set, don't display the
205 * box only if it's not the currently opened
206 * (i.e. always display the currently opened) */
209 mutt_FormatString (no, len, NONULL (SidebarNumberFormat),
210 sidebar_number_format, idx, M_FORMAT_OPTIONAL);
211 lencnt = str_len (no);
212 memset (&entry, ' ', sizeof (entry));
215 if (l > 0 && str_ncmp (box, ImapHomeNamespace, l) == 0 &&
217 box += l + 1; /* we're trimming the ImapHomeNamespace, the "+ 1" is for the separator */
220 if (l_m > 0 && str_ncmp (box, Maildir, l_m) == 0 &&
221 str_len (box) > l_m) {
223 if (Maildir[strlen(Maildir)-1]!='/') {
227 box = basename (box);
229 if (option (OPTSHORTENHIERARCHY) && str_len (box) > len-lencnt-1) {
230 box = shortened_hierarchy (box, len-lencnt-1);
234 snprintf (entry, len-lencnt, "%s", box);
235 entry[str_len (entry)] = ' ';
236 strncpy (entry + (len - lencnt), no, lencnt);
238 addnstr (entry, len);
246 /* returns folder name of currently
247 * selected folder for <sidebar-open>
249 const char* sidebar_get_current (void) {
250 if (list_empty(Incoming))
252 return ((char*) ((BUFFY*) Incoming->data[CurBuffy])->path);
255 /* internally sets item to buf */
256 void sidebar_set_current (const char* buf) {
257 int i = buffy_lookup (buf);
264 /* fix counters for a context
265 * FIXME since ctx must not be of our business, move it elsewhere
267 void sidebar_set_buffystats (CONTEXT* Context) {
270 if (!Context || list_empty(Incoming) || (i = buffy_lookup (Context->path)) < 0)
272 tmp = (BUFFY*) Incoming->data[i];
273 tmp->new = Context->new;
274 tmp->msg_unread = Context->unread;
275 tmp->msgcount = Context->msgcount;
276 tmp->msg_flagged = Context->flagged;
279 void sidebar_draw_frames (void) {
282 if (!option(OPTMBOXPANE) || SidebarWidth==0)
285 delim_len=str_len(NONULL(SidebarDelim));
287 /* draw vertical delimiter */
288 SETCOLOR (MT_COLOR_SIDEBAR);
289 for (i = 0; i < LINES-1; i++) {
290 move (i, SidebarWidth - delim_len);
291 if (option (OPTASCIICHARS))
292 addstr (NONULL (SidebarDelim));
293 else if (!option (OPTASCIICHARS) && !str_cmp (SidebarDelim, "|"))
295 else if ((Charset_is_utf8) && !str_cmp (SidebarDelim, "|"))
296 addstr ("\342\224\202");
298 addstr (NONULL (SidebarDelim));
301 /* fill "gaps" at top+bottom */
302 SETCOLOR(MT_COLOR_STATUS);
303 for (i=0; i<SidebarWidth; i++) {
305 * if we don't have $status_on_top and have $help, fill top
306 * gap with spaces to get bg color
308 if (option(OPTSTATUSONTOP) || option(OPTHELP)) {
313 * if we don't have $status_on_top or we have $help, fill bottom
314 * gap with spaces to get bg color
316 if (!option(OPTSTATUSONTOP) || option(OPTHELP)) {
321 SETCOLOR (MT_COLOR_NORMAL);
324 /* actually draws something
325 * FIXME this needs some clue when to do it
327 int sidebar_draw (int menu) {
328 int first_line = option (OPTSTATUSONTOP) ? 1 : option (OPTHELP) ? 1 : 0,
329 last_line = LINES - 2 + (option (OPTSTATUSONTOP) && !option (OPTHELP) ? 1 : 0),
332 size_t delim_len = str_len (SidebarDelim);
333 char blank[SHORT_STRING];
335 known_lines=last_line-first_line;
337 /* initialize first time */
339 prev_show_value = option (OPTMBOXPANE);
343 if (TopBuffy==0 || CurBuffy==0)
346 /* save or restore the value SidebarWidth */
347 if (prev_show_value != option (OPTMBOXPANE)) {
348 if (!prev_show_value && option (OPTMBOXPANE)) {
349 /* after toggle: force recounting of all mail */
352 prev_show_value = option (OPTMBOXPANE);
355 if (SidebarWidth > 0 && option (OPTMBOXPANE)
356 && str_len (SidebarDelim) >= SidebarWidth) {
357 mutt_error (_("Value for sidebar_delim is too long. Disabling sidebar."));
359 unset_option (OPTMBOXPANE);
363 if (SidebarWidth == 0 || !option (OPTMBOXPANE))
366 sidebar_draw_frames();
368 if (list_empty(Incoming))
371 /* actually print items */
372 for (i = TopBuffy, line=first_line; i < Incoming->length && line < last_line; i++) {
373 tmp = (BUFFY*) Incoming->data[i];
376 SETCOLOR (MT_COLOR_INDICATOR);
377 else if (tmp->new > 0)
378 SETCOLOR (MT_COLOR_NEW);
379 else if (tmp->msg_flagged > 0)
380 SETCOLOR (MT_COLOR_FLAGGED);
382 SETCOLOR (MT_COLOR_NORMAL);
385 line += make_sidebar_entry (tmp->path, i, SidebarWidth-delim_len);
388 SETCOLOR (MT_COLOR_NORMAL);
390 /* fill with blanks to bottom */
391 memset (&blank, ' ', sizeof (blank));
392 for (; line < last_line; line++) {
394 addnstr (blank, SidebarWidth-delim_len);
399 /* returns index of new item with new mail or -1 */
400 static int exist_next_new () {
402 if (list_empty(Incoming))
405 while (i < Incoming->length)
406 if (((BUFFY*) Incoming->data[i++])->new > 0)
411 /* returns index of prev item with new mail or -1 */
412 static int exist_prev_new () {
414 if (list_empty(Incoming))
418 if (((BUFFY*) Incoming->data[i--])->new > 0)
423 void sidebar_scroll (int op, int menu) {
426 if (!SidebarWidth || list_empty(Incoming))
430 case OP_SIDEBAR_NEXT:
431 if (!option (OPTSIDEBARNEWMAILONLY)) {
432 if (CurBuffy + 1 == Incoming->length) {
433 mutt_error (_("You are on the last mailbox."));
438 } /* the fall-through is intentional */
439 case OP_SIDEBAR_NEXT_NEW:
440 if ((i = exist_next_new ()) < 0) {
441 mutt_error (_("No next mailboxes with new mail."));
447 case OP_SIDEBAR_PREV:
448 if (!option (OPTSIDEBARNEWMAILONLY)) {
450 mutt_error (_("You are on the first mailbox."));
455 } /* the fall-through is intentional */
456 case OP_SIDEBAR_PREV_NEW:
457 if ((i = exist_prev_new ()) < 0) {
458 mutt_error (_("No previous mailbox with new mail."));
465 case OP_SIDEBAR_SCROLL_UP:
467 mutt_error (_("You are on the first mailbox."));
470 CurBuffy -= known_lines;
474 case OP_SIDEBAR_SCROLL_DOWN:
475 if (CurBuffy + 1 == Incoming->length) {
476 mutt_error (_("You are on the last mailbox."));
479 CurBuffy += known_lines;
480 if (CurBuffy >= Incoming->length)
481 CurBuffy = Incoming->length - 1;