NeoMutt  2021-10-29-220-g2b1eec
Teaching an old dog new tricks
DOXYGEN
Expando API

Prototype for a mutt_expando_format() Callback Function. More...

Functions

static const char * alias_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)
 Format a string for the alias list - Implements format_t -. More...
 
static const char * query_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)
 Format a string for the query menu - Implements format_t -. More...
 
const char * attach_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)
 Format a string for the attachment menu - Implements format_t -. More...
 
static const char * autocrypt_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)
 Format a string for the Autocrypt account list - Implements format_t -. More...
 
static const char * folder_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)
 Format a string for the folder browser - Implements format_t -. More...
 
static const char * compress_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)
 Expand the filenames in a command string - Implements format_t -. More...
 
static const char * compose_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 for compose mode - Implements format_t -. More...
 
static const char * index_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)
 Format a string for the index list - Implements format_t -. More...
 
static const char * history_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)
 Format a string for the history list - Implements format_t -. More...
 
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 -. More...
 
static const char * crypt_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)
 Format a string for the key selection menu - Implements format_t -. More...
 
static const char * pgp_entry_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)
 Format an entry on the PGP key selection menu - Implements format_t -. More...
 
static const char * pgp_command_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)
 Format a PGP command string - Implements format_t -. More...
 
static const char * smime_command_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)
 Format an SMIME command - Implements format_t -. More...
 
const char * group_index_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)
 Format a string for the newsgroup menu - Implements format_t -. More...
 
const char * nntp_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)
 Expand the newsrc filename - Implements format_t -. More...
 
static const char * pattern_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)
 Format a string for the pattern completion menu - Implements format_t -. More...
 
static const char * mix_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)
 Format a string for the remailer menu - Implements format_t -. More...
 
static const char * greeting_string (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)
 Format a greetings string - Implements format_t -. More...
 
static const char * sidebar_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)
 Format a string for the sidebar - Implements format_t -. More...
 
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 -. More...
 

Detailed Description

Prototype for a mutt_expando_format() Callback Function.

Parameters
[out]bufBuffer in which to save string
[in]buflenBuffer length
[in]colStarting column
[in]colsNumber of screen columns
[in]opprintf-like operator, e.g. 't'
[in]srcprintf-like format string
[in]precField precision, e.g. "-3.4"
[in]if_strIf condition is met, display this string
[in]else_strOtherwise, display this string
[in]dataPrivate data
[in]flagsFlags, see MuttFormatFlags
Return values
ptrsrc (unchanged)

Each callback function implements some expandos, e.g.

Expando Description
%t Title

Function Documentation

◆ alias_format_str()

static const char* alias_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 
)
static

Format a string for the alias list - Implements format_t -.

Expando Description
%a Alias name
%c Comments
%f Flags - currently, a 'd' for an alias marked for deletion
%n Index number
%r Address which alias expands to
%t Character which indicates if the alias is tagged for inclusion

Definition at line 120 of file dlgalias.c.

124 {
125  char fmt[128], addr[1024];
126  struct AliasView *av = (struct AliasView *) data;
127  struct Alias *alias = av->alias;
128 
129  switch (op)
130  {
131  case 'a':
132  mutt_format_s(buf, buflen, prec, alias->name);
133  break;
134  case 'c':
135  mutt_format_s(buf, buflen, prec, alias->comment);
136  break;
137  case 'f':
138  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
139  snprintf(buf, buflen, fmt, av->is_deleted ? "D" : " ");
140  break;
141  case 'n':
142  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
143  snprintf(buf, buflen, fmt, av->num + 1);
144  break;
145  case 'r':
146  addr[0] = '\0';
147  mutt_addrlist_write(&alias->addr, addr, sizeof(addr), true);
148  mutt_format_s(buf, buflen, prec, addr);
149  break;
150  case 't':
151  buf[0] = av->is_tagged ? '*' : ' ';
152  buf[1] = '\0';
153  break;
154  }
155 
156  return src;
157 }
size_t mutt_addrlist_write(const struct AddressList *al, char *buf, size_t buflen, bool display)
Write an Address to a buffer.
Definition: address.c:1150
void mutt_format_s(char *buf, size_t buflen, const char *prec, const char *s)
Format a simple string.
Definition: curs_lib.c:842
GUI data wrapping an Alias.
Definition: gui.h:36
struct Alias * alias
Alias.
Definition: gui.h:44
bool is_deleted
Is it deleted?
Definition: gui.h:42
bool is_tagged
Is it tagged?
Definition: gui.h:41
int num
Index number in list.
Definition: gui.h:37
A shortcut for an email address or addresses.
Definition: alias.h:34
char * comment
Free-form comment string.
Definition: alias.h:37
char * name
Short name.
Definition: alias.h:35
struct AddressList addr
List of Addresses the Alias expands to.
Definition: alias.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ query_format_str()

static const char* query_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 
)
static

Format a string for the query menu - Implements format_t -.

Expando Description
%a Destination address
%c Current entry number
%e Extra information
%n Destination name
%t * if current entry is tagged, a space otherwise

Definition at line 181 of file dlgquery.c.

185 {
186  struct AliasView *av = (struct AliasView *) data;
187  struct Alias *alias = av->alias;
188  char fmt[128];
189  char tmp[256] = { 0 };
190  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
191 
192  switch (op)
193  {
194  case 'a':
195  tmp[0] = '<';
196  mutt_addrlist_write(&alias->addr, tmp + 1, sizeof(tmp) - 1, true);
197  const size_t len = strlen(tmp);
198  if (len < (sizeof(tmp) - 1))
199  {
200  tmp[len] = '>';
201  tmp[len + 1] = '\0';
202  }
203  mutt_format_s(buf, buflen, prec, tmp);
204  break;
205  case 'c':
206  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
207  snprintf(buf, buflen, fmt, av->num + 1);
208  break;
209  case 'e':
210  if (!optional)
211  mutt_format_s(buf, buflen, prec, NONULL(alias->comment));
212  else if (!alias->comment || (*alias->comment == '\0'))
213  optional = false;
214  break;
215  case 'n':
216  mutt_format_s(buf, buflen, prec, NONULL(alias->name));
217  break;
218  case 't':
219  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
220  snprintf(buf, buflen, fmt, av->is_tagged ? '*' : ' ');
221  break;
222  default:
223  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
224  snprintf(buf, buflen, fmt, op);
225  break;
226  }
227 
228  if (optional)
229  {
230  mutt_expando_format(buf, buflen, col, cols, if_str, query_format_str, data,
232  }
233  else if (flags & MUTT_FORMAT_OPTIONAL)
234  {
235  mutt_expando_format(buf, buflen, col, cols, else_str, query_format_str,
236  data, MUTT_FORMAT_NO_FLAGS);
237  }
238 
239  /* We return the format string, unchanged */
240  return src;
241 }
#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
static const char * query_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)
Format a string for the query menu - Implements format_t -.
Definition: dlgquery.c:181
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:780
#define NONULL(x)
Definition: string2.h:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ attach_format_str()

const char* attach_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 
)

Format a string for the attachment menu - Implements format_t -.

Expando Description
%C Character set
%c Character set: convert?
%D Deleted flag
%d Description
%e MIME content-transfer-encoding
%f Filename
%F Filename for content-disposition header
%I Content-disposition, either I (inline) or A (attachment)
%m Major MIME type
%M MIME subtype
%n Attachment number
%Q 'Q', if MIME part qualifies for attachment counting
%s Size
%t Tagged flag
%T Tree chars
%u Unlink
%X Number of qualifying MIME parts in this part and its children

Definition at line 187 of file dlg_attach.c.

190 {
191  char fmt[128];
192  char charset[128];
193  struct AttachPtr *aptr = (struct AttachPtr *) data;
194  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
195 
196  switch (op)
197  {
198  case 'C':
199  if (!optional)
200  {
201  if (mutt_is_text_part(aptr->body) &&
202  mutt_body_get_charset(aptr->body, charset, sizeof(charset)))
203  {
204  mutt_format_s(buf, buflen, prec, charset);
205  }
206  else
207  mutt_format_s(buf, buflen, prec, "");
208  }
209  else if (!mutt_is_text_part(aptr->body) ||
210  !mutt_body_get_charset(aptr->body, charset, sizeof(charset)))
211  {
212  optional = false;
213  }
214  break;
215  case 'c':
216  /* XXX */
217  if (!optional)
218  {
219  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
220  snprintf(buf, buflen, fmt,
221  ((aptr->body->type != TYPE_TEXT) || aptr->body->noconv) ? 'n' : 'c');
222  }
223  else if ((aptr->body->type != TYPE_TEXT) || aptr->body->noconv)
224  optional = false;
225  break;
226  case 'd':
227  {
228  const char *const c_message_format =
229  cs_subset_string(NeoMutt->sub, "message_format");
230  if (!optional)
231  {
232  if (aptr->body->description)
233  {
234  mutt_format_s(buf, buflen, prec, aptr->body->description);
235  break;
236  }
237  if (mutt_is_message_type(aptr->body->type, aptr->body->subtype) &&
238  c_message_format && aptr->body->email)
239  {
240  char s[128];
241  mutt_make_string(s, sizeof(s), cols, c_message_format, NULL, -1,
242  aptr->body->email,
244  if (*s)
245  {
246  mutt_format_s(buf, buflen, prec, s);
247  break;
248  }
249  }
250  if (!aptr->body->d_filename && !aptr->body->filename)
251  {
252  mutt_format_s(buf, buflen, prec, "<no description>");
253  break;
254  }
255  }
256  else if (aptr->body->description ||
257  (mutt_is_message_type(aptr->body->type, aptr->body->subtype) &&
258  c_message_format && aptr->body->email))
259  {
260  break;
261  }
262  }
263  /* fallthrough */
264  case 'F':
265  if (!optional)
266  {
267  if (aptr->body->d_filename)
268  {
269  mutt_format_s(buf, buflen, prec, aptr->body->d_filename);
270  break;
271  }
272  }
273  else if (!aptr->body->d_filename && !aptr->body->filename)
274  {
275  optional = false;
276  break;
277  }
278  /* fallthrough */
279  case 'f':
280  if (!optional)
281  {
282  if (aptr->body->filename && (*aptr->body->filename == '/'))
283  {
284  struct Buffer *path = mutt_buffer_pool_get();
285 
286  mutt_buffer_strcpy(path, aptr->body->filename);
288  mutt_format_s(buf, buflen, prec, mutt_buffer_string(path));
290  }
291  else
292  mutt_format_s(buf, buflen, prec, NONULL(aptr->body->filename));
293  }
294  else if (!aptr->body->filename)
295  optional = false;
296  break;
297  case 'D':
298  if (!optional)
299  snprintf(buf, buflen, "%c", aptr->body->deleted ? 'D' : ' ');
300  else if (!aptr->body->deleted)
301  optional = false;
302  break;
303  case 'e':
304  if (!optional)
305  mutt_format_s(buf, buflen, prec, ENCODING(aptr->body->encoding));
306  break;
307  case 'I':
308  if (optional)
309  break;
310 
311  const char dispchar[] = { 'I', 'A', 'F', '-' };
312  char ch;
313 
314  if (aptr->body->disposition < sizeof(dispchar))
315  ch = dispchar[aptr->body->disposition];
316  else
317  {
318  mutt_debug(LL_DEBUG1, "ERROR: invalid content-disposition %d\n",
319  aptr->body->disposition);
320  ch = '!';
321  }
322  snprintf(buf, buflen, "%c", ch);
323  break;
324  case 'm':
325  if (!optional)
326  mutt_format_s(buf, buflen, prec, TYPE(aptr->body));
327  break;
328  case 'M':
329  if (!optional)
330  mutt_format_s(buf, buflen, prec, aptr->body->subtype);
331  else if (!aptr->body->subtype)
332  optional = false;
333  break;
334  case 'n':
335  if (optional)
336  break;
337 
338  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
339  snprintf(buf, buflen, fmt, aptr->num + 1);
340  break;
341  case 'Q':
342  if (optional)
343  optional = aptr->body->attach_qualifies;
344  else
345  {
346  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
347  mutt_format_s(buf, buflen, fmt, "Q");
348  }
349  break;
350  case 's':
351  {
352  size_t l = 0;
353  if (aptr->body->filename && (flags & MUTT_FORMAT_STAT_FILE))
354  {
355  l = mutt_file_get_size(aptr->body->filename);
356  }
357  else
358  l = aptr->body->length;
359 
360  if (!optional)
361  {
362  char tmp[128];
363  mutt_str_pretty_size(tmp, sizeof(tmp), l);
364  mutt_format_s(buf, buflen, prec, tmp);
365  }
366  else if (l == 0)
367  optional = false;
368 
369  break;
370  }
371  case 't':
372  if (!optional)
373  snprintf(buf, buflen, "%c", aptr->body->tagged ? '*' : ' ');
374  else if (!aptr->body->tagged)
375  optional = false;
376  break;
377  case 'T':
378  if (!optional)
379  mutt_format_s_tree(buf, buflen, prec, NONULL(aptr->tree));
380  else if (!aptr->tree)
381  optional = false;
382  break;
383  case 'u':
384  if (!optional)
385  snprintf(buf, buflen, "%c", aptr->body->unlink ? '-' : ' ');
386  else if (!aptr->body->unlink)
387  optional = false;
388  break;
389  case 'X':
390  if (optional)
391  optional = ((aptr->body->attach_count + aptr->body->attach_qualifies) != 0);
392  else
393  {
394  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
395  snprintf(buf, buflen, fmt, aptr->body->attach_count + aptr->body->attach_qualifies);
396  }
397  break;
398  default:
399  *buf = '\0';
400  }
401 
402  if (optional)
403  {
404  mutt_expando_format(buf, buflen, col, cols, if_str, attach_format_str, data,
406  }
407  else if (flags & MUTT_FORMAT_OPTIONAL)
408  {
409  mutt_expando_format(buf, buflen, col, cols, else_str, attach_format_str,
411  }
412 
413  /* We return the format string, unchanged */
414  return src;
415 }
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
void mutt_format_s_tree(char *buf, size_t buflen, const char *prec, const char *s)
Format a simple string with tree characters.
Definition: curs_lib.c:854
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body's character set.
Definition: body.c:131
long mutt_file_get_size(const char *path)
Get the size of a file.
Definition: file.c:1526
#define MUTT_FORMAT_FORCESUBJ
Print the subject even if unchanged.
Definition: format_flags.h:31
#define MUTT_FORMAT_ARROWCURSOR
Reserve space for arrow_cursor.
Definition: format_flags.h:35
#define MUTT_FORMAT_STAT_FILE
Used by attach_format_str.
Definition: format_flags.h:34
const char * attach_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)
Format a string for the attachment menu - Implements format_t -.
Definition: dlg_attach.c:187
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
void mutt_make_string(char *buf, size_t buflen, int cols, const char *s, struct Mailbox *m, int inpgr, struct Email *e, MuttFormatFlags flags, const char *progress)
Create formatted strings using mailbox expandos.
Definition: hdrline.c:1410
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
@ TYPE_TEXT
Type: 'text/*'.
Definition: mime.h:38
#define ENCODING(x)
Definition: mime.h:92
#define TYPE(body)
Definition: mime.h:89
void mutt_buffer_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
Definition: muttlib.c:603
void mutt_str_pretty_size(char *buf, size_t buflen, size_t num)
Display an abbreviated size, like 3.4K.
Definition: muttlib.c:1679
bool mutt_is_text_part(struct Body *b)
Is this part of an email in plain text?
Definition: muttlib.c:434
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition: parse.c:1435
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
An email to which things will be attached.
Definition: attach.h:35
struct Body * body
Attachment.
Definition: attach.h:36
char * tree
Tree characters to display.
Definition: attach.h:39
int num
Attachment index number.
Definition: attach.h:41
char * d_filename
filename to be used for the content-disposition header If NULL, filename is used instead.
Definition: body.h:55
signed short attach_count
Number of attachments.
Definition: body.h:90
bool deleted
Attachment marked for deletion.
Definition: body.h:87
bool noconv
Don't do character set conversion.
Definition: body.h:45
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:66
LOFF_T length
length (in bytes) of attachment
Definition: body.h:52
struct Email * email
header information for message/rfc822
Definition: body.h:72
char * description
content-description
Definition: body.h:54
unsigned int disposition
content-disposition, ContentDisposition
Definition: body.h:41
bool attach_qualifies
This attachment should be counted.
Definition: body.h:85
bool tagged
This attachment is tagged.
Definition: body.h:89
char * subtype
content-type subtype
Definition: body.h:59
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:40
unsigned int type
content-type primary type, ContentType
Definition: body.h:39
char * filename
When sending a message, this is the file to which this structure refers.
Definition: body.h:57
String manipulation buffer.
Definition: buffer.h:34
char * data
Pointer to data.
Definition: buffer.h:35
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ autocrypt_format_str()

static const char* autocrypt_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 
)
static

Format a string for the Autocrypt account list - Implements format_t -.

Expando Description
%a Email address
%k Gpg keyid
%n Current entry number
%p Prefer-encrypt flag
%s Status flag (active/inactive)

Definition at line 132 of file dlgautocrypt.c.

136 {
137  struct AccountEntry *entry = (struct AccountEntry *) data;
138  char tmp[128];
139 
140  switch (op)
141  {
142  case 'a':
143  mutt_format_s(buf, buflen, prec, entry->addr->mailbox);
144  break;
145  case 'k':
146  mutt_format_s(buf, buflen, prec, entry->account->keyid);
147  break;
148  case 'n':
149  snprintf(tmp, sizeof(tmp), "%%%sd", prec);
150  snprintf(buf, buflen, tmp, entry->num);
151  break;
152  case 'p':
153  if (entry->account->prefer_encrypt)
154  {
155  /* L10N: Autocrypt Account menu.
156  flag that an account has prefer-encrypt set */
157  mutt_format_s(buf, buflen, prec, _("prefer encrypt"));
158  }
159  else
160  {
161  /* L10N: Autocrypt Account menu.
162  flag that an account has prefer-encrypt unset;
163  thus encryption will need to be manually enabled. */
164  mutt_format_s(buf, buflen, prec, _("manual encrypt"));
165  }
166  break;
167  case 's':
168  if (entry->account->enabled)
169  {
170  /* L10N: Autocrypt Account menu.
171  flag that an account is enabled/active */
172  mutt_format_s(buf, buflen, prec, _("active"));
173  }
174  else
175  {
176  /* L10N: Autocrypt Account menu.
177  flag that an account is disabled/inactive */
178  mutt_format_s(buf, buflen, prec, _("inactive"));
179  }
180  break;
181  }
182 
183  return (src);
184 }
#define _(a)
Definition: message.h:28
An entry in the Autocrypt account Menu.
Definition: dlgautocrypt.c:88
struct Address * addr
Email address associated with the account.
Definition: dlgautocrypt.c:91
struct AutocryptAccount * account
Account details.
Definition: dlgautocrypt.c:90
int num
Number in the index.
Definition: dlgautocrypt.c:89
char * mailbox
Mailbox and host address.
Definition: address.h:38
char * keyid
PGP Key id.
Definition: lib.h:107
bool enabled
Is this account enabled.
Definition: lib.h:110
bool prefer_encrypt
false = nopref, true = mutual
Definition: lib.h:109
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ folder_format_str()

static const char* folder_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 
)
static

