NeoMutt  2019-12-07-168-gc45f47
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 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

void mutt_select_file (char *file, size_t filelen, SelectFileFlags flags, char ***files, int *numfiles)
 Let the user select a file. More...
 
void mutt_buffer_select_file (struct Buffer *f, SelectFileFlags flags, 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...
 

Variables

bool C_BrowserAbbreviateMailboxes
 Config: Abbreviate mailboxes using '~' and '=' in the browser. More...
 
char * C_FolderFormat
 Config: printf-like format string for the browser's display of folders. More...
 
char * C_GroupIndexFormat
 Config: (nntp) printf-like format string for the browser's display of newsgroups. More...
 
char * C_NewsgroupsCharset
 Config: (nntp) Character set of newsgroups' descriptions. More...
 
bool C_ShowOnlyUnread
 Config: (nntp) Only show subscribed newsgroups with unread articles. More...
 
short C_SortBrowser
 Config: Sort method for the browser. More...
 
char * C_VfolderFormat
 Config: (notmuch) printf-like format string for the browser's display of virtual folders. 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 44 of file browser.h.

◆ MUTT_SEL_MAILBOX

#define MUTT_SEL_MAILBOX   (1 << 0)

Select a mailbox.

Definition at line 45 of file browser.h.

◆ MUTT_SEL_MULTI

#define MUTT_SEL_MULTI   (1 << 1)

Multi-selection is enabled.

Definition at line 46 of file browser.h.

◆ MUTT_SEL_FOLDER

#define MUTT_SEL_FOLDER   (1 << 2)

Select a local directory.

Definition at line 47 of file browser.h.

Typedef Documentation

◆ SelectFileFlags

typedef uint8_t SelectFileFlags

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

Definition at line 43 of file browser.h.

Function Documentation

◆ mutt_select_file()

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

Let the user select a file.

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

Definition at line 2262 of file browser.c.

2264 {
2265  struct Buffer *f_buf = mutt_buffer_pool_get();
2266 
2267  mutt_buffer_strcpy(f_buf, NONULL(file));
2268  mutt_buffer_select_file(f_buf, flags, files, numfiles);
2269  mutt_str_strfcpy(file, mutt_b2s(f_buf), filelen);
2270 
2271  mutt_buffer_pool_release(&f_buf);
2272 }
#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_select_file(struct Buffer *file, SelectFileFlags flags, char ***files, int *numfiles)
Let the user select a file.
Definition: browser.c:1185
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
#define mutt_b2s(buf)
Definition: buffer.h:41
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:773
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
+ 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,
char ***  files,
int *  numfiles 
)

Let the user select a file.

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

Definition at line 1185 of file browser.c.

