NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
browser.h File Reference

GUI component for displaying/selecting items from a list. More...

#include "config.h"
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
#include <time.h>
#include "mutt/lib.h"
+ Include dependency graph for browser.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  Folder
 A folder/dir in the browser. More...
 
struct  FolderFile
 Browser entry representing a folder/dir. More...
 
struct  BrowserState
 State of the file/mailbox browser. More...
 

Macros

#define MUTT_SEL_NO_FLAGS   0
 No flags are set. More...
 
#define MUTT_SEL_MAILBOX   (1 << 0)
 Select a mailbox. More...
 
#define MUTT_SEL_MULTI   (1 << 1)
 Multi-selection is enabled. More...
 
#define MUTT_SEL_FOLDER   (1 << 2)
 Select a local directory. More...
 

Typedefs

typedef uint8_t SelectFileFlags
 Flags for mutt_select_file(), e.g. MUTT_SEL_MAILBOX. More...
 

Functions

 ARRAY_HEAD (BrowserStateEntry, struct FolderFile)
 
void mutt_select_file (char *file, size_t filelen, SelectFileFlags flags, struct Mailbox *m, char ***files, int *numfiles)
 Let the user select a file. More...
 
void mutt_buffer_select_file (struct Buffer *file, SelectFileFlags flags, struct Mailbox *m, char ***files, int *numfiles)
 Let the user select a file. More...
 
void mutt_browser_select_dir (const char *f)
 Remember the last directory selected. More...
 
void mutt_browser_cleanup (void)
 Clean up working Buffers. More...
 

Detailed Description

GUI component for displaying/selecting items from a list.

Authors
  • Michael R. Elkins

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

Macro Definition Documentation

◆ MUTT_SEL_NO_FLAGS

#define MUTT_SEL_NO_FLAGS   0

No flags are set.

Definition at line 36 of file browser.h.

◆ MUTT_SEL_MAILBOX

#define MUTT_SEL_MAILBOX   (1 << 0)

Select a mailbox.

Definition at line 37 of file browser.h.

◆ MUTT_SEL_MULTI

#define MUTT_SEL_MULTI   (1 << 1)

Multi-selection is enabled.

Definition at line 38 of file browser.h.

◆ MUTT_SEL_FOLDER

#define MUTT_SEL_FOLDER   (1 << 2)

Select a local directory.

Definition at line 39 of file browser.h.

Typedef Documentation

◆ SelectFileFlags

typedef uint8_t SelectFileFlags

Flags for mutt_select_file(), e.g. MUTT_SEL_MAILBOX.

Definition at line 33 of file browser.h.

Function Documentation

◆ ARRAY_HEAD()

ARRAY_HEAD ( BrowserStateEntry  ,
struct FolderFile   
)

◆ mutt_select_file()

void mutt_select_file ( char *  file,
size_t  filelen,
SelectFileFlags  flags,
struct Mailbox m,
char ***  files,
int *  numfiles 
)

Let the user select a file.

Parameters
[in]fileBuffer for the result
[in]filelenLength of buffer
[in]flagsFlags, see SelectFileFlags
[in]mMailbox
[out]filesArray of selected files
[out]numfilesNumber of selected files

Definition at line 2343 of file browser.c.

2345 {
2346  struct Buffer *f_buf = mutt_buffer_pool_get();
2347 
2348  mutt_buffer_strcpy(f_buf, NONULL(file));
2349  mutt_buffer_select_file(f_buf, flags, m, files, numfiles);
2350  mutt_str_copy(file, mutt_buffer_string(f_buf), filelen);
2351 
2352  mutt_buffer_pool_release(&f_buf);
2353 }
#define NONULL(x)
Definition: string2.h:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:749
void mutt_buffer_select_file(struct Buffer *file, SelectFileFlags flags, struct Mailbox *m, char ***files, int *numfiles)
Let the user select a file.
Definition: browser.c:1254
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_buffer_select_file()

void mutt_buffer_select_file ( struct Buffer file,
SelectFileFlags  flags,
struct Mailbox m,
char ***  files,
int *  numfiles 
)

Let the user select a file.

Parameters
[in]fileBuffer for the result
[in]flagsFlags, see SelectFileFlags
[in]mMailbox
[out]filesArray of selected files
[out]numfilesNumber of selected files

Definition at line 1254 of file browser.c.

