NeoMutt  2020-11-20
Teaching an old dog new tricks
DOXYGEN
browser.c File Reference

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

#include "config.h"
#include <dirent.h>
#include <errno.h>
#include <grp.h>
#include <limits.h>
#include <locale.h>
#include <pwd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include "mutt/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "conn/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "browser.h"
#include "send/lib.h"
#include "context.h"
#include "format_flags.h"
#include "keymap.h"
#include "mutt_attach.h"
#include "mutt_globals.h"
#include "mutt_mailbox.h"
#include "mutt_menu.h"
#include "muttlib.h"
#include "mx.h"
#include "opcodes.h"
#include "options.h"
#include "imap/lib.h"
#include "nntp/lib.h"
+ Include dependency graph for browser.c:

Go to the source code of this file.

Functions

static void init_lastdir (void)
 Initialise the browser directories. More...
 
void mutt_browser_cleanup (void)
 Clean up working Buffers. More...
 
static void destroy_state (struct BrowserState *state)
 Free the BrowserState. More...
 
static int browser_compare_subject (const void *a, const void *b)
 Compare the subject of two browser entries - Implements sort_t. More...
 
static int browser_compare_order (const void *a, const void *b)
 Compare the order of creation of two browser entries - Implements sort_t. More...
 
static int browser_compare_desc (const void *a, const void *b)
 Compare the descriptions of two browser entries - Implements sort_t. More...
 
static int browser_compare_date (const void *a, const void *b)
 Compare the date of two browser entries - Implements sort_t. More...
 
static int browser_compare_size (const void *a, const void *b)
 Compare the size of two browser entries - Implements sort_t. More...
 
static int browser_compare_count (const void *a, const void *b)
 Compare the message count of two browser entries - Implements sort_t. More...
 
static int browser_compare_count_new (const void *a, const void *b)
 Compare the new count of two browser entries - Implements sort_t. More...
 
static int browser_compare (const void *a, const void *b)
 Sort the items in the browser - Implements sort_t. More...
 
static void browser_sort (struct BrowserState *state)
 Sort the entries in the browser. More...
 
static bool link_is_dir (const char *folder, const char *path)
 Does this symlink point to a directory? More...
 
static const char * folder_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Format a string for the folder browser - Implements format_t. More...
 
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. More...
 
static void init_state (struct BrowserState *state, struct Menu *menu)
 Initialise a browser state. More...
 
static int examine_directory (struct Menu *menu, struct BrowserState *state, const char *d, const char *prefix)
 Get list of all files/newsgroups with mask. More...
 
static int examine_mailboxes (struct Menu *menu, struct BrowserState *state)
 Get list of mailboxes/subscribed newsgroups. More...
 
static int select_file_search (struct Menu *menu, regex_t *rx, int line)
 Menu search callback for matching files - Implements Menu::search() More...
 
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::make_entry() More...
 
static void browser_highlight_default (struct BrowserState *state, struct Menu *menu)
 Decide which browser item should be highlighted. More...
 
static void init_menu (struct BrowserState *state, struct Menu *menu, char *title, size_t titlelen, bool mailbox)
 Set up a new menu. More...
 
static int file_tag (struct Menu *menu, int sel, int act)
 Tag an entry in the menu - Implements Menu::tag() More...
 
void mutt_browser_select_dir (const char *f)
 Remember the last directory selected. More...
 
void mutt_buffer_select_file (struct Buffer *file, SelectFileFlags flags, char ***files, int *numfiles)
 Let the user select a file. More...
 
void mutt_select_file (char *file, size_t filelen, SelectFileFlags flags, char ***files, int *numfiles)
 Let the user select a file. 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...
 
short C_SortBrowser
 Config: Sort method for the browser. More...
 
static const struct Mapping FolderHelp []
 Help Bar for the File/Dir/Mailbox browser dialog. More...
 
static const struct Mapping FolderNewsHelp []
 Help Bar for the NNTP Mailbox browser dialog. More...
 
static struct Buffer LastDir = { 0 }
 
static struct Buffer LastDirBackup = { 0 }
 

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.c.

Function Documentation

◆ init_lastdir()

static void init_lastdir ( void  )
static

Initialise the browser directories.

These keep track of where the browser used to be looking.

Definition at line 109 of file browser.c.

110 {
111  static bool done = false;
112  if (!done)
113  {
116  done = true;
117  }
118 }
static struct Buffer LastDirBackup
Definition: browser.c:102
#define PATH_MAX
Definition: mutt.h:44
static struct Buffer LastDir
Definition: browser.c:101
void mutt_buffer_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:265
+ 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 123 of file browser.c.

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

◆ destroy_state()

static void destroy_state ( struct BrowserState state)
static

Free the BrowserState.

Parameters
stateState to free

Frees up the memory allocated for the local-global variables.

Definition at line 135 of file browser.c.

136 {
137  struct FolderFile *ff = NULL;
138  ARRAY_FOREACH(ff, &state->entry)
139  {
140  FREE(&ff->name);
141  FREE(&ff->desc);
142  }
143  ARRAY_FREE(&state->entry);
144 
145 #ifdef USE_IMAP
146  FREE(&state->folder);
147 #endif
148 }
char * desc
Definition: browser.h:67
#define ARRAY_FREE(head)
Release all memory.
Definition: array.h:198
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:206
struct BrowserStateEntry entry
Definition: browser.h:97
char * folder
Definition: browser.h:100
char * name
Definition: browser.h:66
Browser entry representing a folder/dir.
Definition: browser.h:57
#define FREE(x)
Definition: memory.h:40
+ Here is the caller graph for this function:

◆ browser_compare_subject()

static int browser_compare_subject ( const void *  a,
const void *  b 
)
static

Compare the subject of two browser entries - Implements sort_t.

Definition at line 153 of file browser.c.

154 {
155  const struct FolderFile *pa = (const struct FolderFile *) a;
156  const struct FolderFile *pb = (const struct FolderFile *) b;
157 
158  /* inbox should be sorted ahead of its siblings */
159  int r = mutt_inbox_cmp(pa->name, pb->name);
160  if (r == 0)
161  r = mutt_str_coll(pa->name, pb->name);
162  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
163 }
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:71
int mutt_str_coll(const char *a, const char *b)
Collate two strings (compare using locale), safely.
Definition: string.c:644
char * name
Definition: browser.h:66
Browser entry representing a folder/dir.
Definition: browser.h:57
int mutt_inbox_cmp(const char *a, const char *b)
do two folders share the same path and one is an inbox
Definition: muttlib.c:1593
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:81
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ browser_compare_order()

static int browser_compare_order ( const void *  a,
const void *  b 
)
static

Compare the order of creation of two browser entries - Implements sort_t.

Note
This only affects browsing mailboxes and is a no-op for folders.

Definition at line 170 of file browser.c.

171 {
172  const struct FolderFile *pa = (const struct FolderFile *) a;
173  const struct FolderFile *pb = (const struct FolderFile *) b;
174 
175  return ((C_SortBrowser & SORT_REVERSE) ? -1 : 1) * (pa->gen - pb->gen);
176 }
int gen
Definition: browser.h:87
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:71
Browser entry representing a folder/dir.
Definition: browser.h:57
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:81
+ Here is the caller graph for this function:

◆ browser_compare_desc()

static int browser_compare_desc ( const void *  a,
const void *  b 
)
static

Compare the descriptions of two browser entries - Implements sort_t.

Definition at line 181 of file browser.c.

182 {
183  const struct FolderFile *pa = (const struct FolderFile *) a;
184  const struct FolderFile *pb = (const struct FolderFile *) b;
185 
186  int r = mutt_str_coll(pa->desc, pb->desc);
187 
188  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
189 }
char * desc
Definition: browser.h:67
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:71
int mutt_str_coll(const char *a, const char *b)
Collate two strings (compare using locale), safely.
Definition: string.c:644
Browser entry representing a folder/dir.
Definition: browser.h:57
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:81
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ browser_compare_date()

static int browser_compare_date ( const void *  a,
const void *  b 
)
static

Compare the date of two browser entries - Implements sort_t.

Definition at line 194 of file browser.c.

195 {
196  const struct FolderFile *pa = (const struct FolderFile *) a;
197  const struct FolderFile *pb = (const struct FolderFile *) b;
198 
199  int r = pa->mtime - pb->mtime;
200 
201  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
202 }
time_t mtime
Definition: browser.h:61
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:71
Browser entry representing a folder/dir.
Definition: browser.h:57
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:81
+ Here is the caller graph for this function:

◆ browser_compare_size()

static int browser_compare_size ( const void *  a,
const void *  b 
)
static

Compare the size of two browser entries - Implements sort_t.

Definition at line 207 of file browser.c.

208 {
209  const struct FolderFile *pa = (const struct FolderFile *) a;
210  const struct FolderFile *pb = (const struct FolderFile *) b;
211 
212  int r = pa->size - pb->size;
213 
214  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
215 }
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:71
off_t size
Definition: browser.h:60
Browser entry representing a folder/dir.
Definition: browser.h:57
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:81
+ Here is the caller graph for this function:

◆ browser_compare_count()

static int browser_compare_count ( const void *  a,
const void *  b 
)
static

Compare the message count of two browser entries - Implements sort_t.

Definition at line 220 of file browser.c.

221 {
222  const struct FolderFile *pa = (const struct FolderFile *) a;
223  const struct FolderFile *pb = (const struct FolderFile *) b;
224 
225  int r = 0;
226  if (pa->has_mailbox && pb->has_mailbox)
227  r = pa->msg_count - pb->msg_count;
228  else if (pa->has_mailbox)
229  r = -1;
230  else
231  r = 1;
232 
233  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
234 }
bool has_mailbox
Definition: browser.h:80
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:71
Browser entry representing a folder/dir.
Definition: browser.h:57
int msg_count
total number of messages
Definition: browser.h:70
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:81
+ Here is the caller graph for this function:

◆ browser_compare_count_new()

static int browser_compare_count_new ( const void *  a,
const void *  b 
)
static

Compare the new count of two browser entries - Implements sort_t.

Definition at line 239 of file browser.c.

240 {
241  const struct FolderFile *pa = (const struct FolderFile *) a;
242  const struct FolderFile *pb = (const struct FolderFile *) b;
243 
244  int r = 0;
245  if (pa->has_mailbox && pb->has_mailbox)
246  r = pa->msg_unread - pb->msg_unread;
247  else if (pa->has_mailbox)
248  r = -1;
249  else
250  r = 1;
251 
252  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
253 }
int msg_unread
number of unread messages
Definition: browser.h:71
bool has_mailbox
Definition: browser.h:80
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:71
Browser entry representing a folder/dir.
Definition: browser.h:57
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:81
+ Here is the caller graph for this function:

◆ browser_compare()

static int browser_compare ( const void *  a,
const void *  b 
)
static

Sort the items in the browser - Implements sort_t.

Wild compare function that calls the others. It's useful because it provides a way to tell "../" is always on the top of the list, independently of the sort method.

Definition at line 262 of file browser.c.

263 {
264  const struct FolderFile *pa = (const struct FolderFile *) a;
265  const struct FolderFile *pb = (const struct FolderFile *) b;
266 
267  if ((mutt_str_coll(pa->desc, "../") == 0) || (mutt_str_coll(pa->desc, "..") == 0))
268  return -1;
269  if ((mutt_str_coll(pb->desc, "../") == 0) || (mutt_str_coll(pb->desc, "..") == 0))
270  return 1;
271 
272  switch (C_SortBrowser & SORT_MASK)
273  {
274  case SORT_COUNT:
275  return browser_compare_count(a, b);
276  case SORT_DATE:
277  return browser_compare_date(a, b);
278  case SORT_DESC:
279  return browser_compare_desc(a, b);
280  case SORT_SIZE:
281  return browser_compare_size(a, b);
282  case SORT_UNREAD:
283  return browser_compare_count_new(a, b);
284  case SORT_SUBJECT:
285  return browser_compare_subject(a, b);
286  default:
287  case SORT_ORDER:
288  return browser_compare_order(a, b);
289  }
290 }
static int browser_compare_date(const void *a, const void *b)
Compare the date of two browser entries - Implements sort_t.
Definition: browser.c:194
char * desc
Definition: browser.h:67
static int browser_compare_order(const void *a, const void *b)
Compare the order of creation of two browser entries - Implements sort_t.
Definition: browser.c:170
static int browser_compare_desc(const void *a, const void *b)
Compare the descriptions of two browser entries - Implements sort_t.
Definition: browser.c:181
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:71
static int browser_compare_count(const void *a, const void *b)
Compare the message count of two browser entries - Implements sort_t.
Definition: browser.c:220
int mutt_str_coll(const char *a, const char *b)
Collate two strings (compare using locale), safely.
Definition: string.c:644
Sort by the size of the email.
Definition: sort2.h:46
Sort by the order the messages appear in the mailbox.
Definition: sort2.h:50
Browser entry representing a folder/dir.
Definition: browser.h:57
static int browser_compare_count_new(const void *a, const void *b)
Compare the new count of two browser entries - Implements sort_t.
Definition: browser.c:239
static int browser_compare_size(const void *a, const void *b)
Compare the size of two browser entries - Implements sort_t.
Definition: browser.c:207
static int browser_compare_subject(const void *a, const void *b)
Compare the subject of two browser entries - Implements sort_t.
Definition: browser.c:153
Sort by the number of unread emails.
Definition: sort2.h:61
Sort by the folder&#39;s description.
Definition: sort2.h:65
Sort by number of emails in a folder.
Definition: sort2.h:60
Sort by the date the email was sent.
Definition: sort2.h:45
Sort by the email&#39;s subject.
Definition: sort2.h:48
#define SORT_MASK
Mask for the sort id.
Definition: sort2.h:80
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ browser_sort()

static void browser_sort ( struct BrowserState state)
static

Sort the entries in the browser.

Parameters
stateBrowser state

Call to qsort using browser_compare function. Some specific sort methods are not used via NNTP.

Definition at line 299 of file browser.c.

300 {
301  switch (C_SortBrowser & SORT_MASK)
302  {
303 #ifdef USE_NNTP
304  case SORT_SIZE:
305  case SORT_DATE:
306  if (OptNews)
307  return;
308 #endif
309  default:
310  break;
311  }
312 
313  ARRAY_SORT(&state->entry, browser_compare);
314 }
struct BrowserStateEntry entry
Definition: browser.h:97
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:71
Sort by the size of the email.
Definition: sort2.h:46
#define ARRAY_SORT(head, fn)
Sort an array.
Definition: array.h:271
static int browser_compare(const void *a, const void *b)
Sort the items in the browser - Implements sort_t.
Definition: browser.c:262
Sort by the date the email was sent.
Definition: sort2.h:45
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:45
#define SORT_MASK
Mask for the sort id.
Definition: sort2.h:80
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ link_is_dir()

static bool link_is_dir ( const char *  folder,
const char *  path 
)
static

Does this symlink point to a directory?

Parameters
folderFolder
pathLink name
Return values
trueLinks to a directory
falseOtherwise

Definition at line 323 of file browser.c.

324 {
325  struct stat st;
326  bool retval = false;
327 
328  struct Buffer *fullpath = mutt_buffer_pool_get();
329  mutt_buffer_concat_path(fullpath, folder, path);
330 
331  if (stat(mutt_b2s(fullpath), &st) == 0)
332  retval = S_ISDIR(st.st_mode);
333 
334  mutt_buffer_pool_release(&fullpath);
335 
336  return retval;
337 }
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
#define mutt_b2s(buf)
Definition: buffer.h:41
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
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ folder_format_str()

static const char* folder_format_str ( char *  buf,
size_t  buflen,
size_t  col,
int  cols,
char  op,
const char *  src,
const char *  prec,
const char *  if_str,
const char *  else_str,
intptr_t  data,
MuttFormatFlags  flags 
)
static

Format a string for the folder browser - Implements format_t.

Expando Description
%C Current file number
%d Date/time folder was last modified
%D Date/time folder was last modified using $date_format.
%F File permissions
%f Filename (with suffix /, @ or *)
%g Group name (or numeric gid, if missing)
%i Description of the folder
%l Number of hard links
%m Number of messages in the mailbox
%N N if mailbox has new mail, blank otherwise
%n Number of unread messages in the mailbox
%s Size in bytes
%t * if the file is tagged, blank otherwise
%u Owner name (or numeric uid, if missing)

Definition at line 359 of file browser.c.

363 {
364  char fn[128], fmt[128];
365  struct Folder *folder = (struct Folder *) data;
366  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
367 
368  switch (op)
369  {
370  case 'C':
371  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
372  snprintf(buf, buflen, fmt, folder->num + 1);
373  break;
374 
375  case 'd':
376  case 'D':
377  if (folder->ff->local)
378  {
379  bool do_locales = true;
380 
381  char *t_fmt = NULL;
382  if (op == 'D')
383  {
384  t_fmt = NONULL(C_DateFormat);
385  if (*t_fmt == '!')
386  {
387  t_fmt++;
388  do_locales = false;
389  }
390  }
391  else
392  {
393  static const time_t one_year = 31536000;
394  t_fmt = ((mutt_date_epoch() - folder->ff->mtime) < one_year) ?
395  "%b %d %H:%M" :
396  "%b %d %Y";
397  }
398 
399  if (!do_locales)
400  setlocale(LC_TIME, "C");
401  char date[128];
402  mutt_date_localtime_format(date, sizeof(date), t_fmt, folder->ff->mtime);
403  if (!do_locales)
404  setlocale(LC_TIME, "");
405 
406  mutt_format_s(buf, buflen, prec, date);
407  }
408  else
409  mutt_format_s(buf, buflen, prec, "");
410  break;
411 
412  case 'f':
413  {
414  char *s = NULL;
415 
416  s = NONULL(folder->ff->name);
417 
418  snprintf(fn, sizeof(fn), "%s%s", s,
419  folder->ff->local ?
420  (S_ISLNK(folder->ff->mode) ?
421  "@" :
422  (S_ISDIR(folder->ff->mode) ?
423  "/" :
424  (((folder->ff->mode & S_IXUSR) != 0) ? "*" : ""))) :
425  "");
426 
427  mutt_format_s(buf, buflen, prec, fn);
428  break;
429  }
430  case 'F':
431  {
432  if (folder->ff->local)
433  {
434  char permission[11];
435  snprintf(permission, sizeof(permission), "%c%c%c%c%c%c%c%c%c%c",
436  S_ISDIR(folder->ff->mode) ? 'd' : (S_ISLNK(folder->ff->mode) ? 'l' : '-'),
437  ((folder->ff->mode & S_IRUSR) != 0) ? 'r' : '-',
438  ((folder->ff->mode & S_IWUSR) != 0) ? 'w' : '-',
439  ((folder->ff->mode & S_ISUID) != 0) ?
440  's' :
441  ((folder->ff->mode & S_IXUSR) != 0) ? 'x' : '-',
442  ((folder->ff->mode & S_IRGRP) != 0) ? 'r' : '-',
443  ((folder->ff->mode & S_IWGRP) != 0) ? 'w' : '-',
444  ((folder->ff->mode & S_ISGID) != 0) ?
445  's' :
446  ((folder->ff->mode & S_IXGRP) != 0) ? 'x' : '-',
447  ((folder->ff->mode & S_IROTH) != 0) ? 'r' : '-',
448  ((folder->ff->mode & S_IWOTH) != 0) ? 'w' : '-',
449  ((folder->ff->mode & S_ISVTX) != 0) ?
450  't' :
451  ((folder->ff->mode & S_IXOTH) != 0) ? 'x' : '-');
452  mutt_format_s(buf, buflen, prec, permission);
453  }
454 #ifdef USE_IMAP
455  else if (folder->ff->imap)
456  {
457  char permission[11];
458  /* mark folders with subfolders AND mail */
459  snprintf(permission, sizeof(permission), "IMAP %c",
460  (folder->ff->inferiors && folder->ff->selectable) ? '+' : ' ');
461  mutt_format_s(buf, buflen, prec, permission);
462  }
463 #endif
464  else
465  mutt_format_s(buf, buflen, prec, "");
466  break;
467  }
468 
469  case 'g':
470  if (folder->ff->local)
471  {
472  struct group *gr = getgrgid(folder->ff->gid);
473  if (gr)
474  mutt_format_s(buf, buflen, prec, gr->gr_name);
475  else
476  {
477  snprintf(fmt, sizeof(fmt), "%%%sld", prec);
478  snprintf(buf, buflen, fmt, folder->ff->gid);
479  }
480  }
481  else
482  mutt_format_s(buf, buflen, prec, "");
483  break;
484 
485  case 'i':
486  {
487  char *s = NULL;
488  if (folder->ff->desc)
489  s = folder->ff->desc;
490  else
491  s = folder->ff->name;
492 
493  snprintf(fn, sizeof(fn), "%s%s", s,
494  folder->ff->local ?
495  (S_ISLNK(folder->ff->mode) ?
496  "@" :
497  (S_ISDIR(folder->ff->mode) ?
498  "/" :
499  (((folder->ff->mode & S_IXUSR) != 0) ? "*" : ""))) :
500  "");
501 
502  mutt_format_s(buf, buflen, prec, fn);
503  break;
504  }
505 
506  case 'l':
507  if (folder->ff->local)
508  {
509  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
510  snprintf(buf, buflen, fmt, folder->ff->nlink);
511  }
512  else
513  mutt_format_s(buf, buflen, prec, "");
514  break;
515 
516  case 'm':
517  if (!optional)
518  {
519  if (folder->ff->has_mailbox)
520  {
521  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
522  snprintf(buf, buflen, fmt, folder->ff->msg_count);
523  }
524  else
525  mutt_format_s(buf, buflen, prec, "");
526  }
527  else if (folder->ff->msg_count == 0)
528  optional = false;
529  break;
530 
531  case 'N':
532  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
533  snprintf(buf, buflen, fmt, folder->ff->has_new_mail ? 'N' : ' ');
534  break;
535 
536  case 'n':
537  if (!optional)
538  {
539  if (folder->ff->has_mailbox)
540  {
541  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
542  snprintf(buf, buflen, fmt, folder->ff->msg_unread);
543  }
544  else
545  mutt_format_s(buf, buflen, prec, "");
546  }
547  else if (folder->ff->msg_unread == 0)
548  optional = false;
549  break;
550 
551  case 's':
552  if (folder->ff->local)
553  {
554  mutt_str_pretty_size(fn, sizeof(fn), folder->ff->size);
555  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
556  snprintf(buf, buflen, fmt, fn);
557  }
558  else
559  mutt_format_s(buf, buflen, prec, "");
560  break;
561 
562  case 't':
563  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
564  snprintf(buf, buflen, fmt, folder->ff->tagged ? '*' : ' ');
565  break;
566 
567  case 'u':
568  if (folder->ff->local)
569  {
570  struct passwd *pw = getpwuid(folder->ff->uid);
571  if (pw)
572  mutt_format_s(buf, buflen, prec, pw->pw_name);
573  else
574  {
575  snprintf(fmt, sizeof(fmt), "%%%sld", prec);
576  snprintf(buf, buflen, fmt, folder->ff->uid);
577  }
578  }
579  else
580  mutt_format_s(buf, buflen, prec, "");
581  break;
582 
583  default:
584  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
585  snprintf(buf, buflen, fmt, op);
586  break;
587  }
588 
589  if (optional)
590  {
591  mutt_expando_format(buf, buflen, col, cols, if_str, folder_format_str, data,
593  }
594  else if (flags & MUTT_FORMAT_OPTIONAL)
595  {
596  mutt_expando_format(buf, buflen, col, cols, else_str, folder_format_str,
597  data, MUTT_FORMAT_NO_FLAGS);
598  }
599 
600  return src;
601 }
int msg_unread
number of unread messages
Definition: browser.h:71
static const char * folder_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
Format a string for the folder browser - Implements format_t.
Definition: browser.c:359
mode_t mode
Definition: browser.h:59
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:416
time_t mtime
Definition: browser.h:61
#define NONULL(x)
Definition: string2.h:37
bool has_mailbox
Definition: browser.h:80
size_t mutt_date_localtime_format(char *buf, size_t buflen, const char *format, time_t t)
Format localtime.
Definition: date.c:680
char * desc
Definition: browser.h:67
gid_t gid
Definition: browser.h:63
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
struct FolderFile * ff
Definition: browser.h:50
off_t size
Definition: browser.h:60
bool selectable
Definition: browser.h:77
uid_t uid
Definition: browser.h:62
nlink_t nlink
Definition: browser.h:64
char * name
Definition: browser.h:66
int num
Definition: browser.h:51
bool imap
Definition: browser.h:76
A folder/dir in the browser.
Definition: browser.h:48
void mutt_str_pretty_size(char *buf, size_t buflen, size_t num)
Display an abbreviated size, like 3.4K.
Definition: muttlib.c:1659
int msg_count
total number of messages
Definition: browser.h:70
WHERE char * C_DateFormat
Config: strftime format string for the d expando.
Definition: mutt_globals.h:89
void mutt_format_s(char *buf, size_t buflen, const char *prec, const char *s)
Format a simple string.
Definition: curs_lib.c:1244
void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t callback, intptr_t data, MuttFormatFlags flags)
Expand expandos (x) in a string.
Definition: muttlib.c:772
#define MUTT_FORMAT_OPTIONAL
Allow optional field processing.
Definition: format_flags.h:33
bool tagged
Definition: browser.h:82
bool local
folder is on local filesystem
Definition: browser.h:81
bool inferiors
Definition: browser.h:78
bool has_new_mail
true if mailbox has "new mail"
Definition: browser.h:69
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ add_folder()

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 
)
static

Add a folder to the browser list.

Parameters
menuMenu to use
stateBrowser state
nameName of folder
descDescription of folder
sstat info for the folder
mMailbox
dataData to associate with the folder

Definition at line 613 of file browser.c.

616 {
617  if ((!menu || menu->is_mailbox_list) && m && (m->flags & MB_HIDDEN))
618  {
619  return;
620  }
621 
622  struct FolderFile ff = { 0 };
623 
624  if (s)
625  {
626  ff.mode = s->st_mode;
627  ff.mtime = s->st_mtime;
628  ff.size = s->st_size;
629  ff.gid = s->st_gid;
630  ff.uid = s->st_uid;
631  ff.nlink = s->st_nlink;
632  ff.local = true;
633  }
634  else
635  ff.local = false;
636 
637  if (m)
638  {
639  ff.has_mailbox = true;
640  ff.gen = m->gen;
641  ff.has_new_mail = m->has_new;
642  ff.msg_count = m->msg_count;
643  ff.msg_unread = m->msg_unread;
644  }
645 
646  ff.name = mutt_str_dup(name);
647  ff.desc = mutt_str_dup(desc ? desc : name);
648 #ifdef USE_IMAP
649  ff.imap = false;
650 #endif
651 #ifdef USE_NNTP
652  if (OptNews)
653  ff.nd = data;
654 #endif
655 
656  ARRAY_ADD(&state->entry, ff);
657 }
int msg_unread
number of unread messages
Definition: browser.h:71
mode_t mode
Definition: browser.h:59
time_t mtime
Definition: browser.h:61
bool has_mailbox
Definition: browser.h:80
int msg_count
Total number of messages.
Definition: mailbox.h:91
int msg_unread
Number of unread messages.
Definition: mailbox.h:92
char * desc
Definition: browser.h:67
gid_t gid
Definition: browser.h:63
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
struct BrowserStateEntry entry
Definition: browser.h:97
int gen
Definition: browser.h:87
off_t size
Definition: browser.h:60
bool has_new
Mailbox has new mail.
Definition: mailbox.h:88
uid_t uid
Definition: browser.h:62
nlink_t nlink
Definition: browser.h:64
char * name
Definition: browser.h:66
bool imap
Definition: browser.h:76
int flags
e.g. MB_NORMAL
Definition: mailbox.h:134
Browser entry representing a folder/dir.
Definition: browser.h:57
#define MB_HIDDEN
Definition: mailbox.h:38
bool is_mailbox_list
Definition: mutt_menu.h:62
int msg_count
total number of messages
Definition: browser.h:70
#define ARRAY_ADD(head, elem)
Add an element at the end of the array.
Definition: array.h:152
struct NntpMboxData * nd
Definition: browser.h:84
bool local
folder is on local filesystem
Definition: browser.h:81
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:45
int gen
Generation number, for sorting.
Definition: mailbox.h:146
bool has_new_mail
true if mailbox has "new mail"
Definition: browser.h:69
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ init_state()

static void init_state ( struct BrowserState state,
struct Menu menu 
)
static

Initialise a browser state.

Parameters
stateBrowserState to initialise
menuCurrent menu

Definition at line 664 of file browser.c.

665 {
666  ARRAY_INIT(&state->entry);
667  ARRAY_RESERVE(&state->entry, 256);
668 #ifdef USE_IMAP
669  state->imap_browse = false;
670 #endif
671  if (menu)
672  menu->mdata = &state->entry;
673 }
#define ARRAY_RESERVE(head, num)
Reserve memory for the array.
Definition: array.h:185
struct BrowserStateEntry entry
Definition: browser.h:97
void * mdata
Extra data for the current menu.
Definition: mutt_menu.h:55
bool imap_browse
Definition: browser.h:99
#define ARRAY_INIT(head)
Initialize an array.
Definition: array.h:61
+ Here is the caller graph for this function:

◆ examine_directory()

static int examine_directory ( struct Menu menu,
struct BrowserState state,
const char *  d,
const char *  prefix 
)
static

Get list of all files/newsgroups with mask.

Parameters
menuCurrent Menu
stateState of browser
dDirectory
prefixFiles/newsgroups must match this prefix
Return values
0Success
-1Error

Definition at line 684 of file browser.c.

686 {
687  int rc = -1;
688  struct Buffer *buf = mutt_buffer_pool_get();
689 #ifdef USE_NNTP
690  if (OptNews)
691  {
693 
694  init_state(state, menu);
695 
696  for (unsigned int i = 0; i < adata->groups_num; i++)
697  {
698  struct NntpMboxData *mdata = adata->groups_list[i];
699  if (!mdata)
700  continue;
701  if (prefix && *prefix && !mutt_str_startswith(mdata->group, prefix))
702  continue;
703  if (!mutt_regex_match(C_Mask, mdata->group))
704  {
705  continue;
706  }
707  add_folder(menu, state, mdata->group, NULL, NULL, NULL, mdata);
708  }
709  }
710  else
711 #endif /* USE_NNTP */
712  {
713  struct stat s;
714  DIR *dp = NULL;
715  struct dirent *de = NULL;
716 
717  while (stat(d, &s) == -1)
718  {
719  if (errno == ENOENT)
720  {
721  /* The last used directory is deleted, try to use the parent dir. */
722  char *c = strrchr(d, '/');
723 
724  if (c && (c > d))
725  {
726  *c = '\0';
727  continue;
728  }
729  }
730  mutt_perror(d);
731  goto ed_out;
732  }
733 
734  if (!S_ISDIR(s.st_mode))
735  {
736  mutt_error(_("%s is not a directory"), d);
737  goto ed_out;
738  }
739 
740  if (Context && Context->mailbox)
742 
743  dp = opendir(d);
744  if (!dp)
745  {
746  mutt_perror(d);
747  goto ed_out;
748  }
749 
750  init_state(state, menu);
751 
752  struct MailboxList ml = STAILQ_HEAD_INITIALIZER(ml);
754  while ((de = readdir(dp)))
755  {
756  if (mutt_str_equal(de->d_name, "."))
757  continue; /* we don't need . */
758 
759  if (prefix && *prefix && !mutt_str_startswith(de->d_name, prefix))
760  {
761  continue;
762  }
763  if (!mutt_regex_match(C_Mask, de->d_name))
764  {
765  continue;
766  }
767 
768  mutt_buffer_concat_path(buf, d, de->d_name);
769  if (lstat(mutt_b2s(buf), &s) == -1)
770  continue;
771 
772  /* No size for directories or symlinks */
773  if (S_ISDIR(s.st_mode) || S_ISLNK(s.st_mode))
774  s.st_size = 0;
775  else if (!S_ISREG(s.st_mode))
776  continue;
777 
778  struct MailboxNode *np = NULL;
779  STAILQ_FOREACH(np, &ml, entries)
780  {
782  break;
783  }
784 
785  if (np && Context && Context->mailbox &&
787  {
790  }
791  add_folder(menu, state, de->d_name, NULL, &s, np ? np->mailbox : NULL, NULL);
792  }
794  closedir(dp);
795  }
796  browser_sort(state);
797  rc = 0;
798 ed_out:
800  return rc;
801 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
The "current" mailbox.
Definition: context.h:38
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:203
int msg_count
Total number of messages.
Definition: mailbox.h:91
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
int msg_unread
Number of unread messages.
Definition: mailbox.h:92
void neomutt_mailboxlist_clear(struct MailboxList *ml)
Free a Mailbox List.
Definition: neomutt.c:137
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:84
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
Match any Mailbox type.
Definition: mailbox.h:45
size_t neomutt_mailboxlist_get_all(struct MailboxList *head, struct NeoMutt *n, enum MailboxType type)
Get a List of all Mailboxes.
Definition: neomutt.c:160
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:613
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
Container for Accounts, Notifications.
Definition: neomutt.h:36
NNTP-specific Account data -.
Definition: lib.h:75
struct Mailbox * mailbox
Definition: context.h:50
char * group
Definition: lib.h:140
void * mdata
Driver specific data.
Definition: mailbox.h:136
#define mutt_b2s(buf)
Definition: buffer.h:41
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:160
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all all Mailboxes for new mail.
Definition: mutt_mailbox.c:138
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
unsigned int groups_num
Definition: lib.h:98
static void browser_sort(struct BrowserState *state)
Sort the entries in the browser.
Definition: browser.c:299
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
NNTP-specific Mailbox data -.
Definition: lib.h:138
#define mutt_error(...)
Definition: logging.h:84
bool mutt_regex_match(const struct Regex *regex, const char *str)
Shorthand to mutt_regex_capture()
Definition: regex.c:609
void ** groups_list
Definition: lib.h:100
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
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:321
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:76
List of Mailboxes.
Definition: mailbox.h:152
static void init_state(struct BrowserState *state, struct Menu *menu)
Initialise a browser state.
Definition: browser.c:664
WHERE struct Regex * C_Mask
Config: Only display files/dirs matching this regex in the browser.
Definition: mutt_globals.h:119
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:45
struct Mailbox * mailbox
Mailbox in the list.
Definition: mailbox.h:154
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ examine_mailboxes()

static int examine_mailboxes ( struct Menu menu,
struct BrowserState state 
)
static

Get list of mailboxes/subscribed newsgroups.

Parameters
menuCurrent menu
stateState of browser
Return values
0Success
-1Error

Definition at line 810 of file browser.c.

811 {
812  struct stat s;
813  struct Buffer *md = NULL;
814  struct Buffer *mailbox = NULL;
815 
816 #ifdef USE_NNTP
817  if (OptNews)
818  {
820 
821  init_state(state, menu);
822 
823  for (unsigned int i = 0; i < adata->groups_num; i++)
824  {
825  struct NntpMboxData *mdata = adata->groups_list[i];
826  if (mdata && (mdata->has_new_mail ||
827  (mdata->subscribed && (mdata->unread || !C_ShowOnlyUnread))))
828  {
829  add_folder(menu, state, mdata->group, NULL, NULL, NULL, mdata);
830  }
831  }
832  }
833  else
834 #endif
835  {
836  init_state(state, menu);
837 
839  return -1;
840  mailbox = mutt_buffer_pool_get();
841  md = mutt_buffer_pool_get();
843 
844  struct MailboxList ml = STAILQ_HEAD_INITIALIZER(ml);
846  struct MailboxNode *np = NULL;
847  STAILQ_FOREACH(np, &ml, entries)
848  {
849  if (!np->mailbox)
850  continue;
851 
852  if (Context && Context->mailbox &&
854  {
857  }
858 
859  mutt_buffer_strcpy(mailbox, mailbox_path(np->mailbox));
862 
863  switch (np->mailbox->type)
864  {
865  case MUTT_IMAP:
866  case MUTT_POP:
867  add_folder(menu, state, mutt_b2s(mailbox), np->mailbox->name, NULL,
868  np->mailbox, NULL);
869  continue;
870  case MUTT_NOTMUCH:
871  case MUTT_NNTP:
872  add_folder(menu, state, mailbox_path(np->mailbox), np->mailbox->name,
873  NULL, np->mailbox, NULL);
874  continue;
875  default: /* Continue */
876  break;
877  }
878 
879  if (lstat(mailbox_path(np->mailbox), &s) == -1)
880  continue;
881 
882  if ((!S_ISREG(s.st_mode)) && (!S_ISDIR(s.st_mode)) && (!S_ISLNK(s.st_mode)))
883  continue;
884 
885  if (np->mailbox->type == MUTT_MAILDIR)
886  {
887  struct stat st2;
888 
889  mutt_buffer_printf(md, "%s/new", mailbox_path(np->mailbox));
890  if (stat(mutt_b2s(md), &s) < 0)
891  s.st_mtime = 0;
892  mutt_buffer_printf(md, "%s/cur", mailbox_path(np->mailbox));
893  if (stat(mutt_b2s(md), &st2) < 0)
894  st2.st_mtime = 0;
895  if (st2.st_mtime > s.st_mtime)
896  s.st_mtime = st2.st_mtime;
897  }
898 
899  add_folder(menu, state, mutt_b2s(mailbox), np->mailbox->name, &s, np->mailbox, NULL);
900  }
902  }
903  browser_sort(state);
904 
905  mutt_buffer_pool_release(&mailbox);
907  return 0;
908 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
bool has_new_mail
Definition: lib.h:148
The "current" mailbox.
Definition: context.h:38
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:203
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
int msg_count
Total number of messages.
Definition: mailbox.h:91
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
int msg_unread
Number of unread messages.
Definition: mailbox.h:92
&#39;NNTP&#39; (Usenet) Mailbox type
Definition: mailbox.h:52
struct AccountList accounts
List of all Accounts.
Definition: neomutt.h:40
void neomutt_mailboxlist_clear(struct MailboxList *ml)
Free a Mailbox List.
Definition: neomutt.c:137
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:84
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
Match any Mailbox type.
Definition: mailbox.h:45
size_t neomutt_mailboxlist_get_all(struct MailboxList *head, struct NeoMutt *n, enum MailboxType type)
Get a List of all Mailboxes.
Definition: neomutt.c:160
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:613
String manipulation buffer.
Definition: buffer.h:33
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
Container for Accounts, Notifications.
Definition: neomutt.h:36
void mutt_buffer_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:598
NNTP-specific Account data -.
Definition: lib.h:75
bool subscribed
Definition: lib.h:147
char * name
A short name for the Mailbox.
Definition: mailbox.h:85
struct Mailbox * mailbox
Definition: context.h:50
bool C_ShowOnlyUnread
Config: (nntp) Only show subscribed newsgroups with unread articles.
Definition: config.c:54
char * group
Definition: lib.h:140
void * mdata
Driver specific data.
Definition: mailbox.h:136
&#39;Maildir&#39; Mailbox type
Definition: mailbox.h:51
#define mutt_b2s(buf)
Definition: buffer.h:41
&#39;POP3&#39; Mailbox type
Definition: mailbox.h:55
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all all Mailboxes for new mail.
Definition: mutt_mailbox.c:138
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
unsigned int groups_num
Definition: lib.h:98
static void browser_sort(struct BrowserState *state)
Sort the entries in the browser.
Definition: browser.c:299
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
NNTP-specific Mailbox data -.
Definition: lib.h:138
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
&#39;Notmuch&#39; (virtual) Mailbox type
Definition: mailbox.h:54
anum_t unread
Definition: lib.h:146
bool C_BrowserAbbreviateMailboxes
Config: Abbreviate mailboxes using &#39;~&#39; and &#39;=&#39; in the browser.
Definition: browser.c:69
void ** groups_list
Definition: lib.h:100
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:321
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:76
List of Mailboxes.
Definition: mailbox.h:152
#define TAILQ_EMPTY(head)
Definition: queue.h:714
static void init_state(struct BrowserState *state, struct Menu *menu)
Initialise a browser state.
Definition: browser.c:664
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:45
struct Mailbox * mailbox
Mailbox in the list.
Definition: mailbox.h:154
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ select_file_search()

static int select_file_search ( struct Menu menu,
regex_t *  rx,
int  line 
)
static

Menu search callback for matching files - Implements Menu::search()

Definition at line 913 of file browser.c.

914 {
915  struct BrowserStateEntry *entry = menu->mdata;
916 #ifdef USE_NNTP
917  if (OptNews)
918  return regexec(rx, ARRAY_GET(entry, line)->desc, 0, NULL, 0);
919 #endif
920  struct FolderFile *ff = ARRAY_GET(entry, line);
921  char *search_on = ff->desc ? ff->desc : ff->name;
922 
923  return regexec(rx, search_on, 0, NULL, 0);
924 }
char * desc
Definition: browser.h:67
#define ARRAY_GET(head, idx)
Return the element at index.
Definition: array.h:105
char * name
Definition: browser.h:66
Browser entry representing a folder/dir.
Definition: browser.h:57
void * mdata
Extra data for the current menu.
Definition: mutt_menu.h:55
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:45
+ Here is the caller graph for this function:

◆ folder_make_entry()

static void folder_make_entry ( char *  buf,
size_t  buflen,
struct Menu menu,
int  line 
)
static

Format a menu item for the folder browser - Implements Menu::make_entry()

Definition at line 929 of file browser.c.

930 {
931  struct BrowserStateEntry *entry = menu->mdata;
932  struct Folder folder = {
933  .ff = ARRAY_GET(entry, line),
934  .num = line,
935  };
936 
937 #ifdef USE_NNTP
938  if (OptNews)
939  {
940  mutt_expando_format(buf, buflen, 0, menu->win_index->state.cols,
942  (intptr_t) &folder, MUTT_FORMAT_ARROWCURSOR);
943  }
944  else
945 #endif
946  {
947  mutt_expando_format(buf, buflen, 0, menu->win_index->state.cols,
949  (intptr_t) &folder, MUTT_FORMAT_ARROWCURSOR);
950  }
951 }
static const char * folder_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
Format a string for the folder browser - Implements format_t.
Definition: browser.c:359
#define NONULL(x)
Definition: string2.h:37
char * C_GroupIndexFormat
Config: (nntp) printf-like format string for the browser&#39;s display of newsgroups. ...
Definition: config.c:39
#define MUTT_FORMAT_ARROWCURSOR
Reserve space for arrow_cursor.
Definition: format_flags.h:35
#define ARRAY_GET(head, idx)
Return the element at index.
Definition: array.h:105
char * C_FolderFormat
Config: printf-like format string for the browser&#39;s display of folders.
Definition: browser.c:70
struct FolderFile * ff
Definition: browser.h:50
const char * group_index_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
Format a string for the newsgroup menu - Implements format_t.
Definition: browse.c:52
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:57
A folder/dir in the browser.
Definition: browser.h:48
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:120
void * mdata
Extra data for the current menu.
Definition: mutt_menu.h:55
void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t callback, intptr_t data, MuttFormatFlags flags)
Expand expandos (x) in a string.
Definition: muttlib.c:772
struct MuttWindow * win_index
Definition: mutt_menu.h:63
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:45
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ browser_highlight_default()

static void browser_highlight_default ( struct BrowserState state,
struct Menu menu 
)
static

Decide which browser item should be highlighted.

Parameters
stateBrowser state
menuCurrent Menu

This function takes a menu and a state and defines the current entry that should be highlighted.

Definition at line 961 of file browser.c.

962 {
963  menu->top = 0;
964  /* Reset menu position to 1.
965  * We do not risk overflow as the init_menu function changes
966  * current if it is bigger than state->entrylen. */
967  if (!ARRAY_EMPTY(&state->entry) &&
968  (mutt_str_equal(ARRAY_FIRST(&state->entry)->desc, "..") ||
969  mutt_str_equal(ARRAY_FIRST(&state->entry)->desc, "../")))
970  {
971  /* Skip the first entry, unless there's only one entry. */
972  menu->current = (menu->max > 1);
973  }
974  else
975  {
976  menu->current = 0;
977  }
978 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
#define ARRAY_FIRST(head)
Convenience method to get the first element.
Definition: array.h:131
struct BrowserStateEntry entry
Definition: browser.h:97
int top
Entry that is the top of the current page.
Definition: mutt_menu.h:75
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition: array.h:70
int max
Number of entries in the menu.
Definition: mutt_menu.h:57
int current
Current entry.
Definition: mutt_menu.h:56
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ init_menu()

static void init_menu ( struct BrowserState state,
struct Menu menu,
char *  title,
size_t  titlelen,
bool  mailbox 
)
static

Set up a new menu.

Parameters
stateBrowser state
menuCurrent menu
titleBuffer for the title
titlelenLength of buffer
mailboxIf true, select mailboxes

Definition at line 988 of file browser.c.

990 {
991  menu->max = ARRAY_SIZE(&state->entry);
992 
993  if (menu->current >= menu->max)
994  menu->current = menu->max - 1;
995  if (menu->current < 0)
996  menu->current = 0;
997  if (menu->top > menu->current)
998  menu->top = 0;
999 
1000  menu->tagged = 0;
1001 
1002 #ifdef USE_NNTP
1003  if (OptNews)
1004  {
1005  if (mailbox)
1006  snprintf(title, titlelen, _("Subscribed newsgroups"));
1007  else
1008  {
1009  snprintf(title, titlelen, _("Newsgroups on server [%s]"),
1011  }
1012  }
1013  else
1014 #endif
1015  {
1016  if (mailbox)
1017  {
1018  menu->is_mailbox_list = true;
1019  snprintf(title, titlelen, _("Mailboxes [%d]"),
1020  mutt_mailbox_check(Context ? Context->mailbox : NULL, 0));
1021  }
1022  else
1023  {
1024  struct Buffer *path = mutt_buffer_pool_get();
1025  menu->is_mailbox_list = false;
1026  mutt_buffer_copy(path, &LastDir);
1028 #ifdef USE_IMAP
1029  if (state->imap_browse && C_ImapListSubscribed)
1030  {
1031  snprintf(title, titlelen, _("Subscribed [%s], File mask: %s"),
1032  mutt_b2s(path), NONULL(C_Mask ? C_Mask->pattern : NULL));
1033  }
1034  else
1035 #endif
1036  {
1037  snprintf(title, titlelen, _("Directory [%s], File mask: %s"),
1038  mutt_b2s(path), NONULL(C_Mask ? C_Mask->pattern : NULL));
1039  }
1040  mutt_buffer_pool_release(&path);
1041  }
1042  }
1043 
1044  /* Browser tracking feature.
1045  * The goal is to highlight the good directory if LastDir is the parent dir
1046  * of LastDirBackup (this occurs mostly when one hit "../"). It should also work
1047  * properly when the user is in examine_mailboxes-mode. */
1049  {
1050  char target_dir[PATH_MAX] = { 0 };
1051 
1052 #ifdef USE_IMAP
1053  /* Check what kind of dir LastDirBackup is. */
1055  {
1056  mutt_str_copy(target_dir, mutt_b2s(&LastDirBackup), sizeof(target_dir));
1057  imap_clean_path(target_dir, sizeof(target_dir));
1058  }
1059  else
1060 #endif
1061  mutt_str_copy(target_dir, strrchr(mutt_b2s(&LastDirBackup), '/') + 1,
1062  sizeof(target_dir));
1063 
1064  /* If we get here, it means that LastDir is the parent directory of
1065  * LastDirBackup. I.e., we're returning from a subdirectory, and we want
1066  * to position the cursor on the directory we're returning from. */
1067  bool matched = false;
1068  struct FolderFile *ff = NULL;
1069  ARRAY_FOREACH(ff, &state->entry)
1070  {
1071  if (mutt_str_equal(ff->name, target_dir))
1072  {
1073  menu->current = ARRAY_FOREACH_IDX;
1074  matched = true;
1075  break;
1076  }
1077  }
1078  if (!matched)
1079  browser_highlight_default(state, menu);
1080  }
1081  else
1082  browser_highlight_default(state, menu);
1083 
1084  menu->redraw = REDRAW_FULL;
1085 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
The "current" mailbox.
Definition: context.h:38
#define REDRAW_FULL
Redraw everything.
Definition: mutt_menu.h:45
#define NONULL(x)
Definition: string2.h:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2367
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:36
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer&#39;s contents to another Buffer.
Definition: buffer.c:445
#define 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
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
struct BrowserStateEntry entry
Definition: browser.h:97
void mutt_buffer_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:598
char host[128]
Server to login to.
Definition: connaccount.h:53
bool C_ImapListSubscribed
Config: (imap) When browsing a mailbox, only display subscribed folders.
Definition: config.c:50
static struct Buffer LastDirBackup
Definition: browser.c:102
struct Mailbox * mailbox
Definition: context.h:50
char * name
Definition: browser.h:66
#define mutt_b2s(buf)
Definition: buffer.h:41
Browser entry representing a folder/dir.
Definition: browser.h:57
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:160
#define PATH_MAX
Definition: mutt.h:44
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all all Mailboxes for new mail.
Definition: mutt_mailbox.c:138
int top
Entry that is the top of the current page.
Definition: mutt_menu.h:75
bool is_mailbox_list
Definition: mutt_menu.h:62
int tagged
Number of tagged entries.
Definition: mutt_menu.h:78
int max
Number of entries in the menu.
Definition: mutt_menu.h:57
MuttRedrawFlags redraw
When to redraw the screen.
Definition: mutt_menu.h:58
struct Connection * conn
Definition: lib.h:102
static void browser_highlight_default(struct BrowserState *state, struct Menu *menu)
Decide which browser item should be highlighted.
Definition: browser.c:961
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 imap_clean_path(char *path, size_t plen)
Cleans an IMAP path using imap_fix_path.
Definition: util.c:326
static struct Buffer LastDir
Definition: browser.c:101
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:76
int current
Current entry.
Definition: mutt_menu.h:56
char * pattern
printable version
Definition: regex3.h:90
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
bool imap_browse
Definition: browser.h:99
WHERE struct Regex * C_Mask
Config: Only display files/dirs matching this regex in the browser.
Definition: mutt_globals.h:119
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:45
#define ARRAY_SIZE(head)
The number of elements stored.
Definition: array.h:83
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ file_tag()

static int file_tag ( struct Menu menu,
int  sel,
int  act 
)
static

Tag an entry in the menu - Implements Menu::tag()

Definition at line 1090 of file browser.c.

1091 {
1092  struct BrowserStateEntry *entry = menu->mdata;
1093  struct FolderFile *ff = ARRAY_GET(entry, sel);
1094  if (S_ISDIR(ff->mode) || (S_ISLNK(ff->mode) && link_is_dir(mutt_b2s(&LastDir), ff->name)))
1095  {
1096  mutt_error(_("Can't attach a directory"));
1097  return 0;
1098  }
1099 
1100  bool ot = ff->tagged;
1101  ff->tagged = ((act >= 0) ? act : !ff->tagged);
1102 
1103  return ff->tagged - ot;
1104 }
mode_t mode
Definition: browser.h:59
static bool link_is_dir(const char *folder, const char *path)
Does this symlink point to a directory?
Definition: browser.c:323
#define ARRAY_GET(head, idx)
Return the element at index.
Definition: array.h:105
#define _(a)
Definition: message.h:28
char * name
Definition: browser.h:66
#define mutt_b2s(buf)
Definition: buffer.h:41
Browser entry representing a folder/dir.
Definition: browser.h:57
void * mdata
Extra data for the current menu.
Definition: mutt_menu.h:55
#define mutt_error(...)
Definition: logging.h:84
static struct Buffer LastDir
Definition: browser.c:101
bool tagged
Definition: browser.h:82
+ Here is the call graph for this function:
+ 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 1116 of file browser.c.

1117 {
1118  init_lastdir();
1119 
1121 
1122  /* Method that will fetch the parent path depending on the type of the path. */
1123  char buf[PATH_MAX];
1124  mutt_get_parent_path(mutt_b2s(&LastDirBackup), buf, sizeof(buf));
1125  mutt_buffer_strcpy(&LastDir, buf);
1126 }
static void init_lastdir(void)
Initialise the browser directories.
Definition: browser.c:109
static struct Buffer LastDirBackup
Definition: browser.c:102
#define mutt_b2s(buf)
Definition: buffer.h:41
#define PATH_MAX
Definition: mutt.h:44
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: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:1538
+ 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 1135 of file browser.c.

1137 {
1138  char title[256];
1139  struct BrowserState state = { { 0 } };
1140  struct Menu *menu = NULL;
1141  bool kill_prefix = false;
1142  bool multiple = (flags & MUTT_SEL_MULTI);
1143  bool folder = (flags & MUTT_SEL_FOLDER);
1144  bool mailbox = (flags & MUTT_SEL_MAILBOX);
1145 
1146  /* Keeps in memory the directory we were in when hitting '='
1147  * to go directly to $folder (`$folder`) */
1148  char goto_swapper[PATH_MAX] = { 0 };
1149 
1150  mailbox = mailbox && folder;
1151 
1152  struct Buffer *OldLastDir = mutt_buffer_pool_get();
1153  struct Buffer *tmp = mutt_buffer_pool_get();
1154  struct Buffer *buf = mutt_buffer_pool_get();
1155  struct Buffer *prefix = mutt_buffer_pool_get();
1156 
1157  init_lastdir();
1158 
1159 #ifdef USE_NNTP
1160  if (OptNews)
1161  {
1162  if (mutt_buffer_is_empty(file))
1163  {
1165 
1166  /* default state for news reader mode is browse subscribed newsgroups */
1167  mailbox = false;
1168  for (size_t i = 0; i < adata->groups_num; i++)
1169  {
1170  struct NntpMboxData *mdata = adata->groups_list[i];
1171  if (mdata && mdata->subscribed)
1172  {
1173  mailbox = true;
1174  break;
1175  }
1176  }
1177  }
1178  else
1179  {
1180  mutt_buffer_copy(prefix, file);
1181  }
1182  }
1183  else
1184 #endif
1185  if (!mutt_buffer_is_empty(file))
1186  {
1188 #ifdef USE_IMAP
1189  if (imap_path_probe(mutt_b2s(file), NULL) == MUTT_IMAP)
1190  {
1191  init_state(&state, NULL);
1192  state.imap_browse = true;
1193  if (imap_browse(mutt_b2s(file), &state) == 0)
1194  {
1196  browser_sort(&state);
1197  }
1198  }
1199  else
1200  {
1201 #endif
1202  int i;
1203  for (i = mutt_buffer_len(file) - 1; (i > 0) && ((mutt_b2s(file))[i] != '/'); i--)
1204  ; // do nothing
1205 
1206  if (i > 0)
1207  {
1208  if ((mutt_b2s(file))[0] == '/')
1210  else
1211  {
1213  mutt_buffer_addch(&LastDir, '/');
1215  }
1216  }
1217  else
1218  {
1219  if ((mutt_b2s(file))[0] == '/')
1220  mutt_buffer_strcpy(&LastDir, "/");
1221  else
1223  }
1224 
1225  if ((i <= 0) && (mutt_b2s(file)[0] != '/'))
1226  mutt_buffer_copy(prefix, file);
1227  else
1228  mutt_buffer_strcpy(prefix, mutt_b2s(file) + i + 1);
1229  kill_prefix = true;
1230 #ifdef USE_IMAP
1231  }
1232 #endif
1233  }
1234  else
1235  {
1236  if (!folder)
1238  else
1239  {
1240  /* Whether we use the tracking feature of the browser depends
1241  * on which sort method we chose to use. This variable is defined
1242  * only to help readability of the code. */
1243  bool browser_track = false;
1244 
1245  switch (C_SortBrowser & SORT_MASK)
1246  {
1247  case SORT_DESC:
1248  case SORT_SUBJECT:
1249  case SORT_ORDER:
1250  browser_track = true;
1251  break;
1252  }
1253 
1254  /* We use mutt_browser_select_dir to initialize the two
1255  * variables (LastDir, LastDirBackup) at the appropriate
1256  * values.
1257  *
1258  * We do it only when LastDir is not set (first pass there)
1259  * or when CurrentFolder and LastDirBackup are not the same.
1260  * This code is executed only when we list files, not when
1261  * we press up/down keys to navigate in a displayed list.
1262  *
1263  * We only do this when CurrentFolder has been set (ie, not
1264  * when listing folders on startup with "neomutt -y").
1265  *
1266  * This tracker is only used when browser_track is true,
1267  * meaning only with sort methods SUBJECT/DESC for now. */
1268  if (CurrentFolder)
1269  {
1271  {
1272  /* If browsing in "local"-mode, than we chose to define LastDir to
1273  * MailDir */
1274  switch (mx_path_probe(CurrentFolder))
1275  {
1276  case MUTT_IMAP:
1277  case MUTT_MAILDIR:
1278  case MUTT_MBOX:
1279  case MUTT_MH:
1280  case MUTT_MMDF:
1281  if (C_Folder)
1283  else if (C_Spoolfile)
1285  break;
1286  default:
1288  break;
1289  }
1290  }
1292  {
1294  }
1295  }
1296 
1297  /* When browser tracking feature is disabled, clear LastDirBackup */
1298  if (!browser_track)
1300  }
1301 
1302 #ifdef USE_IMAP
1303  if (!mailbox && (imap_path_probe(mutt_b2s(&LastDir), NULL) == MUTT_IMAP))
1304  {
1305  init_state(&state, NULL);
1306  state.imap_browse = true;
1307  imap_browse(mutt_b2s(&LastDir), &state);
1308  browser_sort(&state);
1309  }
1310  else
1311 #endif
1312  {
1313  size_t i = mutt_buffer_len(&LastDir);
1314  while ((i > 0) && (mutt_b2s(&LastDir)[--i] == '/'))
1315  LastDir.data[i] = '\0';
1319  }
1320  }
1321 
1322  mutt_buffer_reset(file);
1323 
1324  menu = mutt_menu_new(MENU_FOLDER);
1326 
1327 #ifdef USE_NNTP
1328  if (OptNews)
1329  dlg->help_data = FolderNewsHelp;
1330  else
1331 #endif
1332  dlg->help_data = FolderHelp;
1333  dlg->help_menu = MENU_FOLDER;
1334 
1335  menu->make_entry = folder_make_entry;
1336  menu->search = select_file_search;
1337  menu->title = title;
1338  if (multiple)
1339  menu->tag = file_tag;
1340 
1341  mutt_menu_push_current(menu);
1342 
1343  if (mailbox)
1344  {
1345  examine_mailboxes(NULL, &state);
1346  }
1347  else
1348 #ifdef USE_IMAP
1349  if (!state.imap_browse)
1350 #endif
1351  {
1352  // examine_directory() calls add_folder() which needs the menu
1353  if (examine_directory(menu, &state, mutt_b2s(&LastDir), mutt_b2s(prefix)) == -1)
1354  goto bail;
1355  }
1356 
1357  init_menu(&state, menu, title, sizeof(title), mailbox);
1358  // only now do we have a valid state to attach
1359  menu->mdata = &state.entry;
1360 
1361  while (true)
1362  {
1363  int op = mutt_menu_loop(menu);
1364  if (op >= 0)
1365  mutt_debug(LL_DEBUG1, "Got op %s (%d)\n", OpStrings[op][0], op);
1366  struct FolderFile *ff = ARRAY_GET(&state.entry, menu->current);
1367  switch (op)
1368  {
1369  case OP_DESCEND_DIRECTORY:
1370  case OP_GENERIC_SELECT_ENTRY:
1371  {
1372  if (ARRAY_EMPTY(&state.entry))
1373  {
1374  mutt_error(_("No files match the file mask"));
1375  break;
1376  }
1377 
1378  if (S_ISDIR(ff->mode) ||
1379  (S_ISLNK(ff->mode) && link_is_dir(mutt_b2s(&LastDir), ff->name))
1380 #ifdef USE_IMAP
1381  || ff->inferiors
1382 #endif
1383  )
1384  {
1385  /* make sure this isn't a MH or maildir mailbox */
1386  if (mailbox)
1387  {
1388  mutt_buffer_strcpy(buf, ff->name);
1390  }
1391 #ifdef USE_IMAP
1392  else if (state.imap_browse)
1393  {
1394  mutt_buffer_strcpy(buf, ff->name);
1395  }
1396 #endif
1397  else
1398  {
1400  }
1401 
1402  enum MailboxType type = mx_path_probe(mutt_b2s(buf));
1403  if ((op == OP_DESCEND_DIRECTORY) || (type == MUTT_MAILBOX_ERROR) ||
1404  (type == MUTT_UNKNOWN)
1405 #ifdef USE_IMAP
1406  || ff->inferiors
1407 #endif
1408  )
1409  {
1410  /* save the old directory */
1411  mutt_buffer_copy(OldLastDir, &LastDir);
1412 
1413  if (mutt_str_equal(ff->name, ".."))
1414  {
1415  size_t lastdirlen = mutt_buffer_len(&LastDir);
1416  if ((lastdirlen > 1) &&
1417  mutt_str_equal("..", mutt_b2s(&LastDir) + lastdirlen - 2))
1418  {
1419  mutt_buffer_addstr(&LastDir, "/..");
1420  }
1421  else
1422  {
1423  char *p = NULL;
1424  if (lastdirlen > 1)
1425  p = strrchr(mutt_b2s(&LastDir) + 1, '/');
1426 
1427  if (p)
1428  {
1429  *p = '\0';
1431  }
1432  else
1433  {
1434  if (mutt_b2s(&LastDir)[0] == '/')
1435  mutt_buffer_strcpy(&LastDir, "/");
1436  else
1437  mutt_buffer_addstr(&LastDir, "/..");
1438  }
1439  }
1440  }
1441  else if (mailbox)
1442  {
1445  }
1446 #ifdef USE_IMAP
1447  else if (state.imap_browse)
1448  {
1450  /* tack on delimiter here */
1451 
1452  /* special case "" needs no delimiter */
1453  struct Url *url = url_parse(ff->name);
1454  if (url && url->path && (ff->delim != '\0'))
1455  {
1457  }
1458  url_free(&url);
1459  }
1460 #endif
1461  else
1462  {
1464  mutt_buffer_copy(&LastDir, tmp);
1465  }
1466 
1467  destroy_state(&state);
1468  if (kill_prefix)
1469  {
1470  mutt_buffer_reset(prefix);
1471  kill_prefix = false;
1472  }
1473  mailbox = false;
1474 #ifdef USE_IMAP
1475  if (state.imap_browse)
1476  {
1477  init_state(&state, NULL);
1478  state.imap_browse = true;
1479  imap_browse(mutt_b2s(&LastDir), &state);
1480  browser_sort(&state);
1481  menu->mdata = &state.entry;
1482  }
1483  else
1484 #endif
1485  {
1486  if (examine_directory(menu, &state, mutt_b2s(&LastDir), mutt_b2s(prefix)) == -1)
1487  {
1488  /* try to restore the old values */
1489  mutt_buffer_copy(&LastDir, OldLastDir);
1490  if (examine_directory(menu, &state, mutt_b2s(&LastDir),
1491  mutt_b2s(prefix)) == -1)
1492  {
1494  goto bail;
1495  }
1496  }
1497  /* resolve paths navigated from GUI */
1498  if (mutt_path_realpath(LastDir.data) == 0)
1499  break;
1500  }
1501 
1502  browser_highlight_default(&state, menu);
1503  init_menu(&state, menu, title, sizeof(title), mailbox);
1504  goto_swapper[0] = '\0';
1505  break;
1506  }
1507  }
1508  else if (op == OP_DESCEND_DIRECTORY)
1509  {
1510  mutt_error(_("%s is not a directory"),
1511  ARRAY_GET(&state.entry, menu->current)->name);
1512  break;
1513  }
1514 
1515  if (mailbox || OptNews) /* USE_NNTP */
1516  {
1517  mutt_buffer_strcpy(file, ff->name);
1519  }
1520 #ifdef USE_IMAP
1521  else if (state.imap_browse)
1522  mutt_buffer_strcpy(file, ff->name);
1523 #endif
1524  else
1525  {
1527  }
1528  }
1529  /* fallthrough */
1530 
1531  case OP_EXIT:
1532 
1533  if (multiple)
1534  {
1535  char **tfiles = NULL;
1536 
1537  if (menu->tagged)
1538  {
1539  *numfiles = menu->tagged;
1540  tfiles = mutt_mem_calloc(*numfiles, sizeof(char *));
1541  size_t j = 0;
1542  ARRAY_FOREACH(ff, &state.entry)
1543  {
1544  if (ff->tagged)
1545  {
1548  tfiles[j++] = mutt_buffer_strdup(tmp);
1549  }
1550  }
1551  *files = tfiles;
1552  }
1553  else if (!mutt_buffer_is_empty(file)) /* no tagged entries. return selected entry */
1554  {
1555  *numfiles = 1;
1556  tfiles = mutt_mem_calloc(*numfiles, sizeof(char *));
1558  tfiles[0] = mutt_buffer_strdup(file);
1559  *files = tfiles;
1560  }
1561  }
1562 
1563  destroy_state(&state);
1564  goto bail;
1565 
1566  case OP_BROWSER_TELL:
1567  if (!ARRAY_EMPTY(&state.entry))
1568  mutt_message("%s", ARRAY_GET(&state.entry, menu->current)->name);
1569  break;
1570 
1571 #ifdef USE_IMAP
1572  case OP_BROWSER_TOGGLE_LSUB:
1573  bool_str_toggle(NeoMutt->sub, "imap_list_subscribed", NULL);
1574 
1575  mutt_unget_event(0, OP_CHECK_NEW);
1576  break;
1577 
1578  case OP_CREATE_MAILBOX:
1579  if (!state.imap_browse)
1580  {
1581  mutt_error(_("Create is only supported for IMAP mailboxes"));
1582  break;
1583  }
1584 
1585  if (imap_mailbox_create(mutt_b2s(&LastDir)) == 0)
1586  {
1587  /* TODO: find a way to detect if the new folder would appear in
1588  * this window, and insert it without starting over. */
1589  destroy_state(&state);
1590  init_state(&state, NULL);
1591  state.imap_browse = true;
1592  imap_browse(mutt_b2s(&LastDir), &state);
1593  browser_sort(&state);
1594  menu->mdata = &state.entry;
1595  browser_highlight_default(&state, menu);
1596  init_menu(&state, menu, title, sizeof(title), mailbox);
1597  }
1598  /* else leave error on screen */
1599  break;
1600 
1601  case OP_RENAME_MAILBOX:
1602  if (!ff->imap)
1603  mutt_error(_("Rename is only supported for IMAP mailboxes"));
1604  else
1605  {
1606  if (imap_mailbox_rename(ff->name) >= 0)
1607  {
1608  destroy_state(&state);
1609  init_state(&state, NULL);
1610  state.imap_browse = true;
1611  imap_browse(mutt_b2s(&LastDir), &state);
1612  browser_sort(&state);
1613  menu->mdata = &state.entry;
1614  browser_highlight_default(&state, menu);
1615  init_menu(&state, menu, title, sizeof(title), mailbox);
1616  }
1617  }
1618  break;
1619 
1620  case OP_DELETE_MAILBOX:
1621  if (!ff->imap)
1622  mutt_error(_("Delete is only supported for IMAP mailboxes"));
1623  else
1624  {
1625  char msg[128];
1626 
1627  // TODO(sileht): It could be better to select INBOX instead. But I
1628  // don't want to manipulate Context/Mailboxes/mailbox->account here for now.
1629  // Let's just protect neomutt against crash for now. #1417
1631  {
1632  mutt_error(_("Can't delete currently selected mailbox"));
1633  break;
1634  }
1635 
1636  snprintf(msg, sizeof(msg), _("Really delete mailbox \"%s\"?"), ff->name);
1637  if (mutt_yesorno(msg, MUTT_NO) == MUTT_YES)
1638  {
1639  if (imap_delete_mailbox(Context->mailbox, ff->name) == 0)
1640  {
1641  /* free the mailbox from the browser */
1642  FREE(&ff->name);
1643  FREE(&ff->desc);
1644  /* and move all other entries up */
1645  ARRAY_REMOVE(&state.entry, ff);
1646  mutt_message(_("Mailbox deleted"));
1647  init_menu(&state, menu, title, sizeof(title), mailbox);
1648  }
1649  else
1650  mutt_error(_("Mailbox deletion failed"));
1651  }
1652  else
1653  mutt_message(_("Mailbox not deleted"));
1654  }
1655  break;
1656 #endif
1657 
1658  case OP_GOTO_PARENT:
1659  case OP_CHANGE_DIRECTORY:
1660 
1661 #ifdef USE_NNTP
1662  if (OptNews)
1663  break;
1664 #endif
1665 
1666  mutt_buffer_copy(buf, &LastDir);
1667 #ifdef USE_IMAP
1668  if (!state.imap_browse)
1669 #endif
1670  {
1671  /* add '/' at the end of the directory name if not already there */
1672  size_t len = mutt_buffer_len(buf);
1673  if ((len > 0) && (mutt_b2s(&LastDir)[len - 1] != '/'))
1674  mutt_buffer_addch(buf, '/');
1675  }
1676 
1677  if (op == OP_CHANGE_DIRECTORY)
1678  {
1679  /* buf comes from the buffer pool, so defaults to size 1024 */
1680  int ret = mutt_buffer_get_field(_("Chdir to: "), buf, MUTT_FILE);
1681  if ((ret != 0) && mutt_buffer_is_empty(buf))
1682  break;
1683  }
1684  else if (op == OP_GOTO_PARENT)
1685  mutt_get_parent_path(mutt_b2s(buf), buf->data, buf->dsize);
1686 
1687  if (!mutt_buffer_is_empty(buf))
1688  {
1689  mailbox = false;
1691 #ifdef USE_IMAP
1692  if (imap_path_probe(mutt_b2s(buf), NULL) == MUTT_IMAP)
1693  {
1694  mutt_buffer_copy(&LastDir, buf);
1695  destroy_state(&state);
1696  init_state(&state, NULL);
1697  state.imap_browse = true;
1698  imap_browse(mutt_b2s(&LastDir), &state);
1699  browser_sort(&state);
1700  menu->mdata = &state.entry;
1701  browser_highlight_default(&state, menu);
1702  init_menu(&state, menu, title, sizeof(title), mailbox);
1703  }
1704  else
1705 #endif
1706  {
1707  if (mutt_b2s(buf)[0] != '/')
1708  {
1709  /* in case dir is relative, make it relative to LastDir,
1710  * not current working dir */
1712  mutt_buffer_copy(buf, tmp);
1713  }
1714  /* Resolve path from <chdir>
1715  * Avoids buildup such as /a/b/../../c
1716  * Symlinks are always unraveled to keep code simple */
1717  if (mutt_path_realpath(buf->data) == 0)
1718  break;
1719 
1720  struct stat st;
1721  if (stat(mutt_b2s(buf), &st) == 0)
1722  {
1723  if (S_ISDIR(st.st_mode))
1724  {
1725  destroy_state(&state);
1726  if (examine_directory(menu, &state, mutt_b2s(buf), mutt_b2s(prefix)) == 0)
1727  mutt_buffer_copy(&LastDir, buf);
1728  else
1729  {
1730  mutt_error(_("Error scanning directory"));
1731  if (examine_directory(menu, &state, mutt_b2s(&LastDir),
1732  mutt_b2s(prefix)) == -1)
1733  {
1734  goto bail;
1735  }
1736  }
1737  browser_highlight_default(&state, menu);
1738  init_menu(&state, menu, title, sizeof(title), mailbox);
1739  }
1740  else
1741  mutt_error(_("%s is not a directory"), mutt_b2s(buf));
1742  }
1743  else
1744  mutt_perror(mutt_b2s(buf));
1745  }
1746  }
1747  break;
1748 
1749  case OP_ENTER_MASK:
1750  {
1751  mutt_buffer_strcpy(buf, C_Mask ? C_Mask->pattern : NULL);
1752  if (mutt_get_field(_("File Mask: "), buf->data, buf->dsize, MUTT_COMP_NO_FLAGS) != 0)
1753  break;
1754 
1755  mutt_buffer_fix_dptr(buf);
1756 
1757  mailbox = false;
1758  /* assume that the user wants to see everything */
1759  if (mutt_buffer_is_empty(buf))
1760  mutt_buffer_strcpy(buf, ".");
1761 
1762  struct Buffer errmsg = mutt_buffer_make(256);
1763  int rc = cs_subset_str_string_set(NeoMutt->sub, "mask", mutt_b2s(buf), &errmsg);
1764  if (CSR_RESULT(rc) != CSR_SUCCESS)
1765  {
1766  if (!mutt_buffer_is_empty(&errmsg))
1767  {
1768  mutt_error("%s", mutt_b2s(&errmsg));
1769  mutt_buffer_dealloc(&errmsg);
1770  }
1771  break;
1772  }
1773  mutt_buffer_dealloc(&errmsg);
1774 
1775  destroy_state(&state);
1776 #ifdef USE_IMAP
1777  if (state.imap_browse)
1778  {
1779  init_state(&state, NULL);
1780  state.imap_browse = true;
1781  imap_browse(mutt_b2s(&LastDir), &state);
1782  browser_sort(&state);
1783  menu->mdata = &state.entry;
1784  init_menu(&state, menu, title, sizeof(title), mailbox);
1785  }
1786  else
1787 #endif
1788  if (examine_directory(menu, &state, mutt_b2s(&LastDir), NULL) == 0)
1789  init_menu(&state, menu, title, sizeof(title), mailbox);
1790  else
1791  {
1792  mutt_error(_("Error scanning directory"));
1793  goto bail;
1794  }
1795  kill_prefix = false;
1796  if (ARRAY_EMPTY(&state.entry))
1797  {
1798  mutt_error(_("No files match the file mask"));
1799  break;
1800  }
1801  break;
1802  }
1803 
1804  case OP_SORT:
1805  case OP_SORT_REVERSE:
1806 
1807  {
1808  bool resort = true;
1809  int sort = -1;
1810  int reverse = (op == OP_SORT_REVERSE);
1811 
1812  switch (mutt_multi_choice(
1813  (reverse) ?
1814  /* L10N: The highlighted letters must match the "Sort" options */
1815  _("Reverse sort by (d)ate, (a)lpha, si(z)e, d(e)scription, "
1816  "(c)ount, ne(w) count, or do(n)'t sort?") :
1817  /* L10N: The highlighted letters must match the "Reverse Sort" options */
1818  _("Sort by (d)ate, (a)lpha, si(z)e, d(e)scription, (c)ount, "
1819  "ne(w) count, or do(n)'t sort?"),
1820  /* L10N: These must match the highlighted letters from "Sort" and "Reverse Sort" */
1821  _("dazecwn")))
1822  {
1823  case -1: /* abort */
1824  resort = false;
1825  break;
1826 
1827  case 1: /* (d)ate */
1828  sort = SORT_DATE;
1829  break;
1830 
1831  case 2: /* (a)lpha */
1832  sort = SORT_SUBJECT;
1833  break;
1834 
1835  case 3: /* si(z)e */
1836  sort = SORT_SIZE;
1837  break;
1838 
1839  case 4: /* d(e)scription */
1840  sort = SORT_DESC;
1841  break;
1842 
1843  case 5: /* (c)ount */
1844  sort = SORT_COUNT;
1845  break;
1846 
1847  case 6: /* ne(w) count */
1848  sort = SORT_UNREAD;
1849  break;
1850 
1851  case 7: /* do(n)'t sort */
1852  sort = SORT_ORDER;
1853  break;
1854  }
1855  if (resort)
1856  {
1857  sort |= reverse ? SORT_REVERSE : 0;
1858  cs_subset_str_native_set(NeoMutt->sub, "sort_browser", sort, NULL);
1859  browser_sort(&state);
1860  browser_highlight_default(&state, menu);
1861  menu->redraw = REDRAW_FULL;
1862  }
1863  else
1864  {
1865  cs_subset_str_native_set(NeoMutt->sub, "sort_browser", sort, NULL);
1866  }
1867  break;
1868  }
1869 
1870  case OP_TOGGLE_MAILBOXES:
1871  case OP_BROWSER_GOTO_FOLDER:
1872  case OP_CHECK_NEW:
1873  if (op == OP_TOGGLE_MAILBOXES)
1874  {
1875  mailbox = !mailbox;
1876  menu->is_mailbox_list = mailbox;
1877  }
1878 
1879  if (op == OP_BROWSER_GOTO_FOLDER)
1880  {
1881  /* When in mailboxes mode, disables this feature */
1882  if (C_Folder)
1883  {
1884  mutt_debug(LL_DEBUG3, "= hit! Folder: %s, LastDir: %s\n", C_Folder,
1885  mutt_b2s(&LastDir));
1886  if (goto_swapper[0] == '\0')
1887  {
1889  {
1890  /* Stores into goto_swapper LastDir, and swaps to `$folder` */
1891  mutt_str_copy(goto_swapper, mutt_b2s(&LastDir), sizeof(goto_swapper));
1894  }
1895  }
1896  else
1897  {
1899  mutt_buffer_strcpy(&LastDir, goto_swapper);
1900  goto_swapper[0] = '\0';
1901  }
1902  }
1903  }
1904  destroy_state(&state);
1905  mutt_buffer_reset(prefix);
1906  kill_prefix = false;
1907 
1908  if (mailbox)
1909  {
1910  examine_mailboxes(menu, &state);
1911  }
1912 #ifdef USE_IMAP
1913  else if (imap_path_probe(mutt_b2s(&LastDir), NULL) == MUTT_IMAP)
1914  {
1915  init_state(&state, NULL);
1916  state.imap_browse = true;
1917  imap_browse(mutt_b2s(&LastDir), &state);
1918  browser_sort(&state);
1919  menu->mdata = &state.entry;
1920  }
1921 #endif
1922  else if (examine_directory(menu, &state, mutt_b2s(&LastDir), mutt_b2s(prefix)) == -1)
1923  goto bail;
1924  init_menu(&state, menu, title, sizeof(title), mailbox);
1925  break;
1926 
1927  case OP_MAILBOX_LIST:
1929  break;
1930 
1931  case OP_BROWSER_NEW_FILE:
1932  mutt_buffer_printf(buf, "%s/", mutt_b2s(&LastDir));
1933  /* buf comes from the buffer pool, so defaults to size 1024 */
1934  if (mutt_buffer_get_field(_("New file name: "), buf, MUTT_FILE) == 0)
1935  {
1936  mutt_buffer_copy(file, buf);
1937  destroy_state(&state);
1938  goto bail;
1939  }
1940  break;
1941 
1942  case OP_BROWSER_VIEW_FILE:
1943  if (ARRAY_EMPTY(&state.entry))
1944  {
1945  mutt_error(_("No files match the file mask"));
1946  break;
1947  }
1948 
1949 #ifdef USE_IMAP
1950  if (ff->selectable)
1951  {
1952  mutt_buffer_strcpy(file, ff->name);
1953  destroy_state(&state);
1954  goto bail;
1955  }
1956  else
1957 #endif
1958  if (S_ISDIR(ff->mode) ||
1959  (S_ISLNK(ff->mode) && link_is_dir(mutt_b2s(&LastDir), ff->name)))
1960  {
1961  mutt_error(_("Can't view a directory"));
1962  break;
1963  }
1964  else
1965  {
1966  char buf2[PATH_MAX];
1967 
1968  mutt_path_concat(buf2, mutt_b2s(&LastDir), ff->name, sizeof(buf2));
1969  struct Body *b = mutt_make_file_attach(buf2, NeoMutt->sub);
1970  if (b)
1971  {
1972  mutt_view_attachment(NULL, b, MUTT_VA_REGULAR, NULL, NULL, menu->win_index);
1973  mutt_body_free(&b);
1974  menu->redraw = REDRAW_FULL;
1975  }
1976  else
1977  mutt_error(_("Error trying to view file"));
1978  }
1979  break;
1980 
1981 #ifdef USE_NNTP
1982  case OP_CATCHUP:
1983  case OP_UNCATCHUP:
1984  {
1985  if (!OptNews)
1986  break;
1987 
1988  struct NntpMboxData *mdata = NULL;
1989 
1991  if (rc < 0)
1992  break;
1993 
1994  if (op == OP_CATCHUP)
1996  else
1998 
1999  if (mdata)
2000  {
2002  if ((menu->current + 1) < menu->max)
2003  menu->current++;
2004  menu->redraw = REDRAW_MOTION_RESYNC;
2005  }
2006  if (rc)
2007  menu->redraw = REDRAW_INDEX;
2009  break;
2010  }
2011 
2012  case OP_LOAD_ACTIVE:
2013  {
2014  if (!OptNews)
2015  break;
2016 
2017  struct NntpAccountData *adata = CurrentNewsSrv;
2018 
2019  if (nntp_newsrc_parse(adata) < 0)
2020  break;
2021 
2022  for (size_t i = 0; i < adata->groups_num; i++)
2023  {
2024  struct NntpMboxData *mdata = adata->groups_list[i];
2025  if (mdata)
2026  mdata->deleted = true;
2027  }
2028  nntp_active_fetch(adata, true);
2029  nntp_newsrc_update(adata);
2030  nntp_newsrc_close(adata);
2031 
2032  destroy_state(&state);
2033  if (mailbox)
2034  examine_mailboxes(menu, &state);
2035  else
2036  {
2037  if (examine_directory(menu, &state, NULL, NULL) == -1)
2038  break;
2039  }
2040  init_menu(&state, menu, title, sizeof(title), mailbox);
2041  break;
2042  }
2043 #endif /* USE_NNTP */
2044 
2045 #if defined(USE_IMAP) || defined(USE_NNTP)
2046  case OP_BROWSER_SUBSCRIBE:
2047  case OP_BROWSER_UNSUBSCRIBE:
2048 #endif
2049 #ifdef USE_NNTP
2050  case OP_SUBSCRIBE_PATTERN:
2051  case OP_UNSUBSCRIBE_PATTERN:
2052  if (OptNews)
2053  {
2054  struct NntpAccountData *adata = CurrentNewsSrv;
2055  regex_t rx;
2056  memset(&rx, 0, sizeof(rx));
2057  char *s = buf->data;
2058  int i = menu->current;
2059 
2060  if ((op == OP_SUBSCRIBE_PATTERN) || (op == OP_UNSUBSCRIBE_PATTERN))
2061  {
2062  char tmp2[256];
2063 
2064  mutt_buffer_reset(buf);
2065  if (op == OP_SUBSCRIBE_PATTERN)
2066  snprintf(tmp2, sizeof(tmp2), _("Subscribe pattern: "));
2067  else
2068  snprintf(tmp2, sizeof(tmp2), _("Unsubscribe pattern: "));
2069  /* buf comes from the buffer pool, so defaults to size 1024 */
2070  if ((mutt_buffer_get_field(tmp2, buf, MUTT_PATTERN) != 0) ||
2071  mutt_buffer_is_empty(buf))
2072  {
2073  break;
2074  }
2075 
2076  int err = REG_COMP(&rx, s, REG_NOSUB);
2077  if (err != 0)
2078  {
2079  regerror(err, &rx, buf->data, buf->dsize);
2080  regfree(&rx);
2081  mutt_error("%s", mutt_b2s(buf));
2082  break;
2083  }
2084  menu->redraw = REDRAW_FULL;
2085  i = 0;
2086  }
2087  else if (ARRAY_EMPTY(&state.entry))
2088  {
2089  mutt_error(_("No newsgroups match the mask"));
2090  break;
2091  }
2092 
2093  int rc = nntp_newsrc_parse(adata);
2094  if (rc < 0)
2095  break;
2096 
2097  ARRAY_FOREACH_FROM(ff, &state.entry, i)
2098  {
2099  if ((op == OP_BROWSER_SUBSCRIBE) || (op == OP_BROWSER_UNSUBSCRIBE) ||
2100  (regexec(&rx, ff->name, 0, NULL, 0) == 0))
2101  {
2102  if ((op == OP_BROWSER_SUBSCRIBE) || (op == OP_SUBSCRIBE_PATTERN))
2103  mutt_newsgroup_subscribe(adata, ff->name);
2104  else
2105  mutt_newsgroup_unsubscribe(adata, ff->name);
2106  }
2107  if ((op == OP_BROWSER_SUBSCRIBE) || (op == OP_BROWSER_UNSUBSCRIBE))
2108  {
2109  if ((menu->current + 1) < menu->max)
2110  menu->current++;
2111  menu->redraw = REDRAW_MOTION_RESYNC;
2112  break;
2113  }
2114  }
2115 
2116  if (op == OP_SUBSCRIBE_PATTERN)
2117  {
2118  for (size_t j = 0; adata && (j < adata->groups_num); j++)
2119  {
2120  struct NntpMboxData *mdata = adata->groups_list[j];
2121  if (mdata && mdata->group && !mdata->subscribed)
2122  {
2123  if (regexec(&rx, mdata->group, 0, NULL, 0) == 0)
2124  {
2125  mutt_newsgroup_subscribe(adata, mdata->group);
2126  add_folder(menu, &state, mdata->group, NULL, NULL, NULL, mdata);
2127  }
2128  }
2129  }
2130  init_menu(&state, menu, title, sizeof(title), mailbox);
2131  }
2132  if (rc > 0)
2133  menu->redraw = REDRAW_FULL;
2134  nntp_newsrc_update(adata);
2135  nntp_clear_cache(adata);
2136  nntp_newsrc_close(adata);
2137  if ((op != OP_BROWSER_SUBSCRIBE) && (op != OP_BROWSER_UNSUBSCRIBE))
2138  regfree(&rx);
2139  }
2140 #ifdef USE_IMAP
2141  else
2142 #endif /* USE_IMAP && USE_NNTP */
2143 #endif /* USE_NNTP */
2144 #ifdef USE_IMAP
2145  {
2146  char tmp2[256];
2147  mutt_str_copy(tmp2, ff->name, sizeof(tmp2));
2148  mutt_expand_path(tmp2, sizeof(tmp2));
2149  imap_subscribe(tmp2, (op == OP_BROWSER_SUBSCRIBE));
2150  }
2151 #endif /* USE_IMAP */
2152  }
2153  }
2154 
2155 bail:
2156  mutt_buffer_pool_release(&OldLastDir);
2159  mutt_buffer_pool_release(&prefix);
2160 
2161  if (menu)
2162  {
2163  mutt_menu_pop_current(menu);
2164  mutt_menu_free(&menu);
2166  }
2167 
2168  goto_swapper[0] = '\0';
2169 }
#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:59
The "current" mailbox.
Definition: context.h:38
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:203
#define REDRAW_FULL
Redraw everything.
Definition: mutt_menu.h:45
bool mutt_mailbox_list(void)
List the mailboxes with new mail.
Definition: mutt_mailbox.c:217
#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:323
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:52
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2367
static void destroy_state(struct BrowserState *state)
Free the BrowserState.
Definition: browser.c:135
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:67
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
#define mutt_message(...)
Definition: logging.h:83
int imap_delete_mailbox(struct Mailbox *m, char *path)
Delete a mailbox.
Definition: imap.c:509
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition: url.h:66
int help_menu
Menu for key bindings, e.g. MENU_PAGER.
Definition: mutt_window.h:134
void nntp_clear_cache(struct NntpAccountData *adata)
Clear the NNTP cache.
Definition: newsrc.c:839
static int file_tag(struct Menu *menu, int sel, int act)
Tag an entry in the menu - Implements Menu::tag()
Definition: browser.c:1090
struct NntpMboxData * mutt_newsgroup_uncatchup(struct Mailbox *m, struct NntpAccountData *adata, char *group)
Uncatchup newsgroup.
Definition: newsrc.c:1332
#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:95
#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:613
String manipulation buffer.
Definition: buffer.h:33
struct NntpMboxData * mutt_newsgroup_subscribe(struct NntpAccountData *adata, char *group)
Subscribe newsgroup.
Definition: newsrc.c:1243
void mutt_unget_event(int ch, int op)
Return a keystroke to the input buffer.
Definition: curs_lib.c:834
#define _(a)
Definition: message.h:28
Mailbox wasn&#39;t recognised.
Definition: mailbox.h:47
struct BrowserStateEntry entry
Definition: browser.h:97
Error occurred examining Mailbox.
Definition: mailbox.h:46
#define REG_COMP(preg, regex, cflags)
Compile a regular expression.
Definition: regex3.h:53
int imap_mailbox_create(const char *path)
Create a new IMAP mailbox.
Definition: browse.c:380
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:115
void nntp_newsrc_close(struct NntpAccountData *adata)
Unlock and close .newsrc file.
Definition: newsrc.c:117
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:71
static void init_lastdir(void)
Initialise the browser directories.
Definition: browser.c:109
void url_free(struct Url **ptr)
Free the contents of a URL.
Definition: url.c:123
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
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::make_entry()
Definition: browser.c:929
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::search()
Definition: browser.c:913
Container for Accounts, Notifications.
Definition: neomutt.h:36
#define MUTT_PATTERN
Pattern mode - only used for history classes.
Definition: mutt.h:64
NNTP-specific Account data -.
Definition: lib.h:75
struct MuttWindow * dialog_create_simple_index(struct Menu *menu, enum WindowType type)
Create a simple index Dialog.
Definition: dialog.c:165
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:91
bool subscribed
Definition: lib.h:147
The body of an email.
Definition: body.h:34
#define MUTT_SEL_FOLDER
Select a local directory.
Definition: browser.h:43
#define CSR_RESULT(x)
Definition: set.h:52
char * HomeDir
User&#39;s home directory.
Definition: mutt_globals.h:49
char * folder
Definition: browser.h:100
bool selectable
Definition: browser.h:77
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:46
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:128
int nntp_active_fetch(struct NntpAccountData *adata, bool mark_new)
Fetch list of all newsgroups from server.
Definition: nntp.c:2052
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:379
static struct Buffer LastDirBackup
Definition: browser.c:102
struct Mailbox * mailbox
Definition: context.h:50
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:56
const char * title
Title of this menu.
Definition: mutt_menu.h:54
Sort by the order the messages appear in the mailbox.
Definition: sort2.h:50
static int examine_mailboxes(struct Menu *menu, struct BrowserState *state)
Get list of mailboxes/subscribed newsgroups.
Definition: browser.c:810
struct Body * mutt_make_file_attach(const char *path, struct ConfigSubset *sub)
Create a file attachment.
Definition: sendlib.c:1082
char * name
Definition: browser.h:66
char * group
Definition: lib.h:140
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:76
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:28
void * mdata
Driver specific data.
Definition: mailbox.h:136
Browser Dialog, mutt_buffer_select_file()
Definition: mutt_window.h:77
&#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
#define REDRAW_MOTION_RESYNC
Redraw any changing the menu selection.
Definition: mutt_menu.h:42
#define mutt_b2s(buf)
Definition: buffer.h:41
int mutt_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question.
Definition: curs_lib.c:933
Browser entry representing a folder/dir.
Definition: browser.h:57
static const struct Mapping FolderNewsHelp[]
Help Bar for the NNTP Mailbox browser dialog.
Definition: browser.c:87
void * mdata
Extra data for the current menu.
Definition: mutt_menu.h:55
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:44
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
const struct Mapping * help_data
Data for the Help Bar.
Definition: mutt_window.h:135
char * data
Pointer to data.
Definition: buffer.h:35
void dialog_destroy_simple_index(struct MuttWindow **ptr)
Destroy a simple index Dialog.
Definition: dialog.c:209
unsigned int groups_num
Definition: lib.h:98
static void browser_sort(struct BrowserState *state)
Sort the entries in the browser.
Definition: browser.c:299
WHERE char * C_Folder
Config: Base folder for a set of mailboxes.
Definition: mutt_globals.h:96
&#39;mmdf&#39; Mailbox type
Definition: mailbox.h:49
bool is_mailbox_list
Definition: mutt_menu.h:62
int nntp_newsrc_parse(struct NntpAccountData *adata)
Parse .newsrc file.
Definition: newsrc.c:161
&#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:1267
int(* tag)(struct Menu *menu, int sel, int act)
Tag some menu items.
Definition: mutt_menu.h:107
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:42
NNTP-specific Mailbox data -.
Definition: lib.h:138
int tagged
Number of tagged entries.
Definition: mutt_menu.h:78
#define MUTT_FILE
Do file completion.
Definition: mutt.h:58
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
char * path
Path.
Definition: url.h:73
int max
Number of entries in the menu.
Definition: mutt_menu.h:57
&#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_buffer_get_field(field, buf, complete)
Definition: curs_lib.h:85
MuttRedrawFlags redraw
When to redraw the screen.
Definition: mutt_menu.h:58
#define MUTT_SEL_MAILBOX
Select a mailbox.
Definition: browser.h:41
static void browser_highlight_default(struct BrowserState *state, struct Menu *menu)
Decide which browser item should be highlighted.
Definition: browser.c:961
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:684
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition: mx.c:1335
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:323
MailboxType
Supported mailbox formats.
Definition: mailbox.h:43
WHERE char * C_Spoolfile
Config: Inbox.
Definition: mutt_globals.h:108
Log at debug level 1.
Definition: logging.h:40
bool deleted
Definition: lib.h:150
Sort by the number of unread emails.
Definition: sort2.h:61
void mutt_browser_select_dir(const char *f)
Remember the last directory selected.
Definition: browser.c:1116
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
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:988
#define REDRAW_INDEX
Redraw the index.
Definition: mutt_menu.h:40
#define ARRAY_REMOVE(head, elem)
Remove an entry from the array, shifting down the subsequent entries.
Definition: array.h:261
#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:179
Sort by the folder&#39;s description.
Definition: sort2.h:65
WHERE char * CurrentFolder
Currently selected mailbox.
Definition: mutt_globals.h:54
void ** groups_list
Definition: lib.h:100
#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:432
static struct Buffer LastDir
Definition: browser.c:101
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:76
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:39
Sort by number of emails in a folder.
Definition: sort2.h:60
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:82
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
int nntp_newsrc_update(struct NntpAccountData *adata)
Update .newsrc file.
Definition: newsrc.c:439
int current
Current entry.
Definition: mutt_menu.h:56
char * pattern
printable version
Definition: regex3.h:90
Sort by the date the email was sent.
Definition: sort2.h:45
static void init_state(struct BrowserState *state, struct Menu *menu)
Initialise a browser state.
Definition: browser.c:664
struct NntpMboxData * mutt_newsgroup_catchup(struct Mailbox *m, struct NntpAccountData *adata, char *group)
Catchup newsgroup.
Definition: newsrc.c:1293
struct MuttWindow * win_index
Definition: mutt_menu.h:63
bool inferiors
Definition: browser.h:78
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:81
static const struct Mapping FolderHelp[]
Help Bar for the File/Dir/Mailbox browser dialog.
Definition: browser.c:74
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
bool imap_browse
Definition: browser.h:99
int(* search)(struct Menu *menu, regex_t *rx, int line)
Search a menu for a item matching a regex.
Definition: mutt_menu.h:98
WHERE struct Regex * C_Mask
Config: Only display files/dirs matching this regex in the browser.
Definition: mutt_globals.h:119
void mutt_get_parent_path(const char *path, char *buf, size_t buflen)
Find the parent of a path (or mailbox)
Definition: muttlib.c:1538
void(* make_entry)(char *buf, size_t buflen, struct Menu *menu, int line)
Format a item for a menu.
Definition: mutt_menu.h:88
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:45
char delim
Definition: browser.h:74
Sort by the email&#39;s subject.
Definition: sort2.h:48
Log at debug level 3.
Definition: logging.h:42
#define SORT_MASK
Mask for the sort id.
Definition: sort2.h:80
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
int imap_subscribe(char *path, bool subscribe)
Subscribe to a mailbox.
Definition: imap.c:1261
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:416
struct Url * url_parse(const char *src)
Fill in Url.
Definition: url.c:234
+ Here is the caller graph for this function:

◆ 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 2179 of file browser.c.

2181 {
2182  struct Buffer *f_buf = mutt_buffer_pool_get();
2183 
2184  mutt_buffer_strcpy(f_buf, NONULL(file));
2185  mutt_buffer_select_file(f_buf, flags, files, numfiles);
2186  mutt_str_copy(file, mutt_b2s(f_buf), filelen);
2187 
2188  mutt_buffer_pool_release(&f_buf);
2189 }
#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:1135
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_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
+ 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 69 of file browser.c.

◆ C_FolderFormat

char* C_FolderFormat

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

Definition at line 70 of file browser.c.

◆ C_SortBrowser

short C_SortBrowser

Config: Sort method for the browser.

Definition at line 71 of file browser.c.

◆ FolderHelp

const struct Mapping FolderHelp[]
static
Initial value:
= {
{ N_("Exit"), OP_EXIT },
{ N_("Chdir"), OP_CHANGE_DIRECTORY },
{ N_("Goto"), OP_BROWSER_GOTO_FOLDER },
{ N_("Mask"), OP_ENTER_MASK },
{ N_("Help"), OP_HELP },
{ NULL, 0 },
}
#define N_(a)
Definition: message.h:32

Help Bar for the File/Dir/Mailbox browser dialog.

Definition at line 74 of file browser.c.

◆ FolderNewsHelp

const struct Mapping FolderNewsHelp[]
static
Initial value:
= {
{ N_("Exit"), OP_EXIT },
{ N_("List"), OP_TOGGLE_MAILBOXES },
{ N_("Subscribe"), OP_BROWSER_SUBSCRIBE },
{ N_("Unsubscribe"), OP_BROWSER_UNSUBSCRIBE },
{ N_("Catchup"), OP_CATCHUP },
{ N_("Mask"), OP_ENTER_MASK },
{ N_("Help"), OP_HELP },
{ NULL, 0 },
}
#define N_(a)
Definition: message.h:32

Help Bar for the NNTP Mailbox browser dialog.

Definition at line 87 of file browser.c.

◆ LastDir

struct Buffer LastDir = { 0 }
static

Definition at line 101 of file browser.c.

◆ LastDirBackup

struct Buffer LastDirBackup = { 0 }
static

Definition at line 102 of file browser.c.