1 /**
2 * @file
3 * Postponed Email Selection Dialog
4 *
5 * @authors
6 * Copyright (C) 1996-2002,2012-2013 Michael R. Elkins <me@mutt.org>
7 * Copyright (C) 1999-2002,2004 Thomas Roessler <roessler@does-not-exist.org>
8 *
9 * @copyright
10 * This program is free software: you can redistribute it and/or modify it under
11 * the terms of the GNU General Public License as published by the Free Software
12 * Foundation, either version 2 of the License, or (at your option) any later
13 * version.
14 *
15 * This program is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
18 * details.
19 *
20 * You should have received a copy of the GNU General Public License along with
21 * this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 /**
25 * @page neo_dlg_postpone Postponed Email Selection Dialog
26 *
27 * The Postponed Email Selection Dialog lets the user set a postponed (draft)
28 * email.
29 *
30 * This is a @ref gui_simple
31 *
32 * ## Windows
33 *
34 * | Name | Type | See Also |
35 * | :------------------------------- | :-------------- | :--------------------------- |
36 * | Postponed Email Selection Dialog | WT_DLG_POSTPONE | dlg_select_postponed_email() |
37 *
38 * **Parent**
39 * - @ref gui_dialog
40 *
41 * **Children**
42 * - See: @ref gui_simple
43 *
44 * ## Data
45 * - #Menu
46 * - #Menu::mdata
47 * - #Mailbox
48 *
49 * The @ref gui_simple holds a Menu. The Autocrypt Account Dialog stores its
50 * data (#Mailbox) in Menu::mdata.
51 *
52 * ## Events
53 *
54 * Once constructed, it is controlled by the following events:
55 *
56 * | Event Type | Handler |
57 * | :---------- | :-------------------------- |
58 * | #NT_CONFIG | postponed_config_observer() |
59 * | #NT_WINDOW | postponed_window_observer() |
60 *
61 * The Postponed Email Selection Dialog doesn't have any specific colours, so
62 * it doesn't need to support #NT_COLOR.
63 *
64 * The Postponed Email Selection Dialog does not implement MuttWindow::recalc()
65 * or MuttWindow::repaint().
66 *
67 * Some other events are handled by the @ref gui_simple.
68 */
69
70 #include "config.h"
71 #include <stdbool.h>
72 #include <stdio.h>
73 #include "mutt/lib.h"
74 #include "config/lib.h"
75 #include "core/lib.h"
76 #include "gui/lib.h"
77 #include "mutt.h"
78 #include "menu/lib.h"
79 #include "pattern/lib.h"
80 #include "format_flags.h"
81 #include "hdrline.h"
82 #include "opcodes.h"
83 #include "protos.h"
84
85 struct Email;
86
87 /// Help Bar for the Postponed email selection dialog
88 static const struct Mapping PostponeHelp[] = {
89 // clang-format off
90 { N_("Exit"), OP_EXIT },
91 { N_("Del"), OP_DELETE },
92 { N_("Undel"), OP_UNDELETE },
93 { N_("Help"), OP_HELP },
94 { NULL, 0 },
95 // clang-format on
96 };
97
98 /**
99 * post_make_entry - Format a menu item for the email list - Implements Menu::make_entry() - @ingroup menu_make_entry
100 */
post_make_entry(struct Menu * menu,char * buf,size_t buflen,int line)101 static void post_make_entry(struct Menu *menu, char *buf, size_t buflen, int line)
102 {
103 struct Mailbox *m = menu->mdata;
104
105 const char *const c_index_format =
106 cs_subset_string(NeoMutt->sub, "index_format");
107 mutt_make_string(buf, buflen, menu->win->state.cols, NONULL(c_index_format),
108 m, -1, m->emails[line], MUTT_FORMAT_ARROWCURSOR, NULL);
109 }
110
111 /**
112 * postponed_config_observer - Notification that a Config Variable has changed - Implements ::observer_t - @ingroup observer_api
113 *
114 * The Address Book Window is affected by changes to `$sort_postponed`.
115 */
postponed_config_observer(struct NotifyCallback * nc)116 static int postponed_config_observer(struct NotifyCallback *nc)
117 {
118 if ((nc->event_type != NT_CONFIG) || !nc->global_data || !nc->event_data)
119 return -1;
120
121 struct EventConfig *ev_c = nc->event_data;
122
123 if (!mutt_str_equal(ev_c->name, "index_format") && !mutt_str_equal(ev_c->name, "sort"))
124 return 0;
125
126 struct Menu *menu = nc->global_data;
127 menu_queue_redraw(menu, MENU_REDRAW_FULL);
128 mutt_debug(LL_DEBUG5, "config done, request WA_RECALC, MENU_REDRAW_FULL\n");
129
130 return 0;
131 }
132
133 /**
134 * postponed_window_observer - Notification that a Window has changed - Implements ::observer_t - @ingroup observer_api
135 *
136 * This function is triggered by changes to the windows.
137 *
138 * - Delete (this window): clean up the resources held by the Help Bar
139 */
postponed_window_observer(struct NotifyCallback * nc)140 static int postponed_window_observer(struct NotifyCallback *nc)
141 {
142 if ((nc->event_type != NT_WINDOW) || !nc->global_data || !nc->event_data)
143 return -1;
144
145 if (nc->event_subtype != NT_WINDOW_DELETE)
146 return 0;
147
148 struct MuttWindow *win_menu = nc->global_data;
149 struct EventWindow *ev_w = nc->event_data;
150 if (ev_w->win != win_menu)
151 return 0;
152
153 struct Menu *menu = win_menu->wdata;
154
155 notify_observer_remove(NeoMutt->notify, postponed_config_observer, menu);
156 notify_observer_remove(win_menu->notify, postponed_window_observer, win_menu);
157
158 mutt_debug(LL_DEBUG5, "window delete done\n");
159 return 0;
160 }
161
162 /**
163 * dlg_select_postponed_email - Create a Menu to select a postponed message
164 * @param m Mailbox
165 * @retval ptr Email
166 */
dlg_select_postponed_email(struct Mailbox * m)167 struct Email *dlg_select_postponed_email(struct Mailbox *m)
168 {
169 int r = -1;
170 bool done = false;
171
172 struct MuttWindow *dlg = simple_dialog_new(MENU_POSTPONE, WT_DLG_POSTPONE, PostponeHelp);
173
174 struct Menu *menu = dlg->wdata;
175 menu->make_entry = post_make_entry;
176 menu->max = m->msg_count;
177 menu->mdata = m;
178 menu->custom_search = true;
179
180 struct MuttWindow *win_menu = menu->win;
181
182 // NT_COLOR is handled by the SimpleDialog
183 notify_observer_add(NeoMutt->notify, NT_CONFIG, postponed_config_observer, menu);
184 notify_observer_add(win_menu->notify, NT_WINDOW, postponed_window_observer, win_menu);
185
186 struct MuttWindow *sbar = window_find_child(dlg, WT_STATUS_BAR);
187 sbar_set_title(sbar, _("Postponed Messages"));
188
189 /* The postponed mailbox is setup to have sorting disabled, but the global
190 * `$sort` variable may indicate something different. Sorting has to be
191 * disabled while the postpone menu is being displayed. */
192 const short c_sort = cs_subset_sort(NeoMutt->sub, "sort");
193 cs_subset_str_native_set(NeoMutt->sub, "sort", SORT_ORDER, NULL);
194
195 while (!done)
196 {
197 const int op = menu_loop(menu);
198 switch (op)
199 {
200 case OP_DELETE:
201 case OP_UNDELETE:
202 {
203 const int index = menu_get_index(menu);
204 /* should deleted draft messages be saved in the trash folder? */
205 mutt_set_flag(m, m->emails[index], MUTT_DELETE, (op == OP_DELETE));
206 PostCount = m->msg_count - m->msg_deleted;
207 const bool c_resolve = cs_subset_bool(NeoMutt->sub, "resolve");
208 if (c_resolve && (index < (menu->max - 1)))
209 {
210 menu_set_index(menu, index + 1);
211 if (index >= (menu->top + menu->pagelen))
212 {
213 menu->top = index;
214 menu_queue_redraw(menu, MENU_REDRAW_INDEX);
215 }
216 }
217 else
218 menu_queue_redraw(menu, MENU_REDRAW_CURRENT);
219 break;
220 }
221
222 // All search operations must exist to show the menu
223 case OP_SEARCH_REVERSE:
224 case OP_SEARCH_NEXT:
225 case OP_SEARCH_OPPOSITE:
226 case OP_SEARCH:
227 {
228 int index = menu_get_index(menu);
229 index = mutt_search_command(m, menu, index, op);
230 if (index != -1)
231 menu_set_index(menu, index);
232 break;
233 }
234
235 case OP_GENERIC_SELECT_ENTRY:
236 r = menu_get_index(menu);
237 done = true;
238 break;
239
240 case OP_EXIT:
241 done = true;
242 break;
243 }
244 }
245
246 cs_subset_str_native_set(NeoMutt->sub, "sort", c_sort, NULL);
247 simple_dialog_free(&dlg);
248
249 return (r > -1) ? m->emails[r] : NULL;
250 }
251