Format a string for the folder browser - Implements format_t -.

Expando Description
%C Current file number
%d Date/time folder was last modified
%D Date/time folder was last modified using $date_format.
%F File permissions
%f Filename (with suffix /, @ or *)
%g Group name (or numeric gid, if missing)
%i Description of the folder
%l Number of hard links
%m Number of messages in the mailbox
%N N if mailbox has new mail, blank otherwise
%n Number of unread messages in the mailbox
%s Size in bytes
%t * if the file is tagged, blank otherwise
%u Owner name (or numeric uid, if missing)

Definition at line 228 of file browser.c.

232 {
233  char fn[128], fmt[128];
234  struct Folder *folder = (struct Folder *) data;
235  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
236 
237  switch (op)
238  {
239  case 'C':
240  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
241  snprintf(buf, buflen, fmt, folder->num + 1);
242  break;
243 
244  case 'd':
245  case 'D':
246  if (folder->ff->local)
247  {
248  bool do_locales = true;
249 
250  const char *t_fmt = NULL;
251  if (op == 'D')
252  {
253  const char *const c_date_format =
254  cs_subset_string(NeoMutt->sub, "date_format");
255  t_fmt = NONULL(c_date_format);
256  if (*t_fmt == '!')
257  {
258  t_fmt++;
259  do_locales = false;
260  }
261  }
262  else
263  {
264  static const time_t one_year = 31536000;
265  t_fmt = ((mutt_date_epoch() - folder->ff->mtime) < one_year) ?
266  "%b %d %H:%M" :
267  "%b %d %Y";
268  }
269 
270  if (!do_locales)
271  setlocale(LC_TIME, "C");
272  char date[128];
273  mutt_date_localtime_format(date, sizeof(date), t_fmt, folder->ff->mtime);
274  if (!do_locales)
275  setlocale(LC_TIME, "");
276 
277  mutt_format_s(buf, buflen, prec, date);
278  }
279  else
280  {
281  mutt_format_s(buf, buflen, prec, "");
282  }
283  break;
284 
285  case 'f':
286  {
287  char *s = NULL;
288 
289  s = NONULL(folder->ff->name);
290 
291  snprintf(fn, sizeof(fn), "%s%s", s,
292  folder->ff->local ?
293  (S_ISLNK(folder->ff->mode) ?
294  "@" :
295  (S_ISDIR(folder->ff->mode) ?
296  "/" :
297  (((folder->ff->mode & S_IXUSR) != 0) ? "*" : ""))) :
298  "");
299 
300  mutt_format_s(buf, buflen, prec, fn);
301  break;
302  }
303  case 'F':
304  {
305  if (folder->ff->local)
306  {
307  char permission[11];
308  snprintf(permission, sizeof(permission), "%c%c%c%c%c%c%c%c%c%c",
309  S_ISDIR(folder->ff->mode) ? 'd' : (S_ISLNK(folder->ff->mode) ? 'l' : '-'),
310  ((folder->ff->mode & S_IRUSR) != 0) ? 'r' : '-',
311  ((folder->ff->mode & S_IWUSR) != 0) ? 'w' : '-',
312  ((folder->ff->mode & S_ISUID) != 0) ? 's' :
313  ((folder->ff->mode & S_IXUSR) != 0) ? 'x' :
314  '-',
315  ((folder->ff->mode & S_IRGRP) != 0) ? 'r' : '-',
316  ((folder->ff->mode & S_IWGRP) != 0) ? 'w' : '-',
317  ((folder->ff->mode & S_ISGID) != 0) ? 's' :
318  ((folder->ff->mode & S_IXGRP) != 0) ? 'x' :
319  '-',
320  ((folder->ff->mode & S_IROTH) != 0) ? 'r' : '-',
321  ((folder->ff->mode & S_IWOTH) != 0) ? 'w' : '-',
322  ((folder->ff->mode & S_ISVTX) != 0) ? 't' :
323  ((folder->ff->mode & S_IXOTH) != 0) ? 'x' :
324  '-');
325  mutt_format_s(buf, buflen, prec, permission);
326  }
327 #ifdef USE_IMAP
328  else if (folder->ff->imap)
329  {
330  char permission[11];
331  /* mark folders with subfolders AND mail */
332  snprintf(permission, sizeof(permission), "IMAP %c",
333  (folder->ff->inferiors && folder->ff->selectable) ? '+' : ' ');
334  mutt_format_s(buf, buflen, prec, permission);
335  }
336 #endif
337  else
338  mutt_format_s(buf, buflen, prec, "");
339  break;
340  }
341 
342  case 'g':
343  if (folder->ff->local)
344  {
345  struct group *gr = getgrgid(folder->ff->gid);
346  if (gr)
347  {
348  mutt_format_s(buf, buflen, prec, gr->gr_name);
349  }
350  else
351  {
352  snprintf(fmt, sizeof(fmt), "%%%sld", prec);
353  snprintf(buf, buflen, fmt, folder->ff->gid);
354  }
355  }
356  else
357  {
358  mutt_format_s(buf, buflen, prec, "");
359  }
360  break;
361 
362  case 'i':
363  {
364  char *s = NULL;
365  if (folder->ff->desc)
366  s = folder->ff->desc;
367  else
368  s = folder->ff->name;
369 
370  snprintf(fn, sizeof(fn), "%s%s", s,
371  folder->ff->local ?
372  (S_ISLNK(folder->ff->mode) ?
373  "@" :
374  (S_ISDIR(folder->ff->mode) ?
375  "/" :
376  (((folder->ff->mode & S_IXUSR) != 0) ? "*" : ""))) :
377  "");
378 
379  mutt_format_s(buf, buflen, prec, fn);
380  break;
381  }
382 
383  case 'l':
384  if (folder->ff->local)
385  {
386  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
387  snprintf(buf, buflen, fmt, folder->ff->nlink);
388  }
389  else
390  {
391  mutt_format_s(buf, buflen, prec, "");
392  }
393  break;
394 
395  case 'm':
396  if (!optional)
397  {
398  if (folder->ff->has_mailbox)
399  {
400  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
401  snprintf(buf, buflen, fmt, folder->ff->msg_count);
402  }
403  else
404  {
405  mutt_format_s(buf, buflen, prec, "");
406  }
407  }
408  else if (folder->ff->msg_count == 0)
409  optional = false;
410  break;
411 
412  case 'N':
413  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
414  snprintf(buf, buflen, fmt, folder->ff->has_new_mail ? 'N' : ' ');
415  break;
416 
417  case 'n':
418  if (!optional)
419  {
420  if (folder->ff->has_mailbox)
421  {
422  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
423  snprintf(buf, buflen, fmt, folder->ff->msg_unread);
424  }
425  else
426  {
427  mutt_format_s(buf, buflen, prec, "");
428  }
429  }
430  else if (folder->ff->msg_unread == 0)
431  optional = false;
432  break;
433 
434  case 's':
435  if (folder->ff->local)
436  {
437  mutt_str_pretty_size(fn, sizeof(fn), folder->ff->size);
438  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
439  snprintf(buf, buflen, fmt, fn);
440  }
441  else
442  {
443  mutt_format_s(buf, buflen, prec, "");
444  }
445  break;
446 
447  case 't':
448  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
449  snprintf(buf, buflen, fmt, folder->ff->tagged ? '*' : ' ');
450  break;
451 
452  case 'u':
453  if (folder->ff->local)
454  {
455  struct passwd *pw = getpwuid(folder->ff->uid);
456  if (pw)
457  {
458  mutt_format_s(buf, buflen, prec, pw->pw_name);
459  }
460  else
461  {
462  snprintf(fmt, sizeof(fmt), "%%%sld", prec);
463  snprintf(buf, buflen, fmt, folder->ff->uid);
464  }
465  }
466  else
467  {
468  mutt_format_s(buf, buflen, prec, "");
469  }
470  break;
471 
472  default:
473  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
474  snprintf(buf, buflen, fmt, op);
475  break;
476  }
477 
478  if (optional)
479  {
480  mutt_expando_format(buf, buflen, col, cols, if_str, folder_format_str, data,
482  }
483  else if (flags & MUTT_FORMAT_OPTIONAL)
484  {
485  mutt_expando_format(buf, buflen, col, cols, else_str, folder_format_str,
486  data, MUTT_FORMAT_NO_FLAGS);
487  }
488 
489  /* We return the format string, unchanged */
490  return src;
491 }
size_t mutt_date_localtime_format(char *buf, size_t buflen, const char *format, time_t t)
Format localtime.
Definition: date.c:691
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:427
static const char * folder_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)
Format a string for the folder browser - Implements format_t -.
Definition: browser.c:228
bool selectable
Folder can be selected.
Definition: lib.h:84
bool imap
This is an IMAP folder.
Definition: lib.h:83
bool has_mailbox
This is a mailbox.
Definition: lib.h:87
char * name
Name of file/dir/mailbox.
Definition: lib.h:73
uid_t uid
File's User ID.
Definition: lib.h:69
bool tagged
Folder is tagged.
Definition: lib.h:89
gid_t gid
File's Group ID.
Definition: lib.h:70
bool has_new_mail
true if mailbox has "new mail"
Definition: lib.h:76
nlink_t nlink
Number of hard links.
Definition: lib.h:71
char * desc
Description of mailbox.
Definition: lib.h:74
off_t size
File size.
Definition: lib.h:67
time_t mtime
Modification time.
Definition: lib.h:68
int msg_count
total number of messages
Definition: lib.h:77
mode_t mode
File permissions.
Definition: lib.h:66
bool inferiors
Folder has children.
Definition: lib.h:85
int msg_unread
number of unread messages
Definition: lib.h:78
A folder/dir in the browser.
Definition: lib.h:56
int num
Number in the index.
Definition: lib.h:58
struct FolderFile * ff
File / Dir / Mailbox.
Definition: lib.h:57
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ compress_format_str()

static const char* compress_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 
)
static

Expand the filenames in a command string - Implements format_t -.

Expando Description
%f Compressed file
%t Plaintext, temporary file

Definition at line 249 of file compress.c.

253 {
254  if (!buf || (data == 0))
255  return src;
256 
257  struct Mailbox *m = (struct Mailbox *) data;
258 
259  /* NOTE the compressed file config vars expect %f and %t to be
260  * surrounded by '' (unlike other NeoMutt config vars, which add the
261  * outer quotes for the user). This is why we use the
262  * mutt_buffer_quote_filename() form with add_outer of false. */
263  struct Buffer *quoted = mutt_buffer_pool_get();
264  switch (op)
265  {
266  case 'f':
267  /* Compressed file */
268  mutt_buffer_quote_filename(quoted, m->realpath, false);
269  snprintf(buf, buflen, "%s", mutt_buffer_string(quoted));
270  break;
271  case 't':
272  /* Plaintext, temporary file */
273  mutt_buffer_quote_filename(quoted, mailbox_path(m), false);
274  snprintf(buf, buflen, "%s", mutt_buffer_string(quoted));
275  break;
276  }
277 
278  mutt_buffer_pool_release(&quoted);
279  return src;
280 }
void mutt_buffer_quote_filename(struct Buffer *buf, const char *filename, bool add_outer)
Quote a filename to survive the shell's quoting rules.
Definition: file.c:866
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition: mailbox.h:215
A mailbox.
Definition: mailbox.h:82
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:84
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ compose_format_str()

static const char* compose_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 
)
static

Create the status bar string for compose mode - Implements format_t -.

Expando Description
%a Total number of attachments
%h Local hostname
%l Approximate size (in bytes) of the current message
%v NeoMutt version string

Definition at line 102 of file cbar.c.

106 {
107  char fmt[128], tmp[128];
108  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
109  struct ComposeSharedData *shared = (struct ComposeSharedData *) data;
110 
111  *buf = '\0';
112  switch (op)
113  {
114  case 'a': /* total number of attachments */
115  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
116  snprintf(buf, buflen, fmt, num_attachments(shared->adata));
117  break;
118 
119  case 'h': /* hostname */
120  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
121  snprintf(buf, buflen, fmt, NONULL(ShortHostname));
122  break;
123 
124  case 'l': /* approx length of current message in bytes */
125  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
126  mutt_str_pretty_size(tmp, sizeof(tmp),
127  cum_attachs_size(shared->sub, shared->adata));
128  snprintf(buf, buflen, fmt, tmp);
129  break;
130 
131  case 'v':
132  snprintf(buf, buflen, "%s", mutt_make_version());
133  break;
134 
135  case 0:
136  *buf = '\0';
137  return src;
138 
139  default:
140  snprintf(buf, buflen, "%%%s%c", prec, op);
141  break;
142  }
143 
144  if (optional)
145  {
146  mutt_expando_format(buf, buflen, col, cols, if_str, compose_format_str, data, flags);
147  }
148  // This format function doesn't have any optional expandos,
149  // so there's no `else if (flags & MUTT_FORMAT_OPTIONAL)` clause
150 
151  return src;
152 }
int num_attachments(struct ComposeAttachData *adata)
Count the number of attachments.
Definition: cbar.c:85
unsigned long cum_attachs_size(struct ConfigSubset *sub, struct ComposeAttachData *adata)
Cumulative Attachments Size.
Definition: attach.c:87
static const char * compose_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 for compose mode - Implements format_t -.
Definition: cbar.c:102
char * ShortHostname
Short version of the hostname.
Definition: mutt_globals.h:50
const char * mutt_make_version(void)
Generate the NeoMutt version string.
Definition: muttlib.c:1476
Shared Compose Data.
Definition: shared_data.h:33
struct ConfigSubset * sub
Config set to use.
Definition: shared_data.h:34
int flags
Flags, e.g. MUTT_COMPOSE_NOFREEHEADER.
Definition: shared_data.h:42
struct ComposeAttachData * adata
Attachments.
Definition: shared_data.h:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ index_format_str()

static const char* index_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 
)
static

Format a string for the index list - Implements format_t -.

