NeoMutt
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
functions.c
Go to the documentation of this file.
1
29#include "config.h"
30#include <stddef.h>
31#include <stdbool.h>
32#include <stdint.h>
33#include "mutt/lib.h"
34#include "config/lib.h"
35#include "core/lib.h"
36#include "gui/lib.h"
37#include "mutt.h"
38#include "functions.h"
39#include "lib.h"
40#include "editor/lib.h"
41#include "history/lib.h"
42#include "protos.h"
43#include "type.h"
44
45extern char *SearchBuffers[];
46
47#define MUTT_SEARCH_UP 1
48#define MUTT_SEARCH_DOWN 2
49
57static int search(struct Menu *menu, int op)
58{
59 int rc = -1;
60 int wrap = 0;
61 int search_dir;
62 regex_t re = { 0 };
63 struct Buffer *buf = buf_pool_get();
64
65 char *search_buf = ((menu->type < MENU_MAX)) ? SearchBuffers[menu->type] : NULL;
66
67 if (!(search_buf && *search_buf) || ((op != OP_SEARCH_NEXT) && (op != OP_SEARCH_OPPOSITE)))
68 {
69 buf_strcpy(buf, search_buf && (search_buf[0] != '\0') ? search_buf : "");
70 if ((mw_get_field(((op == OP_SEARCH) || (op == OP_SEARCH_NEXT)) ? _("Search for: ") : _("Reverse search for: "),
71 buf, MUTT_COMP_CLEAR, HC_OTHER, NULL, NULL) != 0) ||
72 buf_is_empty(buf))
73 {
74 goto done;
75 }
76 if (menu->type < MENU_MAX)
77 {
79 search_buf = SearchBuffers[menu->type];
80 }
81 menu->search_dir = ((op == OP_SEARCH) || (op == OP_SEARCH_NEXT)) ?
84 }
85
86 search_dir = (menu->search_dir == MUTT_SEARCH_UP) ? -1 : 1;
87 if (op == OP_SEARCH_OPPOSITE)
88 search_dir = -search_dir;
89
90 if (search_buf)
91 {
92 uint16_t flags = mutt_mb_is_lower(search_buf) ? REG_ICASE : 0;
93 rc = REG_COMP(&re, search_buf, REG_NOSUB | flags);
94 }
95
96 if (rc != 0)
97 {
98 regerror(rc, &re, buf->data, buf->dsize);
99 mutt_error("%s", buf_string(buf));
100 rc = -1;
101 goto done;
102 }
103
104 rc = menu->current + search_dir;
105search_next:
106 if (wrap)
107 mutt_message(_("Search wrapped to top"));
108 while ((rc >= 0) && (rc < menu->max))
109 {
110 if (menu->search(menu, &re, rc) == 0)
111 {
112 regfree(&re);
113 goto done;
114 }
115
116 rc += search_dir;
117 }
118
119 const bool c_wrap_search = cs_subset_bool(menu->sub, "wrap_search");
120 if (c_wrap_search && (wrap++ == 0))
121 {
122 rc = (search_dir == 1) ? 0 : menu->max - 1;
123 goto search_next;
124 }
125 regfree(&re);
126 mutt_error(_("Not found"));
127 rc = -1;
128
129done:
130 buf_pool_release(&buf);
131 return rc;
132}
133
134// -----------------------------------------------------------------------------
135
139static int menu_movement(struct Menu *menu, int op)
140{
141 switch (op)
142 {
143 case OP_BOTTOM_PAGE:
144 menu_bottom_page(menu);
145 return FR_SUCCESS;
146
147 case OP_CURRENT_BOTTOM:
149 return FR_SUCCESS;
150
151 case OP_CURRENT_MIDDLE:
153 return FR_SUCCESS;
154
155 case OP_CURRENT_TOP:
156 menu_current_top(menu);
157 return FR_SUCCESS;
158
159 case OP_FIRST_ENTRY:
160 menu_first_entry(menu);
161 return FR_SUCCESS;
162
163 case OP_HALF_DOWN:
164 menu_half_down(menu);
165 return FR_SUCCESS;
166
167 case OP_HALF_UP:
168 menu_half_up(menu);
169 return FR_SUCCESS;
170
171 case OP_LAST_ENTRY:
172 menu_last_entry(menu);
173 return FR_SUCCESS;
174
175 case OP_MIDDLE_PAGE:
176 menu_middle_page(menu);
177 return FR_SUCCESS;
178
179 case OP_NEXT_ENTRY:
180 menu_next_entry(menu);
181 return FR_SUCCESS;
182
183 case OP_NEXT_LINE:
184 menu_next_line(menu);
185 return FR_SUCCESS;
186
187 case OP_NEXT_PAGE:
188 menu_next_page(menu);
189 return FR_SUCCESS;
190
191 case OP_PREV_ENTRY:
192 menu_prev_entry(menu);
193 return FR_SUCCESS;
194
195 case OP_PREV_LINE:
196 menu_prev_line(menu);
197 return FR_SUCCESS;
198
199 case OP_PREV_PAGE:
200 menu_prev_page(menu);
201 return FR_SUCCESS;
202
203 case OP_TOP_PAGE:
204 menu_top_page(menu);
205 return FR_SUCCESS;
206
207 default:
208 return FR_UNKNOWN;
209 }
210}
211
215static int menu_search(struct Menu *menu, int op)
216{
217 if (menu->search)
218 {
219 int index = search(menu, op);
220 if (index != -1)
221 menu_set_index(menu, index);
222 }
223 return FR_SUCCESS;
224}
225
229static int op_help(struct Menu *menu, int op)
230{
231 mutt_help(menu->type);
232 menu->redraw = MENU_REDRAW_FULL;
233 return FR_SUCCESS;
234}
235
239static int op_jump(struct Menu *menu, int op)
240{
241 if (menu->max == 0)
242 {
243 mutt_error(_("No entries"));
244 return FR_SUCCESS;
245 }
246
247 const int digit = op - OP_JUMP;
248 if ((digit > 0) && (digit < 10))
249 {
250 mutt_unget_ch('0' + digit);
251 }
252
253 struct Buffer *buf = buf_pool_get();
254 if ((mw_get_field(_("Jump to: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) == 0) &&
255 !buf_is_empty(buf))
256 {
257 int n = 0;
258 if (mutt_str_atoi_full(buf_string(buf), &n) && (n > 0) && (n < (menu->max + 1)))
259 {
260 menu_set_index(menu, n - 1); // msg numbers are 0-based
261 }
262 else
263 {
264 mutt_error(_("Invalid index number"));
265 }
266 }
267
268 buf_pool_release(&buf);
269 return FR_SUCCESS;
270}
271
272// -----------------------------------------------------------------------------
273
277static const struct MenuFunction MenuFunctions[] = {
278 // clang-format off
279 { OP_BOTTOM_PAGE, menu_movement },
280 { OP_CURRENT_BOTTOM, menu_movement },
281 { OP_CURRENT_MIDDLE, menu_movement },
282 { OP_CURRENT_TOP, menu_movement },
283 { OP_FIRST_ENTRY, menu_movement },
284 { OP_HALF_DOWN, menu_movement },
285 { OP_HALF_UP, menu_movement },
286 { OP_HELP, op_help },
287 { OP_JUMP, op_jump },
288 { OP_JUMP_1, op_jump },
289 { OP_JUMP_2, op_jump },
290 { OP_JUMP_3, op_jump },
291 { OP_JUMP_4, op_jump },
292 { OP_JUMP_5, op_jump },
293 { OP_JUMP_6, op_jump },
294 { OP_JUMP_7, op_jump },
295 { OP_JUMP_8, op_jump },
296 { OP_JUMP_9, op_jump },
297 { OP_LAST_ENTRY, menu_movement },
298 { OP_MIDDLE_PAGE, menu_movement },
299 { OP_NEXT_ENTRY, menu_movement },
300 { OP_NEXT_LINE, menu_movement },
301 { OP_NEXT_PAGE, menu_movement },
302 { OP_PREV_ENTRY, menu_movement },
303 { OP_PREV_LINE, menu_movement },
304 { OP_PREV_PAGE, menu_movement },
305 { OP_SEARCH, menu_search },
306 { OP_SEARCH_NEXT, menu_search },
307 { OP_SEARCH_OPPOSITE, menu_search },
308 { OP_SEARCH_REVERSE, menu_search },
309 { OP_TOP_PAGE, menu_movement },
310 { 0, NULL },
311 // clang-format on
312};
313
318{
319 if (!win || !win->wdata)
320 return FR_UNKNOWN;
321
322 struct Menu *menu = win->wdata;
323
324 int rc = FR_UNKNOWN;
325 for (size_t i = 0; MenuFunctions[i].op != OP_NULL; i++)
326 {
327 const struct MenuFunction *fn = &MenuFunctions[i];
328 if (fn->op == op)
329 {
330 rc = fn->function(menu, op);
331 break;
332 }
333 }
334
335 if (rc == FR_UNKNOWN) // Not our function
336 return rc;
337
338 const char *result = dispatcher_get_retval_name(rc);
339 mutt_debug(LL_DEBUG1, "Handled %s (%d) -> %s\n", opcodes_get_name(op), op, NONULL(result));
340
341 return rc;
342}
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:303
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:407
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:93
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:48
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
int digit(const char *s)
void mutt_unget_ch(int ch)
Return a keystroke to the input buffer.
Definition: get.c:114
const char * dispatcher_get_retval_name(int rv)
Get the name of a return value.
Definition: dispatcher.c:54
@ FR_SUCCESS
Valid function - successfully performed.
Definition: dispatcher.h:39
@ FR_UNKNOWN
Unknown function.
Definition: dispatcher.h:33
Enter a string.
int menu_function_dispatcher(struct MuttWindow *win, int op)
Perform a Menu function - Implements function_dispatcher_t -.
Definition: functions.c:317
static int op_help(struct EnterWindowData *wdata, int op)
Display Help - Implements enter_function_t -.
Definition: functions.c:424
int mw_get_field(const char *prompt, struct Buffer *buf, CompletionFlags complete, enum HistoryClass hclass, const struct CompleteOps *comp_api, void *cdata)
Ask the user for a string -.
Definition: window.c:275
static int op_jump(struct IndexSharedData *shared, struct IndexPrivateData *priv, int op)
Jump to an index number - Implements index_function_t -.
Definition: functions.c:935
#define mutt_error(...)
Definition: logging2.h:92
#define mutt_message(...)
Definition: logging2.h:91
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
static int menu_search(struct Menu *menu, int op)
Handle Menu searching - Implements menu_function_t -.
Definition: functions.c:215
static int menu_movement(struct Menu *menu, int op)
Handle all the common Menu movements - Implements menu_function_t -.
Definition: functions.c:139
Convenience wrapper for the gui headers.
void mutt_help(enum MenuType menu)
Display the help menu.
Definition: help.c:462
Read/write command history from/to a file.
@ HC_OTHER
Miscellaneous strings.
Definition: lib.h:54
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
bool mutt_mb_is_lower(const char *s)
Does a multi-byte string contain only lowercase characters?
Definition: mbyte.c:353
#define MUTT_SEARCH_DOWN
Definition: functions.c:48
#define MUTT_SEARCH_UP
Definition: functions.c:47
static const struct MenuFunction MenuFunctions[]
All the NeoMutt functions that the Menu supports.
Definition: functions.c:277
char * SearchBuffers[]
Previous search string, one for each MenuType.
Definition: menu.c:42
static int search(struct Menu *menu, int op)
Search a menu.
Definition: functions.c:57
#define MENU_REDRAW_FULL
Redraw everything.
Definition: lib.h:60
MenuRedrawFlags menu_next_page(struct Menu *menu)
Move the focus to the next page in the menu.
Definition: move.c:562
MenuRedrawFlags menu_bottom_page(struct Menu *menu)
Move the focus to the bottom of the page.
Definition: move.c:363
MenuRedrawFlags menu_half_up(struct Menu *menu)
Move the focus up half a page in the menu.
Definition: move.c:506
MenuRedrawFlags menu_prev_line(struct Menu *menu)
Move the view up one line, keeping the selection the same.
Definition: move.c:526
MenuRedrawFlags menu_current_bottom(struct Menu *menu)
Move the current selection to the bottom of the window.
Definition: move.c:484
MenuRedrawFlags menu_current_middle(struct Menu *menu)
Move the current selection to the centre of the window.
Definition: move.c:464
MenuRedrawFlags menu_middle_page(struct Menu *menu)
Move the focus to the centre of the page.
Definition: move.c:343
MenuRedrawFlags menu_first_entry(struct Menu *menu)
Move the focus to the first entry in the menu.
Definition: move.c:410
MenuRedrawFlags menu_half_down(struct Menu *menu)
Move the focus down half a page in the menu.
Definition: move.c:516
MenuRedrawFlags menu_top_page(struct Menu *menu)
Move the focus to the top of the page.
Definition: move.c:333
MenuRedrawFlags menu_last_entry(struct Menu *menu)
Move the focus to the last entry in the menu.
Definition: move.c:426
MenuRedrawFlags menu_prev_page(struct Menu *menu)
Move the focus to the previous page in the menu.
Definition: move.c:552
MenuRedrawFlags menu_next_line(struct Menu *menu)
Move the view down one line, keeping the selection the same.
Definition: move.c:539
MenuRedrawFlags menu_prev_entry(struct Menu *menu)
Move the focus to the previous item in the menu.
Definition: move.c:382
MenuRedrawFlags menu_current_top(struct Menu *menu)
Move the current selection to the top of the window.
Definition: move.c:443
MenuRedrawFlags menu_set_index(struct Menu *menu, int index)
Set the current selection in the Menu.
Definition: menu.c:170
MenuRedrawFlags menu_next_entry(struct Menu *menu)
Move the focus to the next item in the menu.
Definition: move.c:396
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:327
Many unsorted constants and some structs.
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:55
#define MUTT_COMP_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:56
const char * opcodes_get_name(int op)
Get the name of an opcode.
Definition: opcodes.c:48
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
Prototypes for many functions.
#define REG_COMP(preg, regex, cflags)
Compile a regular expression.
Definition: regex3.h:53
Sidebar functions.
Key value store.
#define NONULL(x)
Definition: string2.h:37
String manipulation buffer.
Definition: buffer.h:34
size_t dsize
Length of data.
Definition: buffer.h:37
char * data
Pointer to data.
Definition: buffer.h:35
A NeoMutt function.
Definition: functions.h:44
menu_function_t function
Function to call.
Definition: functions.h:46
int op
Op code, e.g. OP_SEARCH.
Definition: functions.h:45
Definition: lib.h:70
struct MuttWindow * win
Window holding the Menu.
Definition: lib.h:77
int search_dir
Direction of search.
Definition: lib.h:83
int current
Current entry.
Definition: lib.h:71
MenuRedrawFlags redraw
When to redraw the screen.
Definition: lib.h:73
int(* search)(struct Menu *menu, regex_t *rx, int line)
Definition: lib.h:109
enum MenuType type
Menu definition for keymap entries.
Definition: lib.h:74
struct ConfigSubset * sub
Inherited config items.
Definition: lib.h:78
int max
Number of entries in the menu.
Definition: lib.h:72
void * wdata
Private data.
Definition: mutt_window.h:145
Menu types.
@ MENU_MAX
Definition: type.h:60