NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
functions.c
Go to the documentation of this file.
1 
29 #include "config.h"
30 #include <stddef.h>
31 #include <stdbool.h>
32 #include "private.h"
33 #include "mutt/lib.h"
34 #include "config/lib.h"
35 #include "core/lib.h"
36 #include "gui/lib.h"
37 #include "lib.h"
38 #include "opcodes.h"
39 
46 {
47  if (ARRAY_EMPTY(&wdata->entries) || (wdata->hil_index < 0))
48  return false;
49 
50  struct SbEntry **sbep = NULL;
51  ARRAY_FOREACH_FROM(sbep, &wdata->entries, wdata->hil_index + 1)
52  {
53  if (!(*sbep)->is_hidden)
54  {
55  wdata->hil_index = ARRAY_FOREACH_IDX;
56  return true;
57  }
58  }
59 
60  return false;
61 }
62 
71 static struct SbEntry **next_new(struct SidebarWindowData *wdata, size_t begin, size_t end)
72 {
73  struct SbEntry **sbep = NULL;
74  ARRAY_FOREACH_FROM_TO(sbep, &wdata->entries, begin, end)
75  {
76  if ((*sbep)->mailbox->has_new || (*sbep)->mailbox->msg_unread != 0)
77  return sbep;
78  }
79  return NULL;
80 }
81 
90 static bool select_next_new(struct SidebarWindowData *wdata, bool next_new_wrap)
91 {
92  const size_t max_entries = ARRAY_SIZE(&wdata->entries);
93 
94  if ((max_entries == 0) || (wdata->hil_index < 0))
95  return false;
96 
97  struct SbEntry **sbep = NULL;
98  if ((sbep = next_new(wdata, wdata->hil_index + 1, max_entries)) ||
99  (next_new_wrap && (sbep = next_new(wdata, 0, wdata->hil_index))))
100  {
101  wdata->hil_index = ARRAY_IDX(&wdata->entries, sbep);
102  return true;
103  }
104 
105  return false;
106 }
107 
113 bool select_prev(struct SidebarWindowData *wdata)
114 {
115  if (ARRAY_EMPTY(&wdata->entries) || (wdata->hil_index < 0))
116  return false;
117 
118  struct SbEntry **sbep = NULL, **prev = NULL;
119  ARRAY_FOREACH_TO(sbep, &wdata->entries, wdata->hil_index)
120  {
121  if (!(*sbep)->is_hidden)
122  prev = sbep;
123  }
124 
125  if (prev)
126  {
127  wdata->hil_index = ARRAY_IDX(&wdata->entries, prev);
128  return true;
129  }
130 
131  return false;
132 }
133 
142 static struct SbEntry **prev_new(struct SidebarWindowData *wdata, size_t begin, size_t end)
143 {
144  struct SbEntry **sbep = NULL, **prev = NULL;
145  ARRAY_FOREACH_FROM_TO(sbep, &wdata->entries, begin, end)
146  {
147  if ((*sbep)->mailbox->has_new || (*sbep)->mailbox->msg_unread != 0)
148  prev = sbep;
149  }
150 
151  return prev;
152 }
153 
162 static bool select_prev_new(struct SidebarWindowData *wdata, bool next_new_wrap)
163 {
164  const size_t max_entries = ARRAY_SIZE(&wdata->entries);
165 
166  if ((max_entries == 0) || (wdata->hil_index < 0))
167  return false;
168 
169  struct SbEntry **sbep = NULL;
170  if ((sbep = prev_new(wdata, 0, wdata->hil_index)) ||
171  (next_new_wrap && (sbep = prev_new(wdata, wdata->hil_index + 1, max_entries))))
172  {
173  wdata->hil_index = ARRAY_IDX(&wdata->entries, sbep);
174  return true;
175  }
176 
177  return false;
178 }
179 
185 static bool select_page_down(struct SidebarWindowData *wdata)
186 {
187  if (ARRAY_EMPTY(&wdata->entries) || (wdata->bot_index < 0))
188  return false;
189 
190  int orig_hil_index = wdata->hil_index;
191 
192  wdata->hil_index = wdata->bot_index;
193  select_next(wdata);
194  /* If the rest of the entries are hidden, go up to the last unhidden one */
195  if ((*ARRAY_GET(&wdata->entries, wdata->hil_index))->is_hidden)
196  select_prev(wdata);
197 
198  return (orig_hil_index != wdata->hil_index);
199 }
200 
206 static bool select_page_up(struct SidebarWindowData *wdata)
207 {
208  if (ARRAY_EMPTY(&wdata->entries) || (wdata->top_index < 0))
209  return false;
210 
211  int orig_hil_index = wdata->hil_index;
212 
213  wdata->hil_index = wdata->top_index;
214  select_prev(wdata);
215  /* If the rest of the entries are hidden, go down to the last unhidden one */
216  if ((*ARRAY_GET(&wdata->entries, wdata->hil_index))->is_hidden)
217  select_next(wdata);
218 
219  return (orig_hil_index != wdata->hil_index);
220 }
221 
227 static bool select_first(struct SidebarWindowData *wdata)
228 {
229  if (ARRAY_EMPTY(&wdata->entries) || (wdata->hil_index < 0))
230  return false;
231 
232  int orig_hil_index = wdata->hil_index;
233 
234  wdata->hil_index = 0;
235  if ((*ARRAY_GET(&wdata->entries, wdata->hil_index))->is_hidden)
236  if (!select_next(wdata))
237  wdata->hil_index = orig_hil_index;
238 
239  return (orig_hil_index != wdata->hil_index);
240 }
241 
247 static bool select_last(struct SidebarWindowData *wdata)
248 {
249  if (ARRAY_EMPTY(&wdata->entries) || (wdata->hil_index < 0))
250  return false;
251 
252  int orig_hil_index = wdata->hil_index;
253 
254  wdata->hil_index = ARRAY_SIZE(&wdata->entries);
255  if (!select_prev(wdata))
256  wdata->hil_index = orig_hil_index;
257 
258  return (orig_hil_index != wdata->hil_index);
259 }
260 
266 void sb_change_mailbox(struct MuttWindow *win, int op)
267 {
268  if (!mutt_window_is_visible(win))
269  return;
270 
271  struct SidebarWindowData *wdata = sb_wdata_get(win);
272  if (!wdata)
273  return;
274 
275  if (wdata->hil_index < 0) /* It'll get reset on the next draw */
276  return;
277 
278  bool changed = false;
279  const bool c_sidebar_next_new_wrap =
280  cs_subset_bool(NeoMutt->sub, "sidebar_next_new_wrap");
281  switch (op)
282  {
283  case OP_SIDEBAR_FIRST:
284  changed = select_first(wdata);
285  break;
286  case OP_SIDEBAR_LAST:
287  changed = select_last(wdata);
288  break;
289  case OP_SIDEBAR_NEXT:
290  changed = select_next(wdata);
291  break;
292  case OP_SIDEBAR_NEXT_NEW:
293  changed = select_next_new(wdata, c_sidebar_next_new_wrap);
294  break;
295  case OP_SIDEBAR_PAGE_DOWN:
296  changed = select_page_down(wdata);
297  break;
298  case OP_SIDEBAR_PAGE_UP:
299  changed = select_page_up(wdata);
300  break;
301  case OP_SIDEBAR_PREV:
302  changed = select_prev(wdata);
303  break;
304  case OP_SIDEBAR_PREV_NEW:
305  changed = select_prev_new(wdata, c_sidebar_next_new_wrap);
306  break;
307  default:
308  return;
309  }
310  if (changed)
311  win->actions |= WA_RECALC;
312 }
Convenience wrapper for the gui headers.
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
int top_index
First mailbox visible in sidebar.
Definition: private.h:67
#define ARRAY_IDX(head, elem)
Return the index of an element of the array.
Definition: array.h:253
#define ARRAY_GET(head, idx)
Return the element at index.
Definition: array.h:105
#define ARRAY_FOREACH_TO(elem, head, to)
Iterate from the beginning to an index.
Definition: array.h:228
Sidebar private Window data -.
Definition: private.h:62
Info about folders in the sidebar.
Definition: private.h:39
int hil_index
Highlighted mailbox.
Definition: private.h:69
All user-callable functions.
Container for Accounts, Notifications.
Definition: neomutt.h:36
Convenience wrapper for the config headers.
WindowActionFlags actions
Actions to be performed, e.g. WA_RECALC.
Definition: mutt_window.h:132
#define ARRAY_FOREACH_FROM_TO(elem, head, from, to)
Iterate between two indexes.
Definition: array.h:241
Convenience wrapper for the core headers.
bool mutt_window_is_visible(struct MuttWindow *win)
Is the Window visible?
Definition: mutt_window.c:529
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition: array.h:70
#define ARRAY_FOREACH_FROM(elem, head, from)
Iterate from an index to the end.
Definition: array.h:217
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
Convenience wrapper for the library headers.
int bot_index
Last mailbox visible in sidebar.
Definition: private.h:70
void * wdata
Private data.
Definition: mutt_window.h:145
#define ARRAY_SIZE(head)
The number of elements stored.
Definition: array.h:83
#define WA_RECALC
Recalculate the contents of the Window.
Definition: mutt_window.h:110