NeoMutt  2025-12-11-911-gd8d604
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
functions.c
Go to the documentation of this file.
1
23
29
30#include "config.h"
31#include <stdbool.h>
32#include <stddef.h>
33#include "mutt/lib.h"
34#include "config/lib.h"
35#include "email/lib.h"
36#include "core/lib.h"
37#include "gui/lib.h"
38#include "mutt.h"
39#include "functions.h"
40#include "key/lib.h"
41#include "menu/lib.h"
42#include "pattern/lib.h"
43#include "module_data.h"
44
45// clang-format off
49static const struct MenuFuncOp OpPostponed[] = { /* map: postpone */
50 { "exit", OP_EXIT },
51 { "delete-entry", OP_DELETE },
52 { "undelete-entry", OP_UNDELETE },
53 { "tag-entry", OP_TAG },
54 { NULL, 0 },
55};
56
60static const struct MenuOpSeq PostponedDefaultBindings[] = { /* map: postpone */
61 { OP_DELETE, "d" },
62 { OP_EXIT, "q" },
63 { OP_TAG, "t" },
64 { OP_UNDELETE, "u" },
65 { 0, NULL },
66};
67// clang-format on
68
72void postponed_init_keys(struct NeoMutt *n, struct SubMenu *sm_generic)
73{
74 struct MenuDefinition *md = NULL;
75 struct SubMenu *sm = NULL;
76
78 md = km_register_menu(MENU_POSTPONE, "postpone");
79 km_menu_add_submenu(md, sm);
80 km_menu_add_submenu(md, sm_generic);
82
84 ASSERT(mod_data);
85 mod_data->menu_postpone = md;
86}
87
103static int postpone_add_selection(struct EmailArray *ea, struct Menu *menu,
104 struct Mailbox *m, bool tagged, int count)
105{
106 if (!ea || !menu || !m || !m->emails)
107 return 0;
108
109 if (tagged)
110 {
111 for (int i = 0; i < m->msg_count; i++)
112 {
113 struct Email *e = m->emails[i];
114 if (e && e->tagged)
115 ARRAY_ADD(ea, e);
116 }
117 }
118 else
119 {
120 const int index = menu_get_index(menu);
121 if ((index < 0) || (index >= m->msg_count))
122 return 0;
123
124 int n = (count > 1) ? count : 1;
125 if ((index + n) > m->msg_count)
126 n = m->msg_count - index;
127
128 for (int i = 0; i < n; i++)
129 {
130 struct Email *e = m->emails[index + i];
131 if (e)
132 ARRAY_ADD(ea, e);
133 }
134 }
135
136 return ARRAY_SIZE(ea);
137}
138
147static void postpone_apply_set_deleted(struct Mailbox *m, struct EmailArray *ea, bool deleted)
148{
149 if (!m || !ea)
150 return;
151
152 struct Email **ep = NULL;
153 ARRAY_FOREACH(ep, ea)
154 {
155 if (*ep)
156 mutt_set_flag(m, *ep, MUTT_DELETE, deleted, true);
157 }
158
160 if (mod_data)
161 mod_data->post_count = m->msg_count - m->msg_deleted;
162}
163
174static int op_delete(struct PostponeData *pd, const struct KeyEvent *event)
175{
176 struct Menu *menu = pd->menu;
177 struct MailboxView *mv = pd->mailbox_view;
178 struct Mailbox *m = mv->mailbox;
179
180 const int index = menu_get_index(menu);
181 const bool bf = (event->op == OP_DELETE);
182
183 /* should deleted draft messages be saved in the trash folder? */
184 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
185 postpone_add_selection(&ea, menu, m, menu->tag_prefix, event->count);
186 const int num = ARRAY_SIZE(&ea);
187 postpone_apply_set_deleted(m, &ea, bf);
188 ARRAY_FREE(&ea);
189
190 const bool c_resolve = cs_subset_bool(NeoMutt->sub, "resolve");
191 if (!menu->tag_prefix && c_resolve && ((index + num) < menu->max))
192 {
193 const int new_index = index + num;
194 menu_set_index(menu, new_index);
195 if (new_index >= (menu->top + menu->page_len))
196 {
197 menu->top = new_index;
199 }
200 }
201 else
202 {
203 menu_queue_redraw(menu, (menu->tag_prefix || (num > 1)) ? MENU_REDRAW_INDEX :
205 }
206
207 return FR_SUCCESS;
208}
209
213static int op_exit(struct PostponeData *pd, const struct KeyEvent *event)
214{
215 pd->done = true;
216 return FR_SUCCESS;
217}
218
222static int op_generic_select_entry(struct PostponeData *pd, const struct KeyEvent *event)
223{
224 int index = menu_get_index(pd->menu);
225 struct MailboxView *mv = pd->mailbox_view;
226 struct Mailbox *m = mv->mailbox;
227 pd->email = m->emails[index];
228 pd->done = true;
229 return FR_SUCCESS;
230}
231
241static int op_search(struct PostponeData *pd, const struct KeyEvent *event)
242{
243 SearchFlags flags = SEARCH_NONE;
244 switch (event->op)
245 {
246 case OP_SEARCH:
247 flags |= SEARCH_PROMPT;
248 pd->search_state->reverse = false;
249 break;
250 case OP_SEARCH_REVERSE:
251 flags |= SEARCH_PROMPT;
252 pd->search_state->reverse = true;
253 break;
254 case OP_SEARCH_NEXT:
255 break;
256 case OP_SEARCH_OPPOSITE:
257 flags |= SEARCH_OPPOSITE;
258 break;
259 }
260
261 int index = menu_get_index(pd->menu);
262 struct MailboxView *mv = pd->mailbox_view;
263 index = mutt_search_command(mv, pd->menu, index, pd->search_state, flags);
264 if (index != -1)
265 menu_set_index(pd->menu, index);
266
267 return FR_SUCCESS;
268}
269
270// -----------------------------------------------------------------------------
271
275static const struct PostponeFunction PostponeFunctions[] = {
276 // clang-format off
277 { OP_DELETE, op_delete },
278 { OP_EXIT, op_exit },
279 { OP_GENERIC_SELECT_ENTRY, op_generic_select_entry },
280 { OP_SEARCH, op_search },
281 { OP_SEARCH_NEXT, op_search },
282 { OP_SEARCH_OPPOSITE, op_search },
283 { OP_SEARCH_REVERSE, op_search },
284 { OP_UNDELETE, op_delete },
285 { 0, NULL },
286 // clang-format on
287};
288
292int postpone_function_dispatcher(struct MuttWindow *win, const struct KeyEvent *event)
293{
294 // The Dispatcher may be called on any Window in the Dialog
295 struct MuttWindow *dlg = dialog_find(win);
296 if (!event || !dlg || !dlg->wdata)
297 {
299 return FR_ERROR;
300 }
301
302 const int op = event->op;
303 struct Menu *menu = dlg->wdata;
304 struct PostponeData *pd = menu->mdata;
305 if (!pd)
306 {
308 return FR_ERROR;
309 }
310
311 int rc = FR_UNKNOWN;
312 for (size_t i = 0; PostponeFunctions[i].op != OP_NULL; i++)
313 {
314 const struct PostponeFunction *fn = &PostponeFunctions[i];
315 if (fn->op == op)
316 {
317 rc = fn->function(pd, event);
318 break;
319 }
320 }
321
322 if (rc == FR_UNKNOWN) // Not our function
323 return rc;
324
325 const char *result = dispatcher_get_retval_name(rc);
326 mutt_debug(LL_DEBUG1, "Handled %s (%d) -> %s\n", opcodes_get_name(op), op, NONULL(result));
327
329 return rc;
330}
331
338{
339 if (!dlg)
340 return NULL;
341
342 struct Menu *menu = dlg->wdata;
343 struct PostponeData *pd = menu->mdata;
344 if (!pd)
345 return NULL;
346
347 return pd->mailbox_view;
348}
#define ARRAY_ADD(head, elem)
Add an element at the end of the array.
Definition array.h:157
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:223
#define ARRAY_SIZE(head)
The number of elements stored.
Definition array.h:87
#define ARRAY_FREE(head)
Release all memory.
Definition array.h:209
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition array.h:58
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
struct MuttWindow * dialog_find(struct MuttWindow *win)
Find the parent Dialog of a Window.
Definition dialog.c:89
const char * dispatcher_get_retval_name(int rv)
Get the name of a return value.
Definition dispatcher.c:55
void dispatcher_flush_on_error(int rv)
Flush pending keys after a dispatch error.
Definition dispatcher.c:65
@ FR_SUCCESS
Valid function - successfully performed.
Definition dispatcher.h:40
@ FR_UNKNOWN
Unknown function.
Definition dispatcher.h:34
@ FR_ERROR
Valid function - error occurred.
Definition dispatcher.h:39
Structs that make up an email.
void mutt_set_flag(struct Mailbox *m, struct Email *e, enum MessageType flag, bool bf, bool upd_mbox)
Set a flag on an email.
Definition flags.c:54
static int op_exit(struct AliasFunctionData *fdata, const struct KeyEvent *event)
exit this menu - Implements alias_function_t -
Definition functions.c:312
static int op_delete(struct AliasFunctionData *fdata, const struct KeyEvent *event)
delete the current entry - Implements alias_function_t -
Definition functions.c:274
static int op_search(struct AliasFunctionData *fdata, const struct KeyEvent *event)
search for a regular expression - Implements alias_function_t -
Definition functions.c:523
static int op_generic_select_entry(struct AliasFunctionData *fdata, const struct KeyEvent *event)
select the current entry - Implements alias_function_t -
Definition functions.c:392
int postpone_function_dispatcher(struct MuttWindow *win, const struct KeyEvent *event)
Perform a Postpone function - Implements function_dispatcher_t -.
Definition functions.c:292
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
Convenience wrapper for the gui headers.
void km_menu_add_submenu(struct MenuDefinition *md, struct SubMenu *sm)
Add a SubMenu to a Menu Definition.
Definition init.c:121
struct SubMenu * km_register_submenu(const struct MenuFuncOp functions[])
Register a submenu.
Definition init.c:87
struct MenuDefinition * km_register_menu(int menu, const char *name)
Register a menu.
Definition init.c:104
void km_menu_add_bindings(struct MenuDefinition *md, const struct MenuOpSeq bindings[])
Add Keybindings to a Menu.
Definition init.c:134
Manage keymappings.
@ LL_DEBUG1
Log at debug level 1.
Definition logging2.h:45
GUI present the user with a selectable list.
void menu_queue_redraw(struct Menu *menu, MenuRedrawFlags redraw)
Queue a request for a redraw.
Definition menu.c:179
int menu_get_index(struct Menu *menu)
Get the current selection in the Menu.
Definition menu.c:155
@ MENU_REDRAW_INDEX
Redraw the index.
Definition lib.h:61
@ MENU_REDRAW_CURRENT
Redraw the current line of the menu.
Definition lib.h:63
MenuRedrawFlags menu_set_index(struct Menu *menu, int index)
Set the current selection in the Menu.
Definition menu.c:169
@ MODULE_ID_POSTPONE
ModulePostpone, Postponed Emails
Definition module_api.h:87
Convenience wrapper for the library headers.
Many unsorted constants and some structs.
@ MUTT_DELETE
Messages to be deleted.
Definition mutt.h:94
void * neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
Get the private data for a Module.
Definition neomutt.c:663
const char * opcodes_get_name(int op)
Get the name of an opcode.
Definition opcodes.c:48
Match patterns to emails.
int mutt_search_command(struct MailboxView *mv, struct Menu *menu, int cur, struct SearchState *state, SearchFlags flags)
Perform a search.
Definition pattern.c:462
static const struct MenuFuncOp OpPostponed[]
Functions for the Postpone Menu.
Definition functions.c:49
static const struct MenuOpSeq PostponedDefaultBindings[]
Key bindings for the Postpone Menu.
Definition functions.c:60
struct MailboxView * postponed_get_mailbox_view(struct MuttWindow *dlg)
Extract the Mailbox from the Postponed Dialog.
Definition functions.c:337
static void postpone_apply_set_deleted(struct Mailbox *m, struct EmailArray *ea, bool deleted)
Apply the deleted flag to a working set of Emails.
Definition functions.c:147
static int postpone_add_selection(struct EmailArray *ea, struct Menu *menu, struct Mailbox *m, bool tagged, int count)
Build a working set of Emails for an action.
Definition functions.c:103
static const struct PostponeFunction PostponeFunctions[]
All the NeoMutt functions that the Postpone supports.
Definition functions.c:275
void postponed_init_keys(struct NeoMutt *n, struct SubMenu *sm_generic)
Initialise the Postponed Keybindings - Implements ::init_keys_api.
Definition functions.c:72
Postponed Email Functions.
Postpone private Module data.
uint8_t SearchFlags
@ SEARCH_NONE
No flags are set.
@ SEARCH_PROMPT
Ask for search input.
@ SEARCH_OPPOSITE
Search in the opposite direction.
#define ASSERT(COND)
Definition signal2.h:59
#define NONULL(x)
Definition string2.h:44
The envelope/body of an email.
Definition email.h:39
bool deleted
Email is deleted.
Definition email.h:78
int index
The absolute (unsorted) message number.
Definition email.h:110
bool tagged
Email is tagged.
Definition email.h:107
An event such as a keypress.
Definition get.h:75
int count
Optional count prefix, e.g. 3 for 3j
Definition get.h:78
int op
Function opcode, e.g. OP_HELP.
Definition get.h:77
View of a Mailbox.
Definition mview.h:40
struct Mailbox * mailbox
Current Mailbox.
Definition mview.h:51
A mailbox.
Definition mailbox.h:81
int msg_count
Total number of messages.
Definition mailbox.h:90
struct Email ** emails
Array of Emails.
Definition mailbox.h:98
int msg_deleted
Number of deleted messages.
Definition mailbox.h:95
Functions for a Dialog or Window.
Definition menu.h:77
Mapping between a function and an operation.
Definition menu.h:35
Mapping between an operation and a key sequence.
Definition menu.h:45
Definition lib.h:86
int top
Entry that is the top of the current page.
Definition lib.h:98
void * mdata
Private data.
Definition lib.h:155
bool tag_prefix
User has pressed <tag-prefix>
Definition lib.h:92
int max
Number of entries in the menu.
Definition lib.h:88
int page_len
Number of entries per screen.
Definition lib.h:91
void * wdata
Private data.
Container for Accounts, Notifications.
Definition neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
Data to pass to the Postpone Functions.
Definition functions.h:35
struct Email * email
Selected Email.
Definition functions.h:38
struct SearchState * search_state
State of the current search.
Definition functions.h:40
bool done
Should we close the Dialog?
Definition functions.h:39
struct MailboxView * mailbox_view
Postponed Mailbox view.
Definition functions.h:36
struct Menu * menu
Postponed Menu.
Definition functions.h:37
A NeoMutt function.
Definition functions.h:62
postpone_function_t function
Function to call.
Definition functions.h:64
int op
Op code, e.g. OP_DELETE.
Definition functions.h:63
Postpone private Module data.
Definition module_data.h:32
struct MenuDefinition * menu_postpone
Postpone menu definition.
Definition module_data.h:34
short post_count
Number of postponed (draft) emails.
Definition module_data.h:35
bool reverse
search backwards
Collection of related functions.
Definition menu.h:65
@ MENU_POSTPONE
Select a postponed email.
Definition type.h:48