NeoMutt  2025-09-05-2-g4bf191
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
node_conddate.c
Go to the documentation of this file.
1
30#include "config.h"
31#include <limits.h>
32#include <stdio.h>
33#include <string.h>
34#include <time.h>
35#include "mutt/lib.h"
36#include "node_conddate.h"
37#include "helpers.h"
38#include "node.h"
39#include "parse.h"
40#include "render.h"
41
49{
51
52 priv->count = count;
53 priv->period = period;
54
55 return priv;
56}
57
63{
64 if (!ptr || !*ptr)
65 return;
66
67 FREE(ptr);
68}
69
78time_t cutoff_number(char period, int count)
79{
80 time_t t = mutt_date_now();
81 struct tm tm = { 0 };
82 localtime_r(&t, &tm);
83
84 switch (period)
85 {
86 case 'y':
87 tm.tm_year -= count;
88 break;
89
90 case 'm':
91 tm.tm_mon -= count;
92 break;
93
94 case 'w':
95 tm.tm_mday -= (7 * count);
96 break;
97
98 case 'd':
99 tm.tm_mday -= count;
100 break;
101
102 case 'H':
103 tm.tm_hour -= count;
104 break;
105
106 case 'M':
107 tm.tm_min -= count;
108 break;
109 }
110
111 return mktime(&tm);
112}
113
121time_t cutoff_this(char period)
122{
123 time_t t = mutt_date_now();
124 struct tm tm = { 0 };
125 localtime_r(&t, &tm);
126
127 switch (period)
128 {
129 case 'y':
130 tm.tm_mon = 0; // January
132
133 case 'm':
134 tm.tm_mday = 1; // 1st of the month
136
137 case 'd':
138 tm.tm_hour = 0; // Beginning of day (Midnight)
140
141 case 'H':
142 tm.tm_min = 0; // Beginning of hour
144
145 case 'M':
146 tm.tm_sec = 0; // Beginning of minute
147 break;
148
149 case 'w':
150 tm.tm_hour = 0; // Beginning of day (Midnight)
151 tm.tm_min = 0; // Beginning of hour
152 tm.tm_sec = 0; // Beginning of minute
153 int bow = 0; // Beginning of week
154 if (tm.tm_wday == 0)
155 bow = 6; // LCOV_EXCL_LINE
156 else
157 bow = tm.tm_wday - 1; // LCOV_EXCL_LINE
158 tm.tm_mday -= bow;
159 break;
160 }
161
162 return mktime(&tm);
163}
164
168int node_conddate_render(const struct ExpandoNode *node,
169 const struct ExpandoRenderCallback *erc, struct Buffer *buf,
170 int max_cols, void *data, MuttFormatFlags flags)
171{
172 ASSERT(node->type == ENT_CONDDATE);
173
174 const struct ExpandoRenderCallback *erc_match = find_get_number(erc, node->did, node->uid);
175 ASSERT(erc_match && "Unknown UID");
176
177 const long t_test = erc_match->get_number(node, data, flags);
178
179 const struct NodeCondDatePrivate *priv = node->ndata;
180
181 time_t t_cutoff;
182 if (priv->count == 0)
183 t_cutoff = cutoff_this(priv->period);
184 else
185 t_cutoff = cutoff_number(priv->period, priv->count);
186
187 return (t_test > t_cutoff); // bool-ify
188}
189
198struct ExpandoNode *node_conddate_new(int count, char period, int did, int uid)
199{
200 struct ExpandoNode *node = node_new();
201 node->type = ENT_CONDDATE;
202 node->did = did;
203 node->uid = uid;
205
206 node->ndata = node_conddate_private_new(count, period);
208
209 return node;
210}
211
220struct ExpandoNode *node_conddate_parse(const char *str, int did, int uid,
221 const char **parsed_until,
222 struct ExpandoParseError *err)
223{
224 if (!str || (str[0] == '\0') || !parsed_until || !err)
225 return NULL;
226
227 int count = 0;
228 char period = '\0';
229
230 str++;
231
232 if (mutt_isdigit(*str))
233 {
234 unsigned short number = 0;
235 const char *end_ptr = mutt_str_atous(str, &number);
236
237 // NOTE(g0mb4): str is NOT NUL-terminated
238 if (!end_ptr || (number == USHRT_MAX))
239 {
240 err->position = str;
241 snprintf(err->message, sizeof(err->message), _("Invalid number: %s"), str);
242 return NULL;
243 }
244
245 count = number;
246 str = end_ptr;
247 };
248
249 // Allowed periods: year, month, week, day, hour, minute
250 if (!strchr("ymwdHM", *str))
251 {
252 err->position = str;
253 snprintf(err->message, sizeof(err->message),
254 // L10N: The 'ymwdHM' should not be translated
255 _("Invalid time period: '%c', must be one of 'ymwdHM'"), *str);
256 return NULL;
257 }
258
259 period = *str;
260 *parsed_until = str + 1;
261
262 return node_conddate_new(count, period, did, uid);
263}
const char * mutt_str_atous(const char *str, unsigned short *dst)
Convert ASCII string to an unsigned short.
Definition: atoi.c:270
bool mutt_isdigit(int arg)
Wrapper for isdigit(3)
Definition: ctype.c:65
const struct ExpandoRenderCallback * find_get_number(const struct ExpandoRenderCallback *erc, int did, int uid)
Find a get_number() callback function.
Definition: helpers.c:44
Shared code.
Expando Parsing.
int node_conddate_render(const struct ExpandoNode *node, const struct ExpandoRenderCallback *erc, struct Buffer *buf, int max_cols, void *data, MuttFormatFlags flags)
Render a CondDate Node - Implements ExpandoNode::render() -.
#define FREE(x)
Definition: memory.h:62
#define MUTT_MEM_CALLOC(n, type)
Definition: memory.h:47
time_t mutt_date_now(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:456
Convenience wrapper for the library headers.
#define FALLTHROUGH
Definition: lib.h:113
#define _(a)
Definition: message.h:28
struct ExpandoNode * node_new(void)
Create a new empty ExpandoNode.
Definition: node.c:39
Basic Expando Node.
@ ENT_CONDDATE
True/False date condition.
Definition: node.h:43
struct ExpandoNode * node_conddate_new(int count, char period, int did, int uid)
Create a new CondDate ExpandoNode.
struct ExpandoNode * node_conddate_parse(const char *str, int did, int uid, const char **parsed_until, struct ExpandoParseError *err)
Parse a CondDate format string.
struct NodeCondDatePrivate * node_conddate_private_new(int count, char period)
Create new CondDate private data.
Definition: node_conddate.c:48
time_t cutoff_number(char period, int count)
Calculate the cutoff time for n units.
Definition: node_conddate.c:78
time_t cutoff_this(char period)
Calculate the cutoff time of this unit.
void node_conddate_private_free(void **ptr)
Free CondDate private data - Implements ExpandoNode::ndata_free()
Definition: node_conddate.c:62
Expando Node for a Conditional Date.
Render Expandos using Data.
uint8_t MuttFormatFlags
Flags for expando_render(), e.g. MUTT_FORMAT_FORCESUBJ.
Definition: render.h:32
#define ASSERT(COND)
Definition: signal2.h:60
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
void * ndata
Private node data.
Definition: node.h:77
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
Buffer for parsing errors.
Definition: parse.h:37
char message[1024]
Error message.
Definition: parse.h:38
const char * position
Position of error in original string.
Definition: parse.h:39
get_number_t get_number
Definition: render.h:81
Private data for a Conditional Date -.
Definition: node_conddate.h:33
int count
Number of 'units' to count.
Definition: node_conddate.h:34
char period
Units, e.g. 'd' Day or 'm' Month.
Definition: node_conddate.h:35