NeoMutt  2019-11-11
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 <regex.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include "mutt/mutt.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "conn/conn.h"
#include "mutt.h"
#include "browser.h"
#include "context.h"
#include "curs_lib.h"
#include "format_flags.h"
#include "globals.h"
#include "keymap.h"
#include "mutt_attach.h"
#include "mutt_mailbox.h"
#include "mutt_menu.h"
#include "mutt_window.h"
#include "muttlib.h"
#include "mx.h"
#include "opcodes.h"
#include "options.h"
#include "sendlib.h"
#include "imap/imap.h"
#include "nntp/nntp.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, unsigned long 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::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::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::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...
 
char * C_GroupIndexFormat
 Config: (nntp) printf-like format string for the browser's display of newsgroups. More...
 
char * C_NewsgroupsCharset
 Config: (nntp) Character set of newsgroups' descriptions. More...
 
bool C_ShowOnlyUnread
 Config: (nntp) Only show subscribed newsgroups with unread articles. More...
 
short C_SortBrowser
 Config: Sort method for the browser. More...
 
char * C_VfolderFormat
 Config: (notmuch) printf-like format string for the browser's display of virtual folders. More...
 
static const struct Mapping FolderHelp []
 
static struct Mapping FolderNewsHelp []
 
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:50
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  for (size_t c = 0; c < state->entrylen; c++)
138  {
139  FREE(&((state->entry)[c].name));
140  FREE(&((state->entry)[c].desc));
141  }
142 #ifdef USE_IMAP
143  FREE(&state->folder);
144 #endif
145  FREE(&state->entry);
146 }
char * folder
Definition: browser.h:102
size_t entrylen
number of real entries
Definition: browser.h:98
#define FREE(x)
Definition: memory.h:40
struct FolderFile * entry
Definition: browser.h:97
+ 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 156 of file browser.c.

157 {
158  const struct FolderFile *pa = (const struct FolderFile *) a;
159  const struct FolderFile *pb = (const struct FolderFile *) b;
160 
161  /* inbox should be sorted ahead of its siblings */
162  int r = mutt_inbox_cmp(pa->name, pb->name);
163  if (r == 0)
164  r = mutt_str_strcoll(pa->name, pb->name);
165  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
166 }
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:76
char * name
Definition: browser.h:70
Browser entry representing a folder/dir.
Definition: browser.h:61
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:1711
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:86
int mutt_str_strcoll(const char *a, const char *b)
Collate two strings (compare using locale), safely.
Definition: string.c:679
+ 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 176 of file browser.c.

177 {
178  const struct FolderFile *pa = (const struct FolderFile *) a;
179  const struct FolderFile *pb = (const struct FolderFile *) b;
180 
181  int r = mutt_str_strcoll(pa->desc, pb->desc);
182 
183  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
184 }
char * desc
Definition: browser.h:71
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:76
Browser entry representing a folder/dir.
Definition: browser.h:61
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:86
int mutt_str_strcoll(const char *a, const char *b)
Collate two strings (compare using locale), safely.
Definition: string.c:679
+ 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 194 of file browser.c.

195 {
196  const struct FolderFile *pa = (const struct FolderFile *) a;
197  const struct FolderFile *pb = (const struct FolderFile *) b;
198 
199  int r = pa->mtime - pb->mtime;
200 
201  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
202 }
time_t mtime
Definition: browser.h:65
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:76
Browser entry representing a folder/dir.
Definition: browser.h:61
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:86
+ 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 212 of file browser.c.

213 {
214  const struct FolderFile *pa = (const struct FolderFile *) a;
215  const struct FolderFile *pb = (const struct FolderFile *) b;
216 
217  int r = pa->size - pb->size;
218 
219  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
220 }
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:76
off_t size
Definition: browser.h:64
Browser entry representing a folder/dir.
Definition: browser.h:61
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:86
+ 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 230 of file browser.c.

231 {
232  const struct FolderFile *pa = (const struct FolderFile *) a;
233  const struct FolderFile *pb = (const struct FolderFile *) b;
234 
235  int r = 0;
236  if (pa->has_mailbox && pb->has_mailbox)
237  r = pa->msg_count - pb->msg_count;
238  else if (pa->has_mailbox)
239  r = -1;
240  else
241  r = 1;
242 
243  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
244 }
bool has_mailbox
Definition: browser.h:84
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:76
Browser entry representing a folder/dir.
Definition: browser.h:61
int msg_count
total number of messages
Definition: browser.h:74
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:86
+ 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 254 of file browser.c.

255 {
256  const struct FolderFile *pa = (const struct FolderFile *) a;
257  const struct FolderFile *pb = (const struct FolderFile *) b;
258 
259  int r = 0;
260  if (pa->has_mailbox && pb->has_mailbox)
261  r = pa->msg_unread - pb->msg_unread;
262  else if (pa->has_mailbox)
263  r = -1;
264  else
265  r = 1;
266 
267  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
268 }
int msg_unread
number of unread messages
Definition: browser.h:75
bool has_mailbox
Definition: browser.h:84
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:76
Browser entry representing a folder/dir.
Definition: browser.h:61
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:86
+ 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 282 of file browser.c.

283 {
284  const struct FolderFile *pa = (const struct FolderFile *) a;
285  const struct FolderFile *pb = (const struct FolderFile *) b;
286 
287  if ((mutt_str_strcoll(pa->desc, "../") == 0) || (mutt_str_strcoll(pa->desc, "..") == 0))
288  return -1;
289  if ((mutt_str_strcoll(pb->desc, "../") == 0) || (mutt_str_strcoll(pb->desc, "..") == 0))
290  return 1;
291 
292  switch (C_SortBrowser & SORT_MASK)
293  {
294  case SORT_COUNT:
295  return browser_compare_count(a, b);
296  case SORT_DATE:
297  return browser_compare_date(a, b);
298  case SORT_DESC:
299  return browser_compare_desc(a, b);
300  case SORT_SIZE:
301  return browser_compare_size(a, b);
302  case SORT_UNREAD:
303  return browser_compare_count_new(a, b);
304  case SORT_SUBJECT:
305  default:
306  return browser_compare_subject(a, b);
307  }
308 }
static int browser_compare_date(const void *a, const void *b)
Compare the date of two browser entries.
Definition: browser.c:194
char * desc
Definition: browser.h:71
static int browser_compare_desc(const void *a, const void *b)
Compare the descriptions of two browser entries.
Definition: browser.c:176
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:76
static int browser_compare_count(const void *a, const void *b)
Compare the message count of two browser entries.
Definition: browser.c:230
Sort by the size of the email.
Definition: sort2.h:51
Browser entry representing a folder/dir.
Definition: browser.h:61
static int browser_compare_count_new(const void *a, const void *b)
Compare the new count of two browser entries.
Definition: browser.c:254
static int browser_compare_size(const void *a, const void *b)
Compare the size of two browser entries.
Definition: browser.c:212
static int browser_compare_subject(const void *a, const void *b)
Compare the subject of two browser entries.
Definition: browser.c:156
Sort by the number of unread emails.
Definition: sort2.h:66
Sort by the folder&#39;s description.
Definition: sort2.h:70
Sort by number of emails in a folder.
Definition: sort2.h:65
Sort by the date the email was sent.
Definition: sort2.h:50
int mutt_str_strcoll(const char *a, const char *b)
Collate two strings (compare using locale), safely.
Definition: string.c:679
Sort by the email&#39;s subject.
Definition: sort2.h:53
#define SORT_MASK
Mask for the sort id.
Definition: sort2.h:85
+ 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 317 of file browser.c.

318 {
319  switch (C_SortBrowser & SORT_MASK)
320  {
321  /* Also called "I don't care"-sort-method. */
322  case SORT_ORDER:
323  return;
324 #ifdef USE_NNTP
325  case SORT_SIZE:
326  case SORT_DATE:
327  if (OptNews)
328  return;
329 #endif
330  default:
331  break;
332  }
333 
334  qsort(state->entry, state->entrylen, sizeof(struct FolderFile), browser_compare);
335 }
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:76
Sort by the size of the email.
Definition: sort2.h:51
Sort by the order the messages appear in the mailbox.
Definition: sort2.h:55
Browser entry representing a folder/dir.
Definition: browser.h:61
size_t entrylen
number of real entries
Definition: browser.h:98
static int browser_compare(const void *a, const void *b)
Sort the items in the browser.
Definition: browser.c:282
Sort by the date the email was sent.
Definition: sort2.h:50
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:43
struct FolderFile * entry
Definition: browser.h:97
#define SORT_MASK
Mask for the sort id.
Definition: sort2.h:85
+ 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 344 of file browser.c.

345 {
346  struct stat st;
347  bool retval = false;
348 
349  struct Buffer *fullpath = mutt_buffer_pool_get();
350  mutt_buffer_concat_path(fullpath, folder, path);
351 
352  if (stat(mutt_b2s(fullpath), &st) == 0)
353  retval = S_ISDIR(st.st_mode);
354 
355  mutt_buffer_pool_release(&fullpath);
356 
357  return retval;
358 }
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:100
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:111
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,
unsigned long  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 380 of file browser.c.

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

