NeoMutt
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
status.c
Go to the documentation of this file.
1
29#include "config.h"
30#include <stdbool.h>
31#include <stdint.h>
32#include <stdio.h>
33#include "mutt/lib.h"
34#include "config/lib.h"
35#include "core/lib.h"
36#include "status.h"
37#include "index/lib.h"
38#include "menu/lib.h"
39#include "postpone/lib.h"
40#include "format_flags.h"
41#include "globals.h"
42#include "mutt_mailbox.h"
43#include "mutt_thread.h"
44#include "muttlib.h"
45#include "mview.h"
46
54static char *get_sort_str(char *buf, size_t buflen, enum SortType method)
55{
56 snprintf(buf, buflen, "%s%s%s", (method & SORT_REVERSE) ? "reverse-" : "",
57 (method & SORT_LAST) ? "last-" : "",
59 return buf;
60}
61
66{
68 struct Menu *menu;
69};
70
100static const char *status_format_str(char *buf, size_t buflen, size_t col, int cols,
101 char op, const char *src, const char *prec,
102 const char *if_str, const char *else_str,
103 intptr_t data, MuttFormatFlags flags)
104{
105 char fmt[128], tmp[128];
106 bool optional = (flags & MUTT_FORMAT_OPTIONAL);
107 struct MenuStatusLineData *msld = (struct MenuStatusLineData *) data;
108 struct IndexSharedData *shared = msld->shared;
109 struct MailboxView *mv = shared->mailbox_view;
110 struct Mailbox *m = shared->mailbox;
111 struct Menu *menu = msld->menu;
112
113 *buf = '\0';
114 switch (op)
115 {
116 case 'b':
117 {
119 if (!optional)
120 {
121 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
122 snprintf(buf, buflen, fmt, num);
123 }
124 else if (num == 0)
125 {
126 optional = false;
127 }
128 break;
129 }
130
131 case 'd':
132 {
133 const int num = m ? m->msg_deleted : 0;
134 if (!optional)
135 {
136 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
137 snprintf(buf, buflen, fmt, num);
138 }
139 else if (num == 0)
140 {
141 optional = false;
142 }
143 break;
144 }
145
146 case 'D':
147 // If there's a descriptive name, use it. Otherwise, fall-through
148 if (m && m->name)
149 {
150 mutt_str_copy(tmp, m->name, sizeof(tmp));
151 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
152 snprintf(buf, buflen, fmt, tmp);
153 break;
154 }
155 /* fallthrough */
156 case 'f':
157#ifdef USE_COMP_MBOX
158 if (m && m->compress_info && (m->realpath[0] != '\0'))
159 {
160 mutt_str_copy(tmp, m->realpath, sizeof(tmp));
161 mutt_pretty_mailbox(tmp, sizeof(tmp));
162 }
163 else
164#endif
165 if (m && (m->type == MUTT_NOTMUCH) && m->name)
166 {
167 mutt_str_copy(tmp, m->name, sizeof(tmp));
168 }
169 else if (m && !buf_is_empty(&m->pathbuf))
170 {
171 mutt_str_copy(tmp, mailbox_path(m), sizeof(tmp));
172 mutt_pretty_mailbox(tmp, sizeof(tmp));
173 }
174 else
175 {
176 mutt_str_copy(tmp, _("(no mailbox)"), sizeof(tmp));
177 }
178
179 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
180 snprintf(buf, buflen, fmt, tmp);
181 break;
182 case 'F':
183 {
184 const int num = m ? m->msg_flagged : 0;
185 if (!optional)
186 {
187 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
188 snprintf(buf, buflen, fmt, num);
189 }
190 else if (num == 0)
191 {
192 optional = false;
193 }
194 break;
195 }
196
197 case 'h':
198 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
199 snprintf(buf, buflen, fmt, NONULL(ShortHostname));
200 break;
201
202 case 'l':
203 {
204 const off_t num = m ? m->size : 0;
205 if (!optional)
206 {
207 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
208 mutt_str_pretty_size(tmp, sizeof(tmp), num);
209 snprintf(buf, buflen, fmt, tmp);
210 }
211 else if (num == 0)
212 {
213 optional = false;
214 }
215 break;
216 }
217
218 case 'L':
219 if (!optional)
220 {
221 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
222 mutt_str_pretty_size(tmp, sizeof(tmp), mv ? mv->vsize : 0);
223 snprintf(buf, buflen, fmt, tmp);
224 }
225 else if (!mview_has_limit(mv))
226 {
227 optional = false;
228 }
229 break;
230
231 case 'm':
232 {
233 const int num = m ? m->msg_count : 0;
234 if (!optional)
235 {
236 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
237 snprintf(buf, buflen, fmt, num);
238 }
239 else if (num == 0)
240 {
241 optional = false;
242 }
243 break;
244 }
245
246 case 'M':
247 if (!optional)
248 {
249 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
250 snprintf(buf, buflen, fmt, m ? m->vcount : 0);
251 }
252 else if (!mview_has_limit(mv))
253 {
254 optional = false;
255 }
256 break;
257
258 case 'n':
259 {
260 const int num = m ? m->msg_new : 0;
261 if (!optional)
262 {
263 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
264 snprintf(buf, buflen, fmt, num);
265 }
266 else if (num == 0)
267 {
268 optional = false;
269 }
270 break;
271 }
272
273 case 'o':
274 {
275 const int num = m ? (m->msg_unread - m->msg_new) : 0;
276 if (!optional)
277 {
278 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
279 snprintf(buf, buflen, fmt, num);
280 }
281 else if (num == 0)
282 {
283 optional = false;
284 }
285 break;
286 }
287
288 case 'p':
289 {
290 const int count = mutt_num_postponed(m, false);
291 if (!optional)
292 {
293 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
294 snprintf(buf, buflen, fmt, count);
295 }
296 else if (count == 0)
297 {
298 optional = false;
299 }
300 break;
301 }
302
303 case 'P':
304 {
305 if (!menu)
306 break;
307 char *cp = NULL;
308 if (menu->top + menu->page_len >= menu->max)
309 {
310 cp = menu->top ?
311 /* L10N: Status bar message: the end of the list emails is visible in the index */
312 _("end") :
313 /* L10N: Status bar message: all the emails are visible in the index */
314 _("all");
315 }
316 else
317 {
318 int count = (100 * (menu->top + menu->page_len)) / menu->max;
319 /* L10N: Status bar, percentage of way through index.
320 `%d` is the number, `%%` is the percent symbol.
321 They may be reordered, or space inserted, if you wish. */
322 snprintf(tmp, sizeof(tmp), _("%d%%"), count);
323 cp = tmp;
324 }
325 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
326 snprintf(buf, buflen, fmt, cp);
327 break;
328 }
329
330 case 'r':
331 {
332 size_t i = 0;
333
334 if (m)
335 {
336 i = shared->attach_msg ? 3 :
337 ((m->readonly || m->dontwrite) ? 2 :
338 (m->changed ||
339 /* deleted doesn't necessarily mean changed in IMAP */
340 (m->type != MUTT_IMAP && m->msg_deleted)) ?
341 1 :
342 0);
343 }
344
345 const struct MbTable *c_status_chars = cs_subset_mbtable(NeoMutt->sub, "status_chars");
346 if (!c_status_chars || !c_status_chars->len)
347 buf[0] = '\0';
348 else if (i >= c_status_chars->len)
349 snprintf(buf, buflen, "%s", c_status_chars->chars[0]);
350 else
351 snprintf(buf, buflen, "%s", c_status_chars->chars[i]);
352 break;
353 }
354
355 case 'R':
356 {
357 const int read = m ? (m->msg_count - m->msg_unread) : 0;
358 if (!optional)
359 {
360 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
361 snprintf(buf, buflen, fmt, read);
362 }
363 else if (read == 0)
364 {
365 optional = false;
366 }
367 break;
368 }
369
370 case 's':
371 {
372 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
373 const enum SortType c_sort = cs_subset_sort(NeoMutt->sub, "sort");
374 snprintf(buf, buflen, fmt, get_sort_str(tmp, sizeof(tmp), c_sort));
375 break;
376 }
377
378 case 'S':
379 {
380 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
381 const enum SortType c_sort_aux = cs_subset_sort(NeoMutt->sub, "sort_aux");
382 snprintf(buf, buflen, fmt, get_sort_str(tmp, sizeof(tmp), c_sort_aux));
383 break;
384 }
385
386 case 't':
387 {
388 const int num = m ? m->msg_tagged : 0;
389 if (!optional)
390 {
391 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
392 snprintf(buf, buflen, fmt, num);
393 }
394 else if (num == 0)
395 {
396 optional = false;
397 }
398 break;
399 }
400
401 case 'T':
402 {
403 const enum UseThreads c_use_threads = mutt_thread_style();
404 if (!optional)
405 {
406 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
407 snprintf(buf, buflen, fmt, get_use_threads_str(c_use_threads));
408 }
409 else if (c_use_threads == UT_FLAT)
410 {
411 optional = false;
412 }
413 break;
414 }
415
416 case 'u':
417 if (!optional)
418 {
419 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
420 snprintf(buf, buflen, fmt, m ? m->msg_unread : 0);
421 }
422 else if (!m || (m->msg_unread == 0))
423 {
424 optional = false;
425 }
426 break;
427
428 case 'v':
429 snprintf(buf, buflen, "%s", mutt_make_version());
430 break;
431
432 case 'V':
433 if (!optional)
434 {
435 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
436 snprintf(buf, buflen, fmt, mview_has_limit(mv) ? mv->pattern : "");
437 }
438 else if (!mview_has_limit(mv))
439 {
440 optional = false;
441 }
442 break;
443
444 case 0:
445 *buf = '\0';
446 return src;
447
448 default:
449 snprintf(buf, buflen, "%%%s%c", prec, op);
450 break;
451 }
452
453 if (optional)
454 {
455 mutt_expando_format(buf, buflen, col, cols, if_str, status_format_str, data,
457 }
458 else if (flags & MUTT_FORMAT_OPTIONAL)
459 {
460 mutt_expando_format(buf, buflen, col, cols, else_str, status_format_str,
462 }
463
464 /* We return the format string, unchanged */
465 return src;
466}
467
479void menu_status_line(char *buf, size_t buflen, struct IndexSharedData *shared,
480 struct Menu *menu, int cols, const char *fmt)
481{
482 struct MenuStatusLineData data = { shared, menu };
483
484 mutt_expando_format(buf, buflen, 0, cols, fmt, status_format_str,
485 (intptr_t) &data, MUTT_FORMAT_NO_FLAGS);
486}
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:303
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using '~' or '='.
Definition: muttlib.c:483
struct MbTable * cs_subset_mbtable(const struct ConfigSubset *sub, const char *name)
Get a Multibyte table config item by name.
Definition: helpers.c:120
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition: helpers.c:267
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
Flags to control mutt_expando_format()
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
#define MUTT_FORMAT_OPTIONAL
Allow optional field processing.
Definition: format_flags.h:33
uint8_t MuttFormatFlags
Flags for mutt_expando_format(), e.g. MUTT_FORMAT_FORCESUBJ.
Definition: format_flags.h:29
char * ShortHostname
Short version of the hostname.
Definition: globals.c:40
Global variables.
static const char * status_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
Create the status bar string - Implements format_t -.
Definition: status.c:100
void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t callback, intptr_t data, MuttFormatFlags flags)
Expand expandos (x) in a string -.
Definition: muttlib.c:745
GUI manage the main index (list of emails)
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition: mailbox.h:210
@ MUTT_NOTMUCH
'Notmuch' (virtual) Mailbox type
Definition: mailbox.h:51
@ MUTT_IMAP
'IMAP' Mailbox type
Definition: mailbox.h:50
const char * mutt_map_get_name(int val, const struct Mapping *map)
Lookup a string for a constant.
Definition: mapping.c:42
GUI present the user with a selectable list.
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:653
int mutt_mailbox_check(struct Mailbox *m_cur, CheckStatsFlags flags)
Check all all Mailboxes for new mail.
Definition: mutt_mailbox.c:165
Mailbox helper functions.
const char * get_use_threads_str(enum UseThreads value)
Convert UseThreads enum to string.
Definition: mutt_thread.c:97
enum UseThreads mutt_thread_style(void)
Which threading style is active?
Definition: mutt_thread.c:79
Create/manipulate threading in emails.
UseThreads
Which threading style is active, $use_threads.
Definition: mutt_thread.h:95
@ UT_FLAT
Unthreaded.
Definition: mutt_thread.h:97
const char * mutt_make_version(void)
Generate the NeoMutt version string.
Definition: muttlib.c:1443
void mutt_str_pretty_size(char *buf, size_t buflen, size_t num)
Display an abbreviated size, like 3.4K.
Definition: muttlib.c:1651
Some miscellaneous functions.
bool mview_has_limit(const struct MailboxView *mv)
Is a limit active?
Definition: mview.c:440
View of a Mailbox.
#define MUTT_MAILBOX_CHECK_NO_FLAGS
No flags are set.
Definition: mxapi.h:53
Postponed Emails.
int mutt_num_postponed(struct Mailbox *m, bool force)
Return the number of postponed messages.
Definition: postpone.c:70
const struct Mapping SortMethods[]
Sort methods for '$sort' for the index.
Definition: mutt_config.c:75
#define SORT_MASK
Mask for the sort id.
Definition: sort2.h:74
#define SORT_LAST
Sort thread by last-X, e.g. received date.
Definition: sort2.h:76
SortType
Methods for sorting.
Definition: sort2.h:38
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:75
void menu_status_line(char *buf, size_t buflen, struct IndexSharedData *shared, struct Menu *menu, int cols, const char *fmt)
Create the status line.
Definition: status.c:479
static char * get_sort_str(char *buf, size_t buflen, enum SortType method)
Get the sort method as a string.
Definition: status.c:54
GUI display a user-configurable status line.
#define NONULL(x)
Definition: string2.h:37
Data shared between Index, Pager and Sidebar.
Definition: shared_data.h:37
struct Mailbox * mailbox
Current Mailbox.
Definition: shared_data.h:41
bool attach_msg
Are we in "attach message" mode?
Definition: shared_data.h:46
struct MailboxView * mailbox_view
Current Mailbox view.
Definition: shared_data.h:40
View of a Mailbox.
Definition: mview.h:39
off_t vsize
Size (in bytes) of the messages shown.
Definition: mview.h:40
char * pattern
Limit pattern string.
Definition: mview.h:41
A mailbox.
Definition: mailbox.h:79
int vcount
The number of virtual messages.
Definition: mailbox.h:99
bool changed
Mailbox has been modified.
Definition: mailbox.h:109
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:81
int msg_new
Number of new messages.
Definition: mailbox.h:92
int msg_count
Total number of messages.
Definition: mailbox.h:88
enum MailboxType type
Mailbox type.
Definition: mailbox.h:102
char * name
A short name for the Mailbox.
Definition: mailbox.h:82
struct Buffer pathbuf
Path of the Mailbox.
Definition: mailbox.h:80
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:93
bool dontwrite
Don't write the mailbox on close.
Definition: mailbox.h:110
off_t size
Size of the Mailbox.
Definition: mailbox.h:84
int msg_flagged
Number of flagged messages.
Definition: mailbox.h:90
void * compress_info
Compressed mbox module private data.
Definition: mailbox.h:121
bool readonly
Don't allow changes to the mailbox.
Definition: mailbox.h:115
int msg_tagged
How many messages are tagged?
Definition: mailbox.h:94
int msg_unread
Number of unread messages.
Definition: mailbox.h:89
Multibyte character table.
Definition: mbtable.h:34
int len
Number of characters.
Definition: mbtable.h:36
char ** chars
The array of multibyte character strings.
Definition: mbtable.h:37
Data for creating a Menu line.
Definition: status.c:66
struct IndexSharedData * shared
Data shared between Index, Pager and Sidebar.
Definition: status.c:67
struct Menu * menu
Current Menu.
Definition: status.c:68
Definition: lib.h:70
int top
Entry that is the top of the current page.
Definition: lib.h:81
int max
Number of entries in the menu.
Definition: lib.h:72
int page_len
Number of entries per screen.
Definition: lib.h:75
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45