NeoMutt  2020-08-21-74-g346364
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. More...
 
static int browser_compare_desc (const void *a, const void *b)
 Compare the descriptions of two browser entries. More...
 
static int browser_compare_date (const void *a, const void *b)
 Compare the date of two browser entries. More...
 
static int browser_compare_size (const void *a, const void *b)
 Compare the size of two browser entries. More...
 
static int browser_compare_count (const void *a, const void *b)
 Compare the message count of two browser entries. More...
 
static int browser_compare_count_new (const void *a, const void *b)
 Compare the new count of two browser entries. More...
 
static int browser_compare (const void *a, const void *b)
 Sort the items in the browser. 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:95
char * folder
Definition: browser.h:98
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.

Parameters
aFirst browser entry
bSecond browser entry
Return values
-1a precedes b
0a and b are identical
1b precedes a

Definition at line 158 of file browser.c.

159 {
160  const struct FolderFile *pa = (const struct FolderFile *) a;
161  const struct FolderFile *pb = (const struct FolderFile *) b;
162 
163  /* inbox should be sorted ahead of its siblings */
164  int r = mutt_inbox_cmp(pa->name, pb->name);
165  if (r == 0)
166  r = mutt_str_coll(pa->name, pb->name);
167  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
168 }
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:82
+ Here is the call graph for this function:
+ 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.

Parameters
aFirst browser entry
bSecond browser entry
Return values
-1a precedes b
0a and b are identical
1b precedes a

Definition at line 178 of file browser.c.

179 {
180  const struct FolderFile *pa = (const struct FolderFile *) a;
181  const struct FolderFile *pb = (const struct FolderFile *) b;
182 
183  int r = mutt_str_coll(pa->desc, pb->desc);
184 
185  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
186 }
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:82
+ 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.

Parameters
aFirst browser entry
bSecond browser entry
Return values
-1a precedes b
0a and b are identical
1b precedes a

Definition at line 196 of file browser.c.

197 {
198  const struct FolderFile *pa = (const struct FolderFile *) a;
199  const struct FolderFile *pb = (const struct FolderFile *) b;
200 
201  int r = pa->mtime - pb->mtime;
202 
203  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
204 }
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:82
+ 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.

Parameters
aFirst browser entry
bSecond browser entry
Return values
-1a precedes b
0a and b are identical
1b precedes a

Definition at line 214 of file browser.c.

215 {
216  const struct FolderFile *pa = (const struct FolderFile *) a;
217  const struct FolderFile *pb = (const struct FolderFile *) b;
218 
219  int r = pa->size - pb->size;
220 
221  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
222 }
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:82
+ 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.

Parameters
aFirst browser entry
bSecond browser entry
Return values
-1a precedes b
0a and b are identical
1b precedes a

Definition at line 232 of file browser.c.

233 {
234  const struct FolderFile *pa = (const struct FolderFile *) a;
235  const struct FolderFile *pb = (const struct FolderFile *) b;
236 
237  int r = 0;
238  if (pa->has_mailbox && pb->has_mailbox)
239  r = pa->msg_count - pb->msg_count;
240  else if (pa->has_mailbox)
241  r = -1;
242  else
243  r = 1;
244 
245  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
246 }
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:82
+ 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.

Parameters
aFirst browser entry
bSecond browser entry
Return values
-1a precedes b
0a and b are identical
1b precedes a

Definition at line 256 of file browser.c.

257 {
258  const struct FolderFile *pa = (const struct FolderFile *) a;
259  const struct FolderFile *pb = (const struct FolderFile *) b;
260 
261  int r = 0;
262  if (pa->has_mailbox && pb->has_mailbox)
263  r = pa->msg_unread - pb->msg_unread;
264  else if (pa->has_mailbox)
265  r = -1;
266  else
267  r = 1;
268 
269  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
270 }
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:82
+ 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.

Parameters
aFirst item
bSecond item
Return values
-1a precedes b
0a and b are identical
1b precedes a

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

285 {
286  const struct FolderFile *pa = (const struct FolderFile *) a;
287  const struct FolderFile *pb = (const struct FolderFile *) b;
288 
289  if ((mutt_str_coll(pa->desc, "../") == 0) || (mutt_str_coll(pa->desc, "..") == 0))
290  return -1;
291  if ((mutt_str_coll(pb->desc, "../") == 0) || (mutt_str_coll(pb->desc, "..") == 0))
292  return 1;
293 
294  switch (C_SortBrowser & SORT_MASK)
295  {
296  case SORT_COUNT:
297  return browser_compare_count(a, b);
298  case SORT_DATE:
299  return browser_compare_date(a, b);
300  case SORT_DESC:
301  return browser_compare_desc(a, b);
302  case SORT_SIZE:
303  return browser_compare_size(a, b);
304  case SORT_UNREAD:
305  return browser_compare_count_new(a, b);
306  case SORT_SUBJECT:
307  default:
308  return browser_compare_subject(a, b);
309  }
310 }
static int browser_compare_date(const void *a, const void *b)
Compare the date of two browser entries.
Definition: browser.c:196
char * desc
Definition: browser.h:67
static int browser_compare_desc(const void *a, const void *b)
Compare the descriptions of two browser entries.
Definition: browser.c:178
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.
Definition: browser.c:232
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:47
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.
Definition: browser.c:256
static int browser_compare_size(const void *a, const void *b)
Compare the size of two browser entries.
Definition: browser.c:214
static int browser_compare_subject(const void *a, const void *b)
Compare the subject of two browser entries.
Definition: browser.c:158
Sort by the number of unread emails.
Definition: sort2.h:62
Sort by the folder&#39;s description.
Definition: sort2.h:66
Sort by number of emails in a folder.
Definition: sort2.h:61
Sort by the date the email was sent.
Definition: sort2.h:46
Sort by the email&#39;s subject.
Definition: sort2.h:49
#define SORT_MASK
Mask for the sort id.
Definition: sort2.h:81
+ 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 319 of file browser.c.

320 {
321  switch (C_SortBrowser & SORT_MASK)
322  {
323  /* Also called "I don't care"-sort-method. */
324  case SORT_ORDER:
325  return;
326 #ifdef USE_NNTP
327  case SORT_SIZE:
328  case SORT_DATE:
329  if (OptNews)
330  return;
331 #endif
332  default:
333  break;
334  }
335 
336  ARRAY_SORT(&state->entry, browser_compare);
337 }
struct BrowserStateEntry entry
Definition: browser.h:95
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:71
Sort by the size of the email.
Definition: sort2.h:47
Sort by the order the messages appear in the mailbox.
Definition: sort2.h:51
#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.
Definition: browser.c:284
Sort by the date the email was sent.
Definition: sort2.h:46
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:45
#define SORT_MASK
Mask for the sort id.
Definition: sort2.h:81
+ 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 346 of file browser.c.

347 {
348  struct stat st;
349  bool retval = false;
350 
351  struct Buffer *fullpath = mutt_buffer_pool_get();
352  mutt_buffer_concat_path(fullpath, folder, path);
353 
354  if (stat(mutt_b2s(fullpath), &st) == 0)
355  retval = S_ISDIR(st.st_mode);
356 
357  mutt_buffer_pool_release(&fullpath);
358 
359  return retval;
360 }
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 382 of file browser.c.

