NeoMutt  2020-08-21-74-g346364
Teaching an old dog new tricks
DOXYGEN
hdrline.c File Reference

String processing routines to generate the mail index. More...

#include "config.h"
#include <locale.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "mutt/lib.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "alias/lib.h"
#include "gui/lib.h"
#include "hdrline.h"
#include "ncrypt/lib.h"
#include "context.h"
#include "format_flags.h"
#include "hook.h"
#include "maillist.h"
#include "mutt_globals.h"
#include "mutt_menu.h"
#include "mutt_parse.h"
#include "mutt_thread.h"
#include "muttlib.h"
#include "sort.h"
+ Include dependency graph for hdrline.c:

Go to the source code of this file.

Enumerations

enum  FlagChars {
  FLAG_CHAR_TAGGED, FLAG_CHAR_IMPORTANT, FLAG_CHAR_DELETED, FLAG_CHAR_DELETED_ATTACH,
  FLAG_CHAR_REPLIED, FLAG_CHAR_OLD, FLAG_CHAR_NEW, FLAG_CHAR_OLD_THREAD,
  FLAG_CHAR_NEW_THREAD, FLAG_CHAR_SEMPTY, FLAG_CHAR_ZEMPTY
}
 Index into the C_FlagChars variable ($flag_chars) More...
 
enum  CryptChars {
  FLAG_CHAR_CRYPT_GOOD_SIGN, FLAG_CHAR_CRYPT_ENCRYPTED, FLAG_CHAR_CRYPT_SIGNED, FLAG_CHAR_CRYPT_CONTAINS_KEY,
  FLAG_CHAR_CRYPT_NO_CRYPTO
}
 Index into the C_CryptChars variable ($crypt_chars) More...
 
enum  FieldType {
  DISP_TO, DISP_CC, DISP_BCC, DISP_FROM,
  DISP_PLAIN, DISP_MAX
}
 Header types. More...
 

Functions

static size_t add_index_color (char *buf, size_t buflen, MuttFormatFlags flags, char color)
 Insert a color marker into a string. More...
 
static const char * get_nth_wchar (struct MbTable *table, int index)
 Extract one char from a multi-byte table. More...
 
static const char * make_from_prefix (enum FieldType disp)
 Create a prefix for an author field. More...
 
static void make_from (struct Envelope *env, char *buf, size_t buflen, bool do_lists, MuttFormatFlags flags)
 Generate a From: field (with optional prefix) More...
 
static void make_from_addr (struct Envelope *env, char *buf, size_t buflen, bool do_lists)
 Create a 'from' address for a reply email. More...
 
static bool user_in_addr (struct AddressList *al)
 Do any of the addresses refer to the user? More...
 
static int user_is_recipient (struct Email *e)
 Is the user a recipient of the message. More...
 
static char * apply_subject_mods (struct Envelope *env)
 Apply regex modifications to the subject. More...
 
static bool thread_is_new (struct Email *e)
 Does the email thread contain any new emails? More...
 
static bool thread_is_old (struct Email *e)
 Does the email thread contain any unread emails? More...
 
static const char * index_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Format a string for the index list - Implements format_t. More...
 
void mutt_make_string_flags (char *buf, size_t buflen, int cols, const char *s, struct Mailbox *m, int inpgr, struct Email *e, MuttFormatFlags flags)
 Create formatted strings using mailbox expandos. More...
 
void mutt_make_string_info (char *buf, size_t buflen, int cols, const char *s, struct HdrFormatInfo *hfi, MuttFormatFlags flags)
 Create pager status bar string. More...
 

Variables

struct MbTableC_CryptChars
 Config: User-configurable crypto flags: signed, encrypted etc. More...
 
struct MbTableC_FlagChars
 Config: User-configurable index flags: tagged, new, etc. More...
 
struct MbTableC_FromChars
 Config: User-configurable index flags: to address, cc address, etc. More...
 
struct MbTableC_ToChars
 Config: Indicator characters for the 'To' field in the index. More...
 

Detailed Description

String processing routines to generate the mail index.

Authors
  • Michael R. Elkins
  • Richard Russon
  • Ian Zimmerman
  • Pietro Cerutti

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file hdrline.c.

Enumeration Type Documentation

◆ FlagChars

enum FlagChars

Index into the C_FlagChars variable ($flag_chars)

Enumerator
FLAG_CHAR_TAGGED 

Character denoting a tagged email.

FLAG_CHAR_IMPORTANT 

Character denoting a important (flagged) email.

FLAG_CHAR_DELETED 

Character denoting a deleted email.

FLAG_CHAR_DELETED_ATTACH 

Character denoting a deleted attachment.

FLAG_CHAR_REPLIED 

Character denoting an email that has been replied to.

FLAG_CHAR_OLD 

Character denoting an email that has been read.

FLAG_CHAR_NEW 

Character denoting an unread email.

FLAG_CHAR_OLD_THREAD 

Character denoting a thread of emails that has been read.

FLAG_CHAR_NEW_THREAD 

Character denoting a thread containing at least one new email.

FLAG_CHAR_SEMPTY 

Character denoting a read email, $index_format S expando.

FLAG_CHAR_ZEMPTY 

Character denoting a read email, $index_format Z expando.

Definition at line 69 of file hdrline.c.

70 {
82 };
Character denoting a tagged email.
Definition: hdrline.c:71
Character denoting a important (flagged) email.
Definition: hdrline.c:72
Character denoting a thread containing at least one new email.
Definition: hdrline.c:79
Character denoting a read email, $index_format S expando.
Definition: hdrline.c:80
Character denoting a deleted attachment.
Definition: hdrline.c:74
Character denoting an email that has been read.
Definition: hdrline.c:76
Character denoting a thread of emails that has been read.
Definition: hdrline.c:78
Character denoting an email that has been replied to.
Definition: hdrline.c:75
Character denoting a read email, $index_format Z expando.
Definition: hdrline.c:81
Character denoting a deleted email.
Definition: hdrline.c:73
Character denoting an unread email.
Definition: hdrline.c:77

◆ CryptChars

enum CryptChars

Index into the C_CryptChars variable ($crypt_chars)

Enumerator
FLAG_CHAR_CRYPT_GOOD_SIGN 

Character denoting a message signed with a verified key.

FLAG_CHAR_CRYPT_ENCRYPTED 

Character denoting a message is PGP-encrypted.

FLAG_CHAR_CRYPT_SIGNED 

Character denoting a message is signed.

FLAG_CHAR_CRYPT_CONTAINS_KEY 

Character denoting a message contains a PGP key.

FLAG_CHAR_CRYPT_NO_CRYPTO 

Character denoting a message has no cryptography information.

Definition at line 87 of file hdrline.c.

88 {
94 };
Character denoting a message contains a PGP key.
Definition: hdrline.c:92
Character denoting a message signed with a verified key.
Definition: hdrline.c:89
Character denoting a message is PGP-encrypted.
Definition: hdrline.c:90
Character denoting a message has no cryptography information.
Definition: hdrline.c:93
Character denoting a message is signed.
Definition: hdrline.c:91

◆ FieldType

enum FieldType

Header types.

Strings for printing headers

Enumerator
DISP_TO 

To: string.

DISP_CC 

Cc: string.

DISP_BCC 

Bcc: string.

DISP_FROM 

From: string.

DISP_PLAIN 

Empty string.

DISP_MAX 

Definition at line 101 of file hdrline.c.

102 {
103  DISP_TO,
104  DISP_CC,
105  DISP_BCC,
106  DISP_FROM,
107  DISP_PLAIN,
108  DISP_MAX,
109 };
Bcc: string.
Definition: hdrline.c:105
Cc: string.
Definition: hdrline.c:104
Empty string.
Definition: hdrline.c:107
From: string.
Definition: hdrline.c:106
To: string.
Definition: hdrline.c:103

Function Documentation

◆ add_index_color()

static size_t add_index_color ( char *  buf,
size_t  buflen,
MuttFormatFlags  flags,
char  color 
)
static

Insert a color marker into a string.

Parameters
bufBuffer to store marker
buflenBuffer length
flagsFlags, see MuttFormatFlags
colorColor, e.g. MT_COLOR_MESSAGE
Return values
numCharacters written

The colors are stored as "magic" strings embedded in the text.

Definition at line 121 of file hdrline.c.

122 {
123  /* only add color markers if we are operating on main index entries. */
124  if (!(flags & MUTT_FORMAT_INDEX))
125  return 0;
126 
127  /* this item is going to be passed to an external filter */
128  if (flags & MUTT_FORMAT_NOFILTER)
129  return 0;
130 
131  if (color == MT_COLOR_INDEX)
132  { /* buf might be uninitialized other cases */
133  const size_t len = mutt_str_len(buf);
134  buf += len;
135  buflen -= len;
136  }
137 
138  if (buflen <= 2)
139  return 0;
140 
141  buf[0] = MUTT_SPECIAL_INDEX;
142  buf[1] = color;
143  buf[2] = '\0';
144 
145  return 2;
146 }
#define MUTT_FORMAT_INDEX
This is a main index entry.
Definition: format_flags.h:36
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:631
Colour indicator.
Definition: mutt_thread.h:71
#define MUTT_FORMAT_NOFILTER
Do not allow filtering on this pass.
Definition: format_flags.h:37
Index: default colour (takes a pattern)
Definition: color.h:100
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_nth_wchar()

static const char* get_nth_wchar ( struct MbTable table,
int  index 
)
static

Extract one char from a multi-byte table.

Parameters
tableMulti-byte table
indexSelect this character
Return values
ptrString pointer to the character

Extract one multi-byte character from a string table. If the index is invalid, then a space character will be returned. If the character selected is '
' (Ctrl-M), then "" will be returned.

Definition at line 158 of file hdrline.c.

159 {
160  if (!table || !table->chars || (index < 0) || (index >= table->len))
161  return " ";
162 
163  if (table->chars[index][0] == '\r')
164  return "";
165 
166  return table->chars[index];
167 }
char ** chars
The array of multibyte character strings.
Definition: mbtable.h:39
int len
Number of characters.
Definition: mbtable.h:38
+ Here is the caller graph for this function:

◆ make_from_prefix()

static const char* make_from_prefix ( enum FieldType  disp)
static

Create a prefix for an author field.

Parameters
dispType of field
Return values
ptrPrefix string (do not free it)

If $from_chars is set, pick an appropriate character from it. If not, use the default prefix: "To", "Cc", etc

Definition at line 177 of file hdrline.c.

178 {
179  /* need 2 bytes at the end, one for the space, another for NUL */
180  static char padded[8];
181  static const char *long_prefixes[DISP_MAX] = {
182  [DISP_TO] = "To ", [DISP_CC] = "Cc ", [DISP_BCC] = "Bcc ",
183  [DISP_FROM] = "", [DISP_PLAIN] = "",
184  };
185 
186  if (!C_FromChars || !C_FromChars->chars || (C_FromChars->len == 0))
187  return long_prefixes[disp];
188 
189  const char *pchar = get_nth_wchar(C_FromChars, disp);
190  if (mutt_str_len(pchar) == 0)
191  return "";
192 
193  snprintf(padded, sizeof(padded), "%s ", pchar);
194  return padded;
195 }
Bcc: string.
Definition: hdrline.c:105
char ** chars
The array of multibyte character strings.
Definition: mbtable.h:39
Cc: string.
Definition: hdrline.c:104
struct MbTable * C_FromChars
Config: User-configurable index flags: to address, cc address, etc.
Definition: hdrline.c:63
Empty string.
Definition: hdrline.c:107
From: string.
Definition: hdrline.c:106
static const char * get_nth_wchar(struct MbTable *table, int index)
Extract one char from a multi-byte table.
Definition: hdrline.c:158
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:631
To: string.
Definition: hdrline.c:103
int len
Number of characters.
Definition: mbtable.h:38
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ make_from()

static void make_from ( struct Envelope env,
char *  buf,
size_t  buflen,
bool  do_lists,
MuttFormatFlags  flags 
)
static

Generate a From: field (with optional prefix)

Parameters
envEnvelope of the email
bufBuffer to store the result
buflenSize of the buffer
do_listsShould we check for mailing lists?
flagsFormat flags, see MuttFormatFlags

Generate the F or L field in $index_format. This is the author, or recipient of the email.

The field can optionally be prefixed by a character from $from_chars. If $from_chars is not set, the prefix will be, "To", "Cc", etc

Definition at line 211 of file hdrline.c.

213 {
214  if (!env || !buf)
215  return;
216 
217  bool me;
218  enum FieldType disp;
219  struct AddressList *name = NULL;
220 
221  me = mutt_addr_is_user(TAILQ_FIRST(&env->from));
222 
223  if (do_lists || me)
224  {
225  if (check_for_mailing_list(&env->to, make_from_prefix(DISP_TO), buf, buflen))
226  return;
227  if (check_for_mailing_list(&env->cc, make_from_prefix(DISP_CC), buf, buflen))
228  return;
229  }
230 
231  if (me && !TAILQ_EMPTY(&env->to))
232  {
233  disp = (flags & MUTT_FORMAT_PLAIN) ? DISP_PLAIN : DISP_TO;
234  name = &env->to;
235  }
236  else if (me && !TAILQ_EMPTY(&env->cc))
237  {
238  disp = DISP_CC;
239  name = &env->cc;
240  }
241  else if (me && !TAILQ_EMPTY(&env->bcc))
242  {
243  disp = DISP_BCC;
244  name = &env->bcc;
245  }
246  else if (!TAILQ_EMPTY(&env->from))
247  {
248  disp = DISP_FROM;
249  name = &env->from;
250  }
251  else
252  {
253  *buf = '\0';
254  return;
255  }
256 
257  snprintf(buf, buflen, "%s%s", make_from_prefix(disp), mutt_get_name(TAILQ_FIRST(name)));
258 }
Bcc: string.
Definition: hdrline.c:105
#define TAILQ_FIRST(head)
Definition: queue.h:716
struct AddressList bcc
Email&#39;s &#39;Bcc&#39; list.
Definition: envelope.h:60
Cc: string.
Definition: hdrline.c:104
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:79
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:57
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:59
Empty string.
Definition: hdrline.c:107
From: string.
Definition: hdrline.c:106
static const char * make_from_prefix(enum FieldType disp)
Create a prefix for an author field.
Definition: hdrline.c:177
#define MUTT_FORMAT_PLAIN
Do not prepend DISP_TO, DISP_CC ...
Definition: format_flags.h:38
To: string.
Definition: hdrline.c:103
FieldType
Header types.
Definition: hdrline.c:101
bool mutt_addr_is_user(const struct Address *addr)
Does the address belong to the user.
Definition: alias.c:544
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
#define TAILQ_EMPTY(head)
Definition: queue.h:714
const char * mutt_get_name(const struct Address *a)
Pick the best name to display from an address.
Definition: sort.c:157
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ make_from_addr()

static void make_from_addr ( struct Envelope env,
char *  buf,
size_t  buflen,
bool  do_lists 
)
static

Create a 'from' address for a reply email.

Parameters
envEnvelope of current email
bufBuffer for the result
buflenLength of buffer
do_listsIf true, check for mailing lists

Definition at line 267 of file hdrline.c.

268 {
269  if (!env || !buf)
270  return;
271 
272  bool me = mutt_addr_is_user(TAILQ_FIRST(&env->from));
273 
274  if (do_lists || me)
275  {
276  if (check_for_mailing_list_addr(&env->to, buf, buflen))
277  return;
278  if (check_for_mailing_list_addr(&env->cc, buf, buflen))
279  return;
280  }
281 
282  if (me && !TAILQ_EMPTY(&env->to))
283  snprintf(buf, buflen, "%s", TAILQ_FIRST(&env->to)->mailbox);
284  else if (me && !TAILQ_EMPTY(&env->cc))
285  snprintf(buf, buflen, "%s", TAILQ_FIRST(&env->cc)->mailbox);
286  else if (!TAILQ_EMPTY(&env->from))
287  mutt_str_copy(buf, TAILQ_FIRST(&env->from)->mailbox, buflen);
288  else
289  *buf = '\0';
290 }
#define TAILQ_FIRST(head)
Definition: queue.h:716
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:57
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:59
bool check_for_mailing_list_addr(struct AddressList *al, char *buf, int buflen)
Check an address list for a mailing list.
Definition: maillist.c:103
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:716
bool mutt_addr_is_user(const struct Address *addr)
Does the address belong to the user.
Definition: alias.c:544
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
#define TAILQ_EMPTY(head)
Definition: queue.h:714
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ user_in_addr()

static bool user_in_addr ( struct AddressList *  al)
static

Do any of the addresses refer to the user?

Parameters
alAddressList
Return values
trueIf any of the addresses match one of the user's addresses

Definition at line 297 of file hdrline.c.

298 {
299  struct Address *a = NULL;
300  TAILQ_FOREACH(a, al, entries)
301  if (mutt_addr_is_user(a))
302  return true;
303  return false;
304 }
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
An email address.
Definition: address.h:34
bool mutt_addr_is_user(const struct Address *addr)
Does the address belong to the user.
Definition: alias.c:544
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ user_is_recipient()

static int user_is_recipient ( struct Email e)
static

Is the user a recipient of the message.

Parameters
eEmail to test
Return values
0User is not in list
1User is unique recipient
2User is in the TO list
3User is in the CC list
4User is originator
5Sent to a subscribed mailinglist
6User is in the Reply-To list

Definition at line 317 of file hdrline.c.

318 {
319  if (!e || !e->env)
320  return 0;
321 
322  struct Envelope *env = e->env;
323 
324  if (!e->recip_valid)
325  {
326  e->recip_valid = true;
327 
328  if (mutt_addr_is_user(TAILQ_FIRST(&env->from)))
329  e->recipient = 4;
330  else if (user_in_addr(&env->to))
331  {
332  if (TAILQ_NEXT(TAILQ_FIRST(&env->to), entries) || !TAILQ_EMPTY(&env->cc))
333  e->recipient = 2; /* non-unique recipient */
334  else
335  e->recipient = 1; /* unique recipient */
336  }
337  else if (user_in_addr(&env->cc))
338  e->recipient = 3;
339  else if (check_for_mailing_list(&env->to, NULL, NULL, 0))
340  e->recipient = 5;
341  else if (check_for_mailing_list(&env->cc, NULL, NULL, 0))
342  e->recipient = 5;
343  else if (user_in_addr(&env->reply_to))
344  e->recipient = 6;
345  else
346  e->recipient = 0;
347  }
348 
349  return e->recipient;
350 }
#define TAILQ_FIRST(head)
Definition: queue.h:716
struct AddressList reply_to
Email&#39;s &#39;reply-to&#39;.
Definition: envelope.h:62
static bool user_in_addr(struct AddressList *al)
Do any of the addresses refer to the user?
Definition: hdrline.c:297
short recipient
User_is_recipient()&#39;s return value, cached.
Definition: email.h:78
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:79
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:57
struct Envelope * env
Envelope information.
Definition: email.h:90
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:59
bool mutt_addr_is_user(const struct Address *addr)
Does the address belong to the user.
Definition: alias.c:544
bool recip_valid
Is_recipient is valid.
Definition: email.h:58
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
#define TAILQ_NEXT(elm, field)
Definition: queue.h:825
#define TAILQ_EMPTY(head)
Definition: queue.h:714
The header of an Email.
Definition: envelope.h:54
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ apply_subject_mods()

static char* apply_subject_mods ( struct Envelope env)
static

Apply regex modifications to the subject.

Parameters
envEnvelope of email
Return values
ptrModified subject
NULLNo modification made

Definition at line 358 of file hdrline.c.

359 {
360  if (!env)
361  return NULL;
362 
364  return env->subject;
365 
366  if (!env->subject || (*env->subject == '\0'))
367  {
368  env->disp_subj = NULL;
369  return NULL;
370  }
371 
373  return env->disp_subj;
374 }
struct ReplaceList SubjectRegexList
List of regexes to tidy the view of the email&#39;s subject.
Definition: globals.c:53
char * disp_subj
Display subject (modified copy of subject)
Definition: envelope.h:68
char * mutt_replacelist_apply(struct ReplaceList *rl, char *buf, size_t buflen, const char *str)
Apply replacements to a buffer.
Definition: regex.c:351
char * subject
Email&#39;s subject.
Definition: envelope.h:66
#define STAILQ_EMPTY(head)
Definition: queue.h:345
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ thread_is_new()

static bool thread_is_new ( struct Email e)
static

Does the email thread contain any new emails?

Parameters
eEmail
Return values
trueIf thread contains new mail

Definition at line 381 of file hdrline.c.

382 {
383  return e->collapsed && (e->num_hidden > 1) && (mutt_thread_contains_unread(e) == 1);
384 }
#define mutt_thread_contains_unread(e)
Definition: mutt_thread.h:85
size_t num_hidden
Number of hidden messages in this view (only valid when collapsed is set)
Definition: email.h:75
bool collapsed
Is this message part of a collapsed thread?
Definition: email.h:73
+ Here is the caller graph for this function:

◆ thread_is_old()

static bool thread_is_old ( struct Email e)
static

Does the email thread contain any unread emails?

Parameters
eEmail
Return values
trueIf thread contains unread mail

Definition at line 391 of file hdrline.c.

392 {
393  return e->collapsed && (e->num_hidden > 1) && (mutt_thread_contains_unread(e) == 2);
394 }
#define mutt_thread_contains_unread(e)
Definition: mutt_thread.h:85
size_t num_hidden
Number of hidden messages in this view (only valid when collapsed is set)
Definition: email.h:75
bool collapsed
Is this message part of a collapsed thread?
Definition: email.h:73
+ 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
%(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 452 of file hdrline.c.

456 {
457  struct HdrFormatInfo *hfi = (struct HdrFormatInfo *) data;
458  char fmt[128], tmp[1024];
459  char *p = NULL, *tags = NULL;
460  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
461  int threads = ((C_Sort & SORT_MASK) == SORT_THREADS);
462  int is_index = (flags & MUTT_FORMAT_INDEX);
463  size_t colorlen;
464 
465  struct Email *e = hfi->email;
466  size_t msg_in_pager = hfi->msg_in_pager;
467  struct Mailbox *m = hfi->mailbox;
468 
469  if (!e || !e->env)
470  return src;
471 
472  const struct Address *reply_to = TAILQ_FIRST(&e->env->reply_to);
473  const struct Address *from = TAILQ_FIRST(&e->env->from);
474  const struct Address *to = TAILQ_FIRST(&e->env->to);
475  const struct Address *cc = TAILQ_FIRST(&e->env->cc);
476 
477  buf[0] = '\0';
478  switch (op)
479  {
480  case 'A':
481  case 'I':
482  if (op == 'A')
483  {
484  if (reply_to && reply_to->mailbox)
485  {
486  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_AUTHOR);
487  mutt_format_s(buf + colorlen, buflen - colorlen, prec,
488  mutt_addr_for_display(reply_to));
489  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
490  break;
491  }
492  }
493  else
494  {
495  if (mutt_mb_get_initials(mutt_get_name(from), tmp, sizeof(tmp)))
496  {
497  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_AUTHOR);
498  mutt_format_s(buf + colorlen, buflen - colorlen, prec, tmp);
499  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
500  break;
501  }
502  }
503  /* fallthrough */
504 
505  case 'a':
506  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_AUTHOR);
507  if (from && from->mailbox)
508  {
509  mutt_format_s(buf + colorlen, buflen - colorlen, prec, mutt_addr_for_display(from));
510  }
511  else
512  mutt_format_s(buf + colorlen, buflen - colorlen, prec, "");
513  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
514  break;
515 
516  case 'B':
517  case 'K':
518  if (!first_mailing_list(buf, buflen, &e->env->to) &&
519  !first_mailing_list(buf, buflen, &e->env->cc))
520  {
521  buf[0] = '\0';
522  }
523  if (buf[0] != '\0')
524  {
525  mutt_str_copy(tmp, buf, sizeof(tmp));
526  mutt_format_s(buf, buflen, prec, tmp);
527  break;
528  }
529  if (op == 'K')
530  {
531  if (optional)
532  optional = false;
533  /* break if 'K' returns nothing */
534  break;
535  }
536  /* if 'B' returns nothing */
537  /* fallthrough */
538 
539  case 'b':
540  if (m)
541  {
542  p = strrchr(mailbox_path(m), '/');
543  if (p)
544  mutt_str_copy(buf, p + 1, buflen);
545  else
546  mutt_str_copy(buf, mailbox_path(m), buflen);
547  }
548  else
549  mutt_str_copy(buf, "(null)", buflen);
550  mutt_str_copy(tmp, buf, sizeof(tmp));
551  mutt_format_s(buf, buflen, prec, tmp);
552  break;
553 
554  case 'c':
555  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_SIZE);
556  if (src[0] == 'r')
557  {
558  mutt_str_pretty_size(tmp, sizeof(tmp), email_size(e));
559  src++;
560  }
561  else
562  {
563  mutt_str_pretty_size(tmp, sizeof(tmp), e->body->length);
564  }
565  mutt_format_s(buf + colorlen, buflen - colorlen, prec, tmp);
566  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
567  break;
568 
569  case 'C':
570  colorlen = add_index_color(fmt, sizeof(fmt), flags, MT_COLOR_INDEX_NUMBER);
571  snprintf(fmt + colorlen, sizeof(fmt) - colorlen, "%%%sd", prec);
572  add_index_color(fmt + colorlen, sizeof(fmt) - colorlen, flags, MT_COLOR_INDEX);
573  snprintf(buf, buflen, fmt, e->msgno + 1);
574  break;
575 
576  case 'd':
577  case 'D':
578  case '{':
579  case '[':
580  case '(':
581  case '<':
582  /* preprocess $date_format to handle %Z */
583  {
584  const char *cp = NULL;
585  time_t now;
586  int j = 0;
587 
588  if (optional && ((op == '[') || (op == '(')))
589  {
590  now = mutt_date_epoch();
591  struct tm tm = mutt_date_localtime(now);
592  now -= (op == '(') ? e->received : e->date_sent;
593 
594  char *is = (char *) prec;
595  bool invert = false;
596  if (*is == '>')
597  {
598  invert = true;
599  is++;
600  }
601 
602  while (*is && (*is != '?'))
603  {
604  int t = strtol(is, &is, 10);
605  /* semi-broken (assuming 30 days in all months) */
606  switch (*(is++))
607  {
608  case 'y':
609  if (t > 1)
610  {
611  t--;
612  t *= (60 * 60 * 24 * 365);
613  }
614  t += ((tm.tm_mon * 60 * 60 * 24 * 30) + (tm.tm_mday * 60 * 60 * 24) +
615  (tm.tm_hour * 60 * 60) + (tm.tm_min * 60) + tm.tm_sec);
616  break;
617 
618  case 'm':
619  if (t > 1)
620  {
621  t--;
622  t *= (60 * 60 * 24 * 30);
623  }
624  t += ((tm.tm_mday * 60 * 60 * 24) + (tm.tm_hour * 60 * 60) +
625  (tm.tm_min * 60) + tm.tm_sec);
626  break;
627 
628  case 'w':
629  if (t > 1)
630  {
631  t--;
632  t *= (60 * 60 * 24 * 7);
633  }
634  t += ((tm.tm_wday * 60 * 60 * 24) + (tm.tm_hour * 60 * 60) +
635  (tm.tm_min * 60) + tm.tm_sec);
636  break;
637 
638  case 'd':
639  if (t > 1)
640  {
641  t--;
642  t *= (60 * 60 * 24);
643  }
644  t += ((tm.tm_hour * 60 * 60) + (tm.tm_min * 60) + tm.tm_sec);
645  break;
646 
647  case 'H':
648  if (t > 1)
649  {
650  t--;
651  t *= (60 * 60);
652  }
653  t += ((tm.tm_min * 60) + tm.tm_sec);
654  break;
655 
656  case 'M':
657  if (t > 1)
658  {
659  t--;
660  t *= (60);
661  }
662  t += (tm.tm_sec);
663  break;
664 
665  default:
666  break;
667  }
668  j += t;
669  }
670 
671  if (j < 0)
672  j *= -1;
673 
674  if (((now > j) || (now < (-1 * j))) ^ invert)
675  optional = false;
676  break;
677  }
678 
679  p = buf;
680 
681  cp = ((op == 'd') || (op == 'D')) ? (NONULL(C_DateFormat)) : src;
682  bool do_locales;
683  if (*cp == '!')
684  {
685  do_locales = false;
686  cp++;
687  }
688  else
689  do_locales = true;
690 
691  size_t len = buflen - 1;
692  while ((len > 0) &&
693  ((((op == 'd') || (op == 'D')) && *cp) ||
694  ((op == '{') && (*cp != '}')) || ((op == '[') && (*cp != ']')) ||
695  ((op == '(') && (*cp != ')')) || ((op == '<') && (*cp != '>'))))
696  {
697  if (*cp == '%')
698  {
699  cp++;
700  if (((*cp == 'Z') || (*cp == 'z')) && ((op == 'd') || (op == '{')))
701  {
702  if (len >= 5)
703  {
704  sprintf(p, "%c%02u%02u", e->zoccident ? '-' : '+', e->zhours, e->zminutes);
705  p += 5;
706  len -= 5;
707  }
708  else
709  break; /* not enough space left */
710  }
711  else
712  {
713  if (len >= 2)
714  {
715  *p++ = '%';
716  *p++ = *cp;
717  len -= 2;
718  }
719  else
720  break; /* not enough space */
721  }
722  cp++;
723  }
724  else
725  {
726  *p++ = *cp++;
727  len--;
728  }
729  }
730  *p = '\0';
731 
732  struct tm tm;
733  if ((op == '[') || (op == 'D'))
735  else if (op == '(')
736  tm = mutt_date_localtime(e->received);
737  else if (op == '<')
738  {
740  }
741  else
742  {
743  /* restore sender's time zone */
744  now = e->date_sent;
745  if (e->zoccident)
746  now -= (e->zhours * 3600 + e->zminutes * 60);
747  else
748  now += (e->zhours * 3600 + e->zminutes * 60);
749  tm = mutt_date_gmtime(now);
750  }
751 
752  if (!do_locales)
753  setlocale(LC_TIME, "C");
754  strftime(tmp, sizeof(tmp), buf, &tm);
755  if (!do_locales)
756  setlocale(LC_TIME, "");
757 
758  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_DATE);
759  mutt_format_s(buf + colorlen, buflen - colorlen, prec, tmp);
760  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
761 
762  if ((len > 0) && (op != 'd') && (op != 'D')) /* Skip ending op */
763  src = cp + 1;
764  break;
765  }
766 
767  case 'e':
768  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
769  snprintf(buf, buflen, fmt, mutt_messages_in_thread(m, e, 1));
770  break;
771 
772  case 'E':
773  if (!optional)
774  {
775  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
776  snprintf(buf, buflen, fmt, mutt_messages_in_thread(m, e, 0));
777  }
778  else if (mutt_messages_in_thread(m, e, 0) <= 1)
779  optional = false;
780  break;
781 
782  case 'f':
783  tmp[0] = '\0';
784  mutt_addrlist_write(&e->env->from, tmp, sizeof(tmp), true);
785  mutt_format_s(buf, buflen, prec, tmp);
786  break;
787 
788  case 'F':
789  if (!optional)
790  {
791  const bool is_plain = (src[0] == 'p');
792  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_AUTHOR);
793  make_from(e->env, tmp, sizeof(tmp), false,
794  (is_plain ? MUTT_FORMAT_PLAIN : MUTT_FORMAT_NO_FLAGS));
795  mutt_format_s(buf + colorlen, buflen - colorlen, prec, tmp);
796  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
797 
798  if (is_plain)
799  src++;
800  }
801  else if (mutt_addr_is_user(from))
802  {
803  optional = false;
804  }
805  break;
806 
807  case 'g':
808  tags = driver_tags_get_transformed(&e->tags);
809  if (!optional)
810  {
811  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_TAGS);
812  mutt_format_s(buf + colorlen, buflen - colorlen, prec, NONULL(tags));
813  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
814  }
815  else if (!tags)
816  optional = false;
817  FREE(&tags);
818  break;
819 
820  case 'G':
821  {
822  char format[3];
823  char *tag = NULL;
824 
825  if (!optional)
826  {
827  format[0] = op;
828  format[1] = *src;
829  format[2] = '\0';
830 
831  tag = mutt_hash_find(TagFormats, format);
832  if (tag)
833  {
834  tags = driver_tags_get_transformed_for(&e->tags, tag);
835  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_TAG);
836  mutt_format_s(buf + colorlen, buflen - colorlen, prec, NONULL(tags));
837  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
838  FREE(&tags);
839  }
840  src++;
841  }
842  else
843  {
844  format[0] = op;
845  format[1] = *prec;
846  format[2] = '\0';
847 
848  tag = mutt_hash_find(TagFormats, format);
849  if (tag)
850  {
851  tags = driver_tags_get_transformed_for(&e->tags, tag);
852  if (!tags)
853  optional = false;
854  FREE(&tags);
855  }
856  }
857  break;
858  }
859 
860  case 'H':
861  /* (Hormel) spam score */
862  if (optional)
863  optional = !mutt_buffer_is_empty(&e->env->spam);
864 
865  mutt_format_s(buf, buflen, prec, mutt_b2s(&e->env->spam));
866  break;
867 
868  case 'i':
869  mutt_format_s(buf, buflen, prec, e->env->message_id ? e->env->message_id : "<no.id>");
870  break;
871 
872  case 'J':
873  {
874  bool have_tags = true;
875  tags = driver_tags_get_transformed(&e->tags);
876  if (tags)
877  {
878  if (flags & MUTT_FORMAT_TREE)
879  {
880  char *parent_tags = NULL;
881  if (e->thread->prev && e->thread->prev->message)
882  {
883  parent_tags = driver_tags_get_transformed(&e->thread->prev->message->tags);
884  }
885  if (!parent_tags && e->thread->parent && e->thread->parent->message)
886  {
887  parent_tags =
889  }
890  if (parent_tags && mutt_istr_equal(tags, parent_tags))
891  have_tags = false;
892  FREE(&parent_tags);
893  }
894  }
895  else
896  have_tags = false;
897 
898  if (optional)
899  optional = have_tags;
900 
901  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_TAGS);
902  if (have_tags)
903  mutt_format_s(buf + colorlen, buflen - colorlen, prec, tags);
904  else
905  mutt_format_s(buf + colorlen, buflen - colorlen, prec, "");
906  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
907  FREE(&tags);
908  break;
909  }
910 
911  case 'l':
912  if (!optional)
913  {
914  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
915  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_SIZE);
916  snprintf(buf + colorlen, buflen - colorlen, fmt, (int) e->lines);
917  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
918  }
919  else if (e->lines <= 0)
920  optional = false;
921  break;
922 
923  case 'L':
924  if (!optional)
925  {
926  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_AUTHOR);
927  make_from(e->env, tmp, sizeof(tmp), true, flags);
928  mutt_format_s(buf + colorlen, buflen - colorlen, prec, tmp);
929  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
930  }
931  else if (!check_for_mailing_list(&e->env->to, NULL, NULL, 0) &&
932  !check_for_mailing_list(&e->env->cc, NULL, NULL, 0))
933  {
934  optional = false;
935  }
936  break;
937 
938  case 'm':
939  if (m)
940  {
941  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
942  snprintf(buf, buflen, fmt, m->msg_count);
943  }
944  else
945  mutt_str_copy(buf, "(null)", buflen);
946  break;
947 
948  case 'n':
949  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_AUTHOR);
950  mutt_format_s(buf + colorlen, buflen - colorlen, prec, mutt_get_name(from));
951  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
952  break;
953 
954  case 'M':
955  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
956  if (!optional)
957  {
958  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_COLLAPSED);
959  if (threads && is_index && e->collapsed && (e->num_hidden > 1))
960  {
961  snprintf(buf + colorlen, buflen - colorlen, fmt, e->num_hidden);
962  add_index_color(buf, buflen - colorlen, flags, MT_COLOR_INDEX);
963  }
964  else if (is_index && threads)
965  {
966  mutt_format_s(buf + colorlen, buflen - colorlen, prec, " ");
967  add_index_color(buf, buflen - colorlen, flags, MT_COLOR_INDEX);
968  }
969  else
970  *buf = '\0';
971  }
972  else
973  {
974  if (!(threads && is_index && e->collapsed && (e->num_hidden > 1)))
975  optional = false;
976  }
977  break;
978 
979  case 'N':
980  if (!optional)
981  {
982  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
983  snprintf(buf, buflen, fmt, e->score);
984  }
985  else
986  {
987  if (e->score == 0)
988  optional = false;
989  }
990  break;
991 
992  case 'O':
993  if (!optional)
994  {
995  make_from_addr(e->env, tmp, sizeof(tmp), true);
996  if (!C_SaveAddress && (p = strpbrk(tmp, "%@")))
997  *p = '\0';
998  mutt_format_s(buf, buflen, prec, tmp);
999  }
1000  else if (!check_for_mailing_list_addr(&e->env->to, NULL, 0) &&
1001  !check_for_mailing_list_addr(&e->env->cc, NULL, 0))
1002  {
1003  optional = false;
1004  }
1005  break;
1006 
1007  case 'P':
1008  mutt_str_copy(buf, hfi->pager_progress, buflen);
1009  break;
1010 
1011 #ifdef USE_NNTP
1012  case 'q':
1013  mutt_format_s(buf, buflen, prec, e->env->newsgroups ? e->env->newsgroups : "");
1014  break;
1015 #endif
1016 
1017  case 'r':
1018  tmp[0] = '\0';
1019  mutt_addrlist_write(&e->env->to, tmp, sizeof(tmp), true);
1020  if (optional && (tmp[0] == '\0'))
1021  optional = false;
1022  mutt_format_s(buf, buflen, prec, tmp);
1023  break;
1024 
1025  case 'R':
1026  tmp[0] = '\0';
1027  mutt_addrlist_write(&e->env->cc, tmp, sizeof(tmp), true);
1028  if (optional && (tmp[0] == '\0'))
1029  optional = false;
1030  mutt_format_s(buf, buflen, prec, tmp);
1031  break;
1032 
1033  case 's':
1034  {
1035  char *subj = NULL;
1036  if (e->env->disp_subj)
1037  subj = e->env->disp_subj;
1038  else if (!STAILQ_EMPTY(&SubjectRegexList))
1039  subj = apply_subject_mods(e->env);
1040  else
1041  subj = e->env->subject;
1042  if (flags & MUTT_FORMAT_TREE && !e->collapsed)
1043  {
1044  if (flags & MUTT_FORMAT_FORCESUBJ)
1045  {
1046  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_SUBJECT);
1047  mutt_format_s(buf + colorlen, buflen - colorlen, "", NONULL(subj));
1048  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
1049  snprintf(tmp, sizeof(tmp), "%s%s", e->tree, buf);
1050  mutt_format_s_tree(buf, buflen, prec, tmp);
1051  }
1052  else
1053  mutt_format_s_tree(buf, buflen, prec, e->tree);
1054  }
1055  else
1056  {
1057  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_SUBJECT);
1058  mutt_format_s(buf + colorlen, buflen - colorlen, prec, NONULL(subj));
1059  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
1060  }
1061  break;
1062  }
1063 
1064  case 'S':
1065  {
1066  const char *wch = NULL;
1067  if (e->deleted)
1069  else if (e->attach_del)
1071  else if (e->tagged)
1073  else if (e->flagged)
1075  else if (e->replied)
1077  else if (e->read && (msg_in_pager != e->msgno))
1079  else if (e->old)
1081  else
1083 
1084  snprintf(tmp, sizeof(tmp), "%s", wch);
1085  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_FLAGS);
1086  mutt_format_s(buf + colorlen, buflen - colorlen, prec, tmp);
1087  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
1088  break;
1089  }
1090 
1091  case 't':
1092  tmp[0] = '\0';
1093  if (!check_for_mailing_list(&e->env->to, "To ", tmp, sizeof(tmp)) &&
1094  !check_for_mailing_list(&e->env->cc, "Cc ", tmp, sizeof(tmp)))
1095  {
1096  if (to)
1097  snprintf(tmp, sizeof(tmp), "To %s", mutt_get_name(to));
1098  else if (cc)
1099  snprintf(tmp, sizeof(tmp), "Cc %s", mutt_get_name(cc));
1100  }
1101  mutt_format_s(buf, buflen, prec, tmp);
1102  break;
1103 
1104  case 'T':
1105  {
1106  int i;
1107  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
1108  snprintf(buf, buflen, fmt,
1109  (C_ToChars && ((i = user_is_recipient(e))) < C_ToChars->len) ?
1110  C_ToChars->chars[i] :
1111  " ");
1112  break;
1113  }
1114 
1115  case 'u':
1116  if (from && from->mailbox)
1117  {
1118  mutt_str_copy(tmp, mutt_addr_for_display(from), sizeof(tmp));
1119  p = strpbrk(tmp, "%@");
1120  if (p)
1121  *p = '\0';
1122  }
1123  else
1124  tmp[0] = '\0';
1125  mutt_format_s(buf, buflen, prec, tmp);
1126  break;
1127 
1128  case 'v':
1129  if (mutt_addr_is_user(from))
1130  {
1131  if (to)
1132  mutt_format_s(tmp, sizeof(tmp), prec, mutt_get_name(to));
1133  else if (cc)
1134  mutt_format_s(tmp, sizeof(tmp), prec, mutt_get_name(cc));
1135  else
1136  *tmp = '\0';
1137  }
1138  else
1139  mutt_format_s(tmp, sizeof(tmp), prec, mutt_get_name(from));
1140  p = strpbrk(tmp, " %@");
1141  if (p)
1142  *p = '\0';
1143  mutt_format_s(buf, buflen, prec, tmp);
1144  break;
1145 
1146  case 'W':
1147  if (!optional)
1148  {
1149  mutt_format_s(buf, buflen, prec, e->env->organization ? e->env->organization : "");
1150  }
1151  else if (!e->env->organization)
1152  optional = false;
1153  break;
1154 
1155 #ifdef USE_NNTP
1156  case 'x':
1157  if (!optional)
1158  {
1159  mutt_format_s(buf, buflen, prec, e->env->x_comment_to ? e->env->x_comment_to : "");
1160  }
1161  else if (!e->env->x_comment_to)
1162  optional = false;
1163  break;
1164 #endif
1165 
1166  case 'X':
1167  {
1168  int count = mutt_count_body_parts(m, e);
1169 
1170  /* The recursion allows messages without depth to return 0. */
1171  if (optional)
1172  optional = (count != 0);
1173 
1174  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
1175  snprintf(buf, buflen, fmt, count);
1176  break;
1177  }
1178 
1179  case 'y':
1180  if (optional)
1181  optional = (e->env->x_label != NULL);
1182 
1183  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_LABEL);
1184  mutt_format_s(buf + colorlen, buflen - colorlen, prec, NONULL(e->env->x_label));
1185  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
1186  break;
1187 
1188  case 'Y':
1189  {
1190  bool label = true;
1191  if (e->env->x_label)
1192  {
1193  struct Email *e_tmp = NULL;
1194  if (flags & MUTT_FORMAT_TREE && (e->thread->prev && e->thread->prev->message &&
1195  e->thread->prev->message->env->x_label))
1196  {
1197  e_tmp = e->thread->prev->message;
1198  }
1199  else if (flags & MUTT_FORMAT_TREE &&
1200  (e->thread->parent && e->thread->parent->message &&
1201  e->thread->parent->message->env->x_label))
1202  {
1203  e_tmp = e->thread->parent->message;
1204  }
1205  if (e_tmp && mutt_istr_equal(e->env->x_label, e_tmp->env->x_label))
1206  label = false;
1207  }
1208  else
1209  label = false;
1210 
1211  if (optional)
1212  optional = label;
1213 
1214  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_LABEL);
1215  if (label)
1216  mutt_format_s(buf + colorlen, buflen - colorlen, prec, NONULL(e->env->x_label));
1217  else
1218  mutt_format_s(buf + colorlen, buflen - colorlen, prec, "");
1219  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
1220  break;
1221  }
1222 
1223  case 'z':
1224  if (src[0] == 's') /* status: deleted/new/old/replied */
1225  {
1226  const char *ch = NULL;
1227  if (e->deleted)
1229  else if (e->attach_del)
1231  else if (threads && thread_is_new(e))
1233  else if (threads && thread_is_old(e))
1235  else if (e->read && (msg_in_pager != e->msgno))
1236  {
1237  if (e->replied)
1239  else
1241  }
1242  else
1243  {
1244  if (e->old)
1246  else
1248  }
1249 
1250  snprintf(tmp, sizeof(tmp), "%s", ch);
1251  src++;
1252  }
1253  else if (src[0] == 'c') /* crypto */
1254  {
1255  const char *ch = "";
1256  if ((WithCrypto != 0) && (e->security & SEC_GOODSIGN))
1258  else if ((WithCrypto != 0) && (e->security & SEC_ENCRYPT))
1260  else if ((WithCrypto != 0) && (e->security & SEC_SIGN))
1262  else if (((WithCrypto & APPLICATION_PGP) != 0) && ((e->security & PGP_KEY) == PGP_KEY))
1263  {
1265  }
1266  else
1268 
1269  snprintf(tmp, sizeof(tmp), "%s", ch);
1270  src++;
1271  }
1272  else if (src[0] == 't') /* tagged, flagged, recipient */
1273  {
1274  const char *ch = "";
1275  if (e->tagged)
1277  else if (e->flagged)
1279  else
1281 
1282  snprintf(tmp, sizeof(tmp), "%s", ch);
1283  src++;
1284  }
1285  else /* fallthrough */
1286  break;
1287 
1288  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_FLAGS);
1289  mutt_format_s(buf + colorlen, buflen - colorlen, prec, tmp);
1290  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
1291  break;
1292 
1293  case 'Z':
1294  {
1295  /* New/Old for threads; replied; New/Old for messages */
1296  const char *first = NULL;
1297  if (threads && thread_is_new(e))
1299  else if (threads && thread_is_old(e))
1301  else if (e->read && (msg_in_pager != e->msgno))
1302  {
1303  if (e->replied)
1305  else
1307  }
1308  else
1309  {
1310  if (e->old)
1312  else
1314  }
1315 
1316  /* Marked for deletion; deleted attachments; crypto */
1317  const char *second = "";
1318  if (e->deleted)
1320  else if (e->attach_del)
1322  else if ((WithCrypto != 0) && (e->security & SEC_GOODSIGN))
1324  else if ((WithCrypto != 0) && (e->security & SEC_ENCRYPT))
1326  else if ((WithCrypto != 0) && (e->security & SEC_SIGN))
1328  else if (((WithCrypto & APPLICATION_PGP) != 0) && (e->security & PGP_KEY))
1330  else
1332 
1333  /* Tagged, flagged and recipient flag */
1334  const char *third = "";
1335  if (e->tagged)
1337  else if (e->flagged)
1339  else
1341 
1342  snprintf(tmp, sizeof(tmp), "%s%s%s", first, second, third);
1343  }
1344 
1345  colorlen = add_index_color(buf, buflen, flags, MT_COLOR_INDEX_FLAGS);
1346  mutt_format_s(buf + colorlen, buflen - colorlen, prec, tmp);
1347  add_index_color(buf + colorlen, buflen - colorlen, flags, MT_COLOR_INDEX);
1348  break;
1349 
1350  case '@':
1351  {
1352  const char *end = src;
1353  static unsigned char recurse = 0;
1354 
1355  while ((*end != '\0') && (*end != '@'))
1356  end++;
1357  if ((*end == '@') && (recurse < 20))
1358  {
1359  recurse++;
1360  mutt_strn_copy(tmp, src, end - src, sizeof(tmp));
1361  mutt_expando_format(tmp, sizeof(tmp), col, cols,
1362  NONULL(mutt_idxfmt_hook(tmp, m, e)),
1363  index_format_str, data, flags);
1364  mutt_format_s_x(buf, buflen, prec, tmp, true);
1365  recurse--;
1366 
1367  src = end + 1;
1368  break;
1369  }
1370  }
1371  /* fallthrough */
1372 
1373  default:
1374  snprintf(buf, buflen, "%%%s%c", prec, op);
1375  break;
1376  }
1377 
1378  if (optional)
1379  {
1380  mutt_expando_format(buf, buflen, col, cols, if_str, index_format_str,
1381  (intptr_t) hfi, flags);
1382  }
1383  else if (flags & MUTT_FORMAT_OPTIONAL)
1384  {
1385  mutt_expando_format(buf, buflen, col, cols, else_str, index_format_str,
1386  (intptr_t) hfi, flags);
1387  }
1388 
1389  return src;
1390 }
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:416
Character denoting a tagged email.
Definition: hdrline.c:71
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:201
Index: index number.
Definition: color.h:109
Character denoting a important (flagged) email.
Definition: hdrline.c:72
int lines
How many lines in the body of this message?
Definition: email.h:85
#define NONULL(x)
Definition: string2.h:37
int msg_count
Total number of messages.
Definition: mailbox.h:91
#define WithCrypto
Definition: lib.h:123
The envelope/body of an email.
Definition: email.h:37
Index: tags field (g, J)
Definition: color.h:111
#define TAILQ_FIRST(head)
Definition: queue.h:716
char ** chars
The array of multibyte character strings.
Definition: mbtable.h:39
struct Body * body
List of MIME parts.
Definition: email.h:91
struct ReplaceList SubjectRegexList
List of regexes to tidy the view of the email&#39;s subject.
Definition: globals.c:53
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:643
#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:381
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:79
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:85
bool attach_del
Has an attachment marked for deletion.
Definition: email.h:49
Character denoting a message contains a PGP key.
Definition: hdrline.c:92
An email address.
Definition: address.h:34
#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:37
Character denoting a read email, $index_format S expando.
Definition: hdrline.c:80
struct tm mutt_date_gmtime(time_t t)
Converts calendar time to a broken-down time structure expressed in UTC timezone. ...
Definition: date.c:661
static bool thread_is_old(struct Email *e)
Does the email thread contain any unread emails?
Definition: hdrline.c:391
bool zoccident
True, if west of UTC, False if east.
Definition: email.h:65
Index: number of messages in collapsed thread.
Definition: color.h:106
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
struct MbTable * C_ToChars
Config: Indicator characters for the &#39;To&#39; field in the index.
Definition: hdrline.c:64
static char * apply_subject_mods(struct Envelope *env)
Apply regex modifications to the subject.
Definition: hdrline.c:358
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:211
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:79
Index: author field (takes a pattern)
Definition: color.h:101
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.h:44
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:104
Character denoting a deleted attachment.
Definition: hdrline.c:74
struct Mailbox * mailbox
Definition: hdrline.h:46
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:76
static int user_is_recipient(struct Email *e)
Is the user a recipient of the message.
Definition: hdrline.c:317
Character denoting a thread of emails that has been read.
Definition: hdrline.c:78
WHERE short C_Sort
Config: Sort method for the index.
Definition: sort.h:60
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:883
time_t date_sent
Time when the message was sent (UTC)
Definition: email.h:82
#define mutt_b2s(buf)
Definition: buffer.h:41
Index: date field.
Definition: color.h:107
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:866
Sort by email threads.
Definition: sort2.h:52
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:97
Character denoting an email that has been replied to.
Definition: hdrline.c:75
Index: size field.
Definition: color.h:110
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:169
WHERE bool C_SaveAddress
Config: Use sender&#39;s full address as a default save folder.
Definition: mutt_globals.h:156
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:1207
bool check_for_mailing_list_addr(struct AddressList *al, char *buf, int buflen)
Check an address list for a mailing list.
Definition: maillist.c:103
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:267
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:1659
Character denoting a message signed with a verified key.
Definition: hdrline.c:89
bool mutt_mb_get_initials(const char *name, char *buf, size_t buflen)
Turn a name into initials.
Definition: mbyte.c:84
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:121
int msg_in_pager
Definition: hdrline.h:47
bool collapsed
Is this message part of a collapsed thread?
Definition: email.h:73
Character denoting a message is PGP-encrypted.
Definition: hdrline.c:90
int mutt_messages_in_thread(struct Mailbox *m, struct Email *e, int flag)
Count the messages in a thread.
Definition: mutt_thread.c:1479
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
static const char * get_nth_wchar(struct MbTable *table, int index)
Extract one char from a multi-byte table.
Definition: hdrline.c:158
#define SEC_SIGN
Email is signed.
Definition: lib.h:86
Character denoting a read email, $index_format Z expando.
Definition: hdrline.c:81
#define MUTT_FORMAT_INDEX
This is a main index entry.
Definition: format_flags.h:36
Index: label field.
Definition: color.h:108
char * subject
Email&#39;s subject.
Definition: envelope.h:66
WHERE char * C_DateFormat
Config: strftime format string for the d expando.
Definition: mutt_globals.h:89
Index: subject field (takes a pattern)
Definition: color.h:103
void mutt_format_s(char *buf, size_t buflen, const char *prec, const char *s)
Format a simple string.
Definition: curs_lib.c:1244
#define PGP_KEY
Definition: lib.h:106
#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:716
Character denoting a deleted email.
Definition: hdrline.c:73
struct MbTable * C_FlagChars
Config: User-configurable index flags: tagged, new, etc.
Definition: hdrline.c:62
char * driver_tags_get_transformed(struct TagList *list)
Get transformed tags.
Definition: tags.c:130
bool deleted
Email is deleted.
Definition: email.h:45
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:772
bool replied
Email has been replied to.
Definition: email.h:54
Character denoting an unread email.
Definition: hdrline.c:77
Character denoting a message has no cryptography information.
Definition: hdrline.c:93
#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:544
const char * pager_progress
Definition: hdrline.h:49
char * organization
Organisation header.
Definition: envelope.h:73
Character denoting a message is signed.
Definition: hdrline.c:91
#define STAILQ_EMPTY(head)
Definition: queue.h:345
#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
int mutt_count_body_parts(struct Mailbox *m, struct Email *e)
Count the MIME Body parts.
Definition: mutt_parse.c:205
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:125
Index: default colour (takes a pattern)
Definition: color.h:100
struct MbTable * C_CryptChars
Config: User-configurable crypto flags: signed, encrypted etc.
Definition: hdrline.c:61
WHERE struct HashTable * TagFormats
Hash Table of tag-formats (tag -> format string)
Definition: mutt_globals.h:59
struct Email * email
Definition: hdrline.h:48
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:87
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
size_t email_size(const struct Email *e)
compute the size of an email
Definition: email.c:117
#define SORT_MASK
Mask for the sort id.
Definition: sort2.h:81
time_t received
Time when the message was placed in the mailbox.
Definition: email.h:83
static const char * index_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
Format a string for the index list - Implements format_t.
Definition: hdrline.c:452
Index: flags field (takes a pattern)
Definition: color.h:102
struct Buffer spam
Spam header.
Definition: envelope.h:80
int len
Number of characters.
Definition: mbtable.h:38
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:1256
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:157
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_make_string_flags()

void mutt_make_string_flags ( char *  buf,
size_t  buflen,
int  cols,
const char *  s,
struct Mailbox m,
int  inpgr,
struct Email e,
MuttFormatFlags  flags 
)

Create formatted strings using mailbox expandos.

Parameters
bufBuffer for the result
buflenBuffer length
colsNumber of screen columns (OPTIONAL)
sprintf-line format string
mMailbox
inpgrMessage shown in the pager
eEmail
flagsFlags, see MuttFormatFlags

Definition at line 1403 of file hdrline.c.

1406 {
1407  struct HdrFormatInfo hfi;
1408 
1409  hfi.email = e;
1410  hfi.mailbox = m;
1411  hfi.msg_in_pager = inpgr;
1412  hfi.pager_progress = 0;
1413 
1414  mutt_expando_format(buf, buflen, 0, cols, s, index_format_str, (intptr_t) &hfi, flags);
1415 }
Data passed to index_format_str()
Definition: hdrline.h:44
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:772
struct Email * email
Definition: hdrline.h:48
static const char * index_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
Format a string for the index list - Implements format_t.
Definition: hdrline.c:452
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_make_string_info()

void mutt_make_string_info ( char *  buf,
size_t  buflen,
int  cols,
const char *  s,
struct HdrFormatInfo hfi,
MuttFormatFlags  flags 
)

Create pager status bar string.

Parameters
bufBuffer for the result
buflenBuffer length
colsNumber of screen columns
sprintf-line format string
hfiMailbox data to pass to the formatter
flagsFlags, see MuttFormatFlags

Definition at line 1426 of file hdrline.c.

1428 {
1429  mutt_expando_format(buf, buflen, 0, cols, s, index_format_str, (intptr_t) hfi, flags);
1430 }
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:772
static const char * index_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
Format a string for the index list - Implements format_t.
Definition: hdrline.c:452
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ C_CryptChars

struct MbTable* C_CryptChars

Config: User-configurable crypto flags: signed, encrypted etc.

Definition at line 61 of file hdrline.c.

◆ C_FlagChars

struct MbTable* C_FlagChars

Config: User-configurable index flags: tagged, new, etc.

Definition at line 62 of file hdrline.c.

◆ C_FromChars

struct MbTable* C_FromChars

Config: User-configurable index flags: to address, cc address, etc.

Definition at line 63 of file hdrline.c.

◆ C_ToChars

struct MbTable* C_ToChars

Config: Indicator characters for the 'To' field in the index.

Definition at line 64 of file hdrline.c.