1187 {
1188  char helpstr[1024];
1189  char title[256];
1190  struct BrowserState state = { 0 };
1191  struct Menu *menu = NULL;
1192  bool kill_prefix = false;
1193  bool multiple = (flags & MUTT_SEL_MULTI);
1194  bool folder = (flags & MUTT_SEL_FOLDER);
1195  bool mailbox = (flags & MUTT_SEL_MAILBOX);
1196 
1197  /* Keeps in memory the directory we were in when hitting '='
1198  * to go directly to $folder (#C_Folder) */
1199  char goto_swapper[PATH_MAX] = { 0 };
1200 
1201  mailbox = mailbox && folder;
1202 
1203  struct Buffer *OldLastDir = mutt_buffer_pool_get();
1204  struct Buffer *tmp = mutt_buffer_pool_get();
1205  struct Buffer *buf = mutt_buffer_pool_get();
1206  struct Buffer *prefix = mutt_buffer_pool_get();
1207 
1208  init_lastdir();
1209 
1210 #ifdef USE_NNTP
1211  if (OptNews)
1212  {
1213  if (mutt_buffer_is_empty(file))
1214  {
1216 
1217  /* default state for news reader mode is browse subscribed newsgroups */
1218  mailbox = false;
1219  for (size_t i = 0; i < adata->groups_num; i++)
1220  {
1221  struct NntpMboxData *mdata = adata->groups_list[i];
1222  if (mdata && mdata->subscribed)
1223  {
1224  mailbox = true;
1225  break;
1226  }
1227  }
1228  }
1229  else
1230  {
1231  mutt_buffer_copy(prefix, file);
1232  }
1233  }
1234  else
1235 #endif
1236  if (!mutt_buffer_is_empty(file))
1237  {
1239 #ifdef USE_IMAP
1240  if (imap_path_probe(mutt_b2s(file), NULL) == MUTT_IMAP)
1241  {
1242  init_state(&state, NULL);
1243  state.imap_browse = true;
1244  if (imap_browse(mutt_b2s(file), &state) == 0)
1245  {
1247  browser_sort(&state);
1248  }
1249  }
1250  else
1251  {
1252 #endif
1253  int i;
1254  for (i = mutt_buffer_len(file) - 1; (i > 0) && ((mutt_b2s(file))[i] != '/'); i--)
1255  ;
1256  if (i > 0)
1257  {
1258  if ((mutt_b2s(file))[0] == '/')
1260  else
1261  {
1263  mutt_buffer_addch(&LastDir, '/');
1265  }
1266  }
1267  else
1268  {
1269  if ((mutt_b2s(file))[0] == '/')
1270  mutt_buffer_strcpy(&LastDir, "/");
1271  else
1273  }
1274 
1275  if ((i <= 0) && (mutt_b2s(file)[0] != '/'))
1276  mutt_buffer_copy(prefix, file);
1277  else
1278  mutt_buffer_strcpy(prefix, mutt_b2s(file) + i + 1);
1279  kill_prefix = true;
1280 #ifdef USE_IMAP
1281  }
1282 #endif
1283  }
1284  else
1285  {
1286  if (!folder)
1288  else
1289  {
1290  /* Whether we use the tracking feature of the browser depends
1291  * on which sort method we chose to use. This variable is defined
1292  * only to help readability of the code. */
1293  bool browser_track = false;
1294 
1295  switch (C_SortBrowser & SORT_MASK)
1296  {
1297  case SORT_DESC:
1298  case SORT_SUBJECT:
1299  case SORT_ORDER:
1300  browser_track = true;
1301  break;
1302  }
1303 
1304  /* We use mutt_browser_select_dir to initialize the two
1305  * variables (LastDir, LastDirBackup) at the appropriate
1306  * values.
1307  *
1308  * We do it only when LastDir is not set (first pass there)
1309  * or when CurrentFolder and LastDirBackup are not the same.
1310  * This code is executed only when we list files, not when
1311  * we press up/down keys to navigate in a displayed list.
1312  *
1313  * We only do this when CurrentFolder has been set (ie, not
1314  * when listing folders on startup with "neomutt -y").
1315  *
1316  * This tracker is only used when browser_track is true,
1317  * meaning only with sort methods SUBJECT/DESC for now. */
1318  if (CurrentFolder)
1319  {
1321  {
1322  /* If browsing in "local"-mode, than we chose to define LastDir to
1323  * MailDir */
1324  switch (mx_path_probe(CurrentFolder))
1325  {
1326  case MUTT_IMAP:
1327  case MUTT_MAILDIR:
1328  case MUTT_MBOX:
1329  case MUTT_MH:
1330  case MUTT_MMDF:
1331  if (C_Folder)
1333  else if (C_Spoolfile)
1335  break;
1336  default:
1338  break;
1339  }
1340  }
1342  {
1344  }
1345  }
1346 
1347  /* When browser tracking feature is disabled, clear LastDirBackup */
1348  if (!browser_track)
1350  }
1351 
1352 #ifdef USE_IMAP
1353  if (!mailbox && (imap_path_probe(mutt_b2s(&LastDir), NULL) == MUTT_IMAP))
1354  {
1355  init_state(&state, NULL);
1356  state.imap_browse = true;
1357  imap_browse(mutt_b2s(&LastDir), &state);
1358  browser_sort(&state);
1359  }
1360  else
1361 #endif
1362  {
1363  size_t i = mutt_buffer_len(&LastDir);
1364  while ((i > 0) && (mutt_b2s(&LastDir)[--i] == '/'))
1365  LastDir.data[i] = '\0';
1369  }
1370  }
1371 
1372  mutt_buffer_reset(file);
1373 
1374  if (mailbox)
1375  {
1376  examine_mailboxes(NULL, &state);
1377  }
1378  else
1379 #ifdef USE_IMAP
1380  if (!state.imap_browse)
1381 #endif
1382  {
1383  if (examine_directory(NULL, &state, mutt_b2s(&LastDir), mutt_b2s(prefix)) == -1)
1384  goto bail;
1385  }
1386 
1387  struct MuttWindow *dlg =
1390  dlg->type = WT_DIALOG;
1391  struct MuttWindow *index =
1394  index->type = WT_INDEX;
1395  struct MuttWindow *ibar = mutt_window_new(
1397  ibar->type = WT_INDEX_BAR;
1398 
1399  if (C_StatusOnTop)
1400  {
1401  mutt_window_add_child(dlg, ibar);
1402  mutt_window_add_child(dlg, index);
1403  }
1404  else
1405  {
1406  mutt_window_add_child(dlg, index);
1407  mutt_window_add_child(dlg, ibar);
1408  }
1409 
1411  dialog_push(dlg);
1412 
1413  menu = mutt_menu_new(MENU_FOLDER);
1414 
1415  menu->pagelen = index->state.rows;
1416  menu->win_index = index;
1417  menu->win_ibar = ibar;
1418 
1421  menu->title = title;
1422  menu->data = state.entry;
1423  if (multiple)
1424  menu->menu_tag = file_tag;
1425 
1426  menu->help = mutt_compile_help(helpstr, sizeof(helpstr), MENU_FOLDER,
1427 #ifdef USE_NNTP
1429 #endif
1430  FolderHelp);
1431  mutt_menu_push_current(menu);
1432 
1433  init_menu(&state, menu, title, sizeof(title), mailbox);
1434 
1435  int op;
1436  while (true)
1437  {
1438  switch (op = mutt_menu_loop(menu))
1439  {
1440  case OP_DESCEND_DIRECTORY:
1441  case OP_GENERIC_SELECT_ENTRY:
1442 
1443  if (state.entrylen == 0)
1444  {
1445  mutt_error(_("No files match the file mask"));
1446  break;
1447  }
1448 
1449  if (S_ISDIR(state.entry[menu->current].mode) ||
1450  (S_ISLNK(state.entry[menu->current].mode) &&
1451  link_is_dir(mutt_b2s(&LastDir), state.entry[menu->current].name))
1452 #ifdef USE_IMAP
1453  || state.entry[menu->current].inferiors
1454 #endif
1455  )
1456  {
1457  /* make sure this isn't a MH or maildir mailbox */
1458  if (mailbox)
1459  {
1460  mutt_buffer_strcpy(buf, state.entry[menu->current].name);
1462  }
1463 #ifdef USE_IMAP
1464  else if (state.imap_browse)
1465  {
1466  mutt_buffer_strcpy(buf, state.entry[menu->current].name);
1467  }
1468 #endif
1469  else
1470  {
1472  state.entry[menu->current].name);
1473  }
1474 
1475  enum MailboxType magic = mx_path_probe(mutt_b2s(buf));
1476  if ((op == OP_DESCEND_DIRECTORY) || (magic == MUTT_MAILBOX_ERROR) ||
1477  (magic == MUTT_UNKNOWN)
1478 #ifdef USE_IMAP
1479  || state.entry[menu->current].inferiors
1480 #endif
1481  )
1482  {
1483  /* save the old directory */
1484  mutt_buffer_copy(OldLastDir, &LastDir);
1485 
1486  if (mutt_str_strcmp(state.entry[menu->current].name, "..") == 0)
1487  {
1488  size_t lastdirlen = mutt_buffer_len(&LastDir);
1489  if ((lastdirlen > 1) &&
1490  (mutt_str_strcmp("..", mutt_b2s(&LastDir) + lastdirlen - 2) == 0))
1491  {
1492  mutt_buffer_addstr(&LastDir, "/..");
1493  }
1494  else
1495  {
1496  char *p = NULL;
1497  if (lastdirlen > 1)
1498  p = strrchr(mutt_b2s(&LastDir) + 1, '/');
1499 
1500  if (p)
1501  {
1502  *p = '\0';
1504  }
1505  else
1506  {
1507  if (mutt_b2s(&LastDir)[0] == '/')
1508  mutt_buffer_strcpy(&LastDir, "/");
1509  else
1510  mutt_buffer_addstr(&LastDir, "/..");
1511  }
1512  }
1513  }
1514  else if (mailbox)
1515  {
1516  mutt_buffer_strcpy(&LastDir, state.entry[menu->current].name);
1518  }
1519 #ifdef USE_IMAP
1520  else if (state.imap_browse)
1521  {
1522  mutt_buffer_strcpy(&LastDir, state.entry[menu->current].name);
1523  /* tack on delimiter here */
1524 
1525  /* special case "" needs no delimiter */
1526  struct Url *url = url_parse(state.entry[menu->current].name);
1527  if (url->path && (state.entry[menu->current].delim != '\0'))
1528  {
1529  mutt_buffer_addch(&LastDir, state.entry[menu->current].delim);
1530  }
1531  url_free(&url);
1532  }
1533 #endif
1534  else
1535  {
1537  state.entry[menu->current].name);
1538  mutt_buffer_copy(&LastDir, tmp);
1539  }
1540 
1541  destroy_state(&state);
1542  if (kill_prefix)
1543  {
1544  mutt_buffer_reset(prefix);
1545  kill_prefix = false;
1546  }
1547  mailbox = false;
1548 #ifdef USE_IMAP
1549  if (state.imap_browse)
1550  {
1551  init_state(&state, NULL);
1552  state.imap_browse = true;
1553  imap_browse(mutt_b2s(&LastDir), &state);
1554  browser_sort(&state);
1555  menu->data = state.entry;
1556  }
1557  else
1558 #endif
1559  {
1560  if (examine_directory(menu, &state, mutt_b2s(&LastDir), mutt_b2s(prefix)) == -1)
1561  {
1562  /* try to restore the old values */
1563  mutt_buffer_copy(&LastDir, OldLastDir);
1564  if (examine_directory(menu, &state, mutt_b2s(&LastDir),
1565  mutt_b2s(prefix)) == -1)
1566  {
1568  goto bail;
1569  }
1570  }
1571  /* resolve paths navigated from GUI */
1572  if (mutt_path_realpath(LastDir.data) == 0)
1573  break;
1574  }
1575 
1576  browser_highlight_default(&state, menu);
1577  init_menu(&state, menu, title, sizeof(title), mailbox);
1578  goto_swapper[0] = '\0';
1579  break;
1580  }
1581  }
1582  else if (op == OP_DESCEND_DIRECTORY)
1583  {
1584  mutt_error(_("%s is not a directory"), state.entry[menu->current].name);
1585  break;
1586  }
1587 
1588  if (mailbox || OptNews) /* USE_NNTP */
1589  {
1590  mutt_buffer_strcpy(file, state.entry[menu->current].name);
1592  }
1593 #ifdef USE_IMAP
1594  else if (state.imap_browse)
1595  mutt_buffer_strcpy(file, state.entry[menu->current].name);
1596 #endif
1597  else
1598  {
1600  state.entry[menu->current].name);
1601  }
1602  /* fallthrough */
1603 
1604  case OP_EXIT:
1605 
1606  if (multiple)
1607  {
1608  char **tfiles = NULL;
1609 
1610  if (menu->tagged)
1611  {
1612  *numfiles = menu->tagged;
1613  tfiles = mutt_mem_calloc(*numfiles, sizeof(char *));
1614  for (int i = 0, j = 0; i < state.entrylen; i++)
1615  {
1616  struct FolderFile ff = state.entry[i];
1617  if (ff.tagged)
1618  {
1621  tfiles[j++] = mutt_buffer_strdup(tmp);
1622  }
1623  }
1624  *files = tfiles;
1625  }
1626  else if (!mutt_buffer_is_empty(file)) /* no tagged entries. return selected entry */
1627  {
1628  *numfiles = 1;
1629  tfiles = mutt_mem_calloc(*numfiles, sizeof(char *));
1631  tfiles[0] = mutt_buffer_strdup(file);
1632  *files = tfiles;
1633  }
1634  }
1635 
1636  destroy_state(&state);
1637  goto bail;
1638 
1639  case OP_BROWSER_TELL:
1640  if (state.entrylen)
1641  mutt_message("%s", state.entry[menu->current].name);
1642  break;
1643 
1644 #ifdef USE_IMAP
1645  case OP_BROWSER_TOGGLE_LSUB:
1646  bool_str_toggle(NeoMutt->sub, "imap_list_subscribed", NULL);
1647 
1648  mutt_unget_event(0, OP_CHECK_NEW);
1649  break;
1650 
1651  case OP_CREATE_MAILBOX:
1652  if (!state.imap_browse)
1653  {
1654  mutt_error(_("Create is only supported for IMAP mailboxes"));
1655  break;
1656  }
1657 
1658  if (imap_mailbox_create(mutt_b2s(&LastDir)) == 0)
1659  {
1660  /* TODO: find a way to detect if the new folder would appear in
1661  * this window, and insert it without starting over. */
1662  destroy_state(&state);
1663  init_state(&state, NULL);
1664  state.imap_browse = true;
1665  imap_browse(mutt_b2s(&LastDir), &state);
1666  browser_sort(&state);
1667  menu->data = state.entry;
1668  browser_highlight_default(&state, menu);
1669  init_menu(&state, menu, title, sizeof(title), mailbox);
1670  }
1671  /* else leave error on screen */
1672  break;
1673 
1674  case OP_RENAME_MAILBOX:
1675  if (!state.entry[menu->current].imap)
1676  mutt_error(_("Rename is only supported for IMAP mailboxes"));
1677  else
1678  {
1679  int nentry = menu->current;
1680 
1681  if (imap_mailbox_rename(state.entry[nentry].name) >= 0)
1682  {
1683  destroy_state(&state);
1684  init_state(&state, NULL);
1685  state.imap_browse = true;
1686  imap_browse(mutt_b2s(&LastDir), &state);
1687  browser_sort(&state);
1688  menu->data = state.entry;
1689  browser_highlight_default(&state, menu);
1690  init_menu(&state, menu, title, sizeof(title), mailbox);
1691  }
1692  }
1693  break;
1694 
1695  case OP_DELETE_MAILBOX:
1696  if (!state.entry[menu->current].imap)
1697  mutt_error(_("Delete is only supported for IMAP mailboxes"));
1698  else
1699  {
1700  char msg[128];
1701  int nentry = menu->current;
1702 
1703  // TODO(sileht): It could be better to select INBOX instead. But I
1704  // don't want to manipulate Context/Mailboxes/mailbox->account here for now.
1705  // Let's just protect neomutt against crash for now. #1417
1707  state.entry[nentry].name) == 0)
1708  {
1709  mutt_error(_("Can't delete currently selected mailbox"));
1710  break;
1711  }
1712 
1713  snprintf(msg, sizeof(msg), _("Really delete mailbox \"%s\"?"),
1714  state.entry[nentry].name);
1715  if (mutt_yesorno(msg, MUTT_NO) == MUTT_YES)
1716  {
1717  if (imap_delete_mailbox(Context->mailbox, state.entry[nentry].name) == 0)
1718  {
1719  /* free the mailbox from the browser */
1720  FREE(&((state.entry)[nentry].name));
1721  FREE(&((state.entry)[nentry].desc));
1722  /* and move all other entries up */
1723  if ((nentry + 1) < state.entrylen)
1724  {
1725  memmove(state.entry + nentry, state.entry + nentry + 1,
1726  sizeof(struct FolderFile) * (state.entrylen - (nentry + 1)));
1727  }
1728  memset(&state.entry[state.entrylen - 1], 0, sizeof(struct FolderFile));
1729  state.entrylen--;
1730  mutt_message(_("Mailbox deleted"));
1731  init_menu(&state, menu, title, sizeof(title), mailbox);
1732  }
1733  else
1734  mutt_error(_("Mailbox deletion failed"));
1735  }
1736  else
1737  mutt_message(_("Mailbox not deleted"));
1738  }
1739  break;
1740 #endif
1741 
1742  case OP_GOTO_PARENT:
1743  case OP_CHANGE_DIRECTORY:
1744 
1745 #ifdef USE_NNTP
1746  if (OptNews)
1747  break;
1748 #endif
1749 
1750  mutt_buffer_copy(buf, &LastDir);
1751 #ifdef USE_IMAP
1752  if (!state.imap_browse)
1753 #endif
1754  {
1755  /* add '/' at the end of the directory name if not already there */
1756  size_t len = mutt_buffer_len(buf);
1757  if ((len > 0) && (mutt_b2s(&LastDir)[len - 1] != '/'))
1758  mutt_buffer_addch(buf, '/');
1759  }
1760 
1761  if (op == OP_CHANGE_DIRECTORY)
1762  {
1763  /* buf comes from the buffer pool, so defaults to size 1024 */
1764  int ret = mutt_buffer_get_field(_("Chdir to: "), buf, MUTT_FILE);
1765  if ((ret != 0) && mutt_buffer_is_empty(buf))
1766  break;
1767  }
1768  else if (op == OP_GOTO_PARENT)
1769  mutt_get_parent_path(mutt_b2s(buf), buf->data, buf->dsize);
1770 
1771  if (!mutt_buffer_is_empty(buf))
1772  {
1773  mailbox = false;
1775 #ifdef USE_IMAP
1776  if (imap_path_probe(mutt_b2s(buf), NULL) == MUTT_IMAP)
1777  {
1778  mutt_buffer_copy(&LastDir, buf);
1779  destroy_state(&state);
1780  init_state(&state, NULL);
1781  state.imap_browse = true;
1782  imap_browse(mutt_b2s(&LastDir), &state);
1783  browser_sort(&state);
1784  menu->data = state.entry;
1785  browser_highlight_default(&state, menu);
1786  init_menu(&state, menu, title, sizeof(title), mailbox);
1787  }
1788  else
1789 #endif
1790  {
1791  if (mutt_b2s(buf)[0] != '/')
1792  {
1793  /* in case dir is relative, make it relative to LastDir,
1794  * not current working dir */
1796  mutt_buffer_copy(buf, tmp);
1797  }
1798  /* Resolve path from <chdir>
1799  * Avoids buildup such as /a/b/../../c
1800  * Symlinks are always unraveled to keep code simple */
1801  if (mutt_path_realpath(buf->data) == 0)
1802  break;
1803 
1804  struct stat st;
1805  if (stat(mutt_b2s(buf), &st) == 0)
1806  {
1807  if (S_ISDIR(st.st_mode))
1808  {
1809  destroy_state(&state);
1810  if (examine_directory(menu, &state, mutt_b2s(buf), mutt_b2s(prefix)) == 0)
1811  mutt_buffer_copy(&LastDir, buf);
1812  else
1813  {
1814  mutt_error(_("Error scanning directory"));
1815  if (examine_directory(menu, &state, mutt_b2s(&LastDir),
1816  mutt_b2s(prefix)) == -1)
1817  {
1818  goto bail;
1819  }
1820  }
1821  browser_highlight_default(&state, menu);
1822  init_menu(&state, menu, title, sizeof(title), mailbox);
1823  }
1824  else
1825  mutt_error(_("%s is not a directory"), mutt_b2s(buf));
1826  }
1827  else
1828  mutt_perror(mutt_b2s(buf));
1829  }
1830  }
1831  break;
1832 
1833  case OP_ENTER_MASK:
1834  {
1835  mutt_buffer_strcpy(buf, C_Mask ? C_Mask->pattern : NULL);
1836  if (mutt_get_field(_("File Mask: "), buf->data, buf->dsize, MUTT_COMP_NO_FLAGS) != 0)
1837  break;
1838 
1839  mutt_buffer_fix_dptr(buf);
1840 
1841  mailbox = false;
1842  /* assume that the user wants to see everything */
1843  if (mutt_buffer_is_empty(buf))
1844  mutt_buffer_strcpy(buf, ".");
1845 
1846  struct Buffer errmsg = { 0 };
1847  int rc = cs_subset_str_string_set(NeoMutt->sub, "mask", mutt_b2s(buf), NULL);
1848  if (CSR_RESULT(rc) != CSR_SUCCESS)
1849  {
1850  if (!mutt_buffer_is_empty(&errmsg))
1851  {
1852  mutt_error("%s", errmsg.data);
1853  FREE(&errmsg.data);
1854  }
1855  break;
1856  }
1857 
1858  destroy_state(&state);
1859 #ifdef USE_IMAP
1860  if (state.imap_browse)
1861  {
1862  init_state(&state, NULL);
1863  state.imap_browse = true;
1864  imap_browse(mutt_b2s(&LastDir), &state);
1865  browser_sort(&state);
1866  menu->data = state.entry;
1867  init_menu(&state, menu, title, sizeof(title), mailbox);
1868  }
1869  else
1870 #endif
1871  if (examine_directory(menu, &state, mutt_b2s(&LastDir), NULL) == 0)
1872  init_menu(&state, menu, title, sizeof(title), mailbox);
1873  else
1874  {
1875  mutt_error(_("Error scanning directory"));
1876  goto bail;
1877  }
1878  kill_prefix = false;
1879  if (state.entrylen == 0)
1880  {
1881  mutt_error(_("No files match the file mask"));
1882  break;
1883  }
1884  break;
1885  }
1886 
1887  case OP_SORT:
1888  case OP_SORT_REVERSE:
1889 
1890  {
1891  bool resort = true;
1892  int sort = -1;
1893  int reverse = (op == OP_SORT_REVERSE);
1894 
1895  switch (mutt_multi_choice(
1896  (reverse) ?
1897  /* L10N: The highlighted letters must match the "Sort" options */
1898  _("Reverse sort by (d)ate, (a)lpha, si(z)e, d(e)scription, "
1899  "(c)ount, ne(w) count, or do(n)'t sort?") :
1900  /* L10N: The highlighted letters must match the "Reverse Sort" options */
1901  _("Sort by (d)ate, (a)lpha, si(z)e, d(e)scription, (c)ount, "
1902  "ne(w) count, or do(n)'t sort?"),
1903  /* L10N: These must match the highlighted letters from "Sort" and "Reverse Sort" */
1904  _("dazecwn")))
1905  {
1906  case -1: /* abort */
1907  resort = false;
1908  break;
1909 
1910  case 1: /* (d)ate */
1911  sort = SORT_DATE;
1912  break;
1913 
1914  case 2: /* (a)lpha */
1915  sort = SORT_SUBJECT;
1916  break;
1917 
1918  case 3: /* si(z)e */
1919  sort = SORT_SIZE;
1920  break;
1921 
1922  case 4: /* d(e)scription */
1923  sort = SORT_DESC;
1924  break;
1925 
1926  case 5: /* (c)ount */
1927  sort = SORT_COUNT;
1928  break;
1929 
1930  case 6: /* ne(w) count */
1931  sort = SORT_UNREAD;
1932  break;
1933 
1934  case 7: /* do(n)'t sort */
1935  sort = SORT_ORDER;
1936  resort = false;
1937  break;
1938  }
1939  if (resort)
1940  {
1941  sort |= reverse ? SORT_REVERSE : 0;
1942  cs_subset_str_native_set(NeoMutt->sub, "sort_browser", sort, NULL);
1943  browser_sort(&state);
1944  browser_highlight_default(&state, menu);
1945  menu->redraw = REDRAW_FULL;
1946  }
1947  else
1948  {
1949  cs_subset_str_native_set(NeoMutt->sub, "sort_browser", sort, NULL);
1950  }
1951  break;
1952  }
1953 
1954  case OP_TOGGLE_MAILBOXES:
1955  case OP_BROWSER_GOTO_FOLDER:
1956  case OP_CHECK_NEW:
1957  if (op == OP_TOGGLE_MAILBOXES)
1958  mailbox = !mailbox;
1959 
1960  if (op == OP_BROWSER_GOTO_FOLDER)
1961  {
1962  /* When in mailboxes mode, disables this feature */
1963  if (C_Folder)
1964  {
1965  mutt_debug(LL_DEBUG3, "= hit! Folder: %s, LastDir: %s\n", C_Folder,
1966  mutt_b2s(&LastDir));
1967  if (goto_swapper[0] == '\0')
1968  {
1970  {
1971  /* Stores into goto_swapper LastDir, and swaps to C_Folder */
1972  mutt_str_strfcpy(goto_swapper, mutt_b2s(&LastDir), sizeof(goto_swapper));
1975  }
1976  }
1977  else
1978  {
1980  mutt_buffer_strcpy(&LastDir, goto_swapper);
1981  goto_swapper[0] = '\0';
1982  }
1983  }
1984  }
1985  destroy_state(&state);
1986  mutt_buffer_reset(prefix);
1987  kill_prefix = false;
1988 
1989  if (mailbox)
1990  {
1991  examine_mailboxes(menu, &state);
1992  }
1993 #ifdef USE_IMAP
1994  else if (imap_path_probe(mutt_b2s(&LastDir), NULL) == MUTT_IMAP)
1995  {
1996  init_state(&state, NULL);
1997  state.imap_browse = true;
1998  imap_browse(mutt_b2s(&LastDir), &state);
1999  browser_sort(&state);
2000  menu->data = state.entry;
2001  }
2002 #endif
2003  else if (examine_directory(menu, &state, mutt_b2s(&LastDir), mutt_b2s(prefix)) == -1)
2004  goto bail;
2005  init_menu(&state, menu, title, sizeof(title), mailbox);
2006  break;
2007 
2008  case OP_MAILBOX_LIST:
2010  break;
2011 
2012  case OP_BROWSER_NEW_FILE:
2013  mutt_buffer_printf(buf, "%s/", mutt_b2s(&LastDir));
2014  /* buf comes from the buffer pool, so defaults to size 1024 */
2015  if (mutt_buffer_get_field(_("New file name: "), buf, MUTT_FILE) == 0)
2016  {
2017  mutt_buffer_copy(file, buf);
2018  destroy_state(&state);
2019  goto bail;
2020  }
2021  break;
2022 
2023  case OP_BROWSER_VIEW_FILE:
2024  if (state.entrylen == 0)
2025  {
2026  mutt_error(_("No files match the file mask"));
2027  break;
2028  }
2029 
2030 #ifdef USE_IMAP
2031  if (state.entry[menu->current].selectable)
2032  {
2033  mutt_buffer_strcpy(file, state.entry[menu->current].name);
2034  destroy_state(&state);
2035  goto bail;
2036  }
2037  else
2038 #endif
2039  if (S_ISDIR(state.entry[menu->current].mode) ||
2040  (S_ISLNK(state.entry[menu->current].mode) &&
2041  link_is_dir(mutt_b2s(&LastDir), state.entry[menu->current].name)))
2042  {
2043  mutt_error(_("Can't view a directory"));
2044  break;
2045  }
2046  else
2047  {
2048  char buf2[PATH_MAX];
2049 
2051  state.entry[menu->current].name, sizeof(buf2));
2052  struct Body *b = mutt_make_file_attach(buf2);
2053  if (b)
2054  {
2055  mutt_view_attachment(NULL, b, MUTT_VA_REGULAR, NULL, NULL, menu->win_index);
2056  mutt_body_free(&b);
2057  menu->redraw = REDRAW_FULL;
2058  }
2059  else
2060  mutt_error(_("Error trying to view file"));
2061  }
2062  break;
2063 
2064 #ifdef USE_NNTP
2065  case OP_CATCHUP:
2066  case OP_UNCATCHUP:
2067  if (OptNews)
2068  {
2069  struct FolderFile *ff = &state.entry[menu->current];
2070  struct NntpMboxData *mdata = NULL;
2071 
2073  if (rc < 0)
2074  break;
2075 
2076  if (op == OP_CATCHUP)
2078  else
2080 
2081  if (mdata)
2082  {
2084  if ((menu->current + 1) < menu->max)
2085  menu->current++;
2086  menu->redraw = REDRAW_MOTION_RESYNC;
2087  }
2088  if (rc)
2089  menu->redraw = REDRAW_INDEX;
2091  }
2092  break;
2093 
2094  case OP_LOAD_ACTIVE:
2095  if (OptNews)
2096  {
2097  struct NntpAccountData *adata = CurrentNewsSrv;
2098 
2099  if (nntp_newsrc_parse(adata) < 0)
2100  break;
2101 
2102  for (size_t i = 0; i < adata->groups_num; i++)
2103  {
2104  struct NntpMboxData *mdata = adata->groups_list[i];
2105  if (mdata)
2106  mdata->deleted = true;
2107  }
2108  nntp_active_fetch(adata, true);
2109  nntp_newsrc_update(adata);
2110  nntp_newsrc_close(adata);
2111 
2112  destroy_state(&state);
2113  if (mailbox)
2114  examine_mailboxes(menu, &state);
2115  else
2116  {
2117  if (examine_directory(menu, &state, NULL, NULL) == -1)
2118  break;
2119  }
2120  init_menu(&state, menu, title, sizeof(title), mailbox);
2121  }
2122  break;
2123 #endif /* USE_NNTP */
2124 
2125 #if defined(USE_IMAP) || defined(USE_NNTP)
2126  case OP_BROWSER_SUBSCRIBE:
2127  case OP_BROWSER_UNSUBSCRIBE:
2128 #endif
2129 #ifdef USE_NNTP
2130  case OP_SUBSCRIBE_PATTERN:
2131  case OP_UNSUBSCRIBE_PATTERN:
2132  if (OptNews)
2133  {
2134  struct NntpAccountData *adata = CurrentNewsSrv;
2135  regex_t rx;
2136  memset(&rx, 0, sizeof(rx));
2137  char *s = buf->data;
2138  int i = menu->current;
2139 
2140  if ((op == OP_SUBSCRIBE_PATTERN) || (op == OP_UNSUBSCRIBE_PATTERN))
2141  {
2142  char tmp2[256];
2143 
2144  mutt_buffer_reset(buf);
2145  if (op == OP_SUBSCRIBE_PATTERN)
2146  snprintf(tmp2, sizeof(tmp2), _("Subscribe pattern: "));
2147  else
2148  snprintf(tmp2, sizeof(tmp2), _("Unsubscribe pattern: "));
2149  /* buf comes from the buffer pool, so defaults to size 1024 */
2150  if ((mutt_buffer_get_field(tmp2, buf, MUTT_COMP_NO_FLAGS) != 0) ||
2151  mutt_buffer_is_empty(buf))
2152  {
2153  break;
2154  }
2155 
2156  int err = REG_COMP(&rx, s, REG_NOSUB);
2157  if (err != 0)
2158  {
2159  regerror(err, &rx, buf->data, buf->dsize);
2160  regfree(&rx);
2161  mutt_error("%s", mutt_b2s(buf));
2162  break;
2163  }
2164  menu->redraw = REDRAW_FULL;
2165  i = 0;
2166  }
2167  else if (state.entrylen == 0)
2168  {
2169  mutt_error(_("No newsgroups match the mask"));
2170  break;
2171  }
2172 
2173  int rc = nntp_newsrc_parse(adata);
2174  if (rc < 0)
2175  break;
2176 
2177  for (; i < state.entrylen; i++)
2178  {
2179  struct FolderFile *ff = &state.entry[i];
2180 
2181  if ((op == OP_BROWSER_SUBSCRIBE) || (op == OP_BROWSER_UNSUBSCRIBE) ||
2182  (regexec(&rx, ff->name, 0, NULL, 0) == 0))
2183  {
2184  if ((op == OP_BROWSER_SUBSCRIBE) || (op == OP_SUBSCRIBE_PATTERN))
2185  mutt_newsgroup_subscribe(adata, ff->name);
2186  else
2187  mutt_newsgroup_unsubscribe(adata, ff->name);
2188  }
2189  if ((op == OP_BROWSER_SUBSCRIBE) || (op == OP_BROWSER_UNSUBSCRIBE))
2190  {
2191  if ((menu->current + 1) < menu->max)
2192  menu->current++;
2193  menu->redraw = REDRAW_MOTION_RESYNC;
2194  break;
2195  }
2196  }
2197  if (op == OP_SUBSCRIBE_PATTERN)
2198  {
2199  for (size_t j = 0; adata && (j < adata->groups_num); j++)
2200  {
2201  struct NntpMboxData *mdata = adata->groups_list[j];
2202  if (mdata && mdata->group && !mdata->subscribed)
2203  {
2204  if (regexec(&rx, mdata->group, 0, NULL, 0) == 0)
2205  {
2206  mutt_newsgroup_subscribe(adata, mdata->group);
2207  add_folder(menu, &state, mdata->group, NULL, NULL, NULL, mdata);
2208  }
2209  }
2210  }
2211  init_menu(&state, menu, title, sizeof(title), mailbox);
2212  }
2213  if (rc > 0)
2214  menu->redraw = REDRAW_FULL;
2215  nntp_newsrc_update(adata);
2216  nntp_clear_cache(adata);
2217  nntp_newsrc_close(adata);
2218  if ((op != OP_BROWSER_SUBSCRIBE) && (op != OP_BROWSER_UNSUBSCRIBE))
2219  regfree(&rx);
2220  }
2221 #ifdef USE_IMAP
2222  else
2223 #endif /* USE_IMAP && USE_NNTP */
2224 #endif /* USE_NNTP */
2225 #ifdef USE_IMAP
2226  {
2227  char tmp2[256];
2228  mutt_str_strfcpy(tmp2, state.entry[menu->current].name, sizeof(tmp2));
2229  mutt_expand_path(tmp2, sizeof(tmp2));
2230  imap_subscribe(tmp2, (op == OP_BROWSER_SUBSCRIBE));
2231  }
2232 #endif /* USE_IMAP */
2233  }
2234  }
2235 
2236 bail:
2237  mutt_buffer_pool_release(&OldLastDir);
2240  mutt_buffer_pool_release(&prefix);
2241 
2242  if (menu)
2243  {
2244  mutt_menu_pop_current(menu);
2245  mutt_menu_free(&menu);
2246  dialog_pop();
2248  mutt_window_free(&dlg);
2249  }
2250 
2251  goto_swapper[0] = '\0';
2252 }
mode_t mode
Definition: browser.h:63
The "current" mailbox.
Definition: context.h:36
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:191
WHERE bool C_StatusOnTop
Config: Display the status bar at the top.
Definition: globals.h:255
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:348
#define REDRAW_FULL
Redraw everything.
Definition: mutt_menu.h:47
bool mutt_mailbox_list(void)
List the mailboxes with new mail.
Definition: mutt_mailbox.c:230
#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:343
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: mutt_menu.h:82
#define CSR_RESULT(x)
Definition: set.h:53
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2511
static void destroy_state(struct BrowserState *state)
Free the BrowserState.
Definition: browser.c:134
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
Dialog (nested Windows) displayed to the user.
Definition: mutt_window.h:68
#define mutt_message(...)
Definition: logging.h:83
int imap_delete_mailbox(struct Mailbox *m, char *path)
Delete a mailbox.
Definition: imap.c:649
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition: url.h:66
void nntp_clear_cache(struct NntpAccountData *adata)
Clear the NNTP cache.
Definition: newsrc.c:844
Window uses all available vertical space.
Definition: mutt_window.h:33
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
static int file_tag(struct Menu *menu, int sel, int act)
Tag an entry in the menu - Implements Menu::menu_tag()
Definition: browser.c:1111
void dialog_pop(void)
Hide a Window from the user.
Definition: mutt_window.c:623
struct NntpMboxData * mutt_newsgroup_uncatchup(struct Mailbox *m, struct NntpAccountData *adata, char *group)
Uncatchup newsgroup.
Definition: newsrc.c:1336
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:95
void dialog_push(struct MuttWindow *dlg)
Display a Window to the user.
Definition: mutt_window.c:603
General file/mailbox browser.
Definition: keymap.h:75
char * mutt_buffer_strdup(struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
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:633
String manipulation buffer.
Definition: buffer.h:33
struct NntpMboxData * mutt_newsgroup_subscribe(struct NntpAccountData *adata, char *group)
Subscribe newsgroup.
Definition: newsrc.c:1247
void mutt_unget_event(int ch, int op)
Return a keystroke to the input buffer.
Definition: curs_lib.c:807
#define _(a)
Definition: message.h:28
Mailbox wasn&#39;t recognised.
Definition: mailbox.h:46
Error occurred examining Mailbox.
Definition: mailbox.h:45
int imap_mailbox_create(const char *path)
Create a new IMAP mailbox.
Definition: browse.c:382
A division of the screen.
Definition: mutt_window.h:86
void nntp_newsrc_close(struct NntpAccountData *adata)
Unlock and close .newsrc file.
Definition: newsrc.c:123
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:75
static void init_lastdir(void)
Initialise the browser directories.
Definition: browser.c:108
void url_free(struct Url **ptr)
Free the contents of a URL.
Definition: url.c:157
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
static void folder_make_entry(char *buf, size_t buflen, struct Menu *menu, int line)
Format a menu item for the folder browser - Implements Menu::menu_make_entry()
Definition: browser.c:953
View using default method.
Definition: mutt_attach.h:42
static int select_file_search(struct Menu *menu, regex_t *rx, int line)
Menu search callback for matching files - Implements Menu::menu_search()
Definition: browser.c:938
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:393
Container for Accounts, Notifications.
Definition: neomutt.h:35
void(* menu_make_entry)(char *buf, size_t buflen, struct Menu *menu, int line)
Format a item for a menu.
Definition: mutt_menu.h:120
NNTP-specific Account data -.
Definition: lib.h:77
bool notify_observer_add(struct Notify *notify, observer_t callback, void *global_data)
Add an observer to an object.
Definition: notify.c:154
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:90
bool subscribed
Definition: lib.h:149
The body of an email.
Definition: body.h:34
An Index Window containing a selection list.
Definition: mutt_window.h:72
#define MUTT_SEL_FOLDER
Select a local directory.
Definition: browser.h:47
char * folder
Definition: browser.h:102
bool selectable
Definition: browser.h:81
void mutt_window_free(struct MuttWindow **ptr)
Free a Window and its children.
Definition: mutt_window.c:75
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:290
Sort by the size of the email.
Definition: sort2.h:51
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:132
int nntp_active_fetch(struct NntpAccountData *adata, bool mark_new)
Fetch list of all newsgroups from server.
Definition: nntp.c:2058
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:376
static struct Buffer LastDirBackup
Definition: browser.c:101
struct Mailbox * mailbox
Definition: context.h:50
struct Body * mutt_make_file_attach(const char *path)
Create a file attachment.
Definition: sendlib.c:1649
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:62
struct MuttWindow * win_ibar
Definition: mutt_menu.h:96
Sort by the order the messages appear in the mailbox.
Definition: sort2.h:55
static int examine_mailboxes(struct Menu *menu, struct BrowserState *state)
Get list of mailboxes/subscribed newsgroups.
Definition: browser.c:836
char * name
Definition: browser.h:70
#define REG_COMP(preg, regex, cflags)
Compile a regular expression.
Definition: regex3.h:52
WHERE char * HomeDir
User&#39;s home directory.
Definition: globals.h:49
char * group
Definition: lib.h:142
WHERE char * CurrentFolder
Currently selected mailbox.
Definition: globals.h:54
bool imap
Definition: browser.h:80
void * mdata
Driver specific data.
Definition: mailbox.h:135
&#39;Maildir&#39; Mailbox type
Definition: mailbox.h:50
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
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:37
Window has a fixed size.
Definition: mutt_window.h:42
#define REDRAW_MOTION_RESYNC
Redraw any changing the menu selection.
Definition: mutt_menu.h:44
#define mutt_b2s(buf)
Definition: buffer.h:41
const char * mutt_path_getcwd(struct Buffer *cwd)
Get the current working directory.
Definition: path.c:560
int mutt_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question.
Definition: curs_lib.c:906
Browser entry representing a folder/dir.
Definition: browser.h:61
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:91
struct MuttWindow * mutt_window_new(enum MuttWindowOrientation orient, enum MuttWindowSize size, int rows, int cols)
Create a new Window.
Definition: mutt_window.c:57
WHERE char * C_Folder
Config: Base folder for a set of mailboxes.
Definition: globals.h:119
bool notify_observer_remove(struct Notify *notify, observer_t callback, void *global_data)
Remove an observer from an object.
Definition: notify.c:186
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:50
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:39
#define MUTT_WIN_SIZE_UNLIMITED
Use as much space as possible.
Definition: mutt_window.h:47
short rows
Number of rows, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:55
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
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
int bool_str_toggle(struct ConfigSubset *sub, const char *name, struct Buffer *err)
Toggle the value of a bool.
Definition: bool.c:239
size_t mutt_path_realpath(char *buf)
resolve path, unraveling symlinks
Definition: path.c:437
unsigned int groups_num
Definition: lib.h:100
static void browser_sort(struct BrowserState *state)
Sort the entries in the browser.
Definition: browser.c:316
&#39;mmdf&#39; Mailbox type
Definition: mailbox.h:48
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:773
int nntp_newsrc_parse(struct NntpAccountData *adata)
Parse .newsrc file.
Definition: newsrc.c:167
&#39;MH&#39; Mailbox type
Definition: mailbox.h:49
struct NntpMboxData * mutt_newsgroup_unsubscribe(struct NntpAccountData *adata, char *group)
Unsubscribe newsgroup.
Definition: newsrc.c:1271
int pagelen
Number of entries per screen.
Definition: mutt_menu.h:92
struct Notify * notify
Notifications handler.
Definition: neomutt.h:37
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:46
NNTP-specific Mailbox data -.
Definition: lib.h:140
int tagged
Number of tagged entries.
Definition: mutt_menu.h:111
#define MUTT_FILE
Do file completion.
Definition: mutt.h:64
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:73
int max
Number of entries in the menu.
Definition: mutt_menu.h:88
void mutt_window_add_child(struct MuttWindow *parent, struct MuttWindow *child)
Add a child to Window.
Definition: mutt_window.c:471
int(* menu_tag)(struct Menu *menu, int sel, int act)
Tag some menu items.
Definition: mutt_menu.h:137
&#39;mbox&#39; Mailbox type
Definition: mailbox.h:47
size_t entrylen
number of real entries
Definition: browser.h:98
#define mutt_buffer_get_field(field, buf, complete)
Definition: curs_lib.h:84
MuttRedrawFlags redraw
When to redraw the screen.
Definition: mutt_menu.h:89
int(* menu_search)(struct Menu *menu, regex_t *rx, int line)
Search a menu for a item matching a regex.
Definition: mutt_menu.h:129
#define MUTT_SEL_MAILBOX
Select a mailbox.
Definition: browser.h:45
char * title
Title of this menu.
Definition: mutt_menu.h:84
static void browser_highlight_default(struct BrowserState *state, struct Menu *menu)
Decide which browser item should be highlighted.
Definition: browser.c:984
static int examine_directory(struct Menu *menu, struct BrowserState *state, const char *d, const char *prefix)
Get list of all files/newsgroups with mask.
Definition: browser.c:711
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition: mx.c:1310
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:341
MailboxType
Supported mailbox formats.
Definition: mailbox.h:42
bool deleted
Definition: lib.h:152
Sort by the number of unread emails.
Definition: sort2.h:66
WHERE char * C_Spoolfile
Config: Inbox.
Definition: globals.h:144
void mutt_browser_select_dir(const char *f)
Remember the last directory selected.
Definition: browser.c:1136
static void init_menu(struct BrowserState *state, struct Menu *menu, char *title, size_t titlelen, bool mailbox)
Set up a new menu.
Definition: browser.c:1010
#define REDRAW_INDEX
Redraw the index.
Definition: mutt_menu.h:42
#define mutt_error(...)
Definition: logging.h:84
WHERE struct Regex * C_Mask
Config: Only display files/dirs matching this regex in the browser.
Definition: globals.h:173
int imap_browse(const char *path, struct BrowserState *state)
IMAP hook into the folder browser.
Definition: browse.c:184
Sort by the folder&#39;s description.
Definition: sort2.h:70
void ** groups_list
Definition: lib.h:102
#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:434
void * data
Extra data for the current menu.
Definition: mutt_menu.h:86
int mutt_dlg_browser_observer(struct NotifyCallback *nc)
Listen for config changes affecting the Browser menu - Implements observer_t()
Definition: browser.c:1151
static struct Buffer LastDir
Definition: browser.c:100
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:79
Sort by number of emails in a folder.
Definition: sort2.h:65
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
bool tagged
Definition: browser.h:86
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:38
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
int nntp_newsrc_update(struct NntpAccountData *adata)
Update .newsrc file.
Definition: newsrc.c:445
int current
Current entry.
Definition: mutt_menu.h:87
char * pattern
printable version
Definition: regex3.h:59
Sort by the date the email was sent.
Definition: sort2.h:50
static void init_state(struct BrowserState *state, struct Menu *menu)
Initialise a browser state.
Definition: browser.c:690
struct NntpMboxData * mutt_newsgroup_catchup(struct Mailbox *m, struct NntpAccountData *adata, char *group)
Catchup newsgroup.
Definition: newsrc.c:1297
struct MuttWindow * win_index
Definition: mutt_menu.h:95
bool inferiors
Definition: browser.h:82
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:86
char * mutt_compile_help(char *buf, size_t buflen, enum MenuType menu, const struct Mapping *items)
Create the text for the help menu.
Definition: help.c:116
static const struct Mapping FolderHelp[]
Definition: browser.c:78
Window wants as much space as possible.
Definition: mutt_window.h:43
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
static struct Mapping FolderNewsHelp[]
Definition: browser.c:88
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:52
bool imap_browse
Definition: browser.h:101
Index Bar containing status info about the Index.
Definition: mutt_window.h:73
enum WindowType type
Window type, e.g. WT_SIDEBAR.
Definition: mutt_window.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:1637
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:44
char delim
Definition: browser.h:78
char * help
Quickref for the current menu.
Definition: mutt_menu.h:85
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:638
Sort by the email&#39;s subject.
Definition: sort2.h:53
struct FolderFile * entry
Definition: browser.h:97
Log at debug level 3.
Definition: logging.h:42
#define SORT_MASK
Mask for the sort id.
Definition: sort2.h:85
int imap_subscribe(char *path, bool subscribe)
Subscribe to a mailbox.
Definition: imap.c:1404
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:199
+ 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 1136 of file browser.c.

1137 {
1138  init_lastdir();
1139 
1141 
1142  /* Method that will fetch the parent path depending on the type of the path. */
1143  char buf[PATH_MAX];
1144  mutt_get_parent_path(mutt_b2s(&LastDirBackup), buf, sizeof(buf));
1145  mutt_buffer_strcpy(&LastDir, buf);
1146 }
static void init_lastdir(void)
Initialise the browser directories.
Definition: browser.c:108
static struct Buffer LastDirBackup
Definition: browser.c:101
#define mutt_b2s(buf)
Definition: buffer.h:41
#define PATH_MAX
Definition: mutt.h:50
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:100
void mutt_get_parent_path(const char *path, char *buf, size_t buflen)
Find the parent of a path (or mailbox)
Definition: muttlib.c:1637
+ 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 122 of file browser.c.

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

Variable Documentation

◆ C_BrowserAbbreviateMailboxes

bool C_BrowserAbbreviateMailboxes

Config: Abbreviate mailboxes using '~' and '=' in the browser.

Definition at line 70 of file browser.c.

◆ C_FolderFormat

char* C_FolderFormat

Config: printf-like format string for the browser's display of folders.

Definition at line 71 of file browser.c.

◆ C_GroupIndexFormat

char* C_GroupIndexFormat

Config: (nntp) printf-like format string for the browser's display of newsgroups.

Definition at line 72 of file browser.c.

◆ C_NewsgroupsCharset

char* C_NewsgroupsCharset

Config: (nntp) Character set of newsgroups' descriptions.

Definition at line 73 of file browser.c.

◆ C_ShowOnlyUnread

bool C_ShowOnlyUnread

Config: (nntp) Only show subscribed newsgroups with unread articles.

Definition at line 74 of file browser.c.

◆ C_SortBrowser

short C_SortBrowser

Config: Sort method for the browser.

Definition at line 75 of file browser.c.

◆ C_VfolderFormat

char* C_VfolderFormat

Config: (notmuch) printf-like format string for the browser's display of virtual folders.

Definition at line 76 of file browser.c.