386 {
387  char fn[128], fmt[128];
388  struct Folder *folder = (struct Folder *) data;
389  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
390 
391  switch (op)
392  {
393  case 'C':
394  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
395  snprintf(buf, buflen, fmt, folder->num + 1);
396  break;
397 
398  case 'd':
399  case 'D':
400  if (folder->ff->local)
401  {
402  bool do_locales = true;
403 
404  char *t_fmt = NULL;
405  if (op == 'D')
406  {
407  t_fmt = NONULL(C_DateFormat);
408  if (*t_fmt == '!')
409  {
410  t_fmt++;
411  do_locales = false;
412  }
413  }
414  else
415  {
416  static const time_t one_year = 31536000;
417  t_fmt = ((mutt_date_epoch() - folder->ff->mtime) < one_year) ?
418  "%b %d %H:%M" :
419  "%b %d %Y";
420  }
421 
422  if (!do_locales)
423  setlocale(LC_TIME, "C");
424  char date[128];
425  mutt_date_localtime_format(date, sizeof(date), t_fmt, folder->ff->mtime);
426  if (!do_locales)
427  setlocale(LC_TIME, "");
428 
429  mutt_format_s(buf, buflen, prec, date);
430  }
431  else
432  mutt_format_s(buf, buflen, prec, "");
433  break;
434 
435  case 'f':
436  {
437  char *s = NULL;
438 
439  s = NONULL(folder->ff->name);
440 
441  snprintf(fn, sizeof(fn), "%s%s", s,
442  folder->ff->local ?
443  (S_ISLNK(folder->ff->mode) ?
444  "@" :
445  (S_ISDIR(folder->ff->mode) ?
446  "/" :
447  (((folder->ff->mode & S_IXUSR) != 0) ? "*" : ""))) :
448  "");
449 
450  mutt_format_s(buf, buflen, prec, fn);
451  break;
452  }
453  case 'F':
454  {
455  if (folder->ff->local)
456  {
457  char permission[11];
458  snprintf(permission, sizeof(permission), "%c%c%c%c%c%c%c%c%c%c",
459  S_ISDIR(folder->ff->mode) ? 'd' : (S_ISLNK(folder->ff->mode) ? 'l' : '-'),
460  ((folder->ff->mode & S_IRUSR) != 0) ? 'r' : '-',
461  ((folder->ff->mode & S_IWUSR) != 0) ? 'w' : '-',
462  ((folder->ff->mode & S_ISUID) != 0) ?
463  's' :
464  ((folder->ff->mode & S_IXUSR) != 0) ? 'x' : '-',
465  ((folder->ff->mode & S_IRGRP) != 0) ? 'r' : '-',
466  ((folder->ff->mode & S_IWGRP) != 0) ? 'w' : '-',
467  ((folder->ff->mode & S_ISGID) != 0) ?
468  's' :
469  ((folder->ff->mode & S_IXGRP) != 0) ? 'x' : '-',
470  ((folder->ff->mode & S_IROTH) != 0) ? 'r' : '-',
471  ((folder->ff->mode & S_IWOTH) != 0) ? 'w' : '-',
472  ((folder->ff->mode & S_ISVTX) != 0) ?
473  't' :
474  ((folder->ff->mode & S_IXOTH) != 0) ? 'x' : '-');
475  mutt_format_s(buf, buflen, prec, permission);
476  }
477 #ifdef USE_IMAP
478  else if (folder->ff->imap)
479  {
480  char permission[11];
481  /* mark folders with subfolders AND mail */
482  snprintf(permission, sizeof(permission), "IMAP %c",
483  (folder->ff->inferiors && folder->ff->selectable) ? '+' : ' ');
484  mutt_format_s(buf, buflen, prec, permission);
485  }
486 #endif
487  else
488  mutt_format_s(buf, buflen, prec, "");
489  break;
490  }
491 
492  case 'g':
493  if (folder->ff->local)
494  {
495  struct group *gr = getgrgid(folder->ff->gid);
496  if (gr)
497  mutt_format_s(buf, buflen, prec, gr->gr_name);
498  else
499  {
500  snprintf(fmt, sizeof(fmt), "%%%sld", prec);
501  snprintf(buf, buflen, fmt, folder->ff->gid);
502  }
503  }
504  else
505  mutt_format_s(buf, buflen, prec, "");
506  break;
507 
508  case 'i':
509  {
510  char *s = NULL;
511  if (folder->ff->desc)
512  s = folder->ff->desc;
513  else
514  s = folder->ff->name;
515 
516  snprintf(fn, sizeof(fn), "%s%s", s,
517  folder->ff->local ?
518  (S_ISLNK(folder->ff->mode) ?
519  "@" :
520  (S_ISDIR(folder->ff->mode) ?
521  "/" :
522  (((folder->ff->mode & S_IXUSR) != 0) ? "*" : ""))) :
523  "");
524 
525  mutt_format_s(buf, buflen, prec, fn);
526  break;
527  }
528 
529  case 'l':
530  if (folder->ff->local)
531  {
532  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
533  snprintf(buf, buflen, fmt, folder->ff->nlink);
534  }
535  else
536  mutt_format_s(buf, buflen, prec, "");
537  break;
538 
539  case 'm':
540  if (!optional)
541  {
542  if (folder->ff->has_mailbox)
543  {
544  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
545  snprintf(buf, buflen, fmt, folder->ff->msg_count);
546  }
547  else
548  mutt_format_s(buf, buflen, prec, "");
549  }
550  else if (folder->ff->msg_count == 0)
551  optional = false;
552  break;
553 
554  case 'N':
555  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
556  snprintf(buf, buflen, fmt, folder->ff->has_new_mail ? 'N' : ' ');
557  break;
558 
559  case 'n':
560  if (!optional)
561  {
562  if (folder->ff->has_mailbox)
563  {
564  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
565  snprintf(buf, buflen, fmt, folder->ff->msg_unread);
566  }
567  else
568  mutt_format_s(buf, buflen, prec, "");
569  }
570  else if (folder->ff->msg_unread == 0)
571  optional = false;
572  break;
573 
574  case 's':
575  if (folder->ff->local)
576  {
577  mutt_str_pretty_size(fn, sizeof(fn), folder->ff->size);
578  snprintf(fmt, sizeof(fmt), "%%%ss", prec);
579  snprintf(buf, buflen, fmt, fn);
580  }
581  else
582  mutt_format_s(buf, buflen, prec, "");
583  break;
584 
585  case 't':
586  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
587  snprintf(buf, buflen, fmt, folder->ff->tagged ? '*' : ' ');
588  break;
589 
590  case 'u':
591  if (folder->ff->local)
592  {
593  struct passwd *pw = getpwuid(folder->ff->uid);
594  if (pw)
595  mutt_format_s(buf, buflen, prec, pw->pw_name);
596  else
597  {
598  snprintf(fmt, sizeof(fmt), "%%%sld", prec);
599  snprintf(buf, buflen, fmt, folder->ff->uid);
600  }
601  }
602  else
603  mutt_format_s(buf, buflen, prec, "");
604  break;
605 
606  default:
607  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
608  snprintf(buf, buflen, fmt, op);
609  break;
610  }
611 
612  if (optional)
613  {
614  mutt_expando_format(buf, buflen, col, cols, if_str, folder_format_str, data,
616  }
617  else if (flags & MUTT_FORMAT_OPTIONAL)
618  {
619  mutt_expando_format(buf, buflen, col, cols, else_str, folder_format_str,
620  data, MUTT_FORMAT_NO_FLAGS);
621  }
622 
623  return src;
624 }
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:382
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 636 of file browser.c.

639 {
640  if ((!menu || menu->is_mailbox_list) && m && (m->flags & MB_HIDDEN))
641  {
642  return;
643  }
644 
645  struct FolderFile ff = { 0 };
646 
647  if (s)
648  {
649  ff.mode = s->st_mode;
650  ff.mtime = s->st_mtime;
651  ff.size = s->st_size;
652  ff.gid = s->st_gid;
653  ff.uid = s->st_uid;
654  ff.nlink = s->st_nlink;
655  ff.local = true;
656  }
657  else
658  ff.local = false;
659 
660  if (m)
661  {
662  ff.has_mailbox = true;
663  ff.has_new_mail = m->has_new;
664  ff.msg_count = m->msg_count;
665  ff.msg_unread = m->msg_unread;
666  }
667 
668  ff.name = mutt_str_dup(name);
669  ff.desc = mutt_str_dup(desc ? desc : name);
670 #ifdef USE_IMAP
671  ff.imap = false;
672 #endif
673 #ifdef USE_NNTP
674  if (OptNews)
675  ff.nd = data;
676 #endif
677 
678  ARRAY_ADD(&state->entry, ff);
679 }
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:95
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
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 686 of file browser.c.

687 {
688  ARRAY_INIT(&state->entry);
689  ARRAY_RESERVE(&state->entry, 256);
690 #ifdef USE_IMAP
691  state->imap_browse = false;
692 #endif
693  if (menu)
694  menu->mdata = &state->entry;
695 }
#define ARRAY_RESERVE(head, num)
Reserve memory for the array.
Definition: array.h:185
struct BrowserStateEntry entry
Definition: browser.h:95
void * mdata
Extra data for the current menu.
Definition: mutt_menu.h:55
bool imap_browse
Definition: browser.h:97
#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 706 of file browser.c.

708 {
709  int rc = -1;
710  struct Buffer *buf = mutt_buffer_pool_get();
711 #ifdef USE_NNTP
712  if (OptNews)
713  {
715 
716  init_state(state, menu);
717 
718  for (unsigned int i = 0; i < adata->groups_num; i++)
719  {
720  struct NntpMboxData *mdata = adata->groups_list[i];
721  if (!mdata)
722  continue;
723  if (prefix && *prefix && !mutt_str_startswith(mdata->group, prefix))
724  continue;
725  if (!mutt_regex_match(C_Mask, mdata->group))
726  {
727  continue;
728  }
729  add_folder(menu, state, mdata->group, NULL, NULL, NULL, mdata);
730  }
731  }
732  else
733 #endif /* USE_NNTP */
734  {
735  struct stat s;
736  DIR *dp = NULL;
737  struct dirent *de = NULL;
738 
739  while (stat(d, &s) == -1)
740  {
741  if (errno == ENOENT)
742  {
743  /* The last used directory is deleted, try to use the parent dir. */
744  char *c = strrchr(d, '/');
745 
746  if (c && (c > d))
747  {
748  *c = '\0';
749  continue;
750  }
751  }
752  mutt_perror(d);
753  goto ed_out;
754  }
755 
756  if (!S_ISDIR(s.st_mode))
757  {
758  mutt_error(_("%s is not a directory"), d);
759  goto ed_out;
760  }
761 
762  if (Context && Context->mailbox)
764 
765  dp = opendir(d);
766  if (!dp)
767  {
768  mutt_perror(d);
769  goto ed_out;
770  }
771 
772  init_state(state, menu);
773 
774  struct MailboxList ml = STAILQ_HEAD_INITIALIZER(ml);
776  while ((de = readdir(dp)))
777  {
778  if (mutt_str_equal(de->d_name, "."))
779  continue; /* we don't need . */
780 
781  if (prefix && *prefix && !mutt_str_startswith(de->d_name, prefix))
782  {
783  continue;
784  }
785  if (!mutt_regex_match(C_Mask, de->d_name))
786  {
787  continue;
788  }
789 
790  mutt_buffer_concat_path(buf, d, de->d_name);
791  if (lstat(mutt_b2s(buf), &s) == -1)
792  continue;
793 
794  /* No size for directories or symlinks */
795  if (S_ISDIR(s.st_mode) || S_ISLNK(s.st_mode))
796  s.st_size = 0;
797  else if (!S_ISREG(s.st_mode))
798  continue;
799 
800  struct MailboxNode *np = NULL;
801  STAILQ_FOREACH(np, &ml, entries)
802  {
804  break;
805  }
806 
807  if (np && Context && Context->mailbox &&
809  {
812  }
813  add_folder(menu, state, de->d_name, NULL, &s, np ? np->mailbox : NULL, NULL);
814  }
816  closedir(dp);
817  }
818  browser_sort(state);
819  rc = 0;
820 ed_out:
822  return rc;
823 }
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:201
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:636
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:319
#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:150
static void init_state(struct BrowserState *state, struct Menu *menu)
Initialise a browser state.
Definition: browser.c:686
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:152
+ 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 832 of file browser.c.

833 {
834  struct stat s;
835  struct Buffer *md = NULL;
836  struct Buffer *mailbox = NULL;
837 
838 #ifdef USE_NNTP
839  if (OptNews)
840  {
842 
843  init_state(state, menu);
844 
845  for (unsigned int i = 0; i < adata->groups_num; i++)
846  {
847  struct NntpMboxData *mdata = adata->groups_list[i];
848  if (mdata && (mdata->has_new_mail ||
849  (mdata->subscribed && (mdata->unread || !C_ShowOnlyUnread))))
850  {
851  add_folder(menu, state, mdata->group, NULL, NULL, NULL, mdata);
852  }
853  }
854  }
855  else
856 #endif
857  {
858  init_state(state, menu);
859 
861  return -1;
862  mailbox = mutt_buffer_pool_get();
863  md = mutt_buffer_pool_get();
865 
866  struct MailboxList ml = STAILQ_HEAD_INITIALIZER(ml);
868  struct MailboxNode *np = NULL;
869  STAILQ_FOREACH(np, &ml, entries)
870  {
871  if (!np->mailbox)
872  continue;
873 
874  if (Context && Context->mailbox &&
876  {
879  }
880 
881  mutt_buffer_strcpy(mailbox, mailbox_path(np->mailbox));
884 
885  switch (np->mailbox->type)
886  {
887  case MUTT_IMAP:
888  case MUTT_POP:
889  add_folder(menu, state, mutt_b2s(mailbox), np->mailbox->name, NULL,
890  np->mailbox, NULL);
891  continue;
892  case MUTT_NOTMUCH:
893  case MUTT_NNTP:
894  add_folder(menu, state, mailbox_path(np->mailbox), np->mailbox->name,
895  NULL, np->mailbox, NULL);
896  continue;
897  default: /* Continue */
898  break;
899  }
900 
901  if (lstat(mailbox_path(np->mailbox), &s) == -1)
902  continue;
903 
904  if ((!S_ISREG(s.st_mode)) && (!S_ISDIR(s.st_mode)) && (!S_ISLNK(s.st_mode)))
905  continue;
906 
907  if (np->mailbox->type == MUTT_MAILDIR)
908  {
909  struct stat st2;
910 
911  mutt_buffer_printf(md, "%s/new", mailbox_path(np->mailbox));
912  if (stat(mutt_b2s(md), &s) < 0)
913  s.st_mtime = 0;
914  mutt_buffer_printf(md, "%s/cur", mailbox_path(np->mailbox));
915  if (stat(mutt_b2s(md), &st2) < 0)
916  st2.st_mtime = 0;
917  if (st2.st_mtime > s.st_mtime)
918  s.st_mtime = st2.st_mtime;
919  }
920 
921  add_folder(menu, state, mutt_b2s(mailbox), np->mailbox->name, &s, np->mailbox, NULL);
922  }
924  }
925  browser_sort(state);
926 
927  mutt_buffer_pool_release(&mailbox);
929  return 0;
930 }
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:201
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:636
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:319
#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:150
#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:686
&#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:152
+ 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 935 of file browser.c.

936 {
937  struct BrowserStateEntry *entry = menu->mdata;
938 #ifdef USE_NNTP
939  if (OptNews)
940  return regexec(rx, ARRAY_GET(entry, line)->desc, 0, NULL, 0);
941 #endif
942  struct FolderFile *ff = ARRAY_GET(entry, line);
943  char *search_on = ff->desc ? ff->desc : ff->name;
944 
945  return regexec(rx, search_on, 0, NULL, 0);
946 }
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 951 of file browser.c.

952 {
953  struct BrowserStateEntry *entry = menu->mdata;
954  struct Folder folder = {
955  .ff = ARRAY_GET(entry, line),
956  .num = line,
957  };
958 
959 #ifdef USE_NNTP
960  if (OptNews)
961  {
962  mutt_expando_format(buf, buflen, 0, menu->win_index->state.cols,
964  (intptr_t) &folder, MUTT_FORMAT_ARROWCURSOR);
965  }
966  else
967 #endif
968  {
969  mutt_expando_format(buf, buflen, 0, menu->win_index->state.cols,
971  (intptr_t) &folder, MUTT_FORMAT_ARROWCURSOR);
972  }
973 }
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:382
#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 983 of file browser.c.

984 {
985  menu->top = 0;
986  /* Reset menu position to 1.
987  * We do not risk overflow as the init_menu function changes
988  * current if it is bigger than state->entrylen. */
989  if (!ARRAY_EMPTY(&state->entry) &&
990  (mutt_str_equal(ARRAY_FIRST(&state->entry)->desc, "..") ||
991  mutt_str_equal(ARRAY_FIRST(&state->entry)->desc, "../")))
992  {
993  /* Skip the first entry, unless there's only one entry. */
994  menu->current = (menu->max > 1);
995  }
996  else
997  {
998  menu->current = 0;
999  }
1000 }
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:95
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 1010 of file browser.c.

1012 {
1013  menu->max = ARRAY_SIZE(&state->entry);
1014 
1015  if (menu->current >= menu->max)
1016  menu->current = menu->max - 1;
1017  if (menu->current < 0)
1018  menu->current = 0;
1019  if (menu->top > menu->current)
1020  menu->top = 0;
1021 
1022  menu->tagged = 0;
1023 
1024 #ifdef USE_NNTP
1025  if (OptNews)
1026  {
1027  if (mailbox)
1028  snprintf(title, titlelen, _("Subscribed newsgroups"));
1029  else
1030  {
1031  snprintf(title, titlelen, _("Newsgroups on server [%s]"),
1033  }
1034  }
1035  else
1036 #endif
1037  {
1038  if (mailbox)
1039  {
1040  menu->is_mailbox_list = true;
1041  snprintf(title, titlelen, _("Mailboxes [%d]"),
1042  mutt_mailbox_check(Context ? Context->mailbox : NULL, 0));
1043  }
1044  else
1045  {
1046  struct Buffer *path = mutt_buffer_pool_get();
1047  menu->is_mailbox_list = false;
1048  mutt_buffer_copy(path, &LastDir);
1050 #ifdef USE_IMAP
1051  if (state->imap_browse && C_ImapListSubscribed)
1052  {
1053  snprintf(title, titlelen, _("Subscribed [%s], File mask: %s"),
1054  mutt_b2s(path), NONULL(C_Mask ? C_Mask->pattern : NULL));
1055  }
1056  else
1057 #endif
1058  {
1059  snprintf(title, titlelen, _("Directory [%s], File mask: %s"),
1060  mutt_b2s(path), NONULL(C_Mask ? C_Mask->pattern : NULL));
1061  }
1062  mutt_buffer_pool_release(&path);
1063  }
1064  }
1065 
1066  /* Browser tracking feature.
1067  * The goal is to highlight the good directory if LastDir is the parent dir
1068  * of LastDirBackup (this occurs mostly when one hit "../"). It should also work
1069  * properly when the user is in examine_mailboxes-mode. */
1071  {
1072  char target_dir[PATH_MAX] = { 0 };
1073 
1074 #ifdef USE_IMAP
1075  /* Check what kind of dir LastDirBackup is. */
1077  {
1078  mutt_str_copy(target_dir, mutt_b2s(&LastDirBackup), sizeof(target_dir));
1079  imap_clean_path(target_dir, sizeof(target_dir));
1080  }
1081  else
1082 #endif
1083  mutt_str_copy(target_dir, strrchr(mutt_b2s(&LastDirBackup), '/') + 1,
1084  sizeof(target_dir));
1085 
1086  /* If we get here, it means that LastDir is the parent directory of
1087  * LastDirBackup. I.e., we're returning from a subdirectory, and we want
1088  * to position the cursor on the directory we're returning from. */
1089  bool matched = false;
1090  struct FolderFile *ff = NULL;
1091  ARRAY_FOREACH(ff, &state->entry)
1092  {
1093  if (mutt_str_equal(ff->name, target_dir))
1094  {
1095  menu->current = ARRAY_FOREACH_IDX;
1096  matched = true;
1097  break;
1098  }
1099  }
1100  if (!matched)
1101  browser_highlight_default(state, menu);
1102  }
1103  else
1104  browser_highlight_default(state, menu);
1105 
1106  menu->redraw = REDRAW_FULL;
1107 }
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:2370
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:95
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:48
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:983
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:97
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 1112 of file browser.c.

1113 {
1114  struct BrowserStateEntry *entry = menu->mdata;
1115  struct FolderFile *ff = ARRAY_GET(entry, sel);
1116  if (S_ISDIR(ff->mode) || (S_ISLNK(ff->mode) && link_is_dir(mutt_b2s(&LastDir), ff->name)))
1117  {
1118  mutt_error(_("Can't attach a directory"));
1119  return 0;
1120  }
1121 
1122  bool ot = ff->tagged;
1123  ff->tagged = ((act >= 0) ? act : !ff->tagged);
1124 
1125  return ff->tagged - ot;
1126 }
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:346
#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 1138 of file browser.c.

1139 {
1140  init_lastdir();
1141 
1143 
1144  /* Method that will fetch the parent path depending on the type of the path. */
1145  char buf[PATH_MAX];
1146  mutt_get_parent_path(mutt_b2s(&LastDirBackup), buf, sizeof(buf));
1147  mutt_buffer_strcpy(&LastDir, buf);
1148 }
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 1157 of file browser.c.

1159 {
1160  char title[256];
1161  struct BrowserState state = { 0 };
1162  struct Menu *menu = NULL;
1163  bool kill_prefix = false;
1164  bool multiple = (flags & MUTT_SEL_MULTI);
1165  bool folder = (flags & MUTT_SEL_FOLDER);
1166  bool mailbox = (flags & MUTT_SEL_MAILBOX);
1167 
1168  /* Keeps in memory the directory we were in when hitting '='
1169  * to go directly to $folder (#C_Folder) */
1170  char goto_swapper[PATH_MAX] = { 0 };
1171 
1172  mailbox = mailbox && folder;
1173 
1174  struct Buffer *OldLastDir = mutt_buffer_pool_get();
1175  struct Buffer *tmp = mutt_buffer_pool_get();
1176  struct Buffer *buf = mutt_buffer_pool_get();
1177  struct Buffer *prefix = mutt_buffer_pool_get();
1178 
1179  init_lastdir();
1180 
1181 #ifdef USE_NNTP
1182  if (OptNews)
1183  {
1184  if (mutt_buffer_is_empty(file))
1185  {
1187 
1188  /* default state for news reader mode is browse subscribed newsgroups */
1189  mailbox = false;
1190  for (size_t i = 0; i < adata->groups_num; i++)
1191  {
1192  struct NntpMboxData *mdata = adata->groups_list[i];
1193  if (mdata && mdata->subscribed)
1194  {
1195  mailbox = true;
1196  break;
1197  }
1198  }
1199  }
1200  else
1201  {
1202  mutt_buffer_copy(prefix, file);
1203  }
1204  }
1205  else
1206 #endif
1207  if (!mutt_buffer_is_empty(file))
1208  {
1210 #ifdef USE_IMAP
1211  if (imap_path_probe(mutt_b2s(file), NULL) == MUTT_IMAP)
1212  {
1213  init_state(&state, NULL);
1214  state.imap_browse = true;
1215  if (imap_browse(mutt_b2s(file), &state) == 0)
1216  {
1218  browser_sort(&state);
1219  }
1220  }
1221  else
1222  {
1223 #endif
1224  int i;
1225  for (i = mutt_buffer_len(file) - 1; (i > 0) && ((mutt_b2s(file))[i] != '/'); i--)
1226  ; // do nothing
1227 
1228  if (i > 0)
1229  {
1230  if ((mutt_b2s(file))[0] == '/')
1232  else
1233  {
1235  mutt_buffer_addch(&LastDir, '/');
1237  }
1238  }
1239  else
1240  {
1241  if ((mutt_b2s(file))[0] == '/')
1242  mutt_buffer_strcpy(&LastDir, "/");
1243  else
1245  }
1246 
1247  if ((i <= 0) && (mutt_b2s(file)[0] != '/'))
1248  mutt_buffer_copy(prefix, file);
1249  else
1250  mutt_buffer_strcpy(prefix, mutt_b2s(file) + i + 1);
1251  kill_prefix = true;
1252 #ifdef USE_IMAP
1253  }
1254 #endif
1255  }
1256  else
1257  {
1258  if (!folder)
1260  else
1261  {
1262  /* Whether we use the tracking feature of the browser depends
1263  * on which sort method we chose to use. This variable is defined
1264  * only to help readability of the code. */
1265  bool browser_track = false;
1266 
1267  switch (C_SortBrowser & SORT_MASK)
1268  {
1269  case SORT_DESC:
1270  case SORT_SUBJECT:
1271  case SORT_ORDER:
1272  browser_track = true;
1273  break;
1274  }
1275 
1276  /* We use mutt_browser_select_dir to initialize the two
1277  * variables (LastDir, LastDirBackup) at the appropriate
1278  * values.
1279  *
1280  * We do it only when LastDir is not set (first pass there)
1281  * or when CurrentFolder and LastDirBackup are not the same.
1282  * This code is executed only when we list files, not when
1283  * we press up/down keys to navigate in a displayed list.
1284  *
1285  * We only do this when CurrentFolder has been set (ie, not
1286  * when listing folders on startup with "neomutt -y").
1287  *
1288  * This tracker is only used when browser_track is true,
1289  * meaning only with sort methods SUBJECT/DESC for now. */
1290  if (CurrentFolder)
1291  {
1293  {
1294  /* If browsing in "local"-mode, than we chose to define LastDir to
1295  * MailDir */
1296  switch (mx_path_probe(CurrentFolder))
1297  {
1298  case MUTT_IMAP:
1299  case MUTT_MAILDIR:
1300  case MUTT_MBOX:
1301  case MUTT_MH:
1302  case MUTT_MMDF:
1303  if (C_Folder)
1305  else if (C_Spoolfile)
1307  break;
1308  default:
1310  break;
1311  }
1312  }
1314  {
1316  }
1317  }
1318 
1319  /* When browser tracking feature is disabled, clear LastDirBackup */
1320  if (!browser_track)
1322  }
1323 
1324 #ifdef USE_IMAP
1325  if (!mailbox && (imap_path_probe(mutt_b2s(&LastDir), NULL) == MUTT_IMAP))
1326  {
1327  init_state(&state, NULL);
1328  state.imap_browse = true;
1329  imap_browse(mutt_b2s(&LastDir), &state);
1330  browser_sort(&state);
1331  }
1332  else
1333 #endif
1334  {
1335  size_t i = mutt_buffer_len(&LastDir);
1336  while ((i > 0) && (mutt_b2s(&LastDir)[--i] == '/'))
1337  LastDir.data[i] = '\0';
1341  }
1342  }
1343 
1344  mutt_buffer_reset(file);
1345 
1346  menu = mutt_menu_new(MENU_FOLDER);
1348 
1349 #ifdef USE_NNTP
1350  if (OptNews)
1351  dlg->help_data = FolderNewsHelp;
1352  else
1353 #endif
1354  dlg->help_data = FolderHelp;
1355  dlg->help_menu = MENU_FOLDER;
1356 
1357  menu->make_entry = folder_make_entry;
1358  menu->search = select_file_search;
1359  menu->title = title;
1360  if (multiple)
1361  menu->tag = file_tag;
1362 
1363  mutt_menu_push_current(menu);
1364 
1365  if (mailbox)
1366  {
1367  examine_mailboxes(NULL, &state);
1368  }
1369  else
1370 #ifdef USE_IMAP
1371  if (!state.imap_browse)
1372 #endif
1373  {
1374  // examine_directory() calls add_folder() which needs the menu
1375  if (examine_directory(menu, &state, mutt_b2s(&LastDir), mutt_b2s(prefix)) == -1)
1376  goto bail;
1377  }
1378 
1379  init_menu(&state, menu, title, sizeof(title), mailbox);
1380  // only now do we have a valid state to attach
1381  menu->mdata = &state.entry;
1382 
1383  while (true)
1384  {
1385  int op = mutt_menu_loop(menu);
1386  if (op >= 0)
1387  mutt_debug(LL_DEBUG1, "Got op %s (%d)\n", OpStrings[op][0], op);
1388  struct FolderFile *ff = ARRAY_GET(&state.entry, menu->current);
1389  switch (op)
1390  {
1391  case OP_DESCEND_DIRECTORY:
1392  case OP_GENERIC_SELECT_ENTRY:
1393  {
1394  if (ARRAY_EMPTY(&state.entry))
1395  {
1396  mutt_error(_("No files match the file mask"));
1397  break;
1398  }
1399 
1400  if (S_ISDIR(ff->mode) ||
1401  (S_ISLNK(ff->mode) && link_is_dir(mutt_b2s(&LastDir), ff->name))
1402 #ifdef USE_IMAP
1403  || ff->inferiors
1404 #endif
1405  )
1406  {
1407  /* make sure this isn't a MH or maildir mailbox */
1408  if (mailbox)
1409  {
1410  mutt_buffer_strcpy(buf, ff->name);
1412  }
1413 #ifdef USE_IMAP
1414  else if (state.imap_browse)
1415  {
1416  mutt_buffer_strcpy(buf, ff->name);
1417  }
1418 #endif
1419  else
1420  {
1422  }
1423 
1424  enum MailboxType type = mx_path_probe(mutt_b2s(buf));
1425  if ((op == OP_DESCEND_DIRECTORY) || (type == MUTT_MAILBOX_ERROR) ||
1426  (type == MUTT_UNKNOWN)
1427 #ifdef USE_IMAP
1428  || ff->inferiors
1429 #endif
1430  )
1431  {
1432  /* save the old directory */
1433  mutt_buffer_copy(OldLastDir, &LastDir);
1434 
1435  if (mutt_str_equal(ff->name, ".."))
1436  {
1437  size_t lastdirlen = mutt_buffer_len(&LastDir);
1438  if ((lastdirlen > 1) &&
1439  mutt_str_equal("..", mutt_b2s(&LastDir) + lastdirlen - 2))
1440  {
1441  mutt_buffer_addstr(&LastDir, "/..");
1442  }
1443  else
1444  {
1445  char *p = NULL;
1446  if (lastdirlen > 1)
1447  p = strrchr(mutt_b2s(&LastDir) + 1, '/');
1448 
1449  if (p)
1450  {
1451  *p = '\0';
1453  }
1454  else
1455  {
1456  if (mutt_b2s(&LastDir)[0] == '/')
1457  mutt_buffer_strcpy(&LastDir, "/");
1458  else
1459  mutt_buffer_addstr(&LastDir, "/..");
1460  }
1461  }
1462  }
1463  else if (mailbox)
1464  {
1467  }
1468 #ifdef USE_IMAP
1469  else if (state.imap_browse)
1470  {
1472  /* tack on delimiter here */
1473 
1474  /* special case "" needs no delimiter */
1475  struct Url *url = url_parse(ff->name);
1476  if (url->path && (ff->delim != '\0'))
1477  {
1479  }
1480  url_free(&url);
1481  }
1482 #endif
1483  else
1484  {
1486  mutt_buffer_copy(&LastDir, tmp);
1487  }
1488 
1489  destroy_state(&state);
1490  if (kill_prefix)
1491  {
1492  mutt_buffer_reset(prefix);
1493  kill_prefix = false;
1494  }
1495  mailbox = false;
1496 #ifdef USE_IMAP
1497  if (state.imap_browse)
1498  {
1499  init_state(&state, NULL);
1500  state.imap_browse = true;
1501  imap_browse(mutt_b2s(&LastDir), &state);
1502  browser_sort(&state);
1503  menu->mdata = &state.entry;
1504  }
1505  else
1506 #endif
1507  {
1508  if (examine_directory(menu, &state, mutt_b2s(&LastDir), mutt_b2s(prefix)) == -1)
1509  {
1510  /* try to restore the old values */
1511  mutt_buffer_copy(&LastDir, OldLastDir);
1512  if (examine_directory(menu, &state, mutt_b2s(&LastDir),
1513  mutt_b2s(prefix)) == -1)
1514  {
1516  goto bail;
1517  }
1518  }
1519  /* resolve paths navigated from GUI */
1520  if (mutt_path_realpath(LastDir.data) == 0)
1521  break;
1522  }
1523 
1524  browser_highlight_default(&state, menu);
1525  init_menu(&state, menu, title, sizeof(title), mailbox);
1526  goto_swapper[0] = '\0';
1527  break;
1528  }
1529  }
1530  else if (op == OP_DESCEND_DIRECTORY)
1531  {
1532  mutt_error(_("%s is not a directory"),
1533  ARRAY_GET(&state.entry, menu->current)->name);
1534  break;
1535  }
1536 
1537  if (mailbox || OptNews) /* USE_NNTP */
1538  {
1539  mutt_buffer_strcpy(file, ff->name);
1541  }
1542 #ifdef USE_IMAP
1543  else if (state.imap_browse)
1544  mutt_buffer_strcpy(file, ff->name);
1545 #endif
1546  else
1547  {
1549  }
1550  }
1551  /* fallthrough */
1552 
1553  case OP_EXIT:
1554 
1555  if (multiple)
1556  {
1557  char **tfiles = NULL;
1558 
1559  if (menu->tagged)
1560  {
1561  *numfiles = menu->tagged;
1562  tfiles = mutt_mem_calloc(*numfiles, sizeof(char *));
1563  size_t j = 0;
1564  ARRAY_FOREACH(ff, &state.entry)
1565  {
1566  if (ff->tagged)
1567  {
1570  tfiles[j++] = mutt_buffer_strdup(tmp);
1571  }
1572  }
1573  *files = tfiles;
1574  }
1575  else if (!mutt_buffer_is_empty(file)) /* no tagged entries. return selected entry */
1576  {
1577  *numfiles = 1;
1578  tfiles = mutt_mem_calloc(*numfiles, sizeof(char *));
1580  tfiles[0] = mutt_buffer_strdup(file);
1581  *files = tfiles;
1582  }
1583  }
1584 
1585  destroy_state(&state);
1586  goto bail;
1587 
1588  case OP_BROWSER_TELL:
1589  if (!ARRAY_EMPTY(&state.entry))
1590  mutt_message("%s", ARRAY_GET(&state.entry, menu->current)->name);
1591  break;
1592 
1593 #ifdef USE_IMAP
1594  case OP_BROWSER_TOGGLE_LSUB:
1595  bool_str_toggle(NeoMutt->sub, "imap_list_subscribed", NULL);
1596 
1597  mutt_unget_event(0, OP_CHECK_NEW);
1598  break;
1599 
1600  case OP_CREATE_MAILBOX:
1601  if (!state.imap_browse)
1602  {
1603  mutt_error(_("Create is only supported for IMAP mailboxes"));
1604  break;
1605  }
1606 
1607  if (imap_mailbox_create(mutt_b2s(&LastDir)) == 0)
1608  {
1609  /* TODO: find a way to detect if the new folder would appear in
1610  * this window, and insert it without starting over. */
1611  destroy_state(&state);
1612  init_state(&state, NULL);
1613  state.imap_browse = true;
1614  imap_browse(mutt_b2s(&LastDir), &state);
1615  browser_sort(&state);
1616  menu->mdata = &state.entry;
1617  browser_highlight_default(&state, menu);
1618  init_menu(&state, menu, title, sizeof(title), mailbox);
1619  }
1620  /* else leave error on screen */
1621  break;
1622 
1623  case OP_RENAME_MAILBOX:
1624  if (!ff->imap)
1625  mutt_error(_("Rename is only supported for IMAP mailboxes"));
1626  else
1627  {
1628  if (imap_mailbox_rename(ff->name) >= 0)
1629  {
1630  destroy_state(&state);
1631  init_state(&state, NULL);
1632  state.imap_browse = true;
1633  imap_browse(mutt_b2s(&LastDir), &state);
1634  browser_sort(&state);
1635  menu->mdata = &state.entry;
1636  browser_highlight_default(&state, menu);
1637  init_menu(&state, menu, title, sizeof(title), mailbox);
1638  }
1639  }
1640  break;
1641 
1642  case OP_DELETE_MAILBOX:
1643  if (!ff->imap)
1644  mutt_error(_("Delete is only supported for IMAP mailboxes"));
1645  else
1646  {
1647  char msg[128];
1648 
1649  // TODO(sileht): It could be better to select INBOX instead. But I
1650  // don't want to manipulate Context/Mailboxes/mailbox->account here for now.
1651  // Let's just protect neomutt against crash for now. #1417
1653  {
1654  mutt_error(_("Can't delete currently selected mailbox"));
1655  break;
1656  }
1657 
1658  snprintf(msg, sizeof(msg), _("Really delete mailbox \"%s\"?"), ff->name);
1659  if (mutt_yesorno(msg, MUTT_NO) == MUTT_YES)
1660  {
1661  if (imap_delete_mailbox(Context->mailbox, ff->name) == 0)
1662  {
1663  /* free the mailbox from the browser */
1664  FREE(&ff->name);
1665  FREE(&ff->desc);
1666  /* and move all other entries up */
1667  ARRAY_REMOVE(&state.entry, ff);
1668  mutt_message(_("Mailbox deleted"));
1669  init_menu(&state, menu, title, sizeof(title), mailbox);
1670  }
1671  else
1672  mutt_error(_("Mailbox deletion failed"));
1673  }
1674  else
1675  mutt_message(_("Mailbox not deleted"));
1676  }
1677  break;
1678 #endif
1679 
1680  case OP_GOTO_PARENT:
1681  case OP_CHANGE_DIRECTORY:
1682 
1683 #ifdef USE_NNTP
1684  if (OptNews)
1685  break;
1686 #endif
1687 
1688  mutt_buffer_copy(buf, &LastDir);
1689 #ifdef USE_IMAP
1690  if (!state.imap_browse)
1691 #endif
1692  {
1693  /* add '/' at the end of the directory name if not already there */
1694  size_t len = mutt_buffer_len(buf);
1695  if ((len > 0) && (mutt_b2s(&LastDir)[len - 1] != '/'))
1696  mutt_buffer_addch(buf, '/');
1697  }
1698 
1699  if (op == OP_CHANGE_DIRECTORY)
1700  {
1701  /* buf comes from the buffer pool, so defaults to size 1024 */
1702  int ret = mutt_buffer_get_field(_("Chdir to: "), buf, MUTT_FILE);
1703  if ((ret != 0) && mutt_buffer_is_empty(buf))
1704  break;
1705  }
1706  else if (op == OP_GOTO_PARENT)
1707  mutt_get_parent_path(mutt_b2s(buf), buf->data, buf->dsize);
1708 
1709  if (!mutt_buffer_is_empty(buf))
1710  {
1711  mailbox = false;
1713 #ifdef USE_IMAP
1714  if (imap_path_probe(mutt_b2s(buf), NULL) == MUTT_IMAP)
1715  {
1716  mutt_buffer_copy(&LastDir, buf);
1717  destroy_state(&state);
1718  init_state(&state, NULL);
1719  state.imap_browse = true;
1720  imap_browse(mutt_b2s(&LastDir), &state);
1721  browser_sort(&state);
1722  menu->mdata = &state.entry;
1723  browser_highlight_default(&state, menu);
1724  init_menu(&state, menu, title, sizeof(title), mailbox);
1725  }
1726  else
1727 #endif
1728  {
1729  if (mutt_b2s(buf)[0] != '/')
1730  {
1731  /* in case dir is relative, make it relative to LastDir,
1732  * not current working dir */
1734  mutt_buffer_copy(buf, tmp);
1735  }
1736  /* Resolve path from <chdir>
1737  * Avoids buildup such as /a/b/../../c
1738  * Symlinks are always unraveled to keep code simple */
1739  if (mutt_path_realpath(buf->data) == 0)
1740  break;
1741 
1742  struct stat st;
1743  if (stat(mutt_b2s(buf), &st) == 0)
1744  {
1745  if (S_ISDIR(st.st_mode))
1746  {
1747  destroy_state(&state);
1748  if (examine_directory(menu, &state, mutt_b2s(buf), mutt_b2s(prefix)) == 0)
1749  mutt_buffer_copy(&LastDir, buf);
1750  else
1751  {
1752  mutt_error(_("Error scanning directory"));
1753  if (examine_directory(menu, &state, mutt_b2s(&LastDir),
1754  mutt_b2s(prefix)) == -1)
1755  {
1756  goto bail;
1757  }
1758  }
1759  browser_highlight_default(&state, menu);
1760  init_menu(&state, menu, title, sizeof(title), mailbox);
1761  }
1762  else
1763  mutt_error(_("%s is not a directory"), mutt_b2s(buf));
1764  }
1765  else
1766  mutt_perror(mutt_b2s(buf));
1767  }
1768  }
1769  break;
1770 
1771  case OP_ENTER_MASK:
1772  {
1773  mutt_buffer_strcpy(buf, C_Mask ? C_Mask->pattern : NULL);
1774  if (mutt_get_field(_("File Mask: "), buf->data, buf->dsize, MUTT_COMP_NO_FLAGS) != 0)
1775  break;
1776 
1777  mutt_buffer_fix_dptr(buf);
1778 
1779  mailbox = false;
1780  /* assume that the user wants to see everything */
1781  if (mutt_buffer_is_empty(buf))
1782  mutt_buffer_strcpy(buf, ".");
1783 
1784  struct Buffer errmsg = mutt_buffer_make(256);
1785  int rc = cs_subset_str_string_set(NeoMutt->sub, "mask", mutt_b2s(buf), &errmsg);
1786  if (CSR_RESULT(rc) != CSR_SUCCESS)
1787  {
1788  if (!mutt_buffer_is_empty(&errmsg))
1789  {
1790  mutt_error("%s", mutt_b2s(&errmsg));
1791  mutt_buffer_dealloc(&errmsg);
1792  }
1793  break;
1794  }
1795  mutt_buffer_dealloc(&errmsg);
1796 
1797  destroy_state(&state);
1798 #ifdef USE_IMAP
1799  if (state.imap_browse)
1800  {
1801  init_state(&state, NULL);
1802  state.imap_browse = true;
1803  imap_browse(mutt_b2s(&LastDir), &state);
1804  browser_sort(&state);
1805  menu->mdata = &state.entry;
1806  init_menu(&state, menu, title, sizeof(title), mailbox);
1807  }
1808  else
1809 #endif
1810  if (examine_directory(menu, &state, mutt_b2s(&LastDir), NULL) == 0)
1811  init_menu(&state, menu, title, sizeof(title), mailbox);
1812  else
1813  {
1814  mutt_error(_("Error scanning directory"));
1815  goto bail;
1816  }
1817  kill_prefix = false;
1818  if (ARRAY_EMPTY(&state.entry))
1819  {
1820  mutt_error(_("No files match the file mask"));
1821  break;
1822  }
1823  break;
1824  }
1825 
1826  case OP_SORT:
1827  case OP_SORT_REVERSE:
1828 
1829  {
1830  bool resort = true;
1831  int sort = -1;
1832  int reverse = (op == OP_SORT_REVERSE);
1833 
1834  switch (mutt_multi_choice(
1835  (reverse) ?
1836  /* L10N: The highlighted letters must match the "Sort" options */
1837  _("Reverse sort by (d)ate, (a)lpha, si(z)e, d(e)scription, "
1838  "(c)ount, ne(w) count, or do(n)'t sort?") :
1839  /* L10N: The highlighted letters must match the "Reverse Sort" options */
1840  _("Sort by (d)ate, (a)lpha, si(z)e, d(e)scription, (c)ount, "
1841  "ne(w) count, or do(n)'t sort?"),
1842  /* L10N: These must match the highlighted letters from "Sort" and "Reverse Sort" */
1843  _("dazecwn")))
1844  {
1845  case -1: /* abort */
1846  resort = false;
1847  break;
1848 
1849  case 1: /* (d)ate */
1850  sort = SORT_DATE;
1851  break;
1852 
1853  case 2: /* (a)lpha */
1854  sort = SORT_SUBJECT;
1855  break;
1856 
1857  case 3: /* si(z)e */
1858  sort = SORT_SIZE;
1859  break;
1860 
1861  case 4: /* d(e)scription */
1862  sort = SORT_DESC;
1863  break;
1864 
1865  case 5: /* (c)ount */
1866  sort = SORT_COUNT;
1867  break;
1868 
1869  case 6: /* ne(w) count */
1870  sort = SORT_UNREAD;
1871  break;
1872 
1873  case 7: /* do(n)'t sort */
1874  sort = SORT_ORDER;
1875  resort = false;
1876  break;
1877  }
1878  if (resort)
1879  {
1880  sort |= reverse ? SORT_REVERSE : 0;
1881  cs_subset_str_native_set(NeoMutt->sub, "sort_browser", sort, NULL);
1882  browser_sort(&state);
1883  browser_highlight_default(&state, menu);
1884  menu->redraw = REDRAW_FULL;
1885  }
1886  else
1887  {
1888  cs_subset_str_native_set(NeoMutt->sub, "sort_browser", sort, NULL);
1889  }
1890  break;
1891  }
1892 
1893  case OP_TOGGLE_MAILBOXES:
1894  case OP_BROWSER_GOTO_FOLDER:
1895  case OP_CHECK_NEW:
1896  if (op == OP_TOGGLE_MAILBOXES)
1897  {
1898  mailbox = !mailbox;
1899  menu->is_mailbox_list = mailbox;
1900  }
1901 
1902  if (op == OP_BROWSER_GOTO_FOLDER)
1903  {
1904  /* When in mailboxes mode, disables this feature */
1905  if (C_Folder)
1906  {
1907  mutt_debug(LL_DEBUG3, "= hit! Folder: %s, LastDir: %s\n", C_Folder,
1908  mutt_b2s(&LastDir));
1909  if (goto_swapper[0] == '\0')
1910  {
1912  {
1913  /* Stores into goto_swapper LastDir, and swaps to C_Folder */
1914  mutt_str_copy(goto_swapper, mutt_b2s(&LastDir), sizeof(goto_swapper));
1917  }
1918  }
1919  else
1920  {
1922  mutt_buffer_strcpy(&LastDir, goto_swapper);
1923  goto_swapper[0] = '\0';
1924  }
1925  }
1926  }
1927  destroy_state(&state);
1928  mutt_buffer_reset(prefix);
1929  kill_prefix = false;
1930 
1931  if (mailbox)
1932  {
1933  examine_mailboxes(menu, &state);
1934  }
1935 #ifdef USE_IMAP
1936  else if (imap_path_probe(mutt_b2s(&LastDir), NULL) == MUTT_IMAP)
1937  {
1938  init_state(&state, NULL);
1939  state.imap_browse = true;
1940  imap_browse(mutt_b2s(&LastDir), &state);
1941  browser_sort(&state);
1942  menu->mdata = &state.entry;
1943  }
1944 #endif
1945  else if (examine_directory(menu, &state, mutt_b2s(&LastDir), mutt_b2s(prefix)) == -1)
1946  goto bail;
1947  init_menu(&state, menu, title, sizeof(title), mailbox);
1948  break;
1949 
1950  case OP_MAILBOX_LIST:
1952  break;
1953 
1954  case OP_BROWSER_NEW_FILE:
1955  mutt_buffer_printf(buf, "%s/", mutt_b2s(&LastDir));
1956  /* buf comes from the buffer pool, so defaults to size 1024 */
1957  if (mutt_buffer_get_field(_("New file name: "), buf, MUTT_FILE) == 0)
1958  {
1959  mutt_buffer_copy(file, buf);
1960  destroy_state(&state);
1961  goto bail;
1962  }
1963  break;
1964 
1965  case OP_BROWSER_VIEW_FILE:
1966  if (ARRAY_EMPTY(&state.entry))
1967  {
1968  mutt_error(_("No files match the file mask"));
1969  break;
1970  }
1971 
1972 #ifdef USE_IMAP
1973  if (ff->selectable)
1974  {
1975  mutt_buffer_strcpy(file, ff->name);
1976  destroy_state(&state);
1977  goto bail;
1978  }
1979  else
1980 #endif
1981  if (S_ISDIR(ff->mode) ||
1982  (S_ISLNK(ff->mode) && link_is_dir(mutt_b2s(&LastDir), ff->name)))
1983  {
1984  mutt_error(_("Can't view a directory"));
1985  break;
1986  }
1987  else
1988  {
1989  char buf2[PATH_MAX];
1990 
1991  mutt_path_concat(buf2, mutt_b2s(&LastDir), ff->name, sizeof(buf2));
1992  struct Body *b = mutt_make_file_attach(buf2, NeoMutt->sub);
1993  if (b)
1994  {
1995  mutt_view_attachment(NULL, b, MUTT_VA_REGULAR, NULL, NULL, menu->win_index);
1996  mutt_body_free(&b);
1997  menu->redraw = REDRAW_FULL;
1998  }
1999  else
2000  mutt_error(_("Error trying to view file"));
2001  }
2002  break;
2003 
2004 #ifdef USE_NNTP
2005  case OP_CATCHUP:
2006  case OP_UNCATCHUP:
2007  {
2008  if (!OptNews)
2009  break;
2010 
2011  struct NntpMboxData *mdata = NULL;
2012 
2014  if (rc < 0)
2015  break;
2016 
2017  if (op == OP_CATCHUP)
2019  else
2021 
2022  if (mdata)
2023  {
2025  if ((menu->current + 1) < menu->max)
2026  menu->current++;
2027  menu->redraw = REDRAW_MOTION_RESYNC;
2028  }
2029  if (rc)
2030  menu->redraw = REDRAW_INDEX;
2032  break;
2033  }
2034 
2035  case OP_LOAD_ACTIVE:
2036  {
2037  if (!OptNews)
2038  break;
2039 
2040  struct NntpAccountData *adata = CurrentNewsSrv;
2041 
2042  if (nntp_newsrc_parse(adata) < 0)
2043  break;
2044 
2045  for (size_t i = 0; i < adata->groups_num; i++)
2046  {
2047  struct NntpMboxData *mdata = adata->groups_list[i];
2048  if (mdata)
2049  mdata->deleted = true;
2050  }
2051  nntp_active_fetch(adata, true);
2052  nntp_newsrc_update(adata);
2053  nntp_newsrc_close(adata);
2054 
2055  destroy_state(&state);
2056  if (mailbox)
2057  examine_mailboxes(menu, &state);
2058  else
2059  {
2060  if (examine_directory(menu, &state, NULL, NULL) == -1)
2061  break;
2062  }
2063  init_menu(&state, menu, title, sizeof(title), mailbox);
2064  break;
2065  }
2066 #endif /* USE_NNTP */
2067 
2068 #if defined(USE_IMAP) || defined(USE_NNTP)
2069  case OP_BROWSER_SUBSCRIBE:
2070  case OP_BROWSER_UNSUBSCRIBE:
2071 #endif
2072 #ifdef USE_NNTP
2073  case OP_SUBSCRIBE_PATTERN:
2074  case OP_UNSUBSCRIBE_PATTERN:
2075  if (OptNews)
2076  {
2077  struct NntpAccountData *adata = CurrentNewsSrv;
2078  regex_t rx;
2079  memset(&rx, 0, sizeof(rx));
2080  char *s = buf->data;
2081  int i = menu->current;
2082 
2083  if ((op == OP_SUBSCRIBE_PATTERN) || (op == OP_UNSUBSCRIBE_PATTERN))
2084  {
2085  char tmp2[256];
2086 
2087  mutt_buffer_reset(buf);
2088  if (op == OP_SUBSCRIBE_PATTERN)
2089  snprintf(tmp2, sizeof(tmp2), _("Subscribe pattern: "));
2090  else
2091  snprintf(tmp2, sizeof(tmp2), _("Unsubscribe pattern: "));
2092  /* buf comes from the buffer pool, so defaults to size 1024 */
2093  if ((mutt_buffer_get_field(tmp2, buf, MUTT_PATTERN) != 0) ||
2094  mutt_buffer_is_empty(buf))
2095  {
2096  break;
2097  }
2098 
2099  int err = REG_COMP(&rx, s, REG_NOSUB);
2100  if (err != 0)
2101  {
2102  regerror(err, &rx, buf->data, buf->dsize);
2103  regfree(&rx);
2104  mutt_error("%s", mutt_b2s(buf));
2105  break;
2106  }
2107  menu->redraw = REDRAW_FULL;
2108  i = 0;
2109  }
2110  else if (ARRAY_EMPTY(&state.entry))
2111  {
2112  mutt_error(_("No newsgroups match the mask"));
2113  break;
2114  }
2115 
2116  int rc = nntp_newsrc_parse(adata);
2117  if (rc < 0)
2118  break;
2119 
2120  ARRAY_FOREACH_FROM(ff, &state.entry, i)
2121  {
2122  if ((op == OP_BROWSER_SUBSCRIBE) || (op == OP_BROWSER_UNSUBSCRIBE) ||
2123  (regexec(&rx, ff->name, 0, NULL, 0) == 0))
2124  {
2125  if ((op == OP_BROWSER_SUBSCRIBE) || (op == OP_SUBSCRIBE_PATTERN))
2126  mutt_newsgroup_subscribe(adata, ff->name);
2127  else
2128  mutt_newsgroup_unsubscribe(adata, ff->name);
2129  }
2130  if ((op == OP_BROWSER_SUBSCRIBE) || (op == OP_BROWSER_UNSUBSCRIBE))
2131  {
2132  if ((menu->current + 1) < menu->max)
2133  menu->current++;
2134  menu->redraw = REDRAW_MOTION_RESYNC;
2135  break;
2136  }
2137  }
2138 
2139  if (op == OP_SUBSCRIBE_PATTERN)
2140  {
2141  for (size_t j = 0; adata && (j < adata->groups_num); j++)
2142  {
2143  struct NntpMboxData *mdata = adata->groups_list[j];
2144  if (mdata && mdata->group && !mdata->subscribed)
2145  {
2146  if (regexec(&rx, mdata->group, 0, NULL, 0) == 0)
2147  {
2148  mutt_newsgroup_subscribe(adata, mdata->group);
2149  add_folder(menu, &state, mdata->group, NULL, NULL, NULL, mdata);
2150  }
2151  }
2152  }
2153  init_menu(&state, menu, title, sizeof(title), mailbox);
2154  }
2155  if (rc > 0)
2156  menu->redraw = REDRAW_FULL;
2157  nntp_newsrc_update(adata);
2158  nntp_clear_cache(adata);
2159  nntp_newsrc_close(adata);
2160  if ((op != OP_BROWSER_SUBSCRIBE) && (op != OP_BROWSER_UNSUBSCRIBE))
2161  regfree(&rx);
2162  }
2163 #ifdef USE_IMAP
2164  else
2165 #endif /* USE_IMAP && USE_NNTP */
2166 #endif /* USE_NNTP */
2167 #ifdef USE_IMAP
2168  {
2169  char tmp2[256];
2170  mutt_str_copy(tmp2, ff->name, sizeof(tmp2));
2171  mutt_expand_path(tmp2, sizeof(tmp2));
2172  imap_subscribe(tmp2, (op == OP_BROWSER_SUBSCRIBE));
2173  }
2174 #endif /* USE_IMAP */
2175  }
2176  }
2177 
2178 bail:
2179  mutt_buffer_pool_release(&OldLastDir);
2182  mutt_buffer_pool_release(&prefix);
2183 
2184  if (menu)
2185  {
2186  mutt_menu_pop_current(menu);
2187  mutt_menu_free(&menu);
2189  }
2190 
2191  goto_swapper[0] = '\0';
2192 }
#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:201
#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:346
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:2370
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
#define mutt_message(...)
Definition: logging.h:83
int imap_delete_mailbox(struct Mailbox *m, char *path)
Delete a mailbox.
Definition: imap.c:493
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:1112
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:93
#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
char * mutt_buffer_strdup(struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
static void add_folder(struct Menu *menu, struct BrowserState *state, const char *name, const char *desc, const struct stat *s, struct Mailbox *m, void *data)
Add a folder to the browser list.
Definition: browser.c:636
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:95
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:379
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:951
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:935
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:98
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:47
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:51
static int examine_mailboxes(struct Menu *menu, struct BrowserState *state)
Get list of mailboxes/subscribed newsgroups.
Definition: browser.c:832
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:319
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:983
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:706
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition: mx.c:1353
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:62
void mutt_browser_select_dir(const char *f)
Remember the last directory selected.
Definition: browser.c:1138
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:1010
#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:66
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:431
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:61
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:46
static void init_state(struct BrowserState *state, struct Menu *menu)
Initialise a browser state.
Definition: browser.c:686
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:82
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:97
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:49
Log at debug level 3.
Definition: logging.h:42
#define SORT_MASK
Mask for the sort id.
Definition: sort2.h:81
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:1249
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 2202 of file browser.c.

2204 {
2205  struct Buffer *f_buf = mutt_buffer_pool_get();
2206 
2207  mutt_buffer_strcpy(f_buf, NONULL(file));
2208  mutt_buffer_select_file(f_buf, flags, files, numfiles);
2209  mutt_str_copy(file, mutt_b2s(f_buf), filelen);
2210 
2211  mutt_buffer_pool_release(&f_buf);
2212 }
#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:1157
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.