NeoMutt  2022-04-29-249-gaae397
Teaching an old dog new tricks
DOXYGEN
window.c
Go to the documentation of this file.
1
61#include "config.h"
62#include <stdbool.h>
63#include <stdio.h>
64#include "private.h"
65#include "mutt/lib.h"
66#include "address/lib.h"
67#include "config/lib.h"
68#include "email/lib.h"
69#include "core/lib.h"
70#include "gui/lib.h"
71#include "color/lib.h"
72#include "ncrypt/lib.h"
73#include "functions.h"
74#include "options.h"
75#include "wdata.h"
76#ifdef ENABLE_NLS
77#include <libintl.h>
78#endif
79
81#define MAX_ADDR_ROWS 5
82
84#define MAX_USER_HDR_ROWS 5
85
88
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#ifdef MIXMASTER
105 /* L10N: "Mix" refers to the MixMaster chain for anonymous email */
106 N_("Mix: "),
107#endif
108 /* L10N: Compose menu field. Holds "Encrypt", "Sign" related information */
109 N_("Security: "),
110 /* L10N: This string is used by the compose menu.
111 Since it is hidden by default, it does not increase the indentation of
112 other compose menu fields. However, if possible, it should not be longer
113 than the other compose menu fields. Since it shares the row with "Encrypt
114 with:", it should not be longer than 15-20 character cells. */
115 N_("Sign as: "),
116#ifdef USE_AUTOCRYPT
117 // L10N: The compose menu autocrypt line
118 N_("Autocrypt: "),
119#endif
120#ifdef USE_NNTP
121 /* L10N: Compose menu field. May not want to translate. */
122 N_("Newsgroups: "),
123 /* L10N: Compose menu field. May not want to translate. */
124 N_("Followup-To: "),
125 /* L10N: Compose menu field. May not want to translate. */
126 N_("X-Comment-To: "),
127#endif
128 N_("Headers: "),
129};
130
131#ifdef USE_AUTOCRYPT
132static const char *const AutocryptRecUiFlags[] = {
133 /* L10N: Autocrypt recommendation flag: off.
134 This is displayed when Autocrypt is turned off. */
135 N_("Off"),
136 /* L10N: Autocrypt recommendation flag: no.
137 This is displayed when Autocrypt cannot encrypt to the recipients. */
138 N_("No"),
139 /* L10N: Autocrypt recommendation flag: discouraged.
140 This is displayed when Autocrypt believes encryption should not be used.
141 This might occur if one of the recipient Autocrypt Keys has not been
142 used recently, or if the only key available is a Gossip Header key. */
143 N_("Discouraged"),
144 /* L10N: Autocrypt recommendation flag: available.
145 This is displayed when Autocrypt believes encryption is possible, but
146 leaves enabling it up to the sender. Probably because "prefer encrypt"
147 is not set in both the sender and recipient keys. */
148 N_("Available"),
149 /* L10N: Autocrypt recommendation flag: yes.
150 This is displayed when Autocrypt would normally enable encryption
151 automatically. */
152 N_("Yes"),
153};
154#endif
155
162static void calc_header_width_padding(int idx, const char *header, bool calc_max)
163{
164 int width;
165
166 HeaderPadding[idx] = mutt_str_len(header);
167 width = mutt_strwidth(header);
168 if (calc_max && (MaxHeaderWidth < width))
169 MaxHeaderWidth = width;
170 HeaderPadding[idx] -= width;
171}
172
181static void init_header_padding(void)
182{
183 static bool done = false;
184
185 if (done)
186 return;
187 done = true;
188
189 for (int i = 0; i < HDR_ATTACH_TITLE; i++)
190 {
191 if (i == HDR_CRYPTINFO)
192 continue;
193 calc_header_width_padding(i, _(Prompts[i]), true);
194 }
195
196 /* Don't include "Sign as: " in the MaxHeaderWidth calculation. It
197 * doesn't show up by default, and so can make the indentation of
198 * the other fields look funny. */
200
201 for (int i = 0; i < HDR_ATTACH_TITLE; i++)
202 {
204 if (HeaderPadding[i] < 0)
205 HeaderPadding[i] = 0;
206 }
207}
208
219static int calc_address(struct AddressList *al, struct ListHead *slist,
220 short cols, short *srows)
221{
222 mutt_list_free(slist);
223 mutt_addrlist_write_list(al, slist);
224
225 int rows = 1;
226 int addr_len;
227 int width_left = cols;
228 struct ListNode *next = NULL;
229 struct ListNode *np = NULL;
230 STAILQ_FOREACH(np, slist, entries)
231 {
232 next = STAILQ_NEXT(np, entries);
233 addr_len = mutt_strwidth(np->data);
234 if (next)
235 addr_len += 2; // ", "
236
237 try_again:
238 if (addr_len >= width_left)
239 {
240 if (width_left == cols)
241 break;
242
243 rows++;
244 width_left = cols;
245 goto try_again;
246 }
247
248 if (addr_len < width_left)
249 width_left -= addr_len;
250 }
251
252 *srows = MIN(rows, MAX_ADDR_ROWS);
253 return *srows;
254}
255
263static int calc_security(struct Email *e, short *rows, const struct ConfigSubset *sub)
264{
266 *rows = 0; // Neither PGP nor SMIME are built into NeoMutt
267 else if ((e->security & (SEC_ENCRYPT | SEC_SIGN)) != 0)
268 *rows = 2; // 'Security:' and 'Sign as:'
269 else
270 *rows = 1; // Just 'Security:'
271
272#ifdef USE_AUTOCRYPT
273 const bool c_autocrypt = cs_subset_bool(sub, "autocrypt");
274 if (c_autocrypt)
275 *rows += 1;
276#endif
277
278 return *rows;
279}
280
286static int calc_user_hdrs(const struct ListHead *hdrs)
287{
288 int rows = 0; /* Don't print at all if no custom headers*/
289 struct ListNode *np = NULL;
290 STAILQ_FOREACH(np, hdrs, entries)
291 {
292 if (rows == MAX_USER_HDR_ROWS)
293 break;
294 rows++;
295 }
296 return rows;
297}
298
305static int calc_envelope(struct MuttWindow *win, struct EnvelopeWindowData *wdata)
306{
307 int rows = 4; // 'From:', 'Subject:', 'Reply-To:', 'Fcc:'
308#ifdef MIXMASTER
309 rows++;
310#endif
311
312 struct Email *e = wdata->email;
313 struct Envelope *env = e->env;
314 const int cols = win->state.cols - MaxHeaderWidth;
315
316#ifdef USE_NNTP
317 if (wdata->is_news)
318 {
319 rows += 2; // 'Newsgroups:' and 'Followup-To:'
320 const bool c_x_comment_to = cs_subset_bool(wdata->sub, "x_comment_to");
321 if (c_x_comment_to)
322 rows++;
323 }
324 else
325#endif
326 {
327 rows += calc_address(&env->to, &wdata->to_list, cols, &wdata->to_rows);
328 rows += calc_address(&env->cc, &wdata->cc_list, cols, &wdata->cc_rows);
329 rows += calc_address(&env->bcc, &wdata->bcc_list, cols, &wdata->bcc_rows);
330 }
331 rows += calc_security(e, &wdata->sec_rows, wdata->sub);
332 const bool c_compose_show_user_headers = cs_subset_bool(wdata->sub, "compose_show_user_headers");
333 if (c_compose_show_user_headers)
334 rows += calc_user_hdrs(&env->userhdrs);
335
336 return rows;
337}
338
346static void draw_floating(struct MuttWindow *win, int col, int row, const char *text)
347{
349 mutt_window_mvprintw(win, col, row, "%s", text);
351}
352
359static void draw_header(struct MuttWindow *win, int row, enum HeaderField field)
360{
362 mutt_window_mvprintw(win, 0, row, "%*s", HeaderPadding[field], _(Prompts[field]));
364}
365
375static void draw_header_content(struct MuttWindow *win, int row,
376 enum HeaderField field, const char *content)
377{
378 mutt_window_move(win, HeaderPadding[field], row);
379 mutt_paddstr(win, win->state.cols - HeaderPadding[field], content);
380}
381
389static int draw_crypt_lines(struct MuttWindow *win, struct EnvelopeWindowData *wdata, int row)
390{
391 struct Email *e = wdata->email;
392
393 draw_header(win, row++, HDR_CRYPT);
394
396 return 0;
397
398 // We'll probably need two lines for 'Security:' and 'Sign as:'
399 int used = 2;
400 if ((e->security & (SEC_ENCRYPT | SEC_SIGN)) == (SEC_ENCRYPT | SEC_SIGN))
401 {
403 mutt_window_addstr(win, _("Sign, Encrypt"));
404 }
405 else if (e->security & SEC_ENCRYPT)
406 {
408 mutt_window_addstr(win, _("Encrypt"));
409 }
410 else if (e->security & SEC_SIGN)
411 {
413 mutt_window_addstr(win, _("Sign"));
414 }
415 else
416 {
417 /* L10N: This refers to the encryption of the email, e.g. "Security: None" */
419 mutt_window_addstr(win, _("None"));
420 used = 1; // 'Sign as:' won't be needed
421 }
423
424 if ((e->security & (SEC_ENCRYPT | SEC_SIGN)))
425 {
426 if (((WithCrypto & APPLICATION_PGP) != 0) && (e->security & APPLICATION_PGP))
427 {
428 if ((e->security & SEC_INLINE))
429 mutt_window_addstr(win, _(" (inline PGP)"));
430 else
431 mutt_window_addstr(win, _(" (PGP/MIME)"));
432 }
433 else if (((WithCrypto & APPLICATION_SMIME) != 0) && (e->security & APPLICATION_SMIME))
434 mutt_window_addstr(win, _(" (S/MIME)"));
435 }
436
437 const bool c_crypt_opportunistic_encrypt = cs_subset_bool(wdata->sub, "crypt_opportunistic_encrypt");
438 if (c_crypt_opportunistic_encrypt && (e->security & SEC_OPPENCRYPT))
439 mutt_window_addstr(win, _(" (OppEnc mode)"));
440
442
443 if (((WithCrypto & APPLICATION_PGP) != 0) &&
444 (e->security & APPLICATION_PGP) && (e->security & SEC_SIGN))
445 {
446 draw_header(win, row++, HDR_CRYPTINFO);
447 const char *const c_pgp_sign_as = cs_subset_string(wdata->sub, "pgp_sign_as");
448 mutt_window_printf(win, "%s", c_pgp_sign_as ? c_pgp_sign_as : _("<default>"));
449 }
450
451 if (((WithCrypto & APPLICATION_SMIME) != 0) &&
453 {
454 draw_header(win, row++, HDR_CRYPTINFO);
455 const char *const c_smime_sign_as = cs_subset_string(wdata->sub, "pgp_sign_as");
456 mutt_window_printf(win, "%s", c_smime_sign_as ? c_smime_sign_as : _("<default>"));
457 }
458
459 const char *const c_smime_encrypt_with = cs_subset_string(wdata->sub, "smime_encrypt_with");
460 if (((WithCrypto & APPLICATION_SMIME) != 0) && (e->security & APPLICATION_SMIME) &&
461 (e->security & SEC_ENCRYPT) && c_smime_encrypt_with)
462 {
463 draw_floating(win, 40, row - 1, _("Encrypt with: "));
464 mutt_window_printf(win, "%s", NONULL(c_smime_encrypt_with));
465 }
466
467#ifdef USE_AUTOCRYPT
468 const bool c_autocrypt = cs_subset_bool(wdata->sub, "autocrypt");
469 if (c_autocrypt)
470 {
471 draw_header(win, row, HDR_AUTOCRYPT);
472 if (e->security & SEC_AUTOCRYPT)
473 {
475 mutt_window_addstr(win, _("Encrypt"));
476 }
477 else
478 {
480 mutt_window_addstr(win, _("Off"));
481 }
482
483 /* L10N: The autocrypt compose menu Recommendation field.
484 Displays the output of the recommendation engine
485 (Off, No, Discouraged, Available, Yes) */
486 draw_floating(win, 40, row, _("Recommendation: "));
488
489 used++;
490 }
491#endif
492 return used;
493}
494
495#ifdef MIXMASTER
502static void draw_mix_line(struct ListHead *chain, struct MuttWindow *win, int row)
503{
504 char *t = NULL;
505
506 draw_header(win, row, HDR_MIX);
507
508 if (STAILQ_EMPTY(chain))
509 {
510 mutt_window_addstr(win, _("<no chain defined>"));
512 return;
513 }
514
515 int c = 12;
516 struct ListNode *np = NULL;
517 STAILQ_FOREACH(np, chain, entries)
518 {
519 t = np->data;
520 if (t && (t[0] == '0') && (t[1] == '\0'))
521 t = "<random>";
522
523 if (c + mutt_str_len(t) + 2 >= win->state.cols)
524 break;
525
526 mutt_window_addstr(win, NONULL(t));
527 if (STAILQ_NEXT(np, entries))
528 mutt_window_addstr(win, ", ");
529
530 c += mutt_str_len(t) + 2;
531 }
532}
533#endif
534
544static int draw_envelope_addr(int field, struct AddressList *al,
545 struct MuttWindow *win, int row, size_t max_lines)
546{
547 draw_header(win, row, field);
548
549 struct ListHead list = STAILQ_HEAD_INITIALIZER(list);
550 int count = mutt_addrlist_write_list(al, &list);
551
552 int lines_used = 1;
553 int width_left = win->state.cols - MaxHeaderWidth;
554 char more[32] = { 0 };
555 int more_len = 0;
556
557 char *sep = NULL;
558 struct ListNode *next = NULL;
559 struct ListNode *np = NULL;
560 STAILQ_FOREACH(np, &list, entries)
561 {
562 next = STAILQ_NEXT(np, entries);
563 int addr_len = mutt_strwidth(np->data);
564 if (next)
565 {
566 sep = ", ";
567 addr_len += 2;
568 }
569 else
570 {
571 sep = "";
572 }
573
574 count--;
575 try_again:
576 more_len = snprintf(more, sizeof(more),
577 ngettext("(+%d more)", "(+%d more)", count), count);
578 mutt_debug(LL_DEBUG3, "text: '%s' len: %d\n", more, more_len);
579
580 int reserve = ((count > 0) && (lines_used == max_lines)) ? more_len : 0;
581 mutt_debug(LL_DEBUG3, "processing: %s (al:%d, wl:%d, r:%d, lu:%d)\n",
582 np->data, addr_len, width_left, reserve, lines_used);
583 if (addr_len >= (width_left - reserve))
584 {
585 mutt_debug(LL_DEBUG3, "not enough space\n");
586 if (lines_used == max_lines)
587 {
588 mutt_debug(LL_DEBUG3, "no more lines\n");
589 mutt_debug(LL_DEBUG3, "truncating: %s\n", np->data);
590 mutt_paddstr(win, width_left, np->data);
591 break;
592 }
593
594 if (width_left == (win->state.cols - MaxHeaderWidth))
595 {
596 mutt_debug(LL_DEBUG3, "couldn't print: %s\n", np->data);
597 mutt_paddstr(win, width_left, np->data);
598 break;
599 }
600
601 mutt_debug(LL_DEBUG3, "start a new line\n");
603 row++;
604 lines_used++;
605 width_left = win->state.cols - MaxHeaderWidth;
607 goto try_again;
608 }
609
610 if (addr_len < width_left)
611 {
612 mutt_debug(LL_DEBUG3, "space for: %s\n", np->data);
613 mutt_window_addstr(win, np->data);
614 mutt_window_addstr(win, sep);
615 width_left -= addr_len;
616 }
617 mutt_debug(LL_DEBUG3, "%d addresses remaining\n", count);
618 mutt_debug(LL_DEBUG3, "%ld lines remaining\n", max_lines - lines_used);
619 }
620 mutt_list_free(&list);
621
622 if (count > 0)
623 {
624 mutt_window_move(win, win->state.cols - more_len, row);
626 mutt_window_addstr(win, more);
628 mutt_debug(LL_DEBUG3, "%d more (len %d)\n", count, more_len);
629 }
630 else
631 {
633 }
634
635 for (int i = lines_used; i < max_lines; i++)
636 {
637 mutt_window_move(win, 0, row + i);
639 }
640
641 mutt_debug(LL_DEBUG3, "used %d lines\n", lines_used);
642 return lines_used;
643}
644
652static int draw_envelope_user_hdrs(struct MuttWindow *win,
653 struct EnvelopeWindowData *wdata, int row)
654{
655 const char *overflow_text = "...";
656 int rows_used = 0;
657
658 struct ListNode *first = STAILQ_FIRST(&wdata->email->env->userhdrs);
659 if (!first)
660 return rows_used;
661
662 /* Draw first entry on same line as prompt */
664 mutt_paddstr(win,
667 first->data);
668 rows_used++;
669
670 /* Draw any following entries on their own line */
671 struct ListNode *np = STAILQ_NEXT(first, entries);
672 if (!np)
673 return rows_used;
674
675 STAILQ_FOREACH_FROM(np, &wdata->email->env->userhdrs, entries)
676 {
677 if ((rows_used == (MAX_USER_HDR_ROWS - 1)) && STAILQ_NEXT(np, entries))
678 {
679 draw_header_content(win, row + rows_used, HDR_CUSTOM_HEADERS, overflow_text);
680 rows_used++;
681 break;
682 }
683 draw_header_content(win, row + rows_used, HDR_CUSTOM_HEADERS, np->data);
684 rows_used++;
685 }
686 return rows_used;
687}
688
694static void draw_envelope(struct MuttWindow *win, struct EnvelopeWindowData *wdata)
695{
696 struct Email *e = wdata->email;
697 const char *fcc = mutt_buffer_string(wdata->fcc);
698 const int cols = win->state.cols - MaxHeaderWidth;
699
701 int row = draw_envelope_addr(HDR_FROM, &e->env->from, win, 0, 1);
702
703#ifdef USE_NNTP
704 if (wdata->is_news)
705 {
706 draw_header(win, row++, HDR_NEWSGROUPS);
707 mutt_paddstr(win, cols, NONULL(e->env->newsgroups));
708
709 draw_header(win, row++, HDR_FOLLOWUPTO);
710 mutt_paddstr(win, cols, NONULL(e->env->followup_to));
711
712 const bool c_x_comment_to = cs_subset_bool(wdata->sub, "x_comment_to");
713 if (c_x_comment_to)
714 {
715 draw_header(win, row++, HDR_XCOMMENTTO);
716 mutt_paddstr(win, cols, NONULL(e->env->x_comment_to));
717 }
718 }
719 else
720#endif
721 {
722 row += draw_envelope_addr(HDR_TO, &e->env->to, win, row, wdata->to_rows);
723 row += draw_envelope_addr(HDR_CC, &e->env->cc, win, row, wdata->cc_rows);
724 row += draw_envelope_addr(HDR_BCC, &e->env->bcc, win, row, wdata->bcc_rows);
725 }
726
727 draw_header(win, row++, HDR_SUBJECT);
728 mutt_paddstr(win, cols, NONULL(e->env->subject));
729
730 row += draw_envelope_addr(HDR_REPLYTO, &e->env->reply_to, win, row, 1);
731
732 draw_header(win, row++, HDR_FCC);
733 mutt_paddstr(win, cols, fcc);
734
735 if (WithCrypto)
736 row += draw_crypt_lines(win, wdata, row);
737
738#ifdef MIXMASTER
739 draw_mix_line(&e->chain, win, row++);
740#endif
741 const bool c_compose_show_user_headers = cs_subset_bool(wdata->sub, "compose_show_user_headers");
742 if (c_compose_show_user_headers)
743 row += draw_envelope_user_hdrs(win, wdata, row);
744
746}
747
751static int env_recalc(struct MuttWindow *win)
752{
753 struct EnvelopeWindowData *wdata = win->wdata;
754
755 const int cur_rows = win->state.rows;
756 const int new_rows = calc_envelope(win, wdata);
757
758 if (new_rows != cur_rows)
759 {
760 win->req_rows = new_rows;
762 }
763
764 win->actions |= WA_REPAINT;
765 mutt_debug(LL_DEBUG5, "recalc done, request WA_REPAINT\n");
766 return 0;
767}
768
772static int env_repaint(struct MuttWindow *win)
773{
774 struct EnvelopeWindowData *wdata = win->wdata;
775
776 draw_envelope(win, wdata);
777 mutt_debug(LL_DEBUG5, "repaint done\n");
778 return 0;
779}
780
784static int env_color_observer(struct NotifyCallback *nc)
785{
786 if (nc->event_type != NT_COLOR)
787 return 0;
788 if (!nc->global_data || !nc->event_data)
789 return -1;
790
791 struct EventColor *ev_c = nc->event_data;
792 struct MuttWindow *win_env = nc->global_data;
793
794 enum ColorId cid = ev_c->cid;
795
796 switch (cid)
797 {
798 case MT_COLOR_BOLD:
804 case MT_COLOR_NORMAL:
805 case MT_COLOR_STATUS:
806 case MT_COLOR_MAX: // Sent on `uncolor *`
807 mutt_debug(LL_DEBUG5, "color done, request WA_REPAINT\n");
808 win_env->actions |= WA_REPAINT;
809 break;
810
811 default:
812 break;
813 }
814 return 0;
815}
816
821{
822 if (nc->event_type != NT_CONFIG)
823 return 0;
824 if (!nc->global_data || !nc->event_data)
825 return -1;
826
827 struct EventConfig *ev_c = nc->event_data;
828 struct MuttWindow *win_env = nc->global_data;
829
830 switch (ev_c->name[0])
831 {
832 case 'a':
833 if (mutt_str_equal(ev_c->name, "autocrypt"))
834 break;
835 return 0;
836 case 'c':
837 if (mutt_str_equal(ev_c->name, "compose_show_user_headers") ||
838 mutt_str_equal(ev_c->name, "crypt_opportunistic_encrypt"))
839 {
840 break;
841 }
842 return 0;
843 case 'p':
844 if (mutt_str_equal(ev_c->name, "pgp_sign_as"))
845 break;
846 return 0;
847 case 's':
848 if (mutt_str_equal(ev_c->name, "smime_encrypt_with"))
849 break;
850 return 0;
851 case 'x':
852 if (mutt_str_equal(ev_c->name, "x_comment_to"))
853 break;
854 return 0;
855 default:
856 return 0;
857 }
858
859 win_env->actions |= WA_RECALC;
860 mutt_debug(LL_DEBUG5, "config done, request WA_RECALC\n");
861 return 0;
862}
863
867static int env_email_observer(struct NotifyCallback *nc)
868{
869 if ((nc->event_type != NT_EMAIL) && (nc->event_type != NT_ENVELOPE))
870 return 0;
871 if (!nc->global_data)
872 return -1;
873
874 struct MuttWindow *win_env = nc->global_data;
875
876 // pgp/smime/autocrypt menu, or external change
877 if (nc->event_type == NT_EMAIL)
878 {
879 struct EnvelopeWindowData *wdata = win_env->wdata;
880 update_crypt_info(wdata);
881 }
882
883 win_env->actions |= WA_RECALC;
884 mutt_debug(LL_DEBUG5, "email done, request WA_RECALC\n");
885 return 0;
886}
887
892{
893 if (nc->event_type != NT_HEADER)
894 return 0;
895 if (!nc->global_data || !nc->event_data)
896 return -1;
897
898 const struct EventHeader *ev_h = nc->event_data;
899 struct MuttWindow *win_env = nc->global_data;
900 struct EnvelopeWindowData *wdata = win_env->wdata;
901
902 struct Envelope *env = wdata->email->env;
903
905 {
906 header_set(&env->userhdrs, ev_h->header);
907 mutt_debug(LL_DEBUG5, "header done, request reflow\n");
908 win_env->actions |= WA_RECALC;
909 return 0;
910 }
911
913 {
914 struct ListNode *removed = header_find(&env->userhdrs, ev_h->header);
915 if (removed)
916 {
917 header_free(&env->userhdrs, removed);
918 mutt_debug(LL_DEBUG5, "header done, request reflow\n");
919 win_env->actions |= WA_RECALC;
920 }
921 return 0;
922 }
923
924 return 0;
925}
926
931{
932 if (nc->event_type != NT_WINDOW)
933 return 0;
934 if (!nc->global_data || !nc->event_data)
935 return -1;
936
937 struct MuttWindow *win_env = nc->global_data;
938 struct EventWindow *ev_w = nc->event_data;
939 if (ev_w->win != win_env)
940 return 0;
941
943 {
944 win_env->actions |= WA_RECALC;
945 mutt_debug(LL_DEBUG5, "window state done, request WA_RECALC\n");
946 }
947 else if (nc->event_subtype == NT_WINDOW_DELETE)
948 {
949 struct EnvelopeWindowData *wdata = win_env->wdata;
950
956 mutt_debug(LL_DEBUG5, "window delete done\n");
957 }
958
959 return 0;
960}
961
969struct MuttWindow *env_window_new(struct Email *e, struct Buffer *fcc, struct ConfigSubset *sub)
970{
972
975 HDR_ATTACH_TITLE - 1);
976
982
983 struct EnvelopeWindowData *wdata = env_wdata_new();
984 wdata->fcc = fcc;
985 wdata->email = e;
986 wdata->sub = sub;
987 wdata->is_news = OptNewsSend;
988
989 win_env->wdata = wdata;
990 win_env->wdata_free = env_wdata_free;
991 win_env->recalc = env_recalc;
992 win_env->repaint = env_repaint;
993
994 return win_env;
995}
size_t mutt_addrlist_write_list(const struct AddressList *al, struct ListHead *list)
Write Addresses to a List.
Definition: address.c:1201
Email Address Handling.
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
Color and attribute parsing.
ColorId
List of all colored objects.
Definition: color.h:35
@ MT_COLOR_COMPOSE_SECURITY_ENCRYPT
Mail will be encrypted.
Definition: color.h:43
@ MT_COLOR_MAX
Definition: color.h:88
@ MT_COLOR_STATUS
Status bar (takes a pattern)
Definition: color.h:71
@ 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:54
@ 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:317
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
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:816
size_t mutt_strwidth(const char *s)
Measure a string's width in screen cells.
Definition: curs_lib.c:907
void header_free(struct ListHead *hdrlist, struct ListNode *target)
Free and remove a header from a header list.
Definition: email.c:245
struct ListNode * header_set(struct ListHead *hdrlist, const char *header)
Set a header value in a list.
Definition: email.c:233
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:180
Structs that make up an email.
@ NT_HEADER_CHANGE
An existing header has been changed.
Definition: email.h:175
@ NT_HEADER_ADD
Header has been added.
Definition: email.h:173
@ NT_HEADER_DELETE
Header has been removed.
Definition: email.h:174
void update_crypt_info(struct EnvelopeWindowData *wdata)
Update the crypto info.
Definition: functions.c:146
HeaderField
Ordered list of headers for the compose screen.
Definition: private.h:34
@ HDR_SUBJECT
"Subject:" field
Definition: private.h:39
@ HDR_REPLYTO
"Reply-To:" field
Definition: private.h:40
@ HDR_AUTOCRYPT
"Autocrypt:" and "Recommendation:" fields
Definition: private.h:48
@ HDR_FCC
"Fcc:" (save folder) field
Definition: private.h:41
@ HDR_ATTACH_TITLE
The "-- Attachments" line.
Definition: private.h:56
@ HDR_CRYPT
"Security:" field (encryption/signing info)
Definition: private.h:45
@ HDR_CC
"Cc:" field
Definition: private.h:37
@ HDR_MIX
"Mix:" field (Mixmaster chain)
Definition: private.h:43
@ HDR_TO
"To:" field
Definition: private.h:36
@ HDR_BCC
"Bcc:" field
Definition: private.h:38
@ HDR_CUSTOM_HEADERS
"Headers:" field
Definition: private.h:55
@ HDR_FOLLOWUPTO
"Followup-To:" field
Definition: private.h:52
@ HDR_XCOMMENTTO
"X-Comment-To:" field
Definition: private.h:53
@ HDR_NEWSGROUPS
"Newsgroups:" field
Definition: private.h:51
@ HDR_CRYPTINFO
"Sign as:" field (encryption/signing info)
Definition: private.h:46
@ HDR_FROM
"From:" field
Definition: private.h:35
struct EnvelopeWindowData * env_wdata_new(void)
Create new Envelope Data.
Definition: wdata.c:55
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:544
static const char *const AutocryptRecUiFlags[]
Definition: window.c:132
static void draw_header(struct MuttWindow *win, int row, enum HeaderField field)
Draw an aligned label.
Definition: window.c:359
int HeaderPadding[HDR_ATTACH_TITLE]
Definition: window.c:86
static void draw_envelope(struct MuttWindow *win, struct EnvelopeWindowData *wdata)
Write the email headers to the compose window.
Definition: window.c:694
static void draw_floating(struct MuttWindow *win, int col, int row, const char *text)
Draw a floating label.
Definition: window.c:346
static void draw_mix_line(struct ListHead *chain, struct MuttWindow *win, int row)
Redraw the Mixmaster chain.
Definition: window.c:502
const char *const Prompts[]
Definition: window.c:89
#define MAX_USER_HDR_ROWS
Maximum number of rows to use for the Headers: field.
Definition: window.c:84
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:652
struct MuttWindow * env_window_new(struct Email *e, struct Buffer *fcc, struct ConfigSubset *sub)
Create the Envelope Window.
Definition: window.c:969
int MaxHeaderWidth
Definition: window.c:87
static int calc_envelope(struct MuttWindow *win, struct EnvelopeWindowData *wdata)
Calculate how many rows the envelope will need.
Definition: window.c:305
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:375
static int calc_address(struct AddressList *al, struct ListHead *slist, short cols, short *srows)
Calculate how many rows an AddressList will need.
Definition: window.c:219
static int calc_user_hdrs(const struct ListHead *hdrs)
Calculate how many rows are needed for user-defined headers.
Definition: window.c:286
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:263
#define MAX_ADDR_ROWS
Maximum number of rows to use for the To:, Cc:, Bcc: fields.
Definition: window.c:81
static void calc_header_width_padding(int idx, const char *header, bool calc_max)
Calculate the width needed for the compose labels.
Definition: window.c:162
static int draw_crypt_lines(struct MuttWindow *win, struct EnvelopeWindowData *wdata, int row)
Update the encryption info in the compose window.
Definition: window.c:389
static void init_header_padding(void)
Calculate how much padding the compose table will need.
Definition: window.c:181
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
static int env_email_observer(struct NotifyCallback *nc)
Notification that the Email has changed - Implements observer_t -.
Definition: window.c:867
static int env_color_observer(struct NotifyCallback *nc)
Notification that a Color has changed - Implements observer_t -.
Definition: window.c:784
static int env_window_observer(struct NotifyCallback *nc)
Notification that a Window has changed - Implements observer_t -.
Definition: window.c:930
static int env_config_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t -.
Definition: window.c:820
static int env_header_observer(struct NotifyCallback *nc)
Notification that a User Header has changed - Implements observer_t -.
Definition: window.c:891
static int env_recalc(struct MuttWindow *win)
Recalculate the Window data - Implements MuttWindow::recalc() -.
Definition: window.c:751
static int env_repaint(struct MuttWindow *win)
Repaint the Window - Implements MuttWindow::repaint() -.
Definition: window.c:772
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:122
@ LL_DEBUG3
Log at debug level 3.
Definition: logging.h:42
@ LL_DEBUG5
Log at debug level 5.
Definition: logging.h:44
#define MIN(a, b)
Definition: memory.h:31
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:228
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:189
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:807
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:567
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:65
struct AttrColor * mutt_curses_set_color_by_id(enum ColorId cid)
Set the colour and attributes by the colour id.
Definition: mutt_curses.c:81
void mutt_window_clear(struct MuttWindow *win)
Clear a Window.
Definition: mutt_window.c:695
void mutt_window_reflow(struct MuttWindow *win)
Resize a Window and its children.
Definition: mutt_window.c:340
int mutt_window_printf(struct MuttWindow *win, const char *fmt,...)
Write a formatted string to a Window.
Definition: mutt_window.c:424
struct MuttWindow * mutt_window_new(enum WindowType type, enum MuttWindowOrientation orient, enum MuttWindowSize size, int cols, int rows)
Create a new Window.
Definition: mutt_window.c:181
int mutt_window_move(struct MuttWindow *win, int col, int row)
Move the cursor in a Window.
Definition: mutt_window.c:293
int mutt_window_addstr(struct MuttWindow *win, const char *str)
Write a string to a Window.
Definition: mutt_window.c:409
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:242
int mutt_window_mvprintw(struct MuttWindow *win, int col, int row, const char *fmt,...)
Move the cursor and write a formatted string to a Window.
Definition: mutt_window.c:322
#define WA_RECALC
Recalculate the contents of the Window.
Definition: mutt_window.h:110
@ WT_CUSTOM
Window with a custom drawing function.
Definition: mutt_window.h:95
@ 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.
Definition: mutt_window.h:207
@ NT_WINDOW_DELETE
Window is about to be deleted.
Definition: mutt_window.h:206
#define WA_REPAINT
Redraw the contents of the Window.
Definition: mutt_window.h:111
#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:85
#define SEC_AUTOCRYPT
(Autocrypt) Message will be, or was Autocrypt encrypt+signed
Definition: lib.h:87
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: lib.h:86
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:90
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:91
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:78
#define WithCrypto
Definition: lib.h:116
#define SEC_SIGN
Email is signed.
Definition: lib.h:79
@ NT_WINDOW
MuttWindow has changed, NotifyWindow, EventWindow.
Definition: notify_type.h:55
@ 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
Handling of global boolean variables.
bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:51
Progress Bar Window Data.
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:324
#define STAILQ_FIRST(head)
Definition: queue.h:350
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
#define STAILQ_EMPTY(head)
Definition: queue.h:348
#define STAILQ_NEXT(elm, field)
Definition: queue.h:400
#define STAILQ_FOREACH_FROM(var, head, field)
Definition: queue.h:357
Sidebar functions.
GUI display the mailboxes in a side panel.
#define NONULL(x)
Definition: string2.h:37
String manipulation buffer.
Definition: buffer.h:34
A set of inherited config items.
Definition: subset.h:47
The envelope/body of an email.
Definition: email.h:37
struct Envelope * env
Envelope information.
Definition: email.h:66
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition: email.h:41
struct ListHead chain
Mixmaster chain.
Definition: email.h:90
struct Notify * notify
Notifications: NotifyEmail, EventEmail.
Definition: email.h:71
Data to fill the Envelope Window.
Definition: wdata.h:39
struct ListHead cc_list
'Cc:' list of addresses
Definition: wdata.h:45
bool is_news
Email is a news article.
Definition: wdata.h:54
struct ListHead bcc_list
'Bcc:' list of addresses
Definition: wdata.h:46
struct Buffer * fcc
Where the outgoing Email will be saved.
Definition: wdata.h:42
struct Email * email
Email being composed.
Definition: wdata.h:41
short sec_rows
Number of rows used by the security fields.
Definition: wdata.h:51
short cc_rows
Number of rows used by the 'Cc:' field.
Definition: wdata.h:49
struct ConfigSubset * sub
Inherited config items.
Definition: wdata.h:40
enum AutocryptRec autocrypt_rec
Autocrypt recommendation.
Definition: wdata.h:57
struct ListHead to_list
'To:' list of addresses
Definition: wdata.h:44
short to_rows
Number of rows used by the 'To:' field.
Definition: wdata.h:48
short bcc_rows
Number of rows used by the 'Bcc:' field.
Definition: wdata.h:50
The header of an Email.
Definition: envelope.h:57
struct ListHead userhdrs
user defined headers
Definition: envelope.h:87
struct AddressList to
Email's 'To' list.
Definition: envelope.h:60
char * followup_to
List of 'followup-to' fields.
Definition: envelope.h:81
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:82
char * newsgroups
List of newsgroups.
Definition: envelope.h:79
struct AddressList cc
Email's 'Cc' list.
Definition: envelope.h:61
char * subject
Email's subject.
Definition: envelope.h:70
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:53
enum ColorId cid
Colour ID that has changed.
Definition: notify2.h:54
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:182
char * header
The contents of the header.
Definition: email.h:183
An Event that happened to a Window.
Definition: mutt_window.h:216
struct MuttWindow * win
Window that changed.
Definition: mutt_window.h:217
A List node for strings.
Definition: list.h:35
char * data
String.
Definition: list.h:36
int(* repaint)(struct MuttWindow *win)
Definition: mutt_window.h:182
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:127
void * wdata
Private data.
Definition: mutt_window.h:145
struct Notify * notify
Notifications: NotifyWindow, EventWindow.
Definition: mutt_window.h:138
short req_rows
Number of rows required.
Definition: mutt_window.h:125
int(* recalc)(struct MuttWindow *win)
Definition: mutt_window.h:171
void(* wdata_free)(struct MuttWindow *win, void **ptr)
Definition: mutt_window.h:160
struct MuttWindow * parent
Parent Window.
Definition: mutt_window.h:135
WindowActionFlags actions
Actions to be performed, e.g. WA_RECALC.
Definition: mutt_window.h:132
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
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