NeoMutt  2025-12-11-769-g906513
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
window.c
Go to the documentation of this file.
1
23
61
62#include "config.h"
63#include <stdbool.h>
64#include <stdio.h>
65#include "private.h"
66#include "mutt/lib.h"
67#include "address/lib.h"
68#include "config/lib.h"
69#include "email/lib.h"
70#include "core/lib.h"
71#include "gui/lib.h"
72#include "color/lib.h"
73#include "ncrypt/lib.h"
74#include "functions.h"
75#include "globals.h"
76#include "module_data.h"
77#include "wdata.h"
78#ifdef ENABLE_NLS
79#include <libintl.h>
80#endif
81
83#define MAX_ADDR_ROWS 5
84
86#define MAX_USER_HDR_ROWS 5
87
89const char *const Prompts[] = {
90 /* L10N: Compose menu field. May not want to translate. */
91 N_("From: "),
92 /* L10N: Compose menu field. May not want to translate. */
93 N_("To: "),
94 /* L10N: Compose menu field. May not want to translate. */
95 N_("Cc: "),
96 /* L10N: Compose menu field. May not want to translate. */
97 N_("Bcc: "),
98 /* L10N: Compose menu field. May not want to translate. */
99 N_("Subject: "),
100 /* L10N: Compose menu field. May not want to translate. */
101 N_("Reply-To: "),
102 /* L10N: Compose menu field. May not want to translate. */
103 N_("Fcc: "),
104 /* L10N: Compose menu field. Holds "Encrypt", "Sign" related information */
105 N_("Security: "),
106 /* L10N: This string is used by the compose menu.
107 Since it is hidden by default, it does not increase the indentation of
108 other compose menu fields. However, if possible, it should not be longer
109 than the other compose menu fields. Since it shares the row with "Encrypt
110 with:", it should not be longer than 15-20 character cells. */
111 N_("Sign as: "),
112#ifdef USE_AUTOCRYPT
113 // L10N: The compose menu autocrypt line
114 N_("Autocrypt: "),
115#endif
116 /* L10N: Compose menu field. May not want to translate. */
117 N_("Newsgroups: "),
118 /* L10N: Compose menu field. May not want to translate. */
119 N_("Followup-To: "),
120 /* L10N: Compose menu field. May not want to translate. */
121 N_("X-Comment-To: "),
122 N_("Headers: "),
123};
124
125#ifdef USE_AUTOCRYPT
127static const char *const AutocryptRecUiFlags[] = {
128 /* L10N: Autocrypt recommendation flag: off.
129 This is displayed when Autocrypt is turned off. */
130 N_("Off"),
131 /* L10N: Autocrypt recommendation flag: no.
132 This is displayed when Autocrypt cannot encrypt to the recipients. */
133 N_("No"),
134 /* L10N: Autocrypt recommendation flag: discouraged.
135 This is displayed when Autocrypt believes encryption should not be used.
136 This might occur if one of the recipient Autocrypt Keys has not been
137 used recently, or if the only key available is a Gossip Header key. */
138 N_("Discouraged"),
139 /* L10N: Autocrypt recommendation flag: available.
140 This is displayed when Autocrypt believes encryption is possible, but
141 leaves enabling it up to the sender. Probably because "prefer encrypt"
142 is not set in both the sender and recipient keys. */
143 N_("Available"),
144 /* L10N: Autocrypt recommendation flag: yes.
145 This is displayed when Autocrypt would normally enable encryption
146 automatically. */
147 N_("Yes"),
148};
149#endif
150
159 int idx, const char *header, bool calc_max)
160{
161 int width;
162
163 mod_data->header_padding[idx] = mutt_str_len(header);
164 width = mutt_strwidth(header);
165 if (calc_max && (mod_data->max_header_width < width))
166 mod_data->max_header_width = width;
167 mod_data->header_padding[idx] -= width;
168}
169
178static void init_header_padding(void)
179{
180 static bool done = false;
181
182 if (done)
183 return;
184 done = true;
185
187
188 for (int i = 0; i < HDR_ATTACH_TITLE; i++)
189 {
190 if (i == HDR_CRYPTINFO)
191 continue;
192 calc_header_width_padding(mod_data, i, _(Prompts[i]), true);
193 }
194
195 /* Don't include "Sign as: " in the MaxHeaderWidth calculation. It
196 * doesn't show up by default, and so can make the indentation of
197 * the other fields look funny. */
199
200 for (int i = 0; i < HDR_ATTACH_TITLE; i++)
201 {
202 mod_data->header_padding[i] += mod_data->max_header_width;
203 if (mod_data->header_padding[i] < 0)
204 mod_data->header_padding[i] = 0;
205 }
206}
207
217static int calc_address(struct AddressList *al, short cols, short *srows)
218{
219 struct ListHead slist = STAILQ_HEAD_INITIALIZER(slist);
220 mutt_addrlist_write_list(al, &slist);
221
222 short rows = 1;
223 int addr_len;
224 int width_left = cols;
225 struct ListNode *next = NULL;
226 struct ListNode *np = NULL;
227 STAILQ_FOREACH(np, &slist, entries)
228 {
229 next = STAILQ_NEXT(np, entries);
230 addr_len = mutt_strwidth(np->data);
231 if (next)
232 addr_len += 2; // ", "
233
234 try_again:
235 if (addr_len >= width_left)
236 {
237 if (width_left == cols)
238 break;
239
240 rows++;
241 width_left = cols;
242 goto try_again;
243 }
244
245 if (addr_len < width_left)
246 width_left -= addr_len;
247 }
248
249 mutt_list_free(&slist);
250
251 *srows = MIN(rows, MAX_ADDR_ROWS);
252 return *srows;
253}
254
262static int calc_security(struct Email *e, short *rows, const struct ConfigSubset *sub)
263{
265 *rows = 0; // Neither PGP nor SMIME are built into NeoMutt
266 else if ((e->security & (SEC_ENCRYPT | SEC_SIGN)) != 0)
267 *rows = 2; // 'Security:' and 'Sign as:'
268 else
269 *rows = 1; // Just 'Security:'
270
271#ifdef USE_AUTOCRYPT
272 const bool c_autocrypt = cs_subset_bool(sub, "autocrypt");
273 if (c_autocrypt)
274 *rows += 1;
275#endif
276
277 return *rows;
278}
279
285static int calc_user_hdrs(const struct ListHead *hdrs)
286{
287 int rows = 0; /* Don't print at all if no custom headers*/
288 struct ListNode *np = NULL;
289 STAILQ_FOREACH(np, hdrs, entries)
290 {
291 if (rows == MAX_USER_HDR_ROWS)
292 break;
293 rows++;
294 }
295 return rows;
296}
297
304static int calc_envelope(struct MuttWindow *win, struct EnvelopeWindowData *wdata)
305{
306 int rows = 4; // 'From:', 'Subject:', 'Reply-To:', 'Fcc:'
307 struct Email *e = wdata->email;
308
310 struct Envelope *env = e->env;
311 const int cols = win->state.cols - mod_data->max_header_width;
312
313 if (wdata->is_news)
314 {
315 rows += 2; // 'Newsgroups:' and 'Followup-To:'
316 const bool c_x_comment_to = cs_subset_bool(wdata->sub, "x_comment_to");
317 if (c_x_comment_to)
318 rows++;
319 }
320 else
321 {
322 rows += calc_address(&env->to, cols, &wdata->to_rows);
323 rows += calc_address(&env->cc, cols, &wdata->cc_rows);
324 rows += calc_address(&env->bcc, cols, &wdata->bcc_rows);
325 }
326 rows += calc_security(e, &wdata->sec_rows, wdata->sub);
327 const bool c_compose_show_user_headers = cs_subset_bool(wdata->sub, "compose_show_user_headers");
328 if (c_compose_show_user_headers)
329 rows += calc_user_hdrs(&env->userhdrs);
330
331 return rows;
332}
333
341static void draw_floating(struct MuttWindow *win, int col, int row, const char *text)
342{
344 mutt_window_move(win, row, col);
345 mutt_window_printf(win, "%s", text);
347}
348
363
373static void draw_header_content(struct MuttWindow *win, int row,
374 enum HeaderField field, const char *content)
375{
377 mutt_window_move(win, row, mod_data->header_padding[field]);
378 mutt_paddstr(win, win->state.cols - mod_data->header_padding[field], content);
379}
380
388static int draw_crypt_lines(struct MuttWindow *win, struct EnvelopeWindowData *wdata, int row)
389{
390 struct Email *e = wdata->email;
391
392 draw_header(win, row++, HDR_CRYPT);
393
395 return 0;
396
397 // We'll probably need two lines for 'Security:' and 'Sign as:'
398 int used = 2;
399 if ((e->security & (SEC_ENCRYPT | SEC_SIGN)) == (SEC_ENCRYPT | SEC_SIGN))
400 {
402 mutt_window_addstr(win, _("Sign, Encrypt"));
403 }
404 else if (e->security & SEC_ENCRYPT)
405 {
407 mutt_window_addstr(win, _("Encrypt"));
408 }
409 else if (e->security & SEC_SIGN)
410 {
412 mutt_window_addstr(win, _("Sign"));
413 }
414 else
415 {
416 /* L10N: This refers to the encryption of the email, e.g. "Security: None" */
418 mutt_window_addstr(win, _("None"));
419 used = 1; // 'Sign as:' won't be needed
420 }
422
423 if ((e->security & (SEC_ENCRYPT | SEC_SIGN)))
424 {
425 if (((WithCrypto & APPLICATION_PGP) != 0) && (e->security & APPLICATION_PGP))
426 {
427 if ((e->security & SEC_INLINE))
428 mutt_window_addstr(win, _(" (inline PGP)"));
429 else
430 mutt_window_addstr(win, _(" (PGP/MIME)"));
431 }
432 else if (((WithCrypto & APPLICATION_SMIME) != 0) && (e->security & APPLICATION_SMIME))
433 {
434 mutt_window_addstr(win, _(" (S/MIME)"));
435 }
436 }
437
438 const bool c_crypt_opportunistic_encrypt = cs_subset_bool(wdata->sub, "crypt_opportunistic_encrypt");
439 if (c_crypt_opportunistic_encrypt && (e->security & SEC_OPPENCRYPT))
440 mutt_window_addstr(win, _(" (OppEnc mode)"));
441
443
444 if (((WithCrypto & APPLICATION_PGP) != 0) &&
445 (e->security & APPLICATION_PGP) && (e->security & SEC_SIGN))
446 {
447 draw_header(win, row++, HDR_CRYPTINFO);
448 const char *const c_pgp_sign_as = cs_subset_string(wdata->sub, "pgp_sign_as");
449 mutt_window_printf(win, "%s", c_pgp_sign_as ? c_pgp_sign_as : _("<default>"));
450 }
451
452 if (((WithCrypto & APPLICATION_SMIME) != 0) &&
454 {
455 draw_header(win, row++, HDR_CRYPTINFO);
456 const char *const c_smime_sign_as = cs_subset_string(wdata->sub, "smime_sign_as");
457 mutt_window_printf(win, "%s", c_smime_sign_as ? c_smime_sign_as : _("<default>"));
458 }
459
460 const char *const c_smime_encrypt_with = cs_subset_string(wdata->sub, "smime_encrypt_with");
461 if (((WithCrypto & APPLICATION_SMIME) != 0) && (e->security & APPLICATION_SMIME) &&
462 (e->security & SEC_ENCRYPT) && c_smime_encrypt_with)
463 {
464 draw_floating(win, 40, row - 1, _("Encrypt with: "));
465 mutt_window_printf(win, "%s", NONULL(c_smime_encrypt_with));
466 }
467
468#ifdef USE_AUTOCRYPT
469 const bool c_autocrypt = cs_subset_bool(wdata->sub, "autocrypt");
470 if (c_autocrypt)
471 {
472 draw_header(win, row, HDR_AUTOCRYPT);
473 if (e->security & SEC_AUTOCRYPT)
474 {
476 mutt_window_addstr(win, _("Encrypt"));
477 }
478 else
479 {
481 mutt_window_addstr(win, _("Off"));
482 }
483
484 /* L10N: The autocrypt compose menu Recommendation field.
485 Displays the output of the recommendation engine
486 (Off, No, Discouraged, Available, Yes) */
487 draw_floating(win, 40, row, _("Recommendation: "));
489
490 used++;
491 }
492#endif
493 return used;
494}
495
505static int draw_envelope_addr(int field, struct AddressList *al,
506 struct MuttWindow *win, int row, size_t max_lines)
507{
508 draw_header(win, row, field);
509
511
512 /* Format addresses into displayable strings and wrap across multiple
513 * lines as needed, showing "(+N more)" when lines are exhausted */
514 struct ListHead list = STAILQ_HEAD_INITIALIZER(list);
515 int count = mutt_addrlist_count_recips(al);
516
517 int lines_used = 1;
518 int width_left = win->state.cols - mod_data->max_header_width;
519 char more[32] = { 0 };
520 int more_len = 0;
521
522 struct Buffer *buf = buf_pool_get();
523 bool in_group = false;
524 char *sep = NULL;
525 struct Address *addr = NULL;
526 TAILQ_FOREACH(addr, al, entries)
527 {
528 struct Address *next = TAILQ_NEXT(addr, entries);
529
530 if (addr->group)
531 {
532 in_group = true;
533 }
534
535 buf_reset(buf);
536 mutt_addr_write(buf, addr, true);
537 size_t addr_len = mutt_strwidth(buf_string(buf));
538
539 sep = "";
540 if (!addr->group)
541 {
542 // group terminator
543 if (in_group && next && !next->mailbox && !next->personal)
544 {
545 sep = ";";
546 addr_len += 1;
547 in_group = false;
548 }
549 else if (next)
550 {
551 sep = ", ";
552 addr_len += 2;
553 }
554 }
555
556 count--;
557 try_again:
558 /* Calculate the "(+N more)" indicator width if we're on the last line */
559 more_len = snprintf(more, sizeof(more),
560 ngettext("(+%d more)", "(+%d more)", count), count);
561 if ((more_len < 0) || (more_len >= sizeof(more)))
562 more_len = mutt_strwidth(more);
563 mutt_debug(LL_DEBUG3, "text: '%s' len: %d\n", more, more_len);
564
565 int reserve = ((count > 0) && (lines_used == max_lines)) ? more_len : 0;
566 mutt_debug(LL_DEBUG3, "processing: %s (al:%zu, wl:%d, r:%d, lu:%d)\n",
567 buf_string(buf), addr_len, width_left, reserve, lines_used);
568 if (addr_len >= (width_left - reserve))
569 {
570 mutt_debug(LL_DEBUG3, "not enough space\n");
571 if (lines_used == max_lines)
572 {
573 mutt_debug(LL_DEBUG3, "no more lines\n");
574 mutt_debug(LL_DEBUG3, "truncating: %s\n", buf_string(buf));
575 mutt_paddstr(win, width_left, buf_string(buf));
576 break;
577 }
578
579 if (width_left == (win->state.cols - mod_data->max_header_width))
580 {
581 mutt_debug(LL_DEBUG3, "couldn't print: %s\n", buf_string(buf));
582 mutt_paddstr(win, width_left, buf_string(buf));
583 break;
584 }
585
586 mutt_debug(LL_DEBUG3, "start a new line\n");
588 row++;
589 lines_used++;
590 width_left = win->state.cols - mod_data->max_header_width;
591 mutt_window_move(win, row, mod_data->max_header_width);
592 goto try_again;
593 }
594
595 if (addr_len < width_left)
596 {
597 mutt_debug(LL_DEBUG3, "space for: %s\n", buf_string(buf));
599 mutt_window_addstr(win, sep);
600 width_left -= addr_len;
601 }
602 mutt_debug(LL_DEBUG3, "%d addresses remaining\n", count);
603 mutt_debug(LL_DEBUG3, "%zd lines remaining\n", max_lines - lines_used);
604 }
605 mutt_list_free(&list);
606 buf_pool_release(&buf);
607
608 /* Display the "(+N more)" overflow indicator, or clear the rest of the line */
609 if (count > 0)
610 {
611 mutt_window_move(win, row, win->state.cols - more_len);
613 mutt_window_addstr(win, more);
615 mutt_debug(LL_DEBUG3, "%d more (len %d)\n", count, more_len);
616 }
617 else
618 {
620 }
621
622 for (int i = lines_used; i < max_lines; i++)
623 {
624 mutt_window_move(win, row + i, 0);
626 }
627
628 mutt_debug(LL_DEBUG3, "used %d lines\n", lines_used);
629 return lines_used;
630}
631
639static int draw_envelope_user_hdrs(struct MuttWindow *win,
640 struct EnvelopeWindowData *wdata, int row)
641{
642 const char *overflow_text = "...";
643 int rows_used = 0;
644
645 struct ListNode *first = STAILQ_FIRST(&wdata->email->env->userhdrs);
646 if (!first)
647 return rows_used;
648
649 /* Draw first entry on same line as prompt */
652 rows_used++;
653
654 /* Draw any following entries on their own line */
655 struct ListNode *np = STAILQ_NEXT(first, entries);
656 if (!np)
657 return rows_used;
658
659 STAILQ_FOREACH_FROM(np, &wdata->email->env->userhdrs, entries)
660 {
661 if ((rows_used == (MAX_USER_HDR_ROWS - 1)) && STAILQ_NEXT(np, entries))
662 {
663 draw_header_content(win, row + rows_used, HDR_CUSTOM_HEADERS, overflow_text);
664 rows_used++;
665 break;
666 }
667 draw_header_content(win, row + rows_used, HDR_CUSTOM_HEADERS, np->data);
668 rows_used++;
669 }
670 return rows_used;
671}
672
678static void draw_envelope(struct MuttWindow *win, struct EnvelopeWindowData *wdata)
679{
680 struct Email *e = wdata->email;
681 const char *fcc = buf_string(wdata->fcc);
683 const int cols = win->state.cols - mod_data->max_header_width;
684
686 int row = draw_envelope_addr(HDR_FROM, &e->env->from, win, 0, 1);
687
688 if (wdata->is_news)
689 {
690 draw_header(win, row++, HDR_NEWSGROUPS);
691 mutt_paddstr(win, cols, NONULL(e->env->newsgroups));
692
693 draw_header(win, row++, HDR_FOLLOWUPTO);
694 mutt_paddstr(win, cols, NONULL(e->env->followup_to));
695
696 const bool c_x_comment_to = cs_subset_bool(wdata->sub, "x_comment_to");
697 if (c_x_comment_to)
698 {
699 draw_header(win, row++, HDR_XCOMMENTTO);
700 mutt_paddstr(win, cols, NONULL(e->env->x_comment_to));
701 }
702 }
703 else
704 {
705 row += draw_envelope_addr(HDR_TO, &e->env->to, win, row, wdata->to_rows);
706 row += draw_envelope_addr(HDR_CC, &e->env->cc, win, row, wdata->cc_rows);
707 row += draw_envelope_addr(HDR_BCC, &e->env->bcc, win, row, wdata->bcc_rows);
708 }
709
710 draw_header(win, row++, HDR_SUBJECT);
711 mutt_paddstr(win, cols, NONULL(e->env->subject));
712
713 row += draw_envelope_addr(HDR_REPLYTO, &e->env->reply_to, win, row, 1);
714
715 draw_header(win, row++, HDR_FCC);
716 mutt_paddstr(win, cols, fcc);
717
718 if (WithCrypto)
719 row += draw_crypt_lines(win, wdata, row);
720
721 const bool c_compose_show_user_headers = cs_subset_bool(wdata->sub, "compose_show_user_headers");
722 if (c_compose_show_user_headers)
723 row += draw_envelope_user_hdrs(win, wdata, row);
724
726}
727
731static int env_recalc(struct MuttWindow *win)
732{
733 struct EnvelopeWindowData *wdata = win->wdata;
734
735 const int cur_rows = win->state.rows;
736 const int new_rows = calc_envelope(win, wdata);
737
738 if (new_rows != cur_rows)
739 {
740 win->req_rows = new_rows;
742 }
743
744 win->actions |= WA_REPAINT;
745 mutt_debug(LL_DEBUG5, "recalc done, request WA_REPAINT\n");
746 return 0;
747}
748
752static int env_repaint(struct MuttWindow *win)
753{
754 struct EnvelopeWindowData *wdata = win->wdata;
755
756 draw_envelope(win, wdata);
757 mutt_debug(LL_DEBUG5, "repaint done\n");
758 return 0;
759}
760
764static int env_color_observer(struct NotifyCallback *nc)
765{
766 if (nc->event_type != NT_COLOR)
767 return 0;
768 if (!nc->global_data || !nc->event_data)
769 return -1;
770
771 struct EventColor *ev_c = nc->event_data;
772 struct MuttWindow *win_env = nc->global_data;
773
774 enum ColorId cid = ev_c->cid;
775
776 switch (cid)
777 {
778 case MT_COLOR_BOLD:
784 case MT_COLOR_NORMAL:
785 case MT_COLOR_STATUS:
786 case MT_COLOR_MAX: // Sent on `uncolor *`
787 mutt_debug(LL_DEBUG5, "color done, request WA_REPAINT\n");
788 win_env->actions |= WA_REPAINT;
789 break;
790
791 default:
792 break;
793 }
794 return 0;
795}
796
801{
802 if (nc->event_type != NT_CONFIG)
803 return 0;
804 if (!nc->global_data || !nc->event_data)
805 return -1;
806
807 struct EventConfig *ev_c = nc->event_data;
808 if (!ev_c->name)
809 return 0;
810
811 struct MuttWindow *win_env = nc->global_data;
812
813 switch (ev_c->name[0])
814 {
815 case 'a':
816 if (mutt_str_equal(ev_c->name, "autocrypt"))
817 break;
818 return 0;
819 case 'c':
820 if (mutt_str_equal(ev_c->name, "compose_show_user_headers") ||
821 mutt_str_equal(ev_c->name, "crypt_opportunistic_encrypt"))
822 {
823 break;
824 }
825 return 0;
826 case 'p':
827 if (mutt_str_equal(ev_c->name, "pgp_sign_as"))
828 break;
829 return 0;
830 case 's':
831 if (mutt_str_equal(ev_c->name, "smime_encrypt_with") ||
832 mutt_str_equal(ev_c->name, "smime_sign_as"))
833 {
834 break;
835 }
836 return 0;
837 case 'x':
838 if (mutt_str_equal(ev_c->name, "x_comment_to"))
839 break;
840 return 0;
841 default:
842 return 0;
843 }
844
845 win_env->actions |= WA_RECALC;
846 mutt_debug(LL_DEBUG5, "config done, request WA_RECALC\n");
847 return 0;
848}
849
853static int env_email_observer(struct NotifyCallback *nc)
854{
855 if ((nc->event_type != NT_EMAIL) && (nc->event_type != NT_ENVELOPE))
856 return 0;
857 if (!nc->global_data)
858 return -1;
859
860 struct MuttWindow *win_env = nc->global_data;
861
862 // pgp/smime/autocrypt menu, or external change
863 if (nc->event_type == NT_EMAIL)
864 {
865 struct EnvelopeWindowData *wdata = win_env->wdata;
866 update_crypt_info(wdata);
867 }
868
869 win_env->actions |= WA_RECALC;
870 mutt_debug(LL_DEBUG5, "email done, request WA_RECALC\n");
871 return 0;
872}
873
878{
879 if (nc->event_type != NT_HEADER)
880 return 0;
881 if (!nc->global_data || !nc->event_data)
882 return -1;
883
884 const struct EventHeader *ev_h = nc->event_data;
885 struct MuttWindow *win_env = nc->global_data;
886 struct EnvelopeWindowData *wdata = win_env->wdata;
887
888 struct Envelope *env = wdata->email->env;
889
891 {
892 header_set(&env->userhdrs, ev_h->header);
893 mutt_debug(LL_DEBUG5, "header done, request reflow\n");
894 win_env->actions |= WA_RECALC;
895 return 0;
896 }
897
899 {
900 struct ListNode *removed = header_find(&env->userhdrs, ev_h->header);
901 if (removed)
902 {
903 header_free(&env->userhdrs, removed);
904 mutt_debug(LL_DEBUG5, "header done, request reflow\n");
905 win_env->actions |= WA_RECALC;
906 }
907 return 0;
908 }
909
910 return 0;
911}
912
917{
918 if (nc->event_type != NT_WINDOW)
919 return 0;
920 if (!nc->global_data || !nc->event_data)
921 return -1;
922
923 struct MuttWindow *win_env = nc->global_data;
924 struct EventWindow *ev_w = nc->event_data;
925 if (ev_w->win != win_env)
926 return 0;
927
929 {
930 win_env->actions |= WA_RECALC;
931 mutt_debug(LL_DEBUG5, "window state done, request WA_RECALC\n");
932 }
933 else if (nc->event_subtype == NT_WINDOW_DELETE)
934 {
935 struct EnvelopeWindowData *wdata = win_env->wdata;
936
942 mutt_debug(LL_DEBUG5, "window delete done\n");
943 }
944
945 return 0;
946}
947
955struct MuttWindow *env_window_new(struct Email *e, struct Buffer *fcc, struct ConfigSubset *sub)
956{
958
961 HDR_ATTACH_TITLE - 1);
962
968
969 struct EnvelopeWindowData *wdata = env_wdata_new();
970 wdata->fcc = fcc;
971 wdata->email = e;
972 wdata->sub = sub;
973 wdata->is_news = OptNewsSend;
974
975 win_env->wdata = wdata;
976 win_env->wdata_free = env_wdata_free;
977 win_env->recalc = env_recalc;
978 win_env->repaint = env_repaint;
979
980 return win_env;
981}
size_t mutt_addrlist_write_list(const struct AddressList *al, struct ListHead *list)
Write Addresses to a List.
Definition address.c:1226
size_t mutt_addr_write(struct Buffer *buf, struct Address *addr, bool display)
Write a single Address to a buffer.
Definition address.c:1059
int mutt_addrlist_count_recips(const struct AddressList *al)
Count the number of Addresses with valid recipients.
Definition address.c:881
Email Address Handling.
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:76
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
Color and attribute parsing.
void mutt_color_observer_remove(observer_t callback, void *global_data)
Remove an observer.
Definition notify.c:73
void mutt_color_observer_add(observer_t callback, void *global_data)
Add an observer.
Definition notify.c:62
ColorId
List of all coloured objects.
Definition color.h:35
@ MT_COLOR_COMPOSE_SECURITY_ENCRYPT
Mail will be encrypted.
Definition color.h:43
@ MT_COLOR_MAX
Definition color.h:97
@ MT_COLOR_STATUS
Status bar (takes a pattern)
Definition color.h:78
@ MT_COLOR_COMPOSE_SECURITY_NONE
Mail will not be encrypted or signed.
Definition color.h:44
@ MT_COLOR_BOLD
Bold text.
Definition color.h:40
@ MT_COLOR_COMPOSE_SECURITY_BOTH
Mail will be encrypted and signed.
Definition color.h:42
@ MT_COLOR_NORMAL
Plain text.
Definition color.h:53
@ MT_COLOR_COMPOSE_SECURITY_SIGN
Mail will be signed.
Definition color.h:45
@ MT_COLOR_COMPOSE_HEADER
Header labels, e.g. From:
Definition color.h:41
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
void mutt_paddstr(struct MuttWindow *win, int n, const char *s)
Display a string on screen, padded if necessary.
Definition curs_lib.c:344
size_t mutt_strwidth(const char *s)
Measure a string's width in screen cells.
Definition curs_lib.c:446
void header_free(struct ListHead *hdrlist, struct ListNode *target)
Free and remove a header from a header list.
Definition email.c:202
struct ListNode * header_set(struct ListHead *hdrlist, const char *header)
Set a header value in a list.
Definition email.c:190
struct ListNode * header_find(const struct ListHead *hdrlist, const char *header)
Find a header, matching on its field, in a list of headers.
Definition email.c:137
Structs that make up an email.
@ NT_HEADER_CHANGE
An existing header has been changed.
Definition email.h:210
@ NT_HEADER_ADD
Header has been added.
Definition email.h:208
@ NT_HEADER_DELETE
Header has been removed.
Definition email.h:209
void update_crypt_info(struct EnvelopeWindowData *wdata)
Update the crypto info.
Definition functions.c:148
Envelope functions.
Envelope private Module data.
Private Envelope Data.
const char *const Prompts[]
Names of header fields used in the envelope, e.g. From:, To:
Definition window.c:89
HeaderField
Ordered list of headers for the compose screen.
Definition private.h:33
@ HDR_SUBJECT
"Subject:" field
Definition private.h:38
@ HDR_REPLYTO
"Reply-To:" field
Definition private.h:39
@ HDR_AUTOCRYPT
"Autocrypt:" and "Recommendation:" fields
Definition private.h:44
@ HDR_FCC
"Fcc:" (save folder) field
Definition private.h:40
@ HDR_ATTACH_TITLE
The "-- Attachments" line.
Definition private.h:50
@ HDR_CRYPT
"Security:" field (encryption/signing info)
Definition private.h:41
@ HDR_CC
"Cc:" field
Definition private.h:36
@ HDR_TO
"To:" field
Definition private.h:35
@ HDR_BCC
"Bcc:" field
Definition private.h:37
@ HDR_CUSTOM_HEADERS
"Headers:" field
Definition private.h:49
@ HDR_FOLLOWUPTO
"Followup-To:" field
Definition private.h:47
@ HDR_XCOMMENTTO
"X-Comment-To:" field
Definition private.h:48
@ HDR_NEWSGROUPS
"Newsgroups:" field
Definition private.h:46
@ HDR_CRYPTINFO
"Sign as:" field (encryption/signing info)
Definition private.h:42
@ HDR_FROM
"From:" field
Definition private.h:34
struct EnvelopeWindowData * env_wdata_new(void)
Create new Envelope Data.
Definition wdata.c:51
Envelope Window Data.
static void calc_header_width_padding(struct EnvelopeModuleData *mod_data, int idx, const char *header, bool calc_max)
Calculate the width needed for the compose labels.
Definition window.c:158
static int draw_envelope_addr(int field, struct AddressList *al, struct MuttWindow *win, int row, size_t max_lines)
Write addresses to the compose window.
Definition window.c:505
static const char *const AutocryptRecUiFlags[]
Autocrypt "recommendation" strings.
Definition window.c:127
static void draw_header(struct MuttWindow *win, int row, enum HeaderField field)
Draw an aligned label.
Definition window.c:355
static void draw_envelope(struct MuttWindow *win, struct EnvelopeWindowData *wdata)
Write the email headers to the compose window.
Definition window.c:678
static void draw_floating(struct MuttWindow *win, int col, int row, const char *text)
Draw a floating label.
Definition window.c:341
#define MAX_USER_HDR_ROWS
Maximum number of rows to use for the Headers: field.
Definition window.c:86
static int draw_envelope_user_hdrs(struct MuttWindow *win, struct EnvelopeWindowData *wdata, int row)
Write user-defined headers to the compose window.
Definition window.c:639
static int calc_address(struct AddressList *al, short cols, short *srows)
Calculate how many rows an AddressList will need.
Definition window.c:217
struct MuttWindow * env_window_new(struct Email *e, struct Buffer *fcc, struct ConfigSubset *sub)
Create the Envelope Window.
Definition window.c:955
static int calc_envelope(struct MuttWindow *win, struct EnvelopeWindowData *wdata)
Calculate how many rows the envelope will need.
Definition window.c:304
static void draw_header_content(struct MuttWindow *win, int row, enum HeaderField field, const char *content)
Draw content on a separate line aligned to header prompt.
Definition window.c:373
static int calc_user_hdrs(const struct ListHead *hdrs)
Calculate how many rows are needed for user-defined headers.
Definition window.c:285
static int calc_security(struct Email *e, short *rows, const struct ConfigSubset *sub)
Calculate how many rows the security info will need.
Definition window.c:262
#define MAX_ADDR_ROWS
Maximum number of rows to use for the To:, Cc:, Bcc: fields.
Definition window.c:83
static int draw_crypt_lines(struct MuttWindow *win, struct EnvelopeWindowData *wdata, int row)
Update the encryption info in the compose window.
Definition window.c:388
static void init_header_padding(void)
Calculate how much padding the compose table will need.
Definition window.c:178
bool OptNewsSend
(pseudo) used to change behavior when posting
Definition globals.c:54
Global variables.
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
static int env_email_observer(struct NotifyCallback *nc)
Notification that the Email has changed - Implements observer_t -.
Definition window.c:853
static int env_color_observer(struct NotifyCallback *nc)
Notification that a Color has changed - Implements observer_t -.
Definition window.c:764
static int env_window_observer(struct NotifyCallback *nc)
Notification that a Window has changed - Implements observer_t -.
Definition window.c:916
static int env_config_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t -.
Definition window.c:800
static int env_header_observer(struct NotifyCallback *nc)
Notification that a User Header has changed - Implements observer_t -.
Definition window.c:877
static int env_recalc(struct MuttWindow *win)
Recalculate the Window data - Implements MuttWindow::recalc() -.
Definition window.c:731
static int env_repaint(struct MuttWindow *win)
Repaint the Window - Implements MuttWindow::repaint() -.
Definition window.c:752
void env_wdata_free(struct MuttWindow *win, void **ptr)
Free the Envelope Data - Implements MuttWindow::wdata_free() -.
Definition wdata.c:39
Convenience wrapper for the gui headers.
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition list.c:123
@ LL_DEBUG3
Log at debug level 3.
Definition logging2.h:47
@ LL_DEBUG5
Log at debug level 5.
Definition logging2.h:49
#define MIN(a, b)
Return the minimum of two values.
Definition memory.h:40
@ MODULE_ID_ENVELOPE
ModuleEnvelope, Envelope-editing Window
Definition module_api.h:65
Convenience wrapper for the library headers.
#define N_(a)
Definition message.h:32
#define _(a)
Definition message.h:28
bool notify_observer_remove(struct Notify *notify, const observer_t callback, const void *global_data)
Remove an observer from an object.
Definition notify.c:230
bool notify_observer_add(struct Notify *notify, enum NotifyType type, observer_t callback, void *global_data)
Add an observer to an object.
Definition notify.c:191
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:665
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition string.c:503
const struct AttrColor * mutt_curses_set_normal_backed_color_by_id(enum ColorId cid)
Set the colour and attributes by the Colour ID.
Definition mutt_curses.c:63
const struct AttrColor * mutt_curses_set_color_by_id(enum ColorId cid)
Set the colour and attributes by the Colour ID.
Definition mutt_curses.c:79
void mutt_window_clear(struct MuttWindow *win)
Clear a Window.
void mutt_window_reflow(struct MuttWindow *win)
Resize a Window and its children.
int mutt_window_printf(struct MuttWindow *win, const char *fmt,...)
Write a formatted string to a Window.
struct MuttWindow * mutt_window_new(enum WindowType type, enum MuttWindowOrientation orient, enum MuttWindowSize size, int cols, int rows)
Create a new Window.
int mutt_window_move(struct MuttWindow *win, int row, int col)
Move the cursor in a Window.
int mutt_window_addstr(struct MuttWindow *win, const char *str)
Write a string to a Window.
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
#define WA_RECALC
Recalculate the contents of the Window.
@ WT_CUSTOM
Window with a custom drawing function.
Definition mutt_window.h:94
@ MUTT_WIN_ORIENT_VERTICAL
Window uses all available vertical space.
Definition mutt_window.h:38
@ NT_WINDOW_STATE
Window state has changed, e.g. WN_VISIBLE.
@ NT_WINDOW_DELETE
Window is about to be deleted.
#define WA_REPAINT
Redraw the contents of the Window.
#define MUTT_WIN_SIZE_UNLIMITED
Use as much space as possible.
Definition mutt_window.h:52
@ MUTT_WIN_SIZE_FIXED
Window has a fixed size.
Definition mutt_window.h:47
API for encryption/signing of emails.
#define SEC_INLINE
Email has an inline signature.
Definition lib.h:94
#define SEC_AUTOCRYPT
(Autocrypt) Message will be, or was Autocrypt encrypt+signed
Definition lib.h:96
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition lib.h:95
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition lib.h:99
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition lib.h:100
#define SEC_ENCRYPT
Email is encrypted.
Definition lib.h:87
#define WithCrypto
Definition lib.h:125
#define SEC_SIGN
Email is signed.
Definition lib.h:88
void * neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
Get the private data for a Module.
Definition neomutt.c:665
@ NT_WINDOW
MuttWindow has changed, NotifyWindow, EventWindow.
Definition notify_type.h:57
@ NT_CONFIG
Config has changed, NotifyConfig, EventConfig.
Definition notify_type.h:43
@ NT_COLOR
Colour has changed, NotifyColor, EventColor.
Definition notify_type.h:41
@ NT_EMAIL
Email has changed, NotifyEmail, EventEmail.
Definition notify_type.h:44
@ NT_ENVELOPE
Envelope has changed, NotifyEnvelope.
Definition notify_type.h:45
@ NT_HEADER
A header has changed, NotifyHeader EventHeader.
Definition notify_type.h:47
@ NT_ALL
Register for all notifications.
Definition notify_type.h:35
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
#define TAILQ_FOREACH(var, head, field)
Definition queue.h:782
#define STAILQ_HEAD_INITIALIZER(head)
Definition queue.h:324
#define STAILQ_FIRST(head)
Definition queue.h:388
#define STAILQ_FOREACH(var, head, field)
Definition queue.h:390
#define TAILQ_NEXT(elm, field)
Definition queue.h:889
#define STAILQ_NEXT(elm, field)
Definition queue.h:439
#define STAILQ_FOREACH_FROM(var, head, field)
Definition queue.h:395
#define NONULL(x)
Definition string2.h:44
An email address.
Definition address.h:35
struct Buffer * personal
Real name of address.
Definition address.h:36
bool group
Group mailbox?
Definition address.h:38
struct Buffer * mailbox
Mailbox and host address.
Definition address.h:37
String manipulation buffer.
Definition buffer.h:36
A set of inherited config items.
Definition subset.h:46
struct Notify * notify
Notifications: NotifyConfig, EventConfig.
Definition subset.h:51
The envelope/body of an email.
Definition email.h:39
struct Envelope * env
Envelope information.
Definition email.h:68
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition email.h:43
struct Notify * notify
Notifications: NotifyEmail, EventEmail.
Definition email.h:73
Envelope private Module data.
Definition module_data.h:32
int header_padding[HDR_ATTACH_TITLE]
Width of each header prompt.
Definition module_data.h:34
int max_header_width
Width of the widest header.
Definition module_data.h:35
Data to fill the Envelope Window.
Definition wdata.h:38
bool is_news
Email is a news article.
Definition wdata.h:48
struct Buffer * fcc
Where the outgoing Email will be saved.
Definition wdata.h:41
struct Email * email
Email being composed.
Definition wdata.h:40
short sec_rows
Number of rows used by the security fields.
Definition wdata.h:46
short cc_rows
Number of rows used by the 'Cc:' field.
Definition wdata.h:44
struct ConfigSubset * sub
Inherited config items.
Definition wdata.h:39
enum AutocryptRec autocrypt_rec
Autocrypt recommendation.
Definition wdata.h:50
short to_rows
Number of rows used by the 'To:' field.
Definition wdata.h:43
short bcc_rows
Number of rows used by the 'Bcc:' field.
Definition wdata.h:45
The header of an Email.
Definition envelope.h:57
struct ListHead userhdrs
user defined headers
Definition envelope.h:85
char *const subject
Email's subject.
Definition envelope.h:70
struct AddressList to
Email's 'To' list.
Definition envelope.h:60
char * followup_to
List of 'followup-to' fields.
Definition envelope.h:80
struct AddressList reply_to
Email's 'reply-to'.
Definition envelope.h:64
char * x_comment_to
List of 'X-comment-to' fields.
Definition envelope.h:81
char * newsgroups
List of newsgroups.
Definition envelope.h:78
struct AddressList cc
Email's 'Cc' list.
Definition envelope.h:61
struct AddressList bcc
Email's 'Bcc' list.
Definition envelope.h:62
struct AddressList from
Email's 'From' list.
Definition envelope.h:59
An Event that happened to a Colour.
Definition notify2.h:52
enum ColorId cid
Colour ID that has changed.
Definition notify2.h:53
A config-change event.
Definition subset.h:70
const char * name
Name of config item that changed.
Definition subset.h:72
An event that happened to a header.
Definition email.h:217
char * header
The contents of the header.
Definition email.h:218
An Event that happened to a Window.
struct MuttWindow * win
Window that changed.
A List node for strings.
Definition list.h:37
char * data
String.
Definition list.h:38
int(* repaint)(struct MuttWindow *win)
struct WindowState state
Current state of the Window.
void * wdata
Private data.
struct Notify * notify
Notifications: NotifyWindow, EventWindow.
short req_rows
Number of rows required.
int(* recalc)(struct MuttWindow *win)
void(* wdata_free)(struct MuttWindow *win, void **ptr)
struct MuttWindow * parent
Parent Window.
WindowActionFlags actions
Actions to be performed, e.g. WA_RECALC.
Container for Accounts, Notifications.
Definition neomutt.h:41
struct Notify * notify
Notifications handler.
Definition neomutt.h:45
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
Data passed to a notification function.
Definition observer.h:34
void * event_data
Data from notify_send()
Definition observer.h:38
enum NotifyType event_type
Send: Event type, e.g. NT_ACCOUNT.
Definition observer.h:36
int event_subtype
Send: Event subtype, e.g. NT_ACCOUNT_ADD.
Definition observer.h:37
void * global_data
Data from notify_observer_add()
Definition observer.h:39
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition mutt_window.h:60
short rows
Number of rows, can be MUTT_WIN_SIZE_UNLIMITED.
Definition mutt_window.h:61