NeoMutt  2021-02-05
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 "core/lib.h"
35 #include "gui/lib.h"
36 #include "lib.h"
37 #include "opcodes.h"
38 
45 {
46  if (ARRAY_EMPTY(&wdata->entries) || (wdata->hil_index < 0))
47  return false;
48 
49  struct SbEntry **sbep = NULL;
50  ARRAY_FOREACH_FROM(sbep, &wdata->entries, wdata->hil_index + 1)
51  {
52  if (!(*sbep)->is_hidden)
53  {
54  wdata->hil_index = ARRAY_FOREACH_IDX;
55  return true;
56  }
57  }
58 
59  return false;
60 }
61 
70 static struct SbEntry **next_new(struct SidebarWindowData *wdata, size_t begin, size_t end)
71 {
72  struct SbEntry **sbep = NULL;
73  ARRAY_FOREACH_FROM_TO(sbep, &wdata->entries, begin, end)
74  {
75  if ((*sbep)->mailbox->has_new || (*sbep)->mailbox->msg_unread != 0)
76  return sbep;
77  }
78  return NULL;
79 }
80 
89 static bool select_next_new(struct SidebarWindowData *wdata, bool next_new_wrap)
90 {
91  const size_t max_entries = ARRAY_SIZE(&wdata->entries);
92 
93  if ((max_entries == 0) || (wdata->hil_index < 0))
94  return false;
95 
96  struct SbEntry **sbep = NULL;
97  if ((sbep = next_new(wdata, wdata->hil_index + 1, max_entries)) ||
98  (next_new_wrap && (sbep = next_new(wdata, 0, wdata->hil_index))))
99  {
100  wdata->hil_index = ARRAY_IDX(&wdata->entries, sbep);
101  return true;
102  }
103 
104  return false;
105 }
106 
112 bool select_prev(struct SidebarWindowData *wdata)
113 {
114  if (ARRAY_EMPTY(&wdata->entries) || (wdata->hil_index < 0))
115  return false;
116 
117  struct SbEntry **sbep = NULL, **prev = NULL;
118  ARRAY_FOREACH_TO(sbep, &wdata->entries, wdata->hil_index)
119  {
120  if (!(*sbep)->is_hidden)
121  prev = sbep;
122  }
123 
124  if (prev)
125  {
126  wdata->hil_index = ARRAY_IDX(&wdata->entries, prev);
127  return true;
128  }
129 
130  return false;
131 }
132 
141 static struct SbEntry **prev_new(struct SidebarWindowData *wdata, size_t begin, size_t end)
142 {
143  struct SbEntry **sbep = NULL, **prev = NULL;
144  ARRAY_FOREACH_FROM_TO(sbep, &wdata->entries, begin, end)
145  {
146  if ((*sbep)->mailbox->has_new || (*sbep)->mailbox->msg_unread != 0)
147  prev = sbep;
148  }
149 
150  return prev;
151 }
152 
161 static bool select_prev_new(struct SidebarWindowData *wdata, bool next_new_wrap)
162 {
163  const size_t max_entries = ARRAY_SIZE(&wdata->entries);
164 
165  if ((max_entries == 0) || (wdata->hil_index < 0))
166  return false;
167 
168  struct SbEntry **sbep = NULL;
169  if ((sbep = prev_new(wdata, 0, wdata->hil_index)) ||
170  (next_new_wrap && (sbep = prev_new(wdata, wdata->hil_index + 1, max_entries))))
171  {
172  wdata->hil_index = ARRAY_IDX(&wdata->entries, sbep);
173  return true;
174  }
175 
176  return false;
177 }
178 
184 static bool select_page_down(struct SidebarWindowData *wdata)
185 {
186  if (ARRAY_EMPTY(&wdata->entries) || (wdata->bot_index < 0))
187  return false;
188 
189  int orig_hil_index = wdata->hil_index;
190 
191  wdata->hil_index = wdata->bot_index;
192  select_next(wdata);
193  /* If the rest of the entries are hidden, go up to the last unhidden one */
194  if ((*ARRAY_GET(&wdata->entries, wdata->hil_index))->is_hidden)
195  select_prev(wdata);
196 
197  return (orig_hil_index != wdata->hil_index);
198 }
199 
205 static bool select_page_up(struct SidebarWindowData *wdata)
206 {
207  if (ARRAY_EMPTY(&wdata->entries) || (wdata->top_index < 0))
208  return false;
209 
210  int orig_hil_index = wdata->hil_index;
211 
212  wdata->hil_index = wdata->top_index;
213  select_prev(wdata);
214  /* If the rest of the entries are hidden, go down to the last unhidden one */
215  if ((*ARRAY_GET(&wdata->entries, wdata->hil_index))->is_hidden)
216  select_next(wdata);
217 
218  return (orig_hil_index != wdata->hil_index);
219 }
220 
226 static bool select_first(struct SidebarWindowData *wdata)
227 {
228  if (ARRAY_EMPTY(&wdata->entries) || (wdata->hil_index < 0))
229  return false;
230 
231  int orig_hil_index = wdata->hil_index;
232 
233  wdata->hil_index = 0;
234  if ((*ARRAY_GET(&wdata->entries, wdata->hil_index))->is_hidden)
235  if (!select_next(wdata))
236  wdata->hil_index = orig_hil_index;
237 
238  return (orig_hil_index != wdata->hil_index);
239 }
240 
246 static bool select_last(struct SidebarWindowData *wdata)
247 {
248  if (ARRAY_EMPTY(&wdata->entries) || (wdata->hil_index < 0))
249  return false;
250 
251  int orig_hil_index = wdata->hil_index;
252 
253  wdata->hil_index = ARRAY_SIZE(&wdata->entries);
254  if (!select_prev(wdata))
255  wdata->hil_index = orig_hil_index;
256 
257  return (orig_hil_index != wdata->hil_index);
258 }
259 
265 void sb_change_mailbox(struct MuttWindow *win, int op)
266 {
267  if (!mutt_window_is_visible(win))
268  return;
269 
270  struct SidebarWindowData *wdata = sb_wdata_get(win);
271  if (!wdata)
272  return;
273 
274  if (wdata->hil_index < 0) /* It'll get reset on the next draw */
275  return;
276 
277  bool changed = false;
278  switch (op)
279  {
280  case OP_SIDEBAR_FIRST:
281  changed = select_first(wdata);
282  break;
283  case OP_SIDEBAR_LAST:
284  changed = select_last(wdata);
285  break;
286  case OP_SIDEBAR_NEXT:
287  changed = select_next(wdata);
288  break;
289  case OP_SIDEBAR_NEXT_NEW:
290  changed = select_next_new(wdata, C_SidebarNextNewWrap);
291  break;
292  case OP_SIDEBAR_PAGE_DOWN:
293  changed = select_page_down(wdata);
294  break;
295  case OP_SIDEBAR_PAGE_UP:
296  changed = select_page_up(wdata);
297  break;
298  case OP_SIDEBAR_PREV:
299  changed = select_prev(wdata);
300  break;
301  case OP_SIDEBAR_PREV_NEW:
302  changed = select_prev_new(wdata, C_SidebarNextNewWrap);
303  break;
304  default:
305  return;
306  }
307  if (changed)
308  win->actions |= WA_RECALC;
309 }
Convenience wrapper for the gui headers.
int top_index
First mailbox visible in sidebar.
Definition: private.h:65
#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:61
A division of the screen.
Definition: mutt_window.h:115
Info about folders in the sidebar.
Definition: private.h:38
int hil_index
Highlighted mailbox.
Definition: private.h:67
All user-callable functions.
WindowActionFlags actions
Actions to be performed, e.g. WA_RECALC.
Definition: mutt_window.h:125
#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:657
#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
Convenience wrapper for the library headers.
int bot_index
Last mailbox visible in sidebar.
Definition: private.h:68
void * wdata
Private data.
Definition: mutt_window.h:138
#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:107