NeoMutt  2024-04-16-36-g75b6fb
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
window.c File Reference

Envelope Window. More...

#include "config.h"
#include <stdbool.h>
#include <stdio.h>
#include "private.h"
#include "mutt/lib.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "gui/lib.h"
#include "color/lib.h"
#include "ncrypt/lib.h"
#include "functions.h"
#include "globals.h"
#include "wdata.h"
#include <libintl.h>
+ Include dependency graph for window.c:

Go to the source code of this file.

Macros

#define MAX_ADDR_ROWS   5
 Maximum number of rows to use for the To:, Cc:, Bcc: fields.
 
#define MAX_USER_HDR_ROWS   5
 Maximum number of rows to use for the Headers: field.
 

Functions

static void calc_header_width_padding (int idx, const char *header, bool calc_max)
 Calculate the width needed for the compose labels.
 
static void init_header_padding (void)
 Calculate how much padding the compose table will need.
 
static int calc_address (struct AddressList *al, short cols, short *srows)
 Calculate how many rows an AddressList will need.
 
static int calc_security (struct Email *e, short *rows, const struct ConfigSubset *sub)
 Calculate how many rows the security info will need.
 
static int calc_user_hdrs (const struct ListHead *hdrs)
 Calculate how many rows are needed for user-defined headers.
 
static int calc_envelope (struct MuttWindow *win, struct EnvelopeWindowData *wdata)
 Calculate how many rows the envelope will need.
 
static void draw_floating (struct MuttWindow *win, int col, int row, const char *text)
 Draw a floating label.
 
static void draw_header (struct MuttWindow *win, int row, enum HeaderField field)
 Draw an aligned label.
 
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.
 
static int draw_crypt_lines (struct MuttWindow *win, struct EnvelopeWindowData *wdata, int row)
 Update the encryption info in the compose window.
 
static void draw_mix_line (struct ListHead *chain, struct MuttWindow *win, int row)
 Redraw the Mixmaster chain.
 
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.
 
static int draw_envelope_user_hdrs (struct MuttWindow *win, struct EnvelopeWindowData *wdata, int row)
 Write user-defined headers to the compose window.
 
static void draw_envelope (struct MuttWindow *win, struct EnvelopeWindowData *wdata)
 Write the email headers to the compose window.
 
static int env_recalc (struct MuttWindow *win)
 Recalculate the Window data - Implements MuttWindow::recalc() -.
 
static int env_repaint (struct MuttWindow *win)
 Repaint the Window - Implements MuttWindow::repaint() -.
 
static int env_color_observer (struct NotifyCallback *nc)
 Notification that a Color has changed - Implements observer_t -.
 
static int env_config_observer (struct NotifyCallback *nc)
 Notification that a Config Variable has changed - Implements observer_t -.
 
static int env_email_observer (struct NotifyCallback *nc)
 Notification that the Email has changed - Implements observer_t -.
 
static int env_header_observer (struct NotifyCallback *nc)
 Notification that a User Header has changed - Implements observer_t -.
 
static int env_window_observer (struct NotifyCallback *nc)
 Notification that a Window has changed - Implements observer_t -.
 
struct MuttWindowenv_window_new (struct Email *e, struct Buffer *fcc, struct ConfigSubset *sub)
 Create the Envelope Window.
 

Variables

static int HeaderPadding [HDR_ATTACH_TITLE] = { 0 }
 Number of padding spaces needed after each of the strings in Prompts after translation.
 
static int MaxHeaderWidth = 0
 Widest of the Prompts strings after translation.
 
const char *const Prompts []
 Names of header fields used in the envelope, e.g. From:, To:
 
static const char *const AutocryptRecUiFlags []
 Autocrypt "recommendation" strings.
 

Detailed Description

Envelope Window.

Authors
  • Richard Russon
  • Pietro Cerutti

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file window.c.

Macro Definition Documentation

◆ MAX_ADDR_ROWS

#define MAX_ADDR_ROWS   5

Maximum number of rows to use for the To:, Cc:, Bcc: fields.

Definition at line 82 of file window.c.

◆ MAX_USER_HDR_ROWS

#define MAX_USER_HDR_ROWS   5

Maximum number of rows to use for the Headers: field.

Definition at line 85 of file window.c.

Function Documentation

◆ calc_header_width_padding()

static void calc_header_width_padding ( int  idx,
const char *  header,
bool  calc_max 
)
static

Calculate the width needed for the compose labels.

