NeoMutt  2024-10-02-37-gfa9146
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_container.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 = mutt_str_len(node->text);
79 const int pad_cols = mutt_strnwidth(node->text, pad_len);
80 int total_cols = 0;
81
82 if (pad_len != 0)
83 {
84 while (pad_cols <= max_cols)
85 {
86 buf_addstr_n(buf, node->text, pad_len);
87
88 max_cols -= pad_cols;
89 total_cols += pad_cols;
90 }
91 }
92
93 if (max_cols > 0)
94 {
95 buf_add_printf(buf, "%*s", max_cols, "");
96 total_cols += max_cols;
97 }
98
99 return total_cols;
100}
101
106 const struct ExpandoRenderData *rdata, struct Buffer *buf,
107 int max_cols, void *data, MuttFormatFlags flags)
108{
109 struct ExpandoNode *left = node_get_child(node, ENP_LEFT);
110
111 int total_cols = node_render(left, rdata, buf, max_cols, data, flags);
112
113 total_cols += pad_string(node, buf, max_cols - total_cols);
114
115 return total_cols;
116}
117
125 const struct ExpandoRenderData *rdata, struct Buffer *buf,
126 int max_cols, void *data, MuttFormatFlags flags)
127{
128 struct Buffer *buf_left = buf_pool_get();
129 struct Buffer *buf_pad = buf_pool_get();
130 struct Buffer *buf_right = buf_pool_get();
131
132 int cols_used = 0;
133
134 struct ExpandoNode *left = node_get_child(node, ENP_LEFT);
135 if (left)
136 cols_used += node_render(left, rdata, buf_left, max_cols - cols_used, data, flags);
137
138 struct ExpandoNode *right = node_get_child(node, ENP_RIGHT);
139 if (right)
140 cols_used += node_render(right, rdata, buf_right, max_cols - cols_used, data, flags);
141
142 if (max_cols > cols_used)
143 cols_used += pad_string(node, buf_pad, max_cols - cols_used);
144
145 buf_addstr(buf, buf_string(buf_left));
146 buf_addstr(buf, buf_string(buf_pad));
147 buf_addstr(buf, buf_string(buf_right));
148
149 buf_pool_release(&buf_left);
150 buf_pool_release(&buf_pad);
151 buf_pool_release(&buf_right);
152
153 return cols_used;
154}
155
163 const struct ExpandoRenderData *rdata, struct Buffer *buf,
164 int max_cols, void *data, MuttFormatFlags flags)
165{
166 struct Buffer *buf_left = buf_pool_get();
167 struct Buffer *buf_pad = buf_pool_get();
168 struct Buffer *buf_right = buf_pool_get();
169
170 int cols_used = 0;
171
172 struct ExpandoNode *right = node_get_child(node, ENP_RIGHT);
173 if (right)
174 cols_used += node_render(right, rdata, buf_right, max_cols - cols_used, data, flags);
175
176 struct ExpandoNode *left = node_get_child(node, ENP_LEFT);
177 if (left)
178 cols_used += node_render(left, rdata, buf_left, max_cols - cols_used, data, flags);
179
180 if (max_cols > cols_used)
181 cols_used += pad_string(node, buf_pad, max_cols - cols_used);
182
183 buf_addstr(buf, buf_string(buf_left));
184 buf_addstr(buf, buf_string(buf_pad));
185 buf_addstr(buf, buf_string(buf_right));
186
187 buf_pool_release(&buf_left);
188 buf_pool_release(&buf_pad);
189 buf_pool_release(&buf_right);
190
191 return cols_used;
192}
193
202 const char *start, const char *end)
203{
204 struct ExpandoNode *node = node_new();
205
206 node->type = ENT_PADDING;
207 node->text = mutt_strn_dup(start, end - start);
208
209 switch (pad_type)
210 {
211 case EPT_FILL_EOL:
213 break;
214 case EPT_HARD_FILL:
216 break;
217 case EPT_SOFT_FILL:
219 break;
220 };
221
222 node->ndata = node_padding_private_new(pad_type);
224
225 return node;
226}
227
234struct ExpandoNode *node_padding_parse(const char *str, int did, int uid,
235 ExpandoParserFlags flags, const char **parsed_until,
236 struct ExpandoParseError *err)
237{
238 if (flags & EP_CONDITIONAL)
239 {
240 snprintf(err->message, sizeof(err->message),
241 // L10N: Conditional Expandos can only depend on other Expandos
242 // e.g. "%<X?apple>" displays "apple" if "%X" is true.
243 _("Padding cannot be used as a condition"));
244 err->position = str;
245 return NULL;
246 }
247
248 enum ExpandoPadType pt = 0;
249 if (*str == '|')
250 {
251 pt = EPT_FILL_EOL;
252 }
253 else if (*str == '>')
254 {
255 pt = EPT_HARD_FILL;
256 }
257 else if (*str == '*')
258 {
259 pt = EPT_SOFT_FILL;
260 }
261 else
262 {
263 return NULL;
264 }
265 str++;
266
267 size_t consumed = mutt_mb_charlen(str, NULL);
268 if (consumed == 0)
269 {
270 str = " "; // Default to a space
271 consumed = 1;
272 }
273
274 *parsed_until = str + consumed;
275 return node_padding_new(pt, str, str + consumed);
276}
277
283{
284 if (!ptr || !*ptr)
285 return;
286
287 struct ExpandoNode *parent = *ptr;
288 struct ExpandoNode **np = NULL;
289 ARRAY_FOREACH(np, &parent->children)
290 {
291 if (!np || !*np)
292 continue;
293
294 // Repad any children, recursively
296
297 struct ExpandoNode *node = *np;
298 if (node->type != ENT_PADDING)
299 continue;
300
301 struct ExpandoNode *node_left = node_container_new();
302 struct ExpandoNode *node_right = node_container_new();
303
304 if (ARRAY_FOREACH_IDX > 0)
305 {
306 for (int i = 0; i < ARRAY_FOREACH_IDX; i++)
307 {
308 node_add_child(node_left, node_get_child(parent, i));
309 }
310 }
311
312 size_t count = ARRAY_SIZE(&parent->children);
313 if ((ARRAY_FOREACH_IDX + 1) < count)
314 {
315 for (int i = ARRAY_FOREACH_IDX + 1; i < count; i++)
316 {
317 node_add_child(node_right, node_get_child(parent, i));
318 }
319 }
320
321 // All the children have been transferred
322 ARRAY_FREE(&parent->children);
323
324 node_add_child(node, node_left);
325 node_add_child(node, node_right);
326
327 node_add_child(parent, node);
328
329 break; // Only repad the first padding node
330 }
331}
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:212
#define ARRAY_SIZE(head)
The number of elements stored.
Definition: array.h:87
#define ARRAY_FREE(head)
Release all memory.
Definition: array.h:204
int buf_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition: buffer.c:204
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:96
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:226
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, int did, int uid, ExpandoParserFlags flags, const char **parsed_until, struct ExpandoParseError *err)
Parse a Padding Expando - Implements ExpandoDefinition::parse() -.
Definition: node_padding.c:234
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:124
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:162
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:105
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:51
#define FREE(x)
Definition: memory.h:45
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition: string.c:380
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:496
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:91
void node_add_child(struct ExpandoNode *node, struct ExpandoNode *child)
Add a child to an ExpandoNode.
Definition: node.c:76
Basic Expando Node.
@ ENT_PADDING
Padding: soft, hard, EOL.
Definition: node.h:40
struct ExpandoNode * node_container_new(void)
Create a new Container ExpandoNode.
Expando Node for a Container.
void node_padding_private_free(void **ptr)
Free Padding private data - Implements ExpandoNode::ndata_free()
Definition: node_padding.c:60
void node_padding_repad(struct ExpandoNode **ptr)
Rearrange Padding in a tree of ExpandoNodes.
Definition: node_padding.c:282
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:201
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_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:70
int(* render)(const struct ExpandoNode *node, const struct ExpandoRenderData *rdata, struct Buffer *buf, int max_cols, void *data, MuttFormatFlags flags)
Definition: node.h:91
void * ndata
Private node data.
Definition: node.h:77
int did
Domain ID, e.g. ED_EMAIL.
Definition: node.h:69
const char * text
Node-specific text.
Definition: node.h:73
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
struct ExpandoNodeArray children
Children nodes.
Definition: node.h:75
Buffer for parsing errors.
Definition: parse.h:35
const char * position
Position of error in original string.
Definition: parse.h:37
char message[256]
Error message.
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