mem_calloc -> p_new
[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
16 #include "mutt.h"
17 #include "mutt_menu.h"
18 #include "mutt_curses.h"
19 #include "sort.h"
20 #include "mapping.h"
21 #include "mx.h"
22 #include "buffy.h"
23
24 #include "lib/mem.h"
25 #include "lib/intl.h"
26 #include "lib/str.h"
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, size_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 = Mutt-ng version 
60  * %V = currently active limit pattern [option] */
61 static const char *status_format_str (char *buf, size_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 #ifdef USE_COMPRESSED
86     if (Context && Context->compressinfo && Context->realpath) {
87       if ((p = strrchr (Context->realpath, '/')))
88         strfcpy (tmp, p + 1, sizeof (tmp));
89       else
90         strfcpy (tmp, Context->realpath, sizeof (tmp));
91     }
92     else
93 #endif
94     if (Context && Context->path) {
95       if ((p = strrchr (Context->path, '/')))
96         strfcpy (tmp, p + 1, sizeof (tmp));
97       else
98         strfcpy (tmp, Context->path, sizeof (tmp));
99     }
100     else
101       strfcpy (tmp, _("no mailbox"), sizeof (tmp));
102     snprintf (buf, buflen, fmt, tmp);
103     break;
104
105   case 'd':
106     if (!optional) {
107       snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
108       snprintf (buf, buflen, fmt, Context ? Context->deleted : 0);
109     }
110     else if (!Context || !Context->deleted)
111       optional = 0;
112     break;
113
114   case 'h':
115     snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
116     snprintf (buf, buflen, fmt, NONULL (Hostname));
117     break;
118
119   case 'f':
120     snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
121 #ifdef USE_COMPRESSED
122     if (Context && Context->compressinfo && Context->realpath) {
123       strfcpy (tmp, Context->realpath, sizeof (tmp));
124       mutt_pretty_mailbox (tmp);
125     }
126     else
127 #endif
128     if (Context && Context->path) {
129       strfcpy (tmp, Context->path, sizeof (tmp));
130       mutt_pretty_mailbox (tmp);
131     }
132     else
133       strfcpy (tmp, _("(no mailbox)"), sizeof (tmp));
134     snprintf (buf, buflen, fmt, tmp);
135     break;
136
137   case 'F':
138     if (!optional) {
139       snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
140       snprintf (buf, buflen, fmt, Context ? Context->flagged : 0);
141     }
142     else if (!Context || !Context->flagged)
143       optional = 0;
144     break;
145
146   case 'l':
147     if (!optional) {
148       snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
149       mutt_pretty_size (tmp, sizeof (tmp), Context ? Context->size : 0);
150       snprintf (buf, buflen, fmt, tmp);
151     }
152     else if (!Context || !Context->size)
153       optional = 0;
154     break;
155
156   case 'L':
157     if (!optional) {
158       snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
159       mutt_pretty_size (tmp, sizeof (tmp), Context ? Context->vsize : 0);
160       snprintf (buf, buflen, fmt, tmp);
161     }
162     else if (!Context || !Context->pattern)
163       optional = 0;
164     break;
165
166   case 'm':
167     if (!optional) {
168       snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
169       snprintf (buf, buflen, fmt, Context ? Context->msgcount : 0);
170     }
171     else if (!Context || !Context->msgcount)
172       optional = 0;
173     break;
174
175   case 'M':
176     if (!optional) {
177       snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
178       snprintf (buf, buflen, fmt, Context ? Context->vcount : 0);
179     }
180     else if (!Context || !Context->pattern)
181       optional = 0;
182     break;
183
184   case 'n':
185     if (!optional) {
186       snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
187       snprintf (buf, buflen, fmt, Context ? Context->new : 0);
188     }
189     else if (!Context || Context->new <= 0)
190       optional = 0;
191     break;
192
193   case 'o':
194     if (!optional) {
195       snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
196       snprintf (buf, buflen, fmt,
197                 Context ? Context->unread - Context->new : 0);
198     }
199     else if (!Context || !(Context->unread - Context->new))
200       optional = 0;
201     break;
202
203   case 'p':
204     count = mutt_num_postponed (0);
205     if (!optional) {
206       snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
207       snprintf (buf, buflen, fmt, count);
208     }
209     else if (!count)
210       optional = 0;
211     break;
212
213   case 'P':
214     if (menu->top + menu->pagelen >= menu->max)
215       cp = menu->top ? "end" : "all";
216     else {
217       count = (100 * (menu->top + menu->pagelen)) / menu->max;
218       snprintf (tmp, sizeof (tmp), "%d%%", count);
219       cp = tmp;
220     }
221     snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
222     snprintf (buf, buflen, fmt, cp);
223     break;
224
225   case 'r':
226     {
227       int i = 0;
228
229       if (Context) {
230         i = option (OPTATTACHMSG) ? 3 : ((Context->readonly ||
231                                           Context->dontwrite) ? 2 : (Context->
232                                                                      changed
233                                                                      || (
234 #ifdef USE_IMAP
235                                                                              /* deleted doesn't necessarily mean changed in IMAP */
236                                                                              Context->
237                                                                              magic
238                                                                              !=
239                                                                              M_IMAP
240                                                                              &&
241 #endif
242                                                                              Context->
243                                                                              deleted))
244                                          ? 1 : 0);
245       }
246
247       if (!StChars)
248         buf[0] = 0;
249       else if (i >= str_len (StChars))
250         buf[0] = StChars[0];
251       else
252         buf[0] = StChars[i];
253
254       buf[1] = 0;
255       break;
256     }
257
258   case 's':
259     snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
260     snprintf (buf, buflen, fmt, get_sort_str (tmp, sizeof (tmp), Sort));
261     break;
262
263   case 'S':
264     snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
265     snprintf (buf, buflen, fmt, get_sort_str (tmp, sizeof (tmp), SortAux));
266     break;
267
268   case 't':
269     if (!optional) {
270       snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
271       snprintf (buf, buflen, fmt, Context ? Context->tagged : 0);
272     }
273     else if (!Context || !Context->tagged)
274       optional = 0;
275     break;
276
277   case 'u':
278     if (!optional) {
279       snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
280       snprintf (buf, buflen, fmt, Context ? Context->unread : 0);
281     }
282     else if (!Context || !Context->unread)
283       optional = 0;
284     break;
285
286   case 'v':
287     strncpy (buf, mutt_make_version (0), buflen);
288     break;
289
290   case 'V':
291     if (!optional) {
292       snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
293       snprintf (buf, buflen, fmt,
294                 (Context && Context->pattern) ? Context->pattern : "");
295     }
296     else if (!Context || !Context->pattern)
297       optional = 0;
298     break;
299
300   case 0:
301     *buf = 0;
302     return (src);
303
304   default:
305     snprintf (buf, buflen, "%%%s%c", prefix, op);
306     break;
307   }
308
309   if (optional)
310     menu_status_line (buf, buflen, menu, ifstring);
311   else if (flags & M_FORMAT_OPTIONAL)
312     menu_status_line (buf, buflen, menu, elsestring);
313
314   return (src);
315 }
316
317 void menu_status_line (char* buf, size_t len, MUTTMENU* menu, const char* p) {
318   /*
319    * if we have enough space for buffer, format lines to $COLS-$SidebarWidth
320    * only to not wrap past end of screen
321    */
322   int width = COLS - SW;
323   mutt_FormatString (buf, (width >= len ? len : (width + 1)),
324                      p, status_format_str,
325                      (unsigned long) menu, 0);
326 }