Expando Description
%a Address of the author
%A Reply-to address (if present; otherwise: address of author)
%b Filename of the original message folder (think mailbox)
%B The list to which the email was sent, or else the folder name (b)
%C Current message number
%c Number of characters (bytes) in the body of the message
%cr Number of characters (bytes) in the message, including header
%D Date and time of message using $date_format and local timezone
%d Date and time of message using $date_format and sender's timezone
%e Current message number in thread
%E Number of messages in current thread
%Fp Like F, but plain. No contextual formatting is applied to recipient name
%F Author name, or recipient name if the message is from you
%f Sender (address + real name), either From: or Return-Path:
%Gx Individual message tag (e.g. notmuch tags/imap flags)
%g Message tags (e.g. notmuch tags/imap flags)
%H Spam attribute(s) of this message
%I Initials of author
%i Message-id of the current message
%J Message tags (if present, tree unfolded, and != parent's tags)
%K The list to which the email was sent (if any; otherwise: empty)
%L Like F, except 'lists' are displayed first
%l Number of lines in the message
%M Number of hidden messages if the thread is collapsed
%m Total number of message in the mailbox
%n Author's real name (or address if missing)
%N Message score
%O Like L, except using address instead of name
%P Progress indicator for the built-in pager (how much of the file has been displayed)
%q Newsgroup name (if compiled with NNTP support)
%R Comma separated list of Cc: recipients
%r Comma separated list of To: recipients
%S Single character status of the message (N/O/D/d/!/r/-)
%s Subject of the message
%t 'To:' field (recipients)
%T The appropriate character from the $to_chars string
%u User (login) name of the author
%v First name of the author, or the recipient if the message is from you
%W Name of organization of author ('Organization:' field)
%x 'X-Comment-To:' field (if present and compiled with NNTP support)
%X Number of MIME attachments
%y 'X-Label:' field (if present)
%Y 'X-Label:' field (if present, tree unfolded, and != parent's x-label)
%zc Message crypto flags
%zs Message status flags
%zt Message tag flags
%Z Combined message flags
%@name@ Insert and evaluate format-string from the matching "$index-format-hook" command
%(fmt) Date/time when the message was received
%[fmt] Message date/time converted to the local time zone
%{fmt} Message date/time converted to sender's time zone

Definition at line 441 of file hdrline.c.

445 {
446  struct HdrFormatInfo *hfi = (struct HdrFormatInfo *) data;
447  char fmt[128], tmp[1024];
448  char *p = NULL, *tags = NULL;
449  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
450  const bool threads = mutt_using_threads();
451  int is_index = (flags & MUTT_FORMAT_INDEX);
452  size_t colorlen;
453 
454  struct Email *e = hfi->email;
455  size_t msg_in_pager = hfi->msg_in_pager;
456  struct Mailbox *m = hfi->mailbox;
457 
458  if (!e || !e->env)
459  return src;
460 
461  const struct Address *reply_to = TAILQ_FIRST(&e->env->reply_to);
462  const struct Address *from = TAILQ_FIRST(&e->env->from);
463  const struct Address *to = TAILQ_FIRST(&e->env->to);
464  const struct Address *cc = TAILQ_FIRST(&e->env->cc);
465 
466  const struct MbTable *c_crypt_chars =
467  cs_subset_mbtable(NeoMutt->sub, "crypt_chars");
468  const struct MbTable *c_flag_chars =
469  cs_subset_mbtable(NeoMutt->sub, "flag_chars");
470  const struct MbTable *c_to_chars =
471  cs_subset_mbtable(NeoMutt->sub, "to_chars");
472  const char *const c_date_format =
473  cs_subset_string(NeoMutt->sub, "date_format");
474 
475  buf[0] = '\0';
476  switch (op)
477  {
478  case 'A':
479  case 'I':
480  if (op == 'A')
481  {
482  if (reply_to && reply_to->mailbox)
483  {
484  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_AUTHOR);
485  mutt_format_s(buf + colorlen, buflen - colorlen, prec,
486  mutt_addr_for_display(reply_to));
487  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
488  break;
489  }
490  }
491  else
492  {
493  if (mutt_mb_get_initials(mutt_get_name(from), tmp, sizeof(tmp)))
494  {
495  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_AUTHOR);
496  mutt_format_s(buf + colorlen, buflen - colorlen, prec, tmp);
497  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
498  break;
499  }
500  }
501  /* fallthrough */
502 
503  case 'a':
504  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_AUTHOR);
505  if (from && from->mailbox)
506  {
507  mutt_format_s(buf + colorlen, buflen - colorlen, prec, mutt_addr_for_display(from));
508  }
509  else
510  mutt_format_s(buf + colorlen, buflen - colorlen, prec, "");
511  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
512  break;
513 
514  case 'B':
515  case 'K':
516  if (first_mailing_list(buf, buflen, &e->env->to) ||
517  first_mailing_list(buf, buflen, &e->env->cc))
518  {
519  mutt_str_copy(tmp, buf, sizeof(tmp));
520  mutt_format_s(buf, buflen, prec, tmp);
521  }
522  else if (optional)
523  {
524  optional = false;
525  }
526  break;
527 
528  case 'b':
529  if (m)
530  {
531  p = strrchr(mailbox_path(m), '/');
532 #ifdef USE_NOTMUCH
533  if (m->type == MUTT_NOTMUCH)
534  {
535  char *rel_path = nm_email_get_folder_rel_db(m, e);
536  if (rel_path)
537  p = rel_path;
538  }
539 #endif
540 
541  if (p)
542  mutt_str_copy(buf, p + 1, buflen);
543  else
544  mutt_str_copy(buf, mailbox_path(m), buflen);
545  }
546  else
547  mutt_str_copy(buf, "(null)", buflen);
548  mutt_str_copy(tmp, buf, sizeof(tmp));
549  mutt_format_s(buf, buflen, prec, tmp);
550  break;
551 
552  case 'c':
553  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_SIZE);
554  if (src[0] == 'r')
555  {
556  mutt_str_pretty_size(tmp, sizeof(tmp), email_size(e));
557  src++;
558  }
559  else
560  {
561  mutt_str_pretty_size(tmp, sizeof(tmp), e->body->length);
562  }
563  mutt_format_s(buf + colorlen, buflen - colorlen, prec, tmp);
564  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
565  break;
566 
567  case 'C':
568  colorlen = add_index_color(fmt, sizeof(fmt), flags, MT_COLOR_INDEX_NUMBER);
569  snprintf(fmt + colorlen, sizeof(fmt) - colorlen, "%%%sd", prec);
570  add_index_color(fmt + colorlen, sizeof(fmt) - colorlen, flags, MT_COLOR_INDEX);
571  snprintf(buf, buflen, fmt, e->msgno + 1);
572  break;
573 
574  case 'd':
575  case 'D':
576  case '{':
577  case '[':
578  case '(':
579  case '<':
580  /* preprocess $date_format to handle %Z */
581  {
582  const char *cp = NULL;
583  time_t now;
584  int j = 0;
585 
586  if (optional && ((op == '[') || (op == '(')))
587  {
588  now = mutt_date_epoch();
589  struct tm tm = mutt_date_localtime(now);
590  now -= (op == '(') ? e->received : e->date_sent;
591 
592  char *is = (char *) prec;
593  bool invert = false;
594  if (*is == '>')
595  {
596  invert = true;
597  is++;
598  }
599 
600  while (*is && (*is != '?'))
601  {
602  int t = strtol(is, &is, 10);
603  /* semi-broken (assuming 30 days in all months) */
604  switch (*(is++))
605  {
606  case 'y':
607  if (t > 1)
608  {
609  t--;
610  t *= (60 * 60 * 24 * 365);
611  }
612  t += ((tm.tm_mon * 60 * 60 * 24 * 30) + (tm.tm_mday * 60 * 60 * 24) +
613  (tm.tm_hour * 60 * 60) + (tm.tm_min * 60) + tm.tm_sec);
614  break;
615 
616  case 'm':
617  if (t > 1)
618  {
619  t--;
620  t *= (60 * 60 * 24 * 30);
621  }
622  t += ((tm.tm_mday * 60 * 60 * 24) + (tm.tm_hour * 60 * 60) +
623  (tm.tm_min * 60) + tm.tm_sec);
624  break;
625 
626  case 'w':
627  if (t > 1)
628  {
629  t--;
630  t *= (60 * 60 * 24 * 7);
631  }
632  t += ((tm.tm_wday * 60 * 60 * 24) + (tm.tm_hour * 60 * 60) +
633  (tm.tm_min * 60) + tm.tm_sec);
634  break;
635 
636  case 'd':
637  if (t > 1)
638  {
639  t--;
640  t *= (60 * 60 * 24);
641  }
642  t += ((tm.tm_hour * 60 * 60) + (tm.tm_min * 60) + tm.tm_sec);
643  break;
644 
645  case 'H':
646  if (t > 1)
647  {
648  t--;
649  t *= (60 * 60);
650  }
651  t += ((tm.tm_min * 60) + tm.tm_sec);
652  break;
653 
654  case 'M':
655  if (t > 1)
656  {
657  t--;
658  t *= (60);
659  }
660  t += (tm.tm_sec);
661  break;
662 
663  default:
664  break;
665  }
666  j += t;
667  }
668 
669  if (j < 0)
670  j *= -1;
671 
672  if (((now > j) || (now < (-1 * j))) ^ invert)
673  optional = false;
674  break;
675  }
676 
677  p = buf;
678 
679  cp = ((op == 'd') || (op == 'D')) ? (NONULL(c_date_format)) : src;
680  bool do_locales;
681  if (*cp == '!')
682  {
683  do_locales = false;
684  cp++;
685  }
686  else
687  do_locales = true;
688 
689  size_t len = buflen - 1;
690  while ((len > 0) &&
691  ((((op == 'd') || (op == 'D')) && *cp) ||
692  ((op == '{') && (*cp != '}')) || ((op == '[') && (*cp != ']')) ||
693  ((op == '(') && (*cp != ')')) || ((op == '<') && (*cp != '>'))))
694  {
695  if (*cp == '%')
696  {
697  cp++;
698  if (((*cp == 'Z') || (*cp == 'z')) && ((op == 'd') || (op == '{')))
699  {
700  if (len >= 5)
701  {
702  sprintf(p, "%c%02u%02u", e->zoccident ? '-' : '+', e->zhours, e->zminutes);
703  p += 5;
704  len -= 5;
705  }
706  else
707  break; /* not enough space left */
708  }
709  else
710  {
711  if (len >= 2)
712  {
713  *p++ = '%';
714  *p++ = *cp;
715  len -= 2;
716  }
717  else
718  break; /* not enough space */
719  }
720  cp++;
721  }
722  else
723  {
724  *p++ = *cp++;
725  len--;
726  }
727  }
728  *p = '\0';
729 
730  struct tm tm;
731  if ((op == '[') || (op == 'D'))
733  else if (op == '(')
734  tm = mutt_date_localtime(e->received);
735  else if (op == '<')
736  {
738  }
739  else
740  {
741  /* restore sender's time zone */
742  now = e->date_sent;
743  if (e->zoccident)
744  now -= (e->zhours * 3600 + e->zminutes * 60);
745  else
746  now += (e->zhours * 3600 + e->zminutes * 60);
747  tm = mutt_date_gmtime(now);
748  }
749 
750  if (!do_locales)
751  setlocale(LC_TIME, "C");
752  strftime(tmp, sizeof(tmp), buf, &tm);
753  if (!do_locales)
754  setlocale(LC_TIME, "");
755 
756  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_DATE);
757  mutt_format_s(buf + colorlen, buflen - colorlen, prec, tmp);
758  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
759 
760  if ((len > 0) && (op != 'd') && (op != 'D')) /* Skip ending op */
761  src = cp + 1;
762  break;
763  }
764 
765  case 'e':
766  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
767  snprintf(buf, buflen, fmt, mutt_messages_in_thread(m, e, MIT_POSITION));
768  break;
769 
770  case 'E':
771  if (!optional)
772  {
773  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
774  snprintf(buf, buflen, fmt, mutt_messages_in_thread(m, e, MIT_NUM_MESSAGES));
775  }
776  else if (mutt_messages_in_thread(m, e, MIT_NUM_MESSAGES) <= 1)
777  optional = false;
778  break;
779 
780  case 'f':
781  tmp[0] = '\0';
782  mutt_addrlist_write(&e->env->from, tmp, sizeof(tmp), true);
783  mutt_format_s(buf, buflen, prec, tmp);
784  break;
785 
786  case 'F':
787  if (!optional)
788  {
789  const bool is_plain = (src[0] == 'p');
790  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_AUTHOR);
791  make_from(e->env, tmp, sizeof(tmp), false,
792  (is_plain ? MUTT_FORMAT_PLAIN : MUTT_FORMAT_NO_FLAGS));
793  mutt_format_s(buf + colorlen, buflen - colorlen, prec, tmp);
794  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
795 
796  if (is_plain)
797  src++;
798  }
799  else if (mutt_addr_is_user(from))
800  {
801  optional = false;
802  }
803  break;
804 
805  case 'g':
806  tags = driver_tags_get_transformed(&e->tags);
807  if (!optional)
808  {
809  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_TAGS);
810  mutt_format_s(buf + colorlen, buflen - colorlen, prec, NONULL(tags));
811  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
812  }
813  else if (!tags)
814  optional = false;
815  FREE(&tags);
816  break;
817 
818  case 'G':
819  {
820  char format[3];
821  char *tag = NULL;
822 
823  if (!optional)
824  {
825  format[0] = op;
826  format[1] = *src;
827  format[2] = '\0';
828 
829  tag = mutt_hash_find(TagFormats, format);
830  if (tag)
831  {
832  tags = driver_tags_get_transformed_for(&e->tags, tag);
833  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_TAG);
834  mutt_format_s(buf + colorlen, buflen - colorlen, prec, NONULL(tags));
835  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
836  FREE(&tags);
837  }
838  src++;
839  }
840  else
841  {
842  format[0] = op;
843  format[1] = *prec;
844  format[2] = '\0';
845 
846  tag = mutt_hash_find(TagFormats, format);
847  if (tag)
848  {
849  tags = driver_tags_get_transformed_for(&e->tags, tag);
850  if (!tags)
851  optional = false;
852  FREE(&tags);
853  }
854  }
855  break;
856  }
857 
858  case 'H':
859  /* (Hormel) spam score */
860  if (optional)
861  optional = !mutt_buffer_is_empty(&e->env->spam);
862 
863  mutt_format_s(buf, buflen, prec, mutt_buffer_string(&e->env->spam));
864  break;
865 
866  case 'i':
867  mutt_format_s(buf, buflen, prec, e->env->message_id ? e->env->message_id : "<no.id>");
868  break;
869 
870  case 'J':
871  {
872  bool have_tags = true;
873  tags = driver_tags_get_transformed(&e->tags);
874  if (tags)
875  {
876  if (flags & MUTT_FORMAT_TREE)
877  {
878  char *parent_tags = NULL;
879  if (e->thread->prev && e->thread->prev->message)
880  {
881  parent_tags = driver_tags_get_transformed(&e->thread->prev->message->tags);
882  }
883  if (!parent_tags && e->thread->parent && e->thread->parent->message)
884  {
885  parent_tags =
887  }
888  if (parent_tags && mutt_istr_equal(tags, parent_tags))
889  have_tags = false;
890  FREE(&parent_tags);
891  }
892  }
893  else
894  have_tags = false;
895 
896  if (optional)
897  optional = have_tags;
898 
899  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_TAGS);
900  if (have_tags)
901  mutt_format_s(buf + colorlen, buflen - colorlen, prec, tags);
902  else
903  mutt_format_s(buf + colorlen, buflen - colorlen, prec, "");
904  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
905  FREE(&tags);
906  break;
907  }
908 
909  case 'l':
910  if (!optional)
911  {
912  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
913  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_SIZE);
914  snprintf(buf + colorlen, buflen - colorlen, fmt, (int) e->lines);
915  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
916  }
917  else if (e->lines <= 0)
918  optional = false;
919  break;
920 
921  case 'L':
922  if (!optional)
923  {
924  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_AUTHOR);
925  make_from(e->env, tmp, sizeof(tmp), true, flags);
926  mutt_format_s(buf + colorlen, buflen - colorlen, prec, tmp);
927  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
928  }
929  else if (!check_for_mailing_list(&e->env->to, NULL, NULL, 0) &&
930  !check_for_mailing_list(&e->env->cc, NULL, NULL, 0))
931  {
932  optional = false;
933  }
934  break;
935 
936  case 'm':
937  if (m)
938  {
939  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
940  snprintf(buf, buflen, fmt, m->msg_count);
941  }
942  else
943  mutt_str_copy(buf, "(null)", buflen);
944  break;
945 
946  case 'n':
947  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_AUTHOR);
948  mutt_format_s(buf + colorlen, buflen - colorlen, prec, mutt_get_name(from));
949  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
950  break;
951 
952  case 'M':
953  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
954  if (!optional)
955  {
956  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_COLLAPSED);
957  if (threads && is_index && e->collapsed && (e->num_hidden > 1))
958  {
959  snprintf(buf + colorlen, buflen - colorlen, fmt, e->num_hidden);
960  add_index_color(buf, buflen - colorlen, flags, MT_COLOR_INDEX);
961  }
962  else if (is_index && threads)
963  {
964  mutt_format_s(buf + colorlen, buflen - colorlen, prec, " ");
965  add_index_color(buf, buflen - colorlen, flags, MT_COLOR_INDEX);
966  }
967  else
968  *buf = '\0';
969  }
970  else
971  {
972  if (!(threads && is_index && e->collapsed && (e->num_hidden > 1)))
973  optional = false;
974  }
975  break;
976 
977  case 'N':
978  if (!optional)
979  {
980  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
981  snprintf(buf, buflen, fmt, e->score);
982  }
983  else
984  {
985  if (e->score == 0)
986  optional = false;
987  }
988  break;
989 
990  case 'O':
991  if (!optional)
992  {
993  make_from_addr(e->env, tmp, sizeof(tmp), true);
994  const bool c_save_address =
995  cs_subset_bool(NeoMutt->sub, "save_address");
996  if (!c_save_address && (p = strpbrk(tmp, "%@")))
997  *p = '\0';
998  mutt_format_s(buf, buflen, prec, tmp);
999  }
1000  else if (!check_for_mailing_list_addr(&e->env->to, NULL, 0) &&
1001  !check_for_mailing_list_addr(&e->env->cc, NULL, 0))
1002  {
1003  optional = false;
1004  }
1005  break;
1006 
1007  case 'P':
1008  mutt_str_copy(buf, hfi->pager_progress, buflen);
1009  break;
1010 
1011 #ifdef USE_NNTP
1012  case 'q':
1013  mutt_format_s(buf, buflen, prec, e->env->newsgroups ? e->env->newsgroups : "");
1014  break;
1015 #endif
1016 
1017  case 'r':
1018  tmp[0] = '\0';
1019  mutt_addrlist_write(&e->env->to, tmp, sizeof(tmp), true);
1020  if (optional && (tmp[0] == '\0'))
1021  optional = false;
1022  mutt_format_s(buf, buflen, prec, tmp);
1023  break;
1024 
1025  case 'R':
1026  tmp[0] = '\0';
1027  mutt_addrlist_write(&e->env->cc, tmp, sizeof(tmp), true);
1028  if (optional && (tmp[0] == '\0'))
1029  optional = false;
1030  mutt_format_s(buf, buflen, prec, tmp);
1031  break;
1032 
1033  case 's':
1034  {
1035  subjrx_apply_mods(e->env);
1036  char *subj = NULL;
1037  if (e->env->disp_subj)
1038  subj = e->env->disp_subj;
1039  else
1040  subj = e->env->subject;
1041  if (flags & MUTT_FORMAT_TREE && !e->collapsed)
1042  {
1043  if (flags & MUTT_FORMAT_FORCESUBJ)
1044  {
1045  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_SUBJECT);
1046  mutt_format_s(buf + colorlen, buflen - colorlen, "", NONULL(subj));
1047  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
1048  snprintf(tmp, sizeof(tmp), "%s%s", e->tree, buf);
1049  mutt_format_s_tree(buf, buflen, prec, tmp);
1050  }
1051  else
1052  mutt_format_s_tree(buf, buflen, prec, e->tree);
1053  }
1054  else
1055  {
1056  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_SUBJECT);
1057  mutt_format_s(buf + colorlen, buflen - colorlen, prec, NONULL(subj));
1058  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
1059  }
1060  break;
1061  }
1062 
1063  case 'S':
1064  {
1065  const char *wch = NULL;
1066  if (e->deleted)
1067  wch = get_nth_wchar(c_flag_chars, FLAG_CHAR_DELETED);
1068  else if (e->attach_del)
1069  wch = get_nth_wchar(c_flag_chars, FLAG_CHAR_DELETED_ATTACH);
1070  else if (e->tagged)
1071  wch = get_nth_wchar(c_flag_chars, FLAG_CHAR_TAGGED);
1072  else if (e->flagged)
1073  wch = get_nth_wchar(c_flag_chars, FLAG_CHAR_IMPORTANT);
1074  else if (e->replied)
1075  wch = get_nth_wchar(c_flag_chars, FLAG_CHAR_REPLIED);
1076  else if (e->read && (msg_in_pager != e->msgno))
1077  wch = get_nth_wchar(c_flag_chars, FLAG_CHAR_SEMPTY);
1078  else if (e->old)
1079  wch = get_nth_wchar(c_flag_chars, FLAG_CHAR_OLD);
1080  else
1081  wch = get_nth_wchar(c_flag_chars, FLAG_CHAR_NEW);
1082 
1083  snprintf(tmp, sizeof(tmp), "%s", wch);
1084  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_FLAGS);
1085  mutt_format_s(buf + colorlen, buflen - colorlen, prec, tmp);
1086  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
1087  break;
1088  }
1089 
1090  case 't':
1091  tmp[0] = '\0';
1092  if (!check_for_mailing_list(&e->env->to, "To ", tmp, sizeof(tmp)) &&
1093  !check_for_mailing_list(&e->env->cc, "Cc ", tmp, sizeof(tmp)))
1094  {
1095  if (to)
1096  snprintf(tmp, sizeof(tmp), "To %s", mutt_get_name(to));
1097  else if (cc)
1098  snprintf(tmp, sizeof(tmp), "Cc %s", mutt_get_name(cc));
1099  }
1100  mutt_format_s(buf, buflen, prec, tmp);
1101  break;
1102 
1103  case 'T':
1104  {
1105  int i;
1106  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
1107  snprintf(buf, buflen, fmt,
1108  (c_to_chars && ((i = user_is_recipient(e))) < c_to_chars->len) ?
1109  c_to_chars->chars[i] :
1110  " ");
1111  break;
1112  }
1113 
1114  case 'u':
1115  if (from && from->mailbox)
1116  {
1117  mutt_str_copy(tmp, mutt_addr_for_display(from), sizeof(tmp));
1118  p = strpbrk(tmp, "%@");
1119  if (p)
1120  *p = '\0';
1121  }
1122  else
1123  tmp[0] = '\0';
1124  mutt_format_s(buf, buflen, prec, tmp);
1125  break;
1126 
1127  case 'v':
1128  if (mutt_addr_is_user(from))
1129  {
1130  if (to)
1131  mutt_format_s(tmp, sizeof(tmp), prec, mutt_get_name(to));
1132  else if (cc)
1133  mutt_format_s(tmp, sizeof(tmp), prec, mutt_get_name(cc));
1134  else
1135  *tmp = '\0';
1136  }
1137  else
1138  mutt_format_s(tmp, sizeof(tmp), prec, mutt_get_name(from));
1139  p = strpbrk(tmp, " %@");
1140  if (p)
1141  *p = '\0';
1142  mutt_format_s(buf, buflen, prec, tmp);
1143  break;
1144 
1145  case 'W':
1146  if (!optional)
1147  {
1148  mutt_format_s(buf, buflen, prec, e->env->organization ? e->env->organization : "");
1149  }
1150  else if (!e->env->organization)
1151  optional = false;
1152  break;
1153 
1154 #ifdef USE_NNTP
1155  case 'x':
1156  if (!optional)
1157  {
1158  mutt_format_s(buf, buflen, prec, e->env->x_comment_to ? e->env->x_comment_to : "");
1159  }
1160  else if (!e->env->x_comment_to)
1161  optional = false;
1162  break;
1163 #endif
1164 
1165  case 'X':
1166  {
1167  struct Message *msg = mx_msg_open(m, e->msgno);
1168  if (msg)
1169  {
1170  int count = mutt_count_body_parts(m, e, msg->fp);
1171  mx_msg_close(m, &msg);
1172 
1173  /* The recursion allows messages without depth to return 0. */
1174  if (optional)
1175  optional = (count != 0);
1176 
1177  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
1178  snprintf(buf, buflen, fmt, count);
1179  }
1180  break;
1181  }
1182 
1183  case 'y':
1184  if (optional)
1185  optional = (e->env->x_label != NULL);
1186 
1187  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_LABEL);
1188  mutt_format_s(buf + colorlen, buflen - colorlen, prec, NONULL(e->env->x_label));
1189  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
1190  break;
1191 
1192  case 'Y':
1193  {
1194  bool label = true;
1195  if (e->env->x_label)
1196  {
1197  struct Email *e_tmp = NULL;
1198  if (flags & MUTT_FORMAT_TREE && (e->thread->prev && e->thread->prev->message &&
1199  e->thread->prev->message->env->x_label))
1200  {
1201  e_tmp = e->thread->prev->message;
1202  }
1203  else if (flags & MUTT_FORMAT_TREE &&
1204  (e->thread->parent && e->thread->parent->message &&
1205  e->thread->parent->message->env->x_label))
1206  {
1207  e_tmp = e->thread->parent->message;
1208  }
1209  if (e_tmp && mutt_istr_equal(e->env->x_label, e_tmp->env->x_label))
1210  label = false;
1211  }
1212  else
1213  label = false;
1214 
1215  if (optional)
1216  optional = label;
1217 
1218  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_LABEL);
1219  if (label)
1220  mutt_format_s(buf + colorlen, buflen - colorlen, prec, NONULL(e->env->x_label));
1221  else
1222  mutt_format_s(buf + colorlen, buflen - colorlen, prec, "");
1223  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
1224  break;
1225  }
1226 
1227  case 'z':
1228  if (src[0] == 's') /* status: deleted/new/old/replied */
1229  {
1230  const char *ch = NULL;
1231  if (e->deleted)
1232  ch = get_nth_wchar(c_flag_chars, FLAG_CHAR_DELETED);
1233  else if (e->attach_del)
1234  ch = get_nth_wchar(c_flag_chars, FLAG_CHAR_DELETED_ATTACH);
1235  else if (threads && thread_is_new(e))
1236  ch = get_nth_wchar(c_flag_chars, FLAG_CHAR_NEW_THREAD);
1237  else if (threads && thread_is_old(e))
1238  ch = get_nth_wchar(c_flag_chars, FLAG_CHAR_OLD_THREAD);
1239  else if (e->read && (msg_in_pager != e->msgno))
1240  {
1241  if (e->replied)
1242  ch = get_nth_wchar(c_flag_chars, FLAG_CHAR_REPLIED);
1243  else
1244  ch = get_nth_wchar(c_flag_chars, FLAG_CHAR_ZEMPTY);
1245  }
1246  else
1247  {
1248  if (e->old)
1249  ch = get_nth_wchar(c_flag_chars, FLAG_CHAR_OLD);
1250  else
1251  ch = get_nth_wchar(c_flag_chars, FLAG_CHAR_NEW);
1252  }
1253 
1254  snprintf(tmp, sizeof(tmp), "%s", ch);
1255  src++;
1256  }
1257  else if (src[0] == 'c') /* crypto */
1258  {
1259  const char *ch = "";
1260  if ((WithCrypto != 0) && (e->security & SEC_GOODSIGN))
1261  ch = get_nth_wchar(c_crypt_chars, FLAG_CHAR_CRYPT_GOOD_SIGN);
1262  else if ((WithCrypto != 0) && (e->security & SEC_ENCRYPT))
1263  ch = get_nth_wchar(c_crypt_chars, FLAG_CHAR_CRYPT_ENCRYPTED);
1264  else if ((WithCrypto != 0) && (e->security & SEC_SIGN))
1265  ch = get_nth_wchar(c_crypt_chars, FLAG_CHAR_CRYPT_SIGNED);
1266  else if (((WithCrypto & APPLICATION_PGP) != 0) && ((e->security & PGP_KEY) == PGP_KEY))
1267  {
1268  ch = get_nth_wchar(c_crypt_chars, FLAG_CHAR_CRYPT_CONTAINS_KEY);
1269  }
1270  else
1271  ch = get_nth_wchar(c_crypt_chars, FLAG_CHAR_CRYPT_NO_CRYPTO);
1272 
1273  snprintf(tmp, sizeof(tmp), "%s", ch);
1274  src++;
1275  }
1276  else if (src[0] == 't') /* tagged, flagged, recipient */
1277  {
1278  const char *ch = "";
1279  if (e->tagged)
1280  ch = get_nth_wchar(c_flag_chars, FLAG_CHAR_TAGGED);
1281  else if (e->flagged)
1282  ch = get_nth_wchar(c_flag_chars, FLAG_CHAR_IMPORTANT);
1283  else
1284  ch = get_nth_wchar(c_to_chars, user_is_recipient(e));
1285 
1286  snprintf(tmp, sizeof(tmp), "%s", ch);
1287  src++;
1288  }
1289  else /* fallthrough */
1290  break;
1291 
1292  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_FLAGS);
1293  mutt_format_s(buf + colorlen, buflen - colorlen, prec, tmp);
1294  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
1295  break;
1296 
1297  case 'Z':
1298  {
1299  /* New/Old for threads; replied; New/Old for messages */
1300  const char *first = NULL;
1301  if (threads && thread_is_new(e))
1302  first = get_nth_wchar(c_flag_chars, FLAG_CHAR_NEW_THREAD);
1303  else if (threads && thread_is_old(e))
1304  first = get_nth_wchar(c_flag_chars, FLAG_CHAR_OLD_THREAD);
1305  else if (e->read && (msg_in_pager != e->msgno))
1306  {
1307  if (e->replied)
1308  first = get_nth_wchar(c_flag_chars, FLAG_CHAR_REPLIED);
1309  else
1310  first = get_nth_wchar(c_flag_chars, FLAG_CHAR_ZEMPTY);
1311  }
1312  else
1313  {
1314  if (e->old)
1315  first = get_nth_wchar(c_flag_chars, FLAG_CHAR_OLD);
1316  else
1317  first = get_nth_wchar(c_flag_chars, FLAG_CHAR_NEW);
1318  }
1319 
1320  /* Marked for deletion; deleted attachments; crypto */
1321  const char *second = "";
1322  if (e->deleted)
1323  second = get_nth_wchar(c_flag_chars, FLAG_CHAR_DELETED);
1324  else if (e->attach_del)
1325  second = get_nth_wchar(c_flag_chars, FLAG_CHAR_DELETED_ATTACH);
1326  else if ((WithCrypto != 0) && (e->security & SEC_GOODSIGN))
1327  second = get_nth_wchar(c_crypt_chars, FLAG_CHAR_CRYPT_GOOD_SIGN);
1328  else if ((WithCrypto != 0) && (e->security & SEC_ENCRYPT))
1329  second = get_nth_wchar(c_crypt_chars, FLAG_CHAR_CRYPT_ENCRYPTED);
1330  else if ((WithCrypto != 0) && (e->security & SEC_SIGN))
1331  second = get_nth_wchar(c_crypt_chars, FLAG_CHAR_CRYPT_SIGNED);
1332  else if (((WithCrypto & APPLICATION_PGP) != 0) && (e->security & PGP_KEY))
1333  second = get_nth_wchar(c_crypt_chars, FLAG_CHAR_CRYPT_CONTAINS_KEY);
1334  else
1335  second = get_nth_wchar(c_crypt_chars, FLAG_CHAR_CRYPT_NO_CRYPTO);
1336 
1337  /* Tagged, flagged and recipient flag */
1338  const char *third = "";
1339  if (e->tagged)
1340  third = get_nth_wchar(c_flag_chars, FLAG_CHAR_TAGGED);
1341  else if (e->flagged)
1342  third = get_nth_wchar(c_flag_chars, FLAG_CHAR_IMPORTANT);
1343  else
1344  third = get_nth_wchar(c_to_chars, user_is_recipient(e));
1345 
1346  snprintf(tmp, sizeof(tmp), "%s%s%s", first, second, third);
1347  }
1348 
1349  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_FLAGS);
1350  mutt_format_s(buf + colorlen, buflen - colorlen, prec, tmp);
1351  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
1352  break;
1353 
1354  case '@':
1355  {
1356  if (!m)
1357  break;
1358 
1359  const char *end = src;
1360  static unsigned char recurse = 0;
1361 
1362  while ((*end != '\0') && (*end != '@'))
1363  end++;
1364  if ((*end == '@') && (recurse < 20))
1365  {
1366  recurse++;
1367  mutt_strn_copy(tmp, src, end - src, sizeof(tmp));
1368  mutt_expando_format(tmp, sizeof(tmp), col, cols,
1369  NONULL(mutt_idxfmt_hook(tmp, m, e)),
1370  index_format_str, data, flags);
1371  mutt_format_s_x(buf, buflen, prec, tmp, true);
1372  recurse--;
1373 
1374  src = end + 1;
1375  break;
1376  }
1377  }
1378  /* fallthrough */
1379 
1380  default:
1381  snprintf(buf, buflen, "%%%s%c", prec, op);
1382  break;
1383  }
1384 
1385  if (optional)
1386  {
1387  mutt_expando_format(buf, buflen, col, cols, if_str, index_format_str, data, flags);
1388  }
1389  else if (flags & MUTT_FORMAT_OPTIONAL)
1390  {
1391  mutt_expando_format(buf, buflen, col, cols, else_str, index_format_str, data, flags);
1392  }
1393 
1394  /* We return the format string, unchanged */
1395  return src;
1396 }
const char * mutt_addr_for_display(const struct Address *a)
Convert an Address for display purposes.
Definition: address.c:986
bool mutt_addr_is_user(const struct Address *addr)
Does the address belong to the user.
Definition: alias.c:574
int mutt_count_body_parts(struct Mailbox *m, struct Email *e, FILE *fp)
Count the MIME Body parts.
Definition: attachments.c:253
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
@ MT_COLOR_INDEX_AUTHOR
Index: author field (takes a pattern)
Definition: color.h:77
@ MT_COLOR_INDEX_SIZE
Index: size field.
Definition: color.h:86
@ MT_COLOR_INDEX_TAGS
Index: tags field (g, J)
Definition: color.h:87
@ MT_COLOR_INDEX_SUBJECT
Index: subject field (takes a pattern)
Definition: color.h:79
@ MT_COLOR_INDEX_DATE
Index: date field.
Definition: color.h:83
@ MT_COLOR_INDEX_TAG
Index: tag field (g, takes a pattern)
Definition: color.h:80
@ MT_COLOR_INDEX_LABEL
Index: label field.
Definition: color.h:84
@ MT_COLOR_INDEX
Index: default colour (takes a pattern)
Definition: color.h:76
@ MT_COLOR_INDEX_NUMBER
Index: index number.
Definition: color.h:85
@ MT_COLOR_INDEX_FLAGS
Index: flags field (takes a pattern)
Definition: color.h:78
@ MT_COLOR_INDEX_COLLAPSED
Index: number of messages in collapsed thread.
Definition: color.h:82
void mutt_format_s_x(char *buf, size_t buflen, const char *prec, const char *s, bool arboreal)
Format a string like snprintf()
Definition: curs_lib.c:805
struct tm mutt_date_localtime(time_t t)
Converts calendar time to a broken-down time structure expressed in user timezone.
Definition: date.c:654
struct tm mutt_date_gmtime(time_t t)
Converts calendar time to a broken-down time structure expressed in UTC timezone.
Definition: date.c:672
#define MUTT_DATE_NOW
Constant representing the 'current time', see: mutt_date_gmtime(), mutt_date_localtime()
Definition: date.h:39
size_t email_size(const struct Email *e)
Compute the size of an email.
Definition: email.c:125
#define MUTT_FORMAT_INDEX
This is a main index entry.
Definition: format_flags.h:36
#define MUTT_FORMAT_TREE
Draw the thread tree.
Definition: format_flags.h:32
#define MUTT_FORMAT_PLAIN
Do not prepend DISP_TO, DISP_CC ...
Definition: format_flags.h:38
static const char * index_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)
Format a string for the index list - Implements format_t -.
Definition: hdrline.c:441
void * mutt_hash_find(const struct HashTable *table, const char *strkey)
Find the HashElem data in a Hash Table element using a key.
Definition: hash.c:362
@ FLAG_CHAR_CRYPT_CONTAINS_KEY
Character denoting a message contains a PGP key.
Definition: hdrline.c:101
@ FLAG_CHAR_CRYPT_SIGNED
Character denoting a message is signed.
Definition: hdrline.c:100
@ FLAG_CHAR_CRYPT_NO_CRYPTO
Character denoting a message has no cryptography information.
Definition: hdrline.c:102
@ FLAG_CHAR_CRYPT_GOOD_SIGN
Character denoting a message signed with a verified key.
Definition: hdrline.c:98
@ FLAG_CHAR_CRYPT_ENCRYPTED
Character denoting a message is PGP-encrypted.
Definition: hdrline.c:99
static void make_from_addr(struct Envelope *env, char *buf, size_t buflen, bool do_lists)
Create a 'from' address for a reply email.
Definition: hdrline.c:279
static size_t add_index_color(char *buf, size_t buflen, MuttFormatFlags flags, char color)
Insert a color marker into a string.
Definition: hdrline.c:130
static const char * get_nth_wchar(const struct MbTable *table, int index)
Extract one char from a multi-byte table.
Definition: hdrline.c:167
static bool thread_is_old(struct Email *e)
Does the email thread contain any unread emails?
Definition: hdrline.c:379
static int user_is_recipient(struct Email *e)
Is the user a recipient of the message.
Definition: hdrline.c:329
static void make_from(struct Envelope *env, char *buf, size_t buflen, bool do_lists, MuttFormatFlags flags)
Generate a From: field (with optional prefix)
Definition: hdrline.c:223
static bool thread_is_new(struct Email *e)
Does the email thread contain any new emails?
Definition: hdrline.c:369
@ FLAG_CHAR_OLD
Character denoting an email that has been read.
Definition: hdrline.c:85
@ FLAG_CHAR_REPLIED
Character denoting an email that has been replied to.
Definition: hdrline.c:84
@ FLAG_CHAR_OLD_THREAD
Character denoting a thread of emails that has been read.
Definition: hdrline.c:87
@ FLAG_CHAR_ZEMPTY
Character denoting a read email, $index_format Z expando.
Definition: hdrline.c:90
@ FLAG_CHAR_TAGGED
Character denoting a tagged email.
Definition: hdrline.c:80
@ FLAG_CHAR_NEW
Character denoting an unread email.
Definition: hdrline.c:86
@ FLAG_CHAR_DELETED
Character denoting a deleted email.
Definition: hdrline.c:82
@ FLAG_CHAR_NEW_THREAD
Character denoting a thread containing at least one new email.
Definition: hdrline.c:88
@ FLAG_CHAR_DELETED_ATTACH
Character denoting a deleted attachment.
Definition: hdrline.c:83
@ FLAG_CHAR_SEMPTY
Character denoting a read email, $index_format S expando.
Definition: hdrline.c:89
@ FLAG_CHAR_IMPORTANT
Character denoting a important (flagged) email.
Definition: hdrline.c:81
struct MbTable * cs_subset_mbtable(const struct ConfigSubset *sub, const char *name)
Get a Multibyte table config item by name.
Definition: helpers.c:145
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
const char * mutt_idxfmt_hook(const char *name, struct Mailbox *m, struct Email *e)
Get index-format-hook format string.
Definition: hook.c:896
@ MUTT_NOTMUCH
'Notmuch' (virtual) Mailbox type
Definition: mailbox.h:54
bool check_for_mailing_list(struct AddressList *al, const char *pfx, char *buf, int buflen)
Search list of addresses for a mailing list.
Definition: maillist.c:78
bool check_for_mailing_list_addr(struct AddressList *al, char *buf, int buflen)
Check an address list for a mailing list.
Definition: maillist.c:102
bool first_mailing_list(char *buf, size_t buflen, struct AddressList *al)
Get the first mailing list in the list of addresses.
Definition: maillist.c:124
bool mutt_mb_get_initials(const char *name, char *buf, size_t buflen)
Turn a name into initials.
Definition: mbyte.c:82
#define FREE(x)
Definition: memory.h:40
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:727
char * mutt_strn_copy(char *dest, const char *src, size_t len, size_t dsize)
Copy a sub-string into a buffer.
Definition: string.c:339
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:560
struct HashTable * TagFormats
Hash Table of tag-formats (tag -> format string)
Definition: mutt_globals.h:59
int mutt_messages_in_thread(struct Mailbox *m, struct Email *e, enum MessageInThread mit)
Count the messages in a thread.
Definition: mutt_thread.c:1615
#define mutt_using_threads()
Definition: mutt_thread.h:100
@ MIT_NUM_MESSAGES
How many messages are in the thread.
Definition: mutt_thread.h:75
@ MIT_POSITION
Our position in the thread.
Definition: mutt_thread.h:76
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1192
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
Return a stream pointer for a message.
Definition: mx.c:1146
#define SEC_GOODSIGN
Email has a valid signature.
Definition: lib.h:77
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:87
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:75
#define PGP_KEY
Definition: lib.h:96
#define WithCrypto
Definition: lib.h:113
#define SEC_SIGN
Email is signed.
Definition: lib.h:76
char * nm_email_get_folder_rel_db(struct Mailbox *m, struct Email *e)
Get the folder for a Email from the same level as the notmuch database.
Definition: notmuch.c:1482
#define TAILQ_FIRST(head)
Definition: queue.h:723
const char * mutt_get_name(const struct Address *a)
Pick the best name to display from an address.
Definition: sort.c:136
An email address.
Definition: address.h:36
The envelope/body of an email.
Definition: email.h:37
bool read
Email is read.
Definition: email.h:48
unsigned int zminutes
Minutes away from UTC.
Definition: email.h:55
struct Envelope * env
Envelope information.
Definition: email.h:66
bool collapsed
Is this message part of a collapsed thread?
Definition: email.h:120
int lines
How many lines in the body of this message?
Definition: email.h:60
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition: email.h:41
struct Body * body
List of MIME parts.
Definition: email.h:67
char * tree
Character string to print thread tree.
Definition: email.h:124
bool old
Email is seen, but unread.
Definition: email.h:47
size_t num_hidden
Number of hidden messages in this view (only valid when collapsed is set)
Definition: email.h:122
bool zoccident
True, if west of UTC, False if east.
Definition: email.h:56
bool attach_del
Has an attachment marked for deletion.
Definition: email.h:99
bool flagged
Marked important?
Definition: email.h:45
unsigned int zhours
Hours away from UTC.
Definition: email.h:54
time_t date_sent
Time when the message was sent (UTC)
Definition: email.h:58
bool replied
Email has been replied to.
Definition: email.h:49
struct TagList tags
For drivers that support server tagging.
Definition: email.h:70
int score
Message score.
Definition: email.h:113
int msgno
Number displayed to the user.
Definition: email.h:111
bool deleted
Email is deleted.
Definition: email.h:76
bool tagged
Email is tagged.
Definition: email.h:107
time_t received
Time when the message was placed in the mailbox.
Definition: email.h:59
struct MuttThread * thread
Thread of Emails.
Definition: email.h:119
struct AddressList to
Email's 'To' list.
Definition: envelope.h:58
struct AddressList reply_to
Email's 'reply-to'.
Definition: envelope.h:62
char * message_id
Message ID.
Definition: envelope.h:71
char * x_comment_to
List of 'X-comment-to' fields.
Definition: envelope.h:80
char * newsgroups
List of newsgroups.
Definition: envelope.h:77
struct AddressList cc
Email's 'Cc' list.
Definition: envelope.h:59
struct Buffer spam
Spam header.
Definition: envelope.h:82
char * subject
Email's subject.
Definition: envelope.h:68
char * organization
Organisation header.
Definition: envelope.h:75
char * x_label
X-Label.
Definition: envelope.h:74
char * disp_subj
Display subject (modified copy of subject)
Definition: envelope.h:70
struct AddressList from
Email's 'From' list.
Definition: envelope.h:57
Data passed to index_format_str()
Definition: hdrline.c:68
struct Email * email
Current Email.
Definition: hdrline.c:71
int msg_in_pager
Index of Email displayed in the Pager.
Definition: hdrline.c:70
struct Mailbox * mailbox
Current Mailbox.
Definition: hdrline.c:69
const char * pager_progress
String representing Pager postiion through Email.
Definition: hdrline.c:72
int msg_count
Total number of messages.
Definition: mailbox.h:91
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
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
A local copy of an email.
Definition: mxapi.h:42
FILE * fp
pointer to the message data
Definition: mxapi.h:43
struct Message::@0 flags
Flags for the Message.
struct MuttThread * parent
Parent of this Thread.
Definition: thread.h:45
struct MuttThread * prev
Previous sibling Thread.
Definition: thread.h:48
struct Email * message
Email this Thread refers to.
Definition: thread.h:49
bool subjrx_apply_mods(struct Envelope *env)
Apply regex modifications to the subject.
Definition: subjectrx.c:128
char * driver_tags_get_transformed_for(struct TagList *head, const char *name)
Get transformed tag for a tag name from a header.
Definition: tags.c:171
char * driver_tags_get_transformed(struct TagList *list)
Get transformed tags.
Definition: tags.c:132
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ history_format_str()