633 {
634  if (m && (m->flags & MB_HIDDEN))
635  {
636  return;
637  }
638 
639  if (state->entrylen == state->entrymax)
640  {
641  /* need to allocate more space */
642  mutt_mem_realloc(&state->entry, sizeof(struct FolderFile) * (state->entrymax += 256));
643  memset(&state->entry[state->entrylen], 0, sizeof(struct FolderFile) * 256);
644  if (menu)
645  menu->data = state->entry;
646  }
647 
648  if (s)
649  {
650  (state->entry)[state->entrylen].mode = s->st_mode;
651  (state->entry)[state->entrylen].mtime = s->st_mtime;
652  (state->entry)[state->entrylen].size = s->st_size;
653  (state->entry)[state->entrylen].gid = s->st_gid;
654  (state->entry)[state->entrylen].uid = s->st_uid;
655  (state->entry)[state->entrylen].nlink = s->st_nlink;
656 
657  (state->entry)[state->entrylen].local = true;
658  }
659  else
660  (state->entry)[state->entrylen].local = false;
661 
662  if (m)
663  {
664  (state->entry)[state->entrylen].has_mailbox = true;
665  (state->entry)[state->entrylen].has_new_mail = m->has_new;
666  (state->entry)[state->entrylen].msg_count = m->msg_count;
667  (state->entry)[state->entrylen].msg_unread = m->msg_unread;
668  }
669 
670  (state->entry)[state->entrylen].name = mutt_str_strdup(name);
671  (state->entry)[state->entrylen].desc = mutt_str_strdup(desc ? desc : name);
672 #ifdef USE_IMAP
673  (state->entry)[state->entrylen].imap = false;
674 #endif
675 #ifdef USE_NNTP
676  if (OptNews)
677  (state->entry)[state->entrylen].nd = data;
678 #endif
679  (state->entrylen)++;
680 }
mode_t mode
Definition: browser.h:63
int msg_count
Total number of messages.
Definition: mailbox.h:102
int msg_unread
Number of unread messages.
Definition: mailbox.h:103
bool has_new
Mailbox has new mail.
Definition: mailbox.h:99
const char * name
Definition: pgpmicalg.c:45
unsigned int entrymax
max entry
Definition: browser.h:99
int flags
e.g. MB_NORMAL
Definition: mailbox.h:145
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
Browser entry representing a folder/dir.
Definition: browser.h:61
#define MB_HIDDEN
Definition: mailbox.h:37
size_t entrylen
number of real entries
Definition: browser.h:98
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
void * data
Extra data for the current menu.
Definition: mutt_menu.h:86
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:43
struct FolderFile * entry
Definition: browser.h:97
+ 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 687 of file browser.c.

