NeoMutt  2020-04-24
Teaching an old dog new tricks
DOXYGEN
compose.h File Reference

GUI editor for an email's headers. More...

+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define MUTT_COMPOSE_NOFREEHEADER   (1 << 0)
 

Functions

int mutt_compose_menu (struct Email *e, struct Buffer *fcc, struct Email *e_cur, int flags)
 Allow the user to edit the message envelope. More...
 

Variables

char * C_ComposeFormat
 Config: printf-like format string for the Compose panel's status bar. More...
 
char * C_Ispell
 Config: External command to perform spell-checking. More...
 
unsigned char C_Postpone
 Config: Save messages to the C_Postponed folder. More...
 

Detailed Description

GUI editor for an email's headers.

Authors
  • Richard Russon

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 compose.h.

Macro Definition Documentation

◆ MUTT_COMPOSE_NOFREEHEADER

#define MUTT_COMPOSE_NOFREEHEADER   (1 << 0)

Definition at line 35 of file compose.h.

Function Documentation

◆ mutt_compose_menu()

int mutt_compose_menu ( struct Email e,
struct Buffer fcc,
struct Email e_cur,
int  flags 
)

Allow the user to edit the message envelope.

Parameters
eEmail to fill
fccBuffer to save FCC
e_curCurrent message
flagsFlags, e.g. MUTT_COMPOSE_NOFREEHEADER
Return values
1Message should be postponed
0Normal exit
-1Abort message

Definition at line 1317 of file compose.c.

