NeoMutt  2025-12-11-769-g906513
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
node_expando.h File Reference

Expando Node for an Expando. More...

#include <stdbool.h>
#include "definition.h"
#include "render.h"
+ Include dependency graph for node_expando.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  NodeExpandoPrivate
 Private data for an Expando -. More...
 

Functions

struct ExpandoNodenode_expando_new (struct ExpandoFormat *fmt, int did, int uid)
 Create a new Expando ExpandoNode.
 
void node_expando_set_color (const struct ExpandoNode *node, int cid)
 Set the colour for an Expando.
 
void node_expando_set_has_tree (const struct ExpandoNode *node, bool has_tree)
 Set the has_tree flag for an Expando.
 
struct ExpandoFormatparse_format (const char *str, const char **parsed_until, struct ExpandoParseError *err)
 Parse a format string.
 
struct ExpandoNodeparse_long_name (const char *str, const struct ExpandoDefinition *defs, ExpandoParserFlags flags, struct ExpandoFormat *fmt, const char **parsed_until, struct ExpandoParseError *err)
 Create an expando by its long name.
 
struct ExpandoNodeparse_short_name (const char *str, const struct ExpandoDefinition *defs, ExpandoParserFlags flags, struct ExpandoFormat *fmt, const char **parsed_until, struct ExpandoParseError *err)
 Create an expando by its short name.
 
struct ExpandoNodenode_expando_parse (const char *str, const struct ExpandoDefinition *defs, ExpandoParserFlags flags, const char **parsed_until, struct ExpandoParseError *err)
 Parse an Expando format string.
 
struct ExpandoNodenode_expando_parse_name (const char *str, const struct ExpandoDefinition *defs, ExpandoParserFlags flags, const char **parsed_until, struct ExpandoParseError *err)
 Parse an Expando format string.
 
int node_expando_render (const struct ExpandoNode *node, const struct ExpandoRenderCallback *erc, struct Buffer *buf, int max_cols, void *data, MuttFormatFlags flags)
 Render an Expando Node - Implements ExpandoNode::render() -.
 
struct ExpandoNodenode_expando_parse_enclosure (const char *str, int did, int uid, char terminator, struct ExpandoFormat *fmt, const char **parsed_until, struct ExpandoParseError *err)
 Parse an enclosed Expando.
 

Detailed Description

Expando Node for an Expando.

Authors
  • Tóth János
  • Richard Russon

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

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

Definition in file node_expando.h.

Function Documentation

◆ node_expando_new()

struct ExpandoNode * node_expando_new ( struct ExpandoFormat * fmt,
int did,
int uid )

Create a new Expando ExpandoNode.

Parameters
fmtFormatting data
didDomain ID
uidUnique ID
Return values
ptrNew Expando ExpandoNode

Definition at line 79 of file node_expando.c.

80{
81 struct ExpandoNode *node = node_new();
82
83 node->type = ENT_EXPANDO;
84 node->did = did;
85 node->uid = uid;
87
88 node->format = fmt;
89
92
93 return node;
94}
int node_expando_render(const struct ExpandoNode *node, const struct ExpandoRenderCallback *erc, struct Buffer *buf, int max_cols, void *data, MuttFormatFlags flags)
Render an Expando Node - Implements ExpandoNode::render() -.
struct ExpandoNode * node_new(void)
Create a new empty ExpandoNode.
Definition node.c:39
@ ENT_EXPANDO
Expando, e.g. 'n'.
Definition node.h:39
void node_expando_private_free(void **ptr)
Free Expando private data - Implements ExpandoNode::ndata_free()
struct NodeExpandoPrivate * node_expando_private_new(void)
Create new Expando private data.
Basic Expando Node.
Definition node.h:67
int uid
Unique ID, e.g. ED_EMA_SIZE.
Definition node.h:70
void * ndata
Private node data.
Definition node.h:77
struct ExpandoFormat * format
Formatting info.
Definition node.h:72
int(* render)(const struct ExpandoNode *node, const struct ExpandoRenderCallback *erc, struct Buffer *buf, int max_cols, void *data, MuttFormatFlags flags)
Definition node.h:92
int did
Domain ID, e.g. ED_EMAIL.
Definition node.h:69
enum ExpandoNodeType type
Type of Node, e.g. ENT_EXPANDO.
Definition node.h:68
void(* ndata_free)(void **ptr)
Function to free the private node data.
Definition node.h:78
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ node_expando_set_color()

void node_expando_set_color ( const struct ExpandoNode * node,
int cid )

Set the colour for an Expando.

Parameters
nodeNode to alter
cidColour

Definition at line 101 of file node_expando.c.

102{
103 if (!node || (node->type != ENT_EXPANDO) || !node->ndata)
104 return;
105
106 struct NodeExpandoPrivate *priv = node->ndata;
107
108 priv->color = cid;
109}
Private data for an Expando -.
int color
ColorId to use.
+ Here is the caller graph for this function:

◆ node_expando_set_has_tree()

void node_expando_set_has_tree ( const struct ExpandoNode * node,
bool has_tree )

Set the has_tree flag for an Expando.

Parameters
nodeNode to alter
has_treeFlag to set

Definition at line 116 of file node_expando.c.

117{
118 if (!node || (node->type != ENT_EXPANDO) || !node->ndata)
119 return;
120
121 struct NodeExpandoPrivate *priv = node->ndata;
122
123 priv->has_tree = has_tree;
124}
bool has_tree
Contains tree characters, used in $index_format's s.
+ Here is the caller graph for this function:

◆ parse_format()

struct ExpandoFormat * parse_format ( const char * str,
const char ** parsed_until,
struct ExpandoParseError * err )

Parse a format string.

Parameters
[in]strString to parse
[out]parsed_untilFirst character after the parsed string
[out]errBuffer for errors
Return values
ptrNew ExpandoFormat object

Parse a printf()-style format, e.g. '-15.20x'

Note
A trailing _ (underscore) means lowercase the string

Definition at line 137 of file node_expando.c.

139{
140 if (!str || !parsed_until || !err)
141 return NULL;
142
143 const char *start = str;
144
145 struct ExpandoFormat *fmt = MUTT_MEM_CALLOC(1, struct ExpandoFormat);
146
147 fmt->leader = ' ';
149 fmt->min_cols = 0;
150 fmt->max_cols = -1;
151
152 if (*str == '-')
153 {
155 str++;
156 }
157 else if (*str == '=')
158 {
160 str++;
161 }
162
163 if (*str == '0')
164 {
165 // Ignore '0' with left-justification
166 if (fmt->justification != JUSTIFY_LEFT)
167 fmt->leader = '0';
168 str++;
169 }
170
171 // Parse the width (min_cols)
172 if (mutt_isdigit(*str))
173 {
174 unsigned short number = 0;
175 const char *end_ptr = mutt_str_atous(str, &number);
176
177 if (!end_ptr || (number == USHRT_MAX))
178 {
179 err->position = str;
180 snprintf(err->message, sizeof(err->message), _("Invalid number: %s"), str);
181 FREE(&fmt);
182 return NULL;
183 }
184
185 fmt->min_cols = number;
186 str = end_ptr;
187 }
188
189 // Parse the precision (max_cols)
190 if (*str == '.')
191 {
192 str++;
193
194 unsigned short number = 1;
195
196 if (mutt_isdigit(*str))
197 {
198 const char *end_ptr = mutt_str_atous(str, &number);
199
200 if (!end_ptr || (number == USHRT_MAX))
201 {
202 err->position = str;
203 snprintf(err->message, sizeof(err->message), _("Invalid number: %s"), str);
204 FREE(&fmt);
205 return NULL;
206 }
207
208 str = end_ptr;
209 }
210 else
211 {
212 number = 0;
213 }
214
215 fmt->leader = (number == 0) ? ' ' : '0';
216 fmt->max_cols = number;
217 }
218
219 // A modifier of '_' before the letter means force lower case
220 if (*str == '_')
221 {
222 fmt->lower = true;
223 str++;
224 }
225
226 if (str == start) // Failed to parse anything
227 FREE(&fmt);
228
229 if (fmt && (fmt->min_cols == 0) && (fmt->max_cols == -1) && !fmt->lower)
230 FREE(&fmt);
231
232 *parsed_until = str;
233 return fmt;
234}
const char * mutt_str_atous(const char *str, unsigned short *dst)
Convert ASCII string to an unsigned short.
Definition atoi.c:269
bool mutt_isdigit(int arg)
Wrapper for isdigit(3)
Definition ctype.c:66
@ JUSTIFY_RIGHT
Right justify the text.
Definition format.h:36
@ JUSTIFY_LEFT
Left justify the text.
Definition format.h:34
@ JUSTIFY_CENTER
Centre the text.
Definition format.h:35
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
#define MUTT_MEM_CALLOC(n, type)
Definition memory.h:52
#define _(a)
Definition message.h:28
Formatting information for an Expando.
Definition node.h:53
char leader
Leader character, 0 or space.
Definition node.h:57
enum FormatJustify justification
Justification: left, centre, right.
Definition node.h:56
int min_cols
Minimum number of screen columns.
Definition node.h:54
int max_cols
Maximum number of screen columns.
Definition node.h:55
bool lower
Display in lower case.
Definition node.h:58
char message[1024]
Error message.
Definition parse.h:38
const char * position
Position of error in original string.
Definition parse.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_long_name()

struct ExpandoNode * parse_long_name ( const char * str,
const struct ExpandoDefinition * defs,
ExpandoParserFlags flags,
struct ExpandoFormat * fmt,
const char ** parsed_until,
struct ExpandoParseError * err )

Create an expando by its long name.

Parameters
[in]strString to parse
[in]defsExpando definitions
[in]flagsFlag for conditional expandos
[in]fmtFormatting info
[out]parsed_untilFirst character after parsed string
[out]errBuffer for errors
Return values
ptrNew ExpandoNode

Definition at line 288 of file node_expando.c.

292{
293 if (!str || !defs)
294 return NULL;
295
296 const struct ExpandoDefinition *def = defs;
297 for (; def && (def->short_name || def->long_name); def++)
298 {
299 if (!def->long_name)
300 continue;
301
302 size_t len = mutt_str_len(def->long_name);
303
304 if (mutt_strn_equal(def->long_name, str, len))
305 {
306 *parsed_until = str + len;
307 if (def->parse)
308 {
309 struct ExpandoNode *node = def->parse(str, fmt, def->did, def->uid,
310 flags, parsed_until, err);
311 if (node || (err->message[0] != '\0'))
312 return node;
313 }
314 else
315 {
316 if (str[len] != '}') // Not an exact match
317 continue;
318
319 return node_expando_new(fmt, def->did, def->uid);
320 }
321 }
322 }
323
324 return NULL;
325}
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
Definition string.c:429
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition string.c:503
struct ExpandoNode * node_expando_new(struct ExpandoFormat *fmt, int did, int uid)
Create a new Expando ExpandoNode.
Definition of a format string.
Definition definition.h:43
short uid
Unique ID in domain.
Definition definition.h:47
struct ExpandoNode *(* parse)(const char *str, struct ExpandoFormat *fmt, int did, int uid, ExpandoParserFlags flags, const char **parsed_until, struct ExpandoParseError *err)
Definition definition.h:62
const char * long_name
Long Expando name, e.g. "name".
Definition definition.h:45
short did
Domain ID.
Definition definition.h:46
const char * short_name
Short Expando name, e.g. "n".
Definition definition.h:44
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_short_name()

struct ExpandoNode * parse_short_name ( const char * str,
const struct ExpandoDefinition * defs,
ExpandoParserFlags flags,
struct ExpandoFormat * fmt,
const char ** parsed_until,
struct ExpandoParseError * err )

Create an expando by its short name.

Parameters
[in]strString to parse
[in]defsExpando definitions
[in]flagsFlag for conditional expandos
[in]fmtFormatting info
[out]parsed_untilFirst character after parsed string
[out]errBuffer for errors
Return values
ptrNew ExpandoNode

Definition at line 246 of file node_expando.c.

250{
251 if (!str || !defs)
252 return NULL;
253
254 const struct ExpandoDefinition *def = defs;
255 for (; def && (def->short_name || def->long_name); def++)
256 {
257 size_t len = mutt_str_len(def->short_name);
258 if (len == 0)
259 continue;
260
261 if (mutt_strn_equal(def->short_name, str, len))
262 {
263 if (def->parse)
264 {
265 return def->parse(str, fmt, def->did, def->uid, flags, parsed_until, err);
266 }
267 else
268 {
269 *parsed_until = str + len;
270 return node_expando_new(fmt, def->did, def->uid);
271 }
272 }
273 }
274
275 return NULL;
276}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ node_expando_parse()

struct ExpandoNode * node_expando_parse ( const char * str,
const struct ExpandoDefinition * defs,
ExpandoParserFlags flags,
const char ** parsed_until,
struct ExpandoParseError * err )

Parse an Expando format string.

Parameters
[in]strString to parse
[in]defsExpando definitions
[in]flagsFlag for conditional expandos
[out]parsed_untilFirst character after parsed string
[out]errBuffer for errors
Return values
ptrNew ExpandoNode

Definition at line 336 of file node_expando.c.

339{
340 ASSERT(str[0] == '%');
341 str++;
342
343 struct ExpandoFormat *fmt = parse_format(str, parsed_until, err);
344 if (err->position)
345 {
346 FREE(&fmt);
347 return NULL;
348 }
349
350 str = *parsed_until;
351
352 struct ExpandoNode *node = parse_short_name(str, defs, flags, fmt, parsed_until, err);
353 if (node)
354 return node;
355
356 if (!err->position)
357 {
358 err->position = *parsed_until;
359 // L10N: e.g. "Unknown expando: %Q"
360 snprintf(err->message, sizeof(err->message), _("Unknown expando: %%%.1s"), *parsed_until);
361 }
362
363 FREE(&fmt);
364 return NULL;
365}
struct ExpandoNode * parse_short_name(const char *str, const struct ExpandoDefinition *defs, ExpandoParserFlags flags, struct ExpandoFormat *fmt, const char **parsed_until, struct ExpandoParseError *err)
Create an expando by its short name.
struct ExpandoFormat * parse_format(const char *str, const char **parsed_until, struct ExpandoParseError *err)
Parse a format string.
#define ASSERT(COND)
Definition signal2.h:59
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ node_expando_parse_name()

struct ExpandoNode * node_expando_parse_name ( const char * str,
const struct ExpandoDefinition * defs,
ExpandoParserFlags flags,
const char ** parsed_until,
struct ExpandoParseError * err )

Parse an Expando format string.

Parameters
[in]strString to parse
[in]defsExpando definitions
[in]flagsFlag for conditional expandos
[out]parsed_untilFirst character after parsed string
[out]errBuffer for errors
Return values
ptrNew ExpandoNode

Definition at line 376 of file node_expando.c.

380{
381 ASSERT(str[0] == '%');
382 str++;
383
384 struct ExpandoFormat *fmt = parse_format(str, parsed_until, err);
385 if (err->position)
386 goto fail;
387
388 str = *parsed_until;
389
390 if (str[0] != '{')
391 goto fail;
392
393 str++;
394
395 struct ExpandoNode *node = parse_long_name(str, defs, flags, fmt, parsed_until, err);
396 if (!node)
397 {
398 if (!err->position)
399 {
400 const char *end = str + strspn(str, "abcdefghijklmnopqrstuvwxyz0123456789-");
401
402 // Only report an error if the content looks like a long name (i.e. starts
403 // with at least one valid character). If it doesn't, the '{' is probably
404 // a short-name expando like %{%b %d} — let node_expando_parse() handle it.
405 if (end != str)
406 {
407 err->position = str;
408 if (*end != '}')
409 {
410 snprintf(err->message, sizeof(err->message), _("Expando is missing closing '}'"));
411 }
412 else
413 {
414 // L10N: e.g. "Unknown expando: %{bad}"
415 snprintf(err->message, sizeof(err->message),
416 _("Unknown expando: %%{%.*s}"), (int) (end - str), str);
417 }
418 }
419 }
420 goto fail;
421 }
422
423 fmt = NULL; // owned by the node, now
424
425 if ((*parsed_until)[0] == '}')
426 {
427 (*parsed_until)++;
428 return node;
429 }
430
431 node_free(&node);
432
433fail:
434 FREE(&fmt);
435 return NULL;
436}
void node_free(struct ExpandoNode **ptr)
Free an ExpandoNode and its private data.
Definition node.c:48
struct ExpandoNode * parse_long_name(const char *str, const struct ExpandoDefinition *defs, ExpandoParserFlags flags, struct ExpandoFormat *fmt, const char **parsed_until, struct ExpandoParseError *err)
Create an expando by its long name.
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ node_expando_parse_enclosure()

struct ExpandoNode * node_expando_parse_enclosure ( const char * str,
int did,
int uid,
char terminator,
struct ExpandoFormat * fmt,
const char ** parsed_until,
struct ExpandoParseError * err )

Parse an enclosed Expando.

Parameters
[in]strString to parse
[in]didDomain ID
[in]uidUnique ID
[in]terminatorTerminating character
[in]fmtFormatting info
[out]parsed_untilFirst character after the parsed string
[out]errBuffer for errors
Return values
ptrNew ExpandoNode

Definition at line 476 of file node_expando.c.

482{
483 str++; // skip opening char
484
485 const char *expando_end = skip_until_ch(str, terminator);
486
487 if (*expando_end != terminator)
488 {
489 err->position = expando_end;
490 snprintf(err->message, sizeof(err->message),
491 // L10N: Expando is missing a terminator character
492 // e.g. "%[..." is missing the final ']'
493 _("Expando is missing terminator: '%c'"), terminator);
494 return NULL;
495 }
496
497 *parsed_until = expando_end + 1;
498
499 struct ExpandoNode *node = node_expando_new(fmt, did, uid);
500
501 struct Buffer *buf = buf_pool_get();
502 for (; str < expando_end; str++)
503 {
504 if (str[0] == '\\')
505 continue;
506 buf_addch(buf, str[0]);
507 }
508
509 node->text = buf_strdup(buf);
510 buf_pool_release(&buf);
511
512 return node;
513}
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition buffer.c:241
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition buffer.c:571
const char * skip_until_ch(const char *str, char terminator)
Search a string for a terminator character.
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
String manipulation buffer.
Definition buffer.h:36
const char * text
Node-specific text.
Definition node.h:73
+ Here is the call graph for this function:
+ Here is the caller graph for this function: