NeoMutt  2024-04-25-91-gb0e085
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
window.c
Go to the documentation of this file.
1
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 "wdata.h"
77#ifdef ENABLE_NLS
78#include <libintl.h>
79#endif
80
82#define MAX_ADDR_ROWS 5
83
85#define MAX_USER_HDR_ROWS 5
86
88static int HeaderPadding[HDR_ATTACH_TITLE] = { 0 };
90static int MaxHeaderWidth = 0;
91
93const char *const Prompts[] = {
94 /* L10N: Compose menu field. May not want to translate. */
95 N_("From: "),
96 /* L10N: Compose menu field. May not want to translate. */
97 N_("To: "),
98 /* L10N: Compose menu field. May not want to translate. */
99 N_("Cc: "),
100 /* L10N: Compose menu field. May not want to translate. */
101 N_("Bcc: "),
102 /* L10N: Compose menu field. May not want to translate. */
103 N_("Subject: "),
104 /* L10N: Compose menu field. May not want to translate. */
105 N_("Reply-To: "),
106 /* L10N: Compose menu field. May not want to translate. */
107 N_("Fcc: "),
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 /* L10N: Compose menu field. May not want to translate. */
121 N_("Newsgroups: "),
122 /* L10N: Compose menu field. May not want to translate. */
123 N_("Followup-To: "),
124 /* L10N: Compose menu field. May not want to translate. */
125 N_("X-Comment-To: "),
126 N_("Headers: "),
127};
128
129#ifdef USE_AUTOCRYPT
131static const char *const AutocryptRecUiFlags[] = {
132 /* L10N: Autocrypt recommendation flag: off.
133 This is displayed when Autocrypt is turned off. */
134 N_("Off"),
135 /* L10N: Autocrypt recommendation flag: no.
136 This is displayed when Autocrypt cannot encrypt to the recipients. */
137 N_("No"),
138 /* L10N: Autocrypt recommendation flag: discouraged.
139 This is displayed when Autocrypt believes encryption should not be used.
140 This might occur if one of the recipient Autocrypt Keys has not been
141 used recently, or if the only key available is a Gossip Header key. */
142 N_("Discouraged"),
143 /* L10N: Autocrypt recommendation flag: available.
144 This is displayed when Autocrypt believes encryption is possible, but
145 leaves enabling it up to the sender. Probably because "prefer encrypt"
146 is not set in both the sender and recipient keys. */
147 N_("Available"),
148 /* L10N: Autocrypt recommendation flag: yes.
149 This is displayed when Autocrypt would normally enable encryption
150 automatically. */
151 N_("Yes"),
152};
153#endif
154
161static void calc_header_width_padding(int idx, const char *header, bool calc_max)
162{
163 int width;
164
165 HeaderPadding[idx] = mutt_str_len(header);
166 width = mutt_strwidth(header);
167 if (calc_max && (MaxHeaderWidth < width))
168 MaxHeaderWidth = width;
169 HeaderPadding[idx] -= width;
170}
171
180static void init_header_padding(void)
181{
182 static bool done = false;
183
184 if (done)
185 return;
186 done = true;
187
188 for (int i = 0; i < HDR_ATTACH_TITLE; i++)
189 {
190 if (i == HDR_CRYPTINFO)
191 continue;
192 calc_header_width_padding(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 {
203 if (HeaderPadding[i] < 0)
204 HeaderPadding[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 int 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
309 struct Envelope *env = e->env;
310 const int cols = win->state.cols - MaxHeaderWidth;
311
312 if (wdata->is_news)
313 {
314 rows += 2; // 'Newsgroups:' and 'Followup-To:'
315 const bool c_x_comment_to = cs_subset_bool(wdata->sub, "x_comment_to");
316 if (c_x_comment_to)
317 rows++;
318 }
319 else
320 {
321 rows += calc_address(&env->to, cols, &wdata->to_rows);
322 rows += calc_address(&env->cc, cols, &wdata->cc_rows);
323 rows += calc_address(&env->bcc, cols, &wdata->bcc_rows);
324 }
325 rows += calc_security(e, &wdata->sec_rows, wdata->sub);
326 const bool c_compose_show_user_headers = cs_subset_bool(wdata->sub, "compose_show_user_headers");
327 if (c_compose_show_user_headers)
328 rows += calc_user_hdrs(&env->userhdrs);
329
330 return rows;
331}
332
340static void draw_floating(struct MuttWindow *win, int col, int row, const char *text)
341{
343 mutt_window_mvprintw(win, col, row, "%s", text);
345}
346
353static void draw_header(struct MuttWindow *win, int row, enum HeaderField field)
354{
356 mutt_window_mvprintw(win, 0, row, "%*s", HeaderPadding[field], _(Prompts[field]));
358}
359
369static void draw_header_content(struct MuttWindow *win, int row,
370 enum HeaderField field, const char *content)
371{
372 mutt_window_move(win, HeaderPadding[field], row);
373 mutt_paddstr(win, win->state.cols - HeaderPadding[field], content);
374}
375
383static int draw_crypt_lines(struct MuttWindow *win, struct EnvelopeWindowData *wdata, int row)
384{
385 struct Email *e = wdata->email;
386
387 draw_header(win, row++, HDR_CRYPT);
388
390 return 0;
391
392 // We'll probably need two lines for 'Security:' and 'Sign as:'
393 int used = 2;
394 if ((e->security & (SEC_ENCRYPT | SEC_SIGN)) == (SEC_ENCRYPT | SEC_SIGN))
395 {
397 mutt_window_addstr(win, _("Sign, Encrypt"));
398 }
399 else if (e->security & SEC_ENCRYPT)
400 {
402 mutt_window_addstr(win, _("Encrypt"));
403 }
404 else if (e->security & SEC_SIGN)
405 {
407 mutt_window_addstr(win, _("Sign"));
408 }
409 else
410 {
411 /* L10N: This refers to the encryption of the email, e.g. "Security: None" */
413 mutt_window_addstr(win, _("None"));
414 used = 1; // 'Sign as:' won't be needed
415 }
417
418 if ((e->security & (SEC_ENCRYPT | SEC_SIGN)))
419 {
420 if (((WithCrypto & APPLICATION_PGP) != 0) && (e->security & APPLICATION_PGP))
421 {
422 if ((e->security & SEC_INLINE))
423 mutt_window_addstr(win, _(" (inline PGP)"));
424 else
425 mutt_window_addstr(win, _(" (PGP/MIME)"));
426 }
427 else if (((WithCrypto & APPLICATION_SMIME) != 0) && (e->security & APPLICATION_SMIME))
428 {
429 mutt_window_addstr(win, _(" (S/MIME)"));
430 }
431 }
432
433 const bool c_crypt_opportunistic_encrypt = cs_subset_bool(wdata->sub, "crypt_opportunistic_encrypt");
434 if (c_crypt_opportunistic_encrypt && (e->security & SEC_OPPENCRYPT))
435 mutt_window_addstr(win, _(" (OppEnc mode)"));
436
438
439 if (((WithCrypto & APPLICATION_PGP) != 0) &&
440 (e->security & APPLICATION_PGP) && (e->security & SEC_SIGN))
441 {
442 draw_header(win, row++, HDR_CRYPTINFO);
443 const char *const c_pgp_sign_as = cs_subset_string(wdata->sub, "pgp_sign_as");
444 mutt_window_printf(win, "%s", c_pgp_sign_as ? c_pgp_sign_as : _("<default>"));
445 }
446
447 if (((WithCrypto & APPLICATION_SMIME) != 0) &&
449 {
450 draw_header(win, row++, HDR_CRYPTINFO);
451 const char *const c_smime_sign_as = cs_subset_string(wdata->sub, "smime_sign_as");
452 mutt_window_printf(win, "%s", c_smime_sign_as ? c_smime_sign_as : _("<default>"));
453 }
454
455 const char *const c_smime_encrypt_with = cs_subset_string(wdata->sub, "smime_encrypt_with");
456 if (((WithCrypto & APPLICATION_SMIME) != 0) && (e->security & APPLICATION_SMIME) &&
457 (e->security & SEC_ENCRYPT) && c_smime_encrypt_with)
458 {
459 draw_floating(win, 40, row - 1, _("Encrypt with: "));
460 mutt_window_printf(win, "%s", NONULL(c_smime_encrypt_with));
461 }
462
463#ifdef USE_AUTOCRYPT
464 const bool c_autocrypt = cs_subset_bool(wdata->sub, "autocrypt");
465 if (c_autocrypt)
466 {
467 draw_header(win, row, HDR_AUTOCRYPT);
468 if (e->security & SEC_AUTOCRYPT)
469 {
471 mutt_window_addstr(win, _("Encrypt"));
472 }
473 else
474 {
476 mutt_window_addstr(win, _("Off"));
477 }
478
479 /* L10N: The autocrypt compose menu Recommendation field.
480 Displays the output of the recommendation engine
481 (Off, No, Discouraged, Available, Yes) */
482 draw_floating(win, 40, row, _("Recommendation: "));
484
485 used++;
486 }
487#endif
488 return used;
489}
490
500static int draw_envelope_addr(int field, struct AddressList *al,
501 struct MuttWindow *win, int row, size_t max_lines)
502{
503 draw_header(win, row, field);
504
505 struct ListHead list = STAILQ_HEAD_INITIALIZER(list);
506 int count = mutt_addrlist_count_recips(al);
507
508 int lines_used = 1;
509 int width_left = win->state.cols - MaxHeaderWidth;
510 char more[32] = { 0 };
511 int more_len = 0;
512
513 struct Buffer *buf = buf_pool_get();
514 bool in_group = false;
515 char *sep = NULL;
516 struct Address *addr = NULL;
517 TAILQ_FOREACH(addr, al, entries)
518 {
519 struct Address *next = TAILQ_NEXT(addr, entries);
520
521 if (addr->group)
522 {
523 in_group = true;
524 }
525
526 buf_reset(buf);
527 mutt_addr_write(buf, addr, true);
528 size_t addr_len = buf_len(buf);
529
530 sep = "";
531 if (!addr->group)
532 {
533 // group terminator
534 if (in_group && next && !next->mailbox && !next->personal)
535 {
536 sep = ";";
537 addr_len += 1;
538 in_group = false;
539 }
540 else if (next)
541 {
542 sep = ", ";
543 addr_len += 2;
544 }
545 }
546
547 count--;
548 try_again:
549 more_len = snprintf(more, sizeof(more),
550 ngettext("(+%d more)", "(+%d more)", count), count);
551 mutt_debug(LL_DEBUG3, "text: '%s' len: %d\n", more, more_len);
552
553 int reserve = ((count > 0) && (lines_used == max_lines)) ? more_len : 0;
554 mutt_debug(LL_DEBUG3, "processing: %s (al:%zu, wl:%d, r:%d, lu:%d)\n",
555 buf_string(buf), addr_len, width_left, reserve, lines_used);
556 if (addr_len >= (width_left - reserve))
557 {
558 mutt_debug(LL_DEBUG3, "not enough space\n");
559 if (lines_used == max_lines)
560 {
561 mutt_debug(LL_DEBUG3, "no more lines\n");
562 mutt_debug(LL_DEBUG3, "truncating: %s\n", buf_string(buf));
563 mutt_paddstr(win, width_left, buf_string(buf));
564 break;
565 }
566
567 if (width_left == (win->state.cols - MaxHeaderWidth))
568 {
569 mutt_debug(LL_DEBUG3, "couldn't print: %s\n", buf_string(buf));
570 mutt_paddstr(win, width_left, buf_string(buf));
571 break;
572 }
573
574 mutt_debug(LL_DEBUG3, "start a new line\n");
576 row++;
577 lines_used++;
578 width_left = win->state.cols - MaxHeaderWidth;
580 goto try_again;
581 }
582
583 if (addr_len < width_left)
584 {
585 mutt_debug(LL_DEBUG3, "space for: %s\n", buf_string(buf));
587 mutt_window_addstr(win, sep);
588 width_left -= addr_len;
589 }
590 mutt_debug(LL_DEBUG3, "%d addresses remaining\n", count);
591 mutt_debug(LL_DEBUG3, "%zd lines remaining\n", max_lines - lines_used);
592 }
593 mutt_list_free(&list);
594 buf_pool_release(&buf);
595
596 if (count > 0)
597 {
598 mutt_window_move(win, win->state.cols - more_len, row);
600 mutt_window_addstr(win, more);
602 mutt_debug(LL_DEBUG3, "%d more (len %d)\n", count, more_len);
603 }
604 else
605 {
607 }
608
609 for (int i = lines_used; i < max_lines; i++)
610 {
611 mutt_window_move(win, 0, row + i);
613 }
614
615 mutt_debug(LL_DEBUG3, "used %d lines\n", lines_used);
616 return lines_used;
617}
618
626static int draw_envelope_user_hdrs(struct MuttWindow *win,
627 struct EnvelopeWindowData *wdata, int row)
628{
629 const char *overflow_text = "...";
630 int rows_used = 0;
631
632 struct ListNode *first = STAILQ_FIRST(&wdata->email->env->userhdrs);
633 if (!first)
634 return rows_used;
635
636 /* Draw first entry on same line as prompt */
638 mutt_paddstr(win,
641 first->data);
642 rows_used++;
643
644 /* Draw any following entries on their own line */
645 struct ListNode *np = STAILQ_NEXT(first, entries);
646 if (!np)
647 return rows_used;
648
649 STAILQ_FOREACH_FROM(np, &wdata->email->env->userhdrs, entries)
650 {
651 if ((rows_used == (MAX_USER_HDR_ROWS - 1)) && STAILQ_NEXT(np, entries))
652 {
653 draw_header_content(win, row + rows_used, HDR_CUSTOM_HEADERS, overflow_text);
654 rows_used++;
655 break;
656 }
657 draw_header_content(win, row + rows_used, HDR_CUSTOM_HEADERS, np->data);
658 rows_used++;
659 }
660 return rows_used;
661}
662
668static void draw_envelope(struct MuttWindow *win, struct EnvelopeWindowData *wdata)
669{
670 struct Email *e = wdata->email;
671 const char *fcc = buf_string(wdata->fcc);
672 const int cols = win->state.cols - MaxHeaderWidth;
673
675 int row = draw_envelope_addr(HDR_FROM, &e->env->from, win, 0, 1);
676
677 if (wdata->is_news)
678 {
679 draw_header(win, row++, HDR_NEWSGROUPS);
680 mutt_paddstr(win, cols, NONULL(e->env->newsgroups));
681
682 draw_header(win, row++, HDR_FOLLOWUPTO);
683 mutt_paddstr(win, cols, NONULL(e->env->followup_to));
684
685 const bool c_x_comment_to = cs_subset_bool(wdata->sub, "x_comment_to");
686 if (c_x_comment_to)
687 {
688 draw_header(win, row++, HDR_XCOMMENTTO);
689 mutt_paddstr(win, cols, NONULL(e->env->x_comment_to));
690 }
691 }
692 else
693 {
694 row += draw_envelope_addr(HDR_TO, &e->env->to, win, row, wdata->to_rows);
695 row += draw_envelope_addr(HDR_CC, &e->env->cc, win, row, wdata->cc_rows);
696 row += draw_envelope_addr(HDR_BCC, &e->env->bcc, win, row, wdata->bcc_rows);
697 }
698
699 draw_header(win, row++, HDR_SUBJECT);
700 mutt_paddstr(win, cols, NONULL(e->env->subject));
701
702 row += draw_envelope_addr(HDR_REPLYTO, &e->env->reply_to, win, row, 1);
703
704 draw_header(win, row++, HDR_FCC);
705 mutt_paddstr(win, cols, fcc);
706
707 if (WithCrypto)
708 row += draw_crypt_lines(win, wdata, row);
709
710 const bool c_compose_show_user_headers = cs_subset_bool(wdata->sub, "compose_show_user_headers");
711 if (c_compose_show_user_headers)
712 row += draw_envelope_user_hdrs(win, wdata, row);
713
715}
716
720static int env_recalc(struct MuttWindow *win)
721{
722 struct EnvelopeWindowData *wdata = win->wdata;
723
724 const int cur_rows = win->state.rows;
725 const int new_rows = calc_envelope(win, wdata);
726
727 if (new_rows != cur_rows)
728 {
729 win->req_rows = new_rows;
731 }
732
733 win->actions |= WA_REPAINT;
734 mutt_debug(LL_DEBUG5, "recalc done, request WA_REPAINT\n");
735 return 0;
736}
737
741static int env_repaint(struct MuttWindow *win)
742{
743 struct EnvelopeWindowData *wdata = win->wdata;
744
745 draw_envelope(win, wdata);
746 mutt_debug(LL_DEBUG5, "repaint done\n");
747 return 0;
748}
749
753static int env_color_observer(struct NotifyCallback *nc)
754{
755 if (nc->event_type != NT_COLOR)
756 return 0;
757 if (!nc->global_data || !nc->event_data)
758 return -1;
759
760 struct EventColor *ev_c = nc->event_data;
761 struct MuttWindow *win_env = nc->global_data;
762
763 enum ColorId cid = ev_c->cid;
764
765 switch (cid)
766 {
767 case MT_COLOR_BOLD:
773 case MT_COLOR_NORMAL:
774 case MT_COLOR_STATUS:
775 case MT_COLOR_MAX: // Sent on `uncolor *`
776 mutt_debug(LL_DEBUG5, "color done, request WA_REPAINT\n");
777 win_env->actions |= WA_REPAINT;
778 break;
779
780 default:
781 break;
782 }
783 return 0;
784}
785
790{
791 if (nc->event_type != NT_CONFIG)
792 return 0;
793 if (!nc->global_data || !nc->event_data)
794 return -1;
795
796 struct EventConfig *ev_c = nc->event_data;
797 if (!ev_c->name)
798 return 0;
799
800 struct MuttWindow *win_env = nc->global_data;
801
802 switch (ev_c->name[0])
803 {
804 case 'a':
805 if (mutt_str_equal(ev_c->name, "autocrypt"))
806 break;
807 return 0;
808 case 'c':
809 if (mutt_str_equal(ev_c->name, "compose_show_user_headers") ||
810 mutt_str_equal(ev_c->name, "crypt_opportunistic_encrypt"))
811 {
812 break;
813 }
814 return 0;
815 case 'p':
816 if (mutt_str_equal(ev_c->name, "pgp_sign_as"))
817 break;
818 return 0;
819 case 's':
820 if (mutt_str_equal(ev_c->name, "smime_encrypt_with") ||
821 mutt_str_equal(ev_c->name, "smime_sign_as"))
822 {
823 break;
824 }
825 return 0;
826 case 'x':
827 if (mutt_str_equal(ev_c->name, "x_comment_to"))
828 break;
829 return 0;
830 default:
831 return 0;
832 }
833
834 win_env->actions |= WA_RECALC;
835 mutt_debug(LL_DEBUG5, "config done, request WA_RECALC\n");
836 return 0;
837}
838
842static int env_email_observer(struct NotifyCallback *nc)
843{
844 if ((nc->event_type != NT_EMAIL) && (nc->event_type != NT_ENVELOPE))
845 return 0;
846 if (!nc->global_data)
847 return -1;
848
849 struct MuttWindow *win_env = nc->global_data;
850
851 // pgp/smime/autocrypt menu, or external change
852 if (nc->event_type == NT_EMAIL)
853 {
854 struct EnvelopeWindowData *wdata = win_env->wdata;
855 update_crypt_info(wdata);
856 }
857
858 win_env->actions |= WA_RECALC;
859 mutt_debug(LL_DEBUG5, "email done, request WA_RECALC\n");
860 return 0;
861}
862
867{
868 if (nc->event_type != NT_HEADER)
869 return 0;
870 if (!nc->global_data || !nc->event_data)
871 return -1;
872
873 const struct EventHeader *ev_h = nc->event_data;
874 struct MuttWindow *win_env = nc->global_data;
875 struct EnvelopeWindowData *wdata = win_env->wdata;
876
877 struct Envelope *env = wdata->email->env;
878
880 {
881 header_set(&env->userhdrs, ev_h->header);
882 mutt_debug(LL_DEBUG5, "header done, request reflow\n");
883 win_env->actions |= WA_RECALC;
884 return 0;
885 }
886
888 {
889 struct ListNode *removed = header_find(&env->userhdrs, ev_h->header);
890 if (removed)
891 {
892 header_free(&env->userhdrs, removed);
893 mutt_debug(LL_DEBUG5, "header done, request reflow\n");
894 win_env->actions |= WA_RECALC;
895 }
896 return 0;
897 }
898
899 return 0;
900}
901
906{
907 if (nc->event_type != NT_WINDOW)
908 return 0;
909 if (!nc->global_data || !nc->event_data)
910 return -1;
911
912 struct MuttWindow *win_env = nc->global_data;
913 struct EventWindow *ev_w = nc->event_data;
914 if (ev_w->win != win_env)
915 return 0;
916
918 {
919 win_env->actions |= WA_RECALC;
920 mutt_debug(LL_DEBUG5, "window state done, request WA_RECALC\n");
921 }
922 else if (nc->event_subtype == NT_WINDOW_DELETE)
923 {
924 struct EnvelopeWindowData *wdata = win_env->wdata;
925
931 mutt_debug(LL_DEBUG5, "window delete done\n");
932 }
933
934 return 0;
935}
936
944struct MuttWindow *env_window_new(struct Email *e, struct Buffer *fcc, struct ConfigSubset *sub)
945{
947
950 HDR_ATTACH_TITLE - 1);
951
957
958 struct EnvelopeWindowData *wdata = env_wdata_new();
959 wdata->fcc = fcc;
960 wdata->email = e;
961 wdata->sub = sub;
962 wdata->is_news = OptNewsSend;
963
964 win_env->wdata = wdata;
965 win_env->wdata_free = env_wdata_free;
966 win_env->recalc = env_recalc;
967 win_env->repaint = env_repaint;
968
969 return win_env;
970}
size_t mutt_addrlist_write_list(const struct AddressList *al, struct ListHead *list)
Write Addresses to a List.
Definition: address.c:1217
size_t mutt_addr_write(struct Buffer *buf, struct Address *addr, bool display)
Write a single Address to a buffer.
Definition: address.c:1050
int mutt_addrlist_count_recips(const struct AddressList *al)
Count the number of Addresses with valid recipients.
Definition: address.c:872
Email Address Handling.
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:491
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:69
void mutt_color_observer_add(observer_t callback, void *global_data)
Add an observer.
Definition: notify.c:59
ColorId
List of all colored objects.
Definition: color.h:40
@ MT_COLOR_COMPOSE_SECURITY_ENCRYPT
Mail will be encrypted.
Definition: color.h:48
@ MT_COLOR_MAX
Definition: color.h:94
@ MT_COLOR_STATUS
Status bar (takes a pattern)
Definition: color.h:75
@ MT_COLOR_COMPOSE_SECURITY_NONE
Mail will not be encrypted or signed.
Definition: color.h:49
@ MT_COLOR_BOLD
Bold text.
Definition: color.h:45
@ MT_COLOR_COMPOSE_SECURITY_BOTH
Mail will be encrypted and signed.
Definition: color.h:47
@ MT_COLOR_NORMAL
Plain text.
Definition: color.h:59
@ MT_COLOR_COMPOSE_SECURITY_SIGN
Mail will be signed.
Definition: color.h:50
@ MT_COLOR_COMPOSE_HEADER
Header labels, e.g. From:
Definition: color.h:46
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:341
size_t mutt_strwidth(const char *s)
Measure a string's width in screen cells.
Definition: curs_lib.c:443
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:145
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:45
@ HDR_FCC
"Fcc:" (save folder) field
Definition: private.h:41
@ HDR_ATTACH_TITLE
The "-- Attachments" line.
Definition: private.h:51
@ HDR_CRYPT
"Security:" field (encryption/signing info)
Definition: private.h:42
@ HDR_CC
"Cc:" field
Definition: private.h:37
@ HDR_TO
"To:" field
Definition: private.h:36
@ HDR_BCC
"Bcc:" field
Definition: private.h:38
@ HDR_CUSTOM_HEADERS
"Headers:" field
Definition: private.h:50
@ HDR_FOLLOWUPTO
"Followup-To:" field
Definition: private.h:48
@ HDR_XCOMMENTTO
"X-Comment-To:" field
Definition: private.h:49
@ HDR_NEWSGROUPS
"Newsgroups:" field
Definition: private.h:47
@ HDR_CRYPTINFO
"Sign as:" field (encryption/signing info)
Definition: private.h:43
@ HDR_FROM
"From:" field
Definition: private.h:35
struct EnvelopeWindowData * env_wdata_new(void)
Create new Envelope Data.
Definition: wdata.c:51
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:500
static const char *const AutocryptRecUiFlags[]
Autocrypt "recommendation" strings.
Definition: window.c:131
static void draw_header(struct MuttWindow *win, int row, enum HeaderField field)
Draw an aligned label.
Definition: window.c:353
static int HeaderPadding[HDR_ATTACH_TITLE]
Number of padding spaces needed after each of the strings in Prompts after translation.
Definition: window.c:88
static void draw_envelope(struct MuttWindow *win, struct EnvelopeWindowData *wdata)
Write the email headers to the compose window.
Definition: window.c:668
static void draw_floating(struct MuttWindow *win, int col, int row, const char *text)
Draw a floating label.
Definition: window.c:340
const char *const Prompts[]
Names of header fields used in the envelope, e.g. From:, To:
Definition: window.c:93
#define MAX_USER_HDR_ROWS
Maximum number of rows to use for the Headers: field.
Definition: window.c:85
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:626
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:944
static int MaxHeaderWidth
Widest of the Prompts strings after translation.
Definition: window.c:90
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:369
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:82
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:161
static int draw_crypt_lines(struct MuttWindow *win, struct EnvelopeWindowData *wdata, int row)
Update the encryption info in the compose window.
Definition: window.c:383
static void init_header_padding(void)
Calculate how much padding the compose table will need.
Definition: window.c:180
bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: globals.c:71
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
static int env_email_observer(struct NotifyCallback *nc)
Notification that the Email has changed - Implements observer_t -.
Definition: window.c:842
static int env_color_observer(struct NotifyCallback *nc)
Notification that a Color has changed - Implements observer_t -.
Definition: window.c:753
static int env_window_observer(struct NotifyCallback *nc)
Notification that a Window has changed - Implements observer_t -.
Definition: window.c:905
static int env_config_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t -.
Definition: window.c:789
static int env_header_observer(struct NotifyCallback *nc)
Notification that a User Header has changed - Implements observer_t -.
Definition: window.c:866
static int env_recalc(struct MuttWindow *win)
Recalculate the Window data - Implements MuttWindow::recalc() -.
Definition: window.c:720
static int env_repaint(struct MuttWindow *win)
Repaint the Window - Implements MuttWindow::repaint() -.
Definition: window.c:741
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:45
@ LL_DEBUG5
Log at debug level 5.
Definition: logging2.h:47
#define MIN(a, b)
Definition: memory.h:32
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:660
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:496
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.
Definition: mutt_window.c:719
void mutt_window_reflow(struct MuttWindow *win)
Resize a Window and its children.
Definition: mutt_window.c:343
int mutt_window_printf(struct MuttWindow *win, const char *fmt,...)
Write a formatted string to a Window.
Definition: mutt_window.c:430
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:296
int mutt_window_addstr(struct MuttWindow *win, const char *str)
Write a string to a Window.
Definition: mutt_window.c:415
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:243
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:325
#define WA_RECALC
Recalculate the contents of the Window.
Definition: mutt_window.h:109
@ 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.
Definition: mutt_window.h:229
@ NT_WINDOW_DELETE
Window is about to be deleted.
Definition: mutt_window.h:228
#define WA_REPAINT
Redraw the contents of the Window.
Definition: mutt_window.h:110
#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: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:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
Progress Bar Window Data.
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
#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 TAILQ_NEXT(elm, field)
Definition: queue.h:832
#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
An email address.
Definition: address.h:36
struct Buffer * personal
Real name of address.
Definition: address.h:37
bool group
Group mailbox?
Definition: address.h:39
struct Buffer * mailbox
Mailbox and host address.
Definition: address.h:38
String manipulation buffer.
Definition: buffer.h:36
A set of inherited config items.
Definition: subset.h:47
struct Notify * notify
Notifications: NotifyConfig, EventConfig.
Definition: subset.h:52
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
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:53
enum ColorId cid
Colour ID that has changed.
Definition: notify2.h:54
A config-change event.
Definition: subset.h:71
const char * name
Name of config item that changed.
Definition: subset.h:73
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.
Definition: mutt_window.h:238
struct MuttWindow * win
Window that changed.
Definition: mutt_window.h:239
A List node for strings.
Definition: list.h:37
char * data
String.
Definition: list.h:38
int(* repaint)(struct MuttWindow *win)
Definition: mutt_window.h:186
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:126
void * wdata
Private data.
Definition: mutt_window.h:144
struct Notify * notify
Notifications: NotifyWindow, EventWindow.
Definition: mutt_window.h:137
short req_rows
Number of rows required.
Definition: mutt_window.h:124
int(* recalc)(struct MuttWindow *win)
Definition: mutt_window.h:172
void(* wdata_free)(struct MuttWindow *win, void **ptr)
Definition: mutt_window.h:158
struct MuttWindow * parent
Parent Window.
Definition: mutt_window.h:134
WindowActionFlags actions
Actions to be performed, e.g. WA_RECALC.
Definition: mutt_window.h:131
Container for Accounts, Notifications.
Definition: neomutt.h:42
struct Notify * notify
Notifications handler.
Definition: neomutt.h:43
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:46
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