NeoMutt  2018-07-16 +1783-b00bd9
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 <unistd.h>
#include "mutt/mutt.h"
#include "config/lib.h"
#include "email/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 "mailbox.h"
#include "maildir/lib.h"
#include "mutt_attach.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 "sort.h"
#include "imap/imap.h"
#include "nntp/nntp.h"
#include "pop/pop.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 113 of file browser.c.

114 {
117 }
static struct Buffer * LastDir
Definition: browser.c:107
void mutt_buffer_free(struct Buffer **p)
Release a Buffer and its contents.
Definition: buffer.c:138
static struct Buffer * LastDirBackup
Definition: browser.c:108

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

126 {
127  for (size_t c = 0; c < state->entrylen; c++)
128  {
129  FREE(&((state->entry)[c].name));
130  FREE(&((state->entry)[c].desc));
131  }
132 #ifdef USE_IMAP
133  FREE(&state->folder);
134 #endif
135  FREE(&state->entry);
136 }
char * folder
Definition: browser.h:99
size_t entrylen
number of real entries
Definition: browser.h:95
#define FREE(x)
Definition: memory.h:40
struct FolderFile * entry
Definition: browser.h:94

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

147 {
148  struct FolderFile *pa = (struct FolderFile *) a;
149  struct FolderFile *pb = (struct FolderFile *) b;
150 
151  /* inbox should be sorted ahead of its siblings */
152  int r = mutt_inbox_cmp(pa->name, pb->name);
153  if (r == 0)
154  r = mutt_str_strcoll(pa->name, pb->name);
155  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
156 }
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:82
char * name
Definition: browser.h:67
Browser entry representing a folder/dir.
Definition: browser.h:58
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:1648
#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:682

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

167 {
168  struct FolderFile *pa = (struct FolderFile *) a;
169  struct FolderFile *pb = (struct FolderFile *) b;
170 
171  int r = mutt_str_strcoll(pa->desc, pb->desc);
172 
173  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
174 }
char * desc
Definition: browser.h:68
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:82
Browser entry representing a folder/dir.
Definition: browser.h:58
#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:682

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

185 {
186  struct FolderFile *pa = (struct FolderFile *) a;
187  struct FolderFile *pb = (struct FolderFile *) b;
188 
189  int r = pa->mtime - pb->mtime;
190 
191  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
192 }
time_t mtime
Definition: browser.h:62
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:82
Browser entry representing a folder/dir.
Definition: browser.h:58
#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 202 of file browser.c.

203 {
204  struct FolderFile *pa = (struct FolderFile *) a;
205  struct FolderFile *pb = (struct FolderFile *) b;
206 
207  int r = pa->size - pb->size;
208 
209  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
210 }
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:82
off_t size
Definition: browser.h:61
Browser entry representing a folder/dir.
Definition: browser.h:58
#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 220 of file browser.c.

221 {
222  struct FolderFile *pa = (struct FolderFile *) a;
223  struct FolderFile *pb = (struct FolderFile *) b;
224 
225  int r = 0;
226  if (pa->has_mailbox && pb->has_mailbox)
227  r = pa->msg_count - pb->msg_count;
228  else if (pa->has_mailbox)
229  r = -1;
230  else
231  r = 1;
232 
233  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
234 }
bool has_mailbox
Definition: browser.h:81
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:82
Browser entry representing a folder/dir.
Definition: browser.h:58
int msg_count
total number of messages
Definition: browser.h:71
#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 244 of file browser.c.

245 {
246  struct FolderFile *pa = (struct FolderFile *) a;
247  struct FolderFile *pb = (struct FolderFile *) b;
248 
249  int r = 0;
250  if (pa->has_mailbox && pb->has_mailbox)
251  r = pa->msg_unread - pb->msg_unread;
252  else if (pa->has_mailbox)
253  r = -1;
254  else
255  r = 1;
256 
257  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
258 }
int msg_unread
number of unread messages
Definition: browser.h:72
bool has_mailbox
Definition: browser.h:81
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:82
Browser entry representing a folder/dir.
Definition: browser.h:58
#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 272 of file browser.c.

273 {
274  struct FolderFile *pa = (struct FolderFile *) a;
275  struct FolderFile *pb = (struct FolderFile *) b;
276 
277  if ((mutt_str_strcoll(pa->desc, "../") == 0) || (mutt_str_strcoll(pa->desc, "..") == 0))
278  return -1;
279  if ((mutt_str_strcoll(pb->desc, "../") == 0) || (mutt_str_strcoll(pb->desc, "..") == 0))
280  return 1;
281 
282  switch (C_SortBrowser & SORT_MASK)
283  {
284  case SORT_COUNT:
285  return browser_compare_count(a, b);
286  case SORT_DATE:
287  return browser_compare_date(a, b);
288  case SORT_DESC:
289  return browser_compare_desc(a, b);
290  case SORT_SIZE:
291  return browser_compare_size(a, b);
292  case SORT_UNREAD:
293  return browser_compare_count_new(a, b);
294  case SORT_SUBJECT:
295  default:
296  return browser_compare_subject(a, b);
297  }
298 }
static int browser_compare_date(const void *a, const void *b)
Compare the date of two browser entries.
Definition: browser.c:184
Sort by the date the email was sent.
Definition: sort.h:50
char * desc
Definition: browser.h:68
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:166
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:82
static int browser_compare_count(const void *a, const void *b)
Compare the message count of two browser entries.
Definition: browser.c:220
Sort by the email&#39;s subject.
Definition: sort.h:53
Browser entry representing a folder/dir.
Definition: browser.h:58
static int browser_compare_count_new(const void *a, const void *b)
Compare the new count of two browser entries.
Definition: browser.c:244
static int browser_compare_size(const void *a, const void *b)
Compare the size of two browser entries.
Definition: browser.c:202
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:146
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:682
#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 307 of file browser.c.

308 {
309  switch (C_SortBrowser & SORT_MASK)
310  {
311  /* Also called "I don't care"-sort-method. */
312  case SORT_ORDER:
313  return;
314 #ifdef USE_NNTP
315  case SORT_SIZE:
316  case SORT_DATE:
317  if (OptNews)
318  return;
319 #endif
320  default:
321  break;
322  }
323 
324  qsort(state->entry, state->entrylen, sizeof(struct FolderFile), browser_compare);
325 }
Sort by the date the email was sent.
Definition: sort.h:50
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:82
Browser entry representing a folder/dir.
Definition: browser.h:58
size_t entrylen
number of real entries
Definition: browser.h:95
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:272
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:42
struct FolderFile * entry
Definition: browser.h:94

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

335 {
336  struct stat st;
337  bool retval = false;
338 
339  struct Buffer *fullpath = mutt_buffer_pool_get();
340  mutt_buffer_concat_path(fullpath, folder, path);
341 
342  if (stat(mutt_b2s(fullpath), &st) == 0)
343  retval = S_ISDIR(st.st_mode);
344 
345  mutt_buffer_pool_release(&fullpath);
346 
347  return retval;
348 }
String manipulation buffer.
Definition: buffer.h:33
#define mutt_b2s(buf)
Definition: buffer.h:42
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: buffer.c:409
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: buffer.c:398
void mutt_buffer_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition: buffer.c:455

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

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

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

