NeoMutt  2025-12-11-435-g4ac674
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 const bool c_menu_move_off = cs_subset_bool(menu->sub, "menu_move_off");
260
261 short c_menu_context = cs_subset_number(menu->sub, "menu_context");
262 c_menu_context = MIN(c_menu_context, (menu->page_len / 2));
263
264 // Move and range-check the view
265 int top = menu->top + relative;
266 if (top < 0)
267 {
268 top = 0;
269 }
270 else if (c_menu_move_off && (top >= (menu->max - c_menu_context)))
271 {
272 top = menu->max - c_menu_context - 1;
273 }
274 else if (!c_menu_move_off && ((top + menu->page_len) >= menu->max))
275 {
276 top = menu->max - menu->page_len;
277 }
278 if (top < 0)
279 top = 0;
280
281 // Move the selection on-screen
282 int index = menu->current;
283 if (index < top)
284 index = top;
285 else if (index >= (top + menu->page_len))
286 index = top + menu->page_len - 1;
287
288 // Check for top/bottom limits
289 if (index < c_menu_context)
290 {
291 top = 0;
292 index = menu->current;
293 }
294 else if (!c_menu_move_off && (index > (menu->max - c_menu_context)))
295 {
296 top = menu->max - menu->page_len;
297 index = menu->current;
298 }
299
300 if (top == menu->top)
301 {
302 // Can't move the view; move the selection
303 index = calc_fit_selection_to_view(menu, top, index + relative);
304 }
305 else if (index > (top + menu->page_len - c_menu_context - 1))
306 {
307 index = calc_fit_selection_to_view(menu, top, index + relative);
308 }
309 else
310 {
311 // Drag the selection into the view
312 index = calc_fit_selection_to_view(menu, top, index);
313 }
314
315 return menu_set_and_notify(menu, top, index);
316}
317
322void menu_adjust(struct Menu *menu)
323{
324 int top = calc_move_view(menu, 0);
325 top = menu_drag_view(menu, top, menu->current);
326
327 menu_set_and_notify(menu, top, menu->current);
328}
329
330// These functions move the selection (and may cause the view to move)
337{
338 return menu_move_selection(menu, menu->top);
339}
340
347{
348 if (menu->max == 0)
349 {
350 mutt_error(_("No entries"));
352 }
353
354 int i = menu->top + menu->page_len;
355 if (i > (menu->max - 1))
356 i = menu->max - 1;
357
358 return menu_move_selection(menu, menu->top + (i - menu->top) / 2);
359}
360
367{
368 if (menu->max == 0)
369 {
370 mutt_error(_("No entries"));
372 }
373
374 int index = menu->top + menu->page_len - 1;
375 if (index > (menu->max - 1))
376 index = menu->max - 1;
377 return menu_move_selection(menu, index);
378}
379
386{
387 if (menu->current > 0)
388 return menu_move_selection(menu, menu->current - 1);
389
390 mutt_message(_("You are on the first entry"));
392}
393
400{
401 if (menu->current < (menu->max - 1))
402 return menu_move_selection(menu, menu->current + 1);
403
404 mutt_message(_("You are on the last entry"));
406}
407
414{
415 if (menu->max == 0)
416 {
417 mutt_error(_("No entries"));
419 }
420
421 return menu_move_selection(menu, 0);
422}
423
430{
431 if (menu->max == 0)
432 {
433 mutt_error(_("No entries"));
435 }
436
437 return menu_move_selection(menu, menu->max - 1);
438}
439
440// These functions move the view (and may cause the selection to move)
447{
448 if (menu->max == 0)
449 {
450 mutt_error(_("No entries"));
452 }
453
454 short c_menu_context = cs_subset_number(menu->sub, "menu_context");
455 if (c_menu_context > (menu->page_len / 2))
457
458 c_menu_context = MIN(c_menu_context, (menu->page_len / 2));
459 return menu_move_view_relative(menu, menu->current - menu->top - c_menu_context);
460}
461
468{
469 if (menu->max == 0)
470 {
471 mutt_error(_("No entries"));
473 }
474
475 short c_menu_context = cs_subset_number(menu->sub, "menu_context");
476 if (c_menu_context > (menu->page_len / 2))
478
479 return menu_move_view_relative(menu, menu->current - (menu->top + (menu->page_len / 2)));
480}
481
488{
489 if (menu->max == 0)
490 {
491 mutt_error(_("No entries"));
493 }
494
495 short c_menu_context = cs_subset_number(menu->sub, "menu_context");
496 if (c_menu_context > (menu->page_len / 2))
498
499 c_menu_context = MIN(c_menu_context, (menu->page_len / 2));
500 return menu_move_view_relative(menu, 0 - (menu->top + menu->page_len - 1 -
501 menu->current - c_menu_context));
502}
503
510{
511 return menu_move_view_relative(menu, 0 - (menu->page_len / 2));
512}
513
520{
521 return menu_move_view_relative(menu, (menu->page_len / 2));
522}
523
530{
532 if (flags == MENU_REDRAW_NO_FLAGS)
533 mutt_message(_("You can't scroll up farther"));
534 return flags;
535}
536
543{
545 if (flags == MENU_REDRAW_NO_FLAGS)
546 mutt_message(_("You can't scroll down farther"));
547 return flags;
548}
549
556{
557 return menu_move_view_relative(menu, 0 - menu->page_len);
558}
559
566{
567 return menu_move_view_relative(menu, menu->page_len);
568}
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:565
MenuRedrawFlags menu_bottom_page(struct Menu *menu)
Move the focus to the bottom of the page.
Definition move.c:366
void menu_adjust(struct Menu *menu)
Reapply the config to the Menu.
Definition move.c:322
MenuRedrawFlags menu_half_up(struct Menu *menu)
Move the focus up half a page in the menu.
Definition move.c:509
MenuRedrawFlags menu_prev_line(struct Menu *menu)
Move the view up one line, keeping the selection the same.
Definition move.c:529
MenuRedrawFlags menu_current_bottom(struct Menu *menu)
Move the current selection to the bottom of the window.
Definition move.c:487
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:467
MenuRedrawFlags menu_middle_page(struct Menu *menu)
Move the focus to the centre of the page.
Definition move.c:346
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:413
MenuRedrawFlags menu_half_down(struct Menu *menu)
Move the focus down half a page in the menu.
Definition move.c:519
MenuRedrawFlags menu_top_page(struct Menu *menu)
Move the focus to the top of the page.
Definition move.c:336
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:429
MenuRedrawFlags menu_prev_page(struct Menu *menu)
Move the focus to the previous page in the menu.
Definition move.c:555
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:542
MenuRedrawFlags menu_prev_entry(struct Menu *menu)
Move the focus to the previous item in the menu.
Definition move.c:385
MenuRedrawFlags menu_current_top(struct Menu *menu)
Move the current selection to the top of the window.
Definition move.c:446
MenuRedrawFlags menu_next_entry(struct Menu *menu)
Move the focus to the next item in the menu.
Definition move.c:399
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.