NeoMutt  2025-12-11-694-ga89709
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
move.c
Go to the documentation of this file.
1
22
50
51#include "config.h"
52#include <stdbool.h>
53#include <stddef.h>
54#include "mutt/lib.h"
55#include "config/lib.h"
56#include "gui/lib.h"
57#include "lib.h"
58
66MenuRedrawFlags menu_set_and_notify(struct Menu *menu, int top, int index)
67{
69
70 if (top != menu->top)
71 {
72 menu->top = top;
73 flags |= MENU_REDRAW_FULL;
74 }
75
76 if (index != menu->current)
77 {
78 menu->old_current = menu->current;
79 menu->current = index;
80
81 if (menu->redraw == MENU_REDRAW_NO_FLAGS)
82 {
83 // If this is the only change
84 flags |= MENU_REDRAW_MOTION;
85 }
86 else
87 {
88 // otherwise, redraw completely
89 flags |= MENU_REDRAW_FULL;
90 }
91 }
92
93 if (flags != MENU_REDRAW_NO_FLAGS)
94 {
95 menu->redraw |= flags;
96 menu->win->actions |= WA_REPAINT;
97
98 mutt_debug(LL_NOTIFY, "NT_MENU\n");
99 notify_send(menu->notify, NT_MENU, flags, NULL);
100 }
101 return flags;
102}
103
111static int menu_drag_view(struct Menu *menu, int top, int index)
112{
113 if (menu->max <= menu->page_len) // fewer entries than lines
114 return 0;
115
116 const int page = menu->page_len;
117
118 short c_menu_context = cs_subset_number(menu->sub, "menu_context");
119 c_menu_context = MIN(c_menu_context, (page / 2));
120
121 const bool c_menu_scroll = cs_subset_bool(menu->sub, "menu_scroll");
122 if (c_menu_scroll)
123 {
124 int bottom = top + page;
125 // Scroll the view to make the selection visible
126 if (index < top + c_menu_context) // scroll=YES, moving UP
127 top = index - c_menu_context;
128 else if (index >= (bottom - c_menu_context)) // scroll=YES, moving DOWN
129 top = index - page + c_menu_context + 1;
130 }
131 else
132 {
133 if ((index < top) || (index >= (top + page)))
134 top = (index / page) * page; // Round down to a page size
135 int bottom = top + page;
136
137 // Page up/down to make the selection visible
138 if (index < (top + c_menu_context)) // scroll=NO, moving UP
139 top = index - page + c_menu_context + 1;
140 else if (index >= (bottom - c_menu_context)) // scroll=NO, moving DOWN
141 top = index - c_menu_context;
142 }
143
144 if (top < 0)
145 top = 0;
146
147 // Tie the last entry to the bottom of the screen
148 const bool c_menu_move_off = cs_subset_bool(menu->sub, "menu_move_off");
149 if (!c_menu_move_off && (top >= (menu->max - page)))
150 {
151 top = menu->max - page;
152 }
153
154 return top;
155}
156
164static int calc_fit_selection_to_view(struct Menu *menu, int top, int index)
165{
166 short c_menu_context = cs_subset_number(menu->sub, "menu_context");
167 c_menu_context = MIN(c_menu_context, (menu->page_len / 2));
168
169 int min = top;
170 if (top != 0)
171 min += c_menu_context;
172
173 int max = top + menu->page_len - 1;
174 if (max < (menu->max - 1))
175 max -= c_menu_context;
176 else
177 max = menu->max - 1;
178
179 if (index < min)
180 index = min;
181 else if (index > max)
182 index = max;
183
184 return index;
185}
186
194static int calc_move_view(struct Menu *menu, int relative)
195{
196 if (menu->max <= menu->page_len) // fewer entries than lines
197 return 0;
198
199 short c_menu_context = cs_subset_number(menu->sub, "menu_context");
200 c_menu_context = MIN(c_menu_context, (menu->page_len / 2));
201
202 int index = menu->current;
203 if (index < c_menu_context)
204 return 0;
205
206 int top = menu->top + relative;
207 if (top < 0)
208 return 0;
209
210 if ((menu->top + menu->page_len) < menu->max)
211 return top;
212
213 int max = menu->max - 1;
214 const bool c_menu_move_off = cs_subset_bool(menu->sub, "menu_move_off");
215 if (c_menu_move_off)
216 {
217 max -= c_menu_context;
218 }
219 else
220 {
221 max -= menu->page_len - 1;
222 }
223
224 if (top > max)
225 top = max;
226
227 return top;
228}
229
237{
238 if (menu->max == 0)
240
241 if (index < 0)
242 index = 0;
243 else if (index >= menu->max)
244 index = menu->max - 1;
245
246 int top = menu_drag_view(menu, menu->top, index);
247
248 return menu_set_and_notify(menu, top, index);
249}
250
258{
259 if (menu->max <= menu->page_len)
260 return menu_move_selection(menu, menu->current + relative);
261
262 const bool c_menu_move_off = cs_subset_bool(menu->sub, "menu_move_off");
263
264 short c_menu_context = cs_subset_number(menu->sub, "menu_context");
265 c_menu_context = MIN(c_menu_context, (menu->page_len / 2));
266
267 // Move and range-check the view
268 int top = menu->top + relative;
269 if (top < 0)
270 {
271 top = 0;
272 }
273 else if (c_menu_move_off && (top >= (menu->max - c_menu_context)))
274 {
275 top = menu->max - c_menu_context - 1;
276 }
277 else if (!c_menu_move_off && ((top + menu->page_len) >= menu->max))
278 {
279 top = menu->max - menu->page_len;
280 }
281 if (top < 0)
282 top = 0;
283
284 // Move the selection on-screen
285 int index = menu->current;
286 if (index < top)
287 index = top;
288 else if (index >= (top + menu->page_len))
289 index = top + menu->page_len - 1;
290
291 // Check for top/bottom limits
292 if (index < c_menu_context)
293 {
294 top = 0;
295 index = menu->current;
296 }
297 else if (!c_menu_move_off && (index > (menu->max - c_menu_context)))
298 {
299 top = menu->max - menu->page_len;
300 index = menu->current;
301 }
302
303 if (top == menu->top)
304 {
305 // Can't move the view; move the selection
306 index = calc_fit_selection_to_view(menu, top, index + relative);
307 }
308 else if (index > (top + menu->page_len - c_menu_context - 1))
309 {
310 index = calc_fit_selection_to_view(menu, top, index + relative);
311 }
312 else
313 {
314 // Drag the selection into the view
315 index = calc_fit_selection_to_view(menu, top, index);
316 }
317
318 return menu_set_and_notify(menu, top, index);
319}
320
325void menu_adjust(struct Menu *menu)
326{
327 int top = calc_move_view(menu, 0);
328 top = menu_drag_view(menu, top, menu->current);
329
330 menu_set_and_notify(menu, top, menu->current);
331}
332
333// These functions move the selection (and may cause the view to move)
340{
341 return menu_move_selection(menu, menu->top);
342}
343
350{
351 if (menu->max == 0)
352 {
353 mutt_error(_("No entries"));
355 }
356
357 int i = menu->top + menu->page_len;
358 if (i > (menu->max - 1))
359 i = menu->max - 1;
360
361 return menu_move_selection(menu, menu->top + (i - menu->top) / 2);
362}
363
370{
371 if (menu->max == 0)
372 {
373 mutt_error(_("No entries"));
375 }
376
377 int index = menu->top + menu->page_len - 1;
378 if (index > (menu->max - 1))
379 index = menu->max - 1;
380 return menu_move_selection(menu, index);
381}
382
389{
390 if (menu->current > 0)
391 return menu_move_selection(menu, menu->current - 1);
392
393 mutt_message(_("You are on the first entry"));
395}
396
403{
404 if (menu->current < (menu->max - 1))
405 return menu_move_selection(menu, menu->current + 1);
406
407 mutt_message(_("You are on the last entry"));
409}
410
417{
418 if (menu->max == 0)
419 {
420 mutt_error(_("No entries"));
422 }
423
424 return menu_move_selection(menu, 0);
425}
426
433{
434 if (menu->max == 0)
435 {
436 mutt_error(_("No entries"));
438 }
439
440 return menu_move_selection(menu, menu->max - 1);
441}
442
443// These functions move the view (and may cause the selection to move)
450{
451 if (menu->max == 0)
452 {
453 mutt_error(_("No entries"));
455 }
456
457 short c_menu_context = cs_subset_number(menu->sub, "menu_context");
458 if (c_menu_context > (menu->page_len / 2))
460
461 c_menu_context = MIN(c_menu_context, (menu->page_len / 2));
462 return menu_move_view_relative(menu, menu->current - menu->top - c_menu_context);
463}
464
471{
472 if (menu->max == 0)
473 {
474 mutt_error(_("No entries"));
476 }
477
478 short c_menu_context = cs_subset_number(menu->sub, "menu_context");
479 if (c_menu_context > (menu->page_len / 2))
481
482 return menu_move_view_relative(menu, menu->current - (menu->top + (menu->page_len / 2)));
483}
484
491{
492 if (menu->max == 0)
493 {
494 mutt_error(_("No entries"));
496 }
497
498 short c_menu_context = cs_subset_number(menu->sub, "menu_context");
499 if (c_menu_context > (menu->page_len / 2))
501
502 c_menu_context = MIN(c_menu_context, (menu->page_len / 2));
503 return menu_move_view_relative(menu, 0 - (menu->top + menu->page_len - 1 -
504 menu->current - c_menu_context));
505}
506
513{
514 return menu_move_view_relative(menu, 0 - (menu->page_len / 2));
515}
516
523{
524 return menu_move_view_relative(menu, (menu->page_len / 2));
525}
526
533{
535 if (flags == MENU_REDRAW_NO_FLAGS)
536 mutt_message(_("You can't scroll up farther"));
537 return flags;
538}
539
546{
548 if (flags == MENU_REDRAW_NO_FLAGS)
549 mutt_message(_("You can't scroll down farther"));
550 return flags;
551}
552
559{
560 return menu_move_view_relative(menu, 0 - menu->page_len);
561}
562
569{
570 return menu_move_view_relative(menu, menu->page_len);
571}
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition helpers.c:143
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.
#define mutt_error(...)
Definition logging2.h:94
#define mutt_message(...)
Definition logging2.h:93
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
Convenience wrapper for the gui headers.
@ LL_NOTIFY
Log of notifications.
Definition logging2.h:50
#define MIN(a, b)
Return the minimum of two values.
Definition memory.h:40
GUI present the user with a selectable list.
#define MENU_REDRAW_FULL
Redraw everything.
Definition lib.h:60
#define MENU_REDRAW_NO_FLAGS
No flags are set.
Definition lib.h:56
uint8_t MenuRedrawFlags
Flags, e.g. MENU_REDRAW_INDEX.
Definition lib.h:55
#define MENU_REDRAW_MOTION
Redraw after moving the menu list.
Definition lib.h:58
MenuRedrawFlags menu_next_page(struct Menu *menu)
Move the focus to the next page in the menu.
Definition move.c:568
MenuRedrawFlags menu_bottom_page(struct Menu *menu)
Move the focus to the bottom of the page.
Definition move.c:369
void menu_adjust(struct Menu *menu)
Reapply the config to the Menu.
Definition move.c:325
MenuRedrawFlags menu_half_up(struct Menu *menu)
Move the focus up half a page in the menu.
Definition move.c:512
MenuRedrawFlags menu_prev_line(struct Menu *menu)
Move the view up one line, keeping the selection the same.
Definition move.c:532
MenuRedrawFlags menu_current_bottom(struct Menu *menu)
Move the current selection to the bottom of the window.
Definition move.c:490
MenuRedrawFlags menu_move_view_relative(struct Menu *menu, int relative)
Move the view relatively.
Definition move.c:257
static int calc_move_view(struct Menu *menu, int relative)
Move the view.
Definition move.c:194
MenuRedrawFlags menu_current_middle(struct Menu *menu)
Move the current selection to the centre of the window.
Definition move.c:470
MenuRedrawFlags menu_middle_page(struct Menu *menu)
Move the focus to the centre of the page.
Definition move.c:349
MenuRedrawFlags menu_set_and_notify(struct Menu *menu, int top, int index)
Set the Menu selection/view and notify others.
Definition move.c:66
MenuRedrawFlags menu_first_entry(struct Menu *menu)
Move the focus to the first entry in the menu.
Definition move.c:416
MenuRedrawFlags menu_half_down(struct Menu *menu)
Move the focus down half a page in the menu.
Definition move.c:522
MenuRedrawFlags menu_top_page(struct Menu *menu)
Move the focus to the top of the page.
Definition move.c:339
MenuRedrawFlags menu_move_selection(struct Menu *menu, int index)
Move the selection, keeping within between [0, menu->max].
Definition move.c:236
MenuRedrawFlags menu_last_entry(struct Menu *menu)
Move the focus to the last entry in the menu.
Definition move.c:432
MenuRedrawFlags menu_prev_page(struct Menu *menu)
Move the focus to the previous page in the menu.
Definition move.c:558
static int calc_fit_selection_to_view(struct Menu *menu, int top, int index)
Move the selection into the view.
Definition move.c:164
static int menu_drag_view(struct Menu *menu, int top, int index)
Move the view around the selection.
Definition move.c:111
MenuRedrawFlags menu_next_line(struct Menu *menu)
Move the view down one line, keeping the selection the same.
Definition move.c:545
MenuRedrawFlags menu_prev_entry(struct Menu *menu)
Move the focus to the previous item in the menu.
Definition move.c:388
MenuRedrawFlags menu_current_top(struct Menu *menu)
Move the current selection to the top of the window.
Definition move.c:449
MenuRedrawFlags menu_next_entry(struct Menu *menu)
Move the focus to the next item in the menu.
Definition move.c:402
Convenience wrapper for the library headers.
#define _(a)
Definition message.h:28
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition notify.c:173
#define WA_REPAINT
Redraw the contents of the Window.
@ NT_MENU
Menu has changed, MenuRedrawFlags.
Definition notify_type.h:51
Definition lib.h:80
struct MuttWindow * win
Window holding the Menu.
Definition lib.h:88
int current
Current entry.
Definition lib.h:81
MenuRedrawFlags redraw
When to redraw the screen.
Definition lib.h:83
int top
Entry that is the top of the current page.
Definition lib.h:92
struct ConfigSubset * sub
Inherited config items.
Definition lib.h:89
struct Notify * notify
Notifications.
Definition lib.h:147
int max
Number of entries in the menu.
Definition lib.h:82
int page_len
Number of entries per screen.
Definition lib.h:85
int old_current
For driver use only.
Definition lib.h:93
WindowActionFlags actions
Actions to be performed, e.g. WA_RECALC.