NeoMutt  2018-07-16 +2388-bcedc8
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 <time.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

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 BufferLastDir = NULL
 
static struct BufferLastDirBackup = NULL
 

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

void mutt_browser_cleanup ( void  )

Clean up working Buffers.

Definition at line 108 of file browser.c.

109 {
112 }
static struct Buffer * LastDir
Definition: browser.c:102
void mutt_buffer_free(struct Buffer **p)
Release a Buffer and its contents.
Definition: buffer.c:134
static struct Buffer * LastDirBackup
Definition: browser.c:103

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

121 {
122  for (size_t c = 0; c < state->entrylen; c++)
123  {
124  FREE(&((state->entry)[c].name));
125  FREE(&((state->entry)[c].desc));
126  }
127 #ifdef USE_IMAP
128  FREE(&state->folder);
129 #endif
130  FREE(&state->entry);
131 }
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:

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

142 {
143  const struct FolderFile *pa = (const struct FolderFile *) a;
144  const struct FolderFile *pb = (const struct FolderFile *) b;
145 
146  /* inbox should be sorted ahead of its siblings */
147  int r = mutt_inbox_cmp(pa->name, pb->name);
148  if (r == 0)
149  r = mutt_str_strcoll(pa->name, pb->name);
150  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
151 }
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:77
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:1652
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort.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:

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

162 {
163  const struct FolderFile *pa = (const struct FolderFile *) a;
164  const struct FolderFile *pb = (const struct FolderFile *) b;
165 
166  int r = mutt_str_strcoll(pa->desc, pb->desc);
167 
168  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
169 }
char * desc
Definition: browser.h:71
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:77
Browser entry representing a folder/dir.
Definition: browser.h:61
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort.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:

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

180 {
181  const struct FolderFile *pa = (const struct FolderFile *) a;
182  const struct FolderFile *pb = (const struct FolderFile *) b;
183 
184  int r = pa->mtime - pb->mtime;
185 
186  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
187 }
time_t mtime
Definition: browser.h:65
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:77
Browser entry representing a folder/dir.
Definition: browser.h:61
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort.h:86

+ Here is the caller graph for this function:

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

198 {
199  const struct FolderFile *pa = (const struct FolderFile *) a;
200  const struct FolderFile *pb = (const struct FolderFile *) b;
201 
202  int r = pa->size - pb->size;
203 
204  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
205 }
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:77
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: sort.h:86

+ Here is the caller graph for this function:

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

216 {
217  const struct FolderFile *pa = (const struct FolderFile *) a;
218  const struct FolderFile *pb = (const struct FolderFile *) b;
219 
220  int r = 0;
221  if (pa->has_mailbox && pb->has_mailbox)
222  r = pa->msg_count - pb->msg_count;
223  else if (pa->has_mailbox)
224  r = -1;
225  else
226  r = 1;
227 
228  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
229 }
bool has_mailbox
Definition: browser.h:84
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:77
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: sort.h:86

+ Here is the caller graph for this function:

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

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

+ Here is the caller graph for this function:

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

268 {
269  const struct FolderFile *pa = (const struct FolderFile *) a;
270  const struct FolderFile *pb = (const struct FolderFile *) b;
271 
272  if ((mutt_str_strcoll(pa->desc, "../") == 0) || (mutt_str_strcoll(pa->desc, "..") == 0))
273  return -1;
274  if ((mutt_str_strcoll(pb->desc, "../") == 0) || (mutt_str_strcoll(pb->desc, "..") == 0))
275  return 1;
276 
277  switch (C_SortBrowser & SORT_MASK)
278  {
279  case SORT_COUNT:
280  return browser_compare_count(a, b);
281  case SORT_DATE:
282  return browser_compare_date(a, b);
283  case SORT_DESC:
284  return browser_compare_desc(a, b);
285  case SORT_SIZE:
286  return browser_compare_size(a, b);
287  case SORT_UNREAD:
288  return browser_compare_count_new(a, b);
289  case SORT_SUBJECT:
290  default:
291  return browser_compare_subject(a, b);
292  }
293 }
static int browser_compare_date(const void *a, const void *b)
Compare the date of two browser entries.
Definition: browser.c:179
Sort by the date the email was sent.
Definition: sort.h:50
char * desc
Definition: browser.h:71
Sort by the folder&#39;s description.
Definition: sort.h:70
static int browser_compare_desc(const void *a, const void *b)
Compare the descriptions of two browser entries.
Definition: browser.c:161
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:77
static int browser_compare_count(const void *a, const void *b)
Compare the message count of two browser entries.
Definition: browser.c:215
Sort by the email&#39;s subject.
Definition: sort.h:53
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:239
static int browser_compare_size(const void *a, const void *b)
Compare the size of two browser entries.
Definition: browser.c:197
Sort by the number of unread emails.
Definition: sort.h:66
static int browser_compare_subject(const void *a, const void *b)
Compare the subject of two browser entries.
Definition: browser.c:141
Sort by the size of the email.
Definition: sort.h:51
Sort by number of emails in a folder.
Definition: sort.h:65
int mutt_str_strcoll(const char *a, const char *b)
Collate two strings (compare using locale), safely.
Definition: string.c:679
#define SORT_MASK
Mask for the sort id.
Definition: sort.h:85

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

303 {
304  switch (C_SortBrowser & SORT_MASK)
305  {
306  /* Also called "I don't care"-sort-method. */
307  case SORT_ORDER:
308  return;
309 #ifdef USE_NNTP
310  case SORT_SIZE:
311  case SORT_DATE:
312  if (OptNews)
313  return;
314 #endif
315  default:
316  break;
317  }
318 
319  qsort(state->entry, state->entrylen, sizeof(struct FolderFile), browser_compare);
320 }
Sort by the date the email was sent.
Definition: sort.h:50
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:77
Browser entry representing a folder/dir.
Definition: browser.h:61
size_t entrylen
number of real entries
Definition: browser.h:98
Sort by the size of the email.
Definition: sort.h:51
static int browser_compare(const void *a, const void *b)
Sort the items in the browser.
Definition: browser.c:267
Sort by the order the messages appear in the mailbox.
Definition: sort.h:55
#define SORT_MASK
Mask for the sort id.
Definition: sort.h:85
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:

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

330 {
331  struct stat st;
332  bool retval = false;
333 
334  struct Buffer *fullpath = mutt_buffer_pool_get();
335  mutt_buffer_concat_path(fullpath, folder, path);
336 
337  if (stat(mutt_b2s(fullpath), &st) == 0)
338  retval = S_ISDIR(st.st_mode);
339 
340  mutt_buffer_pool_release(&fullpath);
341 
342  return retval;
343 }
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:75
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:86
String manipulation buffer.
Definition: buffer.h:33
#define mutt_b2s(buf)
Definition: buffer.h:41
void mutt_buffer_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition: buffer.c:381

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

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

static void add_folder ( struct Menu menu,
struct BrowserState state,
const char *  name,
const char *  desc,
const struct stat *  s,
struct Mailbox m,
void *  data 
)
static

Add a folder to the browser list.

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

Definition at line 613 of file browser.c.

616 {
617  if (m && (m->flags & MB_HIDDEN))
618  {
619  return;
620  }
621 
622  if (state->entrylen == state->entrymax)
623  {
624  /* need to allocate more space */
625  mutt_mem_realloc(&state->entry, sizeof(struct FolderFile) * (state->entrymax += 256));
626  memset(&state->entry[state->entrylen], 0, sizeof(struct FolderFile) * 256);
627  if (menu)
628  menu->data = state->entry;
629  }
630 
631  if (s)
632  {
633  (state->entry)[state->entrylen].mode = s->st_mode;
634  (state->entry)[state->entrylen].mtime = s->st_mtime;
635  (state->entry)[state->entrylen].size = s->st_size;
636  (state->entry)[state->entrylen].gid = s->st_gid;
637  (state->entry)[state->entrylen].uid = s->st_uid;
638  (state->entry)[state->entrylen].nlink = s->st_nlink;
639 
640  (state->entry)[state->entrylen].local = true;
641  }
642  else
643  (state->entry)[state->entrylen].local = false;
644 
645  if (m)
646  {
647  (state->entry)[state->entrylen].has_mailbox = true;
648  (state->entry)[state->entrylen].has_new_mail = m->has_new;
649  (state->entry)[state->entrylen].msg_count = m->msg_count;
650  (state->entry)[state->entrylen].msg_unread = m->msg_unread;
651  }
652 
653  (state->entry)[state->entrylen].name = mutt_str_strdup(name);
654  (state->entry)[state->entrylen].desc = mutt_str_strdup(desc ? desc : name);
655 #ifdef USE_IMAP
656  (state->entry)[state->entrylen].imap = false;
657 #endif
658 #ifdef USE_NNTP
659  if (OptNews)
660  (state->entry)[state->entrylen].nd = data;
661 #endif
662  (state->entrylen)++;
663 }
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:

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

Initialise a browser state.

Parameters
stateBrowserState to initialise
menuCurrent menu

Definition at line 670 of file browser.c.

671 {
672  state->entrylen = 0;
673  state->entrymax = 256;
674  state->entry = mutt_mem_calloc(state->entrymax, sizeof(struct FolderFile));
675 #ifdef USE_IMAP
676  state->imap_browse = false;
677 #endif
678  if (menu)
679  menu->data = state->entry;
680 }
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:

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

693 {
694  int rc = -1;
695  struct Buffer *buf = mutt_buffer_pool_get();
696 #ifdef USE_NNTP
697  if (OptNews)
698  {
700 
701  init_state(state, menu);
702 
703  for (unsigned int i = 0; i < adata->groups_num; i++)
704  {
705  struct NntpMboxData *mdata = adata->groups_list[i];
706  if (!mdata)
707  continue;
708  if (prefix && *prefix && !mutt_str_startswith(mdata->group, prefix, CASE_MATCH))
709  continue;
710  if (!mutt_regex_match(C_Mask, mdata->group))
711  {
712  continue;
713  }
714  add_folder(menu, state, mdata->group, NULL, NULL, NULL, mdata);
715  }
716  }
717  else
718 #endif /* USE_NNTP */
719  {
720  struct stat s;
721  DIR *dp = NULL;
722  struct dirent *de = NULL;
723 
724  while (stat(d, &s) == -1)
725  {
726  if (errno == ENOENT)
727  {
728  /* The last used directory is deleted, try to use the parent dir. */
729  char *c = strrchr(d, '/');
730 
731  if (c && (c > d))
732  {
733  *c = '\0';
734  continue;
735  }
736  }
737  mutt_perror(d);
738  goto ed_out;
739  }
740 
741  if (!S_ISDIR(s.st_mode))
742  {
743  mutt_error(_("%s is not a directory"), d);
744  goto ed_out;
745  }
746 
747  if (Context && Context->mailbox)
749 
750  dp = opendir(d);
751  if (!dp)
752  {
753  mutt_perror(d);
754  goto ed_out;
755  }
756 
757  init_state(state, menu);
758 
759  struct MailboxList ml = neomutt_mailboxlist_get_all(NeoMutt, MUTT_MAILBOX_ANY);
760  while ((de = readdir(dp)))
761  {
762  if (mutt_str_strcmp(de->d_name, ".") == 0)
763  continue; /* we don't need . */
764 
765  if (prefix && *prefix && !mutt_str_startswith(de->d_name, prefix, CASE_MATCH))
766  {
767  continue;
768  }
769  if (!mutt_regex_match(C_Mask, de->d_name))
770  {
771  continue;
772  }
773 
774  mutt_buffer_concat_path(buf, d, de->d_name);
775  if (lstat(mutt_b2s(buf), &s) == -1)
776  continue;
777 
778  /* No size for directories or symlinks */
779  if (S_ISDIR(s.st_mode) || S_ISLNK(s.st_mode))
780  s.st_size = 0;
781  else if (!S_ISREG(s.st_mode))
782  continue;
783 
784  struct MailboxNode *np = NULL;
785  STAILQ_FOREACH(np, &ml, entries)
786  {
787  if (mutt_str_strcmp(mutt_b2s(buf), mutt_b2s(np->mailbox->pathbuf)) != 0)
788  break;
789  }
790 
791  if (np && Context && Context->mailbox &&
793  {
796  }
797  add_folder(menu, state, de->d_name, NULL, &s, np ? np->mailbox : NULL, NULL);
798  }
800  closedir(dp);
801  }
802  browser_sort(state);
803  rc = 0;
804 ed_out:
806  return rc;
807 }
The "current" mailbox.
Definition: context.h:36
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:75
#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:86
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:613
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:126
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:302
#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
struct Buffer * pathbuf
Definition: mailbox.h:94
#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:185
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
List of Mailboxes.
Definition: mailbox.h:156
static void init_state(struct BrowserState *state, struct Menu *menu)
Initialise a browser state.
Definition: browser.c:670
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
void mutt_buffer_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition: buffer.c:381

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

817 {
818  struct stat s;
819  struct Buffer *md = NULL;
820  struct Buffer *mailbox = NULL;
821 
822 #ifdef USE_NNTP
823  if (OptNews)
824  {
826 
827  init_state(state, menu);
828 
829  for (unsigned int i = 0; i < adata->groups_num; i++)
830  {
831  struct NntpMboxData *mdata = adata->groups_list[i];
832  if (mdata && (mdata->has_new_mail ||
833  (mdata->subscribed && (mdata->unread || !C_ShowOnlyUnread))))
834  {
835  add_folder(menu, state, mdata->group, NULL, NULL, NULL, mdata);
836  }
837  }
838  }
839  else
840 #endif
841  {
842  init_state(state, menu);
843 
845  return -1;
846  mailbox = mutt_buffer_pool_get();
847  md = mutt_buffer_pool_get();
849 
850  struct MailboxList ml = neomutt_mailboxlist_get_all(NeoMutt, MUTT_MAILBOX_ANY);
851  struct MailboxNode *np = NULL;
852  STAILQ_FOREACH(np, &ml, entries)
853  {
855  {
858  }
859 
860  mutt_buffer_strcpy(mailbox, mutt_b2s(np->mailbox->pathbuf));
863 
864  switch (np->mailbox->magic)
865  {
866  case MUTT_IMAP:
867  case MUTT_POP:
868  add_folder(menu, state, mutt_b2s(mailbox), np->mailbox->name, NULL,
869  np->mailbox, NULL);
870  continue;
871  case MUTT_NOTMUCH:
872  case MUTT_NNTP:
873  add_folder(menu, state, mutt_b2s(np->mailbox->pathbuf),
874  np->mailbox->name, NULL, np->mailbox, NULL);
875  continue;
876  default: /* Continue */
877  break;
878  }
879 
880  if (lstat(mutt_b2s(np->mailbox->pathbuf), &s) == -1)
881  continue;
882 
883  if ((!S_ISREG(s.st_mode)) && (!S_ISDIR(s.st_mode)) && (!S_ISLNK(s.st_mode)))
884  continue;
885 
886  if (np->mailbox->magic == MUTT_MAILDIR)
887  {
888  struct stat st2;
889 
890  mutt_buffer_printf(md, "%s/new", mutt_b2s(np->mailbox->pathbuf));
891  if (stat(mutt_b2s(md), &s) < 0)
892  s.st_mtime = 0;
893  mutt_buffer_printf(md, "%s/cur", mutt_b2s(np->mailbox->pathbuf));
894  if (stat(mutt_b2s(md), &st2) < 0)
895  st2.st_mtime = 0;
896  if (st2.st_mtime > s.st_mtime)
897  s.st_mtime = st2.st_mtime;
898  }
899 
900  add_folder(menu, state, mutt_b2s(mailbox), np->mailbox->name, &s, np->mailbox, NULL);
901  }
903  }
904  browser_sort(state);
905 
906  mutt_buffer_pool_release(&mailbox);
908  return 0;
909 }
bool has_new_mail
Definition: nntp.h:148
The "current" mailbox.
Definition: context.h:36
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:75
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:86
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:613
String manipulation buffer.
Definition: buffer.h:33
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:191
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:688
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
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:314
&#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:126
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:302
bool C_ShowOnlyUnread
Config: (nntp) Only show subscribed newsgroups with unread articles.
Definition: browser.c:76
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
NNTP-specific Mailbox data -.
Definition: nntp.h:138
&#39;Notmuch&#39; (virtual) Mailbox type
Definition: mailbox.h:53
struct Buffer * pathbuf
Definition: mailbox.h:94
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:72
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:670
&#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:

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

915 {
916 #ifdef USE_NNTP
917  if (OptNews)
918  return regexec(rx, ((struct FolderFile *) menu->data)[line].desc, 0, NULL, 0);
919 #endif
920  struct FolderFile current_ff = ((struct FolderFile *) menu->data)[line];
921  char *search_on = current_ff.desc ? current_ff.desc : current_ff.name;
922 
923  return regexec(rx, search_on, 0, NULL, 0);
924 }
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:

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

930 {
931  struct Folder folder;
932 
933  folder.ff = &((struct FolderFile *) menu->data)[line];
934  folder.num = line;
935 
936 #ifdef USE_NNTP
937  if (OptNews)
938  {
939  mutt_expando_format(buf, buflen, 0, MuttIndexWindow->cols,
941  (unsigned long) &folder, MUTT_FORMAT_ARROWCURSOR);
942  }
943  else
944 #endif
945  {
946  mutt_expando_format(buf, buflen, 0, MuttIndexWindow->cols,
948  (unsigned long) &folder, MUTT_FORMAT_ARROWCURSOR);
949  }
950 }
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:838
#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:73
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 * MuttIndexWindow
Index Window.
Definition: mutt_window.c:40
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:365
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:74
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:

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

961 {
962  menu->top = 0;
963  /* Reset menu position to 1.
964  * We do not risk overflow as the init_menu function changes
965  * current if it is bigger than state->entrylen. */
966  if ((mutt_str_strcmp(state->entry[0].desc, "..") == 0) ||
967  (mutt_str_strcmp(state->entry[0].desc, "../") == 0))
968  {
969  /* Skip the first entry, unless there's only one entry. */
970  menu->current = (menu->max > 1);
971  }
972  else
973  {
974  menu->current = 0;
975  }
976 }
char * desc
Definition: browser.h:71
int top
entry that is the top of the current page
Definition: mutt_menu.h:110
int max
the 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:

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

988 {
989  menu->max = state->entrylen;
990 
991  if (menu->current >= menu->max)
992  menu->current = menu->max - 1;
993  if (menu->current < 0)
994  menu->current = 0;
995  if (menu->top > menu->current)
996  menu->top = 0;
997 
998  menu->tagged = 0;
999 
1000 #ifdef USE_NNTP
1001  if (OptNews)
1002  {
1003  if (mailbox)
1004  snprintf(title, titlelen, _("Subscribed newsgroups"));
1005  else
1006  {
1007  snprintf(title, titlelen, _("Newsgroups on server [%s]"),
1009  }
1010  }
1011  else
1012 #endif
1013  {
1014  if (mailbox)
1015  {
1016  menu->is_mailbox_list = true;
1017  snprintf(title, titlelen, _("Mailboxes [%d]"),
1018  mutt_mailbox_check(Context ? Context->mailbox : NULL, 0));
1019  }
1020  else
1021  {
1022  struct Buffer *path = mutt_buffer_pool_get();
1023  menu->is_mailbox_list = false;
1026 #ifdef USE_IMAP
1027  if (state->imap_browse && C_ImapListSubscribed)
1028  {
1029  snprintf(title, titlelen, _("Subscribed [%s], File mask: %s"),
1030  mutt_b2s(path), NONULL(C_Mask ? C_Mask->pattern : NULL));
1031  }
1032  else
1033 #endif
1034  {
1035  snprintf(title, titlelen, _("Directory [%s], File mask: %s"),
1036  mutt_b2s(path), NONULL(C_Mask ? C_Mask->pattern : NULL));
1037  }
1038  mutt_buffer_pool_release(&path);
1039  }
1040  }
1041 
1042  /* Browser tracking feature.
1043  * The goal is to highlight the good directory if LastDir is the parent dir
1044  * of LastDirBackup (this occurs mostly when one hit "../"). It should also work
1045  * properly when the user is in examine_mailboxes-mode. */
1047  {
1048  char target_dir[PATH_MAX] = { 0 };
1049 
1050 #ifdef USE_IMAP
1051  /* Check what kind of dir LastDirBackup is. */
1053  {
1054  mutt_str_strfcpy(target_dir, mutt_b2s(LastDirBackup), sizeof(target_dir));
1055  imap_clean_path(target_dir, sizeof(target_dir));
1056  }
1057  else
1058 #endif
1059  mutt_str_strfcpy(target_dir, strrchr(mutt_b2s(LastDirBackup), '/') + 1,
1060  sizeof(target_dir));
1061 
1062  /* If we get here, it means that LastDir is the parent directory of
1063  * LastDirBackup. I.e., we're returning from a subdirectory, and we want
1064  * to position the cursor on the directory we're returning from. */
1065  bool matched = false;
1066  for (unsigned int i = 0; i < state->entrylen; i++)
1067  {
1068  if (mutt_str_strcmp(state->entry[i].name, target_dir) == 0)
1069  {
1070  menu->current = i;
1071  matched = true;
1072  break;
1073  }
1074  }
1075  if (!matched)
1076  browser_highlight_default(state, menu);
1077  }
1078  else
1079  browser_highlight_default(state, menu);
1080 
1081  menu->redraw = REDRAW_FULL;
1082 }
The "current" mailbox.
Definition: context.h:36
WHERE bool C_ImapListSubscribed
Config: (imap) When browsing a mailbox, only display subscribed folders.
Definition: globals.h:235
#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:75
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
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:86
static struct Buffer * LastDir
Definition: browser.c:102
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:688
char host[128]
Definition: connaccount.h:36
struct Mailbox * mailbox
Definition: context.h:50
char * name
Definition: browser.h:70
#define mutt_b2s(buf)
Definition: buffer.h:41
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:314
#define PATH_MAX
Definition: mutt.h:51
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all all Mailboxes for new mail.
Definition: mutt_mailbox.c:126
int top
entry that is the top of the current page
Definition: mutt_menu.h:110
static struct Buffer * LastDirBackup
Definition: browser.c:103
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:113
int max
the 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:960
WHERE struct Regex * C_Mask
Config: Only display files/dirs matching this regex in the browser.
Definition: globals.h:185
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:327

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

1088 {
1089  struct FolderFile *ff = &(((struct FolderFile *) menu->data)[sel]);
1090  if (S_ISDIR(ff->mode) || (S_ISLNK(ff->mode) && link_is_dir(mutt_b2s(LastDir), ff->name)))
1091  {
1092  mutt_error(_("Can't attach a directory"));
1093  return 0;
1094  }
1095 
1096  bool ot = ff->tagged;
1097  ff->tagged = ((act >= 0) ? act : !ff->tagged);
1098 
1099  return ff->tagged - ot;
1100 }
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:329
static struct Buffer * LastDir
Definition: browser.c:102
#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
bool tagged
Definition: browser.h:86

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

1113 {
1114  if (!LastDir)
1115  {
1118  }
1119 
1121 
1122  /* Method that will fetch the parent path depending on the type of the path. */
1123  char buf[PATH_MAX];
1124  mutt_get_parent_path(mutt_b2s(LastDirBackup), buf, sizeof(buf));
1126 }
static struct Buffer * LastDir
Definition: browser.c:102
struct Buffer * mutt_buffer_alloc(size_t size)
Create a new Buffer.
Definition: buffer.c:296
#define mutt_b2s(buf)
Definition: buffer.h:41
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:314
#define PATH_MAX
Definition: mutt.h:51
static struct Buffer * LastDirBackup
Definition: browser.c:103
void mutt_get_parent_path(const char *path, char *buf, size_t buflen)
Find the parent of a path (or mailbox)
Definition: muttlib.c:1597

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_buffer_select_file ( struct Buffer file,
SelectFileFlags  flags,
char ***  files,
int *  numfiles 
)

Let the user select a file.

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

Definition at line 1135 of file browser.c.

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

+ Here is the caller graph for this function:

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

Let the user select a file.

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

Definition at line 2179 of file browser.c.

2181 {
2182  struct Buffer *f_buf = mutt_buffer_pool_get();
2183 
2184  mutt_buffer_strcpy(f_buf, NONULL(file));
2185  mutt_buffer_select_file(f_buf, flags, files, numfiles);
2186  mutt_str_strfcpy(file, mutt_b2s(f_buf), filelen);
2187 
2188  mutt_buffer_pool_release(&f_buf);
2189 }
#define NONULL(x)
Definition: string2.h:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:75
void mutt_buffer_select_file(struct Buffer *file, SelectFileFlags flags, char ***files, int *numfiles)
Let the user select a file.
Definition: browser.c:1135
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:86
String manipulation buffer.
Definition: buffer.h:33
#define mutt_b2s(buf)
Definition: buffer.h:41
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:314
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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Variable Documentation

bool C_BrowserAbbreviateMailboxes

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

Definition at line 72 of file browser.c.

char* C_FolderFormat

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

Definition at line 73 of file browser.c.

char* C_GroupIndexFormat

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

Definition at line 74 of file browser.c.

char* C_NewsgroupsCharset

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

Definition at line 75 of file browser.c.

bool C_ShowOnlyUnread

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

Definition at line 76 of file browser.c.

short C_SortBrowser

Config: Sort method for the browser.

Definition at line 77 of file browser.c.

char* C_VfolderFormat

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

Definition at line 78 of file browser.c.

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

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

struct Buffer* LastDir = NULL
static

Definition at line 102 of file browser.c.

struct Buffer* LastDirBackup = NULL
static

Definition at line 103 of file browser.c.