NeoMutt  2025-12-11-1039-g550ac6
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
node_conddate.c
Go to the documentation of this file.
1
24
30
31#include "config.h"
32#include <limits.h>
33#include <stdio.h>
34#include <string.h>
35#include <time.h>
36#include "mutt/lib.h"
37#include "node_conddate.h"
38#include "helpers.h"
39#include "node.h"
40#include "parse.h"
41#include "render.h"
42
50{
52
53 priv->count = count;
54 priv->period = period;
55
56 return priv;
57}
58
64{
65 if (!ptr || !*ptr)
66 return;
67
68 FREE(ptr);
69}
70
79time_t cutoff_number(char period, int count)
80{
81 time_t t = mutt_date_now();
82 struct tm tm = { 0 };
83 localtime_r(&t, &tm);
84
85 switch (period)
86 {
87 case 'y':
88 tm.tm_year -= count;
89 break;
90
91 case 'm':
92 tm.tm_mon -= count;
93 break;
94
95 case 'w':
96 tm.tm_mday -= (7 * count);
97 break;
98
99 case 'd':
100 tm.tm_mday -= count;
101 break;
102
103 case 'H':
104 tm.tm_hour -= count;
105 break;
106
107 case 'M':
108 tm.tm_min -= count;
109 break;
110
111 default:
112 break;
113 }
114
115 return mktime(&tm);
116}
117
125time_t cutoff_this(char period)
126{
127 time_t t = mutt_date_now();
128 struct tm tm = { 0 };
129 localtime_r(&t, &tm);
130
131 switch (period)
132 {
133 case 'y':
134 tm.tm_mon = 0; // January
136
137 case 'm':
138 tm.tm_mday = 1; // 1st of the month
140
141 case 'd':
142 tm.tm_hour = 0; // Beginning of day (Midnight)
144
145 case 'H':
146 tm.tm_min = 0; // Beginning of hour
148
149 case 'M':
150 tm.tm_sec = 0; // Beginning of minute
151 break;
152
153 case 'w':
154 tm.tm_hour = 0; // Beginning of day (Midnight)
155 tm.tm_min = 0; // Beginning of hour
156 tm.tm_sec = 0; // Beginning of minute
157 int bow = 0; // Beginning of week
158 if (tm.tm_wday == 0)
159 bow = 6; // LCOV_EXCL_LINE
160 else
161 bow = tm.tm_wday - 1; // LCOV_EXCL_LINE
162 tm.tm_mday -= bow;
163 break;
164
165 default:
166 break;
167 }
168
169 return mktime(&tm);
170}
171
175int node_conddate_render(const struct ExpandoNode *node,
176 const struct ExpandoRenderCallback *erc, struct Buffer *buf,
177 int max_cols, void *data, MuttFormatFlags flags)
178{
179 ASSERT(node->type == ENT_CONDDATE);
180
181 const struct ExpandoRenderCallback *erc_match = find_get_number(erc, node->did, node->uid);
182 ASSERT(erc_match && "Unknown UID");
183
184 const long t_test = erc_match->get_number(node, data, flags);
185
186 const struct NodeCondDatePrivate *priv = node->ndata;
187
188 time_t t_cutoff;
189 if (priv->count == 0)
190 t_cutoff = cutoff_this(priv->period);
191 else
192 t_cutoff = cutoff_number(priv->period, priv->count);
193
194 return (t_test > t_cutoff); // bool-ify
195}
196
205struct ExpandoNode *node_conddate_new(int count, char period, int did, int uid)
206{
207 struct ExpandoNode *node = node_new();
208 node->type = ENT_CONDDATE;
209 node->did = did;
210 node->uid = uid;
212
213 node->ndata = node_conddate_private_new(count, period);
215
216 return node;
217}
218
227struct ExpandoNode *node_conddate_parse(const char *str, int did, int uid,
228 const char **parsed_until,
229 struct ExpandoParseError *err)
230{
231 if (!str || (str[0] == '\0') || !parsed_until || !err)
232 return NULL;
233
234 int count = 0;
235 char period = '\0';
236
237 str++;
238
239 if (mutt_isdigit(*str))
240 {
241 unsigned short number = 0;
242 const char *end_ptr = mutt_str_atous(str, &number);
243
244 // NOTE(g0mb4): str is NOT NUL-terminated
245 if (!end_ptr || (number == USHRT_MAX))
246 {
247 err->position = str;
248 snprintf(err->message, sizeof(err->message), _("Invalid number: %s"), str);
249 return NULL;
250 }
251
252 count = number;
253 str = end_ptr;
254 };
255
256 // Allowed periods: year, month, week, day, hour, minute
257 if (!strchr("ymwdHM", *str))
258 {
259 err->position = str;
260 snprintf(err->message, sizeof(err->message),
261 // L10N: The 'ymwdHM' should not be translated
262 _("Invalid time period: '%c', must be one of 'ymwdHM'"), *str);
263 return NULL;
264 }
265
266 period = *str;
267 *parsed_until = str + 1;
268
269 return node_conddate_new(count, period, did, uid);
270}
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
const struct ExpandoRenderCallback * find_get_number(const struct ExpandoRenderCallback *erc, int did, int uid)
Find a get_number() callback function.
Definition helpers.c:45
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)
Free memory and set the pointer to NULL.
Definition memory.h:68
#define MUTT_MEM_CALLOC(n, type)
Definition memory.h:52
time_t mutt_date_now(void)
Return the number of seconds since the Unix epoch.
Definition date.c:459
Convenience wrapper for the library headers.
#define FALLTHROUGH
Definition lib.h:117
#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.
time_t cutoff_number(char period, int count)
Calculate the cutoff time for n units.
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().
Expando Node for a Conditional Date.
Render Expandos using Data.
uint8_t MuttFormatFlags
Definition render.h:45
#define ASSERT(COND)
Definition signal2.h:59
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
Callback function to get a number.
Definition render.h:87
Private data for a Conditional Date -.
int count
Number of 'units' to count.
char period
Units, e.g. 'd' Day or 'm' Month.