NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
envelope.c
Go to the documentation of this file.
1 
64 #include "config.h"
65 #include <stdbool.h>
66 #include <stdio.h>
67 #include "private.h"
68 #include "mutt/lib.h"
69 #include "address/lib.h"
70 #include "config/lib.h"
71 #include "email/lib.h"
72 #include "core/lib.h"
73 #include "gui/lib.h"
74 #include "ncrypt/lib.h"
75 #include "env_data.h"
76 #include "options.h"
77 #include "shared_data.h"
78 #ifdef ENABLE_NLS
79 #include <libintl.h>
80 #endif
81 
83 #define MAX_ADDR_ROWS 5
84 
86 #define MAX_USER_HDR_ROWS 5
87 
88 #ifdef USE_AUTOCRYPT
89 static const char *const AutocryptRecUiFlags[] = {
90  /* L10N: Autocrypt recommendation flag: off.
91  This is displayed when Autocrypt is turned off. */
92  N_("Off"),
93  /* L10N: Autocrypt recommendation flag: no.
94  This is displayed when Autocrypt cannot encrypt to the recipients. */
95  N_("No"),
96  /* L10N: Autocrypt recommendation flag: discouraged.
97  This is displayed when Autocrypt believes encryption should not be used.
98  This might occur if one of the recipient Autocrypt Keys has not been
99  used recently, or if the only key available is a Gossip Header key. */
100  N_("Discouraged"),
101  /* L10N: Autocrypt recommendation flag: available.
102  This is displayed when Autocrypt believes encryption is possible, but
103  leaves enabling it up to the sender. Probably because "prefer encrypt"
104  is not set in both the sender and recipient keys. */
105  N_("Available"),
106  /* L10N: Autocrypt recommendation flag: yes.
107  This is displayed when Autocrypt would normally enable encryption
108  automatically. */
109  N_("Yes"),
110 };
111 #endif
112 
123 static int calc_address(struct AddressList *al, struct ListHead *slist,
124  short cols, short *srows)
125 {
126  mutt_list_free(slist);
127  mutt_addrlist_write_list(al, slist);
128 
129  int rows = 1;
130  int addr_len;
131  int width_left = cols;
132  struct ListNode *next = NULL;
133  struct ListNode *np = NULL;
134  STAILQ_FOREACH(np, slist, entries)
135  {
136  next = STAILQ_NEXT(np, entries);
137  addr_len = mutt_strwidth(np->data);
138  if (next)
139  addr_len += 2; // ", "
140 
141  try_again:
142  if (addr_len >= width_left)
143  {
144  if (width_left == cols)
145  break;
146 
147  rows++;
148  width_left = cols;
149  goto try_again;
150  }
151 
152  if (addr_len < width_left)
153  width_left -= addr_len;
154  }
155 
156  *srows = MIN(rows, MAX_ADDR_ROWS);
157  return *srows;
158 }
159 
167 static int calc_security(struct Email *e, short *rows, const struct ConfigSubset *sub)
168 {
170  *rows = 0; // Neither PGP nor SMIME are built into NeoMutt
171  else if ((e->security & (SEC_ENCRYPT | SEC_SIGN)) != 0)
172  *rows = 2; // 'Security:' and 'Sign as:'
173  else
174  *rows = 1; // Just 'Security:'
175 
176 #ifdef USE_AUTOCRYPT
177  const bool c_autocrypt = cs_subset_bool(sub, "autocrypt");
178  if (c_autocrypt)
179  *rows += 1;
180 #endif
181 
182  return *rows;
183 }
184 
190 static int calc_user_hdrs(const struct ListHead *hdrs)
191 {
192  int rows = 0; /* Don't print at all if no custom headers*/
193  struct ListNode *np = NULL;
194  STAILQ_FOREACH(np, hdrs, entries)
195  {
196  if (rows == MAX_USER_HDR_ROWS)
197  break;
198  rows++;
199  }
200  return rows;
201 }
202 
210 static int calc_envelope(struct MuttWindow *win, struct ComposeSharedData *shared,
211  struct ComposeEnvelopeData *edata)
212 {
213  int rows = 4; // 'From:', 'Subject:', 'Reply-To:', 'Fcc:'
214 #ifdef MIXMASTER
215  rows++;
216 #endif
217 
218  struct Email *e = shared->email;
219  struct Envelope *env = e->env;
220  const int cols = win->state.cols - MaxHeaderWidth;
221 
222 #ifdef USE_NNTP
223  if (OptNewsSend)
224  {
225  rows += 2; // 'Newsgroups:' and 'Followup-To:'
226  const bool c_x_comment_to = cs_subset_bool(shared->sub, "x_comment_to");
227  if (c_x_comment_to)
228  rows++;
229  }
230  else
231 #endif
232  {
233  rows += calc_address(&env->to, &edata->to_list, cols, &edata->to_rows);
234  rows += calc_address(&env->cc, &edata->cc_list, cols, &edata->cc_rows);
235  rows += calc_address(&env->bcc, &edata->bcc_list, cols, &edata->bcc_rows);
236  }
237  rows += calc_security(e, &edata->sec_rows, shared->sub);
238  const bool c_compose_show_user_headers =
239  cs_subset_bool(shared->sub, "compose_show_user_headers");
240  if (c_compose_show_user_headers)
241  rows += calc_user_hdrs(&env->userhdrs);
242 
243  return rows;
244 }
245 
253 static void draw_floating(struct MuttWindow *win, int col, int row, const char *text)
254 {
256  mutt_window_mvprintw(win, col, row, "%s", text);
258 }
259 
266 static void draw_header(struct MuttWindow *win, int row, enum HeaderField field)
267 {
269  mutt_window_mvprintw(win, 0, row, "%*s", HeaderPadding[field], _(Prompts[field]));
271 }
272 
282 static void draw_header_content(struct MuttWindow *win, int row,
283  enum HeaderField field, const char *content)
284 {
285  mutt_window_move(win, HeaderPadding[field], row);
286  mutt_paddstr(win, win->state.cols - HeaderPadding[field], content);
287 }
288 
296 static int draw_crypt_lines(struct MuttWindow *win, struct ComposeSharedData *shared,
297  struct ComposeEnvelopeData *edata, int row)
298 {
299  struct Email *e = shared->email;
300 
301  draw_header(win, row++, HDR_CRYPT);
302 
304  return 0;
305 
306  // We'll probably need two lines for 'Security:' and 'Sign as:'
307  int used = 2;
308  if ((e->security & (SEC_ENCRYPT | SEC_SIGN)) == (SEC_ENCRYPT | SEC_SIGN))
309  {
311  mutt_window_addstr(win, _("Sign, Encrypt"));
312  }
313  else if (e->security & SEC_ENCRYPT)
314  {
316  mutt_window_addstr(win, _("Encrypt"));
317  }
318  else if (e->security & SEC_SIGN)
319  {
321  mutt_window_addstr(win, _("Sign"));
322  }
323  else
324  {
325  /* L10N: This refers to the encryption of the email, e.g. "Security: None" */
327  mutt_window_addstr(win, _("None"));
328  used = 1; // 'Sign as:' won't be needed
329  }
331 
332  if ((e->security & (SEC_ENCRYPT | SEC_SIGN)))
333  {
334  if (((WithCrypto & APPLICATION_PGP) != 0) && (e->security & APPLICATION_PGP))
335  {
336  if ((e->security & SEC_INLINE))
337  mutt_window_addstr(win, _(" (inline PGP)"));
338  else
339  mutt_window_addstr(win, _(" (PGP/MIME)"));
340  }
341  else if (((WithCrypto & APPLICATION_SMIME) != 0) && (e->security & APPLICATION_SMIME))
342  mutt_window_addstr(win, _(" (S/MIME)"));
343  }
344 
345  const bool c_crypt_opportunistic_encrypt =
346  cs_subset_bool(shared->sub, "crypt_opportunistic_encrypt");
347  if (c_crypt_opportunistic_encrypt && (e->security & SEC_OPPENCRYPT))
348  mutt_window_addstr(win, _(" (OppEnc mode)"));
349 
351 
352  if (((WithCrypto & APPLICATION_PGP) != 0) &&
353  (e->security & APPLICATION_PGP) && (e->security & SEC_SIGN))
354  {
355  draw_header(win, row++, HDR_CRYPTINFO);
356  const char *const c_pgp_sign_as =
357  cs_subset_string(shared->sub, "pgp_sign_as");
358  mutt_window_printf(win, "%s", c_pgp_sign_as ? c_pgp_sign_as : _("<default>"));
359  }
360 
361  if (((WithCrypto & APPLICATION_SMIME) != 0) &&
362  (e->security & APPLICATION_SMIME) && (e->security & SEC_SIGN))
363  {
364  draw_header(win, row++, HDR_CRYPTINFO);
365  const char *const c_smime_sign_as =
366  cs_subset_string(shared->sub, "pgp_sign_as");
367  mutt_window_printf(win, "%s", c_smime_sign_as ? c_smime_sign_as : _("<default>"));
368  }
369 
370  const char *const c_smime_encrypt_with =
371  cs_subset_string(shared->sub, "smime_encrypt_with");
372  if (((WithCrypto & APPLICATION_SMIME) != 0) && (e->security & APPLICATION_SMIME) &&
373  (e->security & SEC_ENCRYPT) && c_smime_encrypt_with)
374  {
375  draw_floating(win, 40, row - 1, _("Encrypt with: "));
376  mutt_window_printf(win, "%s", NONULL(c_smime_encrypt_with));
377  }
378 
379 #ifdef USE_AUTOCRYPT
380  const bool c_autocrypt = cs_subset_bool(shared->sub, "autocrypt");
381  if (c_autocrypt)
382  {
383  draw_header(win, row, HDR_AUTOCRYPT);
384  if (e->security & SEC_AUTOCRYPT)
385  {
387  mutt_window_addstr(win, _("Encrypt"));
388  }
389  else
390  {
392  mutt_window_addstr(win, _("Off"));
393  }
394 
395  /* L10N: The autocrypt compose menu Recommendation field.
396  Displays the output of the recommendation engine
397  (Off, No, Discouraged, Available, Yes) */
398  draw_floating(win, 40, row, _("Recommendation: "));
400 
401  used++;
402  }
403 #endif
404  return used;
405 }
406 
407 #ifdef MIXMASTER
408 
414 static void draw_mix_line(struct ListHead *chain, struct MuttWindow *win, int row)
415 {
416  char *t = NULL;
417 
418  draw_header(win, row, HDR_MIX);
419 
420  if (STAILQ_EMPTY(chain))
421  {
422  mutt_window_addstr(win, _("<no chain defined>"));
424  return;
425  }
426 
427  int c = 12;
428  struct ListNode *np = NULL;
429  STAILQ_FOREACH(np, chain, entries)
430  {
431  t = np->data;
432  if (t && (t[0] == '0') && (t[1] == '\0'))
433  t = "<random>";
434 
435  if (c + mutt_str_len(t) + 2 >= win->state.cols)
436  break;
437 
438  mutt_window_addstr(win, NONULL(t));
439  if (STAILQ_NEXT(np, entries))
440  mutt_window_addstr(win, ", ");
441 
442  c += mutt_str_len(t) + 2;
443  }
444 }
445 #endif
446 
455 static int draw_envelope_addr(int field, struct AddressList *al,
456  struct MuttWindow *win, int row, size_t max_lines)
457 {
458  draw_header(win, row, field);
459 
460  struct ListHead list = STAILQ_HEAD_INITIALIZER(list);
461  int count = mutt_addrlist_write_list(al, &list);
462 
463  int lines_used = 1;
464  int width_left = win->state.cols - MaxHeaderWidth;
465  char more[32];
466  int more_len = 0;
467 
468  char *sep = NULL;
469  struct ListNode *next = NULL;
470  struct ListNode *np = NULL;
471  STAILQ_FOREACH(np, &list, entries)
472  {
473  next = STAILQ_NEXT(np, entries);
474  int addr_len = mutt_strwidth(np->data);
475  if (next)
476  {
477  sep = ", ";
478  addr_len += 2;
479  }
480  else
481  {
482  sep = "";
483  }
484 
485  count--;
486  try_again:
487  more_len = snprintf(more, sizeof(more),
488  ngettext("(+%d more)", "(+%d more)", count), count);
489  mutt_debug(LL_DEBUG3, "text: '%s' len: %d\n", more, more_len);
490 
491  int reserve = ((count > 0) && (lines_used == max_lines)) ? more_len : 0;
492  mutt_debug(LL_DEBUG3, "processing: %s (al:%ld, wl:%d, r:%d, lu:%ld)\n",
493  np->data, addr_len, width_left, reserve, lines_used);
494  if (addr_len >= (width_left - reserve))
495  {
496  mutt_debug(LL_DEBUG3, "not enough space\n");
497  if (lines_used == max_lines)
498  {
499  mutt_debug(LL_DEBUG3, "no more lines\n");
500  mutt_debug(LL_DEBUG3, "truncating: %s\n", np->data);
501  mutt_paddstr(win, width_left, np->data);
502  break;
503  }
504 
505  if (width_left == (win->state.cols - MaxHeaderWidth))
506  {
507  mutt_debug(LL_DEBUG3, "couldn't print: %s\n", np->data);
508  mutt_paddstr(win, width_left, np->data);
509  break;
510  }
511 
512  mutt_debug(LL_DEBUG3, "start a new line\n");
514  row++;
515  lines_used++;
516  width_left = win->state.cols - MaxHeaderWidth;
517  mutt_window_move(win, MaxHeaderWidth, row);
518  goto try_again;
519  }
520 
521  if (addr_len < width_left)
522  {
523  mutt_debug(LL_DEBUG3, "space for: %s\n", np->data);
524  mutt_window_addstr(win, np->data);
525  mutt_window_addstr(win, sep);
526  width_left -= addr_len;
527  }
528  mutt_debug(LL_DEBUG3, "%ld addresses remaining\n", count);
529  mutt_debug(LL_DEBUG3, "%ld lines remaining\n", max_lines - lines_used);
530  }
531  mutt_list_free(&list);
532 
533  if (count > 0)
534  {
535  mutt_window_move(win, win->state.cols - more_len, row);
537  mutt_window_addstr(win, more);
539  mutt_debug(LL_DEBUG3, "%ld more (len %d)\n", count, more_len);
540  }
541  else
542  {
544  }
545 
546  for (int i = lines_used; i < max_lines; i++)
547  {
548  mutt_window_move(win, 0, row + i);
550  }
551 
552  mutt_debug(LL_DEBUG3, "used %d lines\n", lines_used);
553  return lines_used;
554 }
555 
562 static int draw_envelope_user_hdrs(struct MuttWindow *win,
563  struct ComposeSharedData *shared, int row)
564 {
565  const char *overflow_text = "...";
566  int rows_used = 0;
567 
568  struct ListNode *first = STAILQ_FIRST(&shared->email->env->userhdrs);
569  if (!first)
570  return rows_used;
571 
572  /* Draw first entry on same line as prompt */
573  draw_header(win, row, HDR_CUSTOM_HEADERS);
574  mutt_paddstr(win,
577  first->data);
578  rows_used++;
579 
580  /* Draw any following entries on their own line */
581  struct ListNode *np = STAILQ_NEXT(first, entries);
582  if (!np)
583  return rows_used;
584 
585  STAILQ_FOREACH_FROM(np, &shared->email->env->userhdrs, entries)
586  {
587  if ((rows_used == (MAX_USER_HDR_ROWS - 1)) && STAILQ_NEXT(np, entries))
588  {
589  draw_header_content(win, row + rows_used, HDR_CUSTOM_HEADERS, overflow_text);
590  rows_used++;
591  break;
592  }
593  draw_header_content(win, row + rows_used, HDR_CUSTOM_HEADERS, np->data);
594  rows_used++;
595  }
596  return rows_used;
597 }
598 
605 static void draw_envelope(struct MuttWindow *win, struct ComposeSharedData *shared,
606  struct ComposeEnvelopeData *edata)
607 {
608  struct Email *e = shared->email;
609  const char *fcc = mutt_buffer_string(edata->fcc);
610  const int cols = win->state.cols - MaxHeaderWidth;
611 
612  mutt_window_clear(win);
613  int row = draw_envelope_addr(HDR_FROM, &e->env->from, win, 0, 1);
614 
615 #ifdef USE_NNTP
616  if (OptNewsSend)
617  {
618  draw_header(win, row++, HDR_NEWSGROUPS);
619  mutt_paddstr(win, cols, NONULL(e->env->newsgroups));
620 
621  draw_header(win, row++, HDR_FOLLOWUPTO);
622  mutt_paddstr(win, cols, NONULL(e->env->followup_to));
623 
624  const bool c_x_comment_to = cs_subset_bool(shared->sub, "x_comment_to");
625  if (c_x_comment_to)
626  {
627  draw_header(win, row++, HDR_XCOMMENTTO);
628  mutt_paddstr(win, cols, NONULL(e->env->x_comment_to));
629  }
630  }
631  else
632 #endif
633  {
634  row += draw_envelope_addr(HDR_TO, &e->env->to, win, row, edata->to_rows);
635  row += draw_envelope_addr(HDR_CC, &e->env->cc, win, row, edata->cc_rows);
636  row += draw_envelope_addr(HDR_BCC, &e->env->bcc, win, row, edata->bcc_rows);
637  }
638 
639  draw_header(win, row++, HDR_SUBJECT);
640  mutt_paddstr(win, cols, NONULL(e->env->subject));
641 
642  row += draw_envelope_addr(HDR_REPLYTO, &e->env->reply_to, win, row, 1);
643 
644  draw_header(win, row++, HDR_FCC);
645  mutt_paddstr(win, cols, fcc);
646 
647  if (WithCrypto)
648  row += draw_crypt_lines(win, shared, edata, row);
649 
650 #ifdef MIXMASTER
651  draw_mix_line(&e->chain, win, row++);
652 #endif
653  const bool c_compose_show_user_headers =
654  cs_subset_bool(shared->sub, "compose_show_user_headers");
655  if (c_compose_show_user_headers)
656  row += draw_envelope_user_hdrs(win, shared, row);
657 
660 }
661 
665 static int env_recalc(struct MuttWindow *win)
666 {
667  struct ComposeSharedData *shared = win->parent->wdata;
668  struct ComposeEnvelopeData *edata = win->wdata;
669 
670  const int cur_rows = win->state.rows;
671  const int new_rows = calc_envelope(win, shared, edata);
672 
673  if (new_rows != cur_rows)
674  {
675  win->req_rows = new_rows;
677  }
678 
679  win->actions |= WA_REPAINT;
680  mutt_debug(LL_DEBUG5, "recalc done, request WA_REPAINT\n");
681  return 0;
682 }
683 
687 static int env_repaint(struct MuttWindow *win)
688 {
689  if (!mutt_window_is_visible(win))
690  return 0;
691 
692  struct ComposeSharedData *shared = win->parent->wdata;
693  struct ComposeEnvelopeData *edata = win->wdata;
694 
695  draw_envelope(win, shared, edata);
696  mutt_debug(LL_DEBUG5, "repaint done\n");
697  return 0;
698 }
699 
703 static int env_color_observer(struct NotifyCallback *nc)
704 {
705  if ((nc->event_type != NT_COLOR) || !nc->global_data || !nc->event_data)
706  return -1;
707 
708  struct EventColor *ev_c = nc->event_data;
709  struct MuttWindow *win_env = nc->global_data;
710 
711  enum ColorId color = ev_c->color;
712 
713  switch (color)
714  {
715  case MT_COLOR_BOLD:
721  case MT_COLOR_NORMAL:
722  case MT_COLOR_STATUS:
723  case MT_COLOR_MAX: // Sent on `uncolor *`
724  mutt_debug(LL_DEBUG5, "color done, request WA_REPAINT\n");
725  win_env->actions |= WA_REPAINT;
726  break;
727 
728  default:
729  break;
730  }
731  return 0;
732 }
733 
737 static int env_compose_observer(struct NotifyCallback *nc)
738 {
739  if ((nc->event_type != NT_COMPOSE) || !nc->global_data)
740  return -1;
741 
743  return 0;
744 
745  struct MuttWindow *win_env = nc->global_data;
746 
747  win_env->actions |= WA_RECALC;
748  mutt_debug(LL_DEBUG5, "compose done, request WA_RECALC\n");
749 
750  return 0;
751 }
752 
756 static int env_config_observer(struct NotifyCallback *nc)
757 {
758  if ((nc->event_type != NT_CONFIG) || !nc->global_data || !nc->event_data)
759  return -1;
760 
761  struct EventConfig *ev_c = nc->event_data;
762  struct MuttWindow *win_env = nc->global_data;
763 
764  switch (ev_c->name[0])
765  {
766  case 'a':
767  if (mutt_str_equal(ev_c->name, "autocrypt"))
768  break;
769  return 0;
770  case 'c':
771  if (mutt_str_equal(ev_c->name, "compose_show_user_headers") ||
772  mutt_str_equal(ev_c->name, "crypt_opportunistic_encrypt"))
773  {
774  break;
775  }
776  return 0;
777  case 'p':
778  if (mutt_str_equal(ev_c->name, "pgp_sign_as"))
779  break;
780  return 0;
781  case 's':
782  if (mutt_str_equal(ev_c->name, "smime_encrypt_with"))
783  break;
784  return 0;
785  case 'x':
786  if (mutt_str_equal(ev_c->name, "x_comment_to"))
787  break;
788  return 0;
789  default:
790  return 0;
791  }
792 
793  win_env->actions |= WA_RECALC;
794  mutt_debug(LL_DEBUG5, "config done, request WA_RECALC\n");
795  return 0;
796 }
797 
801 static int env_header_observer(struct NotifyCallback *nc)
802 {
803  if ((nc->event_type != NT_HEADER) || !nc->global_data || !nc->event_data)
804  return -1;
805 
806  const struct EventHeader *ev_h = nc->event_data;
807  struct MuttWindow *win_env = nc->global_data;
808  // struct ComposeEnvelopeData *edata = win_env->wdata;
809  struct MuttWindow *dlg = win_env->parent;
810  struct ComposeSharedData *shared = dlg->wdata;
811 
812  struct Envelope *env = shared->email->env;
813 
815  {
816  header_set(&env->userhdrs, ev_h->header);
817  mutt_debug(LL_DEBUG5, "header done, request reflow\n");
818  env_recalc(win_env);
819  return 0;
820  }
821 
822  if (nc->event_subtype == NT_HEADER_DELETE)
823  {
824  struct ListNode *removed = header_find(&env->userhdrs, ev_h->header);
825  if (removed)
826  {
827  header_free(&env->userhdrs, removed);
828  mutt_debug(LL_DEBUG5, "header done, request reflow\n");
829  env_recalc(win_env);
830  }
831  return 0;
832  }
833 
834  return 0;
835 }
836 
840 static int env_window_observer(struct NotifyCallback *nc)
841 {
842  if ((nc->event_type != NT_WINDOW) || !nc->global_data || !nc->event_data)
843  return -1;
844 
845  struct MuttWindow *win_env = nc->global_data;
846  struct EventWindow *ev_w = nc->event_data;
847  if (ev_w->win != win_env)
848  return 0;
849 
850  if (nc->event_subtype == NT_WINDOW_STATE)
851  {
852  win_env->actions |= WA_RECALC;
853  mutt_debug(LL_DEBUG5, "window state done, request WA_RECALC\n");
854  }
855  else if (nc->event_subtype == NT_WINDOW_DELETE)
856  {
857  struct ComposeSharedData *shared = win_env->parent->wdata;
858 
864  mutt_debug(LL_DEBUG5, "window delete done\n");
865  }
866 
867  return 0;
868 }
869 
878  struct ComposeSharedData *shared, struct Buffer *fcc)
879 {
880  struct MuttWindow *win_env =
883 
889 
890  struct ComposeEnvelopeData *env_data = env_data_new();
891  env_data->fcc = fcc;
892 
893  shared->edata = env_data;
894 
895  win_env->wdata = env_data;
896  win_env->wdata_free = env_data_free;
897  win_env->recalc = env_recalc;
898  win_env->repaint = env_repaint;
899 
900  return win_env;
901 }
Mail will be encrypted.
Definition: color.h:48
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:904
Convenience wrapper for the gui headers.
"Fcc:" (save folder) field
Definition: private.h:52
enum AutocryptRec autocrypt_rec
Autocrypt recommendation.
Definition: env_data.h:51
short to_rows
Number of rows used by the &#39;To:&#39; field.
Definition: env_data.h:45
Bold text.
Definition: color.h:45
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
The "-- Attachments" line.
Definition: private.h:67
#define NONULL(x)
Definition: string2.h:37
An existing header has been changed.
Definition: email.h:170
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
"Followup-To:" field
Definition: private.h:63
#define WithCrypto
Definition: lib.h:113
The envelope/body of an email.
Definition: email.h:37
void(* wdata_free)(struct MuttWindow *win, void **ptr)
Definition: mutt_window.h:160
#define MIN(a, b)
Definition: memory.h:31
#define WA_REPAINT
Redraw the contents of the Window.
Definition: mutt_window.h:111
Data passed to a notification function.
Definition: observer.h:39
struct MuttWindow * win
Window that changed.
Definition: mutt_window.h:217
Structs that make up an email.
An Event that happened to a Colour.
Definition: color.h:122
An Event that happened to a Window.
Definition: mutt_window.h:215
struct AddressList reply_to
Email&#39;s &#39;reply-to&#39;.
Definition: envelope.h:62
An event that happened to a header.
Definition: email.h:176
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: envelope.c:282
Compose Shared Data.
Header has been removed.
Definition: email.h:169
char * header
The contents of the header.
Definition: email.h:178
Window uses all available vertical space.
Definition: mutt_window.h:38
struct AddressList bcc
Email&#39;s &#39;Bcc&#39; list.
Definition: envelope.h:60
#define STAILQ_FOREACH_FROM(var, head, field)
Definition: queue.h:357
void mutt_curses_set_color(enum ColorId color)
Set the current colour for text.
Definition: mutt_curses.c:56
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:75
static int calc_envelope(struct MuttWindow *win, struct ComposeSharedData *shared, struct ComposeEnvelopeData *edata)
Calculate how many rows the envelope will need.
Definition: envelope.c:210
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:259
struct ListNode * header_set(struct ListHead *hdrlist, const char *header)
Set a header value in a list.
Definition: email.c:233
A config-change event.
Definition: subset.h:69
String manipulation buffer.
Definition: buffer.h:33
Shared Compose Data.
Definition: shared_data.h:29
Compose Envelope Data.
int MaxHeaderWidth
Definition: compose.c:134
#define NT_COMPOSE_ENVELOPE
Envelope has changed.
Definition: private.h:37
struct ListHead userhdrs
user defined headers
Definition: envelope.h:83
#define _(a)
Definition: message.h:28
#define MAX_ADDR_ROWS
Maximum number of rows to use for the To:, Cc:, Bcc: fields.
Definition: envelope.c:83
Window is about to be deleted.
Definition: mutt_window.h:206
struct ListHead cc_list
&#39;Cc:&#39; list of addresses
Definition: env_data.h:42
static int env_window_observer(struct NotifyCallback *nc)
Notification that a Window has changed - Implements observer_t.
Definition: envelope.c:840
static int env_color_observer(struct NotifyCallback *nc)
Notification that a Color has changed - Implements observer_t.
Definition: envelope.c:703
struct Buffer * fcc
Where the outgoing Email will be saved.
Definition: env_data.h:39
#define SEC_AUTOCRYPT
(Autocrypt) Message will be, or was Autocrypt encrypt+signed
Definition: lib.h:84
"Mix:" field (Mixmaster chain)
Definition: private.h:54
"From:" field
Definition: private.h:46
static int draw_crypt_lines(struct MuttWindow *win, struct ComposeSharedData *shared, struct ComposeEnvelopeData *edata, int row)
Update the encryption info in the compose window.
Definition: envelope.c:296
"Newsgroups:" field
Definition: private.h:62
Container for Accounts, Notifications.
Definition: neomutt.h:36
static int env_config_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t.
Definition: envelope.c:756
MuttWindow has changed, NotifyWindow, EventWindow.
Definition: notify_type.h:53
Data to fill the Compose Envelope Window.
Definition: env_data.h:37
"Sign as:" field (encryption/signing info)
Definition: private.h:57
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
short cc_rows
Number of rows used by the &#39;Cc:&#39; field.
Definition: env_data.h:46
Convenience wrapper for the config headers.
int mutt_window_move(struct MuttWindow *win, int col, int row)
Move the cursor in a Window.
Definition: mutt_window.c:310
Email Address Handling.
#define SEC_INLINE
Email has an inline signature.
Definition: lib.h:82
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
void env_data_free(struct MuttWindow *win, void **ptr)
Free the Compose Envelope Data - Implements MuttWindow::wdata_free() -.
Definition: env_data.c:36
int event_subtype
Send: Event subtype, e.g. NT_ACCOUNT_ADD.
Definition: observer.h:43
enum NotifyType event_type
Send: Event type, e.g. NT_ACCOUNT.
Definition: observer.h:42
WindowActionFlags actions
Actions to be performed, e.g. WA_RECALC.
Definition: mutt_window.h:132
void mutt_window_clear(struct MuttWindow *win)
Clear a Window.
Definition: mutt_window.c:716
struct Notify * notify
Notifications: NotifyWindow, EventWindow.
Definition: mutt_window.h:138
static int env_repaint(struct MuttWindow *win)
Repaint the Window - Implements MuttWindow::repaint() -.
Definition: envelope.c:687
static int env_compose_observer(struct NotifyCallback *nc)
Notification that the Compose data has changed - Implements observer_t.
Definition: envelope.c:737
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: envelope.c:455
static int calc_security(struct Email *e, short *rows, const struct ConfigSubset *sub)
Calculate how many rows the security info will need.
Definition: envelope.c:167
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:57
int mutt_window_addstr(struct MuttWindow *win, const char *str)
Write a string to a Window.
Definition: mutt_window.c:434
struct Envelope * env
Envelope information.
Definition: email.h:90
Convenience wrapper for the core headers.
ColorId
List of all colored objects.
Definition: color.h:39
static int env_recalc(struct MuttWindow *win)
Recalculate the Window data - Implements MuttWindow::recalc() -.
Definition: envelope.c:665
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:59
Header has been added.
Definition: email.h:168
static void draw_envelope(struct MuttWindow *win, struct ComposeSharedData *shared, struct ComposeEnvelopeData *edata)
Write the email headers to the compose window.
Definition: envelope.c:605
static int draw_envelope_user_hdrs(struct MuttWindow *win, struct ComposeSharedData *shared, int row)
Write user-defined headers to the compose window.
Definition: envelope.c:562
"Bcc:" field
Definition: private.h:49
Window with a custom drawing function.
Definition: mutt_window.h:95
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
void * global_data
Data from notify_observer_add()
Definition: observer.h:45
Window has a fixed size.
Definition: mutt_window.h:47
Plain text.
Definition: color.h:58
Window state has changed, e.g. WN_VISIBLE.
Definition: mutt_window.h:207
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:60
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:88
Colour has changed, NotifyColor, EventColor.
Definition: notify_type.h:39
char * x_comment_to
List of &#39;X-comment-to&#39; fields.
Definition: envelope.h:78
struct ListHead chain
Mixmaster chain.
Definition: email.h:102
A set of inherited config items.
Definition: subset.h:46
static void draw_header(struct MuttWindow *win, int row, enum HeaderField field)
Draw an aligned label.
Definition: envelope.c:266
struct ListHead bcc_list
&#39;Bcc:&#39; list of addresses
Definition: env_data.h:43
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:127
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:87
bool mutt_window_is_visible(struct MuttWindow *win)
Is the Window visible?
Definition: mutt_window.c:529
Status bar (takes a pattern)
Definition: color.h:75
int mutt_strwidth(const char *s)
Measure a string&#39;s width in screen cells.
Definition: curs_lib.c:983
#define MUTT_WIN_SIZE_UNLIMITED
Use as much space as possible.
Definition: mutt_window.h:52
Header labels, e.g. From:
Definition: color.h:46
short rows
Number of rows, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:61
int mutt_window_printf(struct MuttWindow *win, const char *fmt,...)
Write a formatted string to a Window.
Definition: mutt_window.c:453
"Cc:" field
Definition: private.h:48
short sec_rows
Number of rows used by the security fields.
Definition: env_data.h:48
static void draw_floating(struct MuttWindow *win, int col, int row, const char *text)
Draw a floating label.
Definition: envelope.c:253
enum ColorId color
Definition: color.h:124
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
API for encryption/signing of emails.
#define MAX_USER_HDR_ROWS
Maximum number of rows to use for the Headers: field.
Definition: envelope.c:86
Compose data has changed, NotifyCompose.
Definition: notify_type.h:41
Mail will be signed.
Definition: color.h:50
Compose Private Data.
struct ListHead to_list
&#39;To:&#39; list of addresses
Definition: env_data.h:41
static int env_header_observer(struct NotifyCallback *nc)
Notification that a User Header has changed - Implements observer_t.
Definition: envelope.c:801
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
const char *const Prompts[]
Definition: compose.c:136
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
A header has changed, NotifyHeader EventHeader.
Definition: notify_type.h:46
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
#define STAILQ_NEXT(elm, field)
Definition: queue.h:400
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib...
Definition: email.h:39
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: lib.h:83
void * event_data
Data from notify_send()
Definition: observer.h:44
size_t mutt_addrlist_write_list(const struct AddressList *al, struct ListHead *list)
Write Addresses to a List.
Definition: address.c:1201
"Reply-To:" field
Definition: private.h:51
Config has changed, NotifyConfig, EventConfig.
Definition: notify_type.h:42
#define SEC_SIGN
Email is signed.
Definition: lib.h:76
Mail will be encrypted and signed.
Definition: color.h:47
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:664
"X-Comment-To:" field
Definition: private.h:64
void header_free(struct ListHead *hdrlist, struct ListNode *target)
Free and remove a header from a header list.
Definition: email.c:245
char * data
String.
Definition: list.h:36
char * subject
Email&#39;s subject.
Definition: envelope.h:66
char * newsgroups
List of newsgroups.
Definition: envelope.h:75
static void draw_mix_line(struct ListHead *chain, struct MuttWindow *win, int row)
Redraw the Mixmaster chain.
Definition: envelope.c:414
static int calc_address(struct AddressList *al, struct ListHead *slist, short cols, short *srows)
Calculate how many rows an AddressList will need.
Definition: envelope.c:123
void mutt_window_reflow(struct MuttWindow *win)
Resize a Window and its children.
Definition: mutt_window.c:361
int HeaderPadding[HDR_ATTACH_TITLE]
Definition: compose.c:133
struct Notify * notify
Notifications: NotifyCompose.
Definition: shared_data.h:36
struct MuttWindow * parent
Parent Window.
Definition: mutt_window.h:135
char * followup_to
List of &#39;followup-to&#39; fields.
Definition: envelope.h:77
int(* repaint)(struct MuttWindow *win)
Definition: mutt_window.h:182
struct MuttWindow * compose_env_new(struct MuttWindow *parent, struct ComposeSharedData *shared, struct Buffer *fcc)
Create the Envelope Window.
Definition: envelope.c:877
static const char *const AutocryptRecUiFlags[]
Definition: envelope.c:89
#define STAILQ_EMPTY(head)
Definition: queue.h:348
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:324
short req_rows
Number of rows required.
Definition: mutt_window.h:125
struct ComposeEnvelopeData * edata
Envelope data.
Definition: shared_data.h:35
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
bool notify_observer_remove(struct Notify *notify, observer_t callback, void *global_data)
Remove an observer from an object.
Definition: notify.c:228
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:343
Mail will not be encrypted or signed.
Definition: color.h:49
int(* recalc)(struct MuttWindow *win)
Definition: mutt_window.h:171
Handling of global boolean variables.
HeaderField
Ordered list of headers for the compose screen.
Definition: private.h:44
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:180
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:45
short bcc_rows
Number of rows used by the &#39;Bcc:&#39; field.
Definition: env_data.h:47
Log at debug level 5.
Definition: logging.h:44
"Security:" field (encryption/signing info)
Definition: private.h:56
Convenience wrapper for the library headers.
A List node for strings.
Definition: list.h:34
"To:" field
Definition: private.h:47
void * wdata
Private data.
Definition: mutt_window.h:145
#define N_(a)
Definition: message.h:32
#define STAILQ_FIRST(head)
Definition: queue.h:350
const char * name
Name of config item that changed.
Definition: subset.h:72
struct Email * email
Email being composed.
Definition: shared_data.h:33
struct ConfigSubset * sub
Config set to use.
Definition: shared_data.h:31
Log at debug level 3.
Definition: logging.h:42
"Subject:" field
Definition: private.h:50
"Autocrypt:" and "Recommendation:" fields
Definition: private.h:59
The header of an Email.
Definition: envelope.h:54
void mutt_paddstr(struct MuttWindow *win, int n, const char *s)
Display a string on screen, padded if necessary.
Definition: curs_lib.c:890
struct ComposeEnvelopeData * env_data_new(void)
Create new Compose Envelope Data.
Definition: env_data.c:51
static int calc_user_hdrs(const struct ListHead *hdrs)
Calculate how many rows are needed for user-defined headers.
Definition: envelope.c:190
#define WA_RECALC
Recalculate the contents of the Window.
Definition: mutt_window.h:110
"Headers:" field
Definition: private.h:66