1318 {
1319  char helpstr[1024]; // This isn't copied by the help bar
1320  char buf[PATH_MAX];
1321  int rc = -1;
1322  bool loop = true;
1323  bool fcc_set = false; /* has the user edited the Fcc: field ? */
1324  struct ComposeRedrawData redraw = { 0 };
1325 
1326  STAILQ_INIT(&redraw.to_list);
1327  STAILQ_INIT(&redraw.cc_list);
1328  STAILQ_INIT(&redraw.bcc_list);
1329 
1330  struct ComposeRedrawData *rd = &redraw;
1331 #ifdef USE_NNTP
1332  bool news = OptNewsSend; /* is it a news article ? */
1333 #endif
1334 
1336 
1337  struct MuttWindow *dlg =
1340 #ifdef USE_DEBUG_WINDOW
1341  dlg->name = "compose";
1342 #endif
1343  dlg->type = WT_DIALOG;
1344 
1345  struct MuttWindow *envelope =
1348  envelope->type = WT_PAGER;
1349 
1350  struct MuttWindow *abar = mutt_window_new(
1352  abar->type = WT_PAGER_BAR;
1353 
1354  struct MuttWindow *attach =
1357  attach->type = WT_INDEX;
1358 
1359  struct MuttWindow *ebar = mutt_window_new(
1361  ebar->type = WT_INDEX_BAR;
1362 
1363  rd->email = e;
1364  rd->fcc = fcc;
1365  rd->win_envelope = envelope;
1366  rd->win_cbar = ebar;
1367  rd->win_attach = attach;
1368  rd->win_abar = abar;
1369 
1370  if (C_StatusOnTop)
1371  {
1372  mutt_window_add_child(dlg, ebar);
1373  mutt_window_add_child(dlg, envelope);
1374  mutt_window_add_child(dlg, abar);
1375  mutt_window_add_child(dlg, attach);
1376  }
1377  else
1378  {
1379  mutt_window_add_child(dlg, envelope);
1380  mutt_window_add_child(dlg, abar);
1381  mutt_window_add_child(dlg, attach);
1382  mutt_window_add_child(dlg, ebar);
1383  }
1384 
1386  dialog_push(dlg);
1387 
1388  envelope->req_rows = calc_envelope(rd);
1389  mutt_window_reflow(dlg);
1390 
1391  struct Menu *menu = mutt_menu_new(MENU_COMPOSE);
1392 
1393  menu->pagelen = attach->state.rows;
1394  menu->win_index = attach;
1395  menu->win_ibar = ebar;
1396 
1397  menu->make_entry = snd_make_entry;
1398  menu->tag = attach_tag;
1399 #ifdef USE_NNTP
1400  if (news)
1401  menu->help = mutt_compile_help(helpstr, sizeof(helpstr), MENU_COMPOSE, ComposeNewsHelp);
1402  else
1403 #endif
1404  menu->help = mutt_compile_help(helpstr, sizeof(helpstr), MENU_COMPOSE, ComposeHelp);
1406  menu->redraw_data = rd;
1407  mutt_menu_push_current(menu);
1408 
1409  struct AttachCtx *actx = mutt_actx_new();
1410  actx->email = e;
1411  mutt_update_compose_menu(actx, menu, true);
1412 
1413  update_crypt_info(rd);
1414 
1415  /* Since this is rather long lived, we don't use the pool */
1416  struct Buffer fname = mutt_buffer_make(PATH_MAX);
1417 
1418  bool redraw_env = false;
1419  while (loop)
1420  {
1421  if (redraw_env)
1422  {
1423  redraw_env = false;
1424  envelope->req_rows = calc_envelope(rd);
1425  mutt_window_reflow(dlg);
1426  }
1427 
1428 #ifdef USE_NNTP
1429  OptNews = false; /* for any case */
1430 #endif
1431  const int op = mutt_menu_loop(menu);
1432  switch (op)
1433  {
1434  case OP_COMPOSE_EDIT_FROM:
1436  update_crypt_info(rd);
1438  redraw_env = true;
1439  break;
1440 
1441  case OP_COMPOSE_EDIT_TO:
1442  {
1443 #ifdef USE_NNTP
1444  if (news)
1445  break;
1446 #endif
1447  edit_address_list(HDR_TO, &e->env->to);
1448  update_crypt_info(rd);
1450  redraw_env = true;
1451  break;
1452  }
1453 
1454  case OP_COMPOSE_EDIT_BCC:
1455  {
1456 #ifdef USE_NNTP
1457  if (news)
1458  break;
1459 #endif
1461  update_crypt_info(rd);
1463  redraw_env = true;
1464  break;
1465  }
1466 
1467  case OP_COMPOSE_EDIT_CC:
1468  {
1469 #ifdef USE_NNTP
1470  if (news)
1471  break;
1472 #endif
1473  edit_address_list(HDR_CC, &e->env->cc);
1474  update_crypt_info(rd);
1476  redraw_env = true;
1477  break;
1478  }
1479 
1480 #ifdef USE_NNTP
1481  case OP_COMPOSE_EDIT_NEWSGROUPS:
1482  if (!news)
1483  break;
1484  if (e->env->newsgroups)
1485  mutt_str_strfcpy(buf, e->env->newsgroups, sizeof(buf));
1486  else
1487  buf[0] = '\0';
1488  if (mutt_get_field(Prompts[HDR_NEWSGROUPS], buf, sizeof(buf), MUTT_COMP_NO_FLAGS) == 0)
1489  {
1490  mutt_str_replace(&e->env->newsgroups, buf);
1491  redraw_env = true;
1492  }
1493  break;
1494 
1495  case OP_COMPOSE_EDIT_FOLLOWUP_TO:
1496  if (!news)
1497  break;
1498  if (e->env->followup_to)
1499  mutt_str_strfcpy(buf, e->env->followup_to, sizeof(buf));
1500  else
1501  buf[0] = '\0';
1502  if (mutt_get_field(Prompts[HDR_FOLLOWUPTO], buf, sizeof(buf), MUTT_COMP_NO_FLAGS) == 0)
1503  {
1504  mutt_str_replace(&e->env->followup_to, buf);
1505  redraw_env = true;
1506  }
1507  break;
1508 
1509  case OP_COMPOSE_EDIT_X_COMMENT_TO:
1510  if (!(news && C_XCommentTo))
1511  break;
1512  if (e->env->x_comment_to)
1513  mutt_str_strfcpy(buf, e->env->x_comment_to, sizeof(buf));
1514  else
1515  buf[0] = '\0';
1516  if (mutt_get_field(Prompts[HDR_XCOMMENTTO], buf, sizeof(buf), MUTT_COMP_NO_FLAGS) == 0)
1517  {
1518  mutt_str_replace(&e->env->x_comment_to, buf);
1519  redraw_env = true;
1520  }
1521  break;
1522 #endif
1523 
1524  case OP_COMPOSE_EDIT_SUBJECT:
1525  if (e->env->subject)
1526  mutt_str_strfcpy(buf, e->env->subject, sizeof(buf));
1527  else
1528  buf[0] = '\0';
1529  if (mutt_get_field(Prompts[HDR_SUBJECT], buf, sizeof(buf), MUTT_COMP_NO_FLAGS) == 0)
1530  {
1531  mutt_str_replace(&e->env->subject, buf);
1532  redraw_env = true;
1533  }
1535  break;
1536 
1537  case OP_COMPOSE_EDIT_REPLY_TO:
1540  redraw_env = true;
1541  break;
1542 
1543  case OP_COMPOSE_EDIT_FCC:
1544  mutt_buffer_copy(&fname, fcc);
1546  {
1547  mutt_buffer_copy(fcc, &fname);
1549  fcc_set = true;
1550  redraw_env = true;
1551  }
1553  break;
1554 
1555  case OP_COMPOSE_EDIT_MESSAGE:
1556  if (C_Editor && (mutt_str_strcmp("builtin", C_Editor) != 0) && !C_EditHeaders)
1557  {
1562  menu->redraw = REDRAW_FULL;
1564  break;
1565  }
1566  /* fallthrough */
1567 
1568  case OP_COMPOSE_EDIT_HEADERS:
1570  if ((mutt_str_strcmp("builtin", C_Editor) != 0) &&
1571  ((op == OP_COMPOSE_EDIT_HEADERS) || ((op == OP_COMPOSE_EDIT_MESSAGE) && C_EditHeaders)))
1572  {
1573  const char *tag = NULL;
1574  char *err = NULL;
1575  mutt_env_to_local(e->env);
1577  if (mutt_env_to_intl(e->env, &tag, &err))
1578  {
1579  mutt_error(_("Bad IDN in '%s': '%s'"), tag, err);
1580  FREE(&err);
1581  }
1582  update_crypt_info(rd);
1583  redraw_env = true;
1584  }
1585  else
1586  {
1587  /* this is grouped with OP_COMPOSE_EDIT_HEADERS because the
1588  * attachment list could change if the user invokes ~v to edit
1589  * the message with headers, in which we need to execute the
1590  * code below to regenerate the index array */
1591  mutt_builtin_editor(e->content->filename, e, e_cur);
1592  }
1593 
1596 
1597  /* attachments may have been added */
1598  if (actx->idxlen && actx->idx[actx->idxlen - 1]->content->next)
1599  {
1600  mutt_actx_entries_free(actx);
1601  mutt_update_compose_menu(actx, menu, true);
1602  }
1603 
1604  menu->redraw = REDRAW_FULL;
1606  break;
1607 
1608  case OP_COMPOSE_ATTACH_KEY:
1609  {
1610  if (!(WithCrypto & APPLICATION_PGP))
1611  break;
1612  struct AttachPtr *ap = mutt_mem_calloc(1, sizeof(struct AttachPtr));
1614  if (ap->content)
1615  {
1616  update_idx(menu, actx, ap);
1617  menu->redraw |= REDRAW_INDEX;
1618  }
1619  else
1620  FREE(&ap);
1621 
1622  menu->redraw |= REDRAW_STATUS;
1623 
1625  break;
1626  }
1627 
1628  case OP_COMPOSE_MOVE_UP:
1629  if (menu->current == 0)
1630  {
1631  mutt_error(_("Attachment is already at top"));
1632  break;
1633  }
1634  if (menu->current == 1)
1635  {
1636  mutt_error(_("The fundamental part can't be moved"));
1637  break;
1638  }
1639  compose_attach_swap(e->content, actx->idx, menu->current - 1);
1640  menu->redraw = REDRAW_INDEX;
1641  menu->current--;
1642  break;
1643 
1644  case OP_COMPOSE_MOVE_DOWN:
1645  if (menu->current == (actx->idxlen - 1))
1646  {
1647  mutt_error(_("Attachment is already at bottom"));
1648  break;
1649  }
1650  if (menu->current == 0)
1651  {
1652  mutt_error(_("The fundamental part can't be moved"));
1653  break;
1654  }
1655  compose_attach_swap(e->content, actx->idx, menu->current);
1656  menu->redraw = REDRAW_INDEX;
1657  menu->current++;
1658  break;
1659 
1660  case OP_COMPOSE_GROUP_ALTS:
1661  {
1662  if (menu->tagged < 2)
1663  {
1664  mutt_error(
1665  _("Grouping 'alternatives' requires at least 2 tagged messages"));
1666  break;
1667  }
1668 
1669  struct Body *group = mutt_body_new();
1670  group->type = TYPE_MULTIPART;
1671  group->subtype = mutt_str_strdup("alternative");
1672  group->disposition = DISP_INLINE;
1673 
1674  struct Body *alts = NULL;
1675  /* group tagged message into a multipart/alternative */
1676  struct Body *bptr = e->content;
1677  for (int i = 0; bptr;)
1678  {
1679  if (bptr->tagged)
1680  {
1681  bptr->tagged = false;
1682  bptr->disposition = DISP_INLINE;
1683 
1684  /* for first match, set group desc according to match */
1685 #define ALTS_TAG "Alternatives for \"%s\""
1686  if (!group->description)
1687  {
1688  char *p = bptr->description ? bptr->description : bptr->filename;
1689  if (p)
1690  {
1691  group->description =
1692  mutt_mem_calloc(1, strlen(p) + strlen(ALTS_TAG) + 1);
1693  sprintf(group->description, ALTS_TAG, p);
1694  }
1695  }
1696 
1697  // append bptr to the alts list, and remove from the e->content list
1698  if (alts)
1699  {
1700  alts->next = bptr;
1701  bptr = bptr->next;
1702  alts = alts->next;
1703  alts->next = NULL;
1704  }
1705  else
1706  {
1707  group->parts = bptr;
1708  alts = bptr;
1709  bptr = bptr->next;
1710  alts->next = NULL;
1711  }
1712 
1713  for (int j = i; j < actx->idxlen - 1; j++)
1714  {
1715  actx->idx[j] = actx->idx[j + 1];
1716  actx->idx[j + 1] = NULL; /* for debug reason */
1717  }
1718  actx->idxlen--;
1719  }
1720  else
1721  {
1722  bptr = bptr->next;
1723  i++;
1724  }
1725  }
1726 
1727  group->next = NULL;
1729 
1730  /* if no group desc yet, make one up */
1731  if (!group->description)
1732  group->description = mutt_str_strdup("unknown alternative group");
1733 
1734  struct AttachPtr *gptr = mutt_mem_calloc(1, sizeof(struct AttachPtr));
1735  gptr->content = group;
1736  update_idx(menu, actx, gptr);
1737  menu->redraw = REDRAW_INDEX;
1738  break;
1739  }
1740 
1741  case OP_COMPOSE_GROUP_LINGUAL:
1742  {
1743  if (menu->tagged < 2)
1744  {
1745  mutt_error(
1746  _("Grouping 'multilingual' requires at least 2 tagged messages"));
1747  break;
1748  }
1749 
1750  /* traverse to see whether all the parts have Content-Language: set */
1751  int tagged_with_lang_num = 0;
1752  for (struct Body *b = e->content; b; b = b->next)
1753  if (b->tagged && b->language && *b->language)
1754  tagged_with_lang_num++;
1755 
1756  if (menu->tagged != tagged_with_lang_num)
1757  {
1758  if (mutt_yesorno(
1759  _("Not all parts have 'Content-Language' set, continue?"), MUTT_YES) != MUTT_YES)
1760  {
1761  mutt_message(_("Not sending this message"));
1762  break;
1763  }
1764  }
1765 
1766  struct Body *group = mutt_body_new();
1767  group->type = TYPE_MULTIPART;
1768  group->subtype = mutt_str_strdup("multilingual");
1769  group->disposition = DISP_INLINE;
1770 
1771  struct Body *alts = NULL;
1772  /* group tagged message into a multipart/multilingual */
1773  struct Body *bptr = e->content;
1774  for (int i = 0; bptr;)
1775  {
1776  if (bptr->tagged)
1777  {
1778  bptr->tagged = false;
1779  bptr->disposition = DISP_INLINE;
1780 
1781  /* for first match, set group desc according to match */
1782 #define LINGUAL_TAG "Multilingual part for \"%s\""
1783  if (!group->description)
1784  {
1785  char *p = bptr->description ? bptr->description : bptr->filename;
1786  if (p)
1787  {
1788  group->description =
1789  mutt_mem_calloc(1, strlen(p) + strlen(LINGUAL_TAG) + 1);
1790  sprintf(group->description, LINGUAL_TAG, p);
1791  }
1792  }
1793 
1794  // append bptr to the alts list, and remove from the e->content list
1795  if (alts)
1796  {
1797  alts->next = bptr;
1798  bptr = bptr->next;
1799  alts = alts->next;
1800  alts->next = NULL;
1801  }
1802  else
1803  {
1804  group->parts = bptr;
1805  alts = bptr;
1806  bptr = bptr->next;
1807  alts->next = NULL;
1808  }
1809 
1810  for (int j = i; j < actx->idxlen - 1; j++)
1811  {
1812  actx->idx[j] = actx->idx[j + 1];
1813  actx->idx[j + 1] = NULL; /* for debug reason */
1814  }
1815  actx->idxlen--;
1816  }
1817  else
1818  {
1819  bptr = bptr->next;
1820  i++;
1821  }
1822  }
1823 
1824  group->next = NULL;
1826 
1827  /* if no group desc yet, make one up */
1828  if (!group->description)
1829  group->description = mutt_str_strdup("unknown multilingual group");
1830 
1831  struct AttachPtr *gptr = mutt_mem_calloc(1, sizeof(struct AttachPtr));
1832  gptr->content = group;
1833  update_idx(menu, actx, gptr);
1834  menu->redraw = REDRAW_INDEX;
1835  break;
1836  }
1837 
1838  case OP_COMPOSE_ATTACH_FILE:
1839  {
1840  char *prompt = _("Attach file");
1841  int numfiles = 0;
1842  char **files = NULL;
1843 
1844  mutt_buffer_reset(&fname);
1845  if ((mutt_buffer_enter_fname_full(prompt, &fname, false, true, &files,
1846  &numfiles, MUTT_SEL_MULTI) == -1) ||
1847  mutt_buffer_is_empty(&fname))
1848  {
1849  break;
1850  }
1851 
1852  bool error = false;
1853  if (numfiles > 1)
1854  {
1855  mutt_message(ngettext("Attaching selected file...",
1856  "Attaching selected files...", numfiles));
1857  }
1858  for (int i = 0; i < numfiles; i++)
1859  {
1860  char *att = files[i];
1861  struct AttachPtr *ap = mutt_mem_calloc(1, sizeof(struct AttachPtr));
1862  ap->unowned = true;
1863  ap->content = mutt_make_file_attach(att);
1864  if (ap->content)
1865  update_idx(menu, actx, ap);
1866  else
1867  {
1868  error = true;
1869  mutt_error(_("Unable to attach %s"), att);
1870  FREE(&ap);
1871  }
1872  FREE(&files[i]);
1873  }
1874 
1875  FREE(&files);
1876  if (!error)
1877  mutt_clear_error();
1878 
1879  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
1881  break;
1882  }
1883 
1884  case OP_COMPOSE_ATTACH_MESSAGE:
1885 #ifdef USE_NNTP
1886  case OP_COMPOSE_ATTACH_NEWS_MESSAGE:
1887 #endif
1888  {
1889  mutt_buffer_reset(&fname);
1890  char *prompt = _("Open mailbox to attach message from");
1891 
1892 #ifdef USE_NNTP
1893  OptNews = false;
1894  if (Context && (op == OP_COMPOSE_ATTACH_NEWS_MESSAGE))
1895  {
1897  if (!CurrentNewsSrv)
1898  break;
1899 
1900  prompt = _("Open newsgroup to attach message from");
1901  OptNews = true;
1902  }
1903 #endif
1904 
1905  if (Context)
1906  {
1907 #ifdef USE_NNTP
1908  if ((op == OP_COMPOSE_ATTACH_MESSAGE) ^ (Context->mailbox->type == MUTT_NNTP))
1909 #endif
1910  {
1913  }
1914  }
1915 
1916  if ((mutt_buffer_enter_fname(prompt, &fname, true) == -1) ||
1917  mutt_buffer_is_empty(&fname))
1918  {
1919  break;
1920  }
1921 
1922 #ifdef USE_NNTP
1923  if (OptNews)
1925  else
1926 #endif
1927  mutt_buffer_expand_path(&fname);
1928 #ifdef USE_IMAP
1929  if (imap_path_probe(mutt_b2s(&fname), NULL) != MUTT_IMAP)
1930 #endif
1931 #ifdef USE_POP
1932  if (pop_path_probe(mutt_b2s(&fname), NULL) != MUTT_POP)
1933 #endif
1934 #ifdef USE_NNTP
1935  if (!OptNews && (nntp_path_probe(mutt_b2s(&fname), NULL) != MUTT_NNTP))
1936 #endif
1937  if (mx_path_probe(mutt_b2s(&fname)) != MUTT_NOTMUCH)
1938  {
1939  /* check to make sure the file exists and is readable */
1940  if (access(mutt_b2s(&fname), R_OK) == -1)
1941  {
1942  mutt_perror(mutt_b2s(&fname));
1943  break;
1944  }
1945  }
1946 
1947  menu->redraw = REDRAW_FULL;
1948 
1949  struct Mailbox *m = mx_path_resolve(mutt_b2s(&fname));
1950  bool old_readonly = m->readonly;
1951  struct Context *ctx = mx_mbox_open(m, MUTT_READONLY);
1952  if (!ctx)
1953  {
1954  mutt_error(_("Unable to open mailbox %s"), mutt_b2s(&fname));
1956  m = NULL;
1957  break;
1958  }
1959 
1960  if (ctx->mailbox->msg_count == 0)
1961  {
1962  mx_mbox_close(&ctx);
1963  mutt_error(_("No messages in that folder"));
1964  break;
1965  }
1966 
1967  struct Context *ctx_cur = Context; /* remember current folder and sort methods */
1968  int old_sort = C_Sort; /* C_Sort, SortAux could be changed in mutt_index_menu() */
1969  int old_sort_aux = C_SortAux;
1970 
1971  Context = ctx;
1972  OptAttachMsg = true;
1973  mutt_message(_("Tag the messages you want to attach"));
1974  struct MuttWindow *dlg_index = index_pager_init();
1976  dialog_push(dlg_index);
1977  mutt_index_menu(dlg_index);
1978  dialog_pop();
1980  index_pager_shutdown(dlg_index);
1981  mutt_window_free(&dlg_index);
1982  OptAttachMsg = false;
1983 
1984  if (!Context)
1985  {
1986  /* go back to the folder we started from */
1987  Context = ctx_cur;
1988  /* Restore old $sort and $sort_aux */
1989  C_Sort = old_sort;
1990  C_SortAux = old_sort_aux;
1991  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
1992  break;
1993  }
1994 
1995  for (int i = 0; i < Context->mailbox->msg_count; i++)
1996  {
1997  if (!Context->mailbox->emails[i])
1998  break;
2000  continue;
2001 
2002  struct AttachPtr *ap = mutt_mem_calloc(1, sizeof(struct AttachPtr));
2004  Context->mailbox->emails[i], true);
2005  if (ap->content)
2006  update_idx(menu, actx, ap);
2007  else
2008  {
2009  mutt_error(_("Unable to attach"));
2010  FREE(&ap);
2011  }
2012  }
2013  menu->redraw |= REDRAW_FULL;
2014 
2015  Context->mailbox->readonly = old_readonly;
2017  ctx_free(&Context);
2018 
2019  /* go back to the folder we started from */
2020  Context = ctx_cur;
2021  /* Restore old $sort and $sort_aux */
2022  C_Sort = old_sort;
2023  C_SortAux = old_sort_aux;
2025  break;
2026  }
2027 
2028  case OP_DELETE:
2029  CHECK_COUNT;
2030  if (CUR_ATTACH->unowned)
2031  CUR_ATTACH->content->unlink = false;
2032  if (delete_attachment(actx, menu->current) == -1)
2033  break;
2034  mutt_update_compose_menu(actx, menu, false);
2035  if (menu->current == 0)
2036  e->content = actx->idx[0]->content;
2037 
2039  break;
2040 
2041  case OP_COMPOSE_TOGGLE_RECODE:
2042  {
2043  CHECK_COUNT;
2044  if (!mutt_is_text_part(CUR_ATTACH->content))
2045  {
2046  mutt_error(_("Recoding only affects text attachments"));
2047  break;
2048  }
2049  CUR_ATTACH->content->noconv = !CUR_ATTACH->content->noconv;
2050  if (CUR_ATTACH->content->noconv)
2051  mutt_message(_("The current attachment won't be converted"));
2052  else
2053  mutt_message(_("The current attachment will be converted"));
2054  menu->redraw = REDRAW_CURRENT;
2056  break;
2057  }
2058 
2059  case OP_COMPOSE_EDIT_DESCRIPTION:
2060  CHECK_COUNT;
2062  buf, CUR_ATTACH->content->description ? CUR_ATTACH->content->description : "",
2063  sizeof(buf));
2064  /* header names should not be translated */
2065  if (mutt_get_field("Description: ", buf, sizeof(buf), MUTT_COMP_NO_FLAGS) == 0)
2066  {
2067  mutt_str_replace(&CUR_ATTACH->content->description, buf);
2068  menu->redraw = REDRAW_CURRENT;
2069  }
2071  break;
2072 
2073  case OP_COMPOSE_UPDATE_ENCODING:
2074  CHECK_COUNT;
2075  if (menu->tagprefix)
2076  {
2077  struct Body *top = NULL;
2078  for (top = e->content; top; top = top->next)
2079  {
2080  if (top->tagged)
2081  mutt_update_encoding(top);
2082  }
2083  menu->redraw = REDRAW_FULL;
2084  }
2085  else
2086  {
2087  mutt_update_encoding(CUR_ATTACH->content);
2089  }
2091  break;
2092 
2093  case OP_COMPOSE_TOGGLE_DISPOSITION:
2094  /* toggle the content-disposition between inline/attachment */
2095  CUR_ATTACH->content->disposition =
2096  (CUR_ATTACH->content->disposition == DISP_INLINE) ? DISP_ATTACH : DISP_INLINE;
2097  menu->redraw = REDRAW_CURRENT;
2098  break;
2099 
2100  case OP_EDIT_TYPE:
2101  CHECK_COUNT;
2102  {
2103  mutt_edit_content_type(NULL, CUR_ATTACH->content, NULL);
2104 
2105  /* this may have been a change to text/something */
2106  mutt_update_encoding(CUR_ATTACH->content);
2107 
2108  menu->redraw = REDRAW_CURRENT;
2109  }
2111  break;
2112 
2113  case OP_COMPOSE_EDIT_LANGUAGE:
2114  CHECK_COUNT;
2115  buf[0] = '\0'; /* clear buffer first */
2116  if (CUR_ATTACH->content->language)
2117  mutt_str_strfcpy(buf, CUR_ATTACH->content->language, sizeof(buf));
2118  if (mutt_get_field("Content-Language: ", buf, sizeof(buf), MUTT_COMP_NO_FLAGS) == 0)
2119  {
2120  CUR_ATTACH->content->language = mutt_str_strdup(buf);
2122  mutt_clear_error();
2123  }
2124  else
2125  mutt_warning(_("Empty 'Content-Language'"));
2127  break;
2128 
2129  case OP_COMPOSE_EDIT_ENCODING:
2130  CHECK_COUNT;
2131  mutt_str_strfcpy(buf, ENCODING(CUR_ATTACH->content->encoding), sizeof(buf));
2132  if ((mutt_get_field("Content-Transfer-Encoding: ", buf, sizeof(buf),
2133  MUTT_COMP_NO_FLAGS) == 0) &&
2134  (buf[0] != '\0'))
2135  {
2136  int enc = mutt_check_encoding(buf);
2137  if ((enc != ENC_OTHER) && (enc != ENC_UUENCODED))
2138  {
2139  CUR_ATTACH->content->encoding = enc;
2141  mutt_clear_error();
2142  }
2143  else
2144  mutt_error(_("Invalid encoding"));
2145  }
2147  break;
2148 
2149  case OP_COMPOSE_SEND_MESSAGE:
2150  /* Note: We don't invoke send2-hook here, since we want to leave
2151  * users an opportunity to change settings from the ":" prompt. */
2152  if (check_attachments(actx) != 0)
2153  {
2154  menu->redraw = REDRAW_FULL;
2155  break;
2156  }
2157 
2158 #ifdef MIXMASTER
2159  if (!STAILQ_EMPTY(&e->chain) && (mix_check_message(e) != 0))
2160  break;
2161 #endif
2162 
2163  if (!fcc_set && !mutt_buffer_is_empty(fcc))
2164  {
2165  enum QuadOption ans =
2166  query_quadoption(C_Copy, _("Save a copy of this message?"));
2167  if (ans == MUTT_ABORT)
2168  break;
2169  else if (ans == MUTT_NO)
2170  mutt_buffer_reset(fcc);
2171  }
2172 
2173  loop = false;
2174  rc = 0;
2175  break;
2176 
2177  case OP_COMPOSE_EDIT_FILE:
2178  CHECK_COUNT;
2179  mutt_edit_file(NONULL(C_Editor), CUR_ATTACH->content->filename);
2180  mutt_update_encoding(CUR_ATTACH->content);
2183  break;
2184 
2185  case OP_COMPOSE_TOGGLE_UNLINK:
2186  CHECK_COUNT;
2187  CUR_ATTACH->content->unlink = !CUR_ATTACH->content->unlink;
2188 
2189  menu->redraw = REDRAW_INDEX;
2190  /* No send2hook since this doesn't change the message. */
2191  break;
2192 
2193  case OP_COMPOSE_GET_ATTACHMENT:
2194  CHECK_COUNT;
2195  if (menu->tagprefix)
2196  {
2197  for (struct Body *top = e->content; top; top = top->next)
2198  {
2199  if (top->tagged)
2201  }
2202  menu->redraw = REDRAW_FULL;
2203  }
2204  else if (mutt_get_tmp_attachment(CUR_ATTACH->content) == 0)
2205  menu->redraw = REDRAW_CURRENT;
2206 
2207  /* No send2hook since this doesn't change the message. */
2208  break;
2209 
2210  case OP_COMPOSE_RENAME_ATTACHMENT:
2211  {
2212  CHECK_COUNT;
2213  char *src = NULL;
2214  if (CUR_ATTACH->content->d_filename)
2215  src = CUR_ATTACH->content->d_filename;
2216  else
2217  src = CUR_ATTACH->content->filename;
2219  int ret = mutt_buffer_get_field(_("Send attachment with name: "), &fname, MUTT_FILE);
2220  if (ret == 0)
2221  {
2222  /* As opposed to RENAME_FILE, we don't check buf[0] because it's
2223  * valid to set an empty string here, to erase what was set */
2224  mutt_str_replace(&CUR_ATTACH->content->d_filename, mutt_b2s(&fname));
2225  menu->redraw = REDRAW_CURRENT;
2226  }
2227  break;
2228  }
2229 
2230  case OP_COMPOSE_RENAME_FILE:
2231  CHECK_COUNT;
2232  mutt_buffer_strcpy(&fname, CUR_ATTACH->content->filename);
2234  if ((mutt_buffer_get_field(_("Rename to: "), &fname, MUTT_FILE) == 0) &&
2235  !mutt_buffer_is_empty(&fname))
2236  {
2237  struct stat st;
2238  if (stat(CUR_ATTACH->content->filename, &st) == -1)
2239  {
2240  /* L10N: "stat" is a system call. Do "man 2 stat" for more information. */
2241  mutt_error(_("Can't stat %s: %s"), mutt_b2s(&fname), strerror(errno));
2242  break;
2243  }
2244 
2245  mutt_buffer_expand_path(&fname);
2246  if (mutt_file_rename(CUR_ATTACH->content->filename, mutt_b2s(&fname)))
2247  break;
2248 
2249  mutt_str_replace(&CUR_ATTACH->content->filename, mutt_b2s(&fname));
2250  menu->redraw = REDRAW_CURRENT;
2251 
2252  if (CUR_ATTACH->content->stamp >= st.st_mtime)
2254  }
2256  break;
2257 
2258  case OP_COMPOSE_NEW_MIME:
2259  {
2260  mutt_buffer_reset(&fname);
2261  if ((mutt_buffer_get_field(_("New file: "), &fname, MUTT_FILE) != 0) ||
2262  mutt_buffer_is_empty(&fname))
2263  {
2264  continue;
2265  }
2266  mutt_buffer_expand_path(&fname);
2267 
2268  /* Call to lookup_mime_type () ? maybe later */
2269  char type[256] = { 0 };
2270  if ((mutt_get_field("Content-Type: ", type, sizeof(type), MUTT_COMP_NO_FLAGS) != 0) ||
2271  (type[0] == '\0'))
2272  {
2273  continue;
2274  }
2275 
2276  char *p = strchr(type, '/');
2277  if (!p)
2278  {
2279  mutt_error(_("Content-Type is of the form base/sub"));
2280  continue;
2281  }
2282  *p++ = 0;
2283  enum ContentType itype = mutt_check_mime_type(type);
2284  if (itype == TYPE_OTHER)
2285  {
2286  mutt_error(_("Unknown Content-Type %s"), type);
2287  continue;
2288  }
2289  struct AttachPtr *ap = mutt_mem_calloc(1, sizeof(struct AttachPtr));
2290  /* Touch the file */
2291  FILE *fp = mutt_file_fopen(mutt_b2s(&fname), "w");
2292  if (!fp)
2293  {
2294  mutt_error(_("Can't create file %s"), mutt_b2s(&fname));
2295  FREE(&ap);
2296  continue;
2297  }
2298  mutt_file_fclose(&fp);
2299 
2300  ap->content = mutt_make_file_attach(mutt_b2s(&fname));
2301  if (!ap->content)
2302  {
2303  mutt_error(_("What we have here is a failure to make an attachment"));
2304  FREE(&ap);
2305  continue;
2306  }
2307  update_idx(menu, actx, ap);
2308 
2309  CUR_ATTACH->content->type = itype;
2310  mutt_str_replace(&CUR_ATTACH->content->subtype, p);
2311  CUR_ATTACH->content->unlink = true;
2312  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
2313 
2314  if (mutt_compose_attachment(CUR_ATTACH->content))
2315  {
2316  mutt_update_encoding(CUR_ATTACH->content);
2317  menu->redraw = REDRAW_FULL;
2318  }
2320  break;
2321  }
2322 
2323  case OP_COMPOSE_EDIT_MIME:
2324  CHECK_COUNT;
2325  if (mutt_edit_attachment(CUR_ATTACH->content))
2326  {
2327  mutt_update_encoding(CUR_ATTACH->content);
2328  menu->redraw = REDRAW_FULL;
2329  }
2331  break;
2332 
2333  case OP_VIEW_ATTACH:
2334  case OP_DISPLAY_HEADERS:
2335  CHECK_COUNT;
2336  mutt_attach_display_loop(menu, op, NULL, actx, false);
2337  menu->redraw = REDRAW_FULL;
2338  /* no send2hook, since this doesn't modify the message */
2339  break;
2340 
2341  case OP_SAVE:
2342  CHECK_COUNT;
2343  mutt_save_attachment_list(actx, NULL, menu->tagprefix,
2344  CUR_ATTACH->content, NULL, menu);
2345  /* no send2hook, since this doesn't modify the message */
2346  break;
2347 
2348  case OP_PRINT:
2349  CHECK_COUNT;
2350  mutt_print_attachment_list(actx, NULL, menu->tagprefix, CUR_ATTACH->content);
2351  /* no send2hook, since this doesn't modify the message */
2352  break;
2353 
2354  case OP_PIPE:
2355  case OP_FILTER:
2356  CHECK_COUNT;
2357  mutt_pipe_attachment_list(actx, NULL, menu->tagprefix,
2358  CUR_ATTACH->content, (op == OP_FILTER));
2359  if (op == OP_FILTER) /* cte might have changed */
2360  menu->redraw = menu->tagprefix ? REDRAW_FULL : REDRAW_CURRENT;
2361  menu->redraw |= REDRAW_STATUS;
2363  break;
2364 
2365  case OP_EXIT:
2366  {
2367  enum QuadOption ans =
2368  query_quadoption(C_Postpone, _("Save (postpone) draft message?"));
2369  if (ans == MUTT_NO)
2370  {
2371  for (int i = 0; i < actx->idxlen; i++)
2372  if (actx->idx[i]->unowned)
2373  actx->idx[i]->content->unlink = false;
2374 
2375  if (!(flags & MUTT_COMPOSE_NOFREEHEADER))
2376  {
2377  for (int i = 0; i < actx->idxlen; i++)
2378  {
2379  /* avoid freeing other attachments */
2380  actx->idx[i]->content->next = NULL;
2381  /* See the comment in delete_attachment() */
2382  if (!actx->idx[i]->content->email)
2383  actx->idx[i]->content->parts = NULL;
2384  mutt_body_free(&actx->idx[i]->content);
2385  }
2386  }
2387  rc = -1;
2388  loop = false;
2389  break;
2390  }
2391  else if (ans == MUTT_ABORT)
2392  break; /* abort */
2393  }
2394  /* fallthrough */
2395 
2396  case OP_COMPOSE_POSTPONE_MESSAGE:
2397  if (check_attachments(actx) != 0)
2398  {
2399  menu->redraw = REDRAW_FULL;
2400  break;
2401  }
2402 
2403  loop = false;
2404  rc = 1;
2405  break;
2406 
2407  case OP_COMPOSE_ISPELL:
2408  endwin();
2409  snprintf(buf, sizeof(buf), "%s -x %s", NONULL(C_Ispell), e->content->filename);
2410  if (mutt_system(buf) == -1)
2411  mutt_error(_("Error running \"%s\""), buf);
2412  else
2413  {
2415  menu->redraw |= REDRAW_STATUS;
2416  }
2417  break;
2418 
2419  case OP_COMPOSE_WRITE_MESSAGE:
2420  mutt_buffer_reset(&fname);
2421  if (Context)
2422  {
2425  }
2426  if (actx->idxlen)
2427  e->content = actx->idx[0]->content;
2428  if ((mutt_buffer_enter_fname(_("Write message to mailbox"), &fname, true) != -1) &&
2429  !mutt_buffer_is_empty(&fname))
2430  {
2431  mutt_message(_("Writing message to %s ..."), mutt_b2s(&fname));
2432  mutt_buffer_expand_path(&fname);
2433 
2434  if (e->content->next)
2436 
2437  if (mutt_write_fcc(mutt_b2s(&fname), e, NULL, false, NULL, NULL) == 0)
2438  mutt_message(_("Message written"));
2439 
2441  }
2442  break;
2443 
2444  case OP_COMPOSE_PGP_MENU:
2445  if (!(WithCrypto & APPLICATION_PGP))
2446  break;
2447  if (!crypt_has_module_backend(APPLICATION_PGP))
2448  {
2449  mutt_error(_("No PGP backend configured"));
2450  break;
2451  }
2452  if (((WithCrypto & APPLICATION_SMIME) != 0) && (e->security & APPLICATION_SMIME))
2453  {
2454  if (e->security & (SEC_ENCRYPT | SEC_SIGN))
2455  {
2456  if (mutt_yesorno(_("S/MIME already selected. Clear and continue?"), MUTT_YES) != MUTT_YES)
2457  {
2458  mutt_clear_error();
2459  break;
2460  }
2461  e->security &= ~(SEC_ENCRYPT | SEC_SIGN);
2462  }
2463  e->security &= ~APPLICATION_SMIME;
2464  e->security |= APPLICATION_PGP;
2465  update_crypt_info(rd);
2466  }
2467  e->security = crypt_pgp_send_menu(e);
2468  update_crypt_info(rd);
2470  redraw_env = true;
2471  break;
2472 
2473  case OP_FORGET_PASSPHRASE:
2475  break;
2476 
2477  case OP_COMPOSE_SMIME_MENU:
2478  if (!(WithCrypto & APPLICATION_SMIME))
2479  break;
2480  if (!crypt_has_module_backend(APPLICATION_SMIME))
2481  {
2482  mutt_error(_("No S/MIME backend configured"));
2483  break;
2484  }
2485 
2486  if (((WithCrypto & APPLICATION_PGP) != 0) && (e->security & APPLICATION_PGP))
2487  {
2488  if (e->security & (SEC_ENCRYPT | SEC_SIGN))
2489  {
2490  if (mutt_yesorno(_("PGP already selected. Clear and continue?"), MUTT_YES) != MUTT_YES)
2491  {
2492  mutt_clear_error();
2493  break;
2494  }
2495  e->security &= ~(SEC_ENCRYPT | SEC_SIGN);
2496  }
2497  e->security &= ~APPLICATION_PGP;
2499  update_crypt_info(rd);
2500  }
2502  update_crypt_info(rd);
2504  redraw_env = true;
2505  break;
2506 
2507 #ifdef MIXMASTER
2508  case OP_COMPOSE_MIX:
2511  redraw_env = true;
2512  break;
2513 #endif
2514 
2515 #ifdef USE_AUTOCRYPT
2516  case OP_COMPOSE_AUTOCRYPT_MENU:
2517  if (!C_Autocrypt)
2518  break;
2519 
2520  if ((WithCrypto & APPLICATION_SMIME) && (e->security & APPLICATION_SMIME))
2521  {
2522  if (e->security & (SEC_ENCRYPT | SEC_SIGN))
2523  {
2524  if (mutt_yesorno(_("S/MIME already selected. Clear and continue?"), MUTT_YES) != MUTT_YES)
2525  {
2526  mutt_clear_error();
2527  break;
2528  }
2529  e->security &= ~(SEC_ENCRYPT | SEC_SIGN);
2530  }
2531  e->security &= ~APPLICATION_SMIME;
2532  e->security |= APPLICATION_PGP;
2533  update_crypt_info(rd);
2534  }
2536  update_crypt_info(rd);
2538  redraw_env = true;
2539  break;
2540 #endif
2541  }
2542  }
2543 
2544  mutt_buffer_dealloc(&fname);
2545 
2546 #ifdef USE_AUTOCRYPT
2547  /* This is a fail-safe to make sure the bit isn't somehow turned
2548  * on. The user could have disabled the option after setting SEC_AUTOCRYPT,
2549  * or perhaps resuming or replying to an autocrypt message. */
2550  if (!C_Autocrypt)
2551  e->security &= ~SEC_AUTOCRYPT;
2552 #endif
2553 
2554  mutt_menu_pop_current(menu);
2555  mutt_menu_free(&menu);
2556  dialog_pop();
2558  mutt_window_free(&dlg);
2559 
2560  if (actx->idxlen)
2561  e->content = actx->idx[0]->content;
2562  else
2563  e->content = NULL;
2564 
2565  mutt_actx_free(&actx);
2566 
2567  return rc;
2568 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
#define mutt_warning(...)
Definition: logging.h:82
The "current" mailbox.
Definition: context.h:37
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:192
WHERE bool C_StatusOnTop
Config: Display the status bar at the top.
Definition: globals.h:252
struct Body * mutt_make_message_attach(struct Mailbox *m, struct Email *e, bool attach_msg)
Create a message attachment.
Definition: sendlib.c:1511
static int delete_attachment(struct AttachCtx *actx, int x)
Delete an attachment.
Definition: compose.c:950
void mutt_stamp_attachment(struct Body *a)
Timestamp an Attachment.
Definition: sendlib.c:1443
Unknown Content-Type.
Definition: mime.h:31
#define REDRAW_FULL
Redraw everything.
Definition: mutt_menu.h:47
void mutt_actx_free(struct AttachCtx **ptr)
Free an Attachment Context.
Definition: attach.c:140
void mix_make_chain(struct MuttWindow *win, struct ListHead *chainhead, int cols)
Create a Mixmaster chain.
Definition: remailer.c:601
bool message_is_tagged(struct Context *ctx, struct Email *e)
Is a message in the index tagged (and within limit)
Definition: context.c:351
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
#define NONULL(x)
Definition: string2.h:37
WHERE bool C_Autocrypt
Config: Enables the Autocrypt feature.
Definition: globals.h:200
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
An email to which things will be attached.
Definition: attach.h:34
int mutt_attach_display_loop(struct Menu *menu, int op, struct Email *e, struct AttachCtx *actx, bool recv)
Event loop for the Attachment menu.
Definition: recvattach.c:1151
int msg_count
Total number of messages.
Definition: mailbox.h:91
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
struct Body * mutt_remove_multipart(struct Body *b)
Extract the multipart body if it exists.
Definition: sendlib.c:1772
#define WithCrypto
Definition: lib.h:163
#define MUTT_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:62
#define mutt_perror(...)
Definition: logging.h:85
GUI selectable list of items.
Definition: mutt_menu.h:82
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2524
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:36
&#39;NNTP&#39; (Usenet) Mailbox type
Definition: mailbox.h:52
int mx_mbox_close(struct Context **ptr)
Save changes and close mailbox.
Definition: mx.c:593
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer&#39;s contents to another Buffer.
Definition: buffer.c:445
struct AddressList reply_to
Email&#39;s &#39;reply-to&#39;.
Definition: envelope.h:62
const char * mutt_path_basename(const char *f)
Find the last component for a pathname.
Definition: path.c:329
Pager Bar containing status info about the Pager.
Definition: mutt_window.h:77
Dialog (nested Windows) displayed to the user.
Definition: mutt_window.h:70
User aborted the question (with Ctrl-G)
Definition: quad.h:38
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: init.c:1112
#define mutt_message(...)
Definition: logging.h:83
struct MuttWindow * win_abar
Attachments label.
Definition: compose.c:128
Window uses all available vertical space.
Definition: mutt_window.h:35
struct Email * email
Used by recvattach for updating.
Definition: attach.h:51
int mutt_file_rename(const char *oldfile, const char *newfile)
Rename a file.
Definition: file.c:1341
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
struct AddressList bcc
Email&#39;s &#39;Bcc&#39; list.
Definition: envelope.h:60
static void compose_custom_redraw(struct Menu *menu)
Redraw the compose menu - Implements Menu::custom_redraw()
Definition: compose.c:1079
void dialog_pop(void)
Hide a Window from the user.
Definition: mutt_window.c:628
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:125
void mutt_save_attachment_list(struct AttachCtx *actx, FILE *fp, bool tag, struct Body *top, struct Email *e, struct Menu *menu)
Save a list of attachments.
Definition: recvattach.c:651
"To:" field
Definition: compose.c:150
void dialog_push(struct MuttWindow *dlg)
Display a Window to the user.
Definition: mutt_window.c:605
struct Body * content
List of MIME parts.
Definition: email.h:90
void crypt_forget_passphrase(void)
Forget a passphrase and display a message.
Definition: crypt.c:104
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
static void edit_address_list(int field, struct AddressList *al)
Let the user edit the address list.
Definition: compose.c:921
"Cc:" field
Definition: compose.c:151
int mutt_edit_attachment(struct Body *a)
Edit an attachment.
Definition: mutt_attach.c:257
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
static void update_crypt_info(struct ComposeRedrawData *rd)
Update the crypto info.
Definition: compose.c:615
struct Body * next
next attachment in the list
Definition: body.h:53
short idxlen
Number of attachmentes.
Definition: attach.h:55
Compose an email.
Definition: keymap.h:73
struct Context * mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:255
WHERE unsigned char C_Copy
Config: Save outgoing emails to $record.
Definition: globals.h:180
static int calc_envelope(struct ComposeRedrawData *rd)
Calculate how many rows the envelope will need.
Definition: compose.c:475
A division of the screen.
Definition: mutt_window.h:88
#define SEC_AUTOCRYPT
(Autocrypt) Message will be, or was Autocrypt encrypt+signed
Definition: lib.h:134
struct ListHead bcc_list
Definition: compose.c:116
struct Email * email
Definition: compose.c:111
char * C_Ispell
Config: External command to perform spell-checking.
Definition: compose.c:98
struct Buffer * fcc
Definition: compose.c:112
#define MUTT_READONLY
Open in read-only mode.
Definition: mx.h:55
"Subject:" field
Definition: compose.c:153
int mutt_env_to_intl(struct Envelope *env, const char **tag, char **err)
Convert an Envelope&#39;s Address fields to Punycode format.
Definition: envelope.c:309
static int check_attachments(struct AttachCtx *actx)
Check if any attachments have changed or been deleted.
Definition: compose.c:695
"From:" field
Definition: compose.c:149
struct NntpAccountData * nntp_select_server(struct Mailbox *m, char *server, bool leave_lock)
Open a connection to an NNTP server.
Definition: newsrc.c:1014
Container for Accounts, Notifications.
Definition: neomutt.h:35
void mutt_buffer_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:688
int mutt_write_fcc(const char *path, struct Email *e, const char *msgid, bool post, const char *fcc, char **finalpath)
Write email to FCC mailbox.
Definition: sendlib.c:3258
The "-- Attachments" line.
Definition: compose.c:169
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:90
The body of an email.
Definition: body.h:34
unsigned int disposition
content-disposition
Definition: body.h:67
An Index Window containing a selection list.
Definition: mutt_window.h:74
static void snd_make_entry(char *buf, size_t buflen, struct Menu *menu, int line)
Format a menu item for the attachment list - Implements Menu::make_entry()
Definition: compose.c:325
void mutt_window_free(struct MuttWindow **ptr)
Free a Window and its children.
Definition: mutt_window.c:74
#define CUR_ATTACH
Definition: compose.c:140
int mutt_dlg_index_observer(struct NotifyCallback *nc)
Listen for config changes affecting the Index/Pager - Implements observer_t.
Definition: index.c:4130
size_t dsize
Length of data.
Definition: buffer.h:37
void * redraw_data
Definition: mutt_menu.h:154
void mutt_print_attachment_list(struct AttachCtx *actx, FILE *fp, bool tag, struct Body *top)
Print a list of Attachments.
Definition: recvattach.c:1032
int mutt_get_tmp_attachment(struct Body *a)
Get a temporary copy of an attachment.
Definition: mutt_attach.c:68
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:377
WHERE bool C_EditHeaders
Config: Let the user edit the email headers whilst editing an email.
Definition: globals.h:212
struct Mailbox * mailbox
Definition: context.h:51
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
void mutt_generate_boundary(struct ParameterList *pl)
Create a unique boundary id for a MIME part.
Definition: sendlib.c:636
struct Body * mutt_make_file_attach(const char *path)
Create a file attachment.
Definition: sendlib.c:1650
#define STAILQ_INIT(head)
Definition: queue.h:369
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:56
enum ContentType mutt_check_mime_type(const char *s)
Check a MIME type string.
Definition: parse.c:318
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:57
struct MuttWindow * win_ibar
Definition: mutt_menu.h:95
int crypt_smime_send_menu(struct Email *e)
Wrapper for CryptModuleSpecs::send_menu()
Definition: cryptglue.c:533
bool readonly
Don&#39;t allow changes to the mailbox.
Definition: mailbox.h:119
void mutt_update_encoding(struct Body *a)
Update the encoding type.
Definition: sendlib.c:1480
struct MuttWindow * win_envelope
Envelope: From, To, etc.
Definition: compose.c:127
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
struct Envelope * env
Envelope information.
Definition: email.h:89
#define ENCODING(x)
Definition: mime.h:85
void mx_fastclose_mailbox(struct Mailbox *m)
free up memory associated with the Mailbox
Definition: mx.c:414
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:59
"X-Comment-To:" field
Definition: compose.c:167
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
Content is attached.
Definition: mime.h:63
static void compose_attach_swap(struct Body *msg, struct AttachPtr **idx, short first)
Swap two adjacent entries in the attachment list.
Definition: compose.c:1131
void mutt_rfc3676_space_unstuff(struct Email *e)
Remove RFC3676 space stuffing.
Definition: rfc3676.c:481
struct AttachCtx * mutt_actx_new(void)
Create a new Attachment Context.
Definition: attach.c:131
WHERE short C_Sort
Config: Sort method for the index.
Definition: sort.h:58
bool tagged
This attachment is tagged.
Definition: body.h:70
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:113
bool unowned
Don&#39;t unlink on detach.
Definition: attach.h:42
struct Body * mutt_make_multipart(struct Body *b)
Create a multipart email.
Definition: sendlib.c:1746
Window has a fixed size.
Definition: mutt_window.h:44
const char * help
Quickref for the current menu.
Definition: mutt_menu.h:85
char * subtype
content-type subtype
Definition: body.h:37
int mutt_buffer_enter_fname_full(const char *prompt, struct Buffer *fname, bool mailbox, bool multiple, char ***files, int *numfiles, SelectFileFlags flags)
Ask the user to select a file.
Definition: curs_lib.c:745
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:58
#define mutt_b2s(buf)
Definition: buffer.h:41
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:138
WHERE char * C_NewsServer
Config: (nntp) Url of the news server.
Definition: globals.h:130
static const struct Mapping ComposeHelp[]
Definition: compose.c:216
char * x_comment_to
List of &#39;X-comment-to&#39; fields.
Definition: envelope.h:78
struct ListHead chain
Mixmaster chain.
Definition: email.h:99
WHERE short C_SortAux
Config: Secondary sort method for the index.
Definition: sort.h:59
WHERE struct Context * Context
Definition: globals.h:42
int attach_tag(struct Menu *menu, int sel, int act)
Tag an attachment - Implements Menu::tag()
Definition: recvattach.c:450
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:93
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:137
WHERE bool OptAttachMsg
(pseudo) used by attach-message
Definition: options.h:31
&#39;POP3&#39; Mailbox type
Definition: mailbox.h:55
#define REDRAW_STATUS
Redraw the status bar.
Definition: mutt_menu.h:46
int mutt_check_encoding(const char *c)
Check the encoding type.
Definition: parse.c:427
#define ALTS_TAG
struct MuttWindow * mutt_window_new(enum MuttWindowOrientation orient, enum MuttWindowSize size, int rows, int cols)
Create a new Window.
Definition: mutt_window.c:56
A mailbox.
Definition: mailbox.h:81
#define PATH_MAX
Definition: mutt.h:44
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:39
#define MUTT_WIN_SIZE_UNLIMITED
Use as much space as possible.
Definition: mutt_window.h:49
short rows
Number of rows, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:57
bool tagprefix
Definition: mutt_menu.h:92
enum MailboxType nntp_path_probe(const char *path, const struct stat *st)
Is this an NNTP Mailbox? - Implements MxOps::path_probe()
Definition: nntp.c:2836
char * data
Pointer to data.
Definition: buffer.h:35
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:776
int crypt_pgp_send_menu(struct Email *e)
Wrapper for CryptModuleSpecs::send_menu()
Definition: cryptglue.c:387
FILE * fp
Used in the recvattach menu.
Definition: attach.h:37
static void mutt_update_compose_menu(struct AttachCtx *actx, struct Menu *menu, bool init)
Redraw the compose window.
Definition: compose.c:1036
void(* custom_redraw)(struct Menu *menu)
Redraw the menu.
Definition: mutt_menu.h:152
int(* tag)(struct Menu *menu, int sel, int act)
Tag some menu items.
Definition: mutt_menu.h:138
char * description
content-description
Definition: body.h:40
int pagelen
Number of entries per screen.
Definition: mutt_menu.h:91
bool mutt_is_text_part(struct Body *b)
Is this part of an email in plain text?
Definition: muttlib.c:437
static const char *const Prompts[]
Definition: compose.c:175
struct Notify * notify
Notifications handler.
Definition: neomutt.h:37
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib...
Definition: email.h:39
enum MailboxType pop_path_probe(const char *path, const struct stat *st)
Is this a POP Mailbox? - Implements MxOps::path_probe()
Definition: pop.c:1231
int mutt_index_menu(struct MuttWindow *dlg)
Display a list of emails.
Definition: index.c:1115
#define MUTT_SEL_MULTI
Multi-selection is enabled.
Definition: browser.h:46
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:455
static struct Mapping ComposeNewsHelp[]
Definition: compose.c:232
int tagged
Number of tagged entries.
Definition: mutt_menu.h:110
bool notify_observer_add(struct Notify *notify, observer_t callback, void *global_data)
Add an observer to an object.
Definition: notify.c:153
#define MUTT_FILE
Do file completion.
Definition: mutt.h:58
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
unsigned int type
content-type primary type
Definition: body.h:65
void mutt_window_add_child(struct MuttWindow *parent, struct MuttWindow *child)
Add a child to Window.
Definition: mutt_window.c:473
&#39;Notmuch&#39; (virtual) Mailbox type
Definition: mailbox.h:54
"Bcc:" field
Definition: compose.c:152
"Followup-To:" field
Definition: compose.c:166
#define mutt_buffer_get_field(field, buf, complete)
Definition: curs_lib.h:84
#define LINGUAL_TAG
MuttRedrawFlags redraw
When to redraw the screen.
Definition: mutt_menu.h:89
#define SEC_SIGN
Email is signed.
Definition: lib.h:126
bool crypt_has_module_backend(SecurityFlags type)
Is there a crypto backend for a given type?
Definition: cryptglue.c:172
static void update_idx(struct Menu *menu, struct AttachCtx *actx, struct AttachPtr *ap)
Add a new attchment to the message.
Definition: compose.c:1065
struct Connection * conn
Definition: lib.h:104
Window containing paged free-form text.
Definition: mutt_window.h:76
void mutt_pipe_attachment_list(struct AttachCtx *actx, FILE *fp, bool tag, struct Body *top, bool filter)
Pipe a list of attachments to a command.
Definition: recvattach.c:877
void mutt_env_to_local(struct Envelope *env)
Convert an Envelope&#39;s Address fields to local format.
Definition: envelope.c:271
void mutt_edit_headers(const char *editor, const char *body, struct Email *e, struct Buffer *fcc)
Let the user edit the message header and body.
Definition: mutt_header.c:168
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition: mx.c:1318
struct Body * crypt_pgp_make_key_attachment(void)
Wrapper for CryptModuleSpecs::pgp_make_key_attachment()
Definition: cryptglue.c:308
void mutt_actx_entries_free(struct AttachCtx *actx)
Free entries in an Attachment Context.
Definition: attach.c:103
char * subject
Email&#39;s subject.
Definition: envelope.h:66
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:327
char * newsgroups
List of newsgroups.
Definition: envelope.h:75
#define MUTT_SEND2_HOOK
send2-hook: when changing fields in the compose menu
Definition: hook.h:56
#define REDRAW_INDEX
Redraw the index.
Definition: mutt_menu.h:42
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
WHERE bool C_XCommentTo
Config: (nntp) Add &#39;X-Comment-To&#39; header that contains article author.
Definition: globals.h:283
struct Body * content
Attachment.
Definition: attach.h:36
void mutt_window_reflow(struct MuttWindow *win)
Resize a Window and its children.
Definition: mutt_window.c:345
unsigned char C_Postpone
Config: Save messages to the C_Postponed folder.
Definition: compose.c:99
#define mutt_error(...)
Definition: logging.h:84
int mutt_builtin_editor(const char *path, struct Email *e_new, struct Email *e_cur)
Show the user the built-in editor.
Definition: edit.c:401
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
void mutt_rfc3676_space_stuff(struct Email *e)
Perform RFC3676 space stuffing on an Email.
Definition: rfc3676.c:463
char * followup_to
List of &#39;followup-to&#39; fields.
Definition: envelope.h:77
static void autocrypt_compose_menu(struct Email *e)
Autocrypt compose settings.
Definition: compose.c:340
WHERE char * C_Editor
Config: External command to use as an email editor.
Definition: globals.h:111
struct MuttWindow * win_cbar
Compose bar.
Definition: compose.c:130
struct ListHead cc_list
Definition: compose.c:115
#define FREE(x)
Definition: memory.h:40
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition: mx.c:1655
#define MUTT_COMPOSE_NOFREEHEADER
Definition: compose.h:35
#define STAILQ_EMPTY(head)
Definition: queue.h:345
struct MuttWindow * win_attach
List of Attachments.
Definition: compose.c:129
void index_pager_shutdown(struct MuttWindow *dlg)
Clear up any non-Window parts.
Definition: index.c:4115
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:84
short req_rows
Number of rows required.
Definition: mutt_window.h:90
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:185
"Newsgroups:" field
Definition: compose.c:165
static void init_header_padding(void)
Calculate how much padding the compose table will need.
Definition: compose.c:294
struct MuttWindow * index_pager_init(void)
Allocate the Windows for the Index/Pager.
Definition: index.c:4022
struct ListHead to_list
Definition: compose.c:114
void ctx_free(struct Context **ptr)
Free a Context.
Definition: context.c:48
void mutt_message_hook(struct Mailbox *m, struct Email *e, HookFlags type)
Perform a message hook.
Definition: hook.c:576
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
bool mutt_edit_content_type(struct Email *e, struct Body *b, FILE *fp)
Edit the content type of an attachment.
Definition: commands.c:1249
int current
Current entry.
Definition: mutt_menu.h:87
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:47
"Fcc:" (save folder) field
Definition: compose.c:155
#define CHECK_COUNT
Definition: compose.c:133
struct MuttWindow * win_index
Definition: mutt_menu.h:94
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
char * mutt_compile_help(char *buf, size_t buflen, enum MenuType menu, const struct Mapping *items)
Create the text for the help menu.
Definition: help.c:116
void nntp_expand_path(char *buf, size_t buflen, struct ConnAccount *acct)
Make fully qualified url from newsgroup name.
Definition: newsrc.c:563
Window wants as much space as possible.
Definition: mutt_window.h:45
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
Content is inline.
Definition: mime.h:62
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
struct Email * email
header information for message/rfc822
Definition: body.h:55
Index Bar containing status info about the Index.
Definition: mutt_window.h:75
enum WindowType type
Window type, e.g. WT_SIDEBAR.
Definition: mutt_window.h:103
A set of attachments.
Definition: attach.h:49
Encoding unknown.
Definition: mime.h:48
struct AttachPtr ** idx
Array of attachments.
Definition: attach.h:54
void(* make_entry)(char *buf, size_t buflen, struct Menu *menu, int line)
Format a item for a menu.
Definition: mutt_menu.h:119
void mutt_edit_file(const char *editor, const char *file)
Let the user edit a file.
Definition: curs_lib.c:353
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:46
Keep track when the compose screen needs redrawing.
Definition: compose.c:109
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:641
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:51
#define mutt_buffer_enter_fname(prompt, fname, mailbox)
Definition: curs_lib.h:87
QuadOption
Possible values for a quad-option.
Definition: quad.h:36
UUEncoded text.
Definition: mime.h:54
#define REDRAW_CURRENT
Redraw the current line of the menu.
Definition: mutt_menu.h:45
int mutt_compose_attachment(struct Body *a)
Create an attachment.
Definition: mutt_attach.c:118
int mix_check_message(struct Email *e)
Safety-check the message before passing it to mixmaster.
Definition: remailer.c:854
static int mutt_dlg_compose_observer(struct NotifyCallback *nc)
Listen for config changes affecting the Compose menu - Implements observer_t.
Definition: compose.c:1279
ContentType
Content-Type.
Definition: mime.h:29
"Reply-To:" field
Definition: compose.c:154
+ Here is the caller graph for this function:

Variable Documentation

◆ C_ComposeFormat

char* C_ComposeFormat

Config: printf-like format string for the Compose panel's status bar.

Definition at line 97 of file compose.c.

◆ C_Ispell

char* C_Ispell

Config: External command to perform spell-checking.

Definition at line 98 of file compose.c.

◆ C_Postpone

unsigned char C_Postpone

Config: Save messages to the C_Postponed folder.

Definition at line 99 of file compose.c.