NeoMutt
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
Expando API

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

Functions

static const char * alias_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Format a string for the alias list - Implements format_t -.
 
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 -.
 
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 -.
 
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 -.
 
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 -.
 
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 -.
 
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 -.
 
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 -.
 
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 -.
 
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 -.
 
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 -.
 
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 -.
 
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 -.
 
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 -.
 
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 -.
 
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 -.
 
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 -.
 
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 -.
 
static const char * greeting_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 greetings string - Implements format_t -.
 
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 -.
 
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 -.
 

Detailed Description

Prototype for a mutt_expando_format() Callback Function.

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

Each callback function implements some expandos, e.g.

Expando Description
%t Title

Function Documentation

◆ alias_format_str()

static const char * alias_format_str ( char *  buf,
size_t  buflen,
size_t  col,
int  cols,
char  op,
const char *  src,
const char *  prec,
const char *  if_str,
const char *  else_str,
intptr_t  data,
MuttFormatFlags  flags 
)
static

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

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

Definition at line 122 of file dlg_alias.c.

126{
127 char tmp[1024];
128 struct AliasView *av = (struct AliasView *) data;
129 struct Alias *alias = av->alias;
130
131 switch (op)
132 {
133 case 'a':
134 mutt_format_s(buf, buflen, prec, alias->name);
135 break;
136 case 'c':
137 mutt_format_s(buf, buflen, prec, alias->comment);
138 break;
139 case 'f':
140 snprintf(tmp, sizeof(tmp), "%%%ss", prec);
141 snprintf(buf, buflen, tmp, av->is_deleted ? "D" : " ");
142 break;
143 case 'n':
144 snprintf(tmp, sizeof(tmp), "%%%sd", prec);
145 snprintf(buf, buflen, tmp, av->num + 1);
146 break;
147 case 'r':
148 {
149 struct Buffer *tmpbuf = buf_pool_get();
150 mutt_addrlist_write(&alias->addr, tmpbuf, true);
151 mutt_str_copy(tmp, buf_string(tmpbuf), sizeof(tmp));
152 buf_pool_release(&tmpbuf);
153 mutt_format_s(buf, buflen, prec, tmp);
154 break;
155 }
156 case 't':
157 buf[0] = av->is_tagged ? '*' : ' ';
158 buf[1] = '\0';
159 break;
160 }
161
162 return src;
163}
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
Definition: address.c:1207
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:93
void mutt_format_s(char *buf, size_t buflen, const char *prec, const char *s)
Format a simple string.
Definition: curs_lib.c:522
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:653
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
GUI data wrapping an Alias.
Definition: gui.h:36
struct Alias * alias
Alias.
Definition: gui.h:44
bool is_deleted
Is it deleted?
Definition: gui.h:42
bool is_tagged
Is it tagged?
Definition: gui.h:41
int num
Index number in list.
Definition: gui.h:37
A shortcut for an email address or addresses.
Definition: alias.h:34
char * comment
Free-form comment string.
Definition: alias.h:37
char * name
Short name.
Definition: alias.h:35
struct AddressList addr
List of Addresses the Alias expands to.
Definition: alias.h:36
String manipulation buffer.
Definition: buffer.h:34
+ 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 152 of file dlg_query.c.

156{
157 struct AliasView *av = (struct AliasView *) data;
158 struct Alias *alias = av->alias;
159 char fmt[128] = { 0 };
160 bool optional = (flags & MUTT_FORMAT_OPTIONAL);
161
162 switch (op)
163 {
164 case 'a':
165 {
166 struct Buffer *tmpbuf = buf_pool_get();
167 char tmp[256] = { 0 };
168 tmp[0] = '<';
169 mutt_addrlist_write(&alias->addr, tmpbuf, true);
170 mutt_str_copy(tmp + 1, buf_string(tmpbuf), sizeof(tmp) - 1);
171 buf_pool_release(&tmpbuf);
172 const size_t len = strlen(tmp);
173 if (len < (sizeof(tmp) - 1))
174 {
175 tmp[len] = '>';
176 tmp[len + 1] = '\0';
177 }
178 mutt_format_s(buf, buflen, prec, tmp);
179 break;
180 }
181 case 'c':
182 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
183 snprintf(buf, buflen, fmt, av->num + 1);
184 break;
185 case 'e':
186 if (!optional)
187 mutt_format_s(buf, buflen, prec, NONULL(alias->comment));
188 else if (!alias->comment || (*alias->comment == '\0'))
189 optional = false;
190 break;
191 case 'n':
192 mutt_format_s(buf, buflen, prec, NONULL(alias->name));
193 break;
194 case 't':
195 snprintf(fmt, sizeof(fmt), "%%%sc", prec);
196 snprintf(buf, buflen, fmt, av->is_tagged ? '*' : ' ');
197 break;
198 default:
199 snprintf(fmt, sizeof(fmt), "%%%sc", prec);
200 snprintf(buf, buflen, fmt, op);
201 break;
202 }
203
204 if (optional)
205 {
206 mutt_expando_format(buf, buflen, col, cols, if_str, query_format_str, data,
208 }
209 else if (flags & MUTT_FORMAT_OPTIONAL)
210 {
211 mutt_expando_format(buf, buflen, col, cols, else_str, query_format_str,
213 }
214
215 /* We return the format string, unchanged */
216 return src;
217}
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
#define MUTT_FORMAT_OPTIONAL
Allow optional field processing.
Definition: format_flags.h:33
static const char * query_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
Format a string for the query menu - Implements format_t -.
Definition: dlg_query.c:152
void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t callback, intptr_t data, MuttFormatFlags flags)
Expand expandos (x) in a string -.
Definition: muttlib.c:745
#define NONULL(x)
Definition: string2.h:37
char * data
Pointer to data.
Definition: buffer.h:35
+ 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 151 of file dlg_attach.c.

154{
155 char fmt[128] = { 0 };
156 char charset[128] = { 0 };
157 struct AttachPtr *aptr = (struct AttachPtr *) data;
158 bool optional = (flags & MUTT_FORMAT_OPTIONAL);
159
160 switch (op)
161 {
162 case 'C':
163 if (!optional)
164 {
165 if (mutt_is_text_part(aptr->body) &&
166 mutt_body_get_charset(aptr->body, charset, sizeof(charset)))
167 {
168 mutt_format_s(buf, buflen, prec, charset);
169 }
170 else
171 {
172 mutt_format_s(buf, buflen, prec, "");
173 }
174 }
175 else if (!mutt_is_text_part(aptr->body) ||
176 !mutt_body_get_charset(aptr->body, charset, sizeof(charset)))
177 {
178 optional = false;
179 }
180 break;
181 case 'c':
182 /* XXX */
183 if (!optional)
184 {
185 snprintf(fmt, sizeof(fmt), "%%%sc", prec);
186 snprintf(buf, buflen, fmt,
187 ((aptr->body->type != TYPE_TEXT) || aptr->body->noconv) ? 'n' : 'c');
188 }
189 else if ((aptr->body->type != TYPE_TEXT) || aptr->body->noconv)
190 {
191 optional = false;
192 }
193 break;
194 case 'd':
195 {
196 const char *const c_message_format = cs_subset_string(NeoMutt->sub, "message_format");
197 if (!optional)
198 {
199 if (aptr->body->description)
200 {
201 mutt_format_s(buf, buflen, prec, aptr->body->description);
202 break;
203 }
204 if (mutt_is_message_type(aptr->body->type, aptr->body->subtype) &&
205 c_message_format && aptr->body->email)
206 {
207 char s[128] = { 0 };
208 mutt_make_string(s, sizeof(s), cols, c_message_format, NULL, -1,
209 aptr->body->email,
211 if (*s)
212 {
213 mutt_format_s(buf, buflen, prec, s);
214 break;
215 }
216 }
217 if (!aptr->body->d_filename && !aptr->body->filename)
218 {
219 mutt_format_s(buf, buflen, prec, "<no description>");
220 break;
221 }
222 }
223 else if (aptr->body->description ||
224 (mutt_is_message_type(aptr->body->type, aptr->body->subtype) &&
225 c_message_format && aptr->body->email))
226 {
227 break;
228 }
229 }
230 /* fallthrough */
231 case 'F':
232 if (!optional)
233 {
234 if (aptr->body->d_filename)
235 {
236 mutt_format_s(buf, buflen, prec, aptr->body->d_filename);
237 break;
238 }
239 }
240 else if (!aptr->body->d_filename && !aptr->body->filename)
241 {
242 optional = false;
243 break;
244 }
245 /* fallthrough */
246 case 'f':
247 if (!optional)
248 {
249 if (aptr->body->filename && (*aptr->body->filename == '/'))
250 {
251 struct Buffer *path = buf_pool_get();
252
253 buf_strcpy(path, aptr->body->filename);
254 buf_pretty_mailbox(path);
255 mutt_format_s(buf, buflen, prec, buf_string(path));
256 buf_pool_release(&path);
257 }
258 else
259 {
260 mutt_format_s(buf, buflen, prec, NONULL(aptr->body->filename));
261 }
262 }
263 else if (!aptr->body->filename)
264 {
265 optional = false;
266 }
267 break;
268 case 'D':
269 if (!optional)
270 snprintf(buf, buflen, "%c", aptr->body->deleted ? 'D' : ' ');
271 else if (!aptr->body->deleted)
272 optional = false;
273 break;
274 case 'e':
275 if (!optional)
276 mutt_format_s(buf, buflen, prec, ENCODING(aptr->body->encoding));
277 break;
278 case 'I':
279 if (optional)
280 break;
281
282 const char dispchar[] = { 'I', 'A', 'F', '-' };
283 char ch;
284
285 if (aptr->body->disposition < sizeof(dispchar))
286 {
287 ch = dispchar[aptr->body->disposition];
288 }
289 else
290 {
291 mutt_debug(LL_DEBUG1, "ERROR: invalid content-disposition %d\n",
292 aptr->body->disposition);
293 ch = '!';
294 }
295 snprintf(buf, buflen, "%c", ch);
296 break;
297 case 'm':
298 if (!optional)
299 mutt_format_s(buf, buflen, prec, TYPE(aptr->body));
300 break;
301 case 'M':
302 if (!optional)
303 mutt_format_s(buf, buflen, prec, aptr->body->subtype);
304 else if (!aptr->body->subtype)
305 optional = false;
306 break;
307 case 'n':
308 if (optional)
309 break;
310
311 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
312 snprintf(buf, buflen, fmt, aptr->num + 1);
313 break;
314 case 'Q':
315 if (optional)
316 {
317 optional = aptr->body->attach_qualifies;
318 }
319 else
320 {
321 snprintf(fmt, sizeof(fmt), "%%%sc", prec);
322 mutt_format_s(buf, buflen, fmt, "Q");
323 }
324 break;
325 case 's':
326 {
327 size_t l = 0;
328 if (aptr->body->filename && (flags & MUTT_FORMAT_STAT_FILE))
329 {
330 l = mutt_file_get_size(aptr->body->filename);
331 }
332 else
333 {
334 l = aptr->body->length;
335 }
336
337 if (!optional)
338 {
339 char tmp[128] = { 0 };
340 mutt_str_pretty_size(tmp, sizeof(tmp), l);
341 mutt_format_s(buf, buflen, prec, tmp);
342 }
343 else if (l == 0)
344 {
345 optional = false;
346 }
347
348 break;
349 }
350 case 't':
351 if (!optional)
352 snprintf(buf, buflen, "%c", aptr->body->tagged ? '*' : ' ');
353 else if (!aptr->body->tagged)
354 optional = false;
355 break;
356 case 'T':
357 if (!optional)
358 mutt_format_s_tree(buf, buflen, prec, NONULL(aptr->tree));
359 else if (!aptr->tree)
360 optional = false;
361 break;
362 case 'u':
363 if (!optional)
364 snprintf(buf, buflen, "%c", aptr->body->unlink ? '-' : ' ');
365 else if (!aptr->body->unlink)
366 optional = false;
367 break;
368 case 'X':
369 if (optional)
370 {
371 optional = ((aptr->body->attach_count + aptr->body->attach_qualifies) != 0);
372 }
373 else
374 {
375 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
376 snprintf(buf, buflen, fmt, aptr->body->attach_count + aptr->body->attach_qualifies);
377 }
378 break;
379 default:
380 *buf = '\0';
381 }
382
383 if (optional)
384 {
385 mutt_expando_format(buf, buflen, col, cols, if_str, attach_format_str, data,
387 }
388 else if (flags & MUTT_FORMAT_OPTIONAL)
389 {
390 mutt_expando_format(buf, buflen, col, cols, else_str, attach_format_str,
392 }
393
394 /* We return the format string, unchanged */
395 return src;
396}
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:407
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:292
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:534
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body's character set.
Definition: body.c:131
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition: parse.c:1482
long mutt_file_get_size(const char *path)
Get the size of a file.
Definition: file.c:1560
#define MUTT_FORMAT_FORCESUBJ
Print the subject even if unchanged.
Definition: format_flags.h:31
#define MUTT_FORMAT_ARROWCURSOR
Reserve space for arrow_cursor.
Definition: format_flags.h:35
#define MUTT_FORMAT_STAT_FILE
Used by attach_format_str.
Definition: format_flags.h:34
const char * attach_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
Format a string for the attachment menu - Implements format_t -.
Definition: dlg_attach.c:151
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
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:1426
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
@ TYPE_TEXT
Type: 'text/*'.
Definition: mime.h:38
#define ENCODING(x)
Definition: mime.h:92
#define TYPE(body)
Definition: mime.h:89
void buf_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
Definition: muttlib.c:562
void mutt_str_pretty_size(char *buf, size_t buflen, size_t num)
Display an abbreviated size, like 3.4K.
Definition: muttlib.c:1651
bool mutt_is_text_part(struct Body *b)
Is this part of an email in plain text?
Definition: muttlib.c:450
An email to which things will be attached.
Definition: attach.h:35
struct Body * body
Attachment.
Definition: attach.h:36
char * tree
Tree characters to display.
Definition: attach.h:39
int num
Attachment index number.
Definition: attach.h:41
char * d_filename
filename to be used for the content-disposition header If NULL, filename is used instead.
Definition: body.h:56
signed short attach_count
Number of attachments.
Definition: body.h:90
bool deleted
Attachment marked for deletion.
Definition: body.h:87
bool noconv
Don't do character set conversion.
Definition: body.h:46
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:67
LOFF_T length
length (in bytes) of attachment
Definition: body.h:53
struct Email * email
header information for message/rfc822
Definition: body.h:73
char * description
content-description
Definition: body.h:55
unsigned int disposition
content-disposition, ContentDisposition
Definition: body.h:42
bool attach_qualifies
This attachment should be counted.
Definition: body.h:86
bool tagged
This attachment is tagged.
Definition: body.h:89
char * subtype
content-type subtype
Definition: body.h:60
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:41
unsigned int type
content-type primary type, ContentType
Definition: body.h:40
char * filename
When sending a message, this is the file to which this structure refers.
Definition: body.h:58
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
+ 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 123 of file dlg_autocrypt.c.

127{
128 struct AccountEntry *entry = (struct AccountEntry *) data;
129 char tmp[128] = { 0 };
130
131 switch (op)
132 {
133 case 'a':
134 mutt_format_s(buf, buflen, prec, buf_string(entry->addr->mailbox));
135 break;
136 case 'k':
137 mutt_format_s(buf, buflen, prec, entry->account->keyid);
138 break;
139 case 'n':
140 snprintf(tmp, sizeof(tmp), "%%%sd", prec);
141 snprintf(buf, buflen, tmp, entry->num);
142 break;
143 case 'p':
144 if (entry->account->prefer_encrypt)
145 {
146 /* L10N: Autocrypt Account menu.
147 flag that an account has prefer-encrypt set */
148 mutt_format_s(buf, buflen, prec, _("prefer encrypt"));
149 }
150 else
151 {
152 /* L10N: Autocrypt Account menu.
153 flag that an account has prefer-encrypt unset;
154 thus encryption will need to be manually enabled. */
155 mutt_format_s(buf, buflen, prec, _("manual encrypt"));
156 }
157 break;
158 case 's':
159 if (entry->account->enabled)
160 {
161 /* L10N: Autocrypt Account menu.
162 flag that an account is enabled/active */
163 mutt_format_s(buf, buflen, prec, _("active"));
164 }
165 else
166 {
167 /* L10N: Autocrypt Account menu.
168 flag that an account is disabled/inactive */
169 mutt_format_s(buf, buflen, prec, _("inactive"));
170 }
171 break;
172 }
173
174 return (src);
175}
#define _(a)
Definition: message.h:28
An entry in the Autocrypt account Menu.
Definition: private.h:44
struct Address * addr
Email address associated with the account.
Definition: private.h:47
struct AutocryptAccount * account
Account details.
Definition: private.h:46
int num
Number in the index.
Definition: private.h:45
struct Buffer * mailbox
Mailbox and host address.
Definition: address.h:38
char * keyid
PGP Key id.
Definition: lib.h:108
bool enabled
Is this account enabled.
Definition: lib.h:111
bool prefer_encrypt
false = nopref, true = mutual
Definition: lib.h:110
+ 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
%a Alert: 1 if user is notified of new mail
%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, " " (space) otherwise
%n Number of unread messages in the mailbox
%p Poll: 1 if Mailbox is checked for new mail
%s Size in bytes
%t * if the file is tagged, blank otherwise
%u Owner name (or numeric uid, if missing)
%[fmt] Date folder was last modified using strftime(3)

Definition at line 211 of file dlg_browser.c.

215{
216 char fn[128] = { 0 };
217 char fmt[128] = { 0 };
218 struct Folder *folder = (struct Folder *) data;
219 bool optional = (flags & MUTT_FORMAT_OPTIONAL);
220
221 switch (op)
222 {
223 case 'a':
224 if (!optional)
225 {
226 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
227 snprintf(buf, buflen, fmt, folder->ff->notify_user);
228 }
229 else
230 {
231 if (folder->ff->notify_user == 0)
232 optional = false;
233 }
234 break;
235
236 case 'C':
237 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
238 snprintf(buf, buflen, fmt, folder->num + 1);
239 break;
240
241 case 'd':
242 case 'D':
243 if (folder->ff->local)
244 {
245 bool use_c_locale = false;
246
247 const char *t_fmt = NULL;
248 if (op == 'D')
249 {
250 const char *const c_date_format = cs_subset_string(NeoMutt->sub, "date_format");
251 t_fmt = NONULL(c_date_format);
252 if (*t_fmt == '!')
253 {
254 t_fmt++;
255 use_c_locale = true;
256 }
257 }
258 else
259 {
260 static const time_t one_year = 31536000;
261 t_fmt = ((mutt_date_now() - folder->ff->mtime) < one_year) ? "%b %d %H:%M" : "%b %d %Y";
262 }
263
264 char date[128] = { 0 };
265 if (use_c_locale)
266 {
267 mutt_date_localtime_format_locale(date, sizeof(date), t_fmt,
268 folder->ff->mtime, NeoMutt->time_c_locale);
269 }
270 else
271 {
272 mutt_date_localtime_format(date, sizeof(date), t_fmt, folder->ff->mtime);
273 }
274
275 mutt_format_s(buf, buflen, prec, date);
276 }
277 else
278 {
279 mutt_format_s(buf, buflen, prec, "");
280 }
281 break;
282
283 case '[':
284 if (folder->ff->local)
285 {
286 char buf2[128] = { 0 };
287 bool use_c_locale = false;
288 struct tm tm = { 0 };
289
290 char *p = buf;
291
292 const char *cp = src;
293 if (*cp == '!')
294 {
295 use_c_locale = true;
296 cp++;
297 }
298
299 size_t len = buflen - 1;
300 while ((len > 0) && (*cp != ']'))
301 {
302 if (*cp == '%')
303 {
304 cp++;
305 if (len >= 2)
306 {
307 *p++ = '%';
308 *p++ = *cp;
309 len -= 2;
310 }
311 else
312 {
313 break; /* not enough space */
314 }
315 cp++;
316 }
317 else
318 {
319 *p++ = *cp++;
320 len--;
321 }
322 }
323 *p = '\0';
324
325 tm = mutt_date_localtime(folder->ff->mtime);
326
327 if (use_c_locale)
328 strftime_l(buf2, sizeof(buf2), buf, &tm, NeoMutt->time_c_locale);
329 else
330 strftime(buf2, sizeof(buf2), buf, &tm);
331
332 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
333 snprintf(buf, buflen, fmt, buf2);
334 if (len > 0)
335 src = cp + 1;
336 }
337 else
338 {
339 mutt_format_s(buf, buflen, prec, "");
340 }
341 break;
342
343 case 'f':
344 {
345 char *s = NULL;
346
347 s = NONULL(folder->ff->name);
348
349 snprintf(fn, sizeof(fn), "%s%s", s,
350 folder->ff->local ?
351 (S_ISLNK(folder->ff->mode) ?
352 "@" :
353 (S_ISDIR(folder->ff->mode) ?
354 "/" :
355 (((folder->ff->mode & S_IXUSR) != 0) ? "*" : ""))) :
356 "");
357
358 mutt_format_s(buf, buflen, prec, fn);
359 break;
360 }
361 case 'F':
362 {
363 if (folder->ff->local)
364 {
365 char permission[11] = { 0 };
366 snprintf(permission, sizeof(permission), "%c%c%c%c%c%c%c%c%c%c",
367 S_ISDIR(folder->ff->mode) ? 'd' : (S_ISLNK(folder->ff->mode) ? 'l' : '-'),
368 ((folder->ff->mode & S_IRUSR) != 0) ? 'r' : '-',
369 ((folder->ff->mode & S_IWUSR) != 0) ? 'w' : '-',
370 ((folder->ff->mode & S_ISUID) != 0) ? 's' :
371 ((folder->ff->mode & S_IXUSR) != 0) ? 'x' :
372 '-',
373 ((folder->ff->mode & S_IRGRP) != 0) ? 'r' : '-',
374 ((folder->ff->mode & S_IWGRP) != 0) ? 'w' : '-',
375 ((folder->ff->mode & S_ISGID) != 0) ? 's' :
376 ((folder->ff->mode & S_IXGRP) != 0) ? 'x' :
377 '-',
378 ((folder->ff->mode & S_IROTH) != 0) ? 'r' : '-',
379 ((folder->ff->mode & S_IWOTH) != 0) ? 'w' : '-',
380 ((folder->ff->mode & S_ISVTX) != 0) ? 't' :
381 ((folder->ff->mode & S_IXOTH) != 0) ? 'x' :
382 '-');
383 mutt_format_s(buf, buflen, prec, permission);
384 }
385#ifdef USE_IMAP
386 else if (folder->ff->imap)
387 {
388 char permission[11] = { 0 };
389 /* mark folders with subfolders AND mail */
390 snprintf(permission, sizeof(permission), "IMAP %c",
391 (folder->ff->inferiors && folder->ff->selectable) ? '+' : ' ');
392 mutt_format_s(buf, buflen, prec, permission);
393 }
394#endif
395 else
396 mutt_format_s(buf, buflen, prec, "");
397 break;
398 }
399
400 case 'g':
401 if (folder->ff->local)
402 {
403 struct group *gr = getgrgid(folder->ff->gid);
404 if (gr)
405 {
406 mutt_format_s(buf, buflen, prec, gr->gr_name);
407 }
408 else
409 {
410 snprintf(fmt, sizeof(fmt), "%%%sld", prec);
411 snprintf(buf, buflen, fmt, folder->ff->gid);
412 }
413 }
414 else
415 {
416 mutt_format_s(buf, buflen, prec, "");
417 }
418 break;
419
420 case 'i':
421 {
422 char *s = NULL;
423 if (folder->ff->desc)
424 s = folder->ff->desc;
425 else
426 s = folder->ff->name;
427
428 snprintf(fn, sizeof(fn), "%s%s", s,
429 folder->ff->local ?
430 (S_ISLNK(folder->ff->mode) ?
431 "@" :
432 (S_ISDIR(folder->ff->mode) ?
433 "/" :
434 (((folder->ff->mode & S_IXUSR) != 0) ? "*" : ""))) :
435 "");
436
437 mutt_format_s(buf, buflen, prec, fn);
438 break;
439 }
440
441 case 'l':
442 if (folder->ff->local)
443 {
444 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
445 snprintf(buf, buflen, fmt, folder->ff->nlink);
446 }
447 else
448 {
449 mutt_format_s(buf, buflen, prec, "");
450 }
451 break;
452
453 case 'm':
454 if (!optional)
455 {
456 if (folder->ff->has_mailbox)
457 {
458 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
459 snprintf(buf, buflen, fmt, folder->ff->msg_count);
460 }
461 else
462 {
463 mutt_format_s(buf, buflen, prec, "");
464 }
465 }
466 else if (folder->ff->msg_count == 0)
467 {
468 optional = false;
469 }
470 break;
471
472 case 'N':
473 snprintf(fmt, sizeof(fmt), "%%%sc", prec);
474 snprintf(buf, buflen, fmt, folder->ff->has_new_mail ? 'N' : ' ');
475 break;
476
477 case 'n':
478 if (!optional)
479 {
480 if (folder->ff->has_mailbox)
481 {
482 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
483 snprintf(buf, buflen, fmt, folder->ff->msg_unread);
484 }
485 else
486 {
487 mutt_format_s(buf, buflen, prec, "");
488 }
489 }
490 else if (folder->ff->msg_unread == 0)
491 {
492 optional = false;
493 }
494 break;
495
496 case 'p':
497 if (!optional)
498 {
499 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
500 snprintf(buf, buflen, fmt, folder->ff->poll_new_mail);
501 }
502 else
503 {
504 if (folder->ff->poll_new_mail == 0)
505 optional = false;
506 }
507 break;
508
509 case 's':
510 if (folder->ff->local)
511 {
512 mutt_str_pretty_size(fn, sizeof(fn), folder->ff->size);
513 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
514 snprintf(buf, buflen, fmt, fn);
515 }
516 else
517 {
518 mutt_format_s(buf, buflen, prec, "");
519 }
520 break;
521
522 case 't':
523 snprintf(fmt, sizeof(fmt), "%%%sc", prec);
524 snprintf(buf, buflen, fmt, folder->ff->tagged ? '*' : ' ');
525 break;
526
527 case 'u':
528 if (folder->ff->local)
529 {
530 struct passwd *pw = getpwuid(folder->ff->uid);
531 if (pw)
532 {
533 mutt_format_s(buf, buflen, prec, pw->pw_name);
534 }
535 else
536 {
537 snprintf(fmt, sizeof(fmt), "%%%sld", prec);
538 snprintf(buf, buflen, fmt, folder->ff->uid);
539 }
540 }
541 else
542 {
543 mutt_format_s(buf, buflen, prec, "");
544 }
545 break;
546
547 default:
548 snprintf(fmt, sizeof(fmt), "%%%sc", prec);
549 snprintf(buf, buflen, fmt, op);
550 break;
551 }
552
553 if (optional)
554 {
555 mutt_expando_format(buf, buflen, col, cols, if_str, folder_format_str, data,
557 }
558 else if (flags & MUTT_FORMAT_OPTIONAL)
559 {
560 mutt_expando_format(buf, buflen, col, cols, else_str, folder_format_str,
562 }
563
564 /* We return the format string, unchanged */
565 return src;
566}
static const char * folder_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
Format a string for the folder browser - Implements format_t -.
Definition: dlg_browser.c:211
struct tm mutt_date_localtime(time_t t)
Converts calendar time to a broken-down time structure expressed in user timezone.
Definition: date.c:879
size_t mutt_date_localtime_format(char *buf, size_t buflen, const char *format, time_t t)
Format localtime.
Definition: date.c:924
size_t mutt_date_localtime_format_locale(char *buf, size_t buflen, const char *format, time_t t, locale_t loc)
Format localtime using a given locale.
Definition: date.c:942
time_t mutt_date_now(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:446
bool selectable
Folder can be selected.
Definition: lib.h:97
bool imap
This is an IMAP folder.
Definition: lib.h:96
bool has_mailbox
This is a mailbox.
Definition: lib.h:100
char * name
Name of file/dir/mailbox.
Definition: lib.h:86
uid_t uid
File's User ID.
Definition: lib.h:82
bool tagged
Folder is tagged.
Definition: lib.h:104
gid_t gid
File's Group ID.
Definition: lib.h:83
bool has_new_mail
true if mailbox has "new mail"
Definition: lib.h:89
bool poll_new_mail
Check mailbox for new mail.
Definition: lib.h:103
bool notify_user
User will be notified of new mail.
Definition: lib.h:102
nlink_t nlink
Number of hard links.
Definition: lib.h:84
char * desc
Description of mailbox.
Definition: lib.h:87
off_t size
File size.
Definition: lib.h:80
time_t mtime
Modification time.
Definition: lib.h:81
int msg_count
total number of messages
Definition: lib.h:90
mode_t mode
File permissions.
Definition: lib.h:79
bool inferiors
Folder has children.
Definition: lib.h:98
int msg_unread
number of unread messages
Definition: lib.h:91
A folder/dir in the browser.
Definition: lib.h:69
int num
Number in the index.
Definition: lib.h:71
struct FolderFile * ff
File / Dir / Mailbox.
Definition: lib.h:70
locale_t time_c_locale
Current locale but LC_TIME=C.
Definition: neomutt.h:47
+ 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 255 of file compress.c.

259{
260 if (!buf || (data == 0))
261 return src;
262
263 struct Mailbox *m = (struct Mailbox *) data;
264
265 /* NOTE the compressed file config vars expect %f and %t to be
266 * surrounded by '' (unlike other NeoMutt config vars, which add the
267 * outer quotes for the user). This is why we use the
268 * buf_quote_filename() form with add_outer of false. */
269 struct Buffer *quoted = buf_pool_get();
270 switch (op)
271 {
272 case 'f':
273 /* Compressed file */
274 buf_quote_filename(quoted, m->realpath, false);
275 snprintf(buf, buflen, "%s", buf_string(quoted));
276 break;
277 case 't':
278 /* Plaintext, temporary file */
279 buf_quote_filename(quoted, mailbox_path(m), false);
280 snprintf(buf, buflen, "%s", buf_string(quoted));
281 break;
282 }
283
284 buf_pool_release(&quoted);
285 return src;
286}
void buf_quote_filename(struct Buffer *buf, const char *filename, bool add_outer)
Quote a filename to survive the shell's quoting rules.
Definition: file.c:936
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition: mailbox.h:210
A mailbox.
Definition: mailbox.h:79
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
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 104 of file cbar.c.

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

◆ index_format_str()

static const char * index_format_str ( char *  buf,
size_t  buflen,
size_t  col,
int  cols,
char  op,
const char *  src,
const char *  prec,
const char *  if_str,
const char *  else_str,
intptr_t  data,
MuttFormatFlags  flags 
)
static

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

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

Definition at line 393 of file hdrline.c.

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

95{
96 char *match = (char *) data;
97
98 if (op == 's')
99 {
100 mutt_format_s(buf, buflen, prec, match);
101 }
102
103 return src;
104}
+ 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 119 of file win_hosts.c.

123{
124 char fmt[128] = { 0 };
125 struct Remailer *remailer = (struct Remailer *) data;
126 bool optional = (flags & MUTT_FORMAT_OPTIONAL);
127
128 switch (op)
129 {
130 case 'a':
131 if (!optional)
132 {
133 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
134 snprintf(buf, buflen, fmt, NONULL(remailer->addr));
135 }
136 else if (!remailer->addr)
137 {
138 optional = false;
139 }
140 break;
141
142 case 'c':
143 if (optional)
144 break;
145
146 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
147 snprintf(buf, buflen, fmt, mix_format_caps(remailer));
148 break;
149
150 case 'n':
151 if (optional)
152 break;
153
154 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
155 snprintf(buf, buflen, fmt, remailer->num);
156 break;
157
158 case 's':
159 if (!optional)
160 {
161 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
162 snprintf(buf, buflen, fmt, NONULL(remailer->shortname));
163 }
164 else if (!remailer->shortname)
165 {
166 optional = false;
167 }
168 break;
169
170 default:
171 *buf = '\0';
172 }
173
174 if (optional)
175 {
176 mutt_expando_format(buf, buflen, col, cols, if_str, mix_format_str, data,
178 }
179 else if (flags & MUTT_FORMAT_OPTIONAL)
180 {
181 mutt_expando_format(buf, buflen, col, cols, else_str, mix_format_str, data,
183 }
184
185 /* We return the format string, unchanged */
186 return src;
187}
static const char * mix_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
Format a string for the remailer menu - Implements format_t -.
Definition: win_hosts.c:119
A Mixmaster remailer.
Definition: remailer.h:40
int num
Index number.
Definition: remailer.h:41
char * addr
Address of host.
Definition: remailer.h:43
char * shortname
Short name of remailer host.
Definition: remailer.h:42
static const char * mix_format_caps(struct Remailer *r)
Turn flags into a MixMaster capability string.
Definition: win_hosts.c:67
+ 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 745 of file muttlib.c.

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

◆ crypt_format_str()

static const char * crypt_format_str ( char *  buf,
size_t  buflen,
size_t  col,
int  cols,
char  op,
const char *  src,
const char *  prec,
const char *  if_str,
const char *  else_str,
intptr_t  data,
MuttFormatFlags  flags 
)
static

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

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

| | | %a | Algorithm | %c | Capabilities | %f | Flags | %i | Key fingerprint (or long key id if non-existent) | %k | Key id | %l | Length | | | %A | Algorithm of the principal key | %C | Capabilities of the principal key | %F | Flags of the principal key | %I | Key fingerprint of the principal key (or long key id if non-existent) | %K | Key id of the principal key | %L | Length of the principal key

Definition at line 317 of file dlg_gpgme.c.

321{
322 char fmt[128] = { 0 };
323 bool optional = (flags & MUTT_FORMAT_OPTIONAL);
324
325 struct CryptEntry *entry = (struct CryptEntry *) data;
326 struct CryptKeyInfo *key = entry->key;
327
328 KeyFlags kflags = (key->flags);
329
330 switch (tolower(op))
331 {
332 case 'a':
333 if (!optional)
334 {
335 const char *s = NULL;
336 snprintf(fmt, sizeof(fmt), "%%%s.3s", prec);
337 if (key->kobj->subkeys)
338 s = gpgme_pubkey_algo_name(key->kobj->subkeys->pubkey_algo);
339 else
340 s = "?";
341 snprintf(buf, buflen, fmt, s);
342 }
343 break;
344
345 case 'c':
346 if (!optional)
347 {
348 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
349 snprintf(buf, buflen, fmt, crypt_key_abilities(kflags));
350 }
351 else if (!(kflags & KEYFLAG_ABILITIES))
352 {
353 optional = false;
354 }
355 break;
356
357 case 'f':
358 if (!optional)
359 {
360 snprintf(fmt, sizeof(fmt), "%%%sc", prec);
361 snprintf(buf, buflen, fmt, crypt_flags(kflags));
362 }
363 else if (!(kflags & KEYFLAG_RESTRICTIONS))
364 {
365 optional = false;
366 }
367 break;
368
369 case 'i':
370 if (!optional)
371 {
372 /* fixme: we need a way to distinguish between main and subkeys.
373 * Store the idx in entry? */
374 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
375 snprintf(buf, buflen, fmt, crypt_fpr_or_lkeyid(key));
376 }
377 break;
378
379 case 'k':
380 if (!optional)
381 {
382 /* fixme: we need a way to distinguish between main and subkeys.
383 * Store the idx in entry? */
384 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
385 snprintf(buf, buflen, fmt, crypt_keyid(key));
386 }
387 break;
388
389 case 'l':
390 if (!optional)
391 {
392 snprintf(fmt, sizeof(fmt), "%%%slu", prec);
393 unsigned long val;
394 if (key->kobj->subkeys)
395 val = key->kobj->subkeys->length;
396 else
397 val = 0;
398 snprintf(buf, buflen, fmt, val);
399 }
400 break;
401
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
410 case 'p':
411 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
412 snprintf(buf, buflen, fmt, gpgme_get_protocol_name(key->kobj->protocol));
413 break;
414
415 case 't':
416 {
417 char *s = NULL;
418 if ((kflags & KEYFLAG_ISX509))
419 {
420 s = "x";
421 }
422 else
423 {
424 switch (key->validity)
425 {
426 case GPGME_VALIDITY_FULL:
427 s = "f";
428 break;
429 case GPGME_VALIDITY_MARGINAL:
430 s = "m";
431 break;
432 case GPGME_VALIDITY_NEVER:
433 s = "n";
434 break;
435 case GPGME_VALIDITY_ULTIMATE:
436 s = "u";
437 break;
438 case GPGME_VALIDITY_UNDEFINED:
439 s = "q";
440 break;
441 case GPGME_VALIDITY_UNKNOWN:
442 default:
443 s = "?";
444 break;
445 }
446 }
447 snprintf(fmt, sizeof(fmt), "%%%sc", prec);
448 snprintf(buf, buflen, fmt, *s);
449 break;
450 }
451
452 case 'u':
453 if (!optional)
454 {
455 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
456 snprintf(buf, buflen, fmt, key->uid);
457 }
458 break;
459
460 case '[':
461 {
462 char buf2[128];
463 bool use_c_locale = false;
464 struct tm tm = { 0 };
465
466 char *p = buf;
467
468 const char *cp = src;
469 if (*cp == '!')
470 {
471 use_c_locale = true;
472 cp++;
473 }
474
475 size_t len = buflen - 1;
476 while ((len > 0) && (*cp != ']'))
477 {
478 if (*cp == '%')
479 {
480 cp++;
481 if (len >= 2)
482 {
483 *p++ = '%';
484 *p++ = *cp;
485 len -= 2;
486 }
487 else
488 {
489 break; /* not enough space */
490 }
491 cp++;
492 }
493 else
494 {
495 *p++ = *cp++;
496 len--;
497 }
498 }
499 *p = '\0';
500
501 if (key->kobj->subkeys && (key->kobj->subkeys->timestamp > 0))
502 tm = mutt_date_localtime(key->kobj->subkeys->timestamp);
503 else
504 tm = mutt_date_localtime(0); // Default to 1970-01-01
505
506 if (use_c_locale)
507 strftime_l(buf2, sizeof(buf2), buf, &tm, NeoMutt->time_c_locale);
508 else
509 strftime(buf2, sizeof(buf2), buf, &tm);
510
511 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
512 snprintf(buf, buflen, fmt, buf2);
513 if (len > 0)
514 src = cp + 1;
515 break;
516 }
517
518 default:
519 *buf = '\0';
520 }
521
522 if (optional)
523 {
524 mutt_expando_format(buf, buflen, col, cols, if_str, crypt_format_str, data,
526 }
527 else if (flags & MUTT_FORMAT_OPTIONAL)
528 {
529 mutt_expando_format(buf, buflen, col, cols, else_str, crypt_format_str,
531 }
532
533 /* We return the format string, unchanged */
534 return src;
535}
const char * crypt_fpr_or_lkeyid(struct CryptKeyInfo *k)
Find the fingerprint of a key.
Definition: crypt_gpgme.c:213
const char * crypt_keyid(struct CryptKeyInfo *k)
Find the ID for the key.
Definition: crypt_gpgme.c:137
static char crypt_flags(KeyFlags flags)
Parse the key flags into a single character.
Definition: dlg_gpgme.c:278
static char * crypt_key_abilities(KeyFlags flags)
Parse key flags into a string.
Definition: dlg_gpgme.c:248
static const char * crypt_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
Format a string for the key selection menu - Implements format_t -.
Definition: dlg_gpgme.c:317
#define KEYFLAG_ISX509
Key is an X.509 key.
Definition: lib.h:130
uint16_t KeyFlags
Flags describing PGP/SMIME keys, e.g. KEYFLAG_CANSIGN.
Definition: lib.h:126
#define KEYFLAG_RESTRICTIONS
Definition: lib.h:141
#define KEYFLAG_ABILITIES
Definition: lib.h:143
An entry in the Select-Key menu.
Definition: dlg_gpgme.c:107
struct CryptKeyInfo * key
Key.
Definition: dlg_gpgme.c:109
size_t num
Index number.
Definition: dlg_gpgme.c:108
A stored PGP key.
Definition: crypt_gpgme.h:44
gpgme_validity_t validity
uid validity (cached for convenience)
Definition: crypt_gpgme.h:50
KeyFlags flags
global and per uid flags (for convenience)
Definition: crypt_gpgme.h:49
const char * uid
and for convenience point to this user ID
Definition: crypt_gpgme.h:48
gpgme_key_t kobj
Definition: crypt_gpgme.h:46
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_entry_format_str()

static const char * pgp_entry_format_str ( char *  buf,
size_t  buflen,
size_t  col,
int  cols,
char  op,
const char *  src,
const char *  prec,
const char *  if_str,
const char *  else_str,
intptr_t  data,
MuttFormatFlags  flags 
)
static

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

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

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

Definition at line 282 of file dlg_pgp.c.

286{
287 char fmt[128] = { 0 };
288 bool optional = (flags & MUTT_FORMAT_OPTIONAL);
289
290 struct PgpEntry *entry = (struct PgpEntry *) data;
291 struct PgpUid *uid = entry->uid;
292 struct PgpKeyInfo *key = uid->parent;
293 struct PgpKeyInfo *pkey = pgp_principal_key(key);
294
295 if (isupper((unsigned char) op))
296 key = pkey;
297
298 KeyFlags kflags = key->flags | (pkey->flags & KEYFLAG_RESTRICTIONS) | uid->flags;
299
300 switch (tolower(op))
301 {
302 case 'a':
303 if (!optional)
304 {
305 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
306 snprintf(buf, buflen, fmt, key->algorithm);
307 }
308 break;
309 case 'c':
310 if (!optional)
311 {
312 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
313 snprintf(buf, buflen, fmt, pgp_key_abilities(kflags));
314 }
315 else if (!(kflags & KEYFLAG_ABILITIES))
316 {
317 optional = false;
318 }
319 break;
320 case 'f':
321 if (!optional)
322 {
323 snprintf(fmt, sizeof(fmt), "%%%sc", prec);
324 snprintf(buf, buflen, fmt, pgp_flags(kflags));
325 }
326 else if (!(kflags & KEYFLAG_RESTRICTIONS))
327 {
328 optional = false;
329 }
330 break;
331 case 'k':
332 if (!optional)
333 {
334 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
335 snprintf(buf, buflen, fmt, pgp_this_keyid(key));
336 }
337 break;
338 case 'l':
339 if (!optional)
340 {
341 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
342 snprintf(buf, buflen, fmt, key->keylen);
343 }
344 break;
345 case 'n':
346 if (!optional)
347 {
348 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
349 snprintf(buf, buflen, fmt, entry->num);
350 }
351 break;
352 case 't':
353 if (!optional)
354 {
355 snprintf(fmt, sizeof(fmt), "%%%sc", prec);
356 snprintf(buf, buflen, fmt, TrustFlags[uid->trust & 0x03]);
357 }
358 else if (!(uid->trust & 0x03))
359 {
360 /* undefined trust */
361 optional = false;
362 }
363 break;
364 case 'u':
365 if (!optional)
366 {
367 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
368 snprintf(buf, buflen, fmt, NONULL(uid->addr));
369 }
370 break;
371 case '[':
372 {
373 char buf2[128];
374 bool use_c_locale = false;
375 size_t len;
376
377 char *p = buf;
378
379 const char *cp = src;
380 if (*cp == '!')
381 {
382 use_c_locale = true;
383 cp++;
384 }
385
386 len = buflen - 1;
387 while ((len > 0) && (*cp != ']'))
388 {
389 if (*cp == '%')
390 {
391 cp++;
392 if (len >= 2)
393 {
394 *p++ = '%';
395 *p++ = *cp;
396 len -= 2;
397 }
398 else
399 {
400 break; /* not enough space */
401 }
402 cp++;
403 }
404 else
405 {
406 *p++ = *cp++;
407 len--;
408 }
409 }
410 *p = '\0';
411
412 if (use_c_locale)
413 {
414 mutt_date_localtime_format_locale(buf2, sizeof(buf2), buf,
416 }
417 else
418 {
419 mutt_date_localtime_format(buf2, sizeof(buf2), buf, key->gen_time);
420 }
421
422 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
423 snprintf(buf, buflen, fmt, buf2);
424 if (len > 0)
425 src = cp + 1;
426 break;
427 }
428 default:
429 *buf = '\0';
430 }
431
432 if (optional)
433 {
434 mutt_expando_format(buf, buflen, col, cols, if_str, pgp_entry_format_str,
436 }
437 else if (flags & MUTT_FORMAT_OPTIONAL)
438 {
439 mutt_expando_format(buf, buflen, col, cols, else_str, pgp_entry_format_str,
441 }
442
443 /* We return the format string, unchanged */
444 return src;
445}
static char pgp_flags(KeyFlags flags)
Turn PGP key flags into a string.
Definition: dlg_pgp.c:246
static const char TrustFlags[]
Characters used to show the trust level for PGP keys.
Definition: dlg_pgp.c:113
static char * pgp_key_abilities(KeyFlags flags)
Turn PGP key abilities into a string.
Definition: dlg_pgp.c:218
static const char * pgp_entry_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
Format an entry on the PGP key selection menu - Implements format_t -.
Definition: dlg_pgp.c:282
char * pgp_this_keyid(struct PgpKeyInfo *k)
Get the ID of this key.
Definition: pgp.c:192
struct PgpKeyInfo * pgp_principal_key(struct PgpKeyInfo *key)
Get the main (parent) PGP key.
Definition: pgpkey.c:89
An entry in a PGP key menu.
Definition: dlg_pgp.c:107
struct PgpUid * uid
Definition: dlg_pgp.c:109
size_t num
Index number.
Definition: dlg_pgp.c:108
Information about a PGP key.
Definition: pgplib.h:47
KeyFlags flags
Definition: pgplib.h:51
short keylen
Definition: pgplib.h:52
time_t gen_time
Definition: pgplib.h:53
const char * algorithm
Definition: pgplib.h:55
PGP User ID.
Definition: pgplib.h:35
short trust
Definition: pgplib.h:37
struct PgpKeyInfo * parent
Parent key.
Definition: pgplib.h:39
int flags
Definition: pgplib.h:38
char * addr
Definition: pgplib.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_command_format_str()

static const char * pgp_command_format_str ( char *  buf,
size_t  buflen,
size_t  col,
int  cols,
char  op,
const char *  src,
const char *  prec,
const char *  if_str,
const char *  else_str,
intptr_t  data,
MuttFormatFlags  flags 
)
static

Format a PGP command string - Implements format_t -.

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

Definition at line 80 of file pgpinvoke.c.

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

229{
230 char fmt[128] = { 0 };
231 struct SmimeCommandContext *cctx = (struct SmimeCommandContext *) data;
232 bool optional = (flags & MUTT_FORMAT_OPTIONAL);
233
234 switch (op)
235 {
236 case 'C':
237 {
238 const char *const c_smime_ca_location = cs_subset_path(NeoMutt->sub, "smime_ca_location");
239 if (!optional)
240 {
241 struct Buffer *path = buf_pool_get();
242 struct Buffer *buf1 = buf_pool_get();
243 struct Buffer *buf2 = buf_pool_get();
244 struct stat st = { 0 };
245
246 buf_strcpy(path, c_smime_ca_location);
247 buf_expand_path(path);
248 buf_quote_filename(buf1, buf_string(path), true);
249
250 if ((stat(buf_string(path), &st) != 0) || !S_ISDIR(st.st_mode))
251 buf_printf(buf2, "-CAfile %s", buf_string(buf1));
252 else
253 buf_printf(buf2, "-CApath %s", buf_string(buf1));
254
255 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
256 snprintf(buf, buflen, fmt, buf_string(buf2));
257
258 buf_pool_release(&path);
259 buf_pool_release(&buf1);
260 buf_pool_release(&buf2);
261 }
262 else if (!c_smime_ca_location)
263 {
264 optional = false;
265 }
266 break;
267 }
268
269 case 'c':
270 { /* certificate (list) */
271 if (!optional)
272 {
273 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
274 snprintf(buf, buflen, fmt, NONULL(cctx->certificates));
275 }
276 else if (!cctx->certificates)
277 {
278 optional = false;
279 }
280 break;
281 }
282
283 case 'i':
284 { /* intermediate certificates */
285 if (!optional)
286 {
287 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
288 snprintf(buf, buflen, fmt, NONULL(cctx->intermediates));
289 }
290 else if (!cctx->intermediates)
291 {
292 optional = false;
293 }
294 break;
295 }
296
297 case 's':
298 { /* detached signature */
299 if (!optional)
300 {
301 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
302 snprintf(buf, buflen, fmt, NONULL(cctx->sig_fname));
303 }
304 else if (!cctx->sig_fname)
305 {
306 optional = false;
307 }
308 break;
309 }
310
311 case 'k':
312 { /* private key */
313 if (!optional)
314 {
315 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
316 snprintf(buf, buflen, fmt, NONULL(cctx->key));
317 }
318 else if (!cctx->key)
319 {
320 optional = false;
321 }
322 break;
323 }
324
325 case 'a':
326 { /* algorithm for encryption */
327 if (!optional)
328 {
329 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
330 snprintf(buf, buflen, fmt, NONULL(cctx->cryptalg));
331 }
332 else if (!cctx->key)
333 {
334 optional = false;
335 }
336 break;
337 }
338
339 case 'f':
340 { /* file to process */
341 if (!optional)
342 {
343 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
344 snprintf(buf, buflen, fmt, NONULL(cctx->fname));
345 }
346 else if (!cctx->fname)
347 {
348 optional = false;
349 }
350 break;
351 }
352
353 case 'd':
354 { /* algorithm for the signature message digest */
355 if (!optional)
356 {
357 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
358 snprintf(buf, buflen, fmt, NONULL(cctx->digestalg));
359 }
360 else if (!cctx->key)
361 {
362 optional = false;
363 }
364 break;
365 }
366
367 default:
368 *buf = '\0';
369 break;
370 }
371
372 if (optional)
373 {
374 mutt_expando_format(buf, buflen, col, cols, if_str,
376 }
377 else if (flags & MUTT_FORMAT_OPTIONAL)
378 {
379 mutt_expando_format(buf, buflen, col, cols, else_str,
381 }
382
383 /* We return the format string, unchanged */
384 return src;
385}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:173
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:169
static const char * smime_command_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
Format an SMIME command - Implements format_t -.
Definition: smime.c:224
void buf_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:335
Data for a SIME command.
Definition: smime.c:70
const char * sig_fname
s
Definition: smime.c:75
const char * intermediates
i
Definition: smime.c:77
const char * digestalg
d
Definition: smime.c:73
const char * cryptalg
a
Definition: smime.c:72
const char * key
k
Definition: smime.c:71
const char * fname
f
Definition: smime.c:74
const char * certificates
c
Definition: smime.c:76
+ 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
%a Alert: 1 if user is notified of new mail
%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
%p Poll: 1 if Mailbox is checked for new mail
%s Number of unread articles in newsgroup

Definition at line 57 of file browse.c.

61{
62 char fn[128], fmt[128];
63 struct Folder *folder = (struct Folder *) data;
64 bool optional = (flags & MUTT_FORMAT_OPTIONAL);
65
66 switch (op)
67 {
68 case 'a':
69 if (!optional)
70 {
71 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
72 snprintf(buf, buflen, fmt, folder->ff->notify_user);
73 }
74 else
75 {
76 if (folder->ff->notify_user == 0)
77 optional = false;
78 }
79 break;
80
81 case 'C':
82 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
83 snprintf(buf, buflen, fmt, folder->num + 1);
84 break;
85
86 case 'd':
87 if (folder->ff->nd->desc)
88 {
89 char *desc = mutt_str_dup(folder->ff->nd->desc);
90 const char *const c_newsgroups_charset = cs_subset_string(NeoMutt->sub, "newsgroups_charset");
91 if (c_newsgroups_charset)
92 mutt_ch_convert_string(&desc, c_newsgroups_charset, cc_charset(), MUTT_ICONV_HOOK_FROM);
94
95 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
96 snprintf(buf, buflen, fmt, desc);
97 FREE(&desc);
98 }
99 else
100 {
101 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
102 snprintf(buf, buflen, fmt, "");
103 }
104 break;
105
106 case 'f':
107 mutt_str_copy(fn, folder->ff->name, sizeof(fn));
108 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
109 snprintf(buf, buflen, fmt, fn);
110 break;
111
112 case 'M':
113 snprintf(fmt, sizeof(fmt), "%%%sc", prec);
114 if (folder->ff->nd->deleted)
115 snprintf(buf, buflen, fmt, 'D');
116 else
117 snprintf(buf, buflen, fmt, folder->ff->nd->allowed ? ' ' : '-');
118 break;
119
120 case 'N':
121 snprintf(fmt, sizeof(fmt), "%%%sc", prec);
122 if (folder->ff->nd->subscribed)
123 snprintf(buf, buflen, fmt, ' ');
124 else
125 snprintf(buf, buflen, fmt, folder->ff->has_new_mail ? 'N' : 'u');
126 break;
127
128 case 'n':
129 {
130 const bool c_mark_old = cs_subset_bool(NeoMutt->sub, "mark_old");
131 if (c_mark_old && (folder->ff->nd->last_cached >= folder->ff->nd->first_message) &&
132 (folder->ff->nd->last_cached <= folder->ff->nd->last_message))
133 {
134 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
135 snprintf(buf, buflen, fmt, folder->ff->nd->last_message - folder->ff->nd->last_cached);
136 }
137 else
138 {
139 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
140 snprintf(buf, buflen, fmt, folder->ff->nd->unread);
141 }
142 break;
143 }
144
145 case 'p':
146 if (!optional)
147 {
148 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
149 snprintf(buf, buflen, fmt, folder->ff->poll_new_mail);
150 }
151 else
152 {
153 if (folder->ff->poll_new_mail == 0)
154 optional = false;
155 }
156 break;
157
158 case 's':
159 if (optional)
160 {
161 if (folder->ff->nd->unread != 0)
162 {
163 mutt_expando_format(buf, buflen, col, cols, if_str,
164 group_index_format_str, data, flags);
165 }
166 else
167 {
168 mutt_expando_format(buf, buflen, col, cols, else_str,
169 group_index_format_str, data, flags);
170 }
171 }
172 else
173 {
174 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
175 snprintf(buf, buflen, fmt, folder->ff->nd->unread);
176 }
177 break;
178 }
179 return src;
180}
const char * cc_charset(void)
Get the cached value of $charset.
Definition: config_cache.c:115
const char * group_index_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
Format a string for the newsgroup menu - Implements format_t -.
Definition: browse.c:57
int mutt_mb_filter_unprintable(char **s)
Replace unprintable characters.
Definition: mbyte.c:419
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
Definition: charset.c:826
#define MUTT_ICONV_HOOK_FROM
apply charset-hooks to fromcode
Definition: charset.h:72
struct NntpMboxData * nd
Extra NNTP data.
Definition: lib.h:106
anum_t last_cached
Definition: mdata.h:40
bool deleted
Definition: mdata.h:45
bool allowed
Definition: mdata.h:44
anum_t last_message
Definition: mdata.h:38
char * desc
Description of newsgroup.
Definition: mdata.h:36
anum_t unread
Definition: mdata.h:41
anum_t first_message
Definition: mdata.h:37
bool subscribed
Definition: mdata.h:42
+ 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 927 of file newsrc.c.

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

◆ pattern_format_str()

static const char * pattern_format_str ( char *  buf,
size_t  buflen,
size_t  col,
int  cols,
char  op,
const char *  src,
const char *  prec,
const char *  if_str,
const char *  else_str,
intptr_t  data,
MuttFormatFlags  flags 
)
static

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

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

Definition at line 106 of file dlg_pattern.c.

110{
111 struct PatternEntry *entry = (struct PatternEntry *) data;
112
113 switch (op)
114 {
115 case 'd':
116 mutt_format_s(buf, buflen, prec, NONULL(entry->desc));
117 break;
118 case 'e':
119 mutt_format_s(buf, buflen, prec, NONULL(entry->expr));
120 break;
121 case 'n':
122 {
123 char tmp[32] = { 0 };
124 snprintf(tmp, sizeof(tmp), "%%%sd", prec);
125 snprintf(buf, buflen, tmp, entry->num);
126 break;
127 }
128 }
129
130 return src;
131}
A line in the Pattern Completion menu.
Definition: private.h:36
const char * desc
Description of pattern.
Definition: private.h:40
int num
Index number.
Definition: private.h:37
const char * expr
Displayed in the menu.
Definition: private.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ greeting_format_str()

static const char * greeting_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 greetings string - Implements format_t -.

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

Definition at line 682 of file send.c.

686{
687 struct Email *e = (struct Email *) data;
688 char *p = NULL;
689 char buf2[256];
690
691 const struct Address *to = TAILQ_FIRST(&e->env->to);
692 const struct Address *cc = TAILQ_FIRST(&e->env->cc);
693
694 buf[0] = '\0';
695 switch (op)
696 {
697 case 'n':
698 mutt_format_s(buf, buflen, prec, mutt_get_name(to));
699 break;
700
701 case 'u':
702 if (to)
703 {
704 mutt_str_copy(buf2, mutt_addr_for_display(to), sizeof(buf2));
705 if ((p = strpbrk(buf2, "%@")))
706 *p = '\0';
707 }
708 else
709 {
710 buf2[0] = '\0';
711 }
712 mutt_format_s(buf, buflen, prec, buf2);
713 break;
714
715 case 'v':
716 if (to)
717 mutt_format_s(buf2, sizeof(buf2), prec, mutt_get_name(to));
718 else if (cc)
719 mutt_format_s(buf2, sizeof(buf2), prec, mutt_get_name(cc));
720 else
721 *buf2 = '\0';
722 if ((p = strpbrk(buf2, " %@")))
723 *p = '\0';
724 mutt_format_s(buf, buflen, prec, buf2);
725 break;
726
727 default:
728 snprintf(buf, buflen, "%%%s%c", prec, op);
729 break;
730 }
731
732 if (flags & MUTT_FORMAT_OPTIONAL)
733 mutt_expando_format(buf, buflen, col, cols, else_str, greeting_format_str, data, flags);
734
735 return src;
736}
static const char * greeting_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 greetings string - Implements format_t -.
Definition: send.c:682
+ 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
%a Alert: 1 if user is notified of new mail
%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
%p Poll: 1 if Mailbox is checked for new mail
%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 350 of file window.c.

354{
355 struct SidebarFormatData *sfdata = (struct SidebarFormatData *) data;
356 struct SbEntry *sbe = sfdata->entry;
357 struct IndexSharedData *shared = sfdata->shared;
358 char fmt[256] = { 0 };
359
360 if (!sbe || !shared || !buf)
361 return src;
362
363 buf[0] = '\0'; /* Just in case there's nothing to do */
364
365 struct Mailbox *m = sbe->mailbox;
366 if (!m)
367 return src;
368
369 struct Mailbox *m_cur = shared->mailbox;
370
371 bool c = m_cur && mutt_str_equal(m_cur->realpath, m->realpath);
372
373 bool optional = (flags & MUTT_FORMAT_OPTIONAL);
374
375 switch (op)
376 {
377 case 'a':
378 if (!optional)
379 {
380 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
381 snprintf(buf, buflen, fmt, m->notify_user);
382 }
383 else
384 {
385 if (m->notify_user == 0)
386 optional = false;
387 }
388 break;
389
390 case 'B':
391 case 'D':
392 {
393 char indented[256] = { 0 };
394 size_t ilen = sizeof(indented);
395 size_t off = add_indent(indented, ilen, sbe);
396 snprintf(indented + off, ilen - off, "%s",
397 ((op == 'D') && sbe->mailbox->name) ? sbe->mailbox->name : sbe->box);
398 mutt_format_s(buf, buflen, prec, indented);
399 break;
400 }
401
402 case 'd':
403 if (!optional)
404 {
405 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
406 snprintf(buf, buflen, fmt, c ? m_cur->msg_deleted : 0);
407 }
408 else if ((c && (m_cur->msg_deleted == 0)) || !c)
409 {
410 optional = false;
411 }
412 break;
413
414 case 'F':
415 if (!optional)
416 {
417 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
418 snprintf(buf, buflen, fmt, m->msg_flagged);
419 }
420 else if (m->msg_flagged == 0)
421 {
422 optional = false;
423 }
424 break;
425
426 case 'L':
427 if (!optional)
428 {
429 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
430 snprintf(buf, buflen, fmt, c ? m_cur->vcount : m->msg_count);
431 }
432 else if ((c && (m_cur->vcount == m->msg_count)) || !c)
433 {
434 optional = false;
435 }
436 break;
437
438 case 'N':
439 if (!optional)
440 {
441 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
442 snprintf(buf, buflen, fmt, m->msg_unread);
443 }
444 else if (m->msg_unread == 0)
445 {
446 optional = false;
447 }
448 break;
449
450 case 'n':
451 if (!optional)
452 {
453 snprintf(fmt, sizeof(fmt), "%%%sc", prec);
454 snprintf(buf, buflen, fmt, m->has_new ? 'N' : ' ');
455 }
456 else if (m->has_new == false)
457 {
458 optional = false;
459 }
460 break;
461
462 case 'o':
463 if (!optional)
464 {
465 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
466 snprintf(buf, buflen, fmt, m->msg_unread - m->msg_new);
467 }
468 else if ((c && (m_cur->msg_unread - m_cur->msg_new) == 0) || !c)
469 {
470 optional = false;
471 }
472 break;
473
474 case 'p':
475 if (!optional)
476 {
477 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
478 snprintf(buf, buflen, fmt, m->poll_new_mail);
479 }
480 else
481 {
482 if (m->poll_new_mail == 0)
483 optional = false;
484 }
485 break;
486
487 case 'r':
488 if (!optional)
489 {
490 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
491 snprintf(buf, buflen, fmt, m->msg_count - m->msg_unread);
492 }
493 else if ((c && (m_cur->msg_count - m_cur->msg_unread) == 0) || !c)
494 {
495 optional = false;
496 }
497 break;
498
499 case 'S':
500 if (!optional)
501 {
502 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
503 snprintf(buf, buflen, fmt, m->msg_count);
504 }
505 else if (m->msg_count == 0)
506 {
507 optional = false;
508 }
509 break;
510
511 case 't':
512 if (!optional)
513 {
514 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
515 snprintf(buf, buflen, fmt, c ? m_cur->msg_tagged : 0);
516 }
517 else if ((c && (m_cur->msg_tagged == 0)) || !c)
518 {
519 optional = false;
520 }
521 break;
522
523 case 'Z':
524 if (!optional)
525 {
526 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
527 snprintf(buf, buflen, fmt, m->msg_new);
528 }
529 else if ((c && (m_cur->msg_new) == 0) || !c)
530 {
531 optional = false;
532 }
533 break;
534
535 case '!':
536 if (m->msg_flagged == 0)
537 {
538 mutt_format_s(buf, buflen, prec, "");
539 }
540 else if (m->msg_flagged == 1)
541 {
542 mutt_format_s(buf, buflen, prec, "!");
543 }
544 else if (m->msg_flagged == 2)
545 {
546 mutt_format_s(buf, buflen, prec, "!!");
547 }
548 else
549 {
550 snprintf(fmt, sizeof(fmt), "%d!", m->msg_flagged);
551 mutt_format_s(buf, buflen, prec, fmt);
552 }
553 break;
554 }
555
556 if (optional)
557 {
558 mutt_expando_format(buf, buflen, col, cols, if_str, sidebar_format_str, data, flags);
559 }
560 else if (flags & MUTT_FORMAT_OPTIONAL)
561 {
562 mutt_expando_format(buf, buflen, col, cols, else_str, sidebar_format_str, data, flags);
563 }
564
565 /* We return the format string, unchanged */
566 return src;
567}
static const char * sidebar_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
Format a string for the sidebar - Implements format_t -.
Definition: window.c:350
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:798
static size_t add_indent(char *buf, size_t buflen, const struct SbEntry *sbe)
Generate the needed indentation.
Definition: window.c:231
Data shared between Index, Pager and Sidebar.
Definition: shared_data.h:37
struct Mailbox * mailbox
Current Mailbox.
Definition: shared_data.h:41
int vcount
The number of virtual messages.
Definition: mailbox.h:99
bool has_new
Mailbox has new mail.
Definition: mailbox.h:85
int msg_new
Number of new messages.
Definition: mailbox.h:92
bool poll_new_mail
Check for new mail.
Definition: mailbox.h:114
char * name
A short name for the Mailbox.
Definition: mailbox.h:82
bool notify_user
Notify the user of new mail.
Definition: mailbox.h:112
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:93
int msg_flagged
Number of flagged messages.
Definition: mailbox.h:90
int msg_tagged
How many messages are tagged?
Definition: mailbox.h:94
int msg_unread
Number of unread messages.
Definition: mailbox.h:89
Info about folders in the sidebar.
Definition: private.h:41
struct Mailbox * mailbox
Mailbox this represents.
Definition: private.h:45
char box[256]
Mailbox path (possibly abbreviated)
Definition: private.h:42
Data passed to sidebar_format_str()
Definition: window.c:88
struct IndexSharedData * shared
Shared Index Data.
Definition: window.c:90
struct SbEntry * entry
Info about a folder.
Definition: window.c:89
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ status_format_str()

static const char * status_format_str ( char *  buf,
size_t  buflen,
size_t  col,
int  cols,
char  op,
const char *  src,
const char *  prec,
const char *  if_str,
const char *  else_str,
intptr_t  data,
MuttFormatFlags  flags 
)
static

Create the status bar string - Implements format_t -.

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

Definition at line 100 of file status.c.

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