/src/neomutt/compose/attach.c
Line | Count | Source (jump to first uncovered line) |
1 | | /** |
2 | | * @file |
3 | | * Compose Attachments |
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 compose_attach Attachments window |
25 | | * |
26 | | * The Compose Attachments Window displays the attachments of an email. |
27 | | * |
28 | | * ## Windows |
29 | | * |
30 | | * | Name | Type | See Also | |
31 | | * | :------------------------- | :-------- | :----------- | |
32 | | * | Compose Attachments Window | WT_MENU | attach_new() | |
33 | | * |
34 | | * **Parent** |
35 | | * - @ref compose_dialog |
36 | | * |
37 | | * **Children** |
38 | | * |
39 | | * None. |
40 | | * |
41 | | * ## Data |
42 | | * - #ComposeAttachData |
43 | | * |
44 | | * The Compose Attachments Window stores its data (#ComposeAttachData) in |
45 | | * Menu::mdata. |
46 | | * |
47 | | * ## Events |
48 | | * |
49 | | * Once constructed, it is controlled by the following events: |
50 | | * |
51 | | * | Event Type | Handler | |
52 | | * | :-------------------- | :------------------------ | |
53 | | * | #NT_CONFIG | attach_config_observer() | |
54 | | * | #NT_EMAIL | attach_email_observer() | |
55 | | * | #NT_WINDOW | attach_window_observer() | |
56 | | */ |
57 | | |
58 | | #include "config.h" |
59 | | #include <stddef.h> |
60 | | #include <stdbool.h> |
61 | | #include <stdint.h> |
62 | | #include "private.h" |
63 | | #include "mutt/lib.h" |
64 | | #include "config/lib.h" |
65 | | #include "email/lib.h" |
66 | | #include "core/lib.h" |
67 | | #include "gui/lib.h" |
68 | | #include "attach/lib.h" |
69 | | #include "convert/lib.h" |
70 | | #include "menu/lib.h" |
71 | | #include "attach_data.h" |
72 | | #include "format_flags.h" |
73 | | #include "muttlib.h" |
74 | | #include "shared_data.h" |
75 | | |
76 | | /** |
77 | | * cum_attachs_size - Cumulative Attachments Size |
78 | | * @param sub Config Subset |
79 | | * @param adata Attachment data |
80 | | * @retval num Bytes in attachments |
81 | | * |
82 | | * Returns the total number of bytes used by the attachments in the attachment |
83 | | * list _after_ content-transfer-encodings have been applied. |
84 | | */ |
85 | | unsigned long cum_attachs_size(struct ConfigSubset *sub, struct ComposeAttachData *adata) |
86 | 0 | { |
87 | 0 | if (!adata || !adata->actx) |
88 | 0 | return 0; |
89 | | |
90 | 0 | size_t s = 0; |
91 | 0 | struct Content *info = NULL; |
92 | 0 | struct Body *b = NULL; |
93 | 0 | struct AttachCtx *actx = adata->actx; |
94 | 0 | struct AttachPtr **idx = actx->idx; |
95 | |
|
96 | 0 | for (unsigned short i = 0; i < actx->idxlen; i++) |
97 | 0 | { |
98 | 0 | b = idx[i]->body; |
99 | |
|
100 | 0 | if (!b->content) |
101 | 0 | b->content = mutt_get_content_info(b->filename, b, sub); |
102 | |
|
103 | 0 | info = b->content; |
104 | 0 | if (info) |
105 | 0 | { |
106 | 0 | switch (b->encoding) |
107 | 0 | { |
108 | 0 | case ENC_QUOTED_PRINTABLE: |
109 | 0 | s += 3 * (info->lobin + info->hibin) + info->ascii + info->crlf; |
110 | 0 | break; |
111 | 0 | case ENC_BASE64: |
112 | 0 | s += (4 * (info->lobin + info->hibin + info->ascii + info->crlf)) / 3; |
113 | 0 | break; |
114 | 0 | default: |
115 | 0 | s += info->lobin + info->hibin + info->ascii + info->crlf; |
116 | 0 | break; |
117 | 0 | } |
118 | 0 | } |
119 | 0 | } |
120 | | |
121 | 0 | return s; |
122 | 0 | } |
123 | | |
124 | | /** |
125 | | * attach_email_observer - Notification that the Email has changed - Implements ::observer_t - @ingroup observer_api |
126 | | */ |
127 | | static int attach_email_observer(struct NotifyCallback *nc) |
128 | 0 | { |
129 | 0 | if (nc->event_type != NT_EMAIL) |
130 | 0 | return 0; |
131 | 0 | if (!nc->global_data) |
132 | 0 | return -1; |
133 | 0 | if (nc->event_subtype != NT_EMAIL_CHANGE_ATTACH) |
134 | 0 | return 0; |
135 | | |
136 | 0 | struct MuttWindow *win_attach = nc->global_data; |
137 | |
|
138 | 0 | win_attach->actions |= WA_RECALC; |
139 | 0 | mutt_debug(LL_DEBUG5, "compose done, request WA_RECALC\n"); |
140 | |
|
141 | 0 | return 0; |
142 | 0 | } |
143 | | |
144 | | /** |
145 | | * attach_config_observer - Notification that a Config Variable has changed - Implements ::observer_t - @ingroup observer_api |
146 | | */ |
147 | | int attach_config_observer(struct NotifyCallback *nc) |
148 | 0 | { |
149 | 0 | if (nc->event_type != NT_CONFIG) |
150 | 0 | return 0; |
151 | 0 | if (!nc->global_data || !nc->event_data) |
152 | 0 | return -1; |
153 | | |
154 | 0 | struct EventConfig *ev_c = nc->event_data; |
155 | 0 | if (!mutt_str_equal(ev_c->name, "attach_format")) |
156 | 0 | return 0; |
157 | | |
158 | 0 | struct MuttWindow *win_attach = nc->global_data; |
159 | 0 | win_attach->actions |= WA_RECALC; |
160 | 0 | mutt_debug(LL_DEBUG5, "config, request WA_RECALC\n"); |
161 | |
|
162 | 0 | return 0; |
163 | 0 | } |
164 | | |
165 | | /** |
166 | | * attach_window_observer - Notification that a Window has changed - Implements ::observer_t - @ingroup observer_api |
167 | | */ |
168 | | static int attach_window_observer(struct NotifyCallback *nc) |
169 | 0 | { |
170 | 0 | if (nc->event_type != NT_WINDOW) |
171 | 0 | return 0; |
172 | 0 | if (!nc->global_data || !nc->event_data) |
173 | 0 | return -1; |
174 | | |
175 | 0 | struct MuttWindow *win_attach = nc->global_data; |
176 | 0 | struct EventWindow *ev_w = nc->event_data; |
177 | 0 | if (ev_w->win != win_attach) |
178 | 0 | return 0; |
179 | | |
180 | 0 | if (nc->event_subtype == NT_WINDOW_STATE) |
181 | 0 | { |
182 | 0 | win_attach->actions |= WA_RECALC; |
183 | 0 | mutt_debug(LL_DEBUG5, "window state done, request WA_RECALC\n"); |
184 | 0 | } |
185 | 0 | else if (nc->event_subtype == NT_WINDOW_DELETE) |
186 | 0 | { |
187 | 0 | struct Menu *menu = win_attach->wdata; |
188 | 0 | struct ComposeAttachData *adata = menu->mdata; |
189 | 0 | struct AttachCtx *actx = adata->actx; |
190 | 0 | notify_observer_remove(actx->email->notify, attach_email_observer, win_attach); |
191 | 0 | notify_observer_remove(NeoMutt->notify, attach_config_observer, win_attach); |
192 | 0 | notify_observer_remove(win_attach->notify, attach_window_observer, win_attach); |
193 | 0 | mutt_debug(LL_DEBUG5, "window delete done\n"); |
194 | 0 | } |
195 | |
|
196 | 0 | return 0; |
197 | 0 | } |
198 | | |
199 | | /** |
200 | | * compose_attach_tag - Tag an attachment - Implements Menu::tag() - @ingroup menu_tag |
201 | | */ |
202 | | static int compose_attach_tag(struct Menu *menu, int sel, int act) |
203 | 0 | { |
204 | 0 | struct ComposeAttachData *adata = menu->mdata; |
205 | 0 | struct AttachCtx *actx = adata->actx; |
206 | 0 | struct Body *cur = actx->idx[actx->v2r[sel]]->body; |
207 | 0 | bool ot = cur->tagged; |
208 | |
|
209 | 0 | cur->tagged = ((act >= 0) ? act : !cur->tagged); |
210 | 0 | return cur->tagged - ot; |
211 | 0 | } |
212 | | |
213 | | /** |
214 | | * compose_make_entry - Format a menu item for the attachment list - Implements Menu::make_entry() - @ingroup menu_make_entry |
215 | | * |
216 | | * @sa $attach_format, attach_format_str() |
217 | | */ |
218 | | static void compose_make_entry(struct Menu *menu, char *buf, size_t buflen, int line) |
219 | 0 | { |
220 | 0 | struct ComposeAttachData *adata = menu->mdata; |
221 | 0 | struct AttachCtx *actx = adata->actx; |
222 | 0 | struct ComposeSharedData *shared = menu->win->parent->wdata; |
223 | 0 | struct ConfigSubset *sub = shared->sub; |
224 | |
|
225 | 0 | const char *const c_attach_format = cs_subset_string(sub, "attach_format"); |
226 | 0 | mutt_expando_format(buf, buflen, 0, menu->win->state.cols, NONULL(c_attach_format), |
227 | 0 | attach_format_str, (intptr_t) (actx->idx[actx->v2r[line]]), |
228 | 0 | MUTT_FORMAT_STAT_FILE | MUTT_FORMAT_ARROWCURSOR); |
229 | 0 | } |
230 | | |
231 | | /** |
232 | | * attach_new - Create the Attachments Menu |
233 | | * @param parent Parent Window |
234 | | * @param shared Shared compose data |
235 | | */ |
236 | | struct MuttWindow *attach_new(struct MuttWindow *parent, struct ComposeSharedData *shared) |
237 | 0 | { |
238 | 0 | struct MuttWindow *win_attach = menu_window_new(MENU_COMPOSE, NeoMutt->sub); |
239 | |
|
240 | 0 | struct ComposeAttachData *adata = attach_data_new(shared->email); |
241 | |
|
242 | 0 | shared->adata = adata; |
243 | | |
244 | | // NT_COLOR is handled by the Menu Window |
245 | 0 | notify_observer_add(NeoMutt->notify, NT_CONFIG, attach_config_observer, win_attach); |
246 | 0 | notify_observer_add(shared->email->notify, NT_EMAIL, attach_email_observer, win_attach); |
247 | 0 | notify_observer_add(win_attach->notify, NT_WINDOW, attach_window_observer, win_attach); |
248 | |
|
249 | 0 | struct Menu *menu = win_attach->wdata; |
250 | 0 | menu->page_len = win_attach->state.rows; |
251 | 0 | menu->win = win_attach; |
252 | |
|
253 | 0 | menu->make_entry = compose_make_entry; |
254 | 0 | menu->tag = compose_attach_tag; |
255 | 0 | menu->mdata = adata; |
256 | 0 | menu->mdata_free = attach_data_free; |
257 | 0 | adata->menu = menu; |
258 | |
|
259 | 0 | return win_attach; |
260 | 0 | } |