static const char* history_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 
)
static

Format a string for the history list - Implements format_t -.

Expando Description
%s History match

Definition at line 88 of file dlghistory.c.

92 {
93  char *match = (char *) data;
94 
95  switch (op)
96  {
97  case 's':
98  mutt_format_s(buf, buflen, prec, match);
99  break;
100  }
101 
102  return src;
103 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_expando_format()

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 -.

Parameters
[out]bufBuffer in which to save string
[in]buflenBuffer length
[in]colStarting column
[in]colsNumber of screen columns
[in]srcPrintf-like format string
[in]callbackCallback - Implements format_t
[in]dataCallback data
[in]flagsCallback flags

Definition at line 780 of file muttlib.c.

782 {
783  char prefix[128], tmp[1024];
784  char *cp = NULL, *wptr = buf;
785  char ch;
786  char if_str[128], else_str[128];
787  size_t wlen, count, len, wid;
788  FILE *fp_filter = NULL;
789  char *recycler = NULL;
790 
791  char src2[256];
792  mutt_str_copy(src2, src, mutt_str_len(src) + 1);
793  src = src2;
794 
795  const bool c_arrow_cursor = cs_subset_bool(NeoMutt->sub, "arrow_cursor");
796  const char *const c_arrow_string =
797  cs_subset_string(NeoMutt->sub, "arrow_string");
798 
799  prefix[0] = '\0';
800  buflen--; /* save room for the terminal \0 */
801  wlen = ((flags & MUTT_FORMAT_ARROWCURSOR) && c_arrow_cursor) ?
802  mutt_strwidth(c_arrow_string) + 1 :
803  0;
804  col += wlen;
805 
806  if ((flags & MUTT_FORMAT_NOFILTER) == 0)
807  {
808  int off = -1;
809 
810  /* Do not consider filters if no pipe at end */
811  int n = mutt_str_len(src);
812  if ((n > 1) && (src[n - 1] == '|'))
813  {
814  /* Scan backwards for backslashes */
815  off = n;
816  while ((off > 0) && (src[off - 2] == '\\'))
817  off--;
818  }
819 
820  /* If number of backslashes is even, the pipe is real. */
821  /* n-off is the number of backslashes. */
822  if ((off > 0) && (((n - off) % 2) == 0))
823  {
824  char srccopy[1024];
825  int i = 0;
826 
827  mutt_debug(LL_DEBUG3, "fmtpipe = %s\n", src);
828 
829  strncpy(srccopy, src, n);
830  srccopy[n - 1] = '\0';
831 
832  /* prepare Buffers */
833  struct Buffer srcbuf = mutt_buffer_make(0);
834  mutt_buffer_addstr(&srcbuf, srccopy);
835  /* note: we are resetting dptr and *reading* from the buffer, so we don't
836  * want to use mutt_buffer_reset(). */
837  mutt_buffer_seek(&srcbuf, 0);
838  struct Buffer word = mutt_buffer_make(0);
839  struct Buffer cmd = mutt_buffer_make(0);
840 
841  /* Iterate expansions across successive arguments */
842  do
843  {
844  /* Extract the command name and copy to command line */
845  mutt_debug(LL_DEBUG3, "fmtpipe +++: %s\n", srcbuf.dptr);
846  if (word.data)
847  *word.data = '\0';
848  mutt_extract_token(&word, &srcbuf, MUTT_TOKEN_NO_FLAGS);
849  mutt_debug(LL_DEBUG3, "fmtpipe %2d: %s\n", i++, word.data);
850  mutt_buffer_addch(&cmd, '\'');
851  mutt_expando_format(tmp, sizeof(tmp), 0, cols, word.data, callback,
852  data, flags | MUTT_FORMAT_NOFILTER);
853  for (char *p = tmp; p && (*p != '\0'); p++)
854  {
855  if (*p == '\'')
856  {
857  /* shell quoting doesn't permit escaping a single quote within
858  * single-quoted material. double-quoting instead will lead
859  * shell variable expansions, so break out of the single-quoted
860  * span, insert a double-quoted single quote, and resume. */
861  mutt_buffer_addstr(&cmd, "'\"'\"'");
862  }
863  else
864  mutt_buffer_addch(&cmd, *p);
865  }
866  mutt_buffer_addch(&cmd, '\'');
867  mutt_buffer_addch(&cmd, ' ');
868  } while (MoreArgs(&srcbuf));
869 
870  mutt_debug(LL_DEBUG3, "fmtpipe > %s\n", cmd.data);
871 
872  col -= wlen; /* reset to passed in value */
873  wptr = buf; /* reset write ptr */
874  pid_t pid = filter_create(cmd.data, NULL, &fp_filter, NULL);
875  if (pid != -1)
876  {
877  int rc;
878 
879  n = fread(buf, 1, buflen /* already decremented */, fp_filter);
880  mutt_file_fclose(&fp_filter);
881  rc = filter_wait(pid);
882  if (rc != 0)
883  mutt_debug(LL_DEBUG1, "format pipe cmd exited code %d\n", rc);
884  if (n > 0)
885  {
886  buf[n] = '\0';
887  while ((n > 0) && ((buf[n - 1] == '\n') || (buf[n - 1] == '\r')))
888  buf[--n] = '\0';
889  mutt_debug(LL_DEBUG5, "fmtpipe < %s\n", buf);
890 
891  /* If the result ends with '%', this indicates that the filter
892  * generated %-tokens that neomutt can expand. Eliminate the '%'
893  * marker and recycle the string through mutt_expando_format().
894  * To literally end with "%", use "%%". */
895  if ((n > 0) && (buf[n - 1] == '%'))
896  {
897  n--;
898  buf[n] = '\0'; /* remove '%' */
899  if ((n > 0) && (buf[n - 1] != '%'))
900  {
901  recycler = mutt_str_dup(buf);
902  if (recycler)
903  {
904  /* buflen is decremented at the start of this function
905  * to save space for the terminal nul char. We can add
906  * it back for the recursive call since the expansion of
907  * format pipes does not try to append a nul itself. */
908  mutt_expando_format(buf, buflen + 1, col, cols, recycler,
909  callback, data, flags);
910  FREE(&recycler);
911  }
912  }
913  }
914  }
915  else
916  {
917  /* read error */
918  mutt_debug(LL_DEBUG1, "error reading from fmtpipe: %s (errno=%d)\n",
919  strerror(errno), errno);
920  *wptr = '\0';
921  }
922  }
923  else
924  {
925  /* Filter failed; erase write buffer */
926  *wptr = '\0';
927  }
928 
929  mutt_buffer_dealloc(&cmd);
930  mutt_buffer_dealloc(&srcbuf);
931  mutt_buffer_dealloc(&word);
932  return;
933  }
934  }
935 
936  while (*src && (wlen < buflen))
937  {
938  if (*src == '%')
939  {
940  if (*++src == '%')
941  {
942  *wptr++ = '%';
943  wlen++;
944  col++;
945  src++;
946  continue;
947  }
948 
949  if (*src == '?')
950  {
951  /* change original %? to new %< notation */
952  /* %?x?y&z? to %<x?y&z> where y and z are nestable */
953  char *p = (char *) src;
954  *p = '<';
955  /* skip over "x" */
956  for (; *p && (*p != '?'); p++)
957  ; // do nothing
958 
959  /* nothing */
960  if (*p == '?')
961  p++;
962  /* fix up the "y&z" section */
963  for (; *p && (*p != '?'); p++)
964  {
965  /* escape '<' and '>' to work inside nested-if */
966  if ((*p == '<') || (*p == '>'))
967  {
968  memmove(p + 2, p, mutt_str_len(p) + 1);
969  *p++ = '\\';
970  *p++ = '\\';
971  }
972  }
973  if (*p == '?')
974  *p = '>';
975  }
976 
977  if (*src == '<')
978  {
979  flags |= MUTT_FORMAT_OPTIONAL;
980  ch = *(++src); /* save the character to switch on */
981  src++;
982  cp = prefix;
983  count = 0;
984  while ((count < (sizeof(prefix) - 1)) && (*src != '\0') && (*src != '?'))
985  {
986  *cp++ = *src++;
987  count++;
988  }
989  *cp = '\0';
990  }
991  else
992  {
993  flags &= ~MUTT_FORMAT_OPTIONAL;
994 
995  /* eat the format string */
996  cp = prefix;
997  count = 0;
998  while ((count < (sizeof(prefix) - 1)) && strchr("0123456789.-=", *src))
999  {
1000  *cp++ = *src++;
1001  count++;
1002  }
1003  *cp = '\0';
1004 
1005  if (*src == '\0')
1006  break; /* bad format */
1007 
1008  ch = *src++; /* save the character to switch on */
1009  }
1010 
1011  if (flags & MUTT_FORMAT_OPTIONAL)
1012  {
1013  int lrbalance;
1014 
1015  if (*src != '?')
1016  break; /* bad format */
1017  src++;
1018 
1019  /* eat the 'if' part of the string */
1020  cp = if_str;
1021  count = 0;
1022  lrbalance = 1;
1023  while ((lrbalance > 0) && (count < sizeof(if_str)) && *src)
1024  {
1025  if ((src[0] == '%') && (src[1] == '>'))
1026  {
1027  /* This is a padding expando; copy two chars and carry on */
1028  *cp++ = *src++;
1029  *cp++ = *src++;
1030  count += 2;
1031  continue;
1032  }
1033 
1034  if (*src == '\\')
1035  {
1036  src++;
1037  *cp++ = *src++;
1038  }
1039  else if ((src[0] == '%') && (src[1] == '<'))
1040  {
1041  lrbalance++;
1042  }
1043  else if (src[0] == '>')
1044  {
1045  lrbalance--;
1046  }
1047  if (lrbalance == 0)
1048  break;
1049  if ((lrbalance == 1) && (src[0] == '&'))
1050  break;
1051  *cp++ = *src++;
1052  count++;
1053  }
1054  *cp = '\0';
1055 
1056  /* eat the 'else' part of the string (optional) */
1057  if (*src == '&')
1058  src++; /* skip the & */
1059  cp = else_str;
1060  count = 0;
1061  while ((lrbalance > 0) && (count < sizeof(else_str)) && (*src != '\0'))
1062  {
1063  if ((src[0] == '%') && (src[1] == '>'))
1064  {
1065  /* This is a padding expando; copy two chars and carry on */
1066  *cp++ = *src++;
1067  *cp++ = *src++;
1068  count += 2;
1069  continue;
1070  }
1071 
1072  if (*src == '\\')
1073  {
1074  src++;
1075  *cp++ = *src++;
1076  }
1077  else if ((src[0] == '%') && (src[1] == '<'))
1078  {
1079  lrbalance++;
1080  }
1081  else if (src[0] == '>')
1082  {
1083  lrbalance--;
1084  }
1085  if (lrbalance == 0)
1086  break;
1087  if ((lrbalance == 1) && (src[0] == '&'))
1088  break;
1089  *cp++ = *src++;
1090  count++;
1091  }
1092  *cp = '\0';
1093 
1094  if ((*src == '\0'))
1095  break; /* bad format */
1096 
1097  src++; /* move past the trailing '>' (formerly '?') */
1098  }
1099 
1100  /* handle generic cases first */
1101  if ((ch == '>') || (ch == '*'))
1102  {
1103  /* %>X: right justify to EOL, left takes precedence
1104  * %*X: right justify to EOL, right takes precedence */
1105  int soft = ch == '*';
1106  int pl, pw;
1107  pl = mutt_mb_charlen(src, &pw);
1108  if (pl <= 0)
1109  {
1110  pl = 1;
1111  pw = 1;
1112  }
1113 
1114  /* see if there's room to add content, else ignore */
1115  if (((col < cols) && (wlen < buflen)) || soft)
1116  {
1117  int pad;
1118 
1119  /* get contents after padding */
1120  mutt_expando_format(tmp, sizeof(tmp), 0, cols, src + pl, callback, data, flags);
1121  len = mutt_str_len(tmp);
1122  wid = mutt_strwidth(tmp);
1123 
1124  pad = (cols - col - wid) / pw;
1125  if (pad >= 0)
1126  {
1127  /* try to consume as many columns as we can, if we don't have
1128  * memory for that, use as much memory as possible */
1129  if (wlen + (pad * pl) + len > buflen)
1130  pad = (buflen > (wlen + len)) ? ((buflen - wlen - len) / pl) : 0;
1131  else
1132  {
1133  /* Add pre-spacing to make multi-column pad characters and
1134  * the contents after padding line up */
1135  while (((col + (pad * pw) + wid) < cols) && ((wlen + (pad * pl) + len) < buflen))
1136  {
1137  *wptr++ = ' ';
1138  wlen++;
1139  col++;
1140  }
1141  }
1142  while (pad-- > 0)
1143  {
1144  memcpy(wptr, src, pl);
1145  wptr += pl;
1146  wlen += pl;
1147  col += pw;
1148  }
1149  }
1150  else if (soft)
1151  {
1152  int offset = ((flags & MUTT_FORMAT_ARROWCURSOR) && c_arrow_cursor) ?
1153  mutt_strwidth(c_arrow_string) + 1 :
1154  0;
1155  int avail_cols = (cols > offset) ? (cols - offset) : 0;
1156  /* \0-terminate buf for length computation in mutt_wstr_trunc() */
1157  *wptr = '\0';
1158  /* make sure right part is at most as wide as display */
1159  len = mutt_wstr_trunc(tmp, buflen, avail_cols, &wid);
1160  /* truncate left so that right part fits completely in */
1161  wlen = mutt_wstr_trunc(buf, buflen - len, avail_cols - wid, &col);
1162  wptr = buf + wlen;
1163  /* Multi-column characters may be truncated in the middle.
1164  * Add spacing so the right hand side lines up. */
1165  while (((col + wid) < avail_cols) && ((wlen + len) < buflen))
1166  {
1167  *wptr++ = ' ';
1168  wlen++;
1169  col++;
1170  }
1171  }
1172  if ((len + wlen) > buflen)
1173  len = mutt_wstr_trunc(tmp, buflen - wlen, cols - col, NULL);
1174  memcpy(wptr, tmp, len);
1175  wptr += len;
1176  }
1177  break; /* skip rest of input */
1178  }
1179  else if (ch == '|')
1180  {
1181  /* pad to EOL */
1182  int pl, pw;
1183  pl = mutt_mb_charlen(src, &pw);
1184  if (pl <= 0)
1185  {
1186  pl = 1;
1187  pw = 1;
1188  }
1189 
1190  /* see if there's room to add content, else ignore */
1191  if ((col < cols) && (wlen < buflen))
1192  {
1193  int c = (cols - col) / pw;
1194  if ((c > 0) && ((wlen + (c * pl)) > buflen))
1195  c = ((signed) (buflen - wlen)) / pl;
1196  while (c > 0)
1197  {
1198  memcpy(wptr, src, pl);
1199  wptr += pl;
1200  wlen += pl;
1201  col += pw;
1202  c--;
1203  }
1204  }
1205  break; /* skip rest of input */
1206  }
1207  else
1208  {
1209  bool to_lower = false;
1210  bool no_dots = false;
1211 
1212  while ((ch == '_') || (ch == ':'))
1213  {
1214  if (ch == '_')
1215  to_lower = true;
1216  else if (ch == ':')
1217  no_dots = true;
1218 
1219  ch = *src++;
1220  }
1221 
1222  /* use callback function to handle this case */
1223  *tmp = '\0';
1224  src = callback(tmp, sizeof(tmp), col, cols, ch, src, prefix, if_str,
1225  else_str, data, flags);
1226 
1227  if (to_lower)
1228  mutt_str_lower(tmp);
1229  if (no_dots)
1230  {
1231  char *p = tmp;
1232  for (; *p; p++)
1233  if (*p == '.')
1234  *p = '_';
1235  }
1236 
1237  len = mutt_str_len(tmp);
1238  if ((len + wlen) > buflen)
1239  len = mutt_wstr_trunc(tmp, buflen - wlen, cols - col, NULL);
1240 
1241  memcpy(wptr, tmp, len);
1242  wptr += len;
1243  wlen += len;
1244  col += mutt_strwidth(tmp);
1245  }
1246  }
1247  else if (*src == '\\')
1248  {
1249  if (!*++src)
1250  break;
1251  switch (*src)
1252  {
1253  case 'f':
1254  *wptr = '\f';
1255  break;
1256  case 'n':
1257  *wptr = '\n';
1258  break;
1259  case 'r':
1260  *wptr = '\r';
1261  break;
1262  case 't':
1263  *wptr = '\t';
1264  break;
1265  case 'v':
1266  *wptr = '\v';
1267  break;
1268  default:
1269  *wptr = *src;
1270  break;
1271  }
1272  src++;
1273  wptr++;
1274  wlen++;
1275  col++;
1276  }
1277  else
1278  {
1279  int bytes, width;
1280  /* in case of error, simply copy byte */
1281  bytes = mutt_mb_charlen(src, &width);
1282  if (bytes < 0)
1283  {
1284  bytes = 1;
1285  width = 1;
1286  }
1287  if ((bytes > 0) && ((wlen + bytes) < buflen))
1288  {
1289  memcpy(wptr, src, bytes);
1290  wptr += bytes;
1291  src += bytes;
1292  wlen += bytes;
1293  col += width;
1294  }
1295  else
1296  {
1297  src += buflen - wlen;
1298  wlen = buflen;
1299  }
1300  }
1301  }
1302  *wptr = '\0';
1303 }
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
void mutt_buffer_seek(struct Buffer *buf, size_t offset)
Set current read/write position to offset from beginning.
Definition: buffer.c:468
#define MoreArgs(buf)
Definition: buffer.h:40
size_t mutt_wstr_trunc(const char *src, size_t maxlen, size_t maxwid, size_t *width)
Work out how to truncate a widechar string.
Definition: curs_lib.c:907
int mutt_strwidth(const char *s)
Measure a string's width in screen cells.
Definition: curs_lib.c:956
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:206
#define MUTT_FORMAT_NOFILTER
Do not allow filtering on this pass.
Definition: format_flags.h:37
static int pad(FILE *fp, int col, int i)
Write some padding to a file.
Definition: help.c:198
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:399
@ LL_DEBUG3
Log at debug level 3.
Definition: logging.h:42
@ LL_DEBUG5
Log at debug level 5.
Definition: logging.h:44
int mutt_mb_charlen(const char *s, int *width)
Count the bytes in a (multibyte) character.
Definition: mbyte.c:54
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:181
char * mutt_str_lower(char *str)
Convert all characters in the string to lowercase.
Definition: string.c:315
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:475
#define MUTT_TOKEN_NO_FLAGS
No flags are set.
Definition: mutt.h:66
char * dptr
Current read/write position.
Definition: buffer.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_format_str()

static const char* crypt_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 
)
static