617 {
618  if (state->entrylen == state->entrymax)
619  {
620  /* need to allocate more space */
621  mutt_mem_realloc(&state->entry, sizeof(struct FolderFile) * (state->entrymax += 256));
622  memset(&state->entry[state->entrylen], 0, sizeof(struct FolderFile) * 256);
623  if (menu)
624  menu->data = state->entry;
625  }
626 
627  if (s)
628  {
629  (state->entry)[state->entrylen].mode = s->st_mode;
630  (state->entry)[state->entrylen].mtime = s->st_mtime;
631  (state->entry)[state->entrylen].size = s->st_size;
632  (state->entry)[state->entrylen].gid = s->st_gid;
633  (state->entry)[state->entrylen].uid = s->st_uid;
634  (state->entry)[state->entrylen].nlink = s->st_nlink;
635 
636  (state->entry)[state->entrylen].local = true;
637  }
638  else
639  (state->entry)[state->entrylen].local = false;
640 
641  if (m)
642  {
643  (state->entry)[state->entrylen].has_mailbox = true;
644  (state->entry)[state->entrylen].new = m->has_new;
645  (state->entry)[state->entrylen].msg_count = m->msg_count;
646  (state->entry)[state->entrylen].msg_unread = m->msg_unread;
647  }
648 
649  (state->entry)[state->entrylen].name = mutt_str_strdup(name);
650  (state->entry)[state->entrylen].desc = mutt_str_strdup(desc ? desc : name);
651 #ifdef USE_IMAP
652  (state->entry)[state->entrylen].imap = false;
653 #endif
654 #ifdef USE_NNTP
655  if (OptNews)
656  (state->entry)[state->entrylen].nd = data;
657 #endif
658  (state->entrylen)++;
659 }
mode_t mode
Definition: browser.h:60
int msg_count
total number of messages
Definition: mailbox.h:92
int msg_unread
number of unread messages
Definition: mailbox.h:93
bool has_new
mailbox has new mail
Definition: mailbox.h:89
const char * name
Definition: pgpmicalg.c:45
unsigned int entrymax
max entry
Definition: browser.h:96
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:121
Browser entry representing a folder/dir.
Definition: browser.h:58
size_t entrylen
number of real entries
Definition: browser.h:95
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:42
struct FolderFile * entry
Definition: browser.h:94

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

667 {
668  state->entrylen = 0;
669  state->entrymax = 256;
670  state->entry = mutt_mem_calloc(state->entrymax, sizeof(struct FolderFile));
671 #ifdef USE_IMAP
672  state->imap_browse = false;
673 #endif
674  if (menu)
675  menu->data = state->entry;
676 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:51
unsigned int entrymax
max entry
Definition: browser.h:96
Browser entry representing a folder/dir.
Definition: browser.h:58
size_t entrylen
number of real entries
Definition: browser.h:95
void * data
extra data for the current menu
Definition: mutt_menu.h:86
bool imap_browse
Definition: browser.h:98
struct FolderFile * entry
Definition: browser.h:94

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

689 {
690  int rc = -1;
691  struct Buffer *buf = mutt_buffer_pool_get();
692 #ifdef USE_NNTP
693  if (OptNews)
694  {
696 
697  init_state(state, menu);
698 
699  for (unsigned int i = 0; i < adata->groups_num; i++)
700  {
701  struct NntpMboxData *mdata = adata->groups_list[i];
702  if (!mdata)
703  continue;
704  if (prefix && *prefix && !mutt_str_startswith(mdata->group, prefix, CASE_MATCH))
705  continue;
706  if (C_Mask && C_Mask->regex &&
707  !((regexec(C_Mask->regex, mdata->group, 0, NULL, 0) == 0) ^ C_Mask->not))
708  {
709  continue;
710  }
711  add_folder(menu, state, mdata->group, NULL, NULL, NULL, mdata);
712  }
713  }
714  else
715 #endif /* USE_NNTP */
716  {
717  struct stat s;
718  DIR *dp = NULL;
719  struct dirent *de = NULL;
720 
721  while (stat(d, &s) == -1)
722  {
723  if (errno == ENOENT)
724  {
725  /* The last used directory is deleted, try to use the parent dir. */
726  char *c = strrchr(d, '/');
727 
728  if (c && (c > d))
729  {
730  *c = '\0';
731  continue;
732  }
733  }
734  mutt_perror(d);
735  goto ed_out;
736  }
737 
738  if (!S_ISDIR(s.st_mode))
739  {
740  mutt_error(_("%s is not a directory"), d);
741  goto ed_out;
742  }
743 
744  if (Context && Context->mailbox)
746 
747  dp = opendir(d);
748  if (!dp)
749  {
750  mutt_perror(d);
751  goto ed_out;
752  }
753 
754  init_state(state, menu);
755 
756  while ((de = readdir(dp)))
757  {
758  if (mutt_str_strcmp(de->d_name, ".") == 0)
759  continue; /* we don't need . */
760 
761  if (prefix && *prefix && !mutt_str_startswith(de->d_name, prefix, CASE_MATCH))
762  {
763  continue;
764  }
765  if (C_Mask && C_Mask->regex &&
766  !((regexec(C_Mask->regex, de->d_name, 0, NULL, 0) == 0) ^ C_Mask->not))
767  {
768  continue;
769  }
770 
771  mutt_buffer_concat_path(buf, d, de->d_name);
772  if (lstat(mutt_b2s(buf), &s) == -1)
773  continue;
774 
775  /* No size for directories or symlinks */
776  if (S_ISDIR(s.st_mode) || S_ISLNK(s.st_mode))
777  s.st_size = 0;
778  else if (!S_ISREG(s.st_mode))
779  continue;
780 
781  struct MailboxNode *np = NULL;
782  STAILQ_FOREACH(np, &AllMailboxes, entries)
783  {
784  if (mutt_str_strcmp(mutt_b2s(buf), mutt_b2s(np->mailbox->pathbuf)) != 0)
785  break;
786  }
787 
788  if (np && Context &&
790  {
793  }
794  add_folder(menu, state, de->d_name, NULL, &s, np ? np->mailbox : NULL, NULL);
795  }
796  closedir(dp);
797  }
798  browser_sort(state);
799  rc = 0;
800 ed_out:
802  return rc;
803 }
The "current" mailbox.
Definition: context.h:38
bool not
do not match
Definition: regex3.h:61
int msg_count
total number of messages
Definition: mailbox.h:92
#define mutt_perror(...)
Definition: logging.h:84
int msg_unread
number of unread messages
Definition: mailbox.h:93
char * realpath
used for duplicate detection, context comparison, and the sidebar
Definition: mailbox.h:86
regex_t * regex
compiled expression
Definition: regex3.h:60
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:614
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
Match case when comparing strings.
Definition: string2.h:66
NNTP-specific Account data -.
Definition: nntp.h:76
struct Mailbox * mailbox
Definition: context.h:52
char * group
Definition: nntp.h:141
void * mdata
driver specific data
Definition: mailbox.h:136
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all AllMailboxes for new mail.
Definition: mailbox.c:341
#define mutt_b2s(buf)
Definition: buffer.h:42
void * adata
Definition: account.h:41
unsigned int groups_num
Definition: nntp.h:99
static void browser_sort(struct BrowserState *state)
Sort the entries in the browser.
Definition: browser.c:307
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
NNTP-specific Mailbox data -.
Definition: nntp.h:139
struct MailboxList AllMailboxes
List of all Mailboxes.
Definition: mailbox.c:86
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:85
#define mutt_error(...)
Definition: logging.h:83
WHERE struct Regex * C_Mask
Config: Only display files/dirs matching this regex in the browser.
Definition: globals.h:176
void ** groups_list
Definition: nntp.h:101
List of Mailboxes.
Definition: mailbox.h:146
static void init_state(struct BrowserState *state, struct Menu *menu)
Initialise a browser state.
Definition: browser.c:666
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: buffer.c:409
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:42
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:618
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: buffer.c:398
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:77
struct Mailbox * mailbox
Definition: mailbox.h:148
void mutt_buffer_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition: buffer.c:455

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

813 {
814  struct stat s;
815  struct Buffer *md = NULL;
816  struct Buffer *mailbox = NULL;
817 
818 #ifdef USE_NNTP
819  if (OptNews)
820  {
822 
823  init_state(state, menu);
824 
825  for (unsigned int i = 0; i < adata->groups_num; i++)
826  {
827  struct NntpMboxData *mdata = adata->groups_list[i];
828  if (mdata && (mdata->new || (mdata->subscribed && (mdata->unread || !C_ShowOnlyUnread))))
829  {
830  add_folder(menu, state, mdata->group, NULL, NULL, NULL, mdata);
831  }
832  }
833  }
834  else
835 #endif
836  {
837  init_state(state, menu);
838 
840  return -1;
841  mailbox = mutt_buffer_pool_get();
842  md = mutt_buffer_pool_get();
844 
845  struct MailboxNode *np = NULL;
846  STAILQ_FOREACH(np, &AllMailboxes, entries)
847  {
849  {
852  }
853 
854  mutt_buffer_strcpy(mailbox, mutt_b2s(np->mailbox->pathbuf));
857 
858  switch (np->mailbox->magic)
859  {
860  case MUTT_IMAP:
861  case MUTT_POP:
862  add_folder(menu, state, mutt_b2s(mailbox), np->mailbox->desc, NULL,
863  np->mailbox, NULL);
864  continue;
865  case MUTT_NOTMUCH:
866  case MUTT_NNTP:
867  add_folder(menu, state, mutt_b2s(np->mailbox->pathbuf),
868  np->mailbox->desc, NULL, np->mailbox, NULL);
869  continue;
870  default: /* Continue */
871  break;
872  }
873 
874  if (lstat(mutt_b2s(np->mailbox->pathbuf), &s) == -1)
875  continue;
876 
877  if ((!S_ISREG(s.st_mode)) && (!S_ISDIR(s.st_mode)) && (!S_ISLNK(s.st_mode)))
878  continue;
879 
880  if (np->mailbox->magic == MUTT_MAILDIR)
881  {
882  struct stat st2;
883 
884  mutt_buffer_printf(md, "%s/new", mutt_b2s(np->mailbox->pathbuf));
885  if (stat(mutt_b2s(md), &s) < 0)
886  s.st_mtime = 0;
887  mutt_buffer_printf(md, "%s/cur", mutt_b2s(np->mailbox->pathbuf));
888  if (stat(mutt_b2s(md), &st2) < 0)
889  st2.st_mtime = 0;
890  if (st2.st_mtime > s.st_mtime)
891  s.st_mtime = st2.st_mtime;
892  }
893 
894  add_folder(menu, state, mutt_b2s(mailbox), np->mailbox->desc, &s, np->mailbox, NULL);
895  }
896  }
897  browser_sort(state);
898 
899  mutt_buffer_pool_release(&mailbox);
901  return 0;
902 }
void mutt_buffer_pretty_mailbox(struct Buffer *s)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:688
The "current" mailbox.
Definition: context.h:38
&#39;Notmuch&#39; (virtual) Mailbox type
Definition: magic.h:43
int msg_count
total number of messages
Definition: mailbox.h:92
int msg_unread
number of unread messages
Definition: mailbox.h:93
&#39;NNTP&#39; (Usenet) Mailbox type
Definition: magic.h:41
&#39;Maildir&#39; Mailbox type
Definition: magic.h:40
char * desc
Definition: mailbox.h:87
char * realpath
used for duplicate detection, context comparison, and the sidebar
Definition: mailbox.h:86
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:614
String manipulation buffer.
Definition: buffer.h:33
&#39;IMAP&#39; Mailbox type
Definition: magic.h:42
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:200
NNTP-specific Account data -.
Definition: nntp.h:76
bool subscribed
Definition: nntp.h:148
struct Mailbox * mailbox
Definition: context.h:52
enum MailboxType magic
mailbox type
Definition: mailbox.h:105
char * group
Definition: nntp.h:141
void * mdata
driver specific data
Definition: mailbox.h:136
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all AllMailboxes for new mail.
Definition: mailbox.c:341
#define mutt_b2s(buf)
Definition: buffer.h:42
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:322
void * adata
Definition: account.h:41
bool new
Definition: nntp.h:149
unsigned int groups_num
Definition: nntp.h:99
static void browser_sort(struct BrowserState *state)
Sort the entries in the browser.
Definition: browser.c:307
bool C_ShowOnlyUnread
Config: (nntp) Only show subscribed newsgroups with unread articles.
Definition: browser.c:81
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
NNTP-specific Mailbox data -.
Definition: nntp.h:139
struct MailboxList AllMailboxes
List of all Mailboxes.
Definition: mailbox.c:86
struct Buffer * pathbuf
Definition: mailbox.h:85
anum_t unread
Definition: nntp.h:147
bool C_BrowserAbbreviateMailboxes
Config: Abbreviate mailboxes using &#39;~&#39; and &#39;=&#39; in the browser.
Definition: browser.c:77
void ** groups_list
Definition: nntp.h:101
#define STAILQ_EMPTY(head)
Definition: queue.h:346
List of Mailboxes.
Definition: mailbox.h:146
static void init_state(struct BrowserState *state, struct Menu *menu)
Initialise a browser state.
Definition: browser.c:666
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: buffer.c:409
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:42
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:618
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: buffer.c:398
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:77
&#39;POP3&#39; Mailbox type
Definition: magic.h:44
struct Mailbox * mailbox
Definition: mailbox.h:148

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

908 {
909 #ifdef USE_NNTP
910  if (OptNews)
911  return regexec(rx, ((struct FolderFile *) menu->data)[line].desc, 0, NULL, 0);
912 #endif
913  struct FolderFile current_ff = ((struct FolderFile *) menu->data)[line];
914  char *search_on = current_ff.desc ? current_ff.desc : current_ff.name;
915 
916  return regexec(rx, search_on, 0, NULL, 0);
917 }
char * desc
Definition: browser.h:68
char * name
Definition: browser.h:67
Browser entry representing a folder/dir.
Definition: browser.h:58
const char * line
Definition: common.c:35
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:42

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

923 {
924  struct Folder folder;
925 
926  folder.ff = &((struct FolderFile *) menu->data)[line];
927  folder.num = line;
928 
929 #ifdef USE_NNTP
930  if (OptNews)
931  {
932  mutt_expando_format(buf, buflen, 0, MuttIndexWindow->cols,
934  (unsigned long) &folder, MUTT_FORMAT_ARROWCURSOR);
935  }
936  else
937 #endif
938  {
939  mutt_expando_format(buf, buflen, 0, MuttIndexWindow->cols,
941  (unsigned long) &folder, MUTT_FORMAT_ARROWCURSOR);
942  }
943 }
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:836
#define NONULL(x)
Definition: string2.h:36
#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:78
struct FolderFile * ff
Definition: browser.h:51
A folder/dir in the browser.
Definition: browser.h:49
Browser entry representing a folder/dir.
Definition: browser.h:58
const char * line
Definition: common.c:35
struct MuttWindow * MuttIndexWindow
Index Window.
Definition: mutt_window.c:39
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:370
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:54
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:79
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:42

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

954 {
955  menu->top = 0;
956  /* Reset menu position to 1.
957  * We do not risk overflow as the init_menu function changes
958  * current if it is bigger than state->entrylen. */
959  if ((mutt_str_strcmp(state->entry[0].desc, "..") == 0) ||
960  (mutt_str_strcmp(state->entry[0].desc, "../") == 0))
961  {
962  /* Skip the first entry, unless there's only one entry. */
963  menu->current = (menu->max > 1);
964  }
965  else
966  {
967  menu->current = 0;
968  }
969 }
char * desc
Definition: browser.h:68
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:618
struct FolderFile * entry
Definition: browser.h:94

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

981 {
982  menu->max = state->entrylen;
983 
984  if (menu->current >= menu->max)
985  menu->current = menu->max - 1;
986  if (menu->current < 0)
987  menu->current = 0;
988  if (menu->top > menu->current)
989  menu->top = 0;
990 
991  menu->tagged = 0;
992 
993 #ifdef USE_NNTP
994  if (OptNews)
995  {
996  if (mailbox)
997  snprintf(title, titlelen, _("Subscribed newsgroups"));
998  else
999  {
1000  snprintf(title, titlelen, _("Newsgroups on server [%s]"),
1002  }
1003  }
1004  else
1005 #endif
1006  {
1007  if (mailbox)
1008  {
1009  menu->is_mailbox_list = true;
1010  snprintf(title, titlelen, _("Mailboxes [%d]"),
1011  mutt_mailbox_check(Context ? Context->mailbox : NULL, 0));
1012  }
1013  else
1014  {
1015  struct Buffer *path = mutt_buffer_pool_get();
1016  menu->is_mailbox_list = false;
1019 #ifdef USE_IMAP
1020  if (state->imap_browse && C_ImapListSubscribed)
1021  {
1022  snprintf(title, titlelen, _("Subscribed [%s], File mask: %s"),
1023  mutt_b2s(path), NONULL(C_Mask ? C_Mask->pattern : NULL));
1024  }
1025  else
1026 #endif
1027  {
1028  snprintf(title, titlelen, _("Directory [%s], File mask: %s"),
1029  mutt_b2s(path), NONULL(C_Mask ? C_Mask->pattern : NULL));
1030  }
1031  mutt_buffer_pool_release(&path);
1032  }
1033  }
1034 
1035  /* Browser tracking feature.
1036  * The goal is to highlight the good directory if LastDir is the parent dir
1037  * of LastDirBackup (this occurs mostly when one hit "../"). It should also work
1038  * properly when the user is in examine_mailboxes-mode. */
1040  {
1041  char target_dir[PATH_MAX] = "";
1042 
1043 #ifdef USE_IMAP
1044  /* Check what kind of dir LastDirBackup is. */
1046  {
1047  mutt_str_strfcpy(target_dir, mutt_b2s(LastDirBackup), sizeof(target_dir));
1048  imap_clean_path(target_dir, sizeof(target_dir));
1049  }
1050  else
1051 #endif
1052  mutt_str_strfcpy(target_dir, strrchr(mutt_b2s(LastDirBackup), '/') + 1,
1053  sizeof(target_dir));
1054 
1055  /* If we get here, it means that LastDir is the parent directory of
1056  * LastDirBackup. I.e., we're returning from a subdirectory, and we want
1057  * to position the cursor on the directory we're returning from. */
1058  bool matched = false;
1059  for (unsigned int i = 0; i < state->entrylen; i++)
1060  {
1061  if (mutt_str_strcmp(state->entry[i].name, target_dir) == 0)
1062  {
1063  menu->current = i;
1064  matched = true;
1065  break;
1066  }
1067  }
1068  if (!matched)
1069  browser_highlight_default(state, menu);
1070  }
1071  else
1072  browser_highlight_default(state, menu);
1073 
1074  menu->redraw = REDRAW_FULL;
1075 }
void mutt_buffer_pretty_mailbox(struct Buffer *s)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:688
The "current" mailbox.
Definition: context.h:38
WHERE bool C_ImapListSubscribed
Config: (imap) When browsing a mailbox, only display subscribed folders.
Definition: globals.h:222
#define REDRAW_FULL
Redraw everything.
Definition: mutt_menu.h:47
#define NONULL(x)
Definition: string2.h:36
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2440
struct ConnAccount account
Definition: connection.h:36
static struct Buffer * LastDir
Definition: browser.c:107
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
&#39;IMAP&#39; Mailbox type
Definition: magic.h:42
Match case when comparing strings.
Definition: string2.h:66
char host[128]
Definition: connaccount.h:36
struct Mailbox * mailbox
Definition: context.h:52
char * name
Definition: browser.h:67
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all AllMailboxes for new mail.
Definition: mailbox.c:341
#define mutt_b2s(buf)
Definition: buffer.h:42
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:322
#define PATH_MAX
Definition: mutt.h:49
int top
entry that is the top of the current page
Definition: mutt_menu.h:110
static struct Buffer * LastDirBackup
Definition: browser.c:108
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:753
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:95
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:103
static void browser_highlight_default(struct BrowserState *state, struct Menu *menu)
Decide which browser item should be highlighted.
Definition: browser.c:953
WHERE struct Regex * C_Mask
Config: Only display files/dirs matching this regex in the browser.
Definition: globals.h:176
int current
current entry
Definition: mutt_menu.h:87
char * pattern
printable version
Definition: regex3.h:59
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: buffer.c:409
bool imap_browse
Definition: browser.h:98
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:42
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:618
struct FolderFile * entry
Definition: browser.h:94
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: buffer.c:398
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:77
void imap_clean_path(char *path, size_t plen)
Cleans an IMAP path using imap_fix_path.
Definition: util.c:328

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

1081 {
1082  struct FolderFile *ff = &(((struct FolderFile *) menu->data)[sel]);
1083  if (S_ISDIR(ff->mode) || (S_ISLNK(ff->mode) && link_is_dir(mutt_b2s(LastDir), ff->name)))
1084  {
1085  mutt_error(_("Can't attach a directory"));
1086  return 0;
1087  }
1088 
1089  bool ot = ff->tagged;
1090  ff->tagged = ((act >= 0) ? act : !ff->tagged);
1091 
1092  return ff->tagged - ot;
1093 }
mode_t mode
Definition: browser.h:60
static bool link_is_dir(const char *folder, const char *path)
Does this symlink point to a directory?
Definition: browser.c:334
static struct Buffer * LastDir
Definition: browser.c:107
#define _(a)
Definition: message.h:28
char * name
Definition: browser.h:67
#define mutt_b2s(buf)
Definition: buffer.h:42
Browser entry representing a folder/dir.
Definition: browser.h:58
#define mutt_error(...)
Definition: logging.h:83
void * data
extra data for the current menu
Definition: mutt_menu.h:86
bool tagged
Definition: browser.h:83

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

1106 {
1107  if (!LastDir)
1108  {
1111  }
1112 
1114 
1115  /* Method that will fetch the parent path depending on the type of the path. */
1116  char buf[PATH_MAX];
1117  mutt_get_parent_path(mutt_b2s(LastDirBackup), buf, sizeof(buf));
1119 }
static struct Buffer * LastDir
Definition: browser.c:107
struct Buffer * mutt_buffer_alloc(size_t size)
Create a new Buffer.
Definition: buffer.c:304
#define mutt_b2s(buf)
Definition: buffer.h:42
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:322
#define PATH_MAX
Definition: mutt.h:49
static struct Buffer * LastDirBackup
Definition: browser.c:108
void mutt_get_parent_path(const char *path, char *buf, size_t buflen)
Find the parent of a path (or mailbox)
Definition: muttlib.c:1593

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

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

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

2175 {
2176  struct Buffer *f_buf = mutt_buffer_pool_get();
2177 
2178  mutt_buffer_strcpy(f_buf, NONULL(file));
2179  mutt_buffer_select_file(f_buf, flags, files, numfiles);
2180  mutt_str_strfcpy(file, mutt_b2s(f_buf), filelen);
2181 
2182  mutt_buffer_pool_release(&f_buf);
2183 }
#define NONULL(x)
Definition: string2.h:36
void mutt_buffer_select_file(struct Buffer *file, SelectFileFlags flags, char ***files, int *numfiles)
Let the user select a file.
Definition: browser.c:1128
String manipulation buffer.
Definition: buffer.h:33
#define mutt_b2s(buf)
Definition: buffer.h:42
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:322
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:753
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: buffer.c:409
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: buffer.c:398

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

char* C_FolderFormat

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

Definition at line 78 of file browser.c.

char* C_GroupIndexFormat

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

Definition at line 79 of file browser.c.

char* C_NewsgroupsCharset

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

Definition at line 80 of file browser.c.

bool C_ShowOnlyUnread

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

Definition at line 81 of file browser.c.

short C_SortBrowser

Config: Sort method for the browser.

Definition at line 82 of file browser.c.

char* C_VfolderFormat

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

Definition at line 83 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 85 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 95 of file browser.c.

struct Buffer* LastDir = NULL
static

Definition at line 107 of file browser.c.

struct Buffer* LastDirBackup = NULL
static

Definition at line 108 of file browser.c.