NeoMutt  2021-02-05-329-g9e03b7
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 2233 of file browser.c.

2235 {
2236  struct Buffer *f_buf = mutt_buffer_pool_get();
2237 
2238  mutt_buffer_strcpy(f_buf, NONULL(file));
2239  mutt_buffer_select_file(f_buf, flags, m, files, numfiles);
2240  mutt_str_copy(file, mutt_buffer_string(f_buf), filelen);
2241 
2242  mutt_buffer_pool_release(&f_buf);
2243 }
#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:716
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:1161
+ 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 1161 of file browser.c.

1163 {
1164  char title[256];
1165  struct BrowserState state = { { 0 } };
1166  struct Menu *menu = NULL;
1167  bool kill_prefix = false;
1168  bool multiple = (flags & MUTT_SEL_MULTI);
1169  bool folder = (flags & MUTT_SEL_FOLDER);
1170  bool mailbox = (flags & MUTT_SEL_MAILBOX);
1171 
1172  /* Keeps in memory the directory we were in when hitting '='
1173  * to go directly to $folder (`$folder`) */
1174  char goto_swapper[PATH_MAX] = { 0 };
1175 
1176  mailbox = mailbox && folder;
1177 
1178  struct Buffer *OldLastDir = mutt_buffer_pool_get();
1179  struct Buffer *tmp = mutt_buffer_pool_get();
1180  struct Buffer *buf = mutt_buffer_pool_get();
1181  struct Buffer *prefix = mutt_buffer_pool_get();
1182 
1183  init_lastdir();
1184 
1185 #ifdef USE_NNTP
1186  if (OptNews)
1187  {
1188  if (mutt_buffer_is_empty(file))
1189  {
1191 
1192  /* default state for news reader mode is browse subscribed newsgroups */
1193  mailbox = false;
1194  for (size_t i = 0; i < adata->groups_num; i++)
1195  {
1196  struct NntpMboxData *mdata = adata->groups_list[i];
1197  if (mdata && mdata->subscribed)
1198  {
1199  mailbox = true;
1200  break;
1201  }
1202  }
1203  }
1204  else
1205  {
1206  mutt_buffer_copy(prefix, file);
1207  }
1208  }
1209  else
1210 #endif
1211  if (!mutt_buffer_is_empty(file))
1212  {
1214 #ifdef USE_IMAP
1215  if (imap_path_probe(mutt_buffer_string(file), NULL) == MUTT_IMAP)
1216  {
1217  init_state(&state, NULL);
1218  state.imap_browse = true;
1219  if (imap_browse(mutt_buffer_string(file), &state) == 0)
1220  {
1222  browser_sort(&state);
1223  }
1224  }
1225  else
1226  {
1227 #endif
1228  int i;
1229  for (i = mutt_buffer_len(file) - 1;
1230  (i > 0) && ((mutt_buffer_string(file))[i] != '/'); i--)
1231  {
1232  ; // do nothing
1233  }
1234 
1235  if (i > 0)
1236  {
1237  if ((mutt_buffer_string(file))[0] == '/')
1239  else
1240  {
1242  mutt_buffer_addch(&LastDir, '/');
1244  }
1245  }
1246  else
1247  {
1248  if ((mutt_buffer_string(file))[0] == '/')
1249  mutt_buffer_strcpy(&LastDir, "/");
1250  else
1252  }
1253 
1254  if ((i <= 0) && (mutt_buffer_string(file)[0] != '/'))
1255  mutt_buffer_copy(prefix, file);
1256  else
1257  mutt_buffer_strcpy(prefix, mutt_buffer_string(file) + i + 1);
1258  kill_prefix = true;
1259 #ifdef USE_IMAP
1260  }
1261 #endif
1262  }
1263  else
1264  {
1265  if (!folder)
1267  else
1268  {
1269  /* Whether we use the tracking feature of the browser depends
1270  * on which sort method we chose to use. This variable is defined
1271  * only to help readability of the code. */
1272  bool browser_track = false;
1273 
1274  const short c_sort_browser = cs_subset_sort(NeoMutt->sub, "sort_browser");
1275  switch (c_sort_browser & SORT_MASK)
1276  {
1277  case SORT_DESC:
1278  case SORT_SUBJECT:
1279  case SORT_ORDER:
1280  browser_track = true;
1281  break;
1282  }
1283 
1284  /* We use mutt_browser_select_dir to initialize the two
1285  * variables (LastDir, LastDirBackup) at the appropriate
1286  * values.
1287  *
1288  * We do it only when LastDir is not set (first pass there)
1289  * or when CurrentFolder and LastDirBackup are not the same.
1290  * This code is executed only when we list files, not when
1291  * we press up/down keys to navigate in a displayed list.
1292  *
1293  * We only do this when CurrentFolder has been set (ie, not
1294  * when listing folders on startup with "neomutt -y").
1295  *
1296  * This tracker is only used when browser_track is true,
1297  * meaning only with sort methods SUBJECT/DESC for now. */
1298  if (CurrentFolder)
1299  {
1301  {
1302  /* If browsing in "local"-mode, than we chose to define LastDir to
1303  * MailDir */
1304  switch (mx_path_probe(CurrentFolder))
1305  {
1306  case MUTT_IMAP:
1307  case MUTT_MAILDIR:
1308  case MUTT_MBOX:
1309  case MUTT_MH:
1310  case MUTT_MMDF:
1311  {
1312  const char *const c_folder =
1313  cs_subset_string(NeoMutt->sub, "folder");
1314  const char *const c_spool_file = cs_subset_string(NeoMutt->sub, "spool_file");
1315  if (c_folder)
1316  mutt_buffer_strcpy(&LastDir, c_folder);
1317  else if (c_spool_file)
1318  mutt_browser_select_dir(c_spool_file);
1319  break;
1320  }
1321  default:
1323  break;
1324  }
1325  }
1327  {
1329  }
1330  }
1331 
1332  /* When browser tracking feature is disabled, clear LastDirBackup */
1333  if (!browser_track)
1335  }
1336 
1337 #ifdef USE_IMAP
1338  if (!mailbox && (imap_path_probe(mutt_buffer_string(&LastDir), NULL) == MUTT_IMAP))
1339  {
1340  init_state(&state, NULL);
1341  state.imap_browse = true;
1343  browser_sort(&state);
1344  }
1345  else
1346 #endif
1347  {
1348  size_t i = mutt_buffer_len(&LastDir);
1349  while ((i > 0) && (mutt_buffer_string(&LastDir)[--i] == '/'))
1350  LastDir.data[i] = '\0';
1354  }
1355  }
1356 
1357  mutt_buffer_reset(file);
1358 
1359  const struct Mapping *help_data = NULL;
1360 #ifdef USE_NNTP
1361  if (OptNews)
1362  help_data = FolderNewsHelp;
1363  else
1364 #endif
1365  help_data = FolderHelp;
1366 
1367  struct MuttWindow *dlg =
1369 
1370  menu = dlg->wdata;
1371  menu->make_entry = folder_make_entry;
1372  menu->search = select_file_search;
1373  if (multiple)
1374  menu->tag = file_tag;
1375 
1376  struct MuttWindow *sbar = mutt_window_find(dlg, WT_INDEX_BAR);
1377  sbar_set_title(sbar, title);
1378 
1379  if (mailbox)
1380  {
1381  examine_mailboxes(m, NULL, &state);
1382  }
1383  else
1384 #ifdef USE_IMAP
1385  if (!state.imap_browse)
1386 #endif
1387  {
1388  // examine_directory() calls add_folder() which needs the menu
1389  if (examine_directory(m, menu, &state, mutt_buffer_string(&LastDir),
1390  mutt_buffer_string(prefix)) == -1)
1391  {
1392  goto bail;
1393  }
1394  }
1395 
1396  init_menu(&state, menu, title, sizeof(title), mailbox, m);
1397  // only now do we have a valid state to attach
1398  menu->mdata = &state.entry;
1399 
1400  while (true)
1401  {
1402  int op = menu_loop(menu);
1403  if (op >= 0)
1404  mutt_debug(LL_DEBUG1, "Got op %s (%d)\n", OpStrings[op][0], op);
1405  int index = menu_get_index(menu);
1406  struct FolderFile *ff = ARRAY_GET(&state.entry, index);
1407  switch (op)
1408  {
1409  case OP_DESCEND_DIRECTORY:
1410  case OP_GENERIC_SELECT_ENTRY:
1411  {
1412  if (ARRAY_EMPTY(&state.entry))
1413  {
1414  mutt_error(_("No files match the file mask"));
1415  break;
1416  }
1417 
1418  if (S_ISDIR(ff->mode) ||
1419  (S_ISLNK(ff->mode) && link_is_dir(mutt_buffer_string(&LastDir), ff->name))
1420 #ifdef USE_IMAP
1421  || ff->inferiors
1422 #endif
1423  )
1424  {
1425  /* make sure this isn't a MH or maildir mailbox */
1426  if (mailbox)
1427  {
1428  mutt_buffer_strcpy(buf, ff->name);
1430  }
1431 #ifdef USE_IMAP
1432  else if (state.imap_browse)
1433  {
1434  mutt_buffer_strcpy(buf, ff->name);
1435  }
1436 #endif
1437  else
1438  {
1440  }
1441 
1442  enum MailboxType type = mx_path_probe(mutt_buffer_string(buf));
1443  if ((op == OP_DESCEND_DIRECTORY) || (type == MUTT_MAILBOX_ERROR) ||
1444  (type == MUTT_UNKNOWN)
1445 #ifdef USE_IMAP
1446  || ff->inferiors
1447 #endif
1448  )
1449  {
1450  /* save the old directory */
1451  mutt_buffer_copy(OldLastDir, &LastDir);
1452 
1453  if (mutt_str_equal(ff->name, ".."))
1454  {
1455  size_t lastdirlen = mutt_buffer_len(&LastDir);
1456  if ((lastdirlen > 1) &&
1457  mutt_str_equal("..", mutt_buffer_string(&LastDir) + lastdirlen - 2))
1458  {
1459  mutt_buffer_addstr(&LastDir, "/..");
1460  }
1461  else
1462  {
1463  char *p = NULL;
1464  if (lastdirlen > 1)
1465  p = strrchr(mutt_buffer_string(&LastDir) + 1, '/');
1466 
1467  if (p)
1468  {
1469  *p = '\0';
1471  }
1472  else
1473  {
1474  if (mutt_buffer_string(&LastDir)[0] == '/')
1475  mutt_buffer_strcpy(&LastDir, "/");
1476  else
1477  mutt_buffer_addstr(&LastDir, "/..");
1478  }
1479  }
1480  }
1481  else if (mailbox)
1482  {
1485  }
1486 #ifdef USE_IMAP
1487  else if (state.imap_browse)
1488  {
1490  /* tack on delimiter here */
1491 
1492  /* special case "" needs no delimiter */
1493  struct Url *url = url_parse(ff->name);
1494  if (url && url->path && (ff->delim != '\0'))
1495  {
1497  }
1498  url_free(&url);
1499  }
1500 #endif
1501  else
1502  {
1504  mutt_buffer_copy(&LastDir, tmp);
1505  }
1506 
1507  destroy_state(&state);
1508  if (kill_prefix)
1509  {
1510  mutt_buffer_reset(prefix);
1511  kill_prefix = false;
1512  }
1513  mailbox = false;
1514 #ifdef USE_IMAP
1515  if (state.imap_browse)
1516  {
1517  init_state(&state, NULL);
1518  state.imap_browse = true;
1520  browser_sort(&state);
1521  menu->mdata = &state.entry;
1522  }
1523  else
1524 #endif
1525  {
1526  if (examine_directory(m, menu, &state, mutt_buffer_string(&LastDir),
1527  mutt_buffer_string(prefix)) == -1)
1528  {
1529  /* try to restore the old values */
1530  mutt_buffer_copy(&LastDir, OldLastDir);
1531  if (examine_directory(m, menu, &state, mutt_buffer_string(&LastDir),
1532  mutt_buffer_string(prefix)) == -1)
1533  {
1535  goto bail;
1536  }
1537  }
1538  /* resolve paths navigated from GUI */
1539  if (mutt_path_realpath(LastDir.data) == 0)
1540  break;
1541  }
1542 
1543  browser_highlight_default(&state, menu);
1544  init_menu(&state, menu, title, sizeof(title), mailbox, m);
1545  goto_swapper[0] = '\0';
1546  break;
1547  }
1548  }
1549  else if (op == OP_DESCEND_DIRECTORY)
1550  {
1551  mutt_error(_("%s is not a directory"), ARRAY_GET(&state.entry, index)->name);
1552  break;
1553  }
1554 
1555  if (mailbox || OptNews) /* USE_NNTP */
1556  {
1557  mutt_buffer_strcpy(file, ff->name);
1559  }
1560 #ifdef USE_IMAP
1561  else if (state.imap_browse)
1562  mutt_buffer_strcpy(file, ff->name);
1563 #endif
1564  else
1565  {
1567  }
1568  }
1569  /* fallthrough */
1570 
1571  case OP_EXIT:
1572 
1573  if (multiple)
1574  {
1575  char **tfiles = NULL;
1576 
1577  if (menu->tagged)
1578  {
1579  *numfiles = menu->tagged;
1580  tfiles = mutt_mem_calloc(*numfiles, sizeof(char *));
1581  size_t j = 0;
1582  ARRAY_FOREACH(ff, &state.entry)
1583  {
1584  if (ff->tagged)
1585  {
1588  tfiles[j++] = mutt_buffer_strdup(tmp);
1589  }
1590  }
1591  *files = tfiles;
1592  }
1593  else if (!mutt_buffer_is_empty(file)) /* no tagged entries. return selected entry */
1594  {
1595  *numfiles = 1;
1596  tfiles = mutt_mem_calloc(*numfiles, sizeof(char *));
1598  tfiles[0] = mutt_buffer_strdup(file);
1599  *files = tfiles;
1600  }
1601  }
1602 
1603  destroy_state(&state);
1604  goto bail;
1605 
1606  case OP_BROWSER_TELL:
1607  if (!ARRAY_EMPTY(&state.entry))
1608  mutt_message("%s", ARRAY_GET(&state.entry, index)->name);
1609  break;
1610 
1611 #ifdef USE_IMAP
1612  case OP_BROWSER_TOGGLE_LSUB:
1613  bool_str_toggle(NeoMutt->sub, "imap_list_subscribed", NULL);
1614 
1615  mutt_unget_event(0, OP_CHECK_NEW);
1616  break;
1617 
1618  case OP_CREATE_MAILBOX:
1619  if (!state.imap_browse)
1620  {
1621  mutt_error(_("Create is only supported for IMAP mailboxes"));
1622  break;
1623  }
1624 
1626  {
1627  /* TODO: find a way to detect if the new folder would appear in
1628  * this window, and insert it without starting over. */
1629  destroy_state(&state);
1630  init_state(&state, NULL);
1631  state.imap_browse = true;
1633  browser_sort(&state);
1634  menu->mdata = &state.entry;
1635  browser_highlight_default(&state, menu);
1636  init_menu(&state, menu, title, sizeof(title), mailbox, m);
1637  }
1638  /* else leave error on screen */
1639  break;
1640 
1641  case OP_RENAME_MAILBOX:
1642  if (!ff->imap)
1643  mutt_error(_("Rename is only supported for IMAP mailboxes"));
1644  else
1645  {
1646  if (imap_mailbox_rename(ff->name) >= 0)
1647  {
1648  destroy_state(&state);
1649  init_state(&state, NULL);
1650  state.imap_browse = true;
1652  browser_sort(&state);
1653  menu->mdata = &state.entry;
1654  browser_highlight_default(&state, menu);
1655  init_menu(&state, menu, title, sizeof(title), mailbox, m);
1656  }
1657  }
1658  break;
1659 
1660  case OP_DELETE_MAILBOX:
1661  if (!ff->imap)
1662  mutt_error(_("Delete is only supported for IMAP mailboxes"));
1663  else
1664  {
1665  char msg[128];
1666 
1667  // TODO(sileht): It could be better to select INBOX instead. But I
1668  // don't want to manipulate Context/Mailboxes/mailbox->account here for now.
1669  // Let's just protect neomutt against crash for now. #1417
1670  if (mutt_str_equal(mailbox_path(m), ff->name))
1671  {
1672  mutt_error(_("Can't delete currently selected mailbox"));
1673  break;
1674  }
1675 
1676  snprintf(msg, sizeof(msg), _("Really delete mailbox \"%s\"?"), ff->name);
1677  if (mutt_yesorno(msg, MUTT_NO) == MUTT_YES)
1678  {
1679  if (imap_delete_mailbox(m, ff->name) == 0)
1680  {
1681  /* free the mailbox from the browser */
1682  FREE(&ff->name);
1683  FREE(&ff->desc);
1684  /* and move all other entries up */
1685  ARRAY_REMOVE(&state.entry, ff);
1686  mutt_message(_("Mailbox deleted"));
1687  init_menu(&state, menu, title, sizeof(title), mailbox, m);
1688  }
1689  else
1690  mutt_error(_("Mailbox deletion failed"));
1691  }
1692  else
1693  mutt_message(_("Mailbox not deleted"));
1694  }
1695  break;
1696 #endif
1697 
1698  case OP_GOTO_PARENT:
1699  case OP_CHANGE_DIRECTORY:
1700 
1701 #ifdef USE_NNTP
1702  if (OptNews)
1703  break;
1704 #endif
1705 
1706  mutt_buffer_copy(buf, &LastDir);
1707 #ifdef USE_IMAP
1708  if (!state.imap_browse)
1709 #endif
1710  {
1711  /* add '/' at the end of the directory name if not already there */
1712  size_t len = mutt_buffer_len(buf);
1713  if ((len > 0) && (mutt_buffer_string(&LastDir)[len - 1] != '/'))
1714  mutt_buffer_addch(buf, '/');
1715  }
1716 
1717  if (op == OP_CHANGE_DIRECTORY)
1718  {
1719  /* buf comes from the buffer pool, so defaults to size 1024 */
1720  int ret = mutt_buffer_get_field(_("Chdir to: "), buf, MUTT_FILE,
1721  false, NULL, NULL, NULL);
1722  if ((ret != 0) && mutt_buffer_is_empty(buf))
1723  break;
1724  }
1725  else if (op == OP_GOTO_PARENT)
1727 
1728  if (!mutt_buffer_is_empty(buf))
1729  {
1730  mailbox = false;
1732 #ifdef USE_IMAP
1733  if (imap_path_probe(mutt_buffer_string(buf), NULL) == MUTT_IMAP)
1734  {
1735  mutt_buffer_copy(&LastDir, buf);
1736  destroy_state(&state);
1737  init_state(&state, NULL);
1738  state.imap_browse = true;
1740  browser_sort(&state);
1741  menu->mdata = &state.entry;
1742  browser_highlight_default(&state, menu);
1743  init_menu(&state, menu, title, sizeof(title), mailbox, m);
1744  }
1745  else
1746 #endif
1747  {
1748  if (mutt_buffer_string(buf)[0] != '/')
1749  {
1750  /* in case dir is relative, make it relative to LastDir,
1751  * not current working dir */
1753  mutt_buffer_string(buf));
1754  mutt_buffer_copy(buf, tmp);
1755  }
1756  /* Resolve path from <chdir>
1757  * Avoids buildup such as /a/b/../../c
1758  * Symlinks are always unraveled to keep code simple */
1759  if (mutt_path_realpath(buf->data) == 0)
1760  break;
1761 
1762  struct stat st;
1763  if (stat(mutt_buffer_string(buf), &st) == 0)
1764  {
1765  if (S_ISDIR(st.st_mode))
1766  {
1767  destroy_state(&state);
1768  if (examine_directory(m, menu, &state, mutt_buffer_string(buf),
1769  mutt_buffer_string(prefix)) == 0)
1770  {
1771  mutt_buffer_copy(&LastDir, buf);
1772  }
1773  else
1774  {
1775  mutt_error(_("Error scanning directory"));
1776  if (examine_directory(m, menu, &state, mutt_buffer_string(&LastDir),
1777  mutt_buffer_string(prefix)) == -1)
1778  {
1779  goto bail;
1780  }
1781  }
1782  browser_highlight_default(&state, menu);
1783  init_menu(&state, menu, title, sizeof(title), mailbox, m);
1784  }
1785  else
1786  mutt_error(_("%s is not a directory"), mutt_buffer_string(buf));
1787  }
1788  else
1790  }
1791  }
1792  break;
1793 
1794  case OP_ENTER_MASK:
1795  {
1796  const struct Regex *c_mask = cs_subset_regex(NeoMutt->sub, "mask");
1797  mutt_buffer_strcpy(buf, c_mask ? c_mask->pattern : NULL);
1798  if (mutt_get_field(_("File Mask: "), buf->data, buf->dsize,
1799  MUTT_COMP_NO_FLAGS, false, NULL, NULL) != 0)
1800  {
1801  break;
1802  }
1803 
1804  mutt_buffer_fix_dptr(buf);
1805 
1806  mailbox = false;
1807  /* assume that the user wants to see everything */
1808  if (mutt_buffer_is_empty(buf))
1809  mutt_buffer_strcpy(buf, ".");
1810 
1811  struct Buffer errmsg = mutt_buffer_make(256);
1812  int rc = cs_subset_str_string_set(NeoMutt->sub, "mask",
1813  mutt_buffer_string(buf), &errmsg);
1814  if (CSR_RESULT(rc) != CSR_SUCCESS)
1815  {
1816  if (!mutt_buffer_is_empty(&errmsg))
1817  {
1818  mutt_error("%s", mutt_buffer_string(&errmsg));
1819  mutt_buffer_dealloc(&errmsg);
1820  }
1821  break;
1822  }
1823  mutt_buffer_dealloc(&errmsg);
1824 
1825  destroy_state(&state);
1826 #ifdef USE_IMAP
1827  if (state.imap_browse)
1828  {
1829  init_state(&state, NULL);
1830  state.imap_browse = true;
1832  browser_sort(&state);
1833  menu->mdata = &state.entry;
1834  init_menu(&state, menu, title, sizeof(title), mailbox, m);
1835  }
1836  else
1837 #endif
1838  if (examine_directory(m, menu, &state, mutt_buffer_string(&LastDir), NULL) == 0)
1839  init_menu(&state, menu, title, sizeof(title), mailbox, m);
1840  else
1841  {
1842  mutt_error(_("Error scanning directory"));
1843  goto bail;
1844  }
1845  kill_prefix = false;
1846  if (ARRAY_EMPTY(&state.entry))
1847  {
1848  mutt_error(_("No files match the file mask"));
1849  break;
1850  }
1851  break;
1852  }
1853 
1854  case OP_SORT:
1855  case OP_SORT_REVERSE:
1856 
1857  {
1858  bool resort = true;
1859  int sort = -1;
1860  int reverse = (op == OP_SORT_REVERSE);
1861 
1862  switch (mutt_multi_choice(
1863  (reverse) ?
1864  /* L10N: The highlighted letters must match the "Sort" options */
1865  _("Reverse sort by (d)ate, (a)lpha, si(z)e, d(e)scription, "
1866  "(c)ount, ne(w) count, or do(n)'t sort?") :
1867  /* L10N: The highlighted letters must match the "Reverse Sort" options */
1868  _("Sort by (d)ate, (a)lpha, si(z)e, d(e)scription, (c)ount, "
1869  "ne(w) count, or do(n)'t sort?"),
1870  /* L10N: These must match the highlighted letters from "Sort" and "Reverse Sort" */
1871  _("dazecwn")))
1872  {
1873  case -1: /* abort */
1874  resort = false;
1875  break;
1876 
1877  case 1: /* (d)ate */
1878  sort = SORT_DATE;
1879  break;
1880 
1881  case 2: /* (a)lpha */
1882  sort = SORT_SUBJECT;
1883  break;
1884 
1885  case 3: /* si(z)e */
1886  sort = SORT_SIZE;
1887  break;
1888 
1889  case 4: /* d(e)scription */
1890  sort = SORT_DESC;
1891  break;
1892 
1893  case 5: /* (c)ount */
1894  sort = SORT_COUNT;
1895  break;
1896 
1897  case 6: /* ne(w) count */
1898  sort = SORT_UNREAD;
1899  break;
1900 
1901  case 7: /* do(n)'t sort */
1902  sort = SORT_ORDER;
1903  break;
1904  }
1905  if (resort)
1906  {
1907  sort |= reverse ? SORT_REVERSE : 0;
1908  cs_subset_str_native_set(NeoMutt->sub, "sort_browser", sort, NULL);
1909  browser_sort(&state);
1910  browser_highlight_default(&state, menu);
1912  }
1913  else
1914  {
1915  cs_subset_str_native_set(NeoMutt->sub, "sort_browser", sort, NULL);
1916  }
1917  break;
1918  }
1919 
1920  case OP_TOGGLE_MAILBOXES:
1921  case OP_BROWSER_GOTO_FOLDER:
1922  case OP_CHECK_NEW:
1923  if (op == OP_TOGGLE_MAILBOXES)
1924  {
1925  mailbox = !mailbox;
1926  menu->is_mailbox_list = mailbox;
1927  }
1928 
1929  if (op == OP_BROWSER_GOTO_FOLDER)
1930  {
1931  /* When in mailboxes mode, disables this feature */
1932  const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
1933  if (c_folder)
1934  {
1935  mutt_debug(LL_DEBUG3, "= hit! Folder: %s, LastDir: %s\n", c_folder,
1937  if (goto_swapper[0] == '\0')
1938  {
1939  if (!mutt_str_equal(mutt_buffer_string(&LastDir), c_folder))
1940  {
1941  /* Stores into goto_swapper LastDir, and swaps to `$folder` */
1942  mutt_str_copy(goto_swapper, mutt_buffer_string(&LastDir),
1943  sizeof(goto_swapper));
1945  mutt_buffer_strcpy(&LastDir, c_folder);
1946  }
1947  }
1948  else
1949  {
1951  mutt_buffer_strcpy(&LastDir, goto_swapper);
1952  goto_swapper[0] = '\0';
1953  }
1954  }
1955  }
1956  destroy_state(&state);
1957  mutt_buffer_reset(prefix);
1958  kill_prefix = false;
1959 
1960  if (mailbox)
1961  {
1962  examine_mailboxes(m, menu, &state);
1963  }
1964 #ifdef USE_IMAP
1965  else if (imap_path_probe(mutt_buffer_string(&LastDir), NULL) == MUTT_IMAP)
1966  {
1967  init_state(&state, NULL);
1968  state.imap_browse = true;
1970  browser_sort(&state);
1971  menu->mdata = &state.entry;
1972  }
1973 #endif
1974  else if (examine_directory(m, menu, &state, mutt_buffer_string(&LastDir),
1975  mutt_buffer_string(prefix)) == -1)
1976  {
1977  goto bail;
1978  }
1979  init_menu(&state, menu, title, sizeof(title), mailbox, m);
1980  break;
1981 
1982  case OP_MAILBOX_LIST:
1984  break;
1985 
1986  case OP_BROWSER_NEW_FILE:
1988  /* buf comes from the buffer pool, so defaults to size 1024 */
1989  if (mutt_buffer_get_field(_("New file name: "), buf, MUTT_FILE, false,
1990  NULL, NULL, NULL) == 0)
1991  {
1992  mutt_buffer_copy(file, buf);
1993  destroy_state(&state);
1994  goto bail;
1995  }
1996  break;
1997 
1998  case OP_BROWSER_VIEW_FILE:
1999  if (ARRAY_EMPTY(&state.entry))
2000  {
2001  mutt_error(_("No files match the file mask"));
2002  break;
2003  }
2004 
2005 #ifdef USE_IMAP
2006  if (ff->selectable)
2007  {
2008  mutt_buffer_strcpy(file, ff->name);
2009  destroy_state(&state);
2010  goto bail;
2011  }
2012  else
2013 #endif
2014  if (S_ISDIR(ff->mode) ||
2015  (S_ISLNK(ff->mode) && link_is_dir(mutt_buffer_string(&LastDir), ff->name)))
2016  {
2017  mutt_error(_("Can't view a directory"));
2018  break;
2019  }
2020  else
2021  {
2022  char buf2[PATH_MAX];
2023 
2024  mutt_path_concat(buf2, mutt_buffer_string(&LastDir), ff->name, sizeof(buf2));
2025  struct Body *b = mutt_make_file_attach(buf2, NeoMutt->sub);
2026  if (b)
2027  {
2028  mutt_view_attachment(NULL, b, MUTT_VA_REGULAR, NULL, NULL, menu->win_index);
2029  mutt_body_free(&b);
2031  }
2032  else
2033  mutt_error(_("Error trying to view file"));
2034  }
2035  break;
2036 
2037 #ifdef USE_NNTP
2038  case OP_CATCHUP:
2039  case OP_UNCATCHUP:
2040  {
2041  if (!OptNews)
2042  break;
2043 
2044  struct NntpMboxData *mdata = NULL;
2045 
2047  if (rc < 0)
2048  break;
2049 
2050  if (op == OP_CATCHUP)
2051  mdata = mutt_newsgroup_catchup(m, CurrentNewsSrv, ff->name);
2052  else
2053  mdata = mutt_newsgroup_uncatchup(m, CurrentNewsSrv, ff->name);
2054 
2055  if (mdata)
2056  {
2058  index = menu_get_index(menu) + 1;
2059  if (index < menu->max)
2060  menu_set_index(menu, index);
2061  }
2062  if (rc)
2065  break;
2066  }
2067 
2068  case OP_LOAD_ACTIVE:
2069  {
2070  if (!OptNews)
2071  break;
2072 
2073  struct NntpAccountData *adata = CurrentNewsSrv;
2074 
2075  if (nntp_newsrc_parse(adata) < 0)
2076  break;
2077 
2078  for (size_t i = 0; i < adata->groups_num; i++)
2079  {
2080  struct NntpMboxData *mdata = adata->groups_list[i];
2081  if (mdata)
2082  mdata->deleted = true;
2083  }
2084  nntp_active_fetch(adata, true);
2085  nntp_newsrc_update(adata);
2086  nntp_newsrc_close(adata);
2087 
2088  destroy_state(&state);
2089  if (mailbox)
2090  examine_mailboxes(m, menu, &state);
2091  else
2092  {
2093  if (examine_directory(m, menu, &state, NULL, NULL) == -1)
2094  break;
2095  }
2096  init_menu(&state, menu, title, sizeof(title), mailbox, m);
2097  break;
2098  }
2099 #endif /* USE_NNTP */
2100 
2101 #if defined(USE_IMAP) || defined(USE_NNTP)
2102  case OP_BROWSER_SUBSCRIBE:
2103  case OP_BROWSER_UNSUBSCRIBE:
2104 #endif
2105 #ifdef USE_NNTP
2106  case OP_SUBSCRIBE_PATTERN:
2107  case OP_UNSUBSCRIBE_PATTERN:
2108  {
2109  if (OptNews)
2110  {
2111  struct NntpAccountData *adata = CurrentNewsSrv;
2112  regex_t rx;
2113  memset(&rx, 0, sizeof(rx));
2114  char *s = buf->data;
2115  index = menu_get_index(menu);
2116 
2117  if ((op == OP_SUBSCRIBE_PATTERN) || (op == OP_UNSUBSCRIBE_PATTERN))
2118  {
2119  char tmp2[256];
2120 
2121  mutt_buffer_reset(buf);
2122  if (op == OP_SUBSCRIBE_PATTERN)
2123  snprintf(tmp2, sizeof(tmp2), _("Subscribe pattern: "));
2124  else
2125  snprintf(tmp2, sizeof(tmp2), _("Unsubscribe pattern: "));
2126  /* buf comes from the buffer pool, so defaults to size 1024 */
2127  if ((mutt_buffer_get_field(tmp2, buf, MUTT_PATTERN, false, NULL, NULL, NULL) != 0) ||
2128  mutt_buffer_is_empty(buf))
2129  {
2130  break;
2131  }
2132 
2133  int err = REG_COMP(&rx, s, REG_NOSUB);
2134  if (err != 0)
2135  {
2136  regerror(err, &rx, buf->data, buf->dsize);
2137  regfree(&rx);
2138  mutt_error("%s", mutt_buffer_string(buf));
2139  break;
2140  }
2142  index = 0;
2143  }
2144  else if (ARRAY_EMPTY(&state.entry))
2145  {
2146  mutt_error(_("No newsgroups match the mask"));
2147  break;
2148  }
2149 
2150  int rc = nntp_newsrc_parse(adata);
2151  if (rc < 0)
2152  break;
2153 
2154  ARRAY_FOREACH_FROM(ff, &state.entry, index)
2155  {
2156  if ((op == OP_BROWSER_SUBSCRIBE) || (op == OP_BROWSER_UNSUBSCRIBE) ||
2157  (regexec(&rx, ff->name, 0, NULL, 0) == 0))
2158  {
2159  if ((op == OP_BROWSER_SUBSCRIBE) || (op == OP_SUBSCRIBE_PATTERN))
2160  mutt_newsgroup_subscribe(adata, ff->name);
2161  else
2162  mutt_newsgroup_unsubscribe(adata, ff->name);
2163  }
2164  if ((op == OP_BROWSER_SUBSCRIBE) || (op == OP_BROWSER_UNSUBSCRIBE))
2165  {
2166  if ((index + 1) < menu->max)
2167  menu_set_index(menu, index + 1);
2168  break;
2169  }
2170  }
2171 
2172  if (op == OP_SUBSCRIBE_PATTERN)
2173  {
2174  for (size_t j = 0; adata && (j < adata->groups_num); j++)
2175  {
2176  struct NntpMboxData *mdata = adata->groups_list[j];
2177  if (mdata && mdata->group && !mdata->subscribed)
2178  {
2179  if (regexec(&rx, mdata->group, 0, NULL, 0) == 0)
2180  {
2181  mutt_newsgroup_subscribe(adata, mdata->group);
2182  add_folder(menu, &state, mdata->group, NULL, NULL, NULL, mdata);
2183  }
2184  }
2185  }
2186  init_menu(&state, menu, title, sizeof(title), mailbox, m);
2187  }
2188  if (rc > 0)
2190  nntp_newsrc_update(adata);
2191  nntp_clear_cache(adata);
2192  nntp_newsrc_close(adata);
2193  if ((op != OP_BROWSER_SUBSCRIBE) && (op != OP_BROWSER_UNSUBSCRIBE))
2194  regfree(&rx);
2195  }
2196 #ifdef USE_IMAP
2197  else
2198 #endif /* USE_IMAP && USE_NNTP */
2199 #endif /* USE_NNTP */
2200 #ifdef USE_IMAP
2201  {
2202  char tmp2[256];
2203  mutt_str_copy(tmp2, ff->name, sizeof(tmp2));
2204  mutt_expand_path(tmp2, sizeof(tmp2));
2205  imap_subscribe(tmp2, (op == OP_BROWSER_SUBSCRIBE));
2206  }
2207 #endif /* USE_IMAP */
2208  }
2209  }
2210  }
2211 
2212 bail:
2213  mutt_buffer_pool_release(&OldLastDir);
2216  mutt_buffer_pool_release(&prefix);
2217 
2218  if (menu)
2220 
2221  goto_swapper[0] = '\0';
2222 }
#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:871
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:206
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:328
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
#define mutt_perror(...)
Definition: logging.h:85
GUI selectable list of items.
Definition: lib.h:56
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2400
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:693
static void destroy_state(struct BrowserState *state)
Free the BrowserState.
Definition: browser.c:131
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
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:255
#define mutt_message(...)
Definition: logging.h:83
int imap_delete_mailbox(struct Mailbox *m, char *path)
Delete a mailbox.
Definition: imap.c:513
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:306
static int file_tag(struct Menu *menu, int sel, int act)
Tag an entry in the menu - Implements Menu::tag()
Definition: browser.c:1114
struct NntpMboxData * mutt_newsgroup_uncatchup(struct Mailbox *m, struct NntpAccountData *adata, char *group)
Uncatchup newsgroup.
Definition: newsrc.c:1347
struct MuttWindow * mutt_window_find(struct MuttWindow *root, enum WindowType type)
Find a Window of a given type.
Definition: mutt_window.c:675
#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
General file/mailbox browser.
Definition: keymap.h:78
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:621
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:725
#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
void dialog_destroy_simple_index(struct MuttWindow **ptr)
Destroy a simple index Dialog.
Definition: simple.c:111
const char * mutt_path_getcwd(struct Buffer *cwd)
Get the current working directory.
Definition: path.c:563
A division of the screen.
Definition: mutt_window.h:117
void nntp_newsrc_close(struct NntpAccountData *adata)
Unlock and close .newsrc file.
Definition: newsrc.c:118
static void init_lastdir(void)
Initialise the browser directories.
Definition: browser.c:105
void url_free(struct Url **ptr)
Free the contents of a URL.
Definition: url.c:123
struct MuttWindow * dialog_create_simple_index(enum MenuType mtype, enum WindowType wtype, const struct Mapping *help_data)
Create a simple index Dialog.
Definition: simple.c:76
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:821
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:929
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
bool subscribed
Definition: mdata.h:41
The body of an email.
Definition: body.h:34
void(* make_entry)(struct Menu *menu, char *buf, size_t buflen, int line)
Format a item for a menu.
Definition: lib.h:91
#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:227
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:292
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:121
int nntp_active_fetch(struct NntpAccountData *adata, bool mark_new)
Fetch list of all newsgroups from server.
Definition: nntp.c:1959
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:395
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:375
static struct Buffer LastDirBackup
Definition: browser.c:98
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:52
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
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:213
const char * OpStrings[][2]
Definition: opcodes.c:34
void * mdata
Driver specific data.
Definition: mailbox.h:136
Browser Dialog, mutt_buffer_select_file()
Definition: mutt_window.h:78
&#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:272
int mutt_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question.
Definition: curs_lib.c:824
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:83
void * mdata
Private data.
Definition: lib.h:129
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:303
&#39;mmdf&#39; Mailbox type
Definition: mailbox.h:49
bool is_mailbox_list
Definition: lib.h:65
int nntp_newsrc_parse(struct NntpAccountData *adata)
Parse .newsrc file.
Definition: newsrc.c:162
static void init_menu(struct BrowserState *state, struct Menu *menu, char *title, size_t titlelen, bool mailbox, struct Mailbox *m)
Set up a new menu.
Definition: browser.c:1009
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:295
&#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
void sbar_set_title(struct MuttWindow *win, const char *title)
Set the title for the Simple Bar.
Definition: sbar.c:159
int(* tag)(struct Menu *menu, int sel, int act)
Tag some menu items.
Definition: lib.h:110
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
#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:81
#define MUTT_FILE
Do file completion.
Definition: mutt.h:54
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:60
&#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
#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:981
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition: mx.c:1316
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:321
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:1141
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:716
#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
#define mutt_error(...)
Definition: logging.h:84
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 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:97
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:77
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
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
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
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
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:672
struct NntpMboxData * mutt_newsgroup_catchup(struct Mailbox *m, struct NntpAccountData *adata, char *group)
Catchup newsgroup.
Definition: newsrc.c:1308
struct MuttWindow * win_index
Definition: lib.h:66
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:70
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:140
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
bool imap_browse
Definition: browser.h:95
Index Bar containing status info about the Index.
Definition: mutt_window.h:96
int(* search)(struct Menu *menu, regex_t *rx, int line)
Search a menu for a item matching a regex.
Definition: lib.h:101
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
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:45
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:945
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:1283
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:414
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 1141 of file browser.c.

1142 {
1143  init_lastdir();
1144 
1146 
1147  /* Method that will fetch the parent path depending on the type of the path. */
1148  char buf[PATH_MAX];
1150  mutt_buffer_strcpy(&LastDir, buf);
1151 }
static void init_lastdir(void)
Initialise the browser directories.
Definition: browser.c:105
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:98
#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:97
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 119 of file browser.c.

120 {
123 }
static struct Buffer LastDirBackup
Definition: browser.c:98
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:97
+ Here is the call graph for this function:
+ Here is the caller graph for this function: