NeoMutt  2023-05-17-56-ga67199
Teaching an old dog new tricks
DOXYGEN
Expando API

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

Functions

static const char * alias_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Format a string for the alias list - Implements format_t -. More...
 
static const char * query_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Format a string for the query menu - Implements format_t -. More...
 
const char * attach_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Format a string for the attachment menu - Implements format_t -. More...
 
static const char * autocrypt_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Format a string for the Autocrypt account list - Implements format_t -. More...
 
static const char * folder_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Format a string for the folder browser - Implements format_t -. More...
 
static const char * compress_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Expand the filenames in a command string - Implements format_t -. More...
 
static const char * compose_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Create the status bar string for compose mode - Implements format_t -. More...
 
static const char * index_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Format a string for the index list - Implements format_t -. More...
 
static const char * history_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Format a string for the history list - Implements format_t -. More...
 
static const char * mix_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Format a string for the remailer menu - Implements format_t -. More...
 
void mutt_expando_format (char *buf, size_t buflen, size_t col, int cols, const char *src, format_t callback, intptr_t data, MuttFormatFlags flags)
 Expand expandos (x) in a string -. More...
 
static const char * crypt_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Format a string for the key selection menu - Implements format_t -. More...
 
static const char * pgp_entry_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Format an entry on the PGP key selection menu - Implements format_t -. More...
 
static const char * pgp_command_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Format a PGP command string - Implements format_t -. More...
 
static const char * smime_command_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Format an SMIME command - Implements format_t -. More...
 
const char * group_index_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Format a string for the newsgroup menu - Implements format_t -. More...
 
const char * nntp_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Expand the newsrc filename - Implements format_t -. More...
 
static const char * pattern_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Format a string for the pattern completion menu - Implements format_t -. More...
 
static const char * 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 -. More...
 
static const char * sidebar_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Format a string for the sidebar - Implements format_t -. More...
 
static const char * status_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Create the status bar string - Implements format_t -. More...
 

Detailed Description

Prototype for a mutt_expando_format() Callback Function.

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

Each callback function implements some expandos, e.g.

Expando Description
%t Title

Function Documentation

◆ alias_format_str()

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

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

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

Definition at line 124 of file dlg_alias.c.

128{
129 char tmp[1024];
130 struct AliasView *av = (struct AliasView *) data;
131 struct Alias *alias = av->alias;
132
133 switch (op)
134 {
135 case 'a':
136 mutt_format_s(buf, buflen, prec, alias->name);
137 break;
138 case 'c':
139 mutt_format_s(buf, buflen, prec, alias->comment);
140 break;
141 case 'f':
142 snprintf(tmp, sizeof(tmp), "%%%ss", prec);
143 snprintf(buf, buflen, tmp, av->is_deleted ? "D" : " ");
144 break;
145 case 'n':
146 snprintf(tmp, sizeof(tmp), "%%%sd", prec);
147 snprintf(buf, buflen, tmp, av->num + 1);
148 break;
149 case 'r':
150 {
151 struct Buffer *tmpbuf = buf_pool_get();
152 mutt_addrlist_write(&alias->addr, tmpbuf, true);
153 mutt_str_copy(tmp, buf_string(tmpbuf), sizeof(tmp));
154 buf_pool_release(&tmpbuf);
155 mutt_format_s(buf, buflen, prec, tmp);
156 break;
157 }
158 case 't':
159 buf[0] = av->is_tagged ? '*' : ' ';
160 buf[1] = '\0';
161 break;
162 }
163
164 return src;
165}
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
Definition: address.c:1195
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:90
void mutt_format_s(char *buf, size_t buflen, const char *prec, const char *s)
Format a simple string.
Definition: curs_lib.c:796
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 150 of file dlg_query.c.

154{
155 struct AliasView *av = (struct AliasView *) data;
156 struct Alias *alias = av->alias;
157 char fmt[128] = { 0 };
158 bool optional = (flags & MUTT_FORMAT_OPTIONAL);
159
160 switch (op)
161 {
162 case 'a':
163 {
164 struct Buffer *tmpbuf = buf_pool_get();
165 char tmp[256] = { 0 };
166 tmp[0] = '<';
167 mutt_addrlist_write(&alias->addr, tmpbuf, true);
168 mutt_str_copy(tmp + 1, buf_string(tmpbuf), sizeof(tmp) - 1);
169 buf_pool_release(&tmpbuf);
170 const size_t len = strlen(tmp);
171 if (len < (sizeof(tmp) - 1))
172 {
173 tmp[len] = '>';
174 tmp[len + 1] = '\0';
175 }
176 mutt_format_s(buf, buflen, prec, tmp);
177 break;
178 }
179 case 'c':
180 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
181 snprintf(buf, buflen, fmt, av->num + 1);
182 break;
183 case 'e':
184 if (!optional)
185 mutt_format_s(buf, buflen, prec, NONULL(alias->comment));
186 else if (!alias->comment || (*alias->comment == '\0'))
187 optional = false;
188 break;
189 case 'n':
190 mutt_format_s(buf, buflen, prec, NONULL(alias->name));
191 break;
192 case 't':
193 snprintf(fmt, sizeof(fmt), "%%%sc", prec);
194 snprintf(buf, buflen, fmt, av->is_tagged ? '*' : ' ');
195 break;
196 default:
197 snprintf(fmt, sizeof(fmt), "%%%sc", prec);
198 snprintf(buf, buflen, fmt, op);
199 break;
200 }
201
202 if (optional)
203 {
204 mutt_expando_format(buf, buflen, col, cols, if_str, query_format_str, data,
206 }
207 else if (flags & MUTT_FORMAT_OPTIONAL)
208 {
209 mutt_expando_format(buf, buflen, col, cols, else_str, query_format_str,
211 }
212
213 /* We return the format string, unchanged */
214 return src;
215}
#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:150
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:742
#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 153 of file dlg_attach.c.

156{
157 char fmt[128] = { 0 };
158 char charset[128] = { 0 };
159 struct AttachPtr *aptr = (struct AttachPtr *) data;
160 bool optional = (flags & MUTT_FORMAT_OPTIONAL);
161
162 switch (op)
163 {
164 case 'C':
165 if (!optional)
166 {
167 if (mutt_is_text_part(aptr->body) &&
168 mutt_body_get_charset(aptr->body, charset, sizeof(charset)))
169 {
170 mutt_format_s(buf, buflen, prec, charset);
171 }
172 else
173 {
174 mutt_format_s(buf, buflen, prec, "");
175 }
176 }
177 else if (!mutt_is_text_part(aptr->body) ||
178 !mutt_body_get_charset(aptr->body, charset, sizeof(charset)))
179 {
180 optional = false;
181 }
182 break;
183 case 'c':
184 /* XXX */
185 if (!optional)
186 {
187 snprintf(fmt, sizeof(fmt), "%%%sc", prec);
188 snprintf(buf, buflen, fmt,
189 ((aptr->body->type != TYPE_TEXT) || aptr->body->noconv) ? 'n' : 'c');
190 }
191 else if ((aptr->body->type != TYPE_TEXT) || aptr->body->noconv)
192 {
193 optional = false;
194 }
195 break;
196 case 'd':
197 {
198 const char *const c_message_format = cs_subset_string(NeoMutt->sub, "message_format");
199 if (!optional)
200 {
201 if (aptr->body->description)
202 {
203 mutt_format_s(buf, buflen, prec, aptr->body->description);
204 break;
205 }
206 if (mutt_is_message_type(aptr->body->type, aptr->body->subtype) &&
207 c_message_format && aptr->body->email)
208 {
209 char s[128] = { 0 };
210 mutt_make_string(s, sizeof(s), cols, c_message_format, NULL, -1,
211 aptr->body->email,
213 if (*s)
214 {
215 mutt_format_s(buf, buflen, prec, s);
216 break;
217 }
218 }
219 if (!aptr->body->d_filename && !aptr->body->filename)
220 {
221 mutt_format_s(buf, buflen, prec, "<no description>");
222 break;
223 }
224 }
225 else if (aptr->body->description ||
226 (mutt_is_message_type(aptr->body->type, aptr->body->subtype) &&
227 c_message_format && aptr->body->email))
228 {
229 break;
230 }
231 }
232 /* fallthrough */
233 case 'F':
234 if (!optional)
235 {
236 if (aptr->body->d_filename)
237 {
238 mutt_format_s(buf, buflen, prec, aptr->body->d_filename);
239 break;
240 }
241 }
242 else if (!aptr->body->d_filename && !aptr->body->filename)
243 {
244 optional = false;
245 break;
246 }
247 /* fallthrough */
248 case 'f':
249 if (!optional)
250 {
251 if (aptr->body->filename && (*aptr->body->filename == '/'))
252 {
253 struct Buffer *path = buf_pool_get();
254
255 buf_strcpy(path, aptr->body->filename);
256 buf_pretty_mailbox(path);
257 mutt_format_s(buf, buflen, prec, buf_string(path));
258 buf_pool_release(&path);
259 }
260 else
261 {
262 mutt_format_s(buf, buflen, prec, NONULL(aptr->body->filename));
263 }
264 }
265 else if (!aptr->body->filename)
266 {
267 optional = false;
268 }
269 break;
270 case 'D':
271 if (!optional)
272 snprintf(buf, buflen, "%c", aptr->body->deleted ? 'D' : ' ');
273 else if (!aptr->body->deleted)
274 optional = false;
275 break;
276 case 'e':
277 if (!optional)
278 mutt_format_s(buf, buflen, prec, ENCODING(aptr->body->encoding));
279 break;
280 case 'I':
281 if (optional)
282 break;
283
284 const char dispchar[] = { 'I', 'A', 'F', '-' };
285 char ch;
286
287 if (aptr->body->disposition < sizeof(dispchar))
288 {
289 ch = dispchar[aptr->body->disposition];
290 }
291 else
292 {
293 mutt_debug(LL_DEBUG1, "ERROR: invalid content-disposition %d\n",
294 aptr->body->disposition);
295 ch = '!';
296 }
297 snprintf(buf, buflen, "%c", ch);
298 break;
299 case 'm':
300 if (!optional)
301 mutt_format_s(buf, buflen, prec, TYPE(aptr->body));
302 break;
303 case 'M':
304 if (!optional)
305 mutt_format_s(buf, buflen, prec, aptr->body->subtype);
306 else if (!aptr->body->subtype)
307 optional = false;
308 break;
309 case 'n':
310 if (optional)
311 break;
312
313 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
314 snprintf(buf, buflen, fmt, aptr->num + 1);
315 break;
316 case 'Q':
317 if (optional)
318 {
319 optional = aptr->body->attach_qualifies;
320 }
321 else
322 {
323 snprintf(fmt, sizeof(fmt), "%%%sc", prec);
324 mutt_format_s(buf, buflen, fmt, "Q");
325 }
326 break;
327 case 's':
328 {
329 size_t l = 0;
330 if (aptr->body->filename && (flags & MUTT_FORMAT_STAT_FILE))
331 {
332 l = mutt_file_get_size(aptr->body->filename);
333 }
334 else
335 {
336 l = aptr->body->length;
337 }
338
339 if (!optional)
340 {
341 char tmp[128] = { 0 };
342 mutt_str_pretty_size(tmp, sizeof(tmp), l);
343 mutt_format_s(buf, buflen, prec, tmp);
344 }
345 else if (l == 0)
346 {
347 optional = false;
348 }
349
350 break;
351 }
352 case 't':
353 if (!optional)
354 snprintf(buf, buflen, "%c", aptr->body->tagged ? '*' : ' ');
355 else if (!aptr->body->tagged)
356 optional = false;
357 break;
358 case 'T':
359 if (!optional)
360 mutt_format_s_tree(buf, buflen, prec, NONULL(aptr->tree));
361 else if (!aptr->tree)
362 optional = false;
363 break;
364 case 'u':
365 if (!optional)
366 snprintf(buf, buflen, "%c", aptr->body->unlink ? '-' : ' ');
367 else if (!aptr->body->unlink)
368 optional = false;
369 break;
370 case 'X':
371 if (optional)
372 {
373 optional = ((aptr->body->attach_count + aptr->body->attach_qualifies) != 0);
374 }
375 else
376 {
377 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
378 snprintf(buf, buflen, fmt, aptr->body->attach_count + aptr->body->attach_qualifies);
379 }
380 break;
381 default:
382 *buf = '\0';
383 }
384
385 if (optional)
386 {
387 mutt_expando_format(buf, buflen, col, cols, if_str, attach_format_str, data,
389 }
390 else if (flags & MUTT_FORMAT_OPTIONAL)
391 {
392 mutt_expando_format(buf, buflen, col, cols, else_str, attach_format_str,
394 }
395
396 /* We return the format string, unchanged */
397 return src;
398}
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:401
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
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:808
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body's character set.
Definition: body.c:131
long mutt_file_get_size(const char *path)
Get the size of a file.
Definition: file.c:1538
#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:153
#define mutt_debug(LEVEL,...)
Definition: logging2.h:87
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:1489
@ 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:560
void mutt_str_pretty_size(char *buf, size_t buflen, size_t num)
Display an abbreviated size, like 3.4K.
Definition: muttlib.c:1647
bool mutt_is_text_part(struct Body *b)
Is this part of an email in plain text?
Definition: muttlib.c:448
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition: parse.c:1475
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:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ autocrypt_format_str()

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

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

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

Definition at line 124 of file dlg_autocrypt.c.

128{
129 struct AccountEntry *entry = (struct AccountEntry *) data;
130 char tmp[128] = { 0 };
131
132 switch (op)
133 {
134 case 'a':
135 mutt_format_s(buf, buflen, prec, buf_string(entry->addr->mailbox));
136 break;
137 case 'k':
138 mutt_format_s(buf, buflen, prec, entry->account->keyid);
139 break;
140 case 'n':
141 snprintf(tmp, sizeof(tmp), "%%%sd", prec);
142 snprintf(buf, buflen, tmp, entry->num);
143 break;
144 case 'p':
145 if (entry->account->prefer_encrypt)
146 {
147 /* L10N: Autocrypt Account menu.
148 flag that an account has prefer-encrypt set */
149 mutt_format_s(buf, buflen, prec, _("prefer encrypt"));
150 }
151 else
152 {
153 /* L10N: Autocrypt Account menu.
154 flag that an account has prefer-encrypt unset;
155 thus encryption will need to be manually enabled. */
156 mutt_format_s(buf, buflen, prec, _("manual encrypt"));
157 }
158 break;
159 case 's':
160 if (entry->account->enabled)
161 {
162 /* L10N: Autocrypt Account menu.
163 flag that an account is enabled/active */
164 mutt_format_s(buf, buflen, prec, _("active"));
165 }
166 else
167 {
168 /* L10N: Autocrypt Account menu.
169 flag that an account is disabled/inactive */
170 mutt_format_s(buf, buflen, prec, _("inactive"));
171 }
172 break;
173 }
174
175 return (src);
176}
#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
%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
%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 210 of file browser.c.

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

◆ compress_format_str()

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

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

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

Definition at line 254 of file compress.c.

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

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

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

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

367{
368 char fmt[128] = { 0 };
369 bool optional = (flags & MUTT_FORMAT_OPTIONAL);
370
371 struct CryptEntry *entry = (struct CryptEntry *) data;
372 struct CryptKeyInfo *key = entry->key;
373
374 KeyFlags kflags = (key->flags);
375
376 switch (tolower(op))
377 {
378 case 'a':
379 if (!optional)
380 {
381 const char *s = NULL;
382 snprintf(fmt, sizeof(fmt), "%%%s.3s", prec);
383 if (key->kobj->subkeys)
384 s = gpgme_pubkey_algo_name(key->kobj->subkeys->pubkey_algo);
385 else
386 s = "?";
387 snprintf(buf, buflen, fmt, s);
388 }
389 break;
390
391 case 'c':
392 if (!optional)
393 {
394 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
395 snprintf(buf, buflen, fmt, crypt_key_abilities(kflags));
396 }
397 else if (!(kflags & KEYFLAG_ABILITIES))
398 {
399 optional = false;
400 }
401 break;
402
403 case 'f':
404 if (!optional)
405 {
406 snprintf(fmt, sizeof(fmt), "%%%sc", prec);
407 snprintf(buf, buflen, fmt, crypt_flags(kflags));
408 }
409 else if (!(kflags & KEYFLAG_RESTRICTIONS))
410 {
411 optional = false;
412 }
413 break;
414
415 case 'i':
416 if (!optional)
417 {
418 /* fixme: we need a way to distinguish between main and subkeys.
419 * Store the idx in entry? */
420 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
421 snprintf(buf, buflen, fmt, crypt_fpr_or_lkeyid(key));
422 }
423 break;
424
425 case 'k':
426 if (!optional)
427 {
428 /* fixme: we need a way to distinguish between main and subkeys.
429 * Store the idx in entry? */
430 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
431 snprintf(buf, buflen, fmt, crypt_keyid(key));
432 }
433 break;
434
435 case 'l':
436 if (!optional)
437 {
438 snprintf(fmt, sizeof(fmt), "%%%slu", prec);
439 unsigned long val;
440 if (key->kobj->subkeys)
441 val = key->kobj->subkeys->length;
442 else
443 val = 0;
444 snprintf(buf, buflen, fmt, val);
445 }
446 break;
447
448 case 'n':
449 if (!optional)
450 {
451 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
452 snprintf(buf, buflen, fmt, entry->num);
453 }
454 break;
455
456 case 'p':
457 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
458 snprintf(buf, buflen, fmt, gpgme_get_protocol_name(key->kobj->protocol));
459 break;
460
461 case 't':
462 {
463 char *s = NULL;
464 if ((kflags & KEYFLAG_ISX509))
465 {
466 s = "x";
467 }
468 else
469 {
470 switch (key->validity)
471 {
472 case GPGME_VALIDITY_FULL:
473 s = "f";
474 break;
475 case GPGME_VALIDITY_MARGINAL:
476 s = "m";
477 break;
478 case GPGME_VALIDITY_NEVER:
479 s = "n";
480 break;
481 case GPGME_VALIDITY_ULTIMATE:
482 s = "u";
483 break;
484 case GPGME_VALIDITY_UNDEFINED:
485 s = "q";
486 break;
487 case GPGME_VALIDITY_UNKNOWN:
488 default:
489 s = "?";
490 break;
491 }
492 }
493 snprintf(fmt, sizeof(fmt), "%%%sc", prec);
494 snprintf(buf, buflen, fmt, *s);
495 break;
496 }
497
498 case 'u':
499 if (!optional)
500 {
501 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
502 snprintf(buf, buflen, fmt, key->uid);
503 }
504 break;
505
506 case '[':
507 {
508 char buf2[128];
509 bool do_locales = true;
510 struct tm tm = { 0 };
511
512 char *p = buf;
513
514 const char *cp = src;
515 if (*cp == '!')
516 {
517 do_locales = false;
518 cp++;
519 }
520
521 size_t len = buflen - 1;
522 while ((len > 0) && (*cp != ']'))
523 {
524 if (*cp == '%')
525 {
526 cp++;
527 if (len >= 2)
528 {
529 *p++ = '%';
530 *p++ = *cp;
531 len -= 2;
532 }
533 else
534 {
535 break; /* not enough space */
536 }
537 cp++;
538 }
539 else
540 {
541 *p++ = *cp++;
542 len--;
543 }
544 }
545 *p = '\0';
546
547 if (key->kobj->subkeys && (key->kobj->subkeys->timestamp > 0))
548 tm = mutt_date_localtime(key->kobj->subkeys->timestamp);
549 else
550 tm = mutt_date_localtime(0); // Default to 1970-01-01
551
552 if (!do_locales)
553 setlocale(LC_TIME, "C");
554 strftime(buf2, sizeof(buf2), buf, &tm);
555 if (!do_locales)
556 setlocale(LC_TIME, "");
557
558 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
559 snprintf(buf, buflen, fmt, buf2);
560 if (len > 0)
561 src = cp + 1;
562 break;
563 }
564
565 default:
566 *buf = '\0';
567 }
568
569 if (optional)
570 {
571 mutt_expando_format(buf, buflen, col, cols, if_str, crypt_format_str, data,
573 }
574 else if (flags & MUTT_FORMAT_OPTIONAL)
575 {
576 mutt_expando_format(buf, buflen, col, cols, else_str, crypt_format_str,
578 }
579
580 /* We return the format string, unchanged */
581 return src;
582}
const char * crypt_fpr_or_lkeyid(struct CryptKeyInfo *k)
Find the fingerprint of a key.
Definition: crypt_gpgme.c:212
const char * crypt_keyid(struct CryptKeyInfo *k)
Find the ID for the key.
Definition: crypt_gpgme.c:136
static char crypt_flags(KeyFlags flags)
Parse the key flags into a single character.
Definition: dlg_gpgme.c:324
static char * crypt_key_abilities(KeyFlags flags)
Parse key flags into a string.
Definition: dlg_gpgme.c:294
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:363
#define KEYFLAG_ISX509
Key is an X.509 key.
Definition: lib.h:129
uint16_t KeyFlags
Flags describing PGP/SMIME keys, e.g. KEYFLAG_CANSIGN.
Definition: lib.h:125
#define KEYFLAG_RESTRICTIONS
Definition: lib.h:140
#define KEYFLAG_ABILITIES
Definition: lib.h:142
An entry in the Select-Key menu.
Definition: dlg_gpgme.c:108
struct CryptKeyInfo * key
Key.
Definition: dlg_gpgme.c:110
size_t num
Index number.
Definition: dlg_gpgme.c:109
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 340 of file dlg_pgp.c.

344{
345 char fmt[128] = { 0 };
346 bool optional = (flags & MUTT_FORMAT_OPTIONAL);
347
348 struct PgpEntry *entry = (struct PgpEntry *) data;
349 struct PgpUid *uid = entry->uid;
350 struct PgpKeyInfo *key = uid->parent;
351 struct PgpKeyInfo *pkey = pgp_principal_key(key);
352
353 if (isupper((unsigned char) op))
354 key = pkey;
355
356 KeyFlags kflags = key->flags | (pkey->flags & KEYFLAG_RESTRICTIONS) | uid->flags;
357
358 switch (tolower(op))
359 {
360 case 'a':
361 if (!optional)
362 {
363 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
364 snprintf(buf, buflen, fmt, key->algorithm);
365 }
366 break;
367 case 'c':
368 if (!optional)
369 {
370 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
371 snprintf(buf, buflen, fmt, pgp_key_abilities(kflags));
372 }
373 else if (!(kflags & KEYFLAG_ABILITIES))
374 {
375 optional = false;
376 }
377 break;
378 case 'f':
379 if (!optional)
380 {
381 snprintf(fmt, sizeof(fmt), "%%%sc", prec);
382 snprintf(buf, buflen, fmt, pgp_flags(kflags));
383 }
384 else if (!(kflags & KEYFLAG_RESTRICTIONS))
385 {
386 optional = false;
387 }
388 break;
389 case 'k':
390 if (!optional)
391 {
392 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
393 snprintf(buf, buflen, fmt, pgp_this_keyid(key));
394 }
395 break;
396 case 'l':
397 if (!optional)
398 {
399 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
400 snprintf(buf, buflen, fmt, key->keylen);
401 }
402 break;
403 case 'n':
404 if (!optional)
405 {
406 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
407 snprintf(buf, buflen, fmt, entry->num);
408 }
409 break;
410 case 't':
411 if (!optional)
412 {
413 snprintf(fmt, sizeof(fmt), "%%%sc", prec);
414 snprintf(buf, buflen, fmt, TrustFlags[uid->trust & 0x03]);
415 }
416 else if (!(uid->trust & 0x03))
417 {
418 /* undefined trust */
419 optional = false;
420 }
421 break;
422 case 'u':
423 if (!optional)
424 {
425 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
426 snprintf(buf, buflen, fmt, NONULL(uid->addr));
427 }
428 break;
429 case '[':
430 {
431 char buf2[128];
432 bool do_locales = true;
433 size_t len;
434
435 char *p = buf;
436
437 const char *cp = src;
438 if (*cp == '!')
439 {
440 do_locales = false;
441 cp++;
442 }
443
444 len = buflen - 1;
445 while ((len > 0) && (*cp != ']'))
446 {
447 if (*cp == '%')
448 {
449 cp++;
450 if (len >= 2)
451 {
452 *p++ = '%';
453 *p++ = *cp;
454 len -= 2;
455 }
456 else
457 {
458 break; /* not enough space */
459 }
460 cp++;
461 }
462 else
463 {
464 *p++ = *cp++;
465 len--;
466 }
467 }
468 *p = '\0';
469
470 if (!do_locales)
471 setlocale(LC_TIME, "C");
472 mutt_date_localtime_format(buf2, sizeof(buf2), buf, key->gen_time);
473 if (!do_locales)
474 setlocale(LC_TIME, "");
475
476 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
477 snprintf(buf, buflen, fmt, buf2);
478 if (len > 0)
479 src = cp + 1;
480 break;
481 }
482 default:
483 *buf = '\0';
484 }
485
486 if (optional)
487 {
488 mutt_expando_format(buf, buflen, col, cols, if_str, pgp_entry_format_str,
490 }
491 else if (flags & MUTT_FORMAT_OPTIONAL)
492 {
493 mutt_expando_format(buf, buflen, col, cols, else_str, pgp_entry_format_str,
495 }
496
497 /* We return the format string, unchanged */
498 return src;
499}
static char pgp_flags(KeyFlags flags)
Turn PGP key flags into a string.
Definition: dlg_pgp.c:304
static const char TrustFlags[]
Characters used to show the trust level for PGP keys.
Definition: dlg_pgp.c:114
static char * pgp_key_abilities(KeyFlags flags)
Turn PGP key abilities into a string.
Definition: dlg_pgp.c:276
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:340
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:88
An entry in a PGP key menu.
Definition: dlg_pgp.c:108
struct PgpUid * uid
Definition: dlg_pgp.c:110
size_t num
Index number.
Definition: dlg_pgp.c:109
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 79 of file pgpinvoke.c.

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

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

◆ group_index_format_str()

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

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

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

Definition at line 55 of file browse.c.

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

◆ nntp_format_str()

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

Expand the newsrc filename - Implements format_t -.

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

Definition at line 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 107 of file dlg_pattern.c.

111{
112 struct PatternEntry *entry = (struct PatternEntry *) data;
113
114 switch (op)
115 {
116 case 'd':
117 mutt_format_s(buf, buflen, prec, NONULL(entry->desc));
118 break;
119 case 'e':
120 mutt_format_s(buf, buflen, prec, NONULL(entry->expr));
121 break;
122 case 'n':
123 {
124 char tmp[32] = { 0 };
125 snprintf(tmp, sizeof(tmp), "%%%sd", prec);
126 snprintf(buf, buflen, tmp, entry->num);
127 break;
128 }
129 }
130
131 return src;
132}
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 680 of file send.c.

684{
685 struct Email *e = (struct Email *) data;
686 char *p = NULL;
687 char buf2[256];
688
689 const struct Address *to = TAILQ_FIRST(&e->env->to);
690 const struct Address *cc = TAILQ_FIRST(&e->env->cc);
691
692 buf[0] = '\0';
693 switch (op)
694 {
695 case 'n':
696 mutt_format_s(buf, buflen, prec, mutt_get_name(to));
697 break;
698
699 case 'u':
700 if (to)
701 {
702 mutt_str_copy(buf2, mutt_addr_for_display(to), sizeof(buf2));
703 if ((p = strpbrk(buf2, "%@")))
704 *p = '\0';
705 }
706 else
707 {
708 buf2[0] = '\0';
709 }
710 mutt_format_s(buf, buflen, prec, buf2);
711 break;
712
713 case 'v':
714 if (to)
715 mutt_format_s(buf2, sizeof(buf2), prec, mutt_get_name(to));
716 else if (cc)
717 mutt_format_s(buf2, sizeof(buf2), prec, mutt_get_name(cc));
718 else
719 *buf2 = '\0';
720 if ((p = strpbrk(buf2, " %@")))
721 *p = '\0';
722 mutt_format_s(buf, buflen, prec, buf2);
723 break;
724
725 default:
726 snprintf(buf, buflen, "%%%s%c", prec, op);
727 break;
728 }
729
730 if (flags & MUTT_FORMAT_OPTIONAL)
731 mutt_expando_format(buf, buflen, col, cols, else_str, greeting_format_str, data, flags);
732
733 return src;
734}
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:680
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ sidebar_format_str()

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

Format a string for the sidebar - Implements format_t -.

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

Definition at line 348 of file window.c.

352{
353 struct SidebarFormatData *sfdata = (struct SidebarFormatData *) data;
354 struct SbEntry *sbe = sfdata->entry;
355 struct IndexSharedData *shared = sfdata->shared;
356 char fmt[256] = { 0 };
357
358 if (!sbe || !shared || !buf)
359 return src;
360
361 buf[0] = '\0'; /* Just in case there's nothing to do */
362
363 struct Mailbox *m = sbe->mailbox;
364 if (!m)
365 return src;
366
367 struct Mailbox *m_cur = shared->mailbox;
368
369 bool c = m_cur && mutt_str_equal(m_cur->realpath, m->realpath);
370
371 bool optional = (flags & MUTT_FORMAT_OPTIONAL);
372
373 switch (op)
374 {
375 case 'B':
376 case 'D':
377 {
378 char indented[256] = { 0 };
379 size_t ilen = sizeof(indented);
380 size_t off = add_indent(indented, ilen, sbe);
381 snprintf(indented + off, ilen - off, "%s",
382 ((op == 'D') && sbe->mailbox->name) ? sbe->mailbox->name : sbe->box);
383 mutt_format_s(buf, buflen, prec, indented);
384 break;
385 }
386
387 case 'd':
388 if (!optional)
389 {
390 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
391 snprintf(buf, buflen, fmt, c ? m_cur->msg_deleted : 0);
392 }
393 else if ((c && (m_cur->msg_deleted == 0)) || !c)
394 {
395 optional = false;
396 }
397 break;
398
399 case 'F':
400 if (!optional)
401 {
402 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
403 snprintf(buf, buflen, fmt, m->msg_flagged);
404 }
405 else if (m->msg_flagged == 0)
406 {
407 optional = false;
408 }
409 break;
410
411 case 'L':
412 if (!optional)
413 {
414 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
415 snprintf(buf, buflen, fmt, c ? m_cur->vcount : m->msg_count);
416 }
417 else if ((c && (m_cur->vcount == m->msg_count)) || !c)
418 {
419 optional = false;
420 }
421 break;
422
423 case 'N':
424 if (!optional)
425 {
426 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
427 snprintf(buf, buflen, fmt, m->msg_unread);
428 }
429 else if (m->msg_unread == 0)
430 {
431 optional = false;
432 }
433 break;
434
435 case 'n':
436 if (!optional)
437 {
438 snprintf(fmt, sizeof(fmt), "%%%sc", prec);
439 snprintf(buf, buflen, fmt, m->has_new ? 'N' : ' ');
440 }
441 else if (m->has_new == false)
442 {
443 optional = false;
444 }
445 break;
446
447 case 'o':
448 if (!optional)
449 {
450 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
451 snprintf(buf, buflen, fmt, m->msg_unread - m->msg_new);
452 }
453 else if ((c && (m_cur->msg_unread - m_cur->msg_new) == 0) || !c)
454 {
455 optional = false;
456 }
457 break;
458
459 case 'r':
460 if (!optional)
461 {
462 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
463 snprintf(buf, buflen, fmt, m->msg_count - m->msg_unread);
464 }
465 else if ((c && (m_cur->msg_count - m_cur->msg_unread) == 0) || !c)
466 {
467 optional = false;
468 }
469 break;
470
471 case 'S':
472 if (!optional)
473 {
474 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
475 snprintf(buf, buflen, fmt, m->msg_count);
476 }
477 else if (m->msg_count == 0)
478 {
479 optional = false;
480 }
481 break;
482
483 case 't':
484 if (!optional)
485 {
486 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
487 snprintf(buf, buflen, fmt, c ? m_cur->msg_tagged : 0);
488 }
489 else if ((c && (m_cur->msg_tagged == 0)) || !c)
490 {
491 optional = false;
492 }
493 break;
494
495 case 'Z':
496 if (!optional)
497 {
498 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
499 snprintf(buf, buflen, fmt, m->msg_new);
500 }
501 else if ((c && (m_cur->msg_new) == 0) || !c)
502 {
503 optional = false;
504 }
505 break;
506
507 case '!':
508 if (m->msg_flagged == 0)
509 {
510 mutt_format_s(buf, buflen, prec, "");
511 }
512 else if (m->msg_flagged == 1)
513 {
514 mutt_format_s(buf, buflen, prec, "!");
515 }
516 else if (m->msg_flagged == 2)
517 {
518 mutt_format_s(buf, buflen, prec, "!!");
519 }
520 else
521 {
522 snprintf(fmt, sizeof(fmt), "%d!", m->msg_flagged);
523 mutt_format_s(buf, buflen, prec, fmt);
524 }
525 break;
526 }
527
528 if (optional)
529 {
530 mutt_expando_format(buf, buflen, col, cols, if_str, sidebar_format_str, data, flags);
531 }
532 else if (flags & MUTT_FORMAT_OPTIONAL)
533 {
534 mutt_expando_format(buf, buflen, col, cols, else_str, sidebar_format_str, data, flags);
535 }
536
537 /* We return the format string, unchanged */
538 return src;
539}
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:348
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
char * name
A short name for the Mailbox.
Definition: mailbox.h:82
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 = OptAttachMsg ? 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}
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition: helpers.c:292
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using '~' or '='.
Definition: muttlib.c:481
bool OptAttachMsg
(pseudo) used by attach-message
Definition: globals.c:66
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:158
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:428
#define MUTT_MAILBOX_CHECK_NO_FLAGS
No flags are set.
Definition: mxapi.h:74
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
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:110
struct Buffer pathbuf
Path of the Mailbox.
Definition: mailbox.h:80
bool dontwrite
Don't write the mailbox on close.
Definition: mailbox.h:111
off_t size
Size of the Mailbox.
Definition: mailbox.h:84
void * compress_info
Compressed mbox module private data.
Definition: mailbox.h:120
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: