NeoMutt  2024-04-16-36-g75b6fb
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
node_padding.c
Go to the documentation of this file.
1
30#include "config.h"
31#include <stddef.h>
32#include <stdio.h>
33#include "mutt/lib.h"
34#include "gui/lib.h"
35#include "node_padding.h"
36#include "definition.h"
37#include "node.h"
38#include "node_condition.h"
39#include "parse.h"
40#include "render.h"
41
48{
49 struct NodePaddingPrivate *priv = mutt_mem_calloc(1, sizeof(struct NodePaddingPrivate));
50
51 priv->pad_type = pad_type;
52
53 return priv;
54}
55
61{
62 if (!ptr || !*ptr)
63 return;
64
65 FREE(ptr);
66}
67
76int pad_string(const struct ExpandoNode *node, struct Buffer *buf, int max_cols)
77{
78 const int pad_len = node->end - node->start;
79 const int pad_cols = mutt_strnwidth(node->start, pad_len);
80 int total_cols = 0;
81
82 while (pad_cols <= max_cols)
83 {
84 buf_addstr_n(buf, node->start, pad_len);
85
86 max_cols -= pad_cols;
87 total_cols += pad_cols;
88 }
89
90 for (; (max_cols > 0); buf++, max_cols--)
91 {
92 buf_addch(buf, ' ');
93 total_cols++;
94 }
95
96 return total_cols;
97}
98
103 const struct ExpandoRenderData *rdata, struct Buffer *buf,
104 int max_cols, void *data, MuttFormatFlags flags)
105{
106 struct ExpandoNode *left = node_get_child(node, ENP_LEFT);
107
108 int total_cols = node_tree_render(left, rdata, buf, max_cols, data, flags);
109
110 total_cols += pad_string(node, buf, max_cols - total_cols);
111
112 return total_cols;
113}
114
122 const struct ExpandoRenderData *rdata, struct Buffer *buf,
123 int max_cols, void *data, MuttFormatFlags flags)
124{
125 struct Buffer *buf_left = buf_pool_get();
126 struct Buffer *buf_pad = buf_pool_get();
127 struct Buffer *buf_right = buf_pool_get();
128
129 int cols_used = 0;
130
131 struct ExpandoNode *left = node_get_child(node, ENP_LEFT);
132 if (left)
133 cols_used += node_tree_render(left, rdata, buf_left, max_cols - cols_used, data, flags);
134
135 struct ExpandoNode *right = node_get_child(node, ENP_RIGHT);
136 if (right)
137 cols_used += node_tree_render(right, rdata, buf_right, max_cols - cols_used, data, flags);
138
139 if (max_cols > cols_used)
140 cols_used += pad_string(node, buf_pad, max_cols - cols_used);
141
142 buf_addstr(buf, buf_string(buf_left));
143 buf_addstr(buf, buf_string(buf_pad));
144 buf_addstr(buf, buf_string(buf_right));
145
146 buf_pool_release(&buf_left);
147 buf_pool_release(&buf_pad);
148 buf_pool_release(&buf_right);
149
150 return cols_used;
151}
152
160 const struct ExpandoRenderData *rdata, struct Buffer *buf,
161 int max_cols, void *data, MuttFormatFlags flags)
162{
163 struct Buffer *buf_left = buf_pool_get();
164 struct Buffer *buf_pad = buf_pool_get();
165 struct Buffer *buf_right = buf_pool_get();
166
167 int cols_used = 0;
168
169 struct ExpandoNode *right = node_get_child(node, ENP_RIGHT);
170 if (right)
171 cols_used += node_tree_render(right, rdata, buf_right, max_cols - cols_used, data, flags);
172
173 struct ExpandoNode *left = node_get_child(node, ENP_LEFT);
174 if (left)
175 cols_used += node_tree_render(left, rdata, buf_left, max_cols - cols_used, data, flags);
176
177 if (max_cols > cols_used)
178 cols_used += pad_string(node, buf_pad, max_cols - cols_used);
179
180 buf_addstr(buf, buf_string(buf_left));
181 buf_addstr(buf, buf_string(buf_pad));
182 buf_addstr(buf, buf_string(buf_right));
183
184 buf_pool_release(&buf_left);
185 buf_pool_release(&buf_pad);
186 buf_pool_release(&buf_right);
187
188 return cols_used;
189}
190
199 const char *start, const char *end)
200{
201 struct ExpandoNode *node = node_new();
202
203 node->type = ENT_PADDING;
204 node->start = start;
205 node->end = end;
206
207 switch (pad_type)
208 {
209 case EPT_FILL_EOL:
211 break;
212 case EPT_HARD_FILL:
214 break;
215 case EPT_SOFT_FILL:
217 break;
218 };
219
220 node->ndata = node_padding_private_new(pad_type);
222
223 return node;
224}
225
232struct ExpandoNode *node_padding_parse(const char *str, const char **parsed_until,
233 int did, int uid, ExpandoParserFlags flags,
234 struct ExpandoParseError *error)
235{
236 if (flags & EP_CONDITIONAL)
237 {
238 snprintf(error->message, sizeof(error->message),
239 // L10N: Conditional Expandos can only depend on other Expandos
240 // e.g. "%<X?apple>" displays "apple" if "%X" is true.
241 _("Padding cannot be used as a condition"));
242 error->position = str;
243 return NULL;
244 }
245
246 enum ExpandoPadType pt = 0;
247 if (*str == '|')
248 {
249 pt = EPT_FILL_EOL;
250 }
251 else if (*str == '>')
252 {
253 pt = EPT_HARD_FILL;
254 }
255 else if (*str == '*')
256 {
257 pt = EPT_SOFT_FILL;
258 }
259 else
260 {
261 return NULL;
262 }
263 str++;
264
265 const size_t consumed = mutt_mb_charlen(str, NULL);
266
267 *parsed_until = str + consumed;
268 return node_padding_new(pt, str, str + consumed);
269}
270
275void node_padding_repad(struct ExpandoNode **parent)
276{
277 if (!parent || !*parent)
278 return;
279
280 struct ExpandoNode *node = *parent;
281 struct ExpandoNode *prev = NULL;
282 for (; node; prev = node, node = node->next)
283 {
284 if (node->type == ENT_PADDING)
285 {
286 if (node != *parent)
287 ARRAY_SET(&node->children, ENP_LEFT, *parent); // First sibling
288
289 ARRAY_SET(&node->children, ENP_RIGHT, node->next); // Sibling after Padding
290
291 if (prev)
292 prev->next = NULL;
293 node->next = NULL;
294 *parent = node;
295 return;
296 }
297
298 if (node->type == ENT_CONDITION)
299 {
300 struct ExpandoNode **ptr = NULL;
301
302 ptr = ARRAY_GET(&node->children, ENC_TRUE);
304
305 ptr = ARRAY_GET(&node->children, ENC_FALSE);
307 }
308 }
309}
#define ARRAY_SET(head, idx, elem)
Set an element in the array.
Definition: array.h:123
#define ARRAY_GET(head, idx)
Return the element at index.
Definition: array.h:109
size_t buf_addstr_n(struct Buffer *buf, const char *s, size_t len)
Add a string to a Buffer, expanding it if necessary.
Definition: buffer.c:95
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:96
size_t mutt_strnwidth(const char *s, size_t n)
Measure a string's width in screen cells.
Definition: curs_lib.c:456
Define an Expando format string.
uint8_t ExpandoParserFlags
Flags for expando_parse(), e.g. EP_CONDITIONAL.
Definition: definition.h:41
#define EP_CONDITIONAL
Expando is being used as a condition.
Definition: definition.h:43
Expando Parsing.
struct ExpandoNode * node_padding_parse(const char *str, const char **parsed_until, int did, int uid, ExpandoParserFlags flags, struct ExpandoParseError *error)
Parse a Padding Expando - Implements ExpandoDefinition::parse() -.
Definition: node_padding.c:232
int node_padding_render_hard(const struct ExpandoNode *node, const struct ExpandoRenderData *rdata, struct Buffer *buf, int max_cols, void *data, MuttFormatFlags flags)
Render Hard Padding - Implements ExpandoNode::render() -.
Definition: node_padding.c:121
int node_padding_render_soft(const struct ExpandoNode *node, const struct ExpandoRenderData *rdata, struct Buffer *buf, int max_cols, void *data, MuttFormatFlags flags)
Render Soft Padding - Implements ExpandoNode::render() -.
Definition: node_padding.c:159
int node_padding_render_eol(const struct ExpandoNode *node, const struct ExpandoRenderData *rdata, struct Buffer *buf, int max_cols, void *data, MuttFormatFlags flags)
Render End-of-Line Padding - Implements ExpandoNode::render() -.
Definition: node_padding.c:102
Convenience wrapper for the gui headers.
int mutt_mb_charlen(const char *s, int *width)
Count the bytes in a (multibyte) character.
Definition: mbyte.c:55
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define FREE(x)
Definition: memory.h:45
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
struct ExpandoNode * node_new(void)
Create a new empty ExpandoNode.
Definition: node.c:39
struct ExpandoNode * node_get_child(const struct ExpandoNode *node, int index)
Get a child of an ExpandoNode.
Definition: node.c:99
Basic Expando Node.
@ ENT_CONDITION
True/False condition.
Definition: node.h:40
@ ENT_PADDING
Padding: soft, hard, EOL.
Definition: node.h:39
Expando Node for a Condition.
@ ENC_FALSE
Index of False Node.
@ ENC_TRUE
Index of True Node.
void node_padding_repad(struct ExpandoNode **parent)
Rearrange Padding in a tree of ExpandoNodes.
Definition: node_padding.c:275
void node_padding_private_free(void **ptr)
Free Padding private data - Implements ExpandoNode::ndata_free()
Definition: node_padding.c:60
int pad_string(const struct ExpandoNode *node, struct Buffer *buf, int max_cols)
Pad a buffer with a character.
Definition: node_padding.c:76
struct NodePaddingPrivate * node_padding_private_new(enum ExpandoPadType pad_type)
Create new Padding private data.
Definition: node_padding.c:47
struct ExpandoNode * node_padding_new(enum ExpandoPadType pad_type, const char *start, const char *end)
Creata new Padding ExpandoNode.
Definition: node_padding.c:198
Expando Node for Padding.
@ ENP_LEFT
Index of Left-Hand Nodes.
Definition: node_padding.h:56
@ ENP_RIGHT
Index of Right-Hand Nodes.
Definition: node_padding.h:57
ExpandoPadType
Padding type.
Definition: node_padding.h:43
@ EPT_FILL_EOL
Fill to the end-of-line.
Definition: node_padding.h:44
@ EPT_SOFT_FILL
Soft-fill: right-hand-side will be truncated.
Definition: node_padding.h:46
@ EPT_HARD_FILL
Hard-fill: left-hand-side will be truncated.
Definition: node_padding.h:45
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
int node_tree_render(const struct ExpandoNode *node, const struct ExpandoRenderData *rdata, struct Buffer *buf, int max_cols, void *data, MuttFormatFlags flags)
Render a tree of ExpandoNodes into a string.
Definition: render.c:45
Render Expandos using Data.
uint8_t MuttFormatFlags
Flags for expando_render(), e.g. MUTT_FORMAT_FORCESUBJ.
Definition: render.h:32
String manipulation buffer.
Definition: buffer.h:36
Basic Expando Node.
Definition: node.h:67
int uid
Unique ID, e.g. ED_EMA_SIZE.
Definition: node.h:71
int(* render)(const struct ExpandoNode *node, const struct ExpandoRenderData *rdata, struct Buffer *buf, int max_cols, void *data, MuttFormatFlags flags)
Definition: node.h:94
void * ndata
Private node data.
Definition: node.h:80
const char * end
End of string data.
Definition: node.h:78
struct ExpandoNode * next
Linked list.
Definition: node.h:69
int did
Domain ID, e.g. ED_EMAIL.
Definition: node.h:70
enum ExpandoNodeType type
Type of Node, e.g. ENT_EXPANDO.
Definition: node.h:68
const char * start
Start of string data.
Definition: node.h:77
void(* ndata_free)(void **ptr)
Function to free the private node data.
Definition: node.h:81
struct ExpandoNodeArray children
Children nodes.
Definition: node.h:75
Buffer for parsing errors.
Definition: parse.h:34
char message[128]
Error message.
Definition: parse.h:35
const char * position
Position of error in original string.
Definition: parse.h:36
Private data for a Padding Node.
Definition: node_padding.h:64
enum ExpandoPadType pad_type
Padding type.
Definition: node_padding.h:65