NeoMutt  2022-04-29-249-gaae397
Teaching an old dog new tricks
DOXYGEN
move.c
Go to the documentation of this file.
1
51#include "config.h"
52#include <stddef.h>
53#include <stdbool.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 context = cs_subset_number(menu->sub, "menu_context");
119 context = MIN(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 + context) // scroll=YES, moving UP
127 top = index - context;
128 else if (index >= (bottom - context)) // scroll=YES, moving DOWN
129 top = index - page + 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 + context)) // scroll=NO, moving UP
139 top = index - page + context + 1;
140 else if (index >= (bottom - context)) // scroll=NO, moving DOWN
141 top = index - 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 context = cs_subset_number(menu->sub, "menu_context");
167 context = MIN(context, (menu->page_len / 2));
168
169 int min = top;
170 if (top != 0)
171 min += context;
172
173 int max = top + menu->page_len - 1;
174 if (max < (menu->max - 1))
175 max -= 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 context = cs_subset_number(menu->sub, "menu_context");
200 context = MIN(context, (menu->page_len / 2));
201
202 int index = menu->current;
203 if (index < 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 -= 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 (index < 0)
239 index = 0;
240 else if (index >= menu->max)
241 index = menu->max - 1;
242
243 int top = menu_drag_view(menu, menu->top, index);
244
245 return menu_set_and_notify(menu, top, index);
246}
247
255{
256 const bool c_menu_move_off = cs_subset_bool(menu->sub, "menu_move_off");
257
258 short context = cs_subset_number(menu->sub, "menu_context");
259 context = MIN(context, (menu->page_len / 2));
260
261 // Move and range-check the view
262 int top = menu->top + relative;
263 if (top < 0)
264 {
265 top = 0;
266 }
267 else if (c_menu_move_off && (top >= (menu->max - context)))
268 {
269 top = menu->max - context - 1;
270 }
271 else if (!c_menu_move_off && ((top + menu->page_len) >= menu->max))
272 {
273 top = menu->max - menu->page_len;
274 }
275 if (top < 0)
276 top = 0;
277
278 // Move the selection on-screen
279 int index = menu->current;
280 if (index < top)
281 index = top;
282 else if (index >= (top + menu->page_len))
283 index = top + menu->page_len - 1;
284
285 // Check for top/bottom limits
286 if (index < context)
287 {
288 top = 0;
289 index = menu->current;
290 }
291 else if (!c_menu_move_off && (index > (menu->max - context)))
292 {
293 top = menu->max - menu->page_len;
294 index = menu->current;
295 }
296
297 if (top == menu->top)
298 {
299 // Can't move the view; move the selection
300 index = calc_fit_selection_to_view(menu, top, index + relative);
301 }
302 else if (index > (top + menu->page_len - context - 1))
303 {
304 index = calc_fit_selection_to_view(menu, top, index + relative);
305 }
306 else
307 {
308 // Drag the selection into the view
309 index = calc_fit_selection_to_view(menu, top, index);
310 }
311
312 return menu_set_and_notify(menu, top, index);
313}
314
319void menu_adjust(struct Menu *menu)
320{
321 int top = calc_move_view(menu, 0);
322 top = menu_drag_view(menu, top, menu->current);
323
324 menu_set_and_notify(menu, top, menu->current);
325}
326
327// These functions move the selection (and may cause the view to move)
334{
335 return menu_move_selection(menu, menu->top);
336}
337
344{
345 if (menu->max == 0)
346 {
347 mutt_error(_("No entries"));
349 }
350
351 int i = menu->top + menu->page_len;
352 if (i > (menu->max - 1))
353 i = menu->max - 1;
354
355 return menu_move_selection(menu, menu->top + (i - menu->top) / 2);
356}
357
364{
365 if (menu->max == 0)
366 {
367 mutt_error(_("No entries"));
369 }
370
371 int index = menu->top + menu->page_len - 1;
372 if (index > (menu->max - 1))
373 index = menu->max - 1;
374 return menu_move_selection(menu, index);
375}
376
383{
384 if (menu->current > 0)
385 return menu_move_selection(menu, menu->current - 1);
386
387 mutt_message(_("You are on the first entry"));
389}
390
397{
398 if (menu->current < (menu->max - 1))
399 return menu_move_selection(menu, menu->current + 1);
400
401 mutt_message(_("You are on the last entry"));
403}
404
411{
412 if (menu->max == 0)
413 {
414 mutt_error(_("No entries"));
416 }
417
418 return menu_move_selection(menu, 0);
419}
420
427{
428 if (menu->max == 0)
429 {
430 mutt_error(_("No entries"));
432 }
433
434 return menu_move_selection(menu, menu->max - 1);
435}
436
437// These functions move the view (and may cause the selection to move)
444{
445 if (menu->max == 0)
446 {
447 mutt_error(_("No entries"));
449 }
450
451 short context = cs_subset_number(menu->sub, "menu_context");
452 if (context > (menu->page_len / 2))
454
455 context = MIN(context, (menu->page_len / 2));
456 return menu_move_view_relative(menu, menu->current - menu->top - context);
457}
458
465{
466 if (menu->max == 0)
467 {
468 mutt_error(_("No entries"));
470 }
471
472 short context = cs_subset_number(menu->sub, "menu_context");
473 if (context > (menu->page_len / 2))
475
476 return menu_move_view_relative(menu, menu->current - (menu->top + (menu->page_len / 2)));
477}
478
485{
486 if (menu->max == 0)
487 {
488 mutt_error(_("No entries"));
490 }
491
492 short context = cs_subset_number(menu->sub, "menu_context");
493 if (context > (menu->page_len / 2))
495
496 context = MIN(context, (menu->page_len / 2));
497 return menu_move_view_relative(menu, 0 - (menu->top + menu->page_len - 1 -
498 menu->current - context));
499}
500
507{
508 return menu_move_view_relative(menu, 0 - (menu->page_len / 2));
509}
510
517{
518 return menu_move_view_relative(menu, (menu->page_len / 2));
519}
520
527{
529 if (flags == MENU_REDRAW_NO_FLAGS)
530 mutt_message(_("You can't scroll up farther"));
531 return flags;
532}
533
540{
542 if (flags == MENU_REDRAW_NO_FLAGS)
543 mutt_message(_("You can't scroll down farther"));
544 return flags;
545}
546
553{
554 return menu_move_view_relative(menu, 0 - menu->page_len);
555}
556
563{
564 return menu_move_view_relative(menu, menu->page_len);
565}
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
Convenience wrapper for the config headers.
#define mutt_error(...)
Definition: logging.h:87
#define mutt_message(...)
Definition: logging.h:86
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
Convenience wrapper for the gui headers.
@ LL_NOTIFY
Log of notifications.
Definition: logging.h:45
#define MIN(a, b)
Definition: memory.h:31
#define MENU_REDRAW_FULL
Redraw everything.
Definition: lib.h:59
#define MENU_REDRAW_NO_FLAGS
No flags are set.
Definition: lib.h:55
uint8_t MenuRedrawFlags
Flags, e.g. MENU_REDRAW_INDEX.
Definition: lib.h:54
#define MENU_REDRAW_MOTION
Redraw after moving the menu list.
Definition: lib.h:57
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
void menu_adjust(struct Menu *menu)
Reapply the config to the Menu.
Definition: move.c:319
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_move_view_relative(struct Menu *menu, int relative)
Move the view relatively.
Definition: move.c:254
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:464
MenuRedrawFlags menu_middle_page(struct Menu *menu)
Move the focus to the centre of the page.
Definition: move.c:343
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: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_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:426
MenuRedrawFlags menu_prev_page(struct Menu *menu)
Move the focus to the previous page in the menu.
Definition: move.c:552
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: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_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
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:171
#define WA_REPAINT
Redraw the contents of the Window.
Definition: mutt_window.h:111
@ NT_MENU
Menu has changed, MenuRedrawFlags.
Definition: notify_type.h:51
Key value store.
Definition: lib.h:69
struct MuttWindow * win
Window holding the Menu.
Definition: lib.h:76
int current
Current entry.
Definition: lib.h:70
MenuRedrawFlags redraw
When to redraw the screen.
Definition: lib.h:72
int top
Entry that is the top of the current page.
Definition: lib.h:80
struct ConfigSubset * sub
Inherited config items.
Definition: lib.h:77
struct Notify * notify
Notifications.
Definition: lib.h:135
int max
Number of entries in the menu.
Definition: lib.h:71
int page_len
Number of entries per screen.
Definition: lib.h:74
int old_current
For driver use only.
Definition: lib.h:81
WindowActionFlags actions
Actions to be performed, e.g. WA_RECALC.
Definition: mutt_window.h:132