688 {
689  state->entrylen = 0;
690  state->entrymax = 256;
691  state->entry = mutt_mem_calloc(state->entrymax, sizeof(struct FolderFile));
692 #ifdef USE_IMAP
693  state->imap_browse = false;
694 #endif
695  if (menu)
696  menu->data = state->entry;
697 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
unsigned int entrymax
max entry
Definition: browser.h:99
Browser entry representing a folder/dir.
Definition: browser.h:61
size_t entrylen
number of real entries
Definition: browser.h:98
void * data
Extra data for the current menu.
Definition: mutt_menu.h:86
bool imap_browse
Definition: browser.h:101
struct FolderFile * entry
Definition: browser.h:97
+ Here is the call graph for this function:
+ 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 708 of file browser.c.

710 {
711  int rc = -1;
712  struct Buffer *buf = mutt_buffer_pool_get();
713 #ifdef USE_NNTP
714  if (OptNews)
715  {
717 
718  init_state(state, menu);
719 
720  for (unsigned int i = 0; i < adata->groups_num; i++)
721  {
722  struct NntpMboxData *mdata = adata->groups_list[i];
723  if (!mdata)
724  continue;
725  if (prefix && *prefix && !mutt_str_startswith(mdata->group, prefix, CASE_MATCH))
726  continue;
727  if (!mutt_regex_match(C_Mask, mdata->group))
728  {
729  continue;
730  }
731  add_folder(menu, state, mdata->group, NULL, NULL, NULL, mdata);
732  }
733  }
734  else
735 #endif /* USE_NNTP */
736  {
737  struct stat s;
738  DIR *dp = NULL;
739  struct dirent *de = NULL;
740 
741  while (stat(d, &s) == -1)
742  {
743  if (errno == ENOENT)
744  {
745  /* The last used directory is deleted, try to use the parent dir. */
746  char *c = strrchr(d, '/');
747 
748  if (c && (c > d))
749  {
750  *c = '\0';
751  continue;
752  }
753  }
754  mutt_perror(d);
755  goto ed_out;
756  }
757 
758  if (!S_ISDIR(s.st_mode))
759  {
760  mutt_error(_("%s is not a directory"), d);
761  goto ed_out;
762  }
763 
764  if (Context && Context->mailbox)
766 
767  dp = opendir(d);
768  if (!dp)
769  {
770  mutt_perror(d);
771  goto ed_out;
772  }
773 
774  init_state(state, menu);
775 
776  struct MailboxList ml = neomutt_mailboxlist_get_all(NeoMutt, MUTT_MAILBOX_ANY);
777  while ((de = readdir(dp)))
778  {
779  if (mutt_str_strcmp(de->d_name, ".") == 0)
780  continue; /* we don't need . */
781 
782  if (prefix && *prefix && !mutt_str_startswith(de->d_name, prefix, CASE_MATCH))
783  {
784  continue;
785  }
786  if (!mutt_regex_match(C_Mask, de->d_name))
787  {
788  continue;
789  }
790 
791  mutt_buffer_concat_path(buf, d, de->d_name);
792  if (lstat(mutt_b2s(buf), &s) == -1)
793  continue;
794 
795  /* No size for directories or symlinks */
796  if (S_ISDIR(s.st_mode) || S_ISLNK(s.st_mode))
797  s.st_size = 0;
798  else if (!S_ISREG(s.st_mode))
799  continue;
800 
801  struct MailboxNode *np = NULL;
802  STAILQ_FOREACH(np, &ml, entries)
803  {
804  if (mutt_str_strcmp(mutt_b2s(buf), mailbox_path(np->mailbox)) == 0)
805  break;
806  }
807 
808  if (np && Context && Context->mailbox &&
810  {
813  }
814  add_folder(menu, state, de->d_name, NULL, &s, np ? np->mailbox : NULL, NULL);
815  }
817  closedir(dp);
818  }
819  browser_sort(state);
820  rc = 0;
821 ed_out:
823  return rc;
824 }
The "current" mailbox.
Definition: context.h:36
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:194
int msg_count
Total number of messages.
Definition: mailbox.h:102
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:100
#define mutt_perror(...)
Definition: logging.h:85
int msg_unread
Number of unread messages.
Definition: mailbox.h:103
void neomutt_mailboxlist_clear(struct MailboxList *ml)
Free a Mailbox List.
Definition: neomutt.c:134
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:95
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:111
Match any Mailbox type.
Definition: mailbox.h:44
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:630
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
Match case when comparing strings.
Definition: string2.h:67
Container for Accounts, Notifications.
Definition: neomutt.h:35
NNTP-specific Account data -.
Definition: nntp.h:75
struct Mailbox * mailbox
Definition: context.h:50
struct MailboxList neomutt_mailboxlist_get_all(struct NeoMutt *n, enum MailboxType magic)
Get a List of all Mailboxes.
Definition: neomutt.c:156
char * group
Definition: nntp.h:140
void * mdata
Driver specific data.
Definition: mailbox.h:147
#define mutt_b2s(buf)
Definition: buffer.h:41
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all all Mailboxes for new mail.
Definition: mutt_mailbox.c:127
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
unsigned int groups_num
Definition: nntp.h:98
static void browser_sort(struct BrowserState *state)
Sort the entries in the browser.
Definition: browser.c:317
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
NNTP-specific Mailbox data -.
Definition: nntp.h:138
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:168
#define mutt_error(...)
Definition: logging.h:84
WHERE struct Regex * C_Mask
Config: Only display files/dirs matching this regex in the browser.
Definition: globals.h:178
bool mutt_regex_match(const struct Regex *regex, const char *str)
Shorthand to mutt_regex_capture()
Definition: regex.c:610
void ** groups_list
Definition: nntp.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
List of Mailboxes.
Definition: mailbox.h:156
static void init_state(struct BrowserState *state, struct Menu *menu)
Initialise a browser state.
Definition: browser.c:687
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:43
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:75
struct Mailbox * mailbox
Mailbox in the list.
Definition: mailbox.h:158
+ 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 833 of file browser.c.

834 {
835  struct stat s;
836  struct Buffer *md = NULL;
837  struct Buffer *mailbox = NULL;
838 
839 #ifdef USE_NNTP
840  if (OptNews)
841  {
843 
844  init_state(state, menu);
845 
846  for (unsigned int i = 0; i < adata->groups_num; i++)
847  {
848  struct NntpMboxData *mdata = adata->groups_list[i];
849  if (mdata && (mdata->has_new_mail ||
850  (mdata->subscribed && (mdata->unread || !C_ShowOnlyUnread))))
851  {
852  add_folder(menu, state, mdata->group, NULL, NULL, NULL, mdata);
853  }
854  }
855  }
856  else
857 #endif
858  {
859  init_state(state, menu);
860 
862  return -1;
863  mailbox = mutt_buffer_pool_get();
864  md = mutt_buffer_pool_get();
866 
867  struct MailboxList ml = neomutt_mailboxlist_get_all(NeoMutt, MUTT_MAILBOX_ANY);
868  struct MailboxNode *np = NULL;
869  STAILQ_FOREACH(np, &ml, entries)
870  {
872  {
875  }
876 
877  mutt_buffer_strcpy(mailbox, mailbox_path(np->mailbox));
880 
881  switch (np->mailbox->magic)
882  {
883  case MUTT_IMAP:
884  case MUTT_POP:
885  add_folder(menu, state, mutt_b2s(mailbox), np->mailbox->name, NULL,
886  np->mailbox, NULL);
887  continue;
888  case MUTT_NOTMUCH:
889  case MUTT_NNTP:
890  add_folder(menu, state, mailbox_path(np->mailbox), np->mailbox->name,
891  NULL, np->mailbox, NULL);
892  continue;
893  default: /* Continue */
894  break;
895  }
896 
897  if (lstat(mailbox_path(np->mailbox), &s) == -1)
898  continue;
899 
900  if ((!S_ISREG(s.st_mode)) && (!S_ISDIR(s.st_mode)) && (!S_ISLNK(s.st_mode)))
901  continue;
902 
903  if (np->mailbox->magic == MUTT_MAILDIR)
904  {
905  struct stat st2;
906 
907  mutt_buffer_printf(md, "%s/new", mailbox_path(np->mailbox));
908  if (stat(mutt_b2s(md), &s) < 0)
909  s.st_mtime = 0;
910  mutt_buffer_printf(md, "%s/cur", mailbox_path(np->mailbox));
911  if (stat(mutt_b2s(md), &st2) < 0)
912  st2.st_mtime = 0;
913  if (st2.st_mtime > s.st_mtime)
914  s.st_mtime = st2.st_mtime;
915  }
916 
917  add_folder(menu, state, mutt_b2s(mailbox), np->mailbox->name, &s, np->mailbox, NULL);
918  }
920  }
921  browser_sort(state);
922 
923  mutt_buffer_pool_release(&mailbox);
925  return 0;
926 }
bool has_new_mail
Definition: nntp.h:148
The "current" mailbox.
Definition: context.h:36
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:194
int msg_count
Total number of messages.
Definition: mailbox.h:102
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:100
int msg_unread
Number of unread messages.
Definition: mailbox.h:103
&#39;NNTP&#39; (Usenet) Mailbox type
Definition: mailbox.h:51
struct AccountList accounts
List of all Accounts.
Definition: neomutt.h:39
void neomutt_mailboxlist_clear(struct MailboxList *ml)
Free a Mailbox List.
Definition: neomutt.c:134
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:95
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:111
Match any Mailbox type.
Definition: mailbox.h:44
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:630
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:35
void mutt_buffer_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:704
NNTP-specific Account data -.
Definition: nntp.h:75
bool subscribed
Definition: nntp.h:147
char * name
A short name for the Mailbox.
Definition: mailbox.h:96
struct Mailbox * mailbox
Definition: context.h:50
enum MailboxType magic
Mailbox type.
Definition: mailbox.h:116
struct MailboxList neomutt_mailboxlist_get_all(struct NeoMutt *n, enum MailboxType magic)
Get a List of all Mailboxes.
Definition: neomutt.c:156
char * group
Definition: nntp.h:140
void * mdata
Driver specific data.
Definition: mailbox.h:147
&#39;Maildir&#39; Mailbox type
Definition: mailbox.h:50
#define mutt_b2s(buf)
Definition: buffer.h:41
&#39;POP3&#39; Mailbox type
Definition: mailbox.h:54
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all all Mailboxes for new mail.
Definition: mutt_mailbox.c:127
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
unsigned int groups_num
Definition: nntp.h:98
static void browser_sort(struct BrowserState *state)
Sort the entries in the browser.
Definition: browser.c:317
bool C_ShowOnlyUnread
Config: (nntp) Only show subscribed newsgroups with unread articles.
Definition: browser.c:75
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
NNTP-specific Mailbox data -.
Definition: nntp.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:53
anum_t unread
Definition: nntp.h:146
bool C_BrowserAbbreviateMailboxes
Config: Abbreviate mailboxes using &#39;~&#39; and &#39;=&#39; in the browser.
Definition: browser.c:71
void ** groups_list
Definition: nntp.h:100
List of Mailboxes.
Definition: mailbox.h:156
#define TAILQ_EMPTY(head)
Definition: queue.h:715
static void init_state(struct BrowserState *state, struct Menu *menu)
Initialise a browser state.
Definition: browser.c:687
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:52
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:43
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:75
struct Mailbox * mailbox
Mailbox in the list.
Definition: mailbox.h:158
+ 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::menu_search()

Definition at line 931 of file browser.c.

932 {
933 #ifdef USE_NNTP
934  if (OptNews)
935  return regexec(rx, ((struct FolderFile *) menu->data)[line].desc, 0, NULL, 0);
936 #endif
937  struct FolderFile current_ff = ((struct FolderFile *) menu->data)[line];
938  char *search_on = current_ff.desc ? current_ff.desc : current_ff.name;
939 
940  return regexec(rx, search_on, 0, NULL, 0);
941 }
char * desc
Definition: browser.h:71
char * name
Definition: browser.h:70
Browser entry representing a folder/dir.
Definition: browser.h:61
const char * line
Definition: common.c:36
void * data
Extra data for the current menu.
Definition: mutt_menu.h:86
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:43
+ 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::menu_make_entry()

Definition at line 946 of file browser.c.

947 {
948  struct Folder folder;
949 
950  folder.ff = &((struct FolderFile *) menu->data)[line];
951  folder.num = line;
952 
953 #ifdef USE_NNTP
954  if (OptNews)
955  {
956  mutt_expando_format(buf, buflen, 0, menu->indexwin->cols,
958  (unsigned long) &folder, MUTT_FORMAT_ARROWCURSOR);
959  }
960  else
961 #endif
962  {
963  mutt_expando_format(buf, buflen, 0, menu->indexwin->cols,
965  (unsigned long) &folder, MUTT_FORMAT_ARROWCURSOR);
966  }
967 }
void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t *callback, unsigned long data, MuttFormatFlags flags)
Expand expandos (x) in a string.
Definition: muttlib.c:878
#define NONULL(x)
Definition: string2.h:37
#define MUTT_FORMAT_ARROWCURSOR
Reserve space for arrow_cursor.
Definition: format_flags.h:35
char * C_FolderFormat
Config: printf-like format string for the browser&#39;s display of folders.
Definition: browser.c:72
struct FolderFile * ff
Definition: browser.h:54
A folder/dir in the browser.
Definition: browser.h:52
Browser entry representing a folder/dir.
Definition: browser.h:61
const char * line
Definition: common.c:36
struct MuttWindow * indexwin
Definition: mutt_menu.h:95
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, unsigned long data, MuttFormatFlags flags)
Format a string for the folder browser - Implements format_t.
Definition: browser.c:380
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, unsigned long data, MuttFormatFlags flags)
Format a string for the newsgroup menu - Implements format_t.
Definition: browse.c:51
void * data
Extra data for the current menu.
Definition: mutt_menu.h:86
char * C_GroupIndexFormat
Config: (nntp) printf-like format string for the browser&#39;s display of newsgroups. ...
Definition: browser.c:73
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:43
+ 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 977 of file browser.c.