1256 {
1257  struct BrowserState state = { { 0 } };
1258  struct Menu *menu = NULL;
1259  struct MuttWindow *dlg = NULL;
1260  bool kill_prefix = false;
1261  bool multiple = (flags & MUTT_SEL_MULTI);
1262  bool folder = (flags & MUTT_SEL_FOLDER);
1263  state.is_mailbox_list = (flags & MUTT_SEL_MAILBOX) && folder;
1264 
1265  /* Keeps in memory the directory we were in when hitting '='
1266  * to go directly to $folder (`$folder`) */
1267  char goto_swapper[PATH_MAX] = { 0 };
1268 
1269  struct Buffer *OldLastDir = mutt_buffer_pool_get();
1270  struct Buffer *tmp = mutt_buffer_pool_get();
1271  struct Buffer *buf = mutt_buffer_pool_get();
1272  struct Buffer *prefix = mutt_buffer_pool_get();
1273 
1274  init_lastdir();
1275 
1276 #ifdef USE_NNTP
1277  if (OptNews)
1278  {
1279  if (mutt_buffer_is_empty(file))
1280  {
1282 
1283  /* default state for news reader mode is browse subscribed newsgroups */
1284  state.is_mailbox_list = false;
1285  for (size_t i = 0; i < adata->groups_num; i++)
1286  {
1287  struct NntpMboxData *mdata = adata->groups_list[i];
1288  if (mdata && mdata->subscribed)
1289  {
1290  state.is_mailbox_list = true;
1291  break;
1292  }
1293  }
1294  }
1295  else
1296  {
1297  mutt_buffer_copy(prefix, file);
1298  }
1299  }
1300  else
1301 #endif
1302  if (!mutt_buffer_is_empty(file))
1303  {
1305 #ifdef USE_IMAP
1306  if (imap_path_probe(mutt_buffer_string(file), NULL) == MUTT_IMAP)
1307  {
1308  init_state(&state, NULL);
1309  state.imap_browse = true;
1310  if (imap_browse(mutt_buffer_string(file), &state) == 0)
1311  {
1313  browser_sort(&state);
1314  }
1315  }
1316  else
1317  {
1318 #endif
1319  int i;
1320  for (i = mutt_buffer_len(file) - 1;
1321  (i > 0) && ((mutt_buffer_string(file))[i] != '/'); i--)
1322  {
1323  ; // do nothing
1324  }
1325 
1326  if (i > 0)
1327  {
1328  if ((mutt_buffer_string(file))[0] == '/')
1330  else
1331  {
1333  mutt_buffer_addch(&LastDir, '/');
1335  }
1336  }
1337  else
1338  {
1339  if ((mutt_buffer_string(file))[0] == '/')
1340  mutt_buffer_strcpy(&LastDir, "/");
1341  else
1343  }
1344 
1345  if ((i <= 0) && (mutt_buffer_string(file)[0] != '/'))
1346  mutt_buffer_copy(prefix, file);
1347  else
1348  mutt_buffer_strcpy(prefix, mutt_buffer_string(file) + i + 1);
1349  kill_prefix = true;
1350 #ifdef USE_IMAP
1351  }
1352 #endif
1353  }
1354  else
1355  {
1356  if (!folder)
1358  else
1359  {
1360  /* Whether we use the tracking feature of the browser depends
1361  * on which sort method we chose to use. This variable is defined
1362  * only to help readability of the code. */
1363  bool browser_track = false;
1364 
1365  const short c_sort_browser = cs_subset_sort(NeoMutt->sub, "sort_browser");
1366  switch (c_sort_browser & SORT_MASK)
1367  {
1368  case SORT_DESC:
1369  case SORT_SUBJECT:
1370  case SORT_ORDER:
1371  browser_track = true;
1372  break;
1373  }
1374 
1375  /* We use mutt_browser_select_dir to initialize the two
1376  * variables (LastDir, LastDirBackup) at the appropriate
1377  * values.
1378  *
1379  * We do it only when LastDir is not set (first pass there)
1380  * or when CurrentFolder and LastDirBackup are not the same.
1381  * This code is executed only when we list files, not when
1382  * we press up/down keys to navigate in a displayed list.
1383  *
1384  * We only do this when CurrentFolder has been set (ie, not
1385  * when listing folders on startup with "neomutt -y").
1386  *
1387  * This tracker is only used when browser_track is true,
1388  * meaning only with sort methods SUBJECT/DESC for now. */
1389  if (CurrentFolder)
1390  {
1392  {
1393  /* If browsing in "local"-mode, than we chose to define LastDir to
1394  * MailDir */
1395  switch (mx_path_probe(CurrentFolder))
1396  {
1397  case MUTT_IMAP:
1398  case MUTT_MAILDIR:
1399  case MUTT_MBOX:
1400  case MUTT_MH:
1401  case MUTT_MMDF:
1402  {
1403  const char *const c_folder =
1404  cs_subset_string(NeoMutt->sub, "folder");
1405  const char *const c_spool_file = cs_subset_string(NeoMutt->sub, "spool_file");
1406  if (c_folder)
1407  mutt_buffer_strcpy(&LastDir, c_folder);
1408  else if (c_spool_file)
1409  mutt_browser_select_dir(c_spool_file);
1410  break;
1411  }
1412  default:
1414  break;
1415  }
1416  }
1418  {
1420  }
1421  }
1422 
1423  /* When browser tracking feature is disabled, clear LastDirBackup */
1424  if (!browser_track)
1426  }
1427 
1428 #ifdef USE_IMAP
1429  if (!state.is_mailbox_list &&
1431  {
1432  init_state(&state, NULL);
1433  state.imap_browse = true;
1435  browser_sort(&state);
1436  }
1437  else
1438 #endif
1439  {
1440  size_t i = mutt_buffer_len(&LastDir);
1441  while ((i > 0) && (mutt_buffer_string(&LastDir)[--i] == '/'))
1442  LastDir.data[i] = '\0';
1446  }
1447  }
1448 
1449  mutt_buffer_reset(file);
1450 
1451  const struct Mapping *help_data = NULL;
1452 #ifdef USE_NNTP
1453  if (OptNews)
1454  help_data = FolderNewsHelp;
1455  else
1456 #endif
1457  help_data = FolderHelp;
1458 
1459  dlg = simple_dialog_new(MENU_FOLDER, WT_DLG_BROWSER, help_data);
1460 
1461  menu = dlg->wdata;
1462  menu->make_entry = folder_make_entry;
1463  menu->search = select_file_search;
1464  if (multiple)
1465  menu->tag = file_tag;
1466 
1467  struct MuttWindow *sbar = window_find_child(dlg, WT_STATUS_BAR);
1468 
1469  struct MuttWindow *win_menu = menu->win;
1470 
1471  // NT_COLOR is handled by the SimpleDialog
1474 
1475  if (state.is_mailbox_list)
1476  {
1477  examine_mailboxes(m, NULL, &state);
1478  }
1479  else
1480 #ifdef USE_IMAP
1481  if (!state.imap_browse)
1482 #endif
1483  {
1484  // examine_directory() calls add_folder() which needs the menu
1485  if (examine_directory(m, menu, &state, mutt_buffer_string(&LastDir),
1486  mutt_buffer_string(prefix)) == -1)
1487  {
1488  goto bail;
1489  }
1490  }
1491 
1492  init_menu(&state, menu, m, sbar);
1493  // only now do we have a valid state to attach
1494  menu->mdata = &state.entry;
1495 
1496  int last_selected_mailbox = -1;
1497 
1498  while (true)
1499  {
1500  if (state.is_mailbox_list && (last_selected_mailbox >= 0) &&
1501  (last_selected_mailbox < menu->max))
1502  {
1503  menu_set_index(menu, last_selected_mailbox);
1504  }
1505  int op = menu_loop(menu);
1506  if (op >= 0)
1507  mutt_debug(LL_DEBUG1, "Got op %s (%d)\n", OpStrings[op][0], op);
1508  int index = menu_get_index(menu);
1509  struct FolderFile *ff = ARRAY_GET(&state.entry, index);
1510  switch (op)
1511  {
1512  case OP_DESCEND_DIRECTORY:
1513  case OP_GENERIC_SELECT_ENTRY:
1514  {
1515  if (ARRAY_EMPTY(&state.entry))
1516  {
1517  mutt_error(_("No files match the file mask"));
1518  break;
1519  }
1520 
1521  if (S_ISDIR(ff->mode) ||
1522  (S_ISLNK(ff->mode) && link_is_dir(mutt_buffer_string(&LastDir), ff->name))
1523 #ifdef USE_IMAP
1524  || ff->inferiors
1525 #endif
1526  )
1527  {
1528  /* make sure this isn't a MH or maildir mailbox */
1529  if (state.is_mailbox_list)
1530  {
1531  mutt_buffer_strcpy(buf, ff->name);
1533  }
1534 #ifdef USE_IMAP
1535  else if (state.imap_browse)
1536  {
1537  mutt_buffer_strcpy(buf, ff->name);
1538  }
1539 #endif
1540  else
1541  {
1543  }
1544 
1545  enum MailboxType type = mx_path_probe(mutt_buffer_string(buf));
1546  if ((op == OP_DESCEND_DIRECTORY) || (type == MUTT_MAILBOX_ERROR) ||
1547  (type == MUTT_UNKNOWN)
1548 #ifdef USE_IMAP
1549  || ff->inferiors
1550 #endif
1551  )
1552  {
1553  /* save the old directory */
1554  mutt_buffer_copy(OldLastDir, &LastDir);
1555 
1556  if (mutt_str_equal(ff->name, ".."))
1557  {
1558  size_t lastdirlen = mutt_buffer_len(&LastDir);
1559  if ((lastdirlen > 1) &&
1560  mutt_str_equal("..", mutt_buffer_string(&LastDir) + lastdirlen - 2))
1561  {
1562  mutt_buffer_addstr(&LastDir, "/..");
1563  }
1564  else
1565  {
1566  char *p = NULL;
1567  if (lastdirlen > 1)
1568  p = strrchr(mutt_buffer_string(&LastDir) + 1, '/');
1569 
1570  if (p)
1571  {
1572  *p = '\0';
1574  }
1575  else
1576  {
1577  if (mutt_buffer_string(&LastDir)[0] == '/')
1578  mutt_buffer_strcpy(&LastDir, "/");
1579  else
1580  mutt_buffer_addstr(&LastDir, "/..");
1581  }
1582  }
1583  }
1584  else if (state.is_mailbox_list)
1585  {
1588  }
1589 #ifdef USE_IMAP
1590  else if (state.imap_browse)
1591  {
1593  /* tack on delimiter here */
1594 
1595  /* special case "" needs no delimiter */
1596  struct Url *url = url_parse(ff->name);
1597  if (url && url->path && (ff->delim != '\0'))
1598  {
1600  }
1601  url_free(&url);
1602  }
1603 #endif
1604  else
1605  {
1607  mutt_buffer_copy(&LastDir, tmp);
1608  }
1609 
1610  destroy_state(&state);
1611  if (kill_prefix)
1612  {
1613  mutt_buffer_reset(prefix);
1614  kill_prefix = false;
1615  }
1616  state.is_mailbox_list = false;
1617 #ifdef USE_IMAP
1618  if (state.imap_browse)
1619  {
1620  init_state(&state, NULL);
1621  state.imap_browse = true;
1623  browser_sort(&state);
1624  menu->mdata = &state.entry;
1625  }
1626  else
1627 #endif
1628  {
1629  if (examine_directory(m, menu, &state, mutt_buffer_string(&LastDir),
1630  mutt_buffer_string(prefix)) == -1)
1631  {
1632  /* try to restore the old values */
1633  mutt_buffer_copy(&LastDir, OldLastDir);
1634  if (examine_directory(m, menu, &state, mutt_buffer_string(&LastDir),
1635  mutt_buffer_string(prefix)) == -1)
1636  {
1638  goto bail;
1639  }
1640  }
1641  /* resolve paths navigated from GUI */
1642  if (mutt_path_realpath(LastDir.data) == 0)
1643  break;
1644  }
1645 
1646  browser_highlight_default(&state, menu);
1647  init_menu(&state, menu, m, sbar);
1648  goto_swapper[0] = '\0';
1649  break;
1650  }
1651  }
1652  else if (op == OP_DESCEND_DIRECTORY)
1653  {
1654  mutt_error(_("%s is not a directory"), ARRAY_GET(&state.entry, index)->name);
1655  break;
1656  }
1657 
1658  if (state.is_mailbox_list || OptNews) /* USE_NNTP */
1659  {
1660  mutt_buffer_strcpy(file, ff->name);
1662  }
1663 #ifdef USE_IMAP
1664  else if (state.imap_browse)
1665  mutt_buffer_strcpy(file, ff->name);
1666 #endif
1667  else
1668  {
1670  }
1671  }
1672  /* fallthrough */
1673 
1674  case OP_EXIT:
1675 
1676  if (multiple)
1677  {
1678  char **tfiles = NULL;
1679 
1680  if (menu->tagged)
1681  {
1682  *numfiles = menu->tagged;
1683  tfiles = mutt_mem_calloc(*numfiles, sizeof(char *));
1684  size_t j = 0;
1685  ARRAY_FOREACH(ff, &state.entry)
1686  {
1687  if (ff->tagged)
1688  {
1691  tfiles[j++] = mutt_buffer_strdup(tmp);
1692  }
1693  }
1694  *files = tfiles;
1695  }
1696  else if (!mutt_buffer_is_empty(file)) /* no tagged entries. return selected entry */
1697  {
1698  *numfiles = 1;
1699  tfiles = mutt_mem_calloc(*numfiles, sizeof(char *));
1701  tfiles[0] = mutt_buffer_strdup(file);
1702  *files = tfiles;
1703  }
1704  }
1705 
1706  destroy_state(&state);
1707  goto bail;
1708 
1709  case OP_BROWSER_TELL:
1710  if (!ARRAY_EMPTY(&state.entry))
1711  mutt_message("%s", ARRAY_GET(&state.entry, index)->name);
1712  break;
1713 
1714 #ifdef USE_IMAP
1715  case OP_BROWSER_TOGGLE_LSUB:
1716  bool_str_toggle(NeoMutt->sub, "imap_list_subscribed", NULL);
1717 
1718  mutt_unget_event(0, OP_CHECK_NEW);
1719  break;
1720 
1721  case OP_CREATE_MAILBOX:
1722  if (!state.imap_browse)
1723  {
1724  mutt_error(_("Create is only supported for IMAP mailboxes"));
1725  break;
1726  }
1727 
1729  {
1730  /* TODO: find a way to detect if the new folder would appear in
1731  * this window, and insert it without starting over. */
1732  destroy_state(&state);
1733  init_state(&state, NULL);
1734  state.imap_browse = true;
1736  browser_sort(&state);
1737  menu->mdata = &state.entry;
1738  browser_highlight_default(&state, menu);
1739  init_menu(&state, menu, m, sbar);
1740  }
1741  /* else leave error on screen */
1742  break;
1743 
1744  case OP_RENAME_MAILBOX:
1745  if (!ff->imap)
1746  mutt_error(_("Rename is only supported for IMAP mailboxes"));
1747  else
1748  {
1749  if (imap_mailbox_rename(ff->name) >= 0)
1750  {
1751  destroy_state(&state);
1752  init_state(&state, NULL);
1753  state.imap_browse = true;
1755  browser_sort(&state);
1756  menu->mdata = &state.entry;
1757  browser_highlight_default(&state, menu);
1758  init_menu(&state, menu, m, sbar);
1759  }
1760  }
1761  break;
1762 
1763  case OP_DELETE_MAILBOX:
1764  if (!ff->imap)
1765  mutt_error(_("Delete is only supported for IMAP mailboxes"));
1766  else
1767  {
1768  char msg[128];
1769 
1770  // TODO(sileht): It could be better to select INBOX instead. But I
1771  // don't want to manipulate Context/Mailboxes/mailbox->account here for now.
1772  // Let's just protect neomutt against crash for now. #1417
1773  if (mutt_str_equal(mailbox_path(m), ff->name))
1774  {
1775  mutt_error(_("Can't delete currently selected mailbox"));
1776  break;
1777  }
1778 
1779  snprintf(msg, sizeof(msg), _("Really delete mailbox \"%s\"?"), ff->name);
1780  if (mutt_yesorno(msg, MUTT_NO) == MUTT_YES)
1781  {
1782  if (imap_delete_mailbox(m, ff->name) == 0)
1783  {
1784  /* free the mailbox from the browser */
1785  FREE(&ff->name);
1786  FREE(&ff->desc);
1787  /* and move all other entries up */
1788  ARRAY_REMOVE(&state.entry, ff);
1789  mutt_message(_("Mailbox deleted"));
1790  init_menu(&state, menu, m, sbar);
1791  }
1792  else
1793  mutt_error(_("Mailbox deletion failed"));
1794  }
1795  else
1796  mutt_message(_("Mailbox not deleted"));
1797  }
1798  break;
1799 #endif
1800 
1801  case OP_GOTO_PARENT:
1802  case OP_CHANGE_DIRECTORY:
1803 
1804 #ifdef USE_NNTP
1805  if (OptNews)
1806  break;
1807 #endif
1808 
1809  mutt_buffer_copy(buf, &LastDir);
1810 #ifdef USE_IMAP
1811  if (!state.imap_browse)
1812 #endif
1813  {
1814  /* add '/' at the end of the directory name if not already there */
1815  size_t len = mutt_buffer_len(buf);
1816  if ((len > 0) && (mutt_buffer_string(&LastDir)[len - 1] != '/'))
1817  mutt_buffer_addch(buf, '/');
1818  }
1819 
1820  if (op == OP_CHANGE_DIRECTORY)
1821  {
1822  /* buf comes from the buffer pool, so defaults to size 1024 */
1823  int ret = mutt_buffer_get_field(_("Chdir to: "), buf, MUTT_FILE,
1824  false, NULL, NULL, NULL);
1825  if ((ret != 0) && mutt_buffer_is_empty(buf))
1826  break;
1827  }
1828  else if (op == OP_GOTO_PARENT)
1830 
1831  if (!mutt_buffer_is_empty(buf))
1832  {
1833  state.is_mailbox_list = false;
1835 #ifdef USE_IMAP
1836  if (imap_path_probe(mutt_buffer_string(buf), NULL) == MUTT_IMAP)
1837  {
1838  mutt_buffer_copy(&LastDir, buf);
1839  destroy_state(&state);
1840  init_state(&state, NULL);
1841  state.imap_browse = true;
1843  browser_sort(&state);
1844  menu->mdata = &state.entry;
1845  browser_highlight_default(&state, menu);
1846  init_menu(&state, menu, m, sbar);
1847  }
1848  else
1849 #endif
1850  {
1851  if (mutt_buffer_string(buf)[0] != '/')
1852  {
1853  /* in case dir is relative, make it relative to LastDir,
1854  * not current working dir */
1856  mutt_buffer_string(buf));
1857  mutt_buffer_copy(buf, tmp);
1858  }
1859  /* Resolve path from <chdir>
1860  * Avoids buildup such as /a/b/../../c
1861  * Symlinks are always unraveled to keep code simple */
1862  if (mutt_path_realpath(buf->data) == 0)
1863  break;
1864 
1865  struct stat st;
1866  if (stat(mutt_buffer_string(buf), &st) == 0)
1867  {
1868  if (S_ISDIR(st.st_mode))
1869  {
1870  destroy_state(&state);
1871  if (examine_directory(m, menu, &state, mutt_buffer_string(buf),
1872  mutt_buffer_string(prefix)) == 0)
1873  {
1874  mutt_buffer_copy(&LastDir, buf);
1875  }
1876  else
1877  {
1878  mutt_error(_("Error scanning directory"));
1879  if (examine_directory(m, menu, &state, mutt_buffer_string(&LastDir),
1880  mutt_buffer_string(prefix)) == -1)
1881  {
1882  goto bail;
1883  }
1884  }
1885  browser_highlight_default(&state, menu);
1886  init_menu(&state, menu, m, sbar);
1887  }
1888  else
1889  mutt_error(_("%s is not a directory"), mutt_buffer_string(buf));
1890  }
1891  else
1893  }
1894  }
1895  break;
1896 
1897  case OP_ENTER_MASK:
1898  {
1899  const struct Regex *c_mask = cs_subset_regex(NeoMutt->sub, "mask");
1900  mutt_buffer_strcpy(buf, c_mask ? c_mask->pattern : NULL);
1901  if (mutt_get_field(_("File Mask: "), buf->data, buf->dsize,
1902  MUTT_COMP_NO_FLAGS, false, NULL, NULL) != 0)
1903  {
1904  break;
1905  }
1906 
1907  mutt_buffer_fix_dptr(buf);
1908 
1909  state.is_mailbox_list = false;
1910  /* assume that the user wants to see everything */
1911  if (mutt_buffer_is_empty(buf))
1912  mutt_buffer_strcpy(buf, ".");
1913 
1914  struct Buffer errmsg = mutt_buffer_make(256);
1915  int rc = cs_subset_str_string_set(NeoMutt->sub, "mask",
1916  mutt_buffer_string(buf), &errmsg);
1917  if (CSR_RESULT(rc) != CSR_SUCCESS)
1918  {
1919  if (!mutt_buffer_is_empty(&errmsg))
1920  {
1921  mutt_error("%s", mutt_buffer_string(&errmsg));
1922  mutt_buffer_dealloc(&errmsg);
1923  }
1924  break;
1925  }
1926  mutt_buffer_dealloc(&errmsg);
1927 
1928  destroy_state(&state);
1929 #ifdef USE_IMAP
1930  if (state.imap_browse)
1931  {
1932  init_state(&state, NULL);
1933  state.imap_browse = true;
1935  browser_sort(&state);
1936  menu->mdata = &state.entry;
1937  init_menu(&state, menu, m, sbar);
1938  }
1939  else
1940 #endif
1941  if (examine_directory(m, menu, &state, mutt_buffer_string(&LastDir), NULL) == 0)
1942  {
1943  init_menu(&state, menu, m, sbar);
1944  }
1945  else
1946  {
1947  mutt_error(_("Error scanning directory"));
1948  goto bail;
1949  }
1950  kill_prefix = false;
1951  if (ARRAY_EMPTY(&state.entry))
1952  {
1953  mutt_error(_("No files match the file mask"));
1954  break;
1955  }
1956  break;
1957  }
1958 
1959  case OP_SORT:
1960  case OP_SORT_REVERSE:
1961 
1962  {
1963  bool resort = true;
1964  int sort = -1;
1965  int reverse = (op == OP_SORT_REVERSE);
1966 
1967  switch (mutt_multi_choice(
1968  (reverse) ?
1969  /* L10N: The highlighted letters must match the "Sort" options */
1970  _("Reverse sort by (d)ate, (a)lpha, si(z)e, d(e)scription, "
1971  "(c)ount, ne(w) count, or do(n)'t sort?") :
1972  /* L10N: The highlighted letters must match the "Reverse Sort" options */
1973  _("Sort by (d)ate, (a)lpha, si(z)e, d(e)scription, (c)ount, "
1974  "ne(w) count, or do(n)'t sort?"),
1975  /* L10N: These must match the highlighted letters from "Sort" and "Reverse Sort" */
1976  _("dazecwn")))
1977  {
1978  case -1: /* abort */
1979  resort = false;
1980  break;
1981 
1982  case 1: /* (d)ate */
1983  sort = SORT_DATE;
1984  break;
1985 
1986  case 2: /* (a)lpha */
1987  sort = SORT_SUBJECT;
1988  break;
1989 
1990  case 3: /* si(z)e */
1991  sort = SORT_SIZE;
1992  break;
1993 
1994  case 4: /* d(e)scription */
1995  sort = SORT_DESC;
1996  break;
1997 
1998  case 5: /* (c)ount */
1999  sort = SORT_COUNT;
2000  break;
2001 
2002  case 6: /* ne(w) count */
2003  sort = SORT_UNREAD;
2004  break;
2005 
2006  case 7: /* do(n)'t sort */
2007  sort = SORT_ORDER;
2008  break;
2009  }
2010  if (resort)
2011  {
2012  sort |= reverse ? SORT_REVERSE : 0;
2013  cs_subset_str_native_set(NeoMutt->sub, "sort_browser", sort, NULL);
2014  browser_sort(&state);
2015  browser_highlight_default(&state, menu);
2017  }
2018  else
2019  {
2020  cs_subset_str_native_set(NeoMutt->sub, "sort_browser", sort, NULL);
2021  }
2022  break;
2023  }
2024 
2025  case OP_TOGGLE_MAILBOXES:
2026  case OP_BROWSER_GOTO_FOLDER:
2027  case OP_CHECK_NEW:
2028  if (state.is_mailbox_list)
2029  {
2030  last_selected_mailbox = menu->current;
2031  }
2032 
2033  if (op == OP_TOGGLE_MAILBOXES)
2034  {
2035  state.is_mailbox_list = !state.is_mailbox_list;
2036  }
2037 
2038  if (op == OP_BROWSER_GOTO_FOLDER)
2039  {
2040  /* When in mailboxes mode, disables this feature */
2041  const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
2042  if (c_folder)
2043  {
2044  mutt_debug(LL_DEBUG3, "= hit! Folder: %s, LastDir: %s\n", c_folder,
2046  if (goto_swapper[0] == '\0')
2047  {
2048  if (!mutt_str_equal(mutt_buffer_string(&LastDir), c_folder))
2049  {
2050  /* Stores into goto_swapper LastDir, and swaps to `$folder` */
2051  mutt_str_copy(goto_swapper, mutt_buffer_string(&LastDir),
2052  sizeof(goto_swapper));
2054  mutt_buffer_strcpy(&LastDir, c_folder);
2055  }
2056  }
2057  else
2058  {
2060  mutt_buffer_strcpy(&LastDir, goto_swapper);
2061  goto_swapper[0] = '\0';
2062  }
2063  }
2064  }
2065  destroy_state(&state);
2066  mutt_buffer_reset(prefix);
2067  kill_prefix = false;
2068 
2069  if (state.is_mailbox_list)
2070  {
2071  examine_mailboxes(m, menu, &state);
2072  }
2073 #ifdef USE_IMAP
2074  else if (imap_path_probe(mutt_buffer_string(&LastDir), NULL) == MUTT_IMAP)
2075  {
2076  init_state(&state, NULL);
2077  state.imap_browse = true;
2079  browser_sort(&state);
2080  menu->mdata = &state.entry;
2081  }
2082 #endif
2083  else if (examine_directory(m, menu, &state, mutt_buffer_string(&LastDir),
2084  mutt_buffer_string(prefix)) == -1)
2085  {
2086  goto bail;
2087  }
2088  init_menu(&state, menu, m, sbar);
2089  break;
2090 
2091  case OP_MAILBOX_LIST:
2093  break;
2094 
2095  case OP_BROWSER_NEW_FILE:
2097  /* buf comes from the buffer pool, so defaults to size 1024 */
2098  if (mutt_buffer_get_field(_("New file name: "), buf, MUTT_FILE, false,
2099  NULL, NULL, NULL) == 0)
2100  {
2101  mutt_buffer_copy(file, buf);
2102  destroy_state(&state);
2103  goto bail;
2104  }
2105  break;
2106 
2107  case OP_BROWSER_VIEW_FILE:
2108  if (ARRAY_EMPTY(&state.entry))
2109  {
2110  mutt_error(_("No files match the file mask"));
2111  break;
2112  }
2113 
2114 #ifdef USE_IMAP
2115  if (ff->selectable)
2116  {
2117  mutt_buffer_strcpy(file, ff->name);
2118  destroy_state(&state);
2119  goto bail;
2120  }
2121  else
2122 #endif
2123  if (S_ISDIR(ff->mode) ||
2124  (S_ISLNK(ff->mode) && link_is_dir(mutt_buffer_string(&LastDir), ff->name)))
2125  {
2126  mutt_error(_("Can't view a directory"));
2127  break;
2128  }
2129  else
2130  {
2131  char buf2[PATH_MAX];
2132 
2133  mutt_path_concat(buf2, mutt_buffer_string(&LastDir), ff->name, sizeof(buf2));
2134  struct Body *b = mutt_make_file_attach(buf2, NeoMutt->sub);
2135  if (b)
2136  {
2137  mutt_view_attachment(NULL, b, MUTT_VA_REGULAR, NULL, NULL, menu->win);
2138  mutt_body_free(&b);
2140  }
2141  else
2142  mutt_error(_("Error trying to view file"));
2143  }
2144  break;
2145 
2146 #ifdef USE_NNTP
2147  case OP_CATCHUP:
2148  case OP_UNCATCHUP:
2149  {
2150  if (!OptNews)
2151  break;
2152 
2153  struct NntpMboxData *mdata = NULL;
2154 
2156  if (rc < 0)
2157  break;
2158 
2159  if (op == OP_CATCHUP)
2160  mdata = mutt_newsgroup_catchup(m, CurrentNewsSrv, ff->name);
2161  else
2162  mdata = mutt_newsgroup_uncatchup(m, CurrentNewsSrv, ff->name);
2163 
2164  if (mdata)
2165  {
2167  index = menu_get_index(menu) + 1;
2168  if (index < menu->max)
2169  menu_set_index(menu, index);
2170  }
2171  if (rc)
2174  break;
2175  }
2176 
2177  case OP_LOAD_ACTIVE:
2178  {
2179  if (!OptNews)
2180  break;
2181 
2182  struct NntpAccountData *adata = CurrentNewsSrv;
2183 
2184  if (nntp_newsrc_parse(adata) < 0)
2185  break;
2186 
2187  for (size_t i = 0; i < adata->groups_num; i++)
2188  {
2189  struct NntpMboxData *mdata = adata->groups_list[i];
2190  if (mdata)
2191  mdata->deleted = true;
2192  }
2193  nntp_active_fetch(adata, true);
2194  nntp_newsrc_update(adata);
2195  nntp_newsrc_close(adata);
2196 
2197  destroy_state(&state);
2198  if (state.is_mailbox_list)
2199  {
2200  examine_mailboxes(m, menu, &state);
2201  }
2202  else
2203  {
2204  if (examine_directory(m, menu, &state, NULL, NULL) == -1)
2205  break;
2206  }
2207  init_menu(&state, menu, m, sbar);
2208  break;
2209  }
2210 #endif /* USE_NNTP */
2211 
2212 #if defined(USE_IMAP) || defined(USE_NNTP)
2213  case OP_BROWSER_SUBSCRIBE:
2214  case OP_BROWSER_UNSUBSCRIBE:
2215 #endif
2216 #ifdef USE_NNTP
2217  case OP_SUBSCRIBE_PATTERN:
2218  case OP_UNSUBSCRIBE_PATTERN:
2219  {
2220  if (OptNews)
2221  {
2222  struct NntpAccountData *adata = CurrentNewsSrv;
2223  regex_t rx;
2224  memset(&rx, 0, sizeof(rx));
2225  char *s = buf->data;
2226  index = menu_get_index(menu);
2227 
2228  if ((op == OP_SUBSCRIBE_PATTERN) || (op == OP_UNSUBSCRIBE_PATTERN))
2229  {
2230  char tmp2[256];
2231 
2232  mutt_buffer_reset(buf);
2233  if (op == OP_SUBSCRIBE_PATTERN)
2234  snprintf(tmp2, sizeof(tmp2), _("Subscribe pattern: "));
2235  else
2236  snprintf(tmp2, sizeof(tmp2), _("Unsubscribe pattern: "));
2237  /* buf comes from the buffer pool, so defaults to size 1024 */
2238  if ((mutt_buffer_get_field(tmp2, buf, MUTT_PATTERN, false, NULL, NULL, NULL) != 0) ||
2239  mutt_buffer_is_empty(buf))
2240  {
2241  break;
2242  }
2243 
2244  int err = REG_COMP(&rx, s, REG_NOSUB);
2245  if (err != 0)
2246  {
2247  regerror(err, &rx, buf->data, buf->dsize);
2248  regfree(&rx);
2249  mutt_error("%s", mutt_buffer_string(buf));
2250  break;
2251  }
2253  index = 0;
2254  }
2255  else if (ARRAY_EMPTY(&state.entry))
2256  {
2257  mutt_error(_("No newsgroups match the mask"));
2258  break;
2259  }
2260 
2261  int rc = nntp_newsrc_parse(adata);
2262  if (rc < 0)
2263  break;
2264 
2265  ARRAY_FOREACH_FROM(ff, &state.entry, index)
2266  {
2267  if ((op == OP_BROWSER_SUBSCRIBE) || (op == OP_BROWSER_UNSUBSCRIBE) ||
2268  (regexec(&rx, ff->name, 0, NULL, 0) == 0))
2269  {
2270  if ((op == OP_BROWSER_SUBSCRIBE) || (op == OP_SUBSCRIBE_PATTERN))
2271  mutt_newsgroup_subscribe(adata, ff->name);
2272  else
2273  mutt_newsgroup_unsubscribe(adata, ff->name);
2274  }
2275  if ((op == OP_BROWSER_SUBSCRIBE) || (op == OP_BROWSER_UNSUBSCRIBE))
2276  {
2277  if ((index + 1) < menu->max)
2278  menu_set_index(menu, index + 1);
2279  break;
2280  }
2281  }
2282 
2283  if (op == OP_SUBSCRIBE_PATTERN)
2284  {
2285  for (size_t j = 0; adata && (j < adata->groups_num); j++)
2286  {
2287  struct NntpMboxData *mdata = adata->groups_list[j];
2288  if (mdata && mdata->group && !mdata->subscribed)
2289  {
2290  if (regexec(&rx, mdata->group, 0, NULL, 0) == 0)
2291  {
2292  mutt_newsgroup_subscribe(adata, mdata->group);
2293  add_folder(menu, &state, mdata->group, NULL, NULL, NULL, mdata);
2294  }
2295  }
2296  }
2297  init_menu(&state, menu, m, sbar);
2298  }
2299  if (rc > 0)
2301  nntp_newsrc_update(adata);
2302  nntp_clear_cache(adata);
2303  nntp_newsrc_close(adata);
2304  if ((op != OP_BROWSER_SUBSCRIBE) && (op != OP_BROWSER_UNSUBSCRIBE))
2305  regfree(&rx);
2306  }
2307 #ifdef USE_IMAP
2308  else
2309 #endif /* USE_IMAP && USE_NNTP */
2310 #endif /* USE_NNTP */
2311 #ifdef USE_IMAP
2312  {
2313  char tmp2[256];
2314  mutt_str_copy(tmp2, ff->name, sizeof(tmp2));
2315  mutt_expand_path(tmp2, sizeof(tmp2));
2316  imap_subscribe(tmp2, (op == OP_BROWSER_SUBSCRIBE));
2317  }
2318 #endif /* USE_IMAP */
2319  }
2320  }
2321  }
2322 
2323 bail:
2324  mutt_buffer_pool_release(&OldLastDir);
2327  mutt_buffer_pool_release(&prefix);
2328 
2329  simple_dialog_free(&dlg);
2330 
2331  goto_swapper[0] = '\0';
2332 }
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:904
mode_t mode
Definition: browser.h:55
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:215
struct MuttWindow * window_find_child(struct MuttWindow *win, enum WindowType type)
Recursively find a child Window of a given type.
Definition: mutt_window.c:550
bool mutt_mailbox_list(void)
List the mailboxes with new mail.
Definition: mutt_mailbox.c:222
#define NONULL(x)
Definition: string2.h:37
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
static bool link_is_dir(const char *folder, const char *path)
Does this symlink point to a directory?
Definition: browser.c:369
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
void simple_dialog_free(struct MuttWindow **ptr)
Destroy a simple index Dialog.
Definition: simple.c:165
Definition: lib.h:67
static int examine_directory(struct Mailbox *m, struct Menu *menu, struct BrowserState *state, const char *d, const char *prefix)
Get list of all files/newsgroups with mask.
Definition: browser.c:734
static void destroy_state(struct BrowserState *state)
Free the BrowserState.
Definition: browser.c:172
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
#define mutt_error(...)
Definition: logging.h:88
char * desc
Definition: browser.h:63
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
int mutt_buffer_get_field(const char *field, struct Buffer *buf, CompletionFlags complete, bool multiple, struct Mailbox *m, char ***files, int *numfiles)
Ask the user for a string.
Definition: curs_lib.c:268
int imap_delete_mailbox(struct Mailbox *m, char *path)
Delete a mailbox.
Definition: imap.c:516
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition: url.h:68
void nntp_clear_cache(struct NntpAccountData *adata)
Clear the NNTP cache.
Definition: newsrc.c:846
int mutt_get_field(const char *field, char *buf, size_t buflen, CompletionFlags complete, bool multiple, char ***files, int *numfiles)
Ask the user for a string.
Definition: curs_lib.c:335
struct NntpMboxData * mutt_newsgroup_uncatchup(struct Mailbox *m, struct NntpAccountData *adata, char *group)
Uncatchup newsgroup.
Definition: newsrc.c:1347
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:206
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
State of the file/mailbox browser.
Definition: browser.h:91
#define ARRAY_GET(head, idx)
Return the element at index.
Definition: array.h:105
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
static void add_folder(struct Menu *menu, struct BrowserState *state, const char *name, const char *desc, const struct stat *s, struct Mailbox *m, void *data)
Add a folder to the browser list.
Definition: browser.c:662
String manipulation buffer.
Definition: buffer.h:33
struct NntpMboxData * mutt_newsgroup_subscribe(struct NntpAccountData *adata, char *group)
Subscribe newsgroup.
Definition: newsrc.c:1256
void mutt_unget_event(int ch, int op)
Return a keystroke to the input buffer.
Definition: curs_lib.c:583
#define _(a)
Definition: message.h:28
Mailbox wasn&#39;t recognised.
Definition: mailbox.h:47
struct BrowserStateEntry entry
Definition: browser.h:93
Error occurred examining Mailbox.
Definition: mailbox.h:46
#define REG_COMP(preg, regex, cflags)
Compile a regular expression.
Definition: regex3.h:54
int imap_mailbox_create(const char *path)
Create a new IMAP mailbox.
Definition: browse.c:384
static int browser_window_observer(struct NotifyCallback *nc)
Notification that a Window has changed - Implements observer_t.
Definition: browser.c:1202
const char * mutt_path_getcwd(struct Buffer *cwd)
Get the current working directory.
Definition: path.c:563
void nntp_newsrc_close(struct NntpAccountData *adata)
Unlock and close .newsrc file.
Definition: newsrc.c:118
static void init_menu(struct BrowserState *state, struct Menu *menu, struct Mailbox *m, struct MuttWindow *sbar)
Set up a new menu.
Definition: browser.c:1047
static void init_lastdir(void)
Initialise the browser directories.
Definition: browser.c:146
void url_free(struct Url **ptr)
Free the contents of a URL.
Definition: url.c:123
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
View using default method.
Definition: mutt_attach.h:43
static int examine_mailboxes(struct Mailbox *m, struct Menu *menu, struct BrowserState *state)
Get list of mailboxes/subscribed newsgroups.
Definition: browser.c:862
#define mutt_perror(...)
Definition: logging.h:89
Container for Accounts, Notifications.
Definition: neomutt.h:36
#define MUTT_PATTERN
Pattern mode - only used for history classes.
Definition: mutt.h:60
NNTP-specific Account data -.
Definition: adata.h:36
MuttWindow has changed, NotifyWindow, EventWindow.
Definition: notify_type.h:53
bool subscribed
Definition: mdata.h:41
The body of an email.
Definition: body.h:34
Status Bar containing extra info about the Index/Pager/etc.
Definition: mutt_window.h:102
void(* make_entry)(struct Menu *menu, char *buf, size_t buflen, int line)
Definition: lib.h:105
#define MUTT_SEL_FOLDER
Select a local directory.
Definition: browser.h:39
#define CSR_RESULT(x)
Definition: set.h:52
char * HomeDir
User&#39;s home directory.
Definition: mutt_globals.h:45
char * folder
Definition: browser.h:96
bool selectable
Definition: browser.h:73
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
const struct Regex * cs_subset_regex(const struct ConfigSubset *sub, const char *name)
Get a regex config item by name.
Definition: helpers.c:243
int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
Definition: subset.c:305
Sort by the size of the email.
Definition: sort2.h:44
size_t dsize
Length of data.
Definition: buffer.h:37
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:122
int nntp_active_fetch(struct NntpAccountData *adata, bool mark_new)
Fetch list of all newsgroups from server.
Definition: nntp.c:1963
int cs_subset_str_string_set(const struct ConfigSubset *sub, const char *name, const char *value, struct Buffer *err)
Set a config item by string.
Definition: subset.c:408
struct Notify * notify
Notifications: NotifyWindow, EventWindow.
Definition: mutt_window.h:138
static struct Buffer LastDirBackup
Definition: browser.c:139
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:52
struct MuttWindow * win
Window holding the Menu.
Definition: lib.h:76
Sort by the order the messages appear in the mailbox.
Definition: sort2.h:48
struct Body * mutt_make_file_attach(const char *path, struct ConfigSubset *sub)
Create a file attachment.
Definition: sendlib.c:1088
char * name
Definition: browser.h:62
char * group
Definition: mdata.h:34
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
size_t mutt_path_realpath(char *buf)
resolve path, unraveling symlinks
Definition: path.c:440
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe() -.
Definition: imap.c:2402
bool imap
Definition: browser.h:72
int bool_str_toggle(struct ConfigSubset *sub, const char *name, struct Buffer *err)
Toggle the value of a bool.
Definition: bool.c:214
const char * OpStrings[][2]
Definition: opcodes.c:34
void * mdata
Driver specific data.
Definition: mailbox.h:136
bool notify_observer_add(struct Notify *notify, enum NotifyType type, observer_t callback, void *global_data)
Add an observer to an object.
Definition: notify.c:189
Browser Dialog, mutt_buffer_select_file()
Definition: mutt_window.h:80
&#39;Maildir&#39; Mailbox type
Definition: mailbox.h:51
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
void mutt_buffer_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:181
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition: helpers.c:292
static int browser_config_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t.
Definition: browser.c:1172
Browser entry representing a folder/dir.
Definition: browser.h:53
static const struct Mapping FolderNewsHelp[]
Help Bar for the NNTP Mailbox browser dialog.
Definition: browser.c:124
void * mdata
Private data.
Definition: lib.h:155
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:356
#define PATH_MAX
Definition: mutt.h:40
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition: array.h:70
size_t mutt_buffer_strcpy_n(struct Buffer *buf, const char *s, size_t len)
Copy a string into a Buffer.
Definition: buffer.c:327
size_t mutt_buffer_addstr_n(struct Buffer *buf, const char *s, size_t len)
Add a string to a Buffer, expanding it if necessary.
Definition: buffer.c:99
char * data
Pointer to data.
Definition: buffer.h:35
unsigned int groups_num
Definition: adata.h:59
static void browser_sort(struct BrowserState *state)
Sort the entries in the browser.
Definition: browser.c:344
&#39;mmdf&#39; Mailbox type
Definition: mailbox.h:49
int nntp_newsrc_parse(struct NntpAccountData *adata)
Parse .newsrc file.
Definition: newsrc.c:162
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
int mutt_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question.
Definition: question.c:49
&#39;MH&#39; Mailbox type
Definition: mailbox.h:50
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
struct NntpMboxData * mutt_newsgroup_unsubscribe(struct NntpAccountData *adata, char *group)
Unsubscribe newsgroup.
Definition: newsrc.c:1280
static int select_file_search(struct Menu *menu, regex_t *rx, int line)
Menu search callback for matching files - Implements Menu::search() -.
Definition: browser.c:970
int(* tag)(struct Menu *menu, int sel, int act)
Definition: lib.h:130
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
#define MUTT_SEL_MULTI
Multi-selection is enabled.
Definition: browser.h:38
NNTP-specific Mailbox data -.
Definition: mdata.h:32
int tagged
Number of tagged entries.
Definition: lib.h:92
#define MUTT_FILE
Do file completion.
Definition: mutt.h:54
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:180
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
char * path
Path.
Definition: url.h:75
int max
Number of entries in the menu.
Definition: lib.h:71
&#39;mbox&#39; Mailbox type
Definition: mailbox.h:48
#define ARRAY_FOREACH_FROM(elem, head, from)
Iterate from an index to the end.
Definition: array.h:217
Config has changed, NotifyConfig, EventConfig.
Definition: notify_type.h:42
General file/mailbox browser.
Definition: type.h:44
#define MUTT_SEL_MAILBOX
Select a mailbox.
Definition: browser.h:37
static void browser_highlight_default(struct BrowserState *state, struct Menu *menu)
Decide which browser item should be highlighted.
Definition: browser.c:1021
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition: mx.c:1317
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:322
MailboxType
Supported mailbox formats.
Definition: mailbox.h:43
Log at debug level 1.
Definition: logging.h:40
bool deleted
Definition: mdata.h:44
Sort by the number of unread emails.
Definition: sort2.h:59
void mutt_browser_select_dir(const char *f)
Remember the last directory selected.
Definition: browser.c:1234
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:749
static int file_tag(struct Menu *menu, int sel, int act)
Tag an entry in the menu - Implements Menu::tag() -.
Definition: browser.c:1152
#define ARRAY_REMOVE(head, elem)
Remove an entry from the array, shifting down the subsequent entries.
Definition: array.h:261
Cached regular expression.
Definition: regex3.h:89
int imap_browse(const char *path, struct BrowserState *state)
IMAP hook into the folder browser.
Definition: browse.c:182
Sort by the folder&#39;s description.
Definition: sort2.h:63
WHERE char * CurrentFolder
Currently selected mailbox.
Definition: mutt_globals.h:50
void ** groups_list
Definition: adata.h:61
#define mutt_message(...)
Definition: logging.h:87
#define FREE(x)
Definition: memory.h:40
size_t mutt_buffer_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition: buffer.c:374
int imap_mailbox_rename(const char *path)
Rename a mailbox.
Definition: browse.c:437
Mapping between user-readable string and a constant.
Definition: mapping.h:31
static struct Buffer LastDir
Definition: browser.c:138
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:78
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:38
Sort by number of emails in a folder.
Definition: sort2.h:58
struct MuttWindow * simple_dialog_new(enum MenuType mtype, enum WindowType wtype, const struct Mapping *help_data)
Create a simple index Dialog.
Definition: simple.c:128
char * mutt_path_concat(char *d, const char *dir, const char *fname, size_t l)
Join a directory name and a filename.
Definition: path.c:351
bool tagged
Definition: browser.h:78
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
int nntp_newsrc_update(struct NntpAccountData *adata)
Update .newsrc file.
Definition: newsrc.c:439
int current
Current entry.
Definition: lib.h:70
char * pattern
printable version
Definition: regex3.h:91
Sort by the date the email was sent.
Definition: sort2.h:43
static void init_state(struct BrowserState *state, struct Menu *menu)
Initialise a browser state.
Definition: browser.c:713
struct NntpMboxData * mutt_newsgroup_catchup(struct Mailbox *m, struct NntpAccountData *adata, char *group)
Catchup newsgroup.
Definition: newsrc.c:1308
bool inferiors
Definition: browser.h:74
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:79
static const struct Mapping FolderHelp[]
Help Bar for the File/Dir/Mailbox browser dialog.
Definition: browser.c:111
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
void * wdata
Private data.
Definition: mutt_window.h:145
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
bool imap_browse
Definition: browser.h:95
int(* search)(struct Menu *menu, regex_t *rx, int line)
Definition: lib.h:118
void mutt_get_parent_path(const char *path, char *buf, size_t buflen)
Find the parent of a path (or mailbox)
Definition: muttlib.c:1555
bool is_mailbox_list
Definition: browser.h:98
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:44
char delim
Definition: browser.h:70
Sort by the email&#39;s subject.
Definition: sort2.h:46
Log at debug level 3.
Definition: logging.h:42
#define SORT_MASK
Mask for the sort id.
Definition: sort2.h:78
static void folder_make_entry(struct Menu *menu, char *buf, size_t buflen, int line)
Format a menu item for the folder browser - Implements Menu::make_entry() -.
Definition: browser.c:986
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
int imap_subscribe(char *path, bool subscribe)
Subscribe to a mailbox.
Definition: imap.c:1286
int mutt_view_attachment(FILE *fp, struct Body *a, enum ViewAttachMode mode, struct Email *e, struct AttachCtx *actx, struct MuttWindow *win)
View an attachment.
Definition: mutt_attach.c:415
struct Url * url_parse(const char *src)
Fill in Url.
Definition: url.c:234
+ Here is the caller graph for this function:

◆ mutt_browser_select_dir()

void mutt_browser_select_dir ( const char *  f)

Remember the last directory selected.

Parameters
fDirectory name to save

This function helps the browser to know which directory has been selected. It should be called anywhere a confirm hit is done to open a new directory/file which is a maildir/mbox.

We could check if the sort method is appropriate with this feature.

Definition at line 1234 of file browser.c.

1235 {
1236  init_lastdir();
1237 
1239 
1240  /* Method that will fetch the parent path depending on the type of the path. */
1241  char buf[PATH_MAX];
1243  mutt_buffer_strcpy(&LastDir, buf);
1244 }
static void init_lastdir(void)
Initialise the browser directories.
Definition: browser.c:146
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
static struct Buffer LastDirBackup
Definition: browser.c:139
#define PATH_MAX
Definition: mutt.h:40
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
static struct Buffer LastDir
Definition: browser.c:138
void mutt_get_parent_path(const char *path, char *buf, size_t buflen)
Find the parent of a path (or mailbox)
Definition: muttlib.c:1555
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_browser_cleanup()

void mutt_browser_cleanup ( void  )

Clean up working Buffers.

Definition at line 160 of file browser.c.

161 {
164 }
static struct Buffer LastDirBackup
Definition: browser.c:139
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
static struct Buffer LastDir
Definition: browser.c:138
+ Here is the call graph for this function:
+ Here is the caller graph for this function: