Coverage Report

Created: 2023-09-25 07:17

/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
}