1 /**
2  * @file
3  * Container for Accounts, Notifications
4  *
5  * @authors
6  * Copyright (C) 2019 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 core_neomutt NeoMutt object
25  *
26  * Container for Accounts, Notifications
27  */
28 
29 #include "config.h"
30 #include <stddef.h>
31 #include "mutt/lib.h"
32 #include "config/lib.h"
33 #include "neomutt.h"
34 #include "account.h"
35 #include "mailbox.h"
36 
37 struct NeoMutt *NeoMutt; ///< Global NeoMutt object
38 
39 /**
40  * neomutt_new - Create the main NeoMutt object
41  * @param cs Config Set
42  * @retval ptr New NeoMutt
43  */
neomutt_new(struct ConfigSet * cs)44 struct NeoMutt *neomutt_new(struct ConfigSet *cs)
45 {
46   if (!cs)
47     return NULL;
48 
49   struct NeoMutt *n = mutt_mem_calloc(1, sizeof(*NeoMutt));
50 
51   TAILQ_INIT(&n->accounts);
52   n->notify = notify_new();
53   n->sub = cs_subset_new(NULL, NULL, n->notify);
54   n->sub->cs = cs;
55   n->sub->scope = SET_SCOPE_NEOMUTT;
56 
57   return n;
58 }
59 
60 /**
61  * neomutt_free - Free a NeoMutt
62  * @param[out] ptr NeoMutt to free
63  */
neomutt_free(struct NeoMutt ** ptr)64 void neomutt_free(struct NeoMutt **ptr)
65 {
66   if (!ptr || !*ptr)
67     return;
68 
69   struct NeoMutt *n = *ptr;
70 
71   neomutt_account_remove(n, NULL);
72   cs_subset_free(&n->sub);
73   notify_free(&n->notify);
74 
75   FREE(ptr);
76 }
77 
78 /**
79  * neomutt_account_add - Add an Account to the global list
80  * @param n NeoMutt
81  * @param a Account to add
82  * @retval true Account was added
83  */
neomutt_account_add(struct NeoMutt * n,struct Account * a)84 bool neomutt_account_add(struct NeoMutt *n, struct Account *a)
85 {
86   if (!n || !a)
87     return false;
88 
89   TAILQ_INSERT_TAIL(&n->accounts, a, entries);
90   notify_set_parent(a->notify, n->notify);
91 
92   mutt_debug(LL_NOTIFY, "NT_ACCOUNT_ADD: %s %p\n", mailbox_get_type_name(a->type), a);
93   struct EventAccount ev_a = { a };
94   notify_send(n->notify, NT_ACCOUNT, NT_ACCOUNT_ADD, &ev_a);
95   return true;
96 }
97 
98 /**
99  * neomutt_account_remove - Remove an Account from the global list
100  * @param n NeoMutt
101  * @param a Account to remove
102  * @retval true Account was removed
103  *
104  * @note If a is NULL, all the Accounts will be removed
105  */
neomutt_account_remove(struct NeoMutt * n,struct Account * a)106 bool neomutt_account_remove(struct NeoMutt *n, struct Account *a)
107 {
108   if (!n || TAILQ_EMPTY(&n->accounts))
109     return false;
110 
111   if (!a)
112   {
113     mutt_debug(LL_NOTIFY, "NT_ACCOUNT_DELETE_ALL\n");
114     struct EventAccount ev_a = { NULL };
115     notify_send(n->notify, NT_ACCOUNT, NT_ACCOUNT_DELETE_ALL, &ev_a);
116   }
117 
118   bool result = false;
119   struct Account *np = NULL;
120   struct Account *tmp = NULL;
121   TAILQ_FOREACH_SAFE(np, &n->accounts, entries, tmp)
122   {
123     if (a && (np != a))
124       continue;
125 
126     TAILQ_REMOVE(&n->accounts, np, entries);
127     account_free(&np);
128     result = true;
129     if (a)
130       break;
131   }
132   return result;
133 }
134 
135 /**
136  * neomutt_mailboxlist_clear - Free a Mailbox List
137  * @param ml Mailbox List to free
138  *
139  * @note The Mailboxes aren't freed
140  */
neomutt_mailboxlist_clear(struct MailboxList * ml)141 void neomutt_mailboxlist_clear(struct MailboxList *ml)
142 {
143   if (!ml)
144     return;
145 
146   struct MailboxNode *mn = NULL;
147   struct MailboxNode *tmp = NULL;
148   STAILQ_FOREACH_SAFE(mn, ml, entries, tmp)
149   {
150     STAILQ_REMOVE(ml, mn, MailboxNode, entries);
151     FREE(&mn);
152   }
153 }
154 
155 /**
156  * neomutt_mailboxlist_get_all - Get a List of all Mailboxes
157  * @param head List to store the Mailboxes
158  * @param n    NeoMutt
159  * @param type Type of Account to match, see #MailboxType
160  * @retval num Number of Mailboxes in the List
161  *
162  * @note If type is #MUTT_MAILBOX_ANY then all Mailbox types will be matched
163  */
neomutt_mailboxlist_get_all(struct MailboxList * head,struct NeoMutt * n,enum MailboxType type)164 size_t neomutt_mailboxlist_get_all(struct MailboxList *head, struct NeoMutt *n,
165                                    enum MailboxType type)
166 {
167   if (!n)
168     return 0;
169 
170   size_t count = 0;
171   struct Account *a = NULL;
172   struct MailboxNode *mn = NULL;
173 
174   TAILQ_FOREACH(a, &n->accounts, entries)
175   {
176     if ((type > MUTT_UNKNOWN) && (a->type != type))
177       continue;
178 
179     STAILQ_FOREACH(mn, &a->mailboxes, entries)
180     {
181       struct MailboxNode *mn2 = mutt_mem_calloc(1, sizeof(*mn2));
182       mn2->mailbox = mn->mailbox;
183       STAILQ_INSERT_TAIL(head, mn2, entries);
184       count++;
185     }
186   }
187 
188   return count;
189 }
190