/src/neomutt/index/shared_data.c
Line | Count | Source (jump to first uncovered line) |
1 | | /** |
2 | | * @file |
3 | | * Data shared between Index, Pager and Sidebar |
4 | | * |
5 | | * @authors |
6 | | * Copyright (C) 2021 Richard Russon <rich@flatcap.org> |
7 | | * |
8 | | * @copyright |
9 | | * This program is free software: you can redistribute it and/or modify it under |
10 | | * the terms of the GNU General Public License as published by the Free Software |
11 | | * Foundation, either version 2 of the License, or (at your option) any later |
12 | | * version. |
13 | | * |
14 | | * This program is distributed in the hope that it will be useful, but WITHOUT |
15 | | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
16 | | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
17 | | * details. |
18 | | * |
19 | | * You should have received a copy of the GNU General Public License along with |
20 | | * this program. If not, see <http://www.gnu.org/licenses/>. |
21 | | */ |
22 | | |
23 | | /** |
24 | | * @page index_shared_data Shared data |
25 | | * |
26 | | * Data shared between Index, Pager and Sidebar |
27 | | */ |
28 | | |
29 | | #include "config.h" |
30 | | #include <stdbool.h> |
31 | | #include "mutt/lib.h" |
32 | | #include "email/lib.h" |
33 | | #include "core/lib.h" |
34 | | #include "shared_data.h" |
35 | | #include "lib.h" |
36 | | #include "pattern/lib.h" |
37 | | #include "mview.h" |
38 | | |
39 | | /** |
40 | | * index_shared_mview_observer - Notification that the MailboxView has changed - Implements ::observer_t - @ingroup observer_api |
41 | | */ |
42 | | static int index_shared_mview_observer(struct NotifyCallback *nc) |
43 | 0 | { |
44 | 0 | if (nc->event_type != NT_MVIEW) |
45 | 0 | return 0; |
46 | 0 | if (!nc->global_data || !nc->event_data) |
47 | 0 | return -1; |
48 | 0 | if (nc->event_subtype == NT_MVIEW_ADD) |
49 | 0 | return 0; |
50 | | |
51 | 0 | struct EventMview *ev_m = nc->event_data; |
52 | 0 | struct IndexSharedData *shared = nc->global_data; |
53 | 0 | if (ev_m->mv != shared->mailbox_view) |
54 | 0 | return 0; |
55 | | |
56 | 0 | if (nc->event_subtype == NT_MVIEW_DELETE) |
57 | 0 | shared->mailbox_view = NULL; |
58 | |
|
59 | 0 | mutt_debug(LL_NOTIFY, "relay NT_MVIEW to shared data observers\n"); |
60 | 0 | notify_send(shared->notify, nc->event_type, nc->event_subtype, nc->event_data); |
61 | 0 | return 0; |
62 | 0 | } |
63 | | |
64 | | /** |
65 | | * index_shared_account_observer - Notification that an Account has changed - Implements ::observer_t - @ingroup observer_api |
66 | | */ |
67 | | static int index_shared_account_observer(struct NotifyCallback *nc) |
68 | 0 | { |
69 | 0 | if (nc->event_type != NT_ACCOUNT) |
70 | 0 | return 0; |
71 | 0 | if (!nc->global_data || !nc->event_data) |
72 | 0 | return -1; |
73 | 0 | if (nc->event_subtype == NT_ACCOUNT_ADD) |
74 | 0 | return 0; |
75 | | |
76 | 0 | struct EventAccount *ev_a = nc->event_data; |
77 | 0 | struct IndexSharedData *shared = nc->global_data; |
78 | 0 | if (ev_a->account != shared->account) |
79 | 0 | return 0; |
80 | | |
81 | 0 | if (nc->event_subtype == NT_ACCOUNT_DELETE) |
82 | 0 | shared->account = NULL; |
83 | |
|
84 | 0 | mutt_debug(LL_NOTIFY, "relay NT_ACCOUNT to shared data observers\n"); |
85 | 0 | notify_send(shared->notify, nc->event_type, nc->event_subtype, nc->event_data); |
86 | 0 | return 0; |
87 | 0 | } |
88 | | |
89 | | /** |
90 | | * index_shared_mailbox_observer - Notification that a Mailbox has changed - Implements ::observer_t - @ingroup observer_api |
91 | | */ |
92 | | static int index_shared_mailbox_observer(struct NotifyCallback *nc) |
93 | 0 | { |
94 | 0 | if (nc->event_type != NT_MAILBOX) |
95 | 0 | return 0; |
96 | 0 | if (!nc->global_data || !nc->event_data) |
97 | 0 | return -1; |
98 | 0 | if (nc->event_subtype == NT_MAILBOX_ADD) |
99 | 0 | return 0; |
100 | | |
101 | 0 | struct EventMailbox *ev_m = nc->event_data; |
102 | 0 | struct IndexSharedData *shared = nc->global_data; |
103 | 0 | if (ev_m->mailbox != shared->mailbox) |
104 | 0 | return 0; |
105 | | |
106 | 0 | if (nc->event_subtype == NT_MAILBOX_DELETE) |
107 | 0 | shared->mailbox = NULL; |
108 | |
|
109 | 0 | mutt_debug(LL_NOTIFY, "relay NT_MAILBOX to shared data observers\n"); |
110 | 0 | notify_send(shared->notify, nc->event_type, nc->event_subtype, nc->event_data); |
111 | 0 | return 0; |
112 | 0 | } |
113 | | |
114 | | /** |
115 | | * index_shared_email_observer - Notification that an Email has changed - Implements ::observer_t - @ingroup observer_api |
116 | | */ |
117 | | static int index_shared_email_observer(struct NotifyCallback *nc) |
118 | 0 | { |
119 | 0 | if (nc->event_type != NT_EMAIL) |
120 | 0 | return 0; |
121 | 0 | if (!nc->global_data || !nc->event_data) |
122 | 0 | return -1; |
123 | 0 | if (nc->event_subtype == NT_EMAIL_ADD) |
124 | 0 | return 0; |
125 | | |
126 | 0 | struct EventEmail *ev_e = nc->event_data; |
127 | 0 | struct IndexSharedData *shared = nc->global_data; |
128 | 0 | bool match = false; |
129 | 0 | for (int i = 0; i < ev_e->num_emails; i++) |
130 | 0 | { |
131 | 0 | if (ev_e->emails[i] == shared->email) |
132 | 0 | { |
133 | 0 | match = true; |
134 | 0 | break; |
135 | 0 | } |
136 | 0 | } |
137 | |
|
138 | 0 | if (!match) |
139 | 0 | return 0; |
140 | | |
141 | 0 | if (nc->event_subtype == NT_EMAIL_DELETE) |
142 | 0 | { |
143 | 0 | shared->email = NULL; |
144 | 0 | mutt_debug(LL_NOTIFY, "NT_INDEX_EMAIL: %p\n", (void *) shared->email); |
145 | 0 | notify_send(shared->notify, NT_INDEX, NT_INDEX_EMAIL, shared); |
146 | 0 | } |
147 | |
|
148 | 0 | mutt_debug(LL_NOTIFY, "relay NT_EMAIL %p to shared data observers\n", |
149 | 0 | (void *) shared->email); |
150 | 0 | notify_send(shared->notify, nc->event_type, nc->event_subtype, nc->event_data); |
151 | 0 | return 0; |
152 | 0 | } |
153 | | |
154 | | /** |
155 | | * index_shared_data_set_mview - Set the MailboxView for the Index and friends |
156 | | * @param shared Shared Index data |
157 | | * @param mv Mailbox View, may be NULL |
158 | | */ |
159 | | void index_shared_data_set_mview(struct IndexSharedData *shared, struct MailboxView *mv) |
160 | 0 | { |
161 | 0 | if (!shared) |
162 | 0 | return; |
163 | | |
164 | 0 | NotifyIndex subtype = NT_INDEX_NO_FLAGS; |
165 | |
|
166 | 0 | if (shared->mailbox_view != mv) |
167 | 0 | { |
168 | 0 | if (shared->mailbox_view) |
169 | 0 | { |
170 | 0 | notify_observer_remove(shared->mailbox_view->notify, |
171 | 0 | index_shared_mview_observer, shared); |
172 | 0 | } |
173 | |
|
174 | 0 | shared->mailbox_view = mv; |
175 | 0 | subtype |= NT_INDEX_MVIEW; |
176 | |
|
177 | 0 | if (mv) |
178 | 0 | notify_observer_add(mv->notify, NT_MVIEW, index_shared_mview_observer, shared); |
179 | 0 | } |
180 | |
|
181 | 0 | struct Mailbox *m = mview_mailbox(mv); |
182 | 0 | if (shared->mailbox != m) |
183 | 0 | { |
184 | 0 | if (shared->mailbox) |
185 | 0 | notify_observer_remove(shared->mailbox->notify, index_shared_mailbox_observer, shared); |
186 | |
|
187 | 0 | shared->mailbox = m; |
188 | 0 | shared->email = NULL; |
189 | 0 | shared->email_seq = 0; |
190 | 0 | subtype |= NT_INDEX_MAILBOX | NT_INDEX_EMAIL; |
191 | |
|
192 | 0 | if (m) |
193 | 0 | notify_observer_add(m->notify, NT_MAILBOX, index_shared_mailbox_observer, shared); |
194 | 0 | } |
195 | |
|
196 | 0 | struct Account *a = m ? m->account : NULL; |
197 | 0 | if (shared->account != a) |
198 | 0 | { |
199 | 0 | if (shared->account) |
200 | 0 | notify_observer_remove(shared->account->notify, index_shared_account_observer, shared); |
201 | |
|
202 | 0 | shared->account = a; |
203 | 0 | subtype |= NT_INDEX_ACCOUNT; |
204 | |
|
205 | 0 | if (a) |
206 | 0 | notify_observer_add(a->notify, NT_ACCOUNT, index_shared_account_observer, shared); |
207 | 0 | } |
208 | |
|
209 | 0 | struct ConfigSubset *sub = NeoMutt->sub; |
210 | | #if 0 |
211 | | if (m) |
212 | | sub = m->sub; |
213 | | else if (a) |
214 | | sub = a->sub; |
215 | | #endif |
216 | 0 | if (shared->sub != sub) |
217 | 0 | { |
218 | 0 | shared->sub = sub; |
219 | 0 | subtype |= NT_INDEX_SUBSET; |
220 | 0 | } |
221 | |
|
222 | 0 | if (subtype != NT_INDEX_NO_FLAGS) |
223 | 0 | { |
224 | 0 | mutt_debug(LL_NOTIFY, "NT_INDEX: %p\n", (void *) shared); |
225 | 0 | notify_send(shared->notify, NT_INDEX, subtype, shared); |
226 | 0 | } |
227 | 0 | } |
228 | | |
229 | | /** |
230 | | * index_shared_data_set_email - Set the current Email for the Index and friends |
231 | | * @param shared Shared Index data |
232 | | * @param e Current Email, may be NULL |
233 | | */ |
234 | | void index_shared_data_set_email(struct IndexSharedData *shared, struct Email *e) |
235 | 0 | { |
236 | 0 | if (!shared) |
237 | 0 | return; |
238 | | |
239 | 0 | size_t seq = e ? e->sequence : 0; |
240 | 0 | if ((shared->email != e) || (shared->email_seq != seq)) |
241 | 0 | { |
242 | 0 | if (shared->email) |
243 | 0 | notify_observer_remove(shared->email->notify, index_shared_email_observer, shared); |
244 | |
|
245 | 0 | shared->email = e; |
246 | 0 | shared->email_seq = seq; |
247 | |
|
248 | 0 | if (e) |
249 | 0 | notify_observer_add(e->notify, NT_EMAIL, index_shared_email_observer, shared); |
250 | |
|
251 | 0 | mutt_debug(LL_NOTIFY, "NT_INDEX_EMAIL: %p\n", (void *) shared->email); |
252 | 0 | notify_send(shared->notify, NT_INDEX, NT_INDEX_EMAIL, shared); |
253 | 0 | } |
254 | 0 | } |
255 | | |
256 | | /** |
257 | | * index_shared_data_is_cur_email - Check whether an email is the currently selected Email |
258 | | * @param shared Shared Index data |
259 | | * @param e Email to check |
260 | | * @retval true e is current |
261 | | * @retval false e is not current |
262 | | */ |
263 | | bool index_shared_data_is_cur_email(const struct IndexSharedData *shared, |
264 | | const struct Email *e) |
265 | 0 | { |
266 | 0 | if (!shared) |
267 | 0 | return false; |
268 | | |
269 | 0 | return shared->email_seq == e->sequence; |
270 | 0 | } |
271 | | |
272 | | /** |
273 | | * index_shared_data_free - Free Shared Index Data - Implements MuttWindow::wdata_free() - @ingroup window_wdata_free |
274 | | * |
275 | | * Only `notify` is owned by IndexSharedData and should be freed. |
276 | | */ |
277 | | void index_shared_data_free(struct MuttWindow *win, void **ptr) |
278 | 0 | { |
279 | 0 | if (!ptr || !*ptr) |
280 | 0 | return; |
281 | | |
282 | 0 | struct IndexSharedData *shared = *ptr; |
283 | |
|
284 | 0 | mutt_debug(LL_NOTIFY, "NT_INDEX_DELETE: %p\n", (void *) shared); |
285 | 0 | notify_send(shared->notify, NT_INDEX, NT_INDEX_DELETE, shared); |
286 | 0 | notify_free(&shared->notify); |
287 | |
|
288 | 0 | if (shared->account) |
289 | 0 | notify_observer_remove(shared->account->notify, index_shared_account_observer, shared); |
290 | 0 | if (shared->mailbox_view) |
291 | 0 | notify_observer_remove(shared->mailbox_view->notify, index_shared_mview_observer, shared); |
292 | 0 | if (shared->mailbox) |
293 | 0 | notify_observer_remove(shared->mailbox->notify, index_shared_mailbox_observer, shared); |
294 | 0 | if (shared->email) |
295 | 0 | notify_observer_remove(shared->email->notify, index_shared_email_observer, shared); |
296 | |
|
297 | 0 | search_state_free(&shared->search_state); |
298 | |
|
299 | 0 | FREE(ptr); |
300 | 0 | } |
301 | | |
302 | | /** |
303 | | * index_shared_data_new - Create new Index Data |
304 | | * @retval ptr New IndexSharedData |
305 | | */ |
306 | | struct IndexSharedData *index_shared_data_new(void) |
307 | 0 | { |
308 | 0 | struct IndexSharedData *shared = mutt_mem_calloc(1, sizeof(struct IndexSharedData)); |
309 | |
|
310 | 0 | shared->notify = notify_new(); |
311 | 0 | shared->sub = NeoMutt->sub; |
312 | 0 | shared->search_state = search_state_new(); |
313 | |
|
314 | 0 | mutt_debug(LL_NOTIFY, "NT_INDEX_ADD: %p\n", (void *) shared); |
315 | 0 | notify_send(shared->notify, NT_INDEX, NT_INDEX_ADD, shared); |
316 | |
|
317 | 0 | return shared; |
318 | 0 | } |