Parameters
idxStore the result at this index of HeaderPadding
headerHeader string
calc_maxIf true, calculate the maximum width

Definition at line 165 of file window.c.

166{
167 int width;
168
169 HeaderPadding[idx] = mutt_str_len(header);
170 width = mutt_strwidth(header);
171 if (calc_max && (MaxHeaderWidth < width))
172 MaxHeaderWidth = width;
173 HeaderPadding[idx] -= width;
174}
size_t mutt_strwidth(const char *s)
Measure a string's width in screen cells.
Definition: curs_lib.c:443
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 int MaxHeaderWidth
Widest of the Prompts strings after translation.
Definition: window.c:90
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:490
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ init_header_padding()

static void init_header_padding ( void  )
static

Calculate how much padding the compose table will need.

The padding needed for each header is strlen() + max_width - strwidth().

calc_header_width_padding sets each entry in HeaderPadding to strlen - width. Then, afterwards, we go through and add max_width to each entry.

Definition at line 184 of file window.c.

185{
186 static bool done = false;
187
188 if (done)
189 return;
190 done = true;
191
192 for (int i = 0; i < HDR_ATTACH_TITLE; i++)
193 {
194 if (i == HDR_CRYPTINFO)
195 continue;
196 calc_header_width_padding(i, _(Prompts[i]), true);
197 }
198
199 /* Don't include "Sign as: " in the MaxHeaderWidth calculation. It
200 * doesn't show up by default, and so can make the indentation of
201 * the other fields look funny. */
203
204 for (int i = 0; i < HDR_ATTACH_TITLE; i++)
205 {
207 if (HeaderPadding[i] < 0)
208 HeaderPadding[i] = 0;
209 }
210}
@ HDR_ATTACH_TITLE
The "-- Attachments" line.
Definition: private.h:54
@ HDR_CRYPTINFO
"Sign as:" field (encryption/signing info)
Definition: private.h:46
const char *const Prompts[]
Names of header fields used in the envelope, e.g. From:, To:
Definition: window.c:93
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:165
#define _(a)
Definition: message.h:28
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ calc_address()

static int calc_address ( struct AddressList *  al,
short  cols,
short *  srows 
)
static

Calculate how many rows an AddressList will need.

Parameters
[in]alAddress List
[in]colsScreen columns available
[out]srowsRows needed
Return values
numRows needed
Note
Number of rows is capped at MAX_ADDR_ROWS

Definition at line 221 of file window.c.

222{
223 struct ListHead slist = STAILQ_HEAD_INITIALIZER(slist);
224 mutt_addrlist_write_list(al, &slist);
225
226 int rows = 1;
227 int addr_len;
228 int width_left = cols;
229 struct ListNode *next = NULL;
230 struct ListNode *np = NULL;
231 STAILQ_FOREACH(np, &slist, entries)
232 {
233 next = STAILQ_NEXT(np, entries);
234 addr_len = mutt_strwidth(np->data);
235 if (next)
236 addr_len += 2; // ", "
237
238 try_again:
239 if (addr_len >= width_left)
240 {
241 if (width_left == cols)
242 break;
243
244 rows++;
245 width_left = cols;
246 goto try_again;
247 }
248
249 if (addr_len < width_left)
250 width_left -= addr_len;
251 }
252
253 mutt_list_free(&slist);
254
255 *srows = MIN(rows, MAX_ADDR_ROWS);
256 return *srows;
257}
size_t mutt_addrlist_write_list(const struct AddressList *al, struct ListHead *list)
Write Addresses to a List.
Definition: address.c:1217
#define MAX_ADDR_ROWS
Maximum number of rows to use for the To:, Cc:, Bcc: fields.
Definition: window.c:82
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
#define MIN(a, b)
Definition: memory.h:32
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:324
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
#define STAILQ_NEXT(elm, field)
Definition: queue.h:400
A List node for strings.
Definition: list.h:35
char * data
String.
Definition: list.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ calc_security()

static int calc_security ( struct Email e,
short *  rows,
const struct ConfigSubset sub 
)
static

Calculate how many rows the security info will need.

Parameters
eEmail
rowsRows needed
subConfigSubset
Return values
numRows needed

Definition at line 266 of file window.c.

267{
269 *rows = 0; // Neither PGP nor SMIME are built into NeoMutt
270 else if ((e->security & (SEC_ENCRYPT | SEC_SIGN)) != 0)
271 *rows = 2; // 'Security:' and 'Sign as:'
272 else
273 *rows = 1; // Just 'Security:'
274
275#ifdef USE_AUTOCRYPT
276 const bool c_autocrypt = cs_subset_bool(sub, "autocrypt");
277 if (c_autocrypt)
278 *rows += 1;
279#endif
280
281 return *rows;
282}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:48
#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
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition: email.h:43
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ calc_user_hdrs()

static int calc_user_hdrs ( const struct ListHead *  hdrs)
static

Calculate how many rows are needed for user-defined headers.

Parameters
hdrsHeader List
Return values
numRows needed, limited to MAX_USER_HDR_ROWS

Definition at line 289 of file window.c.

290{
291 int rows = 0; /* Don't print at all if no custom headers*/
292 struct ListNode *np = NULL;
293 STAILQ_FOREACH(np, hdrs, entries)
294 {
295 if (rows == MAX_USER_HDR_ROWS)
296 break;
297 rows++;
298 }
299 return rows;
300}
#define MAX_USER_HDR_ROWS
Maximum number of rows to use for the Headers: field.
Definition: window.c:85
+ Here is the caller graph for this function:

◆ calc_envelope()

static int calc_envelope ( struct MuttWindow win,
struct EnvelopeWindowData wdata 
)
static

Calculate how many rows the envelope will need.

Parameters
winWindow to draw on
wdataEnvelope Window data
Return values
numRows needed

Definition at line 308 of file window.c.

309{
310 int rows = 4; // 'From:', 'Subject:', 'Reply-To:', 'Fcc:'
311 struct Email *e = wdata->email;
312#ifdef MIXMASTER
313 if (!STAILQ_EMPTY(&e->chain))
314 rows++;
315#endif
316
317 struct Envelope *env = e->env;
318 const int cols = win->state.cols - MaxHeaderWidth;
319
320 if (wdata->is_news)
321 {
322 rows += 2; // 'Newsgroups:' and 'Followup-To:'
323 const bool c_x_comment_to = cs_subset_bool(wdata->sub, "x_comment_to");
324 if (c_x_comment_to)
325 rows++;
326 }
327 else
328 {
329 rows += calc_address(&env->to, cols, &wdata->to_rows);
330 rows += calc_address(&env->cc, cols, &wdata->cc_rows);
331 rows += calc_address(&env->bcc, cols, &wdata->bcc_rows);
332 }
333 rows += calc_security(e, &wdata->sec_rows, wdata->sub);
334 const bool c_compose_show_user_headers = cs_subset_bool(wdata->sub, "compose_show_user_headers");
335 if (c_compose_show_user_headers)
336 rows += calc_user_hdrs(&env->userhdrs);
337
338 return rows;
339}
static int calc_address(struct AddressList *al, short cols, short *srows)
Calculate how many rows an AddressList will need.
Definition: window.c:221
static int calc_user_hdrs(const struct ListHead *hdrs)
Calculate how many rows are needed for user-defined headers.
Definition: window.c:289
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:266
#define STAILQ_EMPTY(head)
Definition: queue.h:348
The envelope/body of an email.
Definition: email.h:39
struct Envelope * env
Envelope information.
Definition: email.h:68
struct ListHead chain
Mixmaster chain.
Definition: email.h:93
bool is_news
Email is a news article.
Definition: wdata.h:48
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
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
struct AddressList to
Email's 'To' list.
Definition: envelope.h:60
struct AddressList cc
Email's 'Cc' list.
Definition: envelope.h:61
struct AddressList bcc
Email's 'Bcc' list.
Definition: envelope.h:62
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:127
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:60
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ draw_floating()

static void draw_floating ( struct MuttWindow win,
int  col,
int  row,
const char *  text 
)
static

Draw a floating label.

Parameters
winWindow to draw on
colColumn to draw at
rowRow to draw at
textText to display

Definition at line 348 of file window.c.

349{
351 mutt_window_mvprintw(win, col, row, "%s", text);
353}
@ MT_COLOR_NORMAL
Plain text.
Definition: color.h:59
@ MT_COLOR_COMPOSE_HEADER
Header labels, e.g. From:
Definition: color.h:46
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
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:326
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ draw_header()

static void draw_header ( struct MuttWindow win,
int  row,
enum HeaderField  field 
)
static

Draw an aligned label.

Parameters
winWindow to draw on
rowRow to draw at
fieldField to display, e.g. HDR_FROM

Definition at line 361 of file window.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ draw_header_content()

static void draw_header_content ( struct MuttWindow win,
int  row,
enum HeaderField  field,
const char *  content 
)
static

Draw content on a separate line aligned to header prompt.

Parameters
winWindow to draw on
rowRow to draw at
fieldField to display, e.g. HDR_FROM
contentText to display

Content will be truncated if it is wider than the window.

Definition at line 377 of file window.c.

379{
380 mutt_window_move(win, HeaderPadding[field], row);
381 mutt_paddstr(win, win->state.cols - HeaderPadding[field], content);
382}
void mutt_paddstr(struct MuttWindow *win, int n, const char *s)
Display a string on screen, padded if necessary.
Definition: curs_lib.c:341
int mutt_window_move(struct MuttWindow *win, int col, int row)
Move the cursor in a Window.
Definition: mutt_window.c:297
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ draw_crypt_lines()

static int draw_crypt_lines ( struct MuttWindow win,
struct EnvelopeWindowData wdata,
int  row 
)
static

Update the encryption info in the compose window.

Parameters
winWindow to draw on
wdataEnvelope Window data
rowWindow row to start drawing
Return values
numNumber of lines used

Definition at line 391 of file window.c.

392{
393 struct Email *e = wdata->email;
394
395 draw_header(win, row++, HDR_CRYPT);
396
398 return 0;
399
400 // We'll probably need two lines for 'Security:' and 'Sign as:'
401 int used = 2;
402 if ((e->security & (SEC_ENCRYPT | SEC_SIGN)) == (SEC_ENCRYPT | SEC_SIGN))
403 {
405 mutt_window_addstr(win, _("Sign, Encrypt"));
406 }
407 else if (e->security & SEC_ENCRYPT)
408 {
410 mutt_window_addstr(win, _("Encrypt"));
411 }
412 else if (e->security & SEC_SIGN)
413 {
415 mutt_window_addstr(win, _("Sign"));
416 }
417 else
418 {
419 /* L10N: This refers to the encryption of the email, e.g. "Security: None" */
421 mutt_window_addstr(win, _("None"));
422 used = 1; // 'Sign as:' won't be needed
423 }
425
426 if ((e->security & (SEC_ENCRYPT | SEC_SIGN)))
427 {
428 if (((WithCrypto & APPLICATION_PGP) != 0) && (e->security & APPLICATION_PGP))
429 {
430 if ((e->security & SEC_INLINE))
431 mutt_window_addstr(win, _(" (inline PGP)"));
432 else
433 mutt_window_addstr(win, _(" (PGP/MIME)"));
434 }
435 else if (((WithCrypto & APPLICATION_SMIME) != 0) && (e->security & APPLICATION_SMIME))
436 {
437 mutt_window_addstr(win, _(" (S/MIME)"));
438 }
439 }
440
441 const bool c_crypt_opportunistic_encrypt = cs_subset_bool(wdata->sub, "crypt_opportunistic_encrypt");
442 if (c_crypt_opportunistic_encrypt && (e->security & SEC_OPPENCRYPT))
443 mutt_window_addstr(win, _(" (OppEnc mode)"));
444
446
447 if (((WithCrypto & APPLICATION_PGP) != 0) &&
448 (e->security & APPLICATION_PGP) && (e->security & SEC_SIGN))
449 {
450 draw_header(win, row++, HDR_CRYPTINFO);
451 const char *const c_pgp_sign_as = cs_subset_string(wdata->sub, "pgp_sign_as");
452 mutt_window_printf(win, "%s", c_pgp_sign_as ? c_pgp_sign_as : _("<default>"));
453 }
454
455 if (((WithCrypto & APPLICATION_SMIME) != 0) &&
457 {
458 draw_header(win, row++, HDR_CRYPTINFO);
459 const char *const c_smime_sign_as = cs_subset_string(wdata->sub, "smime_sign_as");
460 mutt_window_printf(win, "%s", c_smime_sign_as ? c_smime_sign_as : _("<default>"));
461 }
462
463 const char *const c_smime_encrypt_with = cs_subset_string(wdata->sub, "smime_encrypt_with");
464 if (((WithCrypto & APPLICATION_SMIME) != 0) && (e->security & APPLICATION_SMIME) &&
465 (e->security & SEC_ENCRYPT) && c_smime_encrypt_with)
466 {
467 draw_floating(win, 40, row - 1, _("Encrypt with: "));
468 mutt_window_printf(win, "%s", NONULL(c_smime_encrypt_with));
469 }
470
471#ifdef USE_AUTOCRYPT
472 const bool c_autocrypt = cs_subset_bool(wdata->sub, "autocrypt");
473 if (c_autocrypt)
474 {
475 draw_header(win, row, HDR_AUTOCRYPT);
476 if (e->security & SEC_AUTOCRYPT)
477 {
479 mutt_window_addstr(win, _("Encrypt"));
480 }
481 else
482 {
484 mutt_window_addstr(win, _("Off"));
485 }
486
487 /* L10N: The autocrypt compose menu Recommendation field.
488 Displays the output of the recommendation engine
489 (Off, No, Discouraged, Available, Yes) */
490 draw_floating(win, 40, row, _("Recommendation: "));
492
493 used++;
494 }
495#endif
496 return used;
497}
@ MT_COLOR_COMPOSE_SECURITY_ENCRYPT
Mail will be encrypted.
Definition: color.h:48
@ MT_COLOR_COMPOSE_SECURITY_NONE
Mail will not be encrypted or signed.
Definition: color.h:49
@ MT_COLOR_COMPOSE_SECURITY_BOTH
Mail will be encrypted and signed.
Definition: color.h:47
@ MT_COLOR_COMPOSE_SECURITY_SIGN
Mail will be signed.
Definition: color.h:50
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:292
@ HDR_AUTOCRYPT
"Autocrypt:" and "Recommendation:" fields
Definition: private.h:48
@ HDR_CRYPT
"Security:" field (encryption/signing info)
Definition: private.h:45
static const char *const AutocryptRecUiFlags[]
Autocrypt "recommendation" strings.
Definition: window.c:135
static void draw_header(struct MuttWindow *win, int row, enum HeaderField field)
Draw an aligned label.
Definition: window.c:361
static void draw_floating(struct MuttWindow *win, int col, int row, const char *text)
Draw a floating label.
Definition: window.c:348
int mutt_window_printf(struct MuttWindow *win, const char *fmt,...)
Write a formatted string to a Window.
Definition: mutt_window.c:431
int mutt_window_addstr(struct MuttWindow *win, const char *str)
Write a string to a Window.
Definition: mutt_window.c:416
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:244
#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 NONULL(x)
Definition: string2.h:37
enum AutocryptRec autocrypt_rec
Autocrypt recommendation.
Definition: wdata.h:50
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ draw_mix_line()

static void draw_mix_line ( struct ListHead *  chain,
struct MuttWindow win,
int  row 
)
static

Redraw the Mixmaster chain.

Parameters
chainList of chain links
winWindow to draw on
rowWindow row to start drawing
Precondition
chain points to a nonempty list.

Definition at line 508 of file window.c.

509{
510 char *t = NULL;
511 int c = MaxHeaderWidth;
512 struct ListNode *np = NULL;
513
514 draw_header(win, row, HDR_MIX);
515
516 STAILQ_FOREACH(np, chain, entries)
517 {
518 t = np->data;
519 if (t && (t[0] == '0') && (t[1] == '\0'))
520 t = "<random>";
521
522 if ((c + mutt_str_len(t) + 2) >= win->state.cols)
523 break;
524
525 mutt_window_addstr(win, NONULL(t));
526 if (STAILQ_NEXT(np, entries))
527 mutt_window_addstr(win, ", ");
528
529 c += mutt_str_len(t) + 2;
530 }
531}
@ HDR_MIX
"Mix:" field (Mixmaster chain)
Definition: private.h:43
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ draw_envelope_addr()

static int draw_envelope_addr ( int  field,
struct AddressList *  al,
struct MuttWindow win,
int  row,
size_t  max_lines 
)
static

Write addresses to the compose window.

Parameters
fieldField to display, e.g. HDR_FROM
alAddress list to write
winWindow
rowWindow row to start drawing
max_linesHow many lines may be used
Return values
numLines used

Definition at line 543 of file window.c.

545{
546 draw_header(win, row, field);
547
548 struct ListHead list = STAILQ_HEAD_INITIALIZER(list);
549 int count = mutt_addrlist_count_recips(al);
550
551 int lines_used = 1;
552 int width_left = win->state.cols - MaxHeaderWidth;
553 char more[32] = { 0 };
554 int more_len = 0;
555
556 struct Buffer *buf = buf_pool_get();
557 bool in_group = false;
558 char *sep = NULL;
559 struct Address *addr = NULL;
560 TAILQ_FOREACH(addr, al, entries)
561 {
562 struct Address *next = TAILQ_NEXT(addr, entries);
563
564 if (addr->group)
565 {
566 in_group = true;
567 }
568
569 buf_reset(buf);
570 mutt_addr_write(buf, addr, true);
571 size_t addr_len = buf_len(buf);
572
573 sep = "";
574 if (!addr->group)
575 {
576 // group terminator
577 if (in_group && next && !next->mailbox && !next->personal)
578 {
579 sep = ";";
580 addr_len += 1;
581 in_group = false;
582 }
583 else if (next)
584 {
585 sep = ", ";
586 addr_len += 2;
587 }
588 }
589
590 count--;
591 try_again:
592 more_len = snprintf(more, sizeof(more),
593 ngettext("(+%d more)", "(+%d more)", count), count);
594 mutt_debug(LL_DEBUG3, "text: '%s' len: %d\n", more, more_len);
595
596 int reserve = ((count > 0) && (lines_used == max_lines)) ? more_len : 0;
597 mutt_debug(LL_DEBUG3, "processing: %s (al:%zu, wl:%d, r:%d, lu:%d)\n",
598 buf_string(buf), addr_len, width_left, reserve, lines_used);
599 if (addr_len >= (width_left - reserve))
600 {
601 mutt_debug(LL_DEBUG3, "not enough space\n");
602 if (lines_used == max_lines)
603 {
604 mutt_debug(LL_DEBUG3, "no more lines\n");
605 mutt_debug(LL_DEBUG3, "truncating: %s\n", buf_string(buf));
606 mutt_paddstr(win, width_left, buf_string(buf));
607 break;
608 }
609
610 if (width_left == (win->state.cols - MaxHeaderWidth))
611 {
612 mutt_debug(LL_DEBUG3, "couldn't print: %s\n", buf_string(buf));
613 mutt_paddstr(win, width_left, buf_string(buf));
614 break;
615 }
616
617 mutt_debug(LL_DEBUG3, "start a new line\n");
619 row++;
620 lines_used++;
621 width_left = win->state.cols - MaxHeaderWidth;
623 goto try_again;
624 }
625
626 if (addr_len < width_left)
627 {
628 mutt_debug(LL_DEBUG3, "space for: %s\n", buf_string(buf));
630 mutt_window_addstr(win, sep);
631 width_left -= addr_len;
632 }
633 mutt_debug(LL_DEBUG3, "%d addresses remaining\n", count);
634 mutt_debug(LL_DEBUG3, "%zd lines remaining\n", max_lines - lines_used);
635 }
636 mutt_list_free(&list);
637 buf_pool_release(&buf);
638
639 if (count > 0)
640 {
641 mutt_window_move(win, win->state.cols - more_len, row);
643 mutt_window_addstr(win, more);
645 mutt_debug(LL_DEBUG3, "%d more (len %d)\n", count, more_len);
646 }
647 else
648 {
650 }
651
652 for (int i = lines_used; i < max_lines; i++)
653 {
654 mutt_window_move(win, 0, row + i);
656 }
657
658 mutt_debug(LL_DEBUG3, "used %d lines\n", lines_used);
659 return lines_used;
660}
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
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:490
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:75
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:96
@ MT_COLOR_BOLD
Bold text.
Definition: color.h:45
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
@ LL_DEBUG3
Log at debug level 3.
Definition: logging2.h:45
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
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
#define TAILQ_NEXT(elm, field)
Definition: queue.h:832
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
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ draw_envelope_user_hdrs()

static int draw_envelope_user_hdrs ( struct MuttWindow win,
struct EnvelopeWindowData wdata,
int  row 
)
static

Write user-defined headers to the compose window.

Parameters
winWindow to draw on
wdataEnvelope Window data
rowWindow row to start drawing from
Return values
numRows used

Definition at line 669 of file window.c.

671{
672 const char *overflow_text = "...";
673 int rows_used = 0;
674
675 struct ListNode *first = STAILQ_FIRST(&wdata->email->env->userhdrs);
676 if (!first)
677 return rows_used;
678
679 /* Draw first entry on same line as prompt */
681 mutt_paddstr(win,
684 first->data);
685 rows_used++;
686
687 /* Draw any following entries on their own line */
688 struct ListNode *np = STAILQ_NEXT(first, entries);
689 if (!np)
690 return rows_used;
691
692 STAILQ_FOREACH_FROM(np, &wdata->email->env->userhdrs, entries)
693 {
694 if ((rows_used == (MAX_USER_HDR_ROWS - 1)) && STAILQ_NEXT(np, entries))
695 {
696 draw_header_content(win, row + rows_used, HDR_CUSTOM_HEADERS, overflow_text);
697 rows_used++;
698 break;
699 }
700 draw_header_content(win, row + rows_used, HDR_CUSTOM_HEADERS, np->data);
701 rows_used++;
702 }
703 return rows_used;
704}
@ HDR_CUSTOM_HEADERS
"Headers:" field
Definition: private.h:53
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:377
#define STAILQ_FIRST(head)
Definition: queue.h:350
#define STAILQ_FOREACH_FROM(var, head, field)
Definition: queue.h:357
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ draw_envelope()

static void draw_envelope ( struct MuttWindow win,
struct EnvelopeWindowData wdata 
)
static

Write the email headers to the compose window.

Parameters
winWindow to draw on
wdataEnvelope Window data

Definition at line 711 of file window.c.

712{
713 struct Email *e = wdata->email;
714 const char *fcc = buf_string(wdata->fcc);
715 const int cols = win->state.cols - MaxHeaderWidth;
716
718 int row = draw_envelope_addr(HDR_FROM, &e->env->from, win, 0, 1);
719
720 if (wdata->is_news)
721 {
722 draw_header(win, row++, HDR_NEWSGROUPS);
723 mutt_paddstr(win, cols, NONULL(e->env->newsgroups));
724
725 draw_header(win, row++, HDR_FOLLOWUPTO);
726 mutt_paddstr(win, cols, NONULL(e->env->followup_to));
727
728 const bool c_x_comment_to = cs_subset_bool(wdata->sub, "x_comment_to");
729 if (c_x_comment_to)
730 {
731 draw_header(win, row++, HDR_XCOMMENTTO);
732 mutt_paddstr(win, cols, NONULL(e->env->x_comment_to));
733 }
734 }
735 else
736 {
737 row += draw_envelope_addr(HDR_TO, &e->env->to, win, row, wdata->to_rows);
738 row += draw_envelope_addr(HDR_CC, &e->env->cc, win, row, wdata->cc_rows);
739 row += draw_envelope_addr(HDR_BCC, &e->env->bcc, win, row, wdata->bcc_rows);
740 }
741
742 draw_header(win, row++, HDR_SUBJECT);
743 mutt_paddstr(win, cols, NONULL(e->env->subject));
744
745 row += draw_envelope_addr(HDR_REPLYTO, &e->env->reply_to, win, row, 1);
746
747 draw_header(win, row++, HDR_FCC);
748 mutt_paddstr(win, cols, fcc);
749
750 if (WithCrypto)
751 row += draw_crypt_lines(win, wdata, row);
752
753#ifdef MIXMASTER
754 if (!STAILQ_EMPTY(&e->chain))
755 draw_mix_line(&e->chain, win, row++);
756#endif
757 const bool c_compose_show_user_headers = cs_subset_bool(wdata->sub, "compose_show_user_headers");
758 if (c_compose_show_user_headers)
759 row += draw_envelope_user_hdrs(win, wdata, row);
760
762}
@ HDR_SUBJECT
"Subject:" field
Definition: private.h:39
@ HDR_REPLYTO
"Reply-To:" field
Definition: private.h:40
@ HDR_FCC
"Fcc:" (save folder) field
Definition: private.h:41
@ 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_FOLLOWUPTO
"Followup-To:" field
Definition: private.h:51
@ HDR_XCOMMENTTO
"X-Comment-To:" field
Definition: private.h:52
@ HDR_NEWSGROUPS
"Newsgroups:" field
Definition: private.h:50
@ HDR_FROM
"From:" field
Definition: private.h:35
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:543
static void draw_mix_line(struct ListHead *chain, struct MuttWindow *win, int row)
Redraw the Mixmaster chain.
Definition: window.c:508
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:669
static int draw_crypt_lines(struct MuttWindow *win, struct EnvelopeWindowData *wdata, int row)
Update the encryption info in the compose window.
Definition: window.c:391
void mutt_window_clear(struct MuttWindow *win)
Clear a Window.
Definition: mutt_window.c:720
struct Buffer * fcc
Where the outgoing Email will be saved.
Definition: wdata.h:41
char *const subject
Email's subject.
Definition: envelope.h:70
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 from
Email's 'From' list.
Definition: envelope.h:59
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ env_window_new()

struct MuttWindow * env_window_new ( struct Email e,
struct Buffer fcc,
struct ConfigSubset sub 
)

Create the Envelope Window.

Parameters
eEmail
fccBuffer to save FCC
subConfigSubset
Return values
ptrNew Window

Definition at line 991 of file window.c.

992{
994
997 HDR_ATTACH_TITLE - 1);
998
1004
1005 struct EnvelopeWindowData *wdata = env_wdata_new();
1006 wdata->fcc = fcc;
1007 wdata->email = e;
1008 wdata->sub = sub;
1009 wdata->is_news = OptNewsSend;
1010
1011 win_env->wdata = wdata;
1012 win_env->wdata_free = env_wdata_free;
1013 win_env->recalc = env_recalc;
1014 win_env->repaint = env_repaint;
1015
1016 return win_env;
1017}
void mutt_color_observer_add(observer_t callback, void *global_data)
Add an observer.
Definition: notify.c:59
struct EnvelopeWindowData * env_wdata_new(void)
Create new Envelope Data.
Definition: wdata.c:51
static void init_header_padding(void)
Calculate how much padding the compose table will need.
Definition: window.c:184
bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: globals.c:71
static int env_email_observer(struct NotifyCallback *nc)
Notification that the Email has changed - Implements observer_t -.
Definition: window.c:889
static int env_color_observer(struct NotifyCallback *nc)
Notification that a Color has changed - Implements observer_t -.
Definition: window.c:800
static int env_window_observer(struct NotifyCallback *nc)
Notification that a Window has changed - Implements observer_t -.
Definition: window.c:952
static int env_config_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t -.
Definition: window.c:836
static int env_header_observer(struct NotifyCallback *nc)
Notification that a User Header has changed - Implements observer_t -.
Definition: window.c:913
static int env_recalc(struct MuttWindow *win)
Recalculate the Window data - Implements MuttWindow::recalc() -.
Definition: window.c:767
static int env_repaint(struct MuttWindow *win)
Repaint the Window - Implements MuttWindow::repaint() -.
Definition: window.c:788
void env_wdata_free(struct MuttWindow *win, void **ptr)
Free the Envelope Data - Implements MuttWindow::wdata_free() -.
Definition: wdata.c:39
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
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:182
@ WT_CUSTOM
Window with a custom drawing function.
Definition: mutt_window.h:95
@ MUTT_WIN_ORIENT_VERTICAL
Window uses all available vertical space.
Definition: mutt_window.h:38
#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
@ 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_HEADER
A header has changed, NotifyHeader EventHeader.
Definition: notify_type.h:47
@ NT_ALL
Register for all notifications.
Definition: notify_type.h:35
struct Notify * notify
Notifications: NotifyConfig, EventConfig.
Definition: subset.h:52
struct Notify * notify
Notifications: NotifyEmail, EventEmail.
Definition: email.h:73
Data to fill the Envelope Window.
Definition: wdata.h:38
int(* repaint)(struct MuttWindow *win)
Definition: mutt_window.h:187
void * wdata
Private data.
Definition: mutt_window.h:145
struct Notify * notify
Notifications: NotifyWindow, EventWindow.
Definition: mutt_window.h:138
int(* recalc)(struct MuttWindow *win)
Definition: mutt_window.h:173
void(* wdata_free)(struct MuttWindow *win, void **ptr)
Definition: mutt_window.h:159
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct Notify * notify
Notifications handler.
Definition: neomutt.h:42
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ HeaderPadding

int HeaderPadding[HDR_ATTACH_TITLE] = { 0 }
static

Number of padding spaces needed after each of the strings in Prompts after translation.

Definition at line 88 of file window.c.

◆ MaxHeaderWidth

int MaxHeaderWidth = 0
static

Widest of the Prompts strings after translation.

Definition at line 90 of file window.c.

◆ Prompts

const char* const Prompts[]

Names of header fields used in the envelope, e.g. From:, To:

Definition at line 93 of file window.c.

◆ AutocryptRecUiFlags

const char* const AutocryptRecUiFlags[]
static
Initial value:
= {
N_("Off"),
N_("No"),
N_("Discouraged"),
N_("Available"),
N_("Yes"),
}
#define N_(a)
Definition: message.h:32

Autocrypt "recommendation" strings.

Definition at line 135 of file window.c.