NeoMutt  2024-11-14-34-g5aaf0d
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 <ctype.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
112 return mktime(&tm);
113}
114
122time_t cutoff_this(char period)
123{
124 time_t t = mutt_date_now();
125 struct tm tm = { 0 };
126 localtime_r(&t, &tm);
127
128 switch (period)
129 {
130 case 'y':
131 tm.tm_mon = 0; // January
133
134 case 'm':
135 tm.tm_mday = 1; // 1st of the month
137
138 case 'd':
139 tm.tm_hour = 0; // Beginning of day (Midnight)
141
142 case 'H':
143 tm.tm_min = 0; // Beginning of hour
145
146 case 'M':
147 tm.tm_sec = 0; // Beginning of minute
148 break;
149
150 case 'w':
151 tm.tm_hour = 0; // Beginning of day (Midnight)
152 tm.tm_min = 0; // Beginning of hour
153 tm.tm_sec = 0; // Beginning of minute
154 int bow = 0; // Beginning of week
155 if (tm.tm_wday == 0)
156 bow = 6; // LCOV_EXCL_LINE
157 else
158 bow = tm.tm_wday - 1; // LCOV_EXCL_LINE
159 tm.tm_mday -= bow;
160 break;
161 }
162
163 return mktime(&tm);
164}
165
169int node_conddate_render(const struct ExpandoNode *node,
170 const struct ExpandoRenderData *rdata, struct Buffer *buf,
171 int max_cols, void *data, MuttFormatFlags flags)
172{
173 ASSERT(node->type == ENT_CONDDATE);
174
175 const struct ExpandoRenderData *rd_match = find_get_number(rdata, node->did, node->uid);
176 ASSERT(rd_match && "Unknown UID");
177
178 const long t_test = rd_match->get_number(node, data, flags);
179
180 const struct NodeCondDatePrivate *priv = node->ndata;
181
182 time_t t_cutoff;
183 if (priv->count == 0)
184 t_cutoff = cutoff_this(priv->period);
185 else
186 t_cutoff = cutoff_number(priv->period, priv->count);
187
188 return (t_test > t_cutoff); // bool-ify
189}
190
199struct ExpandoNode *node_conddate_new(int count, char period, int did, int uid)
200{
201 struct ExpandoNode *node = node_new();
202 node->type = ENT_CONDDATE;
203 node->did = did;
204 node->uid = uid;
206
207 node->ndata = node_conddate_private_new(count, period);
209
210 return node;
211}
212
221struct ExpandoNode *node_conddate_parse(const char *str, int did, int uid,
222 const char **parsed_until,
223 struct ExpandoParseError *err)
224{
225 if (!str || (str[0] == '\0') || !parsed_until || !err)
226 return NULL;
227
228 int count = 0;
229 char period = '\0';
230
231 str++;
232
233 if (isdigit(*str))
234 {
235 unsigned short number = 0;
236 const char *end_ptr = mutt_str_atous(str, &number);
237
238 // NOTE(g0mb4): str is NOT null-terminated
239 if (!end_ptr || (number == USHRT_MAX))
240 {
241 err->position = str;
242 snprintf(err->message, sizeof(err->message), _("Invalid number: %s"), str);
243 return NULL;
244 }
245
246 count = number;
247 str = end_ptr;
248 };
249
250 // Allowed periods: year, month, week, day, hour, minute
251 if (!strchr("ymwdHM", *str))
252 {
253 err->position = str;
254 snprintf(err->message, sizeof(err->message),
255 // L10N: The 'ymwdHM' should not be translated
256 _("Invalid time period: '%c', must be one of 'ymwdHM'"), *str);
257 return NULL;
258 }
259
260 period = *str;
261 *parsed_until = str + 1;
262
263 return node_conddate_new(count, period, did, uid);
264}
const char * mutt_str_atous(const char *str, unsigned short *dst)
Convert ASCII string to an unsigned short.
Definition: atoi.c:270
const struct ExpandoRenderData * find_get_number(const struct ExpandoRenderData *rdata, 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 ExpandoRenderData *rdata, struct Buffer *buf, int max_cols, void *data, MuttFormatFlags flags)
Render a CondDate Node - Implements ExpandoNode::render() -.
#define FREE(x)
Definition: memory.h:55
#define MUTT_MEM_CALLOC(n, type)
Definition: memory.h:40
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:111
#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:49
time_t cutoff_number(char period, int count)
Calculate the cutoff time for n units.
Definition: node_conddate.c:79
time_t cutoff_this(char period)
Calculcate 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:63
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:58
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
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
long(* get_number)(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
Definition: render.h:78
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