Format a string for the key selection menu - Implements format_t -.

Expando Description
%n Number
%p Protocol
%t Trust/validity of the key-uid association
%u User id
%[fmt] Date of key using strftime(3)

| | | %a | Algorithm | %c | Capabilities | %f | Flags | %k | Key id | %l | Length | | | %A | Algorithm of the principal key | %C | Capabilities of the principal key | %F | Flags of the principal key | %K | Key id of the principal key | %L | Length of the principal key

Definition at line 1018 of file dlggpgme.c.

1022 {
1023  char fmt[128];
1024  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
1025 
1026  struct CryptEntry *entry = (struct CryptEntry *) data;
1027  struct CryptKeyInfo *key = entry->key;
1028 
1029  /* if (isupper ((unsigned char) op)) */
1030  /* key = pkey; */
1031 
1032  KeyFlags kflags = (key->flags /* | (pkey->flags & KEYFLAG_RESTRICTIONS)
1033  | uid->flags */);
1034 
1035  switch (tolower(op))
1036  {
1037  case 'a':
1038  if (!optional)
1039  {
1040  const char *s = NULL;
1041  snprintf(fmt, sizeof(fmt), "%%%s.3s", prec);
1042  if (key->kobj->subkeys)
1043  s = gpgme_pubkey_algo_name(key->kobj->subkeys->pubkey_algo);
1044  else
1045  s = "?";
1046  snprintf(buf, buflen, fmt, s);
1047  }
1048  break;
1049 
1050  case 'c':
1051  if (!optional)
1052  {
1053  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
1054  snprintf(buf, buflen, fmt, crypt_key_abilities(kflags));
1055  }
1056  else if (!(kflags & KEYFLAG_ABILITIES))
1057  optional = false;
1058  break;
1059 
1060  case 'f':
1061  if (!optional)
1062  {
1063  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
1064  snprintf(buf, buflen, fmt, crypt_flags(kflags));
1065  }
1066  else if (!(kflags & KEYFLAG_RESTRICTIONS))
1067  optional = false;
1068  break;
1069 
1070  case 'k':
1071  if (!optional)
1072  {
1073  /* fixme: we need a way to distinguish between main and subkeys.
1074  * Store the idx in entry? */
1075  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
1076  snprintf(buf, buflen, fmt, crypt_keyid(key));
1077  }
1078  break;
1079 
1080  case 'l':
1081  if (!optional)
1082  {
1083  snprintf(fmt, sizeof(fmt), "%%%slu", prec);
1084  unsigned long val;
1085  if (key->kobj->subkeys)
1086  val = key->kobj->subkeys->length;
1087  else
1088  val = 0;
1089  snprintf(buf, buflen, fmt, val);
1090  }
1091  break;
1092 
1093  case 'n':
1094  if (!optional)
1095  {
1096  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
1097  snprintf(buf, buflen, fmt, entry->num);
1098  }
1099  break;
1100 
1101  case 'p':
1102  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
1103  snprintf(buf, buflen, fmt, gpgme_get_protocol_name(key->kobj->protocol));
1104  break;
1105 
1106  case 't':
1107  {
1108  char *s = NULL;
1109  if ((kflags & KEYFLAG_ISX509))
1110  s = "x";
1111  else
1112  {
1113  switch (key->validity)
1114  {
1115  case GPGME_VALIDITY_FULL:
1116  s = "f";
1117  break;
1118  case GPGME_VALIDITY_MARGINAL:
1119  s = "m";
1120  break;
1121  case GPGME_VALIDITY_NEVER:
1122  s = "n";
1123  break;
1124  case GPGME_VALIDITY_ULTIMATE:
1125  s = "u";
1126  break;
1127  case GPGME_VALIDITY_UNDEFINED:
1128  s = "q";
1129  break;
1130  case GPGME_VALIDITY_UNKNOWN:
1131  default:
1132  s = "?";
1133  break;
1134  }
1135  }
1136  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
1137  snprintf(buf, buflen, fmt, *s);
1138  break;
1139  }
1140 
1141  case 'u':
1142  if (!optional)
1143  {
1144  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
1145  snprintf(buf, buflen, fmt, key->uid);
1146  }
1147  break;
1148 
1149  case '[':
1150  {
1151  char buf2[128];
1152  bool do_locales = true;
1153  struct tm tm = { 0 };
1154 
1155  char *p = buf;
1156 
1157  const char *cp = src;
1158  if (*cp == '!')
1159  {
1160  do_locales = false;
1161  cp++;
1162  }
1163 
1164  size_t len = buflen - 1;
1165  while ((len > 0) && (*cp != ']'))
1166  {
1167  if (*cp == '%')
1168  {
1169  cp++;
1170  if (len >= 2)
1171  {
1172  *p++ = '%';
1173  *p++ = *cp;
1174  len -= 2;
1175  }
1176  else
1177  break; /* not enough space */
1178  cp++;
1179  }
1180  else
1181  {
1182  *p++ = *cp++;
1183  len--;
1184  }
1185  }
1186  *p = '\0';
1187 
1188  if (key->kobj->subkeys && (key->kobj->subkeys->timestamp > 0))
1189  tm = mutt_date_localtime(key->kobj->subkeys->timestamp);
1190  else
1191  tm = mutt_date_localtime(0); // Default to 1970-01-01
1192 
1193  if (!do_locales)
1194  setlocale(LC_TIME, "C");
1195  strftime(buf2, sizeof(buf2), buf, &tm);
1196  if (!do_locales)
1197  setlocale(LC_TIME, "");
1198 
1199  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
1200  snprintf(buf, buflen, fmt, buf2);
1201  if (len > 0)
1202  src = cp + 1;
1203  break;
1204  }
1205 
1206  default:
1207  *buf = '\0';
1208  }
1209 
1210  if (optional)
1211  {
1212  mutt_expando_format(buf, buflen, col, cols, if_str, crypt_format_str, data,
1214  }
1215  else if (flags & MUTT_FORMAT_OPTIONAL)
1216  {
1217  mutt_expando_format(buf, buflen, col, cols, else_str, crypt_format_str,
1218  data, MUTT_FORMAT_NO_FLAGS);
1219  }
1220 
1221  /* We return the format string, unchanged */
1222  return src;
1223 }
const char * crypt_keyid(struct CryptKeyInfo *k)
Find the ID for the key.
Definition: crypt_gpgme.c:349
static char crypt_flags(KeyFlags flags)
Parse the key flags into a single character.
Definition: dlggpgme.c:981
static char * crypt_key_abilities(KeyFlags flags)
Parse key flags into a string.
Definition: dlggpgme.c:951
static const char * crypt_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)
Format a string for the key selection menu - Implements format_t -.
Definition: dlggpgme.c:1018
#define KEYFLAG_ISX509
Key is an X.509 key.
Definition: lib.h:126
uint16_t KeyFlags
Flags describing PGP/SMIME keys, e.g. KEYFLAG_CANSIGN.
Definition: lib.h:122
#define KEYFLAG_RESTRICTIONS
Definition: lib.h:137
#define KEYFLAG_ABILITIES
Definition: lib.h:139
An entry in the Select-Key menu.
Definition: dlggpgme.c:115
struct CryptKeyInfo * key
Key.
Definition: dlggpgme.c:117
size_t num
Index number.
Definition: dlggpgme.c:116
A stored PGP key.
Definition: crypt_gpgme.h:44
gpgme_validity_t validity
uid validity (cached for convenience)
Definition: crypt_gpgme.h:50
KeyFlags flags
global and per uid flags (for convenience)
Definition: crypt_gpgme.h:49
const char * uid
and for convenience point to this user ID
Definition: crypt_gpgme.h:48
gpgme_key_t kobj
Definition: crypt_gpgme.h:46
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_entry_format_str()

