NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
Expando API

Callback functions for mutt_expando_format(). 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 -
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
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 -
Expando Description
%a Destination address
%c Current entry number
%e Extra information
%n Destination name
%t * if current entry is tagged, a space otherwise
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 -
Expando Description
%a Email address
%k Gpg keyid
%n Current entry number
%p Prefer-encrypt flag
%s Status flag (active/inactive)
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 -
Expando Description
%C Current file number
%d Date/time folder was last modified
%D Date/time folder was last modified using `$date_format.
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 -
Expando Description
%f Compressed file
%t Plaintext, temporary file
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 -
Expando Description
%a Total number of attachments
%h Local hostname
%l Approximate size (in bytes) of the current message
%v NeoMutt version string
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 -
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.
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 -
Expando Description
%s History match
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 -
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. 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 -
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. 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 -
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
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 -
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
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 -
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
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 -
Expando Description
%a Account url
%p Port
%P Port if specified
%s News server name
%S Url schema
%u Username
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 -
Expando Description
%d Pattern description
%e Pattern expression
%n Index number
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 -
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
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 -
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
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 -
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
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 -
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
More...
 

Detailed Description

Callback functions for mutt_expando_format().

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]dataPointer to the mailbox Context
[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 123 of file dlgalias.c.

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

186 {
187  struct AliasView *av = (struct AliasView *) data;
188  struct Alias *alias = av->alias;
189  char fmt[128];
190  char tmp[256] = { 0 };
191  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
192 
193  switch (op)
194  {
195  case 'a':
196  tmp[0] = '<';
197  mutt_addrlist_write(&alias->addr, tmp + 1, sizeof(tmp) - 1, true);
198  const size_t len = strlen(tmp);
199  if (len < (sizeof(tmp) - 1))
200  {
201  tmp[len] = '>';
202  tmp[len + 1] = '\0';
203  }
204  mutt_format_s(buf, buflen, prec, tmp);
205  break;
206  case 'c':
207  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
208  snprintf(buf, buflen, fmt, av->num + 1);
209  break;
210  case 'e':
211  if (!optional)
212  mutt_format_s(buf, buflen, prec, NONULL(alias->comment));
213  else if (!alias->comment || (*alias->comment == '\0'))
214  optional = false;
215  break;
216  case 'n':
217  mutt_format_s(buf, buflen, prec, NONULL(alias->name));
218  break;
219  case 't':
220  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
221  snprintf(buf, buflen, fmt, av->is_tagged ? '*' : ' ');
222  break;
223  default:
224  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
225  snprintf(buf, buflen, fmt, op);
226  break;
227  }
228 
229  if (optional)
230  {
231  mutt_expando_format(buf, buflen, col, cols, if_str, query_format_str, data,
233  }
234  else if (flags & MUTT_FORMAT_OPTIONAL)
235  {
236  mutt_expando_format(buf, buflen, col, cols, else_str, query_format_str,
237  data, MUTT_FORMAT_NO_FLAGS);
238  }
239 
240  /* We return the format string, unchanged */
241  return src;
242 }
A shortcut for an email address or addresses.
Definition: alias.h:33
char * name
Short name.
Definition: alias.h:35
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
GUI data wrapping an Alias.
Definition: gui.h:35
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
struct Alias * alias
Alias.
Definition: gui.h:44
char * comment
Free-form comment string.
Definition: alias.h:37
bool is_tagged
Is it tagged?
Definition: gui.h:41
void mutt_format_s(char *buf, size_t buflen, const char *prec, const char *s)
Format a simple string.
Definition: curs_lib.c:867
#define MUTT_FORMAT_OPTIONAL
Allow optional field processing.
Definition: format_flags.h:33
struct AddressList addr
List of Addresses the Alias expands to.
Definition: alias.h:36
int num
Index number in list.
Definition: gui.h:37
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
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 -Expando Description %a Destination address...
Definition: dlgquery.c:182
+ 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 134 of file dlgautocrypt.c.

138 {
139  struct AccountEntry *entry = (struct AccountEntry *) data;
140  char tmp[128];
141 
142  switch (op)
143  {
144  case 'a':
145  mutt_format_s(buf, buflen, prec, entry->addr->mailbox);
146  break;
147  case 'k':
148  mutt_format_s(buf, buflen, prec, entry->account->keyid);
149  break;
150  case 'n':
151  snprintf(tmp, sizeof(tmp), "%%%sd", prec);
152  snprintf(buf, buflen, tmp, entry->num);
153  break;
154  case 'p':
155  if (entry->account->prefer_encrypt)
156  {
157  /* L10N: Autocrypt Account menu.
158  flag that an account has prefer-encrypt set */
159  mutt_format_s(buf, buflen, prec, _("prefer encrypt"));
160  }
161  else
162  {
163  /* L10N: Autocrypt Account menu.
164  flag that an account has prefer-encrypt unset;
165  thus encryption will need to be manually enabled. */
166  mutt_format_s(buf, buflen, prec, _("manual encrypt"));
167  }
168  break;
169  case 's':
170  if (entry->account->enabled)
171  {
172  /* L10N: Autocrypt Account menu.
173  flag that an account is enabled/active */
174  mutt_format_s(buf, buflen, prec, _("active"));
175  }
176  else
177  {
178  /* L10N: Autocrypt Account menu.
179  flag that an account is disabled/inactive */
180  mutt_format_s(buf, buflen, prec, _("inactive"));
181  }
182  break;
183  }
184 
185  return (src);
186 }
#define _(a)
Definition: message.h:28
char * mailbox
Mailbox and host address.
Definition: address.h:38
char * keyid
Definition: lib.h:106
bool enabled
Definition: lib.h:109
An entry in the Autocrypt account Menu.
Definition: dlgautocrypt.c:89
bool prefer_encrypt
false = nopref, true = mutual
Definition: lib.h:108
struct Address * addr
Definition: dlgautocrypt.c:93
void mutt_format_s(char *buf, size_t buflen, const char *prec, const char *s)
Format a simple string.
Definition: curs_lib.c:867
struct AutocryptAccount * account
Definition: dlgautocrypt.c:92
+ 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 405 of file browser.c.

409 {
410  char fn[128], fmt[128];
411  struct Folder *folder = (struct Folder *) data;
412  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
413 
414  switch (op)
415  {
416  case 'C':
417  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
418  snprintf(buf, buflen, fmt, folder->num + 1);
419  break;
420 
421  case 'd':
422  case 'D':
423  if (folder->ff->local)
424  {
425  bool do_locales = true;
426 
427  const char *t_fmt = NULL;
428  if (op == 'D')
429  {
430  const char *const c_date_format =
431  cs_subset_string(NeoMutt->sub, "date_format");
432  t_fmt = NONULL(c_date_format);
433  if (*t_fmt == '!')
434  {
435  t_fmt++;
436  do_locales = false;
437  }
438  }
439  else
440  {
441  static const time_t one_year = 31536000;
442  t_fmt = ((mutt_date_epoch() - folder->ff->mtime) < one_year) ?
443  "%b %d %H:%M" :
444  "%b %d %Y";
445  }
446 
447  if (!do_locales)
448  setlocale(LC_TIME, "C");
449  char date[128];
450  mutt_date_localtime_format(date, sizeof(date), t_fmt, folder->ff->mtime);
451  if (!do_locales)
452  setlocale(LC_TIME, "");
453 
454  mutt_format_s(buf, buflen, prec, date);
455  }
456  else
457  mutt_format_s(buf, buflen, prec, "");
458  break;
459 
460  case 'f':
461  {
462  char *s = NULL;
463 
464  s = NONULL(folder->ff->name);
465 
466  snprintf(fn, sizeof(fn), "%s%s", s,
467  folder->ff->local ?
468  (S_ISLNK(folder->ff->mode) ?
469  "@" :
470  (S_ISDIR(folder->ff->mode) ?
471  "/" :
472  (((folder->ff->mode & S_IXUSR) != 0) ? "*" : ""))) :
473  "");
474 
475  mutt_format_s(buf, buflen, prec, fn);
476  break;
477  }
478  case 'F':
479  {
480  if (folder->ff->local)
481  {
482  char permission[11];
483  snprintf(permission, sizeof(permission), "%c%c%c%c%c%c%c%c%c%c",
484  S_ISDIR(folder->ff->mode) ? 'd' : (S_ISLNK(folder->ff->mode) ? 'l' : '-'),
485  ((folder->ff->mode & S_IRUSR) != 0) ? 'r' : '-',
486  ((folder->ff->mode & S_IWUSR) != 0) ? 'w' : '-',
487  ((folder->ff->mode & S_ISUID) != 0) ? 's' :
488  ((folder->ff->mode & S_IXUSR) != 0) ? 'x' :
489  '-',
490  ((folder->ff->mode & S_IRGRP) != 0) ? 'r' : '-',
491  ((folder->ff->mode & S_IWGRP) != 0) ? 'w' : '-',
492  ((folder->ff->mode & S_ISGID) != 0) ? 's' :
493  ((folder->ff->mode & S_IXGRP) != 0) ? 'x' :
494  '-',
495  ((folder->ff->mode & S_IROTH) != 0) ? 'r' : '-',
496  ((folder->ff->mode & S_IWOTH) != 0) ? 'w' : '-',
497  ((folder->ff->mode & S_ISVTX) != 0) ? 't' :
498  ((folder->ff->mode & S_IXOTH) != 0) ? 'x' :
499  '-');
500  mutt_format_s(buf, buflen, prec, permission);
501  }
502 #ifdef USE_IMAP
503  else if (folder->ff->imap)
504  {
505  char permission[11];
506  /* mark folders with subfolders AND mail */
507  snprintf(permission, sizeof(permission), "IMAP %c",
508  (folder->ff->inferiors && folder->ff->selectable) ? '+' : ' ');
509  mutt_format_s(buf, buflen, prec, permission);
510  }
511 #endif
512  else
513  mutt_format_s(buf, buflen, prec, "");
514  break;
515  }
516 
517  case 'g':
518  if (folder->ff->local)
519  {
520  struct group *gr = getgrgid(folder->ff->gid);
521  if (gr)
522  mutt_format_s(buf, buflen, prec, gr->gr_name);
523  else
524  {
525  snprintf(fmt, sizeof(fmt), "%%%sld", prec);
526  snprintf(buf, buflen, fmt, folder->ff->gid);
527  }
528  }
529  else
530  mutt_format_s(buf, buflen, prec, "");
531  break;
532 
533  case 'i':
534  {
535  char *s = NULL;
536  if (folder->ff->desc)
537  s = folder->ff->desc;
538  else
539  s = folder->ff->name;
540 
541  snprintf(fn, sizeof(fn), "%s%s", s,
542  folder->ff->local ?
543  (S_ISLNK(folder->ff->mode) ?
544  "@" :
545  (S_ISDIR(folder->ff->mode) ?
546  "/" :
547  (((folder->ff->mode & S_IXUSR) != 0) ? "*" : ""))) :
548  "");
549 
550  mutt_format_s(buf, buflen, prec, fn);
551  break;
552  }
553 
554  case 'l':
555  if (folder->ff->local)
556  {
557  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
558  snprintf(buf, buflen, fmt, folder->ff->nlink);
559  }
560  else
561  mutt_format_s(buf, buflen, prec, "");
562  break;
563 
564  case 'm':
565  if (!optional)
566  {
567  if (folder->ff->has_mailbox)
568  {
569  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
570  snprintf(buf, buflen, fmt, folder->ff->msg_count);
571  }
572  else
573  mutt_format_s(buf, buflen, prec, "");
574  }
575  else if (folder->ff->msg_count == 0)
576  optional = false;
577  break;
578 
579  case 'N':
580  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
581  snprintf(buf, buflen, fmt, folder->ff->has_new_mail ? 'N' : ' ');
582  break;
583 
584  case 'n':
585  if (!optional)
586  {
587  if (folder->ff->has_mailbox)
588  {
589  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
590  snprintf(buf, buflen, fmt, folder->ff->msg_unread);
591  }
592  else
593  mutt_format_s(buf, buflen, prec, "");
594  }
595  else if (folder->ff->msg_unread == 0)
596  optional = false;
597  break;
598 
599  case 's':
600  if (folder->ff->local)
601  {
602  mutt_str_pretty_size(fn, sizeof(fn), folder->ff->size);
603  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
604  snprintf(buf, buflen, fmt, fn);
605  }
606  else
607  mutt_format_s(buf, buflen, prec, "");
608  break;
609 
610  case 't':
611  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
612  snprintf(buf, buflen, fmt, folder->ff->tagged ? '*' : ' ');
613  break;
614 
615  case 'u':
616  if (folder->ff->local)
617  {
618  struct passwd *pw = getpwuid(folder->ff->uid);
619  if (pw)
620  mutt_format_s(buf, buflen, prec, pw->pw_name);
621  else
622  {
623  snprintf(fmt, sizeof(fmt), "%%%sld", prec);
624  snprintf(buf, buflen, fmt, folder->ff->uid);
625  }
626  }
627  else
628  mutt_format_s(buf, buflen, prec, "");
629  break;
630 
631  default:
632  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
633  snprintf(buf, buflen, fmt, op);
634  break;
635  }
636 
637  if (optional)
638  {
639  mutt_expando_format(buf, buflen, col, cols, if_str, folder_format_str, data,
641  }
642  else if (flags & MUTT_FORMAT_OPTIONAL)
643  {
644  mutt_expando_format(buf, buflen, col, cols, else_str, folder_format_str,
645  data, MUTT_FORMAT_NO_FLAGS);
646  }
647 
648  /* We return the format string, unchanged */
649  return src;
650 }
int msg_unread
number of unread messages
Definition: browser.h:67
mode_t mode
Definition: browser.h:55
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:427
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
time_t mtime
Definition: browser.h:57
#define NONULL(x)
Definition: string2.h:37
bool has_mailbox
Definition: browser.h:76
size_t mutt_date_localtime_format(char *buf, size_t buflen, const char *format, time_t t)
Format localtime.
Definition: date.c:691
char * desc
Definition: browser.h:63
gid_t gid
Definition: browser.h:59
Container for Accounts, Notifications.
Definition: neomutt.h:36
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
struct FolderFile * ff
Definition: browser.h:46
off_t size
Definition: browser.h:56
bool selectable
Definition: browser.h:73
uid_t uid
Definition: browser.h:58
nlink_t nlink
Definition: browser.h:60
char * name
Definition: browser.h:62
int num
Definition: browser.h:47
bool imap
Definition: browser.h:72
A folder/dir in the browser.
Definition: browser.h:44
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 -Expando Description %C Current file nu...
Definition: browser.c:405
void mutt_str_pretty_size(char *buf, size_t buflen, size_t num)
Display an abbreviated size, like 3.4K.
Definition: muttlib.c:1679
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
int msg_count
total number of messages
Definition: browser.h:66
void mutt_format_s(char *buf, size_t buflen, const char *prec, const char *s)
Format a simple string.
Definition: curs_lib.c:867
#define MUTT_FORMAT_OPTIONAL
Allow optional field processing.
Definition: format_flags.h:33
bool tagged
Definition: browser.h:78
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
bool local
folder is on local filesystem
Definition: browser.h:77
bool inferiors
Definition: browser.h:74
bool has_new_mail
true if mailbox has "new mail"
Definition: browser.h:65
+ 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&#39;s quoting rules.
Definition: file.c:838
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:215
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:84
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
A mailbox.
Definition: mailbox.h:81
+ 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 103 of file cbar.c.

107 {
108  char fmt[128], tmp[128];
109  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
110  struct ComposeSharedData *shared = (struct ComposeSharedData *) data;
111 
112  *buf = '\0';
113  switch (op)
114  {
115  case 'a': /* total number of attachments */
116  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
117  snprintf(buf, buflen, fmt, num_attachments(shared->adata));
118  break;
119 
120  case 'h': /* hostname */
121  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
122  snprintf(buf, buflen, fmt, NONULL(ShortHostname));
123  break;
124 
125  case 'l': /* approx length of current message in bytes */
126  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
127  mutt_str_pretty_size(tmp, sizeof(tmp),
128  cum_attachs_size(shared->sub, shared->adata));
129  snprintf(buf, buflen, fmt, tmp);
130  break;
131 
132  case 'v':
133  snprintf(buf, buflen, "%s", mutt_make_version());
134  break;
135 
136  case 0:
137  *buf = '\0';
138  return src;
139 
140  default:
141  snprintf(buf, buflen, "%%%s%c", prec, op);
142  break;
143  }
144 
145  if (optional)
146  {
147  mutt_expando_format(buf, buflen, col, cols, if_str, compose_format_str, data, flags);
148  }
149  // This format function doesn't have any optional expandos,
150  // so there's no `else if (flags & MUTT_FORMAT_OPTIONAL)` clause
151 
152  return src;
153 }
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
Shared Compose Data.
Definition: shared_data.h:29
int num_attachments(struct ComposeAttachData *adata)
Count the number of attachments.
Definition: cbar.c:86
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 -Expando Description %a Total nu...
Definition: cbar.c:103
unsigned long cum_attachs_size(struct ConfigSubset *sub, struct ComposeAttachData *adata)
Cumulative Attachments Size.
Definition: attach.c:89
WHERE char * ShortHostname
Short version of the hostname.
Definition: mutt_globals.h:46
void mutt_str_pretty_size(char *buf, size_t buflen, size_t num)
Display an abbreviated size, like 3.4K.
Definition: muttlib.c:1679
#define MUTT_FORMAT_OPTIONAL
Allow optional field processing.
Definition: format_flags.h:33
struct ConfigSubset * sub
Config set to use.
Definition: shared_data.h:31
const char * mutt_make_version(void)
Generate the NeoMutt version string.
Definition: muttlib.c:1476
struct ComposeAttachData * adata
Attachments.
Definition: shared_data.h:34
+ 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 440 of file hdrline.c.

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

94 {
95  char *match = (char *) data;
96 
97  switch (op)
98  {
99  case 's':
100  mutt_format_s(buf, buflen, prec, match);
101  break;
102  }
103 
104  return src;
105 }
void mutt_format_s(char *buf, size_t buflen, const char *prec, const char *s)
Format a simple string.
Definition: curs_lib.c:867
+ 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 }
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
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
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_ARROWCURSOR
Reserve space for arrow_cursor.
Definition: format_flags.h:35
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
int mutt_mb_charlen(const char *s, int *width)
Count the bytes in a (multibyte) character.
Definition: mbyte.c:54
Container for Accounts, Notifications.
Definition: neomutt.h:36
#define MoreArgs(buf)
Definition: buffer.h:40
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
int mutt_strwidth(const char *s)
Measure a string&#39;s width in screen cells.
Definition: curs_lib.c:983
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:395
char * dptr
Current read/write position.
Definition: buffer.h:36
char * data
Pointer to data.
Definition: buffer.h:35
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:933
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:664
Log at debug level 1.
Definition: logging.h:40
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:749
char * mutt_str_lower(char *str)
Convert all characters in the string to lowercase.
Definition: string.c:504
#define FREE(x)
Definition: memory.h:40
#define MUTT_FORMAT_NOFILTER
Do not allow filtering on this pass.
Definition: format_flags.h:37
#define MUTT_FORMAT_OPTIONAL
Allow optional field processing.
Definition: format_flags.h:33
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
void mutt_buffer_seek(struct Buffer *buf, size_t offset)
set current read/write position to offset from beginning
Definition: buffer.c:466
Log at debug level 5.
Definition: logging.h:44
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
static int pad(FILE *fp, int col, int i)
Write some padding to a file.
Definition: help.c:200
Log at debug level 3.
Definition: logging.h:42
#define MUTT_TOKEN_NO_FLAGS
No flags are set.
Definition: mutt.h:66
+ 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 1020 of file dlggpgme.c.

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

347 {
348  char fmt[128];
349  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
350 
351  struct PgpEntry *entry = (struct PgpEntry *) data;
352  struct PgpUid *uid = entry->uid;
353  struct PgpKeyInfo *key = uid->parent;
354  struct PgpKeyInfo *pkey = pgp_principal_key(key);
355 
356  if (isupper((unsigned char) op))
357  key = pkey;
358 
359  KeyFlags kflags = key->flags | (pkey->flags & KEYFLAG_RESTRICTIONS) | uid->flags;
360 
361  switch (tolower(op))
362  {
363  case 'a':
364  if (!optional)
365  {
366  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
367  snprintf(buf, buflen, fmt, key->algorithm);
368  }
369  break;
370  case 'c':
371  if (!optional)
372  {
373  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
374  snprintf(buf, buflen, fmt, pgp_key_abilities(kflags));
375  }
376  else if (!(kflags & KEYFLAG_ABILITIES))
377  optional = false;
378  break;
379  case 'f':
380  if (!optional)
381  {
382  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
383  snprintf(buf, buflen, fmt, pgp_flags(kflags));
384  }
385  else if (!(kflags & KEYFLAG_RESTRICTIONS))
386  optional = false;
387  break;
388  case 'k':
389  if (!optional)
390  {
391  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
392  snprintf(buf, buflen, fmt, pgp_this_keyid(key));
393  }
394  break;
395  case 'l':
396  if (!optional)
397  {
398  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
399  snprintf(buf, buflen, fmt, key->keylen);
400  }
401  break;
402  case 'n':
403  if (!optional)
404  {
405  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
406  snprintf(buf, buflen, fmt, entry->num);
407  }
408  break;
409  case 't':
410  if (!optional)
411  {
412  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
413  snprintf(buf, buflen, fmt, trust_flags[uid->trust & 0x03]);
414  }
415  else if (!(uid->trust & 0x03))
416  {
417  /* undefined trust */
418  optional = false;
419  }
420  break;
421  case 'u':
422  if (!optional)
423  {
424  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
425  snprintf(buf, buflen, fmt, NONULL(uid->addr));
426  }
427  break;
428  case '[':
429 
430  {
431  char buf2[128];
432  bool do_locales = true;
433  size_t len;
434 
435  char *p = buf;
436 
437  const char *cp = src;
438  if (*cp == '!')
439  {
440  do_locales = false;
441  cp++;
442  }
443 
444  len = buflen - 1;
445  while ((len > 0) && (*cp != ']'))
446  {
447  if (*cp == '%')
448  {
449  cp++;
450  if (len >= 2)
451  {
452  *p++ = '%';
453  *p++ = *cp;
454  len -= 2;
455  }
456  else
457  break; /* not enough space */
458  cp++;
459  }
460  else
461  {
462  *p++ = *cp++;
463  len--;
464  }
465  }
466  *p = '\0';
467 
468  if (!do_locales)
469  setlocale(LC_TIME, "C");
470  mutt_date_localtime_format(buf2, sizeof(buf2), buf, key->gen_time);
471  if (!do_locales)
472  setlocale(LC_TIME, "");
473 
474  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
475  snprintf(buf, buflen, fmt, buf2);
476  if (len > 0)
477  src = cp + 1;
478  break;
479  }
480  default:
481  *buf = '\0';
482  }
483 
484  if (optional)
485  {
486  mutt_expando_format(buf, buflen, col, cols, if_str, pgp_entry_format_str,
487  data, MUTT_FORMAT_NO_FLAGS);
488  }
489  else if (flags & MUTT_FORMAT_OPTIONAL)
490  {
491  mutt_expando_format(buf, buflen, col, cols, else_str, pgp_entry_format_str,
492  data, MUTT_FORMAT_NO_FLAGS);
493  }
494 
495  /* We return the format string, unchanged */
496  return src;
497 }
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
size_t mutt_date_localtime_format(char *buf, size_t buflen, const char *format, time_t t)
Format localtime.
Definition: date.c:691
static char * pgp_key_abilities(KeyFlags flags)
Turn PGP key abilities into a string.
Definition: dlgpgp.c:279
size_t num
Definition: dlgpgp.c:113
static const char trust_flags[]
Definition: dlgpgp.c:117
static char pgp_flags(KeyFlags flags)
Turn PGP key flags into a string.
Definition: dlgpgp.c:307
PGP User ID.
Definition: pgplib.h:34
KeyFlags flags
Definition: pgplib.h:51
#define KEYFLAG_ABILITIES
Definition: lib.h:139
struct PgpKeyInfo * pgp_principal_key(struct PgpKeyInfo *key)
Get the main (parent) PGP key.
Definition: pgpkey.c:89
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
char * addr
Definition: pgplib.h:36
Information about a PGP key.
Definition: pgplib.h:46
short trust
Definition: pgplib.h:37
An entry in a PGP key menu.
Definition: dlgpgp.c:111
short keylen
Definition: pgplib.h:52
uint16_t KeyFlags
Flags describing PGP/SMIME keys, e.g. KEYFLAG_CANSIGN.
Definition: lib.h:122
struct PgpKeyInfo * parent
Definition: pgplib.h:39
struct PgpUid * uid
Definition: dlgpgp.c:114
#define KEYFLAG_RESTRICTIONS
Definition: lib.h:137
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 -Expando Description %n Number %...
Definition: dlgpgp.c:343
const char * algorithm
Definition: pgplib.h:55
char * pgp_this_keyid(struct PgpKeyInfo *k)
Get the ID of this key.
Definition: pgp.c:184
#define MUTT_FORMAT_OPTIONAL
Allow optional field processing.
Definition: format_flags.h:33
int flags
Definition: pgplib.h:38
time_t gen_time
Definition: pgplib.h:53
+ 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 }
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
const char * sig_fname
s
Definition: pgpinvoke.c:62
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
const char * signas
a
Definition: pgpinvoke.c:63
const char * fname
f
Definition: pgpinvoke.c:61
bool need_passphrase
p
Definition: pgpinvoke.c:60
bool pgp_use_gpg_agent(void)
Does the user want to use the gpg agent?
Definition: pgp.c:118
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 -Expando Description %a Value of $pgp_sign_as if s...
Definition: pgpinvoke.c:78
#define MUTT_FORMAT_OPTIONAL
Allow optional field processing.
Definition: format_flags.h:33
const char * ids
r
Definition: pgpinvoke.c:64
Data for a PGP command.
Definition: pgpinvoke.c:58
+ 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 210 of file smime.c.

215 {
216  char fmt[128];
217  struct SmimeCommandContext *cctx = (struct SmimeCommandContext *) data;
218  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
219 
220  switch (op)
221  {
222  case 'C':
223  {
224  const char *const c_smime_ca_location =
225  cs_subset_path(NeoMutt->sub, "smime_ca_location");
226  if (!optional)
227  {
228  struct Buffer *path = mutt_buffer_pool_get();
229  struct Buffer *buf1 = mutt_buffer_pool_get();
230  struct Buffer *buf2 = mutt_buffer_pool_get();
231  struct stat sb;
232 
233  mutt_buffer_strcpy(path, c_smime_ca_location);
236 
237  if ((stat(mutt_buffer_string(path), &sb) != 0) || !S_ISDIR(sb.st_mode))
238  mutt_buffer_printf(buf2, "-CAfile %s", mutt_buffer_string(buf1));
239  else
240  mutt_buffer_printf(buf2, "-CApath %s", mutt_buffer_string(buf1));
241 
242  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
243  snprintf(buf, buflen, fmt, mutt_buffer_string(buf2));
244 
248  }
249  else if (!c_smime_ca_location)
250  optional = false;
251  break;
252  }
253 
254  case 'c':
255  { /* certificate (list) */
256  if (!optional)
257  {
258  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
259  snprintf(buf, buflen, fmt, NONULL(cctx->certificates));
260  }
261  else if (!cctx->certificates)
262  optional = false;
263  break;
264  }
265 
266  case 'i':
267  { /* intermediate certificates */
268  if (!optional)
269  {
270  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
271  snprintf(buf, buflen, fmt, NONULL(cctx->intermediates));
272  }
273  else if (!cctx->intermediates)
274  optional = false;
275  break;
276  }
277 
278  case 's':
279  { /* detached signature */
280  if (!optional)
281  {
282  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
283  snprintf(buf, buflen, fmt, NONULL(cctx->sig_fname));
284  }
285  else if (!cctx->sig_fname)
286  optional = false;
287  break;
288  }
289 
290  case 'k':
291  { /* private key */
292  if (!optional)
293  {
294  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
295  snprintf(buf, buflen, fmt, NONULL(cctx->key));
296  }
297  else if (!cctx->key)
298  optional = false;
299  break;
300  }
301 
302  case 'a':
303  { /* algorithm for encryption */
304  if (!optional)
305  {
306  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
307  snprintf(buf, buflen, fmt, NONULL(cctx->cryptalg));
308  }
309  else if (!cctx->key)
310  optional = false;
311  break;
312  }
313 
314  case 'f':
315  { /* file to process */
316  if (!optional)
317  {
318  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
319  snprintf(buf, buflen, fmt, NONULL(cctx->fname));
320  }
321  else if (!cctx->fname)
322  optional = false;
323  break;
324  }
325 
326  case 'd':
327  { /* algorithm for the signature message digest */
328  if (!optional)
329  {
330  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
331  snprintf(buf, buflen, fmt, NONULL(cctx->digestalg));
332  }
333  else if (!cctx->key)
334  optional = false;
335  break;
336  }
337 
338  default:
339  *buf = '\0';
340  break;
341  }
342 
343  if (optional)
344  {
345  mutt_expando_format(buf, buflen, col, cols, if_str,
347  }
348  else if (flags & MUTT_FORMAT_OPTIONAL)
349  {
350  mutt_expando_format(buf, buflen, col, cols, else_str,
352  }
353 
354  /* We return the format string, unchanged */
355  return src;
356 }
void mutt_buffer_quote_filename(struct Buffer *buf, const char *filename, bool add_outer)
Quote a filename to survive the shell&#39;s quoting rules.
Definition: file.c:838
const char * certificates
c
Definition: smime.c:73
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
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
const char * sig_fname
s
Definition: smime.c:72
Container for Accounts, Notifications.
Definition: neomutt.h:36
const char * digestalg
d
Definition: smime.c:70
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
Data for a SIME command.
Definition: smime.c:66
const char * fname
f
Definition: smime.c:71
const char * cryptalg
a
Definition: smime.c:69
const char * key
k
Definition: smime.c:68
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:194
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
const char * intermediates
i
Definition: smime.c:74
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:322
#define MUTT_FORMAT_OPTIONAL
Allow optional field processing.
Definition: format_flags.h:33
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 -Expando Description %a Algorithm used for encryption ...
Definition: smime.c:210
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:

◆ 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 }
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
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
Definition: charset.c:758
Container for Accounts, Notifications.
Definition: neomutt.h:36
bool subscribed
Definition: mdata.h:41
anum_t last_cached
Definition: mdata.h:39
struct FolderFile * ff
Definition: browser.h:46
char * name
Definition: browser.h:62
int num
Definition: browser.h:47
A folder/dir in the browser.
Definition: browser.h:44
#define MUTT_ICONV_HOOK_FROM
apply charset-hooks to fromcode
Definition: charset.h:72
bool allowed
Definition: mdata.h:43
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
bool deleted
Definition: mdata.h:44
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:749
anum_t first_message
Definition: mdata.h:36
anum_t unread
Definition: mdata.h:40
#define FREE(x)
Definition: memory.h:40
#define MUTT_FORMAT_OPTIONAL
Allow optional field processing.
Definition: format_flags.h:33
int mutt_mb_filter_unprintable(char **s)
Replace unprintable characters.
Definition: mbyte.c:423
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
struct NntpMboxData * nd
Definition: browser.h:80
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 newsgro...
Definition: browse.c:55
char * desc
Definition: mdata.h:35
anum_t last_message
Definition: mdata.h:37
bool has_new_mail
true if mailbox has "new mail"
Definition: browser.h:65
+ 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 925 of file newsrc.c.

928 {
929  struct NntpAccountData *adata = (struct NntpAccountData *) data;
930  struct ConnAccount *cac = &adata->conn->account;
931  char fn[128], fmt[128];
932 
933  switch (op)
934  {
935  case 'a':
936  {
937  struct Url url = { 0 };
938  mutt_account_tourl(cac, &url);
939  url_tostring(&url, fn, sizeof(fn), U_PATH);
940  char *p = strchr(fn, '/');
941  if (p)
942  *p = '\0';
943  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
944  snprintf(buf, buflen, fmt, fn);
945  break;
946  }
947  case 'p':
948  snprintf(fmt, sizeof(fmt), "%%%su", prec);
949  snprintf(buf, buflen, fmt, cac->port);
950  break;
951  case 'P':
952  *buf = '\0';
953  if (cac->flags & MUTT_ACCT_PORT)
954  {
955  snprintf(fmt, sizeof(fmt), "%%%su", prec);
956  snprintf(buf, buflen, fmt, cac->port);
957  }
958  break;
959  case 's':
960  mutt_str_copy(fn, cac->host, sizeof(fn));
961  mutt_str_lower(fn);
962  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
963  snprintf(buf, buflen, fmt, fn);
964  break;
965  case 'S':
966  {
967  struct Url url = { 0 };
968  mutt_account_tourl(cac, &url);
969  url_tostring(&url, fn, sizeof(fn), U_PATH);
970  char *p = strchr(fn, ':');
971  if (p)
972  *p = '\0';
973  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
974  snprintf(buf, buflen, fmt, fn);
975  break;
976  }
977  case 'u':
978  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
979  snprintf(buf, buflen, fmt, cac->user);
980  break;
981  }
982  return src;
983 }
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:40
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition: url.h:68
char user[128]
Username.
Definition: connaccount.h:55
NNTP-specific Account data -.
Definition: adata.h:36
void mutt_account_tourl(struct ConnAccount *cac, struct Url *url)
Fill URL with info from account.
Definition: mutt_account.c:79
char host[128]
Server to login to.
Definition: connaccount.h:53
unsigned short port
Port to connect to.
Definition: connaccount.h:57
#define MUTT_ACCT_PORT
Port field has been set.
Definition: connaccount.h:42
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
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
Login details for a remote server.
Definition: connaccount.h:51
struct Connection * conn
Definition: adata.h:63
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:749
char * mutt_str_lower(char *str)
Convert all characters in the string to lowercase.
Definition: string.c:504
char * src
Raw URL string.
Definition: url.h:77
#define U_PATH
Definition: url.h:50
MuttAccountFlags flags
Which fields are initialised, e.g. MUTT_ACCT_USER.
Definition: connaccount.h:59
+ 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 117 of file dlgpattern.c.

121 {
122  struct PatternEntry *entry = (struct PatternEntry *) data;
123 
124  switch (op)
125  {
126  case 'd':
127  mutt_format_s(buf, buflen, prec, NONULL(entry->desc));
128  break;
129  case 'e':
130  mutt_format_s(buf, buflen, prec, NONULL(entry->expr));
131  break;
132  case 'n':
133  {
134  char tmp[32];
135  snprintf(tmp, sizeof(tmp), "%%%sd", prec);
136  snprintf(buf, buflen, tmp, entry->num);
137  break;
138  }
139  }
140 
141  return src;
142 }
#define NONULL(x)
Definition: string2.h:37
const char * expr
Displayed in the menu.
Definition: dlgpattern.c:94
void mutt_format_s(char *buf, size_t buflen, const char *prec, const char *s)
Format a simple string.
Definition: curs_lib.c:867
int num
Index number.
Definition: dlgpattern.c:92
const char * desc
Description of pattern.
Definition: dlgpattern.c:95
A line in the Pattern Completion menu.
Definition: dlgpattern.c:90
+ 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 270 of file recvattach.c.

273 {
274  char fmt[128];
275  char charset[128];
276  struct AttachPtr *aptr = (struct AttachPtr *) data;
277  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
278 
279  switch (op)
280  {
281  case 'C':
282  if (!optional)
283  {
284  if (mutt_is_text_part(aptr->body) &&
285  mutt_body_get_charset(aptr->body, charset, sizeof(charset)))
286  {
287  mutt_format_s(buf, buflen, prec, charset);
288  }
289  else
290  mutt_format_s(buf, buflen, prec, "");
291  }
292  else if (!mutt_is_text_part(aptr->body) ||
293  !mutt_body_get_charset(aptr->body, charset, sizeof(charset)))
294  {
295  optional = false;
296  }
297  break;
298  case 'c':
299  /* XXX */
300  if (!optional)
301  {
302  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
303  snprintf(buf, buflen, fmt,
304  ((aptr->body->type != TYPE_TEXT) || aptr->body->noconv) ? 'n' : 'c');
305  }
306  else if ((aptr->body->type != TYPE_TEXT) || aptr->body->noconv)
307  optional = false;
308  break;
309  case 'd':
310  {
311  const char *const c_message_format =
312  cs_subset_string(NeoMutt->sub, "message_format");
313  if (!optional)
314  {
315  if (aptr->body->description)
316  {
317  mutt_format_s(buf, buflen, prec, aptr->body->description);
318  break;
319  }
320  if (mutt_is_message_type(aptr->body->type, aptr->body->subtype) &&
321  c_message_format && aptr->body->email)
322  {
323  char s[128];
324  mutt_make_string(s, sizeof(s), cols, c_message_format, NULL, -1,
325  aptr->body->email,
327  if (*s)
328  {
329  mutt_format_s(buf, buflen, prec, s);
330  break;
331  }
332  }
333  if (!aptr->body->d_filename && !aptr->body->filename)
334  {
335  mutt_format_s(buf, buflen, prec, "<no description>");
336  break;
337  }
338  }
339  else if (aptr->body->description ||
340  (mutt_is_message_type(aptr->body->type, aptr->body->subtype) &&
341  c_message_format && aptr->body->email))
342  {
343  break;
344  }
345  }
346  /* fallthrough */
347  case 'F':
348  if (!optional)
349  {
350  if (aptr->body->d_filename)
351  {
352  mutt_format_s(buf, buflen, prec, aptr->body->d_filename);
353  break;
354  }
355  }
356  else if (!aptr->body->d_filename && !aptr->body->filename)
357  {
358  optional = false;
359  break;
360  }
361  /* fallthrough */
362  case 'f':
363  if (!optional)
364  {
365  if (aptr->body->filename && (*aptr->body->filename == '/'))
366  {
367  struct Buffer *path = mutt_buffer_pool_get();
368 
369  mutt_buffer_strcpy(path, aptr->body->filename);
371  mutt_format_s(buf, buflen, prec, mutt_buffer_string(path));
373  }
374  else
375  mutt_format_s(buf, buflen, prec, NONULL(aptr->body->filename));
376  }
377  else if (!aptr->body->filename)
378  optional = false;
379  break;
380  case 'D':
381  if (!optional)
382  snprintf(buf, buflen, "%c", aptr->body->deleted ? 'D' : ' ');
383  else if (!aptr->body->deleted)
384  optional = false;
385  break;
386  case 'e':
387  if (!optional)
388  mutt_format_s(buf, buflen, prec, ENCODING(aptr->body->encoding));
389  break;
390  case 'I':
391  if (optional)
392  break;
393 
394  const char dispchar[] = { 'I', 'A', 'F', '-' };
395  char ch;
396 
397  if (aptr->body->disposition < sizeof(dispchar))
398  ch = dispchar[aptr->body->disposition];
399  else
400  {
401  mutt_debug(LL_DEBUG1, "ERROR: invalid content-disposition %d\n",
402  aptr->body->disposition);
403  ch = '!';
404  }
405  snprintf(buf, buflen, "%c", ch);
406  break;
407  case 'm':
408  if (!optional)
409  mutt_format_s(buf, buflen, prec, TYPE(aptr->body));
410  break;
411  case 'M':
412  if (!optional)
413  mutt_format_s(buf, buflen, prec, aptr->body->subtype);
414  else if (!aptr->body->subtype)
415  optional = false;
416  break;
417  case 'n':
418  if (optional)
419  break;
420 
421  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
422  snprintf(buf, buflen, fmt, aptr->num + 1);
423  break;
424  case 'Q':
425  if (optional)
426  optional = aptr->body->attach_qualifies;
427  else
428  {
429  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
430  mutt_format_s(buf, buflen, fmt, "Q");
431  }
432  break;
433  case 's':
434  {
435  size_t l;
436  if (aptr->body->filename && (flags & MUTT_FORMAT_STAT_FILE))
437  {
438  struct stat st;
439  stat(aptr->body->filename, &st);
440  l = st.st_size;
441  }
442  else
443  l = aptr->body->length;
444 
445  if (!optional)
446  {
447  char tmp[128];
448  mutt_str_pretty_size(tmp, sizeof(tmp), l);
449  mutt_format_s(buf, buflen, prec, tmp);
450  }
451  else if (l == 0)
452  optional = false;
453 
454  break;
455  }
456  case 't':
457  if (!optional)
458  snprintf(buf, buflen, "%c", aptr->body->tagged ? '*' : ' ');
459  else if (!aptr->body->tagged)
460  optional = false;
461  break;
462  case 'T':
463  if (!optional)
464  mutt_format_s_tree(buf, buflen, prec, NONULL(aptr->tree));
465  else if (!aptr->tree)
466  optional = false;
467  break;
468  case 'u':
469  if (!optional)
470  snprintf(buf, buflen, "%c", aptr->body->unlink ? '-' : ' ');
471  else if (!aptr->body->unlink)
472  optional = false;
473  break;
474  case 'X':
475  if (optional)
476  optional = ((aptr->body->attach_count + aptr->body->attach_qualifies) != 0);
477  else
478  {
479  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
480  snprintf(buf, buflen, fmt, aptr->body->attach_count + aptr->body->attach_qualifies);
481  }
482  break;
483  default:
484  *buf = '\0';
485  }
486 
487  if (optional)
488  {
489  mutt_expando_format(buf, buflen, col, cols, if_str, attach_format_str, data,
491  }
492  else if (flags & MUTT_FORMAT_OPTIONAL)
493  {
494  mutt_expando_format(buf, buflen, col, cols, else_str, attach_format_str,
495  data, MUTT_FORMAT_NO_FLAGS);
496  }
497 
498  /* We return the format string, unchanged */
499  return src;
500 }
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
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
#define NONULL(x)
Definition: string2.h:37
An email to which things will be attached.
Definition: attach.h:34
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition: parse.c:1385
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define MUTT_FORMAT_FORCESUBJ
Print the subject even if unchanged.
Definition: format_flags.h:31
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
#define MUTT_FORMAT_ARROWCURSOR
Reserve space for arrow_cursor.
Definition: format_flags.h:35
bool noconv
Don&#39;t do character set conversion.
Definition: body.h:73
String manipulation buffer.
Definition: buffer.h:33
#define MUTT_FORMAT_STAT_FILE
Used by attach_format_str.
Definition: format_flags.h:34
Container for Accounts, Notifications.
Definition: neomutt.h:36
void mutt_buffer_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:603
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
unsigned int disposition
content-disposition, ContentDisposition
Definition: body.h:67
char * tree
Tree characters to display.
Definition: attach.h:39
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
bool attach_qualifies
This attachment should be counted.
Definition: body.h:84
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 ...
Definition: recvattach.c:270
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:1409
#define ENCODING(x)
Definition: mime.h:92
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body&#39;s character set.
Definition: body.c:131
signed short attach_count
Number of attachments.
Definition: body.h:59
bool tagged
This attachment is tagged.
Definition: body.h:70
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
char * subtype
content-type subtype
Definition: body.h:37
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
int num
Attachment index number.
Definition: attach.h:41
Type: &#39;text/*&#39;.
Definition: mime.h:38
void mutt_str_pretty_size(char *buf, size_t buflen, size_t num)
Display an abbreviated size, like 3.4K.
Definition: muttlib.c:1679
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
char * description
content-description
Definition: body.h:40
bool mutt_is_text_part(struct Body *b)
Is this part of an email in plain text?
Definition: muttlib.c:434
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
bool deleted
Attachment marked for deletion.
Definition: body.h:71
#define TYPE(body)
Definition: mime.h:89
void mutt_format_s(char *buf, size_t buflen, const char *prec, const char *s)
Format a simple string.
Definition: curs_lib.c:867
Log at debug level 1.
Definition: logging.h:40
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
#define MUTT_FORMAT_OPTIONAL
Allow optional field processing.
Definition: format_flags.h:33
char * d_filename
filename to be used for the content-disposition header.
Definition: body.h:47
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
struct Email * email
header information for message/rfc822
Definition: body.h:55
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:879
struct Body * body
Attachment.
Definition: attach.h:36
+ 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 477 of file remailer.c.

481 {
482  char fmt[128];
483  struct Remailer *remailer = (struct Remailer *) data;
484  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
485 
486  switch (op)
487  {
488  case 'a':
489  if (!optional)
490  {
491  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
492  snprintf(buf, buflen, fmt, NONULL(remailer->addr));
493  }
494  else if (!remailer->addr)
495  optional = false;
496  break;
497 
498  case 'c':
499  if (optional)
500  break;
501 
502  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
503  snprintf(buf, buflen, fmt, mix_format_caps(remailer));
504  break;
505 
506  case 'n':
507  if (optional)
508  break;
509 
510  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
511  snprintf(buf, buflen, fmt, remailer->num);
512  break;
513 
514  case 's':
515  if (!optional)
516  {
517  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
518  snprintf(buf, buflen, fmt, NONULL(remailer->shortname));
519  }
520  else if (!remailer->shortname)
521  optional = false;
522  break;
523 
524  default:
525  *buf = '\0';
526  }
527 
528  if (optional)
529  {
530  mutt_expando_format(buf, buflen, col, cols, if_str, mix_format_str, data,
532  }
533  else if (flags & MUTT_FORMAT_OPTIONAL)
534  {
535  mutt_expando_format(buf, buflen, col, cols, else_str, mix_format_str, data,
537  }
538 
539  /* We return the format string, unchanged */
540  return src;
541 }
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
static const char * mix_format_caps(struct Remailer *r)
Turn flags into a MixMaster capability string.
Definition: remailer.c:425
int num
Definition: remailer.h:47
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
char * shortname
Definition: remailer.h:48
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 -Expando Description %a The remailer&#39;s e...
Definition: remailer.c:477
#define MUTT_FORMAT_OPTIONAL
Allow optional field processing.
Definition: format_flags.h:33
char * addr
Definition: remailer.h:49
A Mixmaster remailer.
Definition: remailer.h:45
+ 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 325 of file window.c.

329 {
330  struct SidebarFormatData *sfdata = (struct SidebarFormatData *) data;
331  struct SbEntry *sbe = sfdata->entry;
332  struct IndexSharedData *shared = sfdata->shared;
333  char fmt[256];
334 
335  if (!sbe || !shared || !buf)
336  return src;
337 
338  buf[0] = '\0'; /* Just in case there's nothing to do */
339 
340  struct Mailbox *m = sbe->mailbox;
341  if (!m)
342  return src;
343 
344  struct Mailbox *m_cur = shared->mailbox;
345 
346  bool c = m_cur && mutt_str_equal(m_cur->realpath, m->realpath);
347 
348  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
349 
350  switch (op)
351  {
352  case 'B':
353  case 'D':
354  {
355  char indented[256] = { 0 };
356  size_t ilen = sizeof(indented);
357  size_t off = add_indent(indented, ilen, sbe);
358  snprintf(indented + off, ilen - off, "%s",
359  ((op == 'D') && sbe->mailbox->name) ? sbe->mailbox->name : sbe->box);
360  mutt_format_s(buf, buflen, prec, indented);
361  break;
362  }
363 
364  case 'd':
365  if (!optional)
366  {
367  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
368  snprintf(buf, buflen, fmt, c ? m_cur->msg_deleted : 0);
369  }
370  else if ((c && (m_cur->msg_deleted == 0)) || !c)
371  optional = false;
372  break;
373 
374  case 'F':
375  if (!optional)
376  {
377  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
378  snprintf(buf, buflen, fmt, m->msg_flagged);
379  }
380  else if (m->msg_flagged == 0)
381  optional = false;
382  break;
383 
384  case 'L':
385  if (!optional)
386  {
387  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
388  snprintf(buf, buflen, fmt, c ? m_cur->vcount : m->msg_count);
389  }
390  else if ((c && (m_cur->vcount == m->msg_count)) || !c)
391  optional = false;
392  break;
393 
394  case 'N':
395  if (!optional)
396  {
397  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
398  snprintf(buf, buflen, fmt, m->msg_unread);
399  }
400  else if (m->msg_unread == 0)
401  optional = false;
402  break;
403 
404  case 'n':
405  if (!optional)
406  {
407  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
408  snprintf(buf, buflen, fmt, m->has_new ? 'N' : ' ');
409  }
410  else if (m->has_new == false)
411  optional = false;
412  break;
413 
414  case 'o':
415  if (!optional)
416  {
417  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
418  snprintf(buf, buflen, fmt, m->msg_unread - m->msg_new);
419  }
420  else if ((c && (m_cur->msg_unread - m_cur->msg_new) == 0) || !c)
421  optional = false;
422  break;
423 
424  case 'r':
425  if (!optional)
426  {
427  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
428  snprintf(buf, buflen, fmt, m->msg_count - m->msg_unread);
429  }
430  else if ((c && (m_cur->msg_count - m_cur->msg_unread) == 0) || !c)
431  optional = false;
432  break;
433 
434  case 'S':
435  if (!optional)
436  {
437  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
438  snprintf(buf, buflen, fmt, m->msg_count);
439  }
440  else if (m->msg_count == 0)
441  optional = false;
442  break;
443 
444  case 't':
445  if (!optional)
446  {
447  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
448  snprintf(buf, buflen, fmt, c ? m_cur->msg_tagged : 0);
449  }
450  else if ((c && (m_cur->msg_tagged == 0)) || !c)
451  optional = false;
452  break;
453 
454  case 'Z':
455  if (!optional)
456  {
457  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
458  snprintf(buf, buflen, fmt, m->msg_new);
459  }
460  else if ((c && (m_cur->msg_new) == 0) || !c)
461  optional = false;
462  break;
463 
464  case '!':
465  if (m->msg_flagged == 0)
466  mutt_format_s(buf, buflen, prec, "");
467  else if (m->msg_flagged == 1)
468  mutt_format_s(buf, buflen, prec, "!");
469  else if (m->msg_flagged == 2)
470  mutt_format_s(buf, buflen, prec, "!!");
471  else
472  {
473  snprintf(fmt, sizeof(fmt), "%d!", m->msg_flagged);
474  mutt_format_s(buf, buflen, prec, fmt);
475  }
476  break;
477  }
478 
479  if (optional)
480  {
481  mutt_expando_format(buf, buflen, col, cols, if_str, sidebar_format_str, data, flags);
482  }
483  else if (flags & MUTT_FORMAT_OPTIONAL)
484  {
485  mutt_expando_format(buf, buflen, col, cols, else_str, sidebar_format_str, data, flags);
486  }
487 
488  /* We return the format string, unchanged */
489  return src;
490 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:904
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
int msg_count
Total number of messages.
Definition: mailbox.h:91
Data passed to sidebar_format_str()
Definition: window.c:88
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:96
int msg_unread
Number of unread messages.
Definition: mailbox.h:92
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 -Expando Description %! &#39;n!&#39; Flagged messages ...
Definition: window.c:325
int msg_flagged
Number of flagged messages.
Definition: mailbox.h:93
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:84
struct SbEntry * entry
Info about a folder.
Definition: window.c:90
Data shared between Index, Pager and Sidebar.
Definition: shared_data.h:36
Info about folders in the sidebar.
Definition: private.h:39
int vcount
The number of virtual messages.
Definition: mailbox.h:102
bool has_new
Mailbox has new mail.
Definition: mailbox.h:88
struct Mailbox * mailbox
Mailbox this represents.
Definition: private.h:44
char * name
A short name for the Mailbox.
Definition: mailbox.h:85
char box[256]
Mailbox path (possibly abbreviated)
Definition: private.h:41
A mailbox.
Definition: mailbox.h:81
int msg_tagged
How many messages are tagged?
Definition: mailbox.h:97
uint8_t flags
e.g. MB_NORMAL
Definition: mailbox.h:134
struct IndexSharedData * shared
Shared Index Data.
Definition: window.c:91
void mutt_format_s(char *buf, size_t buflen, const char *prec, const char *s)
Format a simple string.
Definition: curs_lib.c:867
int msg_new
Number of new messages.
Definition: mailbox.h:95
#define MUTT_FORMAT_OPTIONAL
Allow optional field processing.
Definition: format_flags.h:33
struct Mailbox * mailbox
Current Mailbox.
Definition: shared_data.h:41
+ 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 }
The "current" mailbox.
Definition: context.h:37
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:215
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 -Expando Description %b Number of incoming folder...
Definition: status.c:102
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:526
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
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
#define NONULL(x)
Definition: string2.h:37
int msg_count
Total number of messages.
Definition: mailbox.h:91
off_t size
Size of the Mailbox.
Definition: mailbox.h:87
char ** chars
The array of multibyte character strings.
Definition: mbtable.h:37
Definition: lib.h:67
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:96
int msg_unread
Number of unread messages.
Definition: mailbox.h:92
int msg_flagged
Number of flagged messages.
Definition: mailbox.h:93
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:84
bool ctx_has_limit(const struct Context *ctx)
Is a limit active?
Definition: context.c:433
#define _(a)
Definition: message.h:28
Data shared between Index, Pager and Sidebar.
Definition: shared_data.h:36
enum UseThreads mutt_thread_style(void)
Which threading style is active?
Definition: mutt_thread.c:89
multibyte character table
Definition: mbtable.h:33
Container for Accounts, Notifications.
Definition: neomutt.h:36
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
int vcount
The number of virtual messages.
Definition: mailbox.h:102
char * name
A short name for the Mailbox.
Definition: mailbox.h:85
UseThreads
Which threading style is active, $use_threads.
Definition: mutt_thread.h:77
bool readonly
Don&#39;t allow changes to the mailbox.
Definition: mailbox.h:119
static char * get_sort_str(char *buf, size_t buflen, enum SortType method)
Get the sort method as a string.
Definition: status.c:56
struct Context * ctx
Current Mailbox view.
Definition: shared_data.h:39
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition: helpers.c:292
off_t vsize
Size (in bytes) of the messages shown.
Definition: context.h:39
WHERE bool OptAttachMsg
(pseudo) used by attach-message
Definition: options.h:31
A mailbox.
Definition: mailbox.h:81
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all all Mailboxes for new mail.
Definition: mutt_mailbox.c:137
int top
Entry that is the top of the current page.
Definition: lib.h:89
WHERE char * ShortHostname
Short version of the hostname.
Definition: mutt_globals.h:46
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 dontwrite
Don&#39;t write the mailbox on close.
Definition: mailbox.h:115
int msg_tagged
How many messages are tagged?
Definition: mailbox.h:97
int pagelen
Number of entries per screen.
Definition: lib.h:74
Data for creating a Menu line.
Definition: status.c:67
struct MbTable * cs_subset_mbtable(const struct ConfigSubset *sub, const char *name)
Get a Multibyte table config item by name.
Definition: helpers.c:145
Unthreaded.
Definition: mutt_thread.h:80
int max
Number of entries in the menu.
Definition: lib.h:71
&#39;Notmuch&#39; (virtual) Mailbox type
Definition: mailbox.h:54
uint8_t flags
e.g. MB_NORMAL
Definition: mailbox.h:134
int mutt_num_postponed(struct Mailbox *m, bool force)
Return the number of postponed messages.
Definition: postpone.c:127
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:749
struct IndexSharedData * shared
Data shared between Index, Pager and Sidebar.
Definition: status.c:69
int msg_new
Number of new messages.
Definition: mailbox.h:95
void * compress_info
Compressed mbox module private data.
Definition: mailbox.h:124
#define MUTT_FORMAT_OPTIONAL
Allow optional field processing.
Definition: format_flags.h:33
bool changed
Mailbox has been modified.
Definition: mailbox.h:114
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
struct Mailbox * mailbox
Current Mailbox.
Definition: shared_data.h:41
struct Buffer pathbuf
Definition: mailbox.h:83
const char * get_use_threads_str(enum UseThreads value)
Convert UseThreads enum to string.
Definition: mutt_thread.c:108
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
char * pattern
Limit pattern string.
Definition: context.h:40
struct Menu * menu
Current Menu.
Definition: status.c:70
int len
Number of characters.
Definition: mbtable.h:36
const char * mutt_make_version(void)
Generate the NeoMutt version string.
Definition: muttlib.c:1476
+ Here is the call graph for this function:
+ Here is the caller graph for this function: