NeoMutt  2024-10-02-24-gaf3843
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 if (pad_len != 0)
83 {
84 while (pad_cols <= max_cols)
85 {
86 buf_addstr_n(buf, node->start, 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->start = start;
208 node->end = end;
209
210 switch (pad_type)
211 {
212 case EPT_FILL_EOL:
214 break;
215 case EPT_HARD_FILL:
217 break;
218 case EPT_SOFT_FILL:
220 break;
221 };
222
223 node->ndata = node_padding_private_new(pad_type);
225
226 return node;
227}
228
235struct ExpandoNode *node_padding_parse(const char *str, int did, int uid,
236 ExpandoParserFlags flags, const char **parsed_until,
237 struct ExpandoParseError *err)
238{
239 if (flags & EP_CONDITIONAL)
240 {
241 snprintf(err->message, sizeof(err->message),
242 // L10N: Conditional Expandos can only depend on other Expandos
243 // e.g. "%<X?apple>" displays "apple" if "%X" is true.
244 _("Padding cannot be used as a condition"));
245 err->position = str;
246 return NULL;
247 }
248
249 enum ExpandoPadType pt = 0;
250 if (*str == '|')
251 {
252 pt = EPT_FILL_EOL;
253 }
254 else if (*str == '>')
255 {
256 pt = EPT_HARD_FILL;
257 }
258 else if (*str == '*')
259 {
260 pt = EPT_SOFT_FILL;
261 }
262 else
263 {
264 return NULL;
265 }
266 str++;
267
268 const size_t consumed = mutt_mb_charlen(str, NULL);
269
270 *parsed_until = str + consumed;
271 return node_padding_new(pt, str, str + consumed);
272}
273
278void node_padding_repad(struct ExpandoNode **parent)
279{
280 if (!parent || !*parent)
281 return;
282
283 struct ExpandoNode *node = *parent;
284 struct ExpandoNode *prev = NULL;
285 for (; node; prev = node, node = node->next)
286 {
287 if (node->type == ENT_PADDING)
288 {
289 if (node != *parent)
290 ARRAY_SET(&node->children, ENP_LEFT, *parent); // First sibling
291
292 ARRAY_SET(&node->children, ENP_RIGHT, node->next); // Sibling after Padding
293
294 if (prev)
295 prev->next = NULL;
296 node->next = NULL;
297 *parent = node;
298 return;
299 }
300
301 if (node->type == ENT_CONDITION)
302 {
303 struct ExpandoNode **ptr = NULL;
304
305 ptr = ARRAY_GET(&node->children, ENC_TRUE);
307
308 ptr = ARRAY_GET(&node->children, ENC_FALSE);
310 }
311 }
312}
#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
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:235
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
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:41
@ ENT_PADDING
Padding: soft, hard, EOL.
Definition: node.h:40
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:278
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: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:69
int uid
Unique ID, e.g. ED_EMA_SIZE.
Definition: node.h:73
int(* render)(const struct ExpandoNode *node, const struct ExpandoRenderData *rdata, struct Buffer *buf, int max_cols, void *data, MuttFormatFlags flags)
Definition: node.h:96
void * ndata
Private node data.
Definition: node.h:82
const char * end
End of string data.
Definition: node.h:80
struct ExpandoNode * next
Linked list.
Definition: node.h:71
int did
Domain ID, e.g. ED_EMAIL.
Definition: node.h:72
enum ExpandoNodeType type
Type of Node, e.g. ENT_EXPANDO.
Definition: node.h:70
const char * start
Start of string data.
Definition: node.h:79
void(* ndata_free)(void **ptr)
Function to free the private node data.
Definition: node.h:83
struct ExpandoNodeArray children
Children nodes.
Definition: node.h:77
Buffer for parsing errors.
Definition: parse.h:34
const char * position
Position of error in original string.
Definition: parse.h:36
char message[256]
Error message.
Definition: parse.h:35
Private data for a Padding Node -.
Definition: node_padding.h:64
enum ExpandoPadType pad_type
Padding type.
Definition: node_padding.h:65