978 {
979  menu->top = 0;
980  /* Reset menu position to 1.
981  * We do not risk overflow as the init_menu function changes
982  * current if it is bigger than state->entrylen. */
983  if ((mutt_str_strcmp(state->entry[0].desc, "..") == 0) ||
984  (mutt_str_strcmp(state->entry[0].desc, "../") == 0))
985  {
986  /* Skip the first entry, unless there's only one entry. */
987  menu->current = (menu->max > 1);
988  }
989  else
990  {
991  menu->current = 0;
992  }
993 }
char * desc
Definition: browser.h:71
int top
Entry that is the top of the current page.
Definition: mutt_menu.h:108
int max
Number of entries in the menu.
Definition: mutt_menu.h:88
int current
Current entry.
Definition: mutt_menu.h:87
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
struct FolderFile * entry
Definition: browser.h:97
+ 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 1003 of file browser.c.

1005 {
1006  menu->max = state->entrylen;
1007 
1008  if (menu->current >= menu->max)
1009  menu->current = menu->max - 1;
1010  if (menu->current < 0)
1011  menu->current = 0;
1012  if (menu->top > menu->current)
1013  menu->top = 0;
1014 
1015  menu->tagged = 0;
1016 
1017 #ifdef USE_NNTP
1018  if (OptNews)
1019  {
1020  if (mailbox)
1021  snprintf(title, titlelen, _("Subscribed newsgroups"));
1022  else
1023  {
1024  snprintf(title, titlelen, _("Newsgroups on server [%s]"),
1026  }
1027  }
1028  else
1029 #endif
1030  {
1031  if (mailbox)
1032  {
1033  menu->is_mailbox_list = true;
1034  snprintf(title, titlelen, _("Mailboxes [%d]"),
1035  mutt_mailbox_check(Context ? Context->mailbox : NULL, 0));
1036  }
1037  else
1038  {
1039  struct Buffer *path = mutt_buffer_pool_get();
1040  menu->is_mailbox_list = false;
1041  mutt_buffer_copy(path, &LastDir);
1043 #ifdef USE_IMAP
1044  if (state->imap_browse && C_ImapListSubscribed)
1045  {
1046  snprintf(title, titlelen, _("Subscribed [%s], File mask: %s"),
1047  mutt_b2s(path), NONULL(C_Mask ? C_Mask->pattern : NULL));
1048  }
1049  else
1050 #endif
1051  {
1052  snprintf(title, titlelen, _("Directory [%s], File mask: %s"),
1053  mutt_b2s(path), NONULL(C_Mask ? C_Mask->pattern : NULL));
1054  }
1055  mutt_buffer_pool_release(&path);
1056  }
1057  }
1058 
1059  /* Browser tracking feature.
1060  * The goal is to highlight the good directory if LastDir is the parent dir
1061  * of LastDirBackup (this occurs mostly when one hit "../"). It should also work
1062  * properly when the user is in examine_mailboxes-mode. */
1064  {
1065  char target_dir[PATH_MAX] = { 0 };
1066 
1067 #ifdef USE_IMAP
1068  /* Check what kind of dir LastDirBackup is. */
1070  {
1071  mutt_str_strfcpy(target_dir, mutt_b2s(&LastDirBackup), sizeof(target_dir));
1072  imap_clean_path(target_dir, sizeof(target_dir));
1073  }
1074  else
1075 #endif
1076  mutt_str_strfcpy(target_dir, strrchr(mutt_b2s(&LastDirBackup), '/') + 1,
1077  sizeof(target_dir));
1078 
1079  /* If we get here, it means that LastDir is the parent directory of
1080  * LastDirBackup. I.e., we're returning from a subdirectory, and we want
1081  * to position the cursor on the directory we're returning from. */
1082  bool matched = false;
1083  for (unsigned int i = 0; i < state->entrylen; i++)
1084  {
1085  if (mutt_str_strcmp(state->entry[i].name, target_dir) == 0)
1086  {
1087  menu->current = i;
1088  matched = true;
1089  break;
1090  }
1091  }
1092  if (!matched)
1093  browser_highlight_default(state, menu);
1094  }
1095  else
1096  browser_highlight_default(state, menu);
1097 
1098  menu->redraw = REDRAW_FULL;
1099 }
The "current" mailbox.
Definition: context.h:36
WHERE bool C_ImapListSubscribed
Config: (imap) When browsing a mailbox, only display subscribed folders.
Definition: globals.h:229
#define REDRAW_FULL
Redraw everything.
Definition: mutt_menu.h:47
#define NONULL(x)
Definition: string2.h:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:100
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2430
struct ConnAccount account
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
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:111
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
Match case when comparing strings.
Definition: string2.h:67
void mutt_buffer_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:704
char host[128]
Definition: connaccount.h:36
static struct Buffer LastDirBackup
Definition: browser.c:102
struct Mailbox * mailbox
Definition: context.h:50
char * name
Definition: browser.h:70
#define mutt_b2s(buf)
Definition: buffer.h:41
#define PATH_MAX
Definition: mutt.h:50
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all all Mailboxes for new mail.
Definition: mutt_mailbox.c:127
int top
Entry that is the top of the current page.
Definition: mutt_menu.h:108
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:750
bool is_mailbox_list
Definition: mutt_menu.h:94
int tagged
Number of tagged entries.
Definition: mutt_menu.h:111
int max
Number of entries in the menu.
Definition: mutt_menu.h:88
size_t entrylen
number of real entries
Definition: browser.h:98
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:168
MuttRedrawFlags redraw
When to redraw the screen.
Definition: mutt_menu.h:89
struct Connection * conn
Definition: nntp.h:102
static void browser_highlight_default(struct BrowserState *state, struct Menu *menu)
Decide which browser item should be highlighted.
Definition: browser.c:977
WHERE struct Regex * C_Mask
Config: Only display files/dirs matching this regex in the browser.
Definition: globals.h:178
static struct Buffer LastDir
Definition: browser.c:101
int current
Current entry.
Definition: mutt_menu.h:87
char * pattern
printable version
Definition: regex3.h:59
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:52
bool imap_browse
Definition: browser.h:101
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:43
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
struct FolderFile * entry
Definition: browser.h:97
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:75
void imap_clean_path(char *path, size_t plen)
Cleans an IMAP path using imap_fix_path.
Definition: util.c:326
+ 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::menu_tag()

Definition at line 1104 of file browser.c.

1105 {
1106  struct FolderFile *ff = &(((struct FolderFile *) menu->data)[sel]);
1107  if (S_ISDIR(ff->mode) || (S_ISLNK(ff->mode) && link_is_dir(mutt_b2s(&LastDir), ff->name)))
1108  {
1109  mutt_error(_("Can't attach a directory"));
1110  return 0;
1111  }
1112 
1113  bool ot = ff->tagged;
1114  ff->tagged = ((act >= 0) ? act : !ff->tagged);
1115 
1116  return ff->tagged - ot;
1117 }
mode_t mode
Definition: browser.h:63
static bool link_is_dir(const char *folder, const char *path)
Does this symlink point to a directory?
Definition: browser.c:344
#define _(a)
Definition: message.h:28
char * name
Definition: browser.h:70
#define mutt_b2s(buf)
Definition: buffer.h:41
Browser entry representing a folder/dir.
Definition: browser.h:61
#define mutt_error(...)
Definition: logging.h:84
void * data
Extra data for the current menu.
Definition: mutt_menu.h:86
static struct Buffer LastDir
Definition: browser.c:101
bool tagged
Definition: browser.h:86
+ 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 1129 of file browser.c.

1130 {
1131  init_lastdir();
1132 
1134 
1135  /* Method that will fetch the parent path depending on the type of the path. */
1136  char buf[PATH_MAX];
1137  mutt_get_parent_path(mutt_b2s(&LastDirBackup), buf, sizeof(buf));
1138  mutt_buffer_strcpy(&LastDir, buf);
1139 }
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:50
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
static struct Buffer LastDir
Definition: browser.c: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:1656
+ 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 1148 of file browser.c.

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

2187 {
2188  struct Buffer *f_buf = mutt_buffer_pool_get();
2189 
2190  mutt_buffer_strcpy(f_buf, NONULL(file));
2191  mutt_buffer_select_file(f_buf, flags, files, numfiles);
2192  mutt_str_strfcpy(file, mutt_b2s(f_buf), filelen);
2193 
2194  mutt_buffer_pool_release(&f_buf);
2195 }
#define NONULL(x)
Definition: string2.h:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:100
void mutt_buffer_select_file(struct Buffer *file, SelectFileFlags flags, char ***files, int *numfiles)
Let the user select a file.
Definition: browser.c:1148
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:111
String manipulation buffer.
Definition: buffer.h:33
#define mutt_b2s(buf)
Definition: buffer.h:41
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:750
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ C_BrowserAbbreviateMailboxes

bool C_BrowserAbbreviateMailboxes

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

Definition at line 71 of file browser.c.

◆ C_FolderFormat

char* C_FolderFormat

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

Definition at line 72 of file browser.c.

◆ C_GroupIndexFormat

char* C_GroupIndexFormat

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

Definition at line 73 of file browser.c.

◆ C_NewsgroupsCharset

char* C_NewsgroupsCharset

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

Definition at line 74 of file browser.c.

◆ C_ShowOnlyUnread

bool C_ShowOnlyUnread

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

Definition at line 75 of file browser.c.

◆ C_SortBrowser

short C_SortBrowser

Config: Sort method for the browser.

Definition at line 76 of file browser.c.

◆ C_VfolderFormat

char* C_VfolderFormat

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

Definition at line 77 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

Definition at line 79 of file browser.c.

◆ FolderNewsHelp

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

Definition at line 89 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.