many simplifications, copyright statements.
[apps/madmutt.git] / status.c
1 /*
2  * Copyright notice from original mutt:
3  * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
4  *
5  * This file is part of mutt-ng, see http://www.muttng.org/.
6  * It's licensed under the GNU General Public License,
7  * please see the file GPL in the top level source directory.
8  */
9
10 #if HAVE_CONFIG_H
11 # include "config.h"
12 #endif
13
14 #include <lib-lib/mem.h>
15 #include <lib-lib/str.h>
16 #include <lib-lib/macros.h>
17 #include <lib-lib/mapping.h>
18
19 #include <lib-ui/curses.h>
20 #include <lib-ui/menu.h>
21
22 #include "mutt.h"
23 #include "sort.h"
24 #include "mx.h"
25 #include "buffy.h"
26
27
28 #include <string.h>
29 #include <ctype.h>
30 #include <unistd.h>
31
32 #define SW              (option(OPTMBOXPANE)?SidebarWidth:0)
33
34 static char *get_sort_str (char *buf, ssize_t buflen, int method)
35 {
36   snprintf (buf, buflen, "%s%s%s",
37             (method & SORT_REVERSE) ? "reverse-" : "",
38             (method & SORT_LAST) ? "last-" : "",
39             mutt_getnamebyvalue (method & SORT_MASK, SortMethods));
40   return buf;
41 }
42
43 /* %b = number of incoming folders with unread messages [option]
44  * %B = short mailbox path
45  * %d = number of deleted messages [option]
46  * %f = full mailbox path
47  * %F = number of flagged messages [option]
48  * %h = hostname
49  * %l = length of mailbox (in bytes) [option]
50  * %m = total number of messages [option]
51  * %M = number of messages shown (virutal message count when limiting) [option]
52  * %n = number of new messages [option]
53  * %p = number of postponed messages [option]
54  * %P = percent of way through index
55  * %r = readonly/wontwrite/changed flag
56  * %s = current sorting method ($sort)
57  * %S = current aux sorting method ($sort_aux)
58  * %t = # of tagged messages [option]
59  * %v = Madmutt version 
60  * %V = currently active limit pattern [option] */
61 static const char *status_format_str (char *buf, ssize_t buflen, char op,
62                                       const char *src, const char *prefix,
63                                       const char *ifstring,
64                                       const char *elsestring,
65                                       unsigned long data, format_flag flags)
66 {
67   char fmt[SHORT_STRING], tmp[SHORT_STRING];
68   const char *cp, *p;
69   int count, optional = (flags & M_FORMAT_OPTIONAL);
70   MUTTMENU *menu = (MUTTMENU *) data;
71
72   *buf = 0;
73   switch (op) {
74   case 'b':
75     if (!optional) {
76       snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
77       snprintf (buf, buflen, fmt, buffy_check (0));
78     }
79     else if (!buffy_check (0))
80       optional = 0;
81     break;
82
83   case 'B':
84     snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
85     if (Context && Context->compressinfo && Context->realpath) {
86       if ((p = strrchr (Context->realpath, '/')))
87         m_strcpy(tmp, sizeof(tmp), p + 1);
88       else
89         m_strcpy(tmp, sizeof(tmp), Context->realpath);
90     }
91     else
92     if (Context && Context->path) {
93       if ((p = strrchr (Context->path, '/')))
94         m_strcpy(tmp, sizeof(tmp), p + 1);
95       else
96         m_strcpy(tmp, sizeof(tmp), Context->path);
97     }
98     else
99       m_strcpy(tmp, sizeof(tmp), _("no mailbox"));
100     snprintf (buf, buflen, fmt, tmp);
101     break;
102
103   case 'd':
104     if (!optional) {
105       snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
106       snprintf (buf, buflen, fmt, Context ? Context->deleted : 0);
107     }
108     else if (!Context || !Context->deleted)
109       optional = 0;
110     break;
111
112   case 'h':
113     snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
114     snprintf (buf, buflen, fmt, NONULL (Hostname));
115     break;
116
117   case 'f':
118     snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
119     if (Context && Context->compressinfo && Context->realpath) {
120       m_strcpy(tmp, sizeof(tmp), Context->realpath);
121       mutt_pretty_mailbox (tmp);
122     }
123     else
124     if (Context && Context->path) {
125       m_strcpy(tmp, sizeof(tmp), Context->path);
126       mutt_pretty_mailbox (tmp);
127     }
128     else
129       m_strcpy(tmp, sizeof(tmp), _("(no mailbox)"));
130     snprintf (buf, buflen, fmt, tmp);
131     break;
132
133   case 'F':
134     if (!optional) {
135       snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
136       snprintf (buf, buflen, fmt, Context ? Context->flagged : 0);
137     }
138     else if (!Context || !Context->flagged)
139       optional = 0;
140     break;
141
142   case 'l':
143     if (!optional) {
144       snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
145       mutt_pretty_size (tmp, sizeof (tmp), Context ? Context->size : 0);
146       snprintf (buf, buflen, fmt, tmp);
147     }
148     else if (!Context || !Context->size)
149       optional = 0;
150     break;
151
152   case 'L':
153     if (!optional) {
154       snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
155       mutt_pretty_size (tmp, sizeof (tmp), Context ? Context->vsize : 0);
156       snprintf (buf, buflen, fmt, tmp);
157     }
158     else if (!Context || !Context->pattern)
159       optional = 0;
160     break;
161
162   case 'm':
163     if (!optional) {
164       snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
165       snprintf (buf, buflen, fmt, Context ? Context->msgcount : 0);
166     }
167     else if (!Context || !Context->msgcount)
168       optional = 0;
169     break;
170
171   case 'M':
172     if (!optional) {
173       snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
174       snprintf (buf, buflen, fmt, Context ? Context->vcount : 0);
175     }
176     else if (!Context || !Context->pattern)
177       optional = 0;
178     break;
179
180   case 'n':
181     if (!optional) {
182       snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
183       snprintf (buf, buflen, fmt, Context ? Context->new : 0);
184     }
185     else if (!Context || Context->new <= 0)
186       optional = 0;
187     break;
188
189   case 'o':
190     if (!optional) {
191       snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
192       snprintf (buf, buflen, fmt,
193                 Context ? Context->unread - Context->new : 0);
194     }
195     else if (!Context || !(Context->unread - Context->new))
196       optional = 0;
197     break;
198
199   case 'p':
200     count = mutt_num_postponed (0);
201     if (!optional) {
202       snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
203       snprintf (buf, buflen, fmt, count);
204     }
205     else if (!count)
206       optional = 0;
207     break;
208
209   case 'P':
210     if (menu->top + menu->pagelen >= menu->max)
211       cp = menu->top ? "end" : "all";
212     else {
213       count = (100 * (menu->top + menu->pagelen)) / menu->max;
214       snprintf (tmp, sizeof (tmp), "%d%%", count);
215       cp = tmp;
216     }
217     snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
218     snprintf (buf, buflen, fmt, cp);
219     break;
220
221   case 'r':
222     {
223       int i = 0;
224
225       if (Context) {
226         /* XXX: deleted doesn't necessarily mean changed in IMAP */
227         i = option (OPTATTACHMSG) ? 3
228             : ((Context->readonly || Context->dontwrite) ? 2
229                : (Context->changed || (Context-> magic != M_IMAP && Context->
230                                         deleted)) ? 1 : 0);
231       }
232
233       if (!StChars)
234         buf[0] = 0;
235       else if (i >= m_strlen(StChars))
236         buf[0] = StChars[0];
237       else
238         buf[0] = StChars[i];
239
240       buf[1] = 0;
241       break;
242     }
243
244   case 's':
245     snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
246     snprintf (buf, buflen, fmt, get_sort_str (tmp, sizeof (tmp), Sort));
247     break;
248
249   case 'S':
250     snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
251     snprintf (buf, buflen, fmt, get_sort_str (tmp, sizeof (tmp), SortAux));
252     break;
253
254   case 't':
255     if (!optional) {
256       snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
257       snprintf (buf, buflen, fmt, Context ? Context->tagged : 0);
258     }
259     else if (!Context || !Context->tagged)
260       optional = 0;
261     break;
262
263   case 'u':
264     if (!optional) {
265       snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
266       snprintf (buf, buflen, fmt, Context ? Context->unread : 0);
267     }
268     else if (!Context || !Context->unread)
269       optional = 0;
270     break;
271
272   case 'v':
273     m_strcpy(buf, buflen, mutt_make_version(0));
274     break;
275
276   case 'V':
277     if (!optional) {
278       snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
279       snprintf (buf, buflen, fmt,
280                 (Context && Context->pattern) ? Context->pattern : "");
281     }
282     else if (!Context || !Context->pattern)
283       optional = 0;
284     break;
285
286   case 0:
287     *buf = 0;
288     return (src);
289
290   default:
291     snprintf (buf, buflen, "%%%s%c", prefix, op);
292     break;
293   }
294
295   if (optional)
296     menu_status_line (buf, buflen, menu, ifstring);
297   else if (flags & M_FORMAT_OPTIONAL)
298     menu_status_line (buf, buflen, menu, elsestring);
299
300   return (src);
301 }
302
303 void menu_status_line (char* buf, ssize_t len, MUTTMENU* menu, const char* p) {
304   /*
305    * if we have enough space for buffer, format lines to $COLS-$SidebarWidth
306    * only to not wrap past end of screen
307    */
308   int width = COLS - SW;
309   mutt_FormatString (buf, (width >= len ? len : (width + 1)),
310                      p, status_format_str,
311                      (unsigned long) menu, 0);
312 }