NeoMutt  2025-12-11-694-ga89709
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 "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 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
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_move(win, row, col);
344 mutt_window_printf(win, "%s", text);
346}
347
354static void draw_header(struct MuttWindow *win, int row, enum HeaderField field)
355{
357 mutt_window_move(win, row, 0);
358 mutt_window_printf(win, "%*s", HeaderPadding[field], _(Prompts[field]));
360}
361
371static void draw_header_content(struct MuttWindow *win, int row,
372 enum HeaderField field, const char *content)
373{
374 mutt_window_move(win, row, HeaderPadding[field]);
375 mutt_paddstr(win, win->state.cols - HeaderPadding[field], content);
376}
377
385static int draw_crypt_lines(struct MuttWindow *win, struct EnvelopeWindowData *wdata, int row)
386{
387 struct Email *e = wdata->email;
388
389 draw_header(win, row++, HDR_CRYPT);
390
392 return 0;
393
394 // We'll probably need two lines for 'Security:' and 'Sign as:'
395 int used = 2;
396 if ((e->security & (SEC_ENCRYPT | SEC_SIGN)) == (SEC_ENCRYPT | SEC_SIGN))
397 {
399 mutt_window_addstr(win, _("Sign, Encrypt"));
400 }
401 else if (e->security & SEC_ENCRYPT)
402 {
404 mutt_window_addstr(win, _("Encrypt"));
405 }
406 else if (e->security & SEC_SIGN)
407 {
409 mutt_window_addstr(win, _("Sign"));
410 }
411 else
412 {
413 /* L10N: This refers to the encryption of the email, e.g. "Security: None" */
415 mutt_window_addstr(win, _("None"));
416 used = 1; // 'Sign as:' won't be needed
417 }
419
420 if ((e->security & (SEC_ENCRYPT | SEC_SIGN)))
421 {
422 if (((WithCrypto & APPLICATION_PGP) != 0) && (e->security & APPLICATION_PGP))
423 {
424 if ((e->security & SEC_INLINE))
425 mutt_window_addstr(win, _(" (inline PGP)"));
426 else
427 mutt_window_addstr(win, _(" (PGP/MIME)"));
428 }
429 else if (((WithCrypto & APPLICATION_SMIME) != 0) && (e->security & APPLICATION_SMIME))
430 {
431 mutt_window_addstr(win, _(" (S/MIME)"));
432 }
433 }
434
435 const bool c_crypt_opportunistic_encrypt = cs_subset_bool(wdata->sub, "crypt_opportunistic_encrypt");
436 if (c_crypt_opportunistic_encrypt && (e->security & SEC_OPPENCRYPT))
437 mutt_window_addstr(win, _(" (OppEnc mode)"));
438
440
441 if (((WithCrypto & APPLICATION_PGP) != 0) &&
442 (e->security & APPLICATION_PGP) && (e->security & SEC_SIGN))
443 {
444 draw_header(win, row++, HDR_CRYPTINFO);
445 const char *const c_pgp_sign_as = cs_subset_string(wdata->sub, "pgp_sign_as");
446 mutt_window_printf(win, "%s", c_pgp_sign_as ? c_pgp_sign_as : _("<default>"));
447 }
448
449 if (((WithCrypto & APPLICATION_SMIME) != 0) &&
451 {
452 draw_header(win, row++, HDR_CRYPTINFO);
453 const char *const c_smime_sign_as = cs_subset_string(wdata->sub, "smime_sign_as");
454 mutt_window_printf(win, "%s", c_smime_sign_as ? c_smime_sign_as : _("<default>"));
455 }
456
457 const char *const c_smime_encrypt_with = cs_subset_string(wdata->sub, "smime_encrypt_with");
458 if (((WithCrypto & APPLICATION_SMIME) != 0) && (e->security & APPLICATION_SMIME) &&
459 (e->security & SEC_ENCRYPT) && c_smime_encrypt_with)
460 {
461 draw_floating(win, 40, row - 1, _("Encrypt with: "));
462 mutt_window_printf(win, "%s", NONULL(c_smime_encrypt_with));
463 }
464
465#ifdef USE_AUTOCRYPT
466 const bool c_autocrypt = cs_subset_bool(wdata->sub, "autocrypt");
467 if (c_autocrypt)
468 {
469 draw_header(win, row, HDR_AUTOCRYPT);
470 if (e->security & SEC_AUTOCRYPT)
471 {
473 mutt_window_addstr(win, _("Encrypt"));
474 }
475 else
476 {
478 mutt_window_addstr(win, _("Off"));
479 }
480
481 /* L10N: The autocrypt compose menu Recommendation field.
482 Displays the output of the recommendation engine
483 (Off, No, Discouraged, Available, Yes) */
484 draw_floating(win, 40, row, _("Recommendation: "));
486
487 used++;
488 }
489#endif
490 return used;
491}
492
502static int draw_envelope_addr(int field, struct AddressList *al,
503 struct MuttWindow *win, int row, size_t max_lines)
504{
505 draw_header(win, row, field);
506
507 /* Format addresses into displayable strings and wrap across multiple
508 * lines as needed, showing "(+N more)" when lines are exhausted */
509 struct ListHead list = STAILQ_HEAD_INITIALIZER(list);
510 int count = mutt_addrlist_count_recips(al);
511
512 int lines_used = 1;
513 int width_left = win->state.cols - MaxHeaderWidth;
514 char more[32] = { 0 };
515 int more_len = 0;
516
517 struct Buffer *buf = buf_pool_get();
518 bool in_group = false;
519 char *sep = NULL;
520 struct Address *addr = NULL;
521 TAILQ_FOREACH(addr, al, entries)
522 {
523 struct Address *next = TAILQ_NEXT(addr, entries);
524
525 if (addr->group)
526 {
527 in_group = true;
528 }
529
530 buf_reset(buf);
531 mutt_addr_write(buf, addr, true);
532 size_t addr_len = mutt_strwidth(buf_string(buf));
533
534 sep = "";
535 if (!addr->group)
536 {
537 // group terminator
538 if (in_group && next && !next->mailbox && !next->personal)
539 {
540 sep = ";";
541 addr_len += 1;
542 in_group = false;
543 }
544 else if (next)
545 {
546 sep = ", ";
547 addr_len += 2;
548 }
549 }
550
551 count--;
552 try_again:
553 /* Calculate the "(+N more)" indicator width if we're on the last line */
554 more_len = snprintf(more, sizeof(more),
555 ngettext("(+%d more)", "(+%d more)", count), count);
556 if ((more_len < 0) || (more_len >= sizeof(more)))
557 more_len = mutt_strwidth(more);
558 mutt_debug(LL_DEBUG3, "text: '%s' len: %d\n", more, more_len);
559
560 int reserve = ((count > 0) && (lines_used == max_lines)) ? more_len : 0;
561 mutt_debug(LL_DEBUG3, "processing: %s (al:%zu, wl:%d, r:%d, lu:%d)\n",
562 buf_string(buf), addr_len, width_left, reserve, lines_used);
563 if (addr_len >= (width_left - reserve))
564 {
565 mutt_debug(LL_DEBUG3, "not enough space\n");
566 if (lines_used == max_lines)
567 {
568 mutt_debug(LL_DEBUG3, "no more lines\n");
569 mutt_debug(LL_DEBUG3, "truncating: %s\n", buf_string(buf));
570 mutt_paddstr(win, width_left, buf_string(buf));
571 break;
572 }
573
574 if (width_left == (win->state.cols - MaxHeaderWidth))
575 {
576 mutt_debug(LL_DEBUG3, "couldn't print: %s\n", buf_string(buf));
577 mutt_paddstr(win, width_left, buf_string(buf));
578 break;
579 }
580
581 mutt_debug(LL_DEBUG3, "start a new line\n");
583 row++;
584 lines_used++;
585 width_left = win->state.cols - MaxHeaderWidth;
587 goto try_again;
588 }
589
590 if (addr_len < width_left)
591 {
592 mutt_debug(LL_DEBUG3, "space for: %s\n", buf_string(buf));
594 mutt_window_addstr(win, sep);
595 width_left -= addr_len;
596 }
597 mutt_debug(LL_DEBUG3, "%d addresses remaining\n", count);
598 mutt_debug(LL_DEBUG3, "%zd lines remaining\n", max_lines - lines_used);
599 }
600 mutt_list_free(&list);
601 buf_pool_release(&buf);
602
603 /* Display the "(+N more)" overflow indicator, or clear the rest of the line */
604 if (count > 0)
605 {
606 mutt_window_move(win, row, win->state.cols - more_len);
608 mutt_window_addstr(win, more);
610 mutt_debug(LL_DEBUG3, "%d more (len %d)\n", count, more_len);
611 }
612 else
613 {
615 }
616
617 for (int i = lines_used; i < max_lines; i++)
618 {
619 mutt_window_move(win, row + i, 0);
621 }
622
623 mutt_debug(LL_DEBUG3, "used %d lines\n", lines_used);
624 return lines_used;
625}
626
634static int draw_envelope_user_hdrs(struct MuttWindow *win,
635 struct EnvelopeWindowData *wdata, int row)
636{
637 const char *overflow_text = "...";
638 int rows_used = 0;
639
640 struct ListNode *first = STAILQ_FIRST(&wdata->email->env->userhdrs);
641 if (!first)
642 return rows_used;
643
644 /* Draw first entry on same line as prompt */
647 rows_used++;
648
649 /* Draw any following entries on their own line */
650 struct ListNode *np = STAILQ_NEXT(first, entries);
651 if (!np)
652 return rows_used;
653
654 STAILQ_FOREACH_FROM(np, &wdata->email->env->userhdrs, entries)
655 {
656 if ((rows_used == (MAX_USER_HDR_ROWS - 1)) && STAILQ_NEXT(np, entries))
657 {
658 draw_header_content(win, row + rows_used, HDR_CUSTOM_HEADERS, overflow_text);
659 rows_used++;
660 break;
661 }
662 draw_header_content(win, row + rows_used, HDR_CUSTOM_HEADERS, np->data);
663 rows_used++;
664 }
665 return rows_used;
666}
667
673static void draw_envelope(struct MuttWindow *win, struct EnvelopeWindowData *wdata)
674{
675 struct Email *e = wdata->email;
676 const char *fcc = buf_string(wdata->fcc);
677 const int cols = win->state.cols - MaxHeaderWidth;
678
680 int row = draw_envelope_addr(HDR_FROM, &e->env->from, win, 0, 1);
681
682 if (wdata->is_news)
683 {
684 draw_header(win, row++, HDR_NEWSGROUPS);
685 mutt_paddstr(win, cols, NONULL(e->env->newsgroups));
686
687 draw_header(win, row++, HDR_FOLLOWUPTO);
688 mutt_paddstr(win, cols, NONULL(e->env->followup_to));
689
690 const bool c_x_comment_to = cs_subset_bool(wdata->sub, "x_comment_to");
691 if (c_x_comment_to)
692 {
693 draw_header(win, row++, HDR_XCOMMENTTO);
694 mutt_paddstr(win, cols, NONULL(e->env->x_comment_to));
695 }
696 }
697 else
698 {
699 row += draw_envelope_addr(HDR_TO, &e->env->to, win, row, wdata->to_rows);
700 row += draw_envelope_addr(HDR_CC, &e->env->cc, win, row, wdata->cc_rows);
701 row += draw_envelope_addr(HDR_BCC, &e->env->bcc, win, row, wdata->bcc_rows);
702 }
703
704 draw_header(win, row++, HDR_SUBJECT);
705 mutt_paddstr(win, cols, NONULL(e->env->subject));
706
707 row += draw_envelope_addr(HDR_REPLYTO, &e->env->reply_to, win, row, 1);
708
709 draw_header(win, row++, HDR_FCC);
710 mutt_paddstr(win, cols, fcc);
711
712 if (WithCrypto)
713 row += draw_crypt_lines(win, wdata, row);
714
715 const bool c_compose_show_user_headers = cs_subset_bool(wdata->sub, "compose_show_user_headers");
716 if (c_compose_show_user_headers)
717 row += draw_envelope_user_hdrs(win, wdata, row);
718
720}
721
725static int env_recalc(struct MuttWindow *win)
726{
727 struct EnvelopeWindowData *wdata = win->wdata;
728
729 const int cur_rows = win->state.rows;
730 const int new_rows = calc_envelope(win, wdata);
731
732 if (new_rows != cur_rows)
733 {
734 win->req_rows = new_rows;
736 }
737
738 win->actions |= WA_REPAINT;
739 mutt_debug(LL_DEBUG5, "recalc done, request WA_REPAINT\n");
740 return 0;
741}
742
746static int env_repaint(struct MuttWindow *win)
747{
748 struct EnvelopeWindowData *wdata = win->wdata;
749
750 draw_envelope(win, wdata);
751 mutt_debug(LL_DEBUG5, "repaint done\n");
752 return 0;
753}
754
758static int env_color_observer(struct NotifyCallback *nc)
759{
760 if (nc->event_type != NT_COLOR)
761 return 0;
762 if (!nc->global_data || !nc->event_data)
763 return -1;
764
765 struct EventColor *ev_c = nc->event_data;
766 struct MuttWindow *win_env = nc->global_data;
767
768 enum ColorId cid = ev_c->cid;
769
770 switch (cid)
771 {
772 case MT_COLOR_BOLD:
778 case MT_COLOR_NORMAL:
779 case MT_COLOR_STATUS:
780 case MT_COLOR_MAX: // Sent on `uncolor *`
781 mutt_debug(LL_DEBUG5, "color done, request WA_REPAINT\n");
782 win_env->actions |= WA_REPAINT;
783 break;
784
785 default:
786 break;
787 }
788 return 0;
789}
790
795{
796 if (nc->event_type != NT_CONFIG)
797 return 0;
798 if (!nc->global_data || !nc->event_data)
799 return -1;
800
801 struct EventConfig *ev_c = nc->event_data;
802 if (!ev_c->name)
803 return 0;
804
805 struct MuttWindow *win_env = nc->global_data;
806
807 switch (ev_c->name[0])
808 {
809 case 'a':
810 if (mutt_str_equal(ev_c->name, "autocrypt"))
811 break;
812 return 0;
813 case 'c':
814 if (mutt_str_equal(ev_c->name, "compose_show_user_headers") ||
815 mutt_str_equal(ev_c->name, "crypt_opportunistic_encrypt"))
816 {
817 break;
818 }
819 return 0;
820 case 'p':
821 if (mutt_str_equal(ev_c->name, "pgp_sign_as"))
822 break;
823 return 0;
824 case 's':
825 if (mutt_str_equal(ev_c->name, "smime_encrypt_with") ||
826 mutt_str_equal(ev_c->name, "smime_sign_as"))
827 {
828 break;
829 }
830 return 0;
831 case 'x':
832 if (mutt_str_equal(ev_c->name, "x_comment_to"))
833 break;
834 return 0;
835 default:
836 return 0;
837 }
838
839 win_env->actions |= WA_RECALC;
840 mutt_debug(LL_DEBUG5, "config done, request WA_RECALC\n");
841 return 0;
842}
843
847static int env_email_observer(struct NotifyCallback *nc)
848{
849 if ((nc->event_type != NT_EMAIL) && (nc->event_type != NT_ENVELOPE))
850 return 0;
851 if (!nc->global_data)
852 return -1;
853
854 struct MuttWindow *win_env = nc->global_data;
855
856 // pgp/smime/autocrypt menu, or external change
857 if (nc->event_type == NT_EMAIL)
858 {
859 struct EnvelopeWindowData *wdata = win_env->wdata;
860 update_crypt_info(wdata);
861 }
862
863 win_env->actions |= WA_RECALC;
864 mutt_debug(LL_DEBUG5, "email done, request WA_RECALC\n");
865 return 0;
866}
867
872{
873 if (nc->event_type != NT_HEADER)
874 return 0;
875 if (!nc->global_data || !nc->event_data)
876 return -1;
877
878 const struct EventHeader *ev_h = nc->event_data;
879 struct MuttWindow *win_env = nc->global_data;
880 struct EnvelopeWindowData *wdata = win_env->wdata;
881
882 struct Envelope *env = wdata->email->env;
883
885 {
886 header_set(&env->userhdrs, ev_h->header);
887 mutt_debug(LL_DEBUG5, "header done, request reflow\n");
888 win_env->actions |= WA_RECALC;
889 return 0;
890 }
891
893 {
894 struct ListNode *removed = header_find(&env->userhdrs, ev_h->header);
895 if (removed)
896 {
897 header_free(&env->userhdrs, removed);
898 mutt_debug(LL_DEBUG5, "header done, request reflow\n");
899 win_env->actions |= WA_RECALC;
900 }
901 return 0;
902 }
903
904 return 0;
905}
906
911{
912 if (nc->event_type != NT_WINDOW)
913 return 0;
914 if (!nc->global_data || !nc->event_data)
915 return -1;
916
917 struct MuttWindow *win_env = nc->global_data;
918 struct EventWindow *ev_w = nc->event_data;
919 if (ev_w->win != win_env)
920 return 0;
921
923 {
924 win_env->actions |= WA_RECALC;
925 mutt_debug(LL_DEBUG5, "window state done, request WA_RECALC\n");
926 }
927 else if (nc->event_subtype == NT_WINDOW_DELETE)
928 {
929 struct EnvelopeWindowData *wdata = win_env->wdata;
930
936 mutt_debug(LL_DEBUG5, "window delete done\n");
937 }
938
939 return 0;
940}
941
949struct MuttWindow *env_window_new(struct Email *e, struct Buffer *fcc, struct ConfigSubset *sub)
950{
952
955 HDR_ATTACH_TITLE - 1);
956
962
963 struct EnvelopeWindowData *wdata = env_wdata_new();
964 wdata->fcc = fcc;
965 wdata->email = e;
966 wdata->sub = sub;
967 wdata->is_news = OptNewsSend;
968
969 win_env->wdata = wdata;
970 win_env->wdata_free = env_wdata_free;
971 win_env->recalc = env_recalc;
972 win_env->repaint = env_repaint;
973
974 return win_env;
975}
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:71
void mutt_color_observer_add(observer_t callback, void *global_data)
Add an observer.
Definition notify.c:61
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:342
size_t mutt_strwidth(const char *s)
Measure a string's width in screen cells.
Definition curs_lib.c:444
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.
Private Envelope Data.
const char *const Prompts[]
Names of header fields used in the envelope, e.g. From:, To:
Definition window.c:93
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 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:502
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:354
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:673
static void draw_floating(struct MuttWindow *win, int col, int row, const char *text)
Draw a floating label.
Definition window.c:340
#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:634
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:949
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:371
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:385
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: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:847
static int env_color_observer(struct NotifyCallback *nc)
Notification that a Color has changed - Implements observer_t -.
Definition window.c:758
static int env_window_observer(struct NotifyCallback *nc)
Notification that a Window has changed - Implements observer_t -.
Definition window.c:910
static int env_config_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t -.
Definition window.c:794
static int env_header_observer(struct NotifyCallback *nc)
Notification that a User Header has changed - Implements observer_t -.
Definition window.c:871
static int env_recalc(struct MuttWindow *win)
Recalculate the Window data - Implements MuttWindow::recalc() -.
Definition window.c:725
static int env_repaint(struct MuttWindow *win)
Repaint the Window - Implements MuttWindow::repaint() -.
Definition window.c:746
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
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:93
#define SEC_AUTOCRYPT
(Autocrypt) Message will be, or was Autocrypt encrypt+signed
Definition lib.h:95
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition lib.h:94
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition lib.h:98
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition lib.h:99
#define SEC_ENCRYPT
Email is encrypted.
Definition lib.h:86
#define WithCrypto
Definition lib.h:124
#define SEC_SIGN
Email is signed.
Definition lib.h:87
@ 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
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:54
enum ColorId cid
Colour ID that has changed.
Definition notify2.h:55
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