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-ui/lib-ui.h>
18 #include <lib-ui/menu.h>
19 #include <lib-ui/sidebar.h>
26 static int TopBuffy = 0;
27 static int CurBuffy = 0;
28 static short initialized = 0;
29 static short prev_show_value;
31 /* computes first entry to be shown */
32 static void calc_boundaries(void)
36 if (CurBuffy < 0 || CurBuffy >= Incoming.len)
38 if (TopBuffy < 0 || TopBuffy >= Incoming.len)
41 if (option (OPTSIDEBARNEWMAILONLY)) {
43 TopBuffy = CurBuffy - 1;
45 if (Incoming.arr[i]->new > 0)
50 TopBuffy = CurBuffy - (CurBuffy % (LINES - 3));
56 static char *shortened_hierarchy (char *hbox, int maxlen)
59 char *last_dot = NULL;
60 int i, j, len = m_strlen(hbox);
63 if (!SidebarBoundary || !*SidebarBoundary)
64 return (m_strdup(hbox));
66 for (i = 0; i < len; ++i) {
67 if (strchr (SidebarBoundary, hbox[i])) {
75 new_box = p_new(char, maxlen + 1);
77 for (i = 1, j = 1; j < maxlen && i < len; ++i) {
78 if (strchr (SidebarBoundary, hbox[i])) {
79 new_box[j++] = hbox[i];
81 if (&hbox[i + 1] != last_dot || j + m_strlen(last_dot) > maxlen) {
82 new_box[j++] = hbox[i + 1];
85 m_strcat(&new_box[j], maxlen + 1, last_dot);
92 return m_strdup(hbox);
96 sidebar_number_format(char* dest, ssize_t destlen,
97 char op, const char* src, const char* fmt,
98 const char* ifstr, const char* elstr,
99 anytype data, format_flag flags)
102 BUFFY* b = Incoming.arr[data.i];
103 int opt = flags & M_FORMAT_OPTIONAL;
104 int c = Context && !m_strcmp(Context->path, b->path);
110 snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
111 snprintf (dest, destlen, tmp, c ? Context->deleted : 0);
112 } else if ((c && Context->deleted == 0) || !c)
117 case 'f': /* for compatibility */
119 snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
120 snprintf (dest, destlen, tmp, c ? Context->flagged : b->msg_flagged);
121 } else if ((c && Context->flagged == 0) || (!c && b->msg_flagged == 0))
125 case 'c': /* for compatibility */
128 snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
129 snprintf (dest, destlen, tmp, c ? Context->msgcount : b->msgcount);
130 } else if ((c && Context->msgcount == 0) || (!c && b->msgcount == 0))
133 /* total shown, i.e. not hidden by limit */
136 snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
137 snprintf (dest, destlen, tmp, c ? Context->vcount : 0);
138 } else if ((c && Context->vcount == 0) || !c)
144 snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
145 snprintf (dest, destlen, tmp, c ? Context->new : b->new);
146 } else if ((c && Context->new == 0) || (!c && b->new == 0))
152 snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
153 snprintf (dest, destlen, tmp, c ? Context->unread : b->msg_unread);
154 } else if ((c && Context->unread == 0) || (!c && b->msg_unread == 0))
160 snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
161 snprintf (dest, destlen, tmp, c ? Context->tagged : 0);
162 } else if ((c && Context->tagged == 0) || !c)
167 if (flags & M_FORMAT_OPTIONAL)
168 m_strformat(dest, destlen, 0, opt ? ifstr : elstr,
169 sidebar_number_format, data, flags);
173 int sidebar_need_count(void)
175 return ui_layout_sidebar_w()
176 && !m_strisempty(SidebarNumberFormat);
181 * 0 item was not printed ('cause of $sidebar_newmail_only)
184 static int make_sidebar_entry(WINDOW *sw, char *sbox, int idx, ssize_t len)
186 int shortened = 0, lencnt = 0;
187 char no[STRING], entry[STRING];
188 int l_m = m_strlen(Maildir);
190 if (option(OPTSIDEBARNEWMAILONLY) && sbox && Context && Context->path &&
191 m_strcmp(Context->path, sbox) && Incoming.arr[idx]->new == 0)
192 /* if $sidebar_newmail_only is set, don't display the
193 * box only if it's not the currently opened
194 * (i.e. always display the currently opened) */
197 m_strformat(no, sizeof(no), len, SidebarNumberFormat,
198 sidebar_number_format, idx, 0);
199 lencnt = m_strlen(no);
201 if (l_m > 0 && m_strncmp(sbox, Maildir, l_m) == 0 &&
202 m_strlen(sbox) > l_m) {
204 if (Maildir[strlen(Maildir)-1]!='/') {
208 sbox = basename(sbox);
211 if (option(OPTSHORTENHIERARCHY) && m_strlen(sbox) > len - lencnt) {
212 sbox = shortened_hierarchy(sbox, len - lencnt);
216 snprintf(entry, sizeof(entry), "%*s", (int)len, no);
217 memcpy(entry, sbox, MIN(len, m_strlen(sbox)));
218 waddnstr(sw, entry, len);
226 /* returns folder name of currently
227 * selected folder for <sidebar-open>
229 const char* sidebar_get_current (void) {
232 return Incoming.arr[CurBuffy]->path;
235 /* internally sets item to buf */
236 void sidebar_set_current (const char* buf) {
237 int i = buffy_lookup (buf);
244 /* fix counters for a context
245 * FIXME since ctx must not be of our business, move it elsewhere
247 void sidebar_set_buffystats (CONTEXT* curContext) {
250 if (!curContext || !Incoming.len || (i = buffy_lookup (curContext->path)) < 0)
252 tmp = Incoming.arr[i];
253 tmp->new = curContext->new;
254 tmp->msg_unread = curContext->unread;
255 tmp->msgcount = curContext->msgcount;
256 tmp->msg_flagged = curContext->flagged;
259 /* actually draws something
260 * FIXME this needs some clue when to do it
262 int sidebar_draw(void)
268 /* initialize first time */
270 prev_show_value = option(OPTMBOXPANE);
274 if (TopBuffy == 0 || CurBuffy == 0)
277 /* save or restore the value SidebarWidth */
278 if (prev_show_value != option(OPTMBOXPANE)) {
279 if (!prev_show_value && option(OPTMBOXPANE)) {
280 /* after toggle: force recounting of all mail */
283 prev_show_value = option(OPTMBOXPANE);
286 sw = ui_layout_sidebar_w();
291 memset(&blank, ' ', sizeof(blank));
294 WSETCOLOR(sw, MT_COLOR_STATUS);
295 waddnstr(sw, blank, x);
297 for (i = TopBuffy, line = 1; i < Incoming.len && line < y; i++) {
298 BUFFY *tmp = Incoming.arr[i];
301 WSETCOLOR(sw, MT_COLOR_INDICATOR);
302 else if (tmp->new > 0)
303 WSETCOLOR(sw, MT_COLOR_NEW);
304 else if (tmp->msg_flagged > 0)
305 WSETCOLOR(sw, MT_COLOR_FLAGGED);
307 WSETCOLOR(sw, MT_COLOR_NORMAL);
309 if (make_sidebar_entry(sw, tmp->path, i, x - 1)) {
310 WSETCOLOR(sw, MT_COLOR_SIDEBAR);
311 waddch(sw, ACS_VLINE);
316 while (line < y - 1) {
317 WSETCOLOR(sw, MT_COLOR_NORMAL);
318 waddnstr(sw, blank, x - 1);
319 WSETCOLOR(sw, MT_COLOR_SIDEBAR);
320 waddch(sw, ACS_VLINE);
324 WSETCOLOR(sw, MT_COLOR_STATUS);
325 waddnstr(sw, blank, x);
326 WSETCOLOR(sw, MT_COLOR_NORMAL);
331 /* returns index of new item with new mail or -1 */
332 static int exist_next_new (void) {
337 while (i < Incoming.len)
338 if (Incoming.arr[i++]->new > 0)
343 /* returns index of prev item with new mail or -1 */
344 static int exist_prev_new (void) {
350 if (Incoming.arr[i--]->new > 0)
355 void sidebar_scroll (int op) {
358 if (!SidebarWidth || !Incoming.len)
362 case OP_SIDEBAR_NEXT:
363 if (!option (OPTSIDEBARNEWMAILONLY)) {
364 if (CurBuffy + 1 == Incoming.len) {
365 mutt_error (_("You are on the last mailbox."));
370 } /* the fall-through is intentional */
371 case OP_SIDEBAR_NEXT_NEW:
372 if ((i = exist_next_new ()) < 0) {
373 mutt_error (_("No next mailboxes with new mail."));
379 case OP_SIDEBAR_PREV:
380 if (!option (OPTSIDEBARNEWMAILONLY)) {
382 mutt_error (_("You are on the first mailbox."));
387 } /* the fall-through is intentional */
388 case OP_SIDEBAR_PREV_NEW:
389 if ((i = exist_prev_new ()) < 0) {
390 mutt_error (_("No previous mailbox with new mail."));
397 case OP_SIDEBAR_SCROLL_UP:
399 mutt_error (_("You are on the first mailbox."));
402 CurBuffy -= LINES - 3;
406 case OP_SIDEBAR_SCROLL_DOWN:
407 if (CurBuffy + 1 == Incoming.len) {
408 mutt_error (_("You are on the last mailbox."));
411 CurBuffy += LINES - 3;
412 if (CurBuffy >= Incoming.len)
413 CurBuffy = Incoming.len - 1;