NeoMutt  2024-10-02-37-gfa9146
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{
51 struct NodeCondDatePrivate *priv = mutt_mem_calloc(1, sizeof(struct NodeCondDatePrivate));
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_mday = 1;
152 break;
153 }
154
155 return mktime(&tm);
156}
157
161int node_conddate_render(const struct ExpandoNode *node,
162 const struct ExpandoRenderData *rdata, struct Buffer *buf,
163 int max_cols, void *data, MuttFormatFlags flags)
164{
165 ASSERT(node->type == ENT_CONDDATE);
166
167 const struct ExpandoRenderData *rd_match = find_get_number(rdata, node->did, node->uid);
168 ASSERT(rd_match && "Unknown UID");
169
170 const long t_test = rd_match->get_number(node, data, flags);
171
172 const struct NodeCondDatePrivate *priv = node->ndata;
173
174 time_t t_cutoff;
175 if (priv->count == 0)
176 t_cutoff = cutoff_this(priv->period);
177 else
178 t_cutoff = cutoff_number(priv->period, priv->count);
179
180 return (t_test > t_cutoff); // bool-ify
181}
182
191struct ExpandoNode *node_conddate_new(int count, char period, int did, int uid)
192{
193 struct ExpandoNode *node = node_new();
194 node->type = ENT_CONDDATE;
195 node->did = did;
196 node->uid = uid;
198
199 node->ndata = node_conddate_private_new(count, period);
201
202 return node;
203}
204
208struct ExpandoNode *node_conddate_parse(const char *str, int did, int uid,
209 const char **parsed_until,
210 struct ExpandoParseError *err)
211{
212 int count = 0;
213 char period = '\0';
214
215 if (isdigit(*str))
216 {
217 unsigned short number = 0;
218 const char *end_ptr = mutt_str_atous(str, &number);
219
220 // NOTE(g0mb4): str is NOT null-terminated
221 if (!end_ptr || (number == USHRT_MAX))
222 {
223 err->position = str;
224 snprintf(err->message, sizeof(err->message), _("Invalid number: %s"), str);
225 return NULL;
226 }
227
228 count = number;
229 str = end_ptr;
230 };
231
232 // Allowed periods: year, month, week, day, hour, minute
233 if (!strchr("ymwdHM", *str))
234 {
235 err->position = str;
236 snprintf(err->message, sizeof(err->message),
237 // L10N: The 'ymwdHM' should not be translated
238 _("Invalid time period: '%c', must be one of 'ymwdHM'"), *str);
239 return NULL;
240 }
241
242 period = *str;
243 *parsed_until = str + 1;
244
245 return node_conddate_new(count, period, did, uid);
246}
const char * mutt_str_atous(const char *str, unsigned short *dst)
Convert ASCII string to an unsigned short.
Definition: atoi.c:266
const struct ExpandoRenderData * find_get_number(const struct ExpandoRenderData *rdata, int did, int uid)
Find a get_number() callback function.
Definition: helpers.c:47
Shared code.
Expando Parsing.
struct ExpandoNode * node_conddate_parse(const char *str, int did, int uid, const char **parsed_until, struct ExpandoParseError *err)
Parse a CondDate format string - Implements ExpandoDefinition::parse() -.
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() -.
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
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 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:35
const char * position
Position of error in original string.
Definition: parse.h:37
char message[256]
Error message.
Definition: parse.h:36
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