static const char* pgp_entry_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 
)
static

Format an entry on the PGP key selection menu - Implements format_t -.

Expando Description
%n Number
%t Trust/validity of the key-uid association
%u User id
%[fmt] Date of key using strftime(3)

| | | %a | Algorithm | %c | Capabilities | %f | Flags | %k | Key id | %l | Length | | | %A | Algorithm of the principal key | %C | Capabilities of the principal key | %F | Flags of the principal key | %K | Key id of the principal key | %L | Length of the principal key

Definition at line 341 of file dlgpgp.c.

345 {
346  char fmt[128];
347  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
348 
349  struct PgpEntry *entry = (struct PgpEntry *) data;
350  struct PgpUid *uid = entry->uid;
351  struct PgpKeyInfo *key = uid->parent;
352  struct PgpKeyInfo *pkey = pgp_principal_key(key);
353 
354  if (isupper((unsigned char) op))
355  key = pkey;
356 
357  KeyFlags kflags = key->flags | (pkey->flags & KEYFLAG_RESTRICTIONS) | uid->flags;
358 
359  switch (tolower(op))
360  {
361  case 'a':
362  if (!optional)
363  {
364  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
365  snprintf(buf, buflen, fmt, key->algorithm);
366  }
367  break;
368  case 'c':
369  if (!optional)
370  {
371  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
372  snprintf(buf, buflen, fmt, pgp_key_abilities(kflags));
373  }
374  else if (!(kflags & KEYFLAG_ABILITIES))
375  optional = false;
376  break;
377  case 'f':
378  if (!optional)
379  {
380  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
381  snprintf(buf, buflen, fmt, pgp_flags(kflags));
382  }
383  else if (!(kflags & KEYFLAG_RESTRICTIONS))
384  optional = false;
385  break;
386  case 'k':
387  if (!optional)
388  {
389  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
390  snprintf(buf, buflen, fmt, pgp_this_keyid(key));
391  }
392  break;
393  case 'l':
394  if (!optional)
395  {
396  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
397  snprintf(buf, buflen, fmt, key->keylen);
398  }
399  break;
400  case 'n':
401  if (!optional)
402  {
403  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
404  snprintf(buf, buflen, fmt, entry->num);
405  }
406  break;
407  case 't':
408  if (!optional)
409  {
410  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
411  snprintf(buf, buflen, fmt, trust_flags[uid->trust & 0x03]);
412  }
413  else if (!(uid->trust & 0x03))
414  {
415  /* undefined trust */
416  optional = false;
417  }
418  break;
419  case 'u':
420  if (!optional)
421  {
422  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
423  snprintf(buf, buflen, fmt, NONULL(uid->addr));
424  }
425  break;
426  case '[':
427 
428  {
429  char buf2[128];
430  bool do_locales = true;
431  size_t len;
432 
433  char *p = buf;
434 
435  const char *cp = src;
436  if (*cp == '!')
437  {
438  do_locales = false;
439  cp++;
440  }
441 
442  len = buflen - 1;
443  while ((len > 0) && (*cp != ']'))
444  {
445  if (*cp == '%')
446  {
447  cp++;
448  if (len >= 2)
449  {
450  *p++ = '%';
451  *p++ = *cp;
452  len -= 2;
453  }
454  else
455  break; /* not enough space */
456  cp++;
457  }
458  else
459  {
460  *p++ = *cp++;
461  len--;
462  }
463  }
464  *p = '\0';
465 
466  if (!do_locales)
467  setlocale(LC_TIME, "C");
468  mutt_date_localtime_format(buf2, sizeof(buf2), buf, key->gen_time);
469  if (!do_locales)
470  setlocale(LC_TIME, "");
471 
472  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
473  snprintf(buf, buflen, fmt, buf2);
474  if (len > 0)
475  src = cp + 1;
476  break;
477  }
478  default:
479  *buf = '\0';
480  }
481 
482  if (optional)
483  {
484  mutt_expando_format(buf, buflen, col, cols, if_str, pgp_entry_format_str,
485  data, MUTT_FORMAT_NO_FLAGS);
486  }
487  else if (flags & MUTT_FORMAT_OPTIONAL)
488  {
489  mutt_expando_format(buf, buflen, col, cols, else_str, pgp_entry_format_str,
490  data, MUTT_FORMAT_NO_FLAGS);
491  }
492 
493  /* We return the format string, unchanged */
494  return src;
495 }
static const char trust_flags[]
Definition: dlgpgp.c:115
static char pgp_flags(KeyFlags flags)
Turn PGP key flags into a string.
Definition: dlgpgp.c:305
static char * pgp_key_abilities(KeyFlags flags)
Turn PGP key abilities into a string.
Definition: dlgpgp.c:277
static const char * pgp_entry_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)
Format an entry on the PGP key selection menu - Implements format_t -.
Definition: dlgpgp.c:341
char * pgp_this_keyid(struct PgpKeyInfo *k)
Get the ID of this key.
Definition: pgp.c:189
struct PgpKeyInfo * pgp_principal_key(struct PgpKeyInfo *key)
Get the main (parent) PGP key.
Definition: pgpkey.c:89
An entry in a PGP key menu.
Definition: dlgpgp.c:110
struct PgpUid * uid
Definition: dlgpgp.c:112
size_t num
Index number.
Definition: dlgpgp.c:111
Information about a PGP key.
Definition: pgplib.h:47
KeyFlags flags
Definition: pgplib.h:51
short keylen
Definition: pgplib.h:52
time_t gen_time
Definition: pgplib.h:53
const char * algorithm
Definition: pgplib.h:55
PGP User ID.
Definition: pgplib.h:35
short trust
Definition: pgplib.h:37
struct PgpKeyInfo * parent
Parent key.
Definition: pgplib.h:39
int flags
Definition: pgplib.h:38
char * addr
Definition: pgplib.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_command_format_str()

static const char* pgp_command_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 
)
static

Format a PGP command string - Implements format_t -.

Expando Description
%a Value of $pgp_sign_as if set, otherwise $pgp_default_key
%f File containing a message
%p Expands to PGPPASSFD=0 when a pass phrase is needed, to an empty string otherwise
%r One or more key IDs (or fingerprints if available)
%s File containing the signature part of a multipart/signed attachment when verifying it

Definition at line 78 of file pgpinvoke.c.

82 {
83  char fmt[128];
84  struct PgpCommandContext *cctx = (struct PgpCommandContext *) data;
85  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
86 
87  switch (op)
88  {
89  case 'a':
90  {
91  if (!optional)
92  {
93  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
94  snprintf(buf, buflen, fmt, NONULL(cctx->signas));
95  }
96  else if (!cctx->signas)
97  optional = false;
98  break;
99  }
100  case 'f':
101  {
102  if (!optional)
103  {
104  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
105  snprintf(buf, buflen, fmt, NONULL(cctx->fname));
106  }
107  else if (!cctx->fname)
108  optional = false;
109  break;
110  }
111  case 'p':
112  {
113  if (!optional)
114  {
115  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
116  snprintf(buf, buflen, fmt, cctx->need_passphrase ? "PGPPASSFD=0" : "");
117  }
118  else if (!cctx->need_passphrase || pgp_use_gpg_agent())
119  optional = false;
120  break;
121  }
122  case 'r':
123  {
124  if (!optional)
125  {
126  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
127  snprintf(buf, buflen, fmt, NONULL(cctx->ids));
128  }
129  else if (!cctx->ids)
130  optional = false;
131  break;
132  }
133  case 's':
134  {
135  if (!optional)
136  {
137  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
138  snprintf(buf, buflen, fmt, NONULL(cctx->sig_fname));
139  }
140  else if (!cctx->sig_fname)
141  optional = false;
142  break;
143  }
144  default:
145  {
146  *buf = '\0';
147  break;
148  }
149  }
150 
151  if (optional)
152  {
153  mutt_expando_format(buf, buflen, col, cols, if_str, pgp_command_format_str,
154  data, MUTT_FORMAT_NO_FLAGS);
155  }
156  else if (flags & MUTT_FORMAT_OPTIONAL)
157  {
158  mutt_expando_format(buf, buflen, col, cols, else_str,
160  }
161 
162  /* We return the format string, unchanged */
163  return src;
164 }
static const char * pgp_command_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)
Format a PGP command string - Implements format_t -.
Definition: pgpinvoke.c:78
bool pgp_use_gpg_agent(void)
Does the user want to use the gpg agent?
Definition: pgp.c:123
Data for a PGP command.
Definition: pgpinvoke.c:59
bool need_passphrase
p
Definition: pgpinvoke.c:60
const char * signas
a
Definition: pgpinvoke.c:63
const char * fname
f
Definition: pgpinvoke.c:61
const char * ids
r
Definition: pgpinvoke.c:64
const char * sig_fname
s
Definition: pgpinvoke.c:62
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ smime_command_format_str()

static const char* smime_command_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 
)
static

Format an SMIME command - Implements format_t -.

Expando Description
%a Algorithm used for encryption
%C CA location: Depending on whether $smime_ca_location points to a directory or file
%c One or more certificate IDs
%d Message digest algorithm specified with $smime_sign_digest_alg
%f File containing a message
%i Intermediate certificates
%k The key-pair specified with $smime_default_key
%s File containing the signature part of a multipart/signed attachment when verifying it

Definition at line 216 of file smime.c.

221 {
222  char fmt[128];
223  struct SmimeCommandContext *cctx = (struct SmimeCommandContext *) data;
224  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
225 
226  switch (op)
227  {
228  case 'C':
229  {
230  const char *const c_smime_ca_location =
231  cs_subset_path(NeoMutt->sub, "smime_ca_location");
232  if (!optional)
233  {
234  struct Buffer *path = mutt_buffer_pool_get();
235  struct Buffer *buf1 = mutt_buffer_pool_get();
236  struct Buffer *buf2 = mutt_buffer_pool_get();
237  struct stat st = { 0 };
238 
239  mutt_buffer_strcpy(path, c_smime_ca_location);
242 
243  if ((stat(mutt_buffer_string(path), &st) != 0) || !S_ISDIR(st.st_mode))
244  mutt_buffer_printf(buf2, "-CAfile %s", mutt_buffer_string(buf1));
245  else
246  mutt_buffer_printf(buf2, "-CApath %s", mutt_buffer_string(buf1));
247 
248  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
249  snprintf(buf, buflen, fmt, mutt_buffer_string(buf2));
250 
254  }
255  else if (!c_smime_ca_location)
256  optional = false;
257  break;
258  }
259 
260  case 'c':
261  { /* certificate (list) */
262  if (!optional)
263  {
264  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
265  snprintf(buf, buflen, fmt, NONULL(cctx->certificates));
266  }
267  else if (!cctx->certificates)
268  optional = false;
269  break;
270  }
271 
272  case 'i':
273  { /* intermediate certificates */
274  if (!optional)
275  {
276  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
277  snprintf(buf, buflen, fmt, NONULL(cctx->intermediates));
278  }
279  else if (!cctx->intermediates)
280  optional = false;
281  break;
282  }
283 
284  case 's':
285  { /* detached signature */
286  if (!optional)
287  {
288  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
289  snprintf(buf, buflen, fmt, NONULL(cctx->sig_fname));
290  }
291  else if (!cctx->sig_fname)
292  optional = false;
293  break;
294  }
295 
296  case 'k':
297  { /* private key */
298  if (!optional)
299  {
300  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
301  snprintf(buf, buflen, fmt, NONULL(cctx->key));
302  }
303  else if (!cctx->key)
304  optional = false;
305  break;
306  }
307 
308  case 'a':
309  { /* algorithm for encryption */
310  if (!optional)
311  {
312  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
313  snprintf(buf, buflen, fmt, NONULL(cctx->cryptalg));
314  }
315  else if (!cctx->key)
316  optional = false;
317  break;
318  }
319 
320  case 'f':
321  { /* file to process */
322  if (!optional)
323  {
324  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
325  snprintf(buf, buflen, fmt, NONULL(cctx->fname));
326  }
327  else if (!cctx->fname)
328  optional = false;
329  break;
330  }
331 
332  case 'd':
333  { /* algorithm for the signature message digest */
334  if (!optional)
335  {
336  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
337  snprintf(buf, buflen, fmt, NONULL(cctx->digestalg));
338  }
339  else if (!cctx->key)
340  optional = false;
341  break;
342  }
343 
344  default:
345  *buf = '\0';
346  break;
347  }
348 
349  if (optional)
350  {
351  mutt_expando_format(buf, buflen, col, cols, if_str,
353  }
354  else if (flags & MUTT_FORMAT_OPTIONAL)
355  {
356  mutt_expando_format(buf, buflen, col, cols, else_str,
358  }
359 
360  /* We return the format string, unchanged */
361  return src;
362 }
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
static const char * smime_command_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)
Format an SMIME command - Implements format_t -.
Definition: smime.c:216
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:194
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:322
Data for a SIME command.
Definition: smime.c:67
const char * sig_fname
s
Definition: smime.c:72
const char * intermediates
i
Definition: smime.c:74
const char * digestalg
d
Definition: smime.c:70
const char * cryptalg
a
Definition: smime.c:69
const char * key
k
Definition: smime.c:68
const char * fname
f
Definition: smime.c:71
const char * certificates
c
Definition: smime.c:73
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ group_index_format_str()

const char* group_index_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 
)

Format a string for the newsgroup menu - Implements format_t -.

Expando Description
%C Current newsgroup number
%d Description of newsgroup (becomes from server)
%f Newsgroup name
%M - if newsgroup not allowed for direct post (moderated for example)
%N N if newsgroup is new, u if unsubscribed, blank otherwise
%n Number of new articles in newsgroup
%s Number of unread articles in newsgroup

Definition at line 55 of file browse.c.

59 {
60  char fn[128], fmt[128];
61  struct Folder *folder = (struct Folder *) data;
62 
63  switch (op)
64  {
65  case 'C':
66  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
67  snprintf(buf, buflen, fmt, folder->num + 1);
68  break;
69 
70  case 'd':
71  if (folder->ff->nd->desc)
72  {
73  char *desc = mutt_str_dup(folder->ff->nd->desc);
74  const char *const c_newsgroups_charset =
75  cs_subset_string(NeoMutt->sub, "newsgroups_charset");
76  const char *const c_charset = cs_subset_string(NeoMutt->sub, "charset");
77  if (c_newsgroups_charset)
78  mutt_ch_convert_string(&desc, c_newsgroups_charset, c_charset, MUTT_ICONV_HOOK_FROM);
80 
81  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
82  snprintf(buf, buflen, fmt, desc);
83  FREE(&desc);
84  }
85  else
86  {
87  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
88  snprintf(buf, buflen, fmt, "");
89  }
90  break;
91 
92  case 'f':
93  mutt_str_copy(fn, folder->ff->name, sizeof(fn));
94  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
95  snprintf(buf, buflen, fmt, fn);
96  break;
97 
98  case 'M':
99  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
100  if (folder->ff->nd->deleted)
101  snprintf(buf, buflen, fmt, 'D');
102  else
103  snprintf(buf, buflen, fmt, folder->ff->nd->allowed ? ' ' : '-');
104  break;
105 
106  case 'N':
107  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
108  if (folder->ff->nd->subscribed)
109  snprintf(buf, buflen, fmt, ' ');
110  else
111  snprintf(buf, buflen, fmt, folder->ff->has_new_mail ? 'N' : 'u');
112  break;
113 
114  case 'n':
115  {
116  const bool c_mark_old = cs_subset_bool(NeoMutt->sub, "mark_old");
117  if (c_mark_old && (folder->ff->nd->last_cached >= folder->ff->nd->first_message) &&
118  (folder->ff->nd->last_cached <= folder->ff->nd->last_message))
119  {
120  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
121  snprintf(buf, buflen, fmt, folder->ff->nd->last_message - folder->ff->nd->last_cached);
122  }
123  else
124  {
125  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
126  snprintf(buf, buflen, fmt, folder->ff->nd->unread);
127  }
128  break;
129  }
130 
131  case 's':
132  if (flags & MUTT_FORMAT_OPTIONAL)
133  {
134  if (folder->ff->nd->unread != 0)
135  {
136  mutt_expando_format(buf, buflen, col, cols, if_str,
137  group_index_format_str, data, flags);
138  }
139  else
140  {
141  mutt_expando_format(buf, buflen, col, cols, else_str,
142  group_index_format_str, data, flags);
143  }
144  }
145  else
146  {
147  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
148  snprintf(buf, buflen, fmt, folder->ff->nd->unread);
149  }
150  break;
151  }
152  return src;
153 }
const char * group_index_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)
Format a string for the newsgroup menu - Implements format_t -.
Definition: browse.c:55
int mutt_mb_filter_unprintable(char **s)
Replace unprintable characters.
Definition: mbyte.c:421
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
Definition: charset.c:764
#define MUTT_ICONV_HOOK_FROM
apply charset-hooks to fromcode
Definition: charset.h:72
struct NntpMboxData * nd
Extra NNTP data.
Definition: lib.h:91
anum_t last_cached
Definition: mdata.h:39
bool deleted
Definition: mdata.h:44
bool allowed
Definition: mdata.h:43
anum_t last_message
Definition: mdata.h:37
char * desc
Description of newsgroup.
Definition: mdata.h:35
anum_t unread
Definition: mdata.h:40
anum_t first_message
Definition: mdata.h:36
bool subscribed
Definition: mdata.h:41
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nntp_format_str()

const char* nntp_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 
)

Expand the newsrc filename - Implements format_t -.

Expando Description
%a Account url
%p Port
%P Port if specified
%s News server name
%S Url schema
%u Username

Definition at line 926 of file newsrc.c.

929 {
930  struct NntpAccountData *adata = (struct NntpAccountData *) data;
931  struct ConnAccount *cac = &adata->conn->account;
932  char fn[128], fmt[128];
933 
934  switch (op)
935  {
936  case 'a':
937  {
938  struct Url url = { 0 };
939  mutt_account_tourl(cac, &url);
940  url_tostring(&url, fn, sizeof(fn), U_PATH);
941  char *p = strchr(fn, '/');
942  if (p)
943  *p = '\0';
944  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
945  snprintf(buf, buflen, fmt, fn);
946  break;
947  }
948  case 'p':
949  snprintf(fmt, sizeof(fmt), "%%%su", prec);
950  snprintf(buf, buflen, fmt, cac->port);
951  break;
952  case 'P':
953  *buf = '\0';
954  if (cac->flags & MUTT_ACCT_PORT)
955  {
956  snprintf(fmt, sizeof(fmt), "%%%su", prec);
957  snprintf(buf, buflen, fmt, cac->port);
958  }
959  break;
960  case 's':
961  mutt_str_copy(fn, cac->host, sizeof(fn));
962  mutt_str_lower(fn);
963  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
964  snprintf(buf, buflen, fmt, fn);
965  break;
966  case 'S':
967  {
968  struct Url url = { 0 };
969  mutt_account_tourl(cac, &url);
970  url_tostring(&url, fn, sizeof(fn), U_PATH);
971  char *p = strchr(fn, ':');
972  if (p)
973  *p = '\0';
974  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
975  snprintf(buf, buflen, fmt, fn);
976  break;
977  }
978  case 'u':
979  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
980  snprintf(buf, buflen, fmt, cac->user);
981  break;
982  }
983  return src;
984 }
#define MUTT_ACCT_PORT
Port field has been set.
Definition: connaccount.h:43
void mutt_account_tourl(struct ConnAccount *cac, struct Url *url)
Fill URL with info from account.
Definition: mutt_account.c:79
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
Login details for a remote server.
Definition: connaccount.h:53
char user[128]
Username.
Definition: connaccount.h:56
char host[128]
Server to login to.
Definition: connaccount.h:54
MuttAccountFlags flags
Which fields are initialised, e.g. MUTT_ACCT_USER.
Definition: connaccount.h:60
unsigned short port
Port to connect to.
Definition: connaccount.h:58
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:50
NNTP-specific Account data -.
Definition: adata.h:37
struct Connection * conn
Connection to NNTP Server.
Definition: adata.h:63
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition: url.h:69
char * src
Raw URL string.
Definition: url.h:77
int url_tostring(struct Url *url, char *dest, size_t len, uint8_t flags)
Output the URL string for a given Url object.
Definition: url.c:418
#define U_PATH
Definition: url.h:50
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pattern_format_str()

static const char* pattern_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 
)
static

Format a string for the pattern completion menu - Implements format_t -.

Expando Description
%d Pattern description
%e Pattern expression
%n Index number

Definition at line 115 of file dlgpattern.c.

119 {
120  struct PatternEntry *entry = (struct PatternEntry *) data;
121 
122  switch (op)
123  {
124  case 'd':
125  mutt_format_s(buf, buflen, prec, NONULL(entry->desc));
126  break;
127  case 'e':
128  mutt_format_s(buf, buflen, prec, NONULL(entry->expr));
129  break;
130  case 'n':
131  {
132  char tmp[32];
133  snprintf(tmp, sizeof(tmp), "%%%sd", prec);
134  snprintf(buf, buflen, tmp, entry->num);
135  break;
136  }
137  }
138 
139  return src;
140 }
A line in the Pattern Completion menu.
Definition: dlgpattern.c:89
const char * desc
Description of pattern.
Definition: dlgpattern.c:93
int num
Index number.
Definition: dlgpattern.c:90
const char * expr
Displayed in the menu.
Definition: dlgpattern.c:92
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mix_format_str()

static const char* mix_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 
)
static

Format a string for the remailer menu - Implements format_t -.

Expando Description
%a The remailer's e-mail address
%c Remailer capabilities
%n The running number on the menu
%s The remailer's short name

Definition at line 476 of file remailer.c.

480 {
481  char fmt[128];
482  struct Remailer *remailer = (struct Remailer *) data;
483  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
484 
485  switch (op)
486  {
487  case 'a':
488  if (!optional)
489  {
490  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
491  snprintf(buf, buflen, fmt, NONULL(remailer->addr));
492  }
493  else if (!remailer->addr)
494  optional = false;
495  break;
496 
497  case 'c':
498  if (optional)
499  break;
500 
501  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
502  snprintf(buf, buflen, fmt, mix_format_caps(remailer));
503  break;
504 
505  case 'n':
506  if (optional)
507  break;
508 
509  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
510  snprintf(buf, buflen, fmt, remailer->num);
511  break;
512 
513  case 's':
514  if (!optional)
515  {
516  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
517  snprintf(buf, buflen, fmt, NONULL(remailer->shortname));
518  }
519  else if (!remailer->shortname)
520  optional = false;
521  break;
522 
523  default:
524  *buf = '\0';
525  }
526 
527  if (optional)
528  {
529  mutt_expando_format(buf, buflen, col, cols, if_str, mix_format_str, data,
531  }
532  else if (flags & MUTT_FORMAT_OPTIONAL)
533  {
534  mutt_expando_format(buf, buflen, col, cols, else_str, mix_format_str, data,
536  }
537 
538  /* We return the format string, unchanged */
539  return src;
540 }
static const char * mix_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)
Format a string for the remailer menu - Implements format_t -.
Definition: remailer.c:476
static const char * mix_format_caps(struct Remailer *r)
Turn flags into a MixMaster capability string.
Definition: remailer.c:424
A Mixmaster remailer.
Definition: remailer.h:46
int num
Index number.
Definition: remailer.h:47
char * addr
Address of host.
Definition: remailer.h:49
char * shortname
Short name of remailer host.
Definition: remailer.h:48
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ greeting_string()

static const char* greeting_string ( 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 
)
static

Format a greetings string - Implements format_t -.

Expando Description
%n Recipient's real name (or address if missing)
%u User (login) name of the recipient
%v First name of the recipient

Definition at line 663 of file send.c.

667 {
668  struct Email *e = (struct Email *) data;
669  char *p = NULL;
670  char buf2[256];
671 
672  const struct Address *to = TAILQ_FIRST(&e->env->to);
673  const struct Address *cc = TAILQ_FIRST(&e->env->cc);
674 
675  buf[0] = '\0';
676  switch (op)
677  {
678  case 'n':
679  mutt_format_s(buf, buflen, prec, mutt_get_name(to));
680  break;
681 
682  case 'u':
683  if (to)
684  {
685  mutt_str_copy(buf2, mutt_addr_for_display(to), sizeof(buf2));
686  if ((p = strpbrk(buf2, "%@")))
687  *p = '\0';
688  }
689  else
690  buf2[0] = '\0';
691  mutt_format_s(buf, buflen, prec, buf2);
692  break;
693 
694  case 'v':
695  if (to)
696  mutt_format_s(buf2, sizeof(buf2), prec, mutt_get_name(to));
697  else if (cc)
698  mutt_format_s(buf2, sizeof(buf2), prec, mutt_get_name(cc));
699  else
700  *buf2 = '\0';
701  if ((p = strpbrk(buf2, " %@")))
702  *p = '\0';
703  mutt_format_s(buf, buflen, prec, buf2);
704  break;
705 
706  default:
707  snprintf(buf, buflen, "%%%s%c", prec, op);
708  break;
709  }
710 
711  if (flags & MUTT_FORMAT_OPTIONAL)
712  mutt_expando_format(buf, buflen, col, cols, else_str, greeting_string, data, flags);
713 
714  return src;
715 }
static const char * greeting_string(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)
Format a greetings string - Implements format_t -.
Definition: send.c:663
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ sidebar_format_str()

static const char* sidebar_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 
)
static

Format a string for the sidebar - Implements format_t -.

Expando Description
%! 'n!' Flagged messages
%B Name of the mailbox
%D Description of the mailbox
%d Number of deleted messages
%F Number of Flagged messages in the mailbox
%L Number of messages after limiting
%n 'N' if mailbox has new mail, ' ' (space) otherwise
%N Number of unread messages in the mailbox
%o Number of old unread messages in the mailbox
%r Number of read messages in the mailbox
%S Size of mailbox (total number of messages)
%t Number of tagged messages
%Z Number of new unseen messages in the mailbox

Definition at line 326 of file window.c.

330 {
331  struct SidebarFormatData *sfdata = (struct SidebarFormatData *) data;
332  struct SbEntry *sbe = sfdata->entry;
333  struct IndexSharedData *shared = sfdata->shared;
334  char fmt[256];
335 
336  if (!sbe || !shared || !buf)
337  return src;
338 
339  buf[0] = '\0'; /* Just in case there's nothing to do */
340 
341  struct Mailbox *m = sbe->mailbox;
342  if (!m)
343  return src;
344 
345  struct Mailbox *m_cur = shared->mailbox;
346 
347  bool c = m_cur && mutt_str_equal(m_cur->realpath, m->realpath);
348 
349  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
350 
351  switch (op)
352  {
353  case 'B':
354  case 'D':
355  {
356  char indented[256] = { 0 };
357  size_t ilen = sizeof(indented);
358  size_t off = add_indent(indented, ilen, sbe);
359  snprintf(indented + off, ilen - off, "%s",
360  ((op == 'D') && sbe->mailbox->name) ? sbe->mailbox->name : sbe->box);
361  mutt_format_s(buf, buflen, prec, indented);
362  break;
363  }
364 
365  case 'd':
366  if (!optional)
367  {
368  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
369  snprintf(buf, buflen, fmt, c ? m_cur->msg_deleted : 0);
370  }
371  else if ((c && (m_cur->msg_deleted == 0)) || !c)
372  optional = false;
373  break;
374 
375  case 'F':
376  if (!optional)
377  {
378  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
379  snprintf(buf, buflen, fmt, m->msg_flagged);
380  }
381  else if (m->msg_flagged == 0)
382  optional = false;
383  break;
384 
385  case 'L':
386  if (!optional)
387  {
388  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
389  snprintf(buf, buflen, fmt, c ? m_cur->vcount : m->msg_count);
390  }
391  else if ((c && (m_cur->vcount == m->msg_count)) || !c)
392  optional = false;
393  break;
394 
395  case 'N':
396  if (!optional)
397  {
398  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
399  snprintf(buf, buflen, fmt, m->msg_unread);
400  }
401  else if (m->msg_unread == 0)
402  optional = false;
403  break;
404 
405  case 'n':
406  if (!optional)
407  {
408  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
409  snprintf(buf, buflen, fmt, m->has_new ? 'N' : ' ');
410  }
411  else if (m->has_new == false)
412  optional = false;
413  break;
414 
415  case 'o':
416  if (!optional)
417  {
418  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
419  snprintf(buf, buflen, fmt, m->msg_unread - m->msg_new);
420  }
421  else if ((c && (m_cur->msg_unread - m_cur->msg_new) == 0) || !c)
422  optional = false;
423  break;
424 
425  case 'r':
426  if (!optional)
427  {
428  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
429  snprintf(buf, buflen, fmt, m->msg_count - m->msg_unread);
430  }
431  else if ((c && (m_cur->msg_count - m_cur->msg_unread) == 0) || !c)
432  optional = false;
433  break;
434 
435  case 'S':
436  if (!optional)
437  {
438  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
439  snprintf(buf, buflen, fmt, m->msg_count);
440  }
441  else if (m->msg_count == 0)
442  optional = false;
443  break;
444 
445  case 't':
446  if (!optional)
447  {
448  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
449  snprintf(buf, buflen, fmt, c ? m_cur->msg_tagged : 0);
450  }
451  else if ((c && (m_cur->msg_tagged == 0)) || !c)
452  optional = false;
453  break;
454 
455  case 'Z':
456  if (!optional)
457  {
458  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
459  snprintf(buf, buflen, fmt, m->msg_new);
460  }
461  else if ((c && (m_cur->msg_new) == 0) || !c)
462  optional = false;
463  break;
464 
465  case '!':
466  if (m->msg_flagged == 0)
467  mutt_format_s(buf, buflen, prec, "");
468  else if (m->msg_flagged == 1)
469  mutt_format_s(buf, buflen, prec, "!");
470  else if (m->msg_flagged == 2)
471  mutt_format_s(buf, buflen, prec, "!!");
472  else
473  {
474  snprintf(fmt, sizeof(fmt), "%d!", m->msg_flagged);
475  mutt_format_s(buf, buflen, prec, fmt);
476  }
477  break;
478  }
479 
480  if (optional)
481  {
482  mutt_expando_format(buf, buflen, col, cols, if_str, sidebar_format_str, data, flags);
483  }
484  else if (flags & MUTT_FORMAT_OPTIONAL)
485  {
486  mutt_expando_format(buf, buflen, col, cols, else_str, sidebar_format_str, data, flags);
487  }
488 
489  /* We return the format string, unchanged */
490  return src;
491 }
static const char * sidebar_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)
Format a string for the sidebar - Implements format_t -.
Definition: window.c:326
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:715
static size_t add_indent(char *buf, size_t buflen, const struct SbEntry *sbe)
Generate the needed indentation.
Definition: window.c:232
Data shared between Index, Pager and Sidebar.
Definition: shared_data.h:37
struct Mailbox * mailbox
Current Mailbox.
Definition: shared_data.h:41
int vcount
The number of virtual messages.
Definition: mailbox.h:102
bool has_new
Mailbox has new mail.
Definition: mailbox.h:88
int msg_new
Number of new messages.
Definition: mailbox.h:95
char * name
A short name for the Mailbox.
Definition: mailbox.h:85
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:96
int msg_flagged
Number of flagged messages.
Definition: mailbox.h:93
int msg_tagged
How many messages are tagged?
Definition: mailbox.h:97
int msg_unread
Number of unread messages.
Definition: mailbox.h:92
uint8_t flags
e.g. MB_NORMAL
Definition: mailbox.h:134
Info about folders in the sidebar.
Definition: private.h:41
struct Mailbox * mailbox
Mailbox this represents.
Definition: private.h:45
char box[256]
Mailbox path (possibly abbreviated)
Definition: private.h:42
Data passed to sidebar_format_str()
Definition: window.c:88
struct IndexSharedData * shared
Shared Index Data.
Definition: window.c:90
struct SbEntry * entry
Info about a folder.
Definition: window.c:89
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ status_format_str()

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 
)
static

Create the status bar string - Implements format_t -.

Expando Description
%b Number of incoming folders with unread messages
%D Description of the mailbox
%d Number of deleted messages
%f Full mailbox path
%F Number of flagged messages
%h Hostname
%l Length of mailbox (in bytes)
%L Size (in bytes) of the messages shown (or limited)
%M Number of messages shown (virtual message count when limiting)
%m Total number of messages
%n Number of new messages
%o Number of old unread messages
%p Number of postponed messages
%P Percent of way through index
%R Number of read messages
%r Readonly/wontwrite/changed flag
%S Current aux sorting method ($sort_aux)
%s Current sorting method ($sort)
%T Current threading view ($use_threads)
%t Number of tagged messages
%u Number of unread messages
%V Currently active limit pattern
%v NeoMutt version

Definition at line 102 of file status.c.

106 {
107  char fmt[128], tmp[128];
108  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
109  struct MenuStatusLineData *msld = (struct MenuStatusLineData *) data;
110  struct IndexSharedData *shared = msld->shared;
111  struct Context *ctx = shared->ctx;
112  struct Mailbox *m = shared->mailbox;
113  struct Menu *menu = msld->menu;
114 
115  *buf = '\0';
116  switch (op)
117  {
118  case 'b':
119  {
120  const int num = mutt_mailbox_check(m, 0);
121  if (!optional)
122  {
123  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
124  snprintf(buf, buflen, fmt, num);
125  }
126  else if (num == 0)
127  optional = false;
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  optional = false;
141  break;
142  }
143 
144  case 'D':
145  // If there's a descriptive name, use it. Otherwise, fall-through
146  if (m && m->name)
147  {
148  mutt_str_copy(tmp, m->name, sizeof(tmp));
149  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
150  snprintf(buf, buflen, fmt, tmp);
151  break;
152  }
153  /* fallthrough */
154  case 'f':
155 #ifdef USE_COMP_MBOX
156  if (m && m->compress_info && (m->realpath[0] != '\0'))
157  {
158  mutt_str_copy(tmp, m->realpath, sizeof(tmp));
159  mutt_pretty_mailbox(tmp, sizeof(tmp));
160  }
161  else
162 #endif
163  if (m && (m->type == MUTT_NOTMUCH) && m->name)
164  {
165  mutt_str_copy(tmp, m->name, sizeof(tmp));
166  }
167  else if (m && !mutt_buffer_is_empty(&m->pathbuf))
168  {
169  mutt_str_copy(tmp, mailbox_path(m), sizeof(tmp));
170  mutt_pretty_mailbox(tmp, sizeof(tmp));
171  }
172  else
173  mutt_str_copy(tmp, _("(no mailbox)"), sizeof(tmp));
174 
175  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
176  snprintf(buf, buflen, fmt, tmp);
177  break;
178  case 'F':
179  {
180  const int num = m ? m->msg_flagged : 0;
181  if (!optional)
182  {
183  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
184  snprintf(buf, buflen, fmt, num);
185  }
186  else if (num == 0)
187  optional = false;
188  break;
189  }
190 
191  case 'h':
192  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
193  snprintf(buf, buflen, fmt, NONULL(ShortHostname));
194  break;
195 
196  case 'l':
197  {
198  const off_t num = m ? m->size : 0;
199  if (!optional)
200  {
201  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
202  mutt_str_pretty_size(tmp, sizeof(tmp), num);
203  snprintf(buf, buflen, fmt, tmp);
204  }
205  else if (num == 0)
206  optional = false;
207  break;
208  }
209 
210  case 'L':
211  if (!optional)
212  {
213  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
214  mutt_str_pretty_size(tmp, sizeof(tmp), ctx ? ctx->vsize : 0);
215  snprintf(buf, buflen, fmt, tmp);
216  }
217  else if (!ctx_has_limit(ctx))
218  optional = false;
219  break;
220 
221  case 'm':
222  {
223  const int num = m ? m->msg_count : 0;
224  if (!optional)
225  {
226  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
227  snprintf(buf, buflen, fmt, num);
228  }
229  else if (num == 0)
230  optional = false;
231  break;
232  }
233 
234  case 'M':
235  if (!optional)
236  {
237  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
238  snprintf(buf, buflen, fmt, m ? m->vcount : 0);
239  }
240  else if (!ctx_has_limit(ctx))
241  optional = false;
242  break;
243 
244  case 'n':
245  {
246  const int num = m ? m->msg_new : 0;
247  if (!optional)
248  {
249  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
250  snprintf(buf, buflen, fmt, num);
251  }
252  else if (num == 0)
253  optional = false;
254  break;
255  }
256 
257  case 'o':
258  {
259  const int num = m ? (m->msg_unread - m->msg_new) : 0;
260  if (!optional)
261  {
262  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
263  snprintf(buf, buflen, fmt, num);
264  }
265  else if (num == 0)
266  optional = false;
267  break;
268  }
269 
270  case 'p':
271  {
272  const int count = mutt_num_postponed(m, false);
273  if (!optional)
274  {
275  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
276  snprintf(buf, buflen, fmt, count);
277  }
278  else if (count == 0)
279  optional = false;
280  break;
281  }
282 
283  case 'P':
284  {
285  if (!menu)
286  break;
287  char *cp = NULL;
288  if (menu->top + menu->pagelen >= menu->max)
289  {
290  cp = menu->top ?
291  /* L10N: Status bar message: the end of the list emails is visible in the index */
292  _("end") :
293  /* L10N: Status bar message: all the emails are visible in the index */
294  _("all");
295  }
296  else
297  {
298  int count = (100 * (menu->top + menu->pagelen)) / menu->max;
299  snprintf(tmp, sizeof(tmp), "%d%%", count);
300  cp = tmp;
301  }
302  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
303  snprintf(buf, buflen, fmt, cp);
304  break;
305  }
306 
307  case 'r':
308  {
309  size_t i = 0;
310 
311  if (m)
312  {
313  i = OptAttachMsg ? 3 :
314  ((m->readonly || m->dontwrite) ? 2 :
315  (m->changed ||
316  /* deleted doesn't necessarily mean changed in IMAP */
317  (m->type != MUTT_IMAP && m->msg_deleted)) ?
318  1 :
319  0);
320  }
321 
322  const struct MbTable *c_status_chars =
323  cs_subset_mbtable(NeoMutt->sub, "status_chars");
324  if (!c_status_chars || !c_status_chars->len)
325  buf[0] = '\0';
326  else if (i >= c_status_chars->len)
327  snprintf(buf, buflen, "%s", c_status_chars->chars[0]);
328  else
329  snprintf(buf, buflen, "%s", c_status_chars->chars[i]);
330  break;
331  }
332 
333  case 'R':
334  {
335  const int read = m ? (m->msg_count - m->msg_unread) : 0;
336  if (!optional)
337  {
338  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
339  snprintf(buf, buflen, fmt, read);
340  }
341  else if (read == 0)
342  optional = false;
343  break;
344  }
345 
346  case 's':
347  {
348  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
349  const short c_sort = cs_subset_sort(NeoMutt->sub, "sort");
350  snprintf(buf, buflen, fmt, get_sort_str(tmp, sizeof(tmp), c_sort));
351  break;
352  }
353 
354  case 'S':
355  {
356  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
357  const short c_sort_aux = cs_subset_sort(NeoMutt->sub, "sort_aux");
358  snprintf(buf, buflen, fmt, get_sort_str(tmp, sizeof(tmp), c_sort_aux));
359  break;
360  }
361 
362  case 't':
363  {
364  const int num = m ? m->msg_tagged : 0;
365  if (!optional)
366  {
367  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
368  snprintf(buf, buflen, fmt, num);
369  }
370  else if (num == 0)
371  optional = false;
372  break;
373  }
374 
375  case 'T':
376  {
377  const enum UseThreads c_use_threads = mutt_thread_style();
378  if (!optional)
379  {
380  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
381  snprintf(buf, buflen, fmt, get_use_threads_str(c_use_threads));
382  }
383  else if (c_use_threads == UT_FLAT)
384  optional = false;
385  break;
386  }
387 
388  case 'u':
389  if (!optional)
390  {
391  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
392  snprintf(buf, buflen, fmt, m ? m->msg_unread : 0);
393  }
394  else if (!m || (m->msg_unread == 0))
395  optional = false;
396  break;
397 
398  case 'v':
399  snprintf(buf, buflen, "%s", mutt_make_version());
400  break;
401 
402  case 'V':
403  if (!optional)
404  {
405  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
406  snprintf(buf, buflen, fmt, ctx_has_limit(ctx) ? ctx->pattern : "");
407  }
408  else if (!ctx_has_limit(ctx))
409  optional = false;
410  break;
411 
412  case 0:
413  *buf = '\0';
414  return src;
415 
416  default:
417  snprintf(buf, buflen, "%%%s%c", prec, op);
418  break;
419  }
420 
421  if (optional)
422  {
423  mutt_expando_format(buf, buflen, col, cols, if_str, status_format_str, data,
425  }
426  else if (flags & MUTT_FORMAT_OPTIONAL)
427  {
428  mutt_expando_format(buf, buflen, col, cols, else_str, status_format_str,
429  data, MUTT_FORMAT_NO_FLAGS);
430  }
431 
432  /* We return the format string, unchanged */
433  return src;
434 }
bool ctx_has_limit(const struct Context *ctx)
Is a limit active?
Definition: context.c:433
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using '~' or '='.
Definition: muttlib.c:526
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:102
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition: helpers.c:292
@ MUTT_IMAP
'IMAP' Mailbox type
Definition: mailbox.h:53
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all all Mailboxes for new mail.
Definition: mutt_mailbox.c:162
const char * get_use_threads_str(enum UseThreads value)
Convert UseThreads enum to string.
Definition: mutt_thread.c:108
enum UseThreads mutt_thread_style(void)
Which threading style is active?
Definition: mutt_thread.c:89
UseThreads
Which threading style is active, $use_threads.
Definition: mutt_thread.h:83
@ UT_FLAT
Unthreaded.
Definition: mutt_thread.h:85
bool OptAttachMsg
(pseudo) used by attach-message
Definition: options.h:37
int mutt_num_postponed(struct Mailbox *m, bool force)
Return the number of postponed messages.
Definition: postpone.c:68
static char * get_sort_str(char *buf, size_t buflen, enum SortType method)
Get the sort method as a string.
Definition: status.c:56
The "current" mailbox.
Definition: context.h:38
char * pattern
Limit pattern string.
Definition: context.h:40
off_t vsize
Size (in bytes) of the messages shown.
Definition: context.h:39
struct Context * ctx
Current Mailbox view.
Definition: shared_data.h:39
bool changed
Mailbox has been modified.
Definition: mailbox.h:114
struct Buffer pathbuf
Path of the Mailbox.
Definition: mailbox.h:83
bool dontwrite
Don't write the mailbox on close.
Definition: mailbox.h:115
off_t size
Size of the Mailbox.
Definition: mailbox.h:87
void * compress_info
Compressed mbox module private data.
Definition: mailbox.h:124
bool readonly
Don't allow changes to the mailbox.
Definition: mailbox.h:119
Data for creating a Menu line.
Definition: status.c:68
struct IndexSharedData * shared
Data shared between Index, Pager and Sidebar.
Definition: status.c:69
struct Menu * menu
Current Menu.
Definition: status.c:70
Definition: lib.h:69
int top
Entry that is the top of the current page.
Definition: lib.h:88
int pagelen
Number of entries per screen.
Definition: lib.h:74
int max
Number of entries in the menu.
Definition: lib.h:71
+ Here is the call graph for this function:
+ Here is the caller graph for this function: