NeoMutt  2018-07-16 +2225-8687db
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 "core/lib.h"
#include "curs_lib.h"
#include "format_flags.h"
#include "globals.h"
#include "keymap.h"
#include "maildir/lib.h"
#include "mutt_attach.h"
#include "mutt_mailbox.h"
#include "mutt_menu.h"
#include "mutt_window.h"
#include "muttlib.h"
#include "mx.h"
#include "opcodes.h"
#include "options.h"
#include "sendlib.h"
#include "sort.h"
#include "imap/imap.h"
#include "nntp/nntp.h"
#include "pop/pop.h"

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

115 {
118 }
static struct Buffer * LastDir
Definition: browser.c:108
void mutt_buffer_free(struct Buffer **p)
Release a Buffer and its contents.
Definition: buffer.c:134
static struct Buffer * LastDirBackup
Definition: browser.c:109
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 126 of file browser.c.

127 {
128  for (size_t c = 0; c < state->entrylen; c++)
129  {
130  FREE(&((state->entry)[c].name));
131  FREE(&((state->entry)[c].desc));
132  }
133 #ifdef USE_IMAP
134  FREE(&state->folder);
135 #endif
136  FREE(&state->entry);
137 }
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
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 147 of file browser.c.

148 {
149  const struct FolderFile *pa = (const struct FolderFile *) a;
150  const struct FolderFile *pb = (const struct FolderFile *) b;
151 
152  /* inbox should be sorted ahead of its siblings */
153  int r = mutt_inbox_cmp(pa->name, pb->name);
154  if (r == 0)
155  r = mutt_str_strcoll(pa->name, pb->name);
156  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
157 }
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:83
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:1655
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort.h:86
int mutt_str_strcoll(const char *a, const char *b)
Collate two strings (compare using locale), safely.
Definition: string.c:679
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 167 of file browser.c.

168 {
169  const struct FolderFile *pa = (const struct FolderFile *) a;
170  const struct FolderFile *pb = (const struct FolderFile *) b;
171 
172  int r = mutt_str_strcoll(pa->desc, pb->desc);
173 
174  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
175 }
char * desc
Definition: browser.h:68
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:83
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:679
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 185 of file browser.c.

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

204 {
205  const struct FolderFile *pa = (const struct FolderFile *) a;
206  const struct FolderFile *pb = (const struct FolderFile *) b;
207 
208  int r = pa->size - pb->size;
209 
210  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
211 }
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:83
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
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 221 of file browser.c.

222 {
223  const struct FolderFile *pa = (const struct FolderFile *) a;
224  const struct FolderFile *pb = (const struct FolderFile *) b;
225 
226  int r = 0;
227  if (pa->has_mailbox && pb->has_mailbox)
228  r = pa->msg_count - pb->msg_count;
229  else if (pa->has_mailbox)
230  r = -1;
231  else
232  r = 1;
233 
234  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
235 }
bool has_mailbox
Definition: browser.h:81
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:83
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
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 245 of file browser.c.

246 {
247  const struct FolderFile *pa = (const struct FolderFile *) a;
248  const struct FolderFile *pb = (const struct FolderFile *) b;
249 
250  int r = 0;
251  if (pa->has_mailbox && pb->has_mailbox)
252  r = pa->msg_unread - pb->msg_unread;
253  else if (pa->has_mailbox)
254  r = -1;
255  else
256  r = 1;
257 
258  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
259 }
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:83
Browser entry representing a folder/dir.
Definition: browser.h:58
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort.h:86
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 273 of file browser.c.

274 {
275  const struct FolderFile *pa = (const struct FolderFile *) a;
276  const struct FolderFile *pb = (const struct FolderFile *) b;
277 
278  if ((mutt_str_strcoll(pa->desc, "../") == 0) || (mutt_str_strcoll(pa->desc, "..") == 0))
279  return -1;
280  if ((mutt_str_strcoll(pb->desc, "../") == 0) || (mutt_str_strcoll(pb->desc, "..") == 0))
281  return 1;
282 
283  switch (C_SortBrowser & SORT_MASK)
284  {
285  case SORT_COUNT:
286  return browser_compare_count(a, b);
287  case SORT_DATE:
288  return browser_compare_date(a, b);
289  case SORT_DESC:
290  return browser_compare_desc(a, b);
291  case SORT_SIZE:
292  return browser_compare_size(a, b);
293  case SORT_UNREAD:
294  return browser_compare_count_new(a, b);
295  case SORT_SUBJECT:
296  default:
297  return browser_compare_subject(a, b);
298  }
299 }
static int browser_compare_date(const void *a, const void *b)
Compare the date of two browser entries.
Definition: browser.c:185
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:167
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:83
static int browser_compare_count(const void *a, const void *b)
Compare the message count of two browser entries.
Definition: browser.c:221
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:245
static int browser_compare_size(const void *a, const void *b)
Compare the size of two browser entries.
Definition: browser.c:203
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:147
Sort by the size of the email.
Definition: sort.h:51
Sort by number of emails in a folder.
Definition: sort.h:65
int mutt_str_strcoll(const char *a, const char *b)
Collate two strings (compare using locale), safely.
Definition: string.c:679
#define SORT_MASK
Mask for the sort id.
Definition: sort.h:85
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 308 of file browser.c.

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

336 {
337  struct stat st;
338  bool retval = false;
339 
340  struct Buffer *fullpath = mutt_buffer_pool_get();
341  mutt_buffer_concat_path(fullpath, folder, path);
342 
343  if (stat(mutt_b2s(fullpath), &st) == 0)
344  retval = S_ISDIR(st.st_mode);
345 
346  mutt_buffer_pool_release(&fullpath);
347 
348  return retval;
349 }
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:75
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:86
String manipulation buffer.
Definition: buffer.h:33
#define mutt_b2s(buf)
Definition: buffer.h:42
void mutt_buffer_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition: buffer.c:381
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 371 of file browser.c.

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

622 {
623  if (state->entrylen == state->entrymax)
624  {
625  /* need to allocate more space */
626  mutt_mem_realloc(&state->entry, sizeof(struct FolderFile) * (state->entrymax += 256));
627  memset(&state->entry[state->entrylen], 0, sizeof(struct FolderFile) * 256);
628  if (menu)
629  menu->data = state->entry;
630  }
631 
632  if (s)
633  {
634  (state->entry)[state->entrylen].mode = s->st_mode;
635  (state->entry)[state->entrylen].mtime = s->st_mtime;
636  (state->entry)[state->entrylen].size = s->st_size;
637  (state->entry)[state->entrylen].gid = s->st_gid;
638  (state->entry)[state->entrylen].uid = s->st_uid;
639  (state->entry)[state->entrylen].nlink = s->st_nlink;
640 
641  (state->entry)[state->entrylen].local = true;
642  }
643  else
644  (state->entry)[state->entrylen].local = false;
645 
646  if (m)
647  {
648  (state->entry)[state->entrylen].has_mailbox = true;
649  (state->entry)[state->entrylen].has_new_mail = m->has_new;
650  (state->entry)[state->entrylen].msg_count = m->msg_count;
651  (state->entry)[state->entrylen].msg_unread = m->msg_unread;
652  }
653 
654  (state->entry)[state->entrylen].name = mutt_str_strdup(name);
655  (state->entry)[state->entrylen].desc = mutt_str_strdup(desc ? desc : name);
656 #ifdef USE_IMAP
657  (state->entry)[state->entrylen].imap = false;
658 #endif
659 #ifdef USE_NNTP
660  if (OptNews)
661  (state->entry)[state->entrylen].nd = data;
662 #endif
663  (state->entrylen)++;
664 }
mode_t mode
Definition: browser.h:60
int msg_count
Total number of messages.
Definition: mailbox.h:103
int msg_unread
Number of unread messages.
Definition: mailbox.h:104
bool has_new
Mailbox has new mail.
Definition: mailbox.h:100
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:114
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
static void init_state ( struct BrowserState state,
struct Menu menu 
)
static

Initialise a browser state.

Parameters
stateBrowserState to initialise
menuCurrent menu

Definition at line 671 of file browser.c.

672 {
673  state->entrylen = 0;
674  state->entrymax = 256;
675  state->entry = mutt_mem_calloc(state->entrymax, sizeof(struct FolderFile));
676 #ifdef USE_IMAP
677  state->imap_browse = false;
678 #endif
679  if (menu)
680  menu->data = state->entry;
681 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
unsigned int entrymax
max entry
Definition: browser.h: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
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 692 of file browser.c.

694 {
695  int rc = -1;
696  struct Buffer *buf = mutt_buffer_pool_get();
697 #ifdef USE_NNTP
698  if (OptNews)
699  {
701 
702  init_state(state, menu);
703 
704  for (unsigned int i = 0; i < adata->groups_num; i++)
705  {
706  struct NntpMboxData *mdata = adata->groups_list[i];
707  if (!mdata)
708  continue;
709  if (prefix && *prefix && !mutt_str_startswith(mdata->group, prefix, CASE_MATCH))
710  continue;
711  if (C_Mask && C_Mask->regex &&
712  !((regexec(C_Mask->regex, mdata->group, 0, NULL, 0) == 0) ^ C_Mask->pat_not))
713  {
714  continue;
715  }
716  add_folder(menu, state, mdata->group, NULL, NULL, NULL, mdata);
717  }
718  }
719  else
720 #endif /* USE_NNTP */
721  {
722  struct stat s;
723  DIR *dp = NULL;
724  struct dirent *de = NULL;
725 
726  while (stat(d, &s) == -1)
727  {
728  if (errno == ENOENT)
729  {
730  /* The last used directory is deleted, try to use the parent dir. */
731  char *c = strrchr(d, '/');
732 
733  if (c && (c > d))
734  {
735  *c = '\0';
736  continue;
737  }
738  }
739  mutt_perror(d);
740  goto ed_out;
741  }
742 
743  if (!S_ISDIR(s.st_mode))
744  {
745  mutt_error(_("%s is not a directory"), d);
746  goto ed_out;
747  }
748 
749  if (Context && Context->mailbox)
751 
752  dp = opendir(d);
753  if (!dp)
754  {
755  mutt_perror(d);
756  goto ed_out;
757  }
758 
759  init_state(state, menu);
760 
761  while ((de = readdir(dp)))
762  {
763  if (mutt_str_strcmp(de->d_name, ".") == 0)
764  continue; /* we don't need . */
765 
766  if (prefix && *prefix && !mutt_str_startswith(de->d_name, prefix, CASE_MATCH))
767  {
768  continue;
769  }
770  if (C_Mask && C_Mask->regex &&
771  !((regexec(C_Mask->regex, de->d_name, 0, NULL, 0) == 0) ^ C_Mask->pat_not))
772  {
773  continue;
774  }
775 
776  mutt_buffer_concat_path(buf, d, de->d_name);
777  if (lstat(mutt_b2s(buf), &s) == -1)
778  continue;
779 
780  /* No size for directories or symlinks */
781  if (S_ISDIR(s.st_mode) || S_ISLNK(s.st_mode))
782  s.st_size = 0;
783  else if (!S_ISREG(s.st_mode))
784  continue;
785 
786  struct MailboxList ml = neomutt_mailboxlist_get_all(NeoMutt, MUTT_MAILBOX_ANY);
787  struct MailboxNode *np = NULL;
788  STAILQ_FOREACH(np, &ml, entries)
789  {
790  if (mutt_str_strcmp(mutt_b2s(buf), mutt_b2s(np->mailbox->pathbuf)) != 0)
791  break;
792  }
794 
795  if (np && Context && Context->mailbox &&
797  {
800  }
801  add_folder(menu, state, de->d_name, NULL, &s, np ? np->mailbox : NULL, NULL);
802  }
803  closedir(dp);
804  }
805  browser_sort(state);
806  rc = 0;
807 ed_out:
809  return rc;
810 }
The "current" mailbox.
Definition: context.h:39
int msg_count
Total number of messages.
Definition: mailbox.h:103
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:75
#define mutt_perror(...)
Definition: logging.h:85
int msg_unread
Number of unread messages.
Definition: mailbox.h:104
void neomutt_mailboxlist_clear(struct MailboxList *ml)
Free a Mailbox List.
Definition: neomutt.c:134
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:96
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:86
regex_t * regex
compiled expression
Definition: regex3.h:60
Match any Mailbox type.
Definition: mailbox.h:45
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:619
String manipulation buffer.
Definition: buffer.h:33
bool pat_not
do not match
Definition: regex3.h:61
#define _(a)
Definition: message.h:28
Match case when comparing strings.
Definition: string2.h:67
Container for Accounts, Notifications.
Definition: neomutt.h:35
NNTP-specific Account data -.
Definition: nntp.h:76
struct Mailbox * mailbox
Definition: context.h:53
struct MailboxList neomutt_mailboxlist_get_all(struct NeoMutt *n, enum MailboxType magic)
Get a List of all Mailboxes.
Definition: neomutt.c:156
char * group
Definition: nntp.h:141
void * mdata
Driver specific data.
Definition: mailbox.h:148
#define mutt_b2s(buf)
Definition: buffer.h:42
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all all Mailboxes for new mail.
Definition: mutt_mailbox.c:126
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
unsigned int groups_num
Definition: nntp.h:99
static void browser_sort(struct BrowserState *state)
Sort the entries in the browser.
Definition: browser.c:308
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
NNTP-specific Mailbox data -.
Definition: nntp.h:139
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:95
#define mutt_error(...)
Definition: logging.h:84
WHERE struct Regex * C_Mask
Config: Only display files/dirs matching this regex in the browser.
Definition: globals.h:176
void ** groups_list
Definition: nntp.h:101
List of Mailboxes.
Definition: mailbox.h:157
static void init_state(struct BrowserState *state, struct Menu *menu)
Initialise a browser state.
Definition: browser.c:671
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:615
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:76
struct Mailbox * mailbox
Mailbox in the list.
Definition: mailbox.h:159
void mutt_buffer_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition: buffer.c:381
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 819 of file browser.c.

820 {
821  struct stat s;
822  struct Buffer *md = NULL;
823  struct Buffer *mailbox = NULL;
824 
825 #ifdef USE_NNTP
826  if (OptNews)
827  {
829 
830  init_state(state, menu);
831 
832  for (unsigned int i = 0; i < adata->groups_num; i++)
833  {
834  struct NntpMboxData *mdata = adata->groups_list[i];
835  if (mdata && (mdata->has_new_mail ||
836  (mdata->subscribed && (mdata->unread || !C_ShowOnlyUnread))))
837  {
838  add_folder(menu, state, mdata->group, NULL, NULL, NULL, mdata);
839  }
840  }
841  }
842  else
843 #endif
844  {
845  init_state(state, menu);
846 
848  return -1;
849  mailbox = mutt_buffer_pool_get();
850  md = mutt_buffer_pool_get();
852 
853  struct MailboxList ml = neomutt_mailboxlist_get_all(NeoMutt, MUTT_MAILBOX_ANY);
854  struct MailboxNode *np = NULL;
855  STAILQ_FOREACH(np, &ml, entries)
856  {
858  {
861  }
862 
863  mutt_buffer_strcpy(mailbox, mutt_b2s(np->mailbox->pathbuf));
866 
867  switch (np->mailbox->magic)
868  {
869  case MUTT_IMAP:
870  case MUTT_POP:
871  add_folder(menu, state, mutt_b2s(mailbox), np->mailbox->name, NULL,
872  np->mailbox, NULL);
873  continue;
874  case MUTT_NOTMUCH:
875  case MUTT_NNTP:
876  add_folder(menu, state, mutt_b2s(np->mailbox->pathbuf),
877  np->mailbox->name, NULL, np->mailbox, NULL);
878  continue;
879  default: /* Continue */
880  break;
881  }
882 
883  if (lstat(mutt_b2s(np->mailbox->pathbuf), &s) == -1)
884  continue;
885 
886  if ((!S_ISREG(s.st_mode)) && (!S_ISDIR(s.st_mode)) && (!S_ISLNK(s.st_mode)))
887  continue;
888 
889  if (np->mailbox->magic == MUTT_MAILDIR)
890  {
891  struct stat st2;
892 
893  mutt_buffer_printf(md, "%s/new", mutt_b2s(np->mailbox->pathbuf));
894  if (stat(mutt_b2s(md), &s) < 0)
895  s.st_mtime = 0;
896  mutt_buffer_printf(md, "%s/cur", mutt_b2s(np->mailbox->pathbuf));
897  if (stat(mutt_b2s(md), &st2) < 0)
898  st2.st_mtime = 0;
899  if (st2.st_mtime > s.st_mtime)
900  s.st_mtime = st2.st_mtime;
901  }
902 
903  add_folder(menu, state, mutt_b2s(mailbox), np->mailbox->name, &s, np->mailbox, NULL);
904  }
906  }
907  browser_sort(state);
908 
909  mutt_buffer_pool_release(&mailbox);
911  return 0;
912 }
bool has_new_mail
Definition: nntp.h:149
The "current" mailbox.
Definition: context.h:39
int msg_count
Total number of messages.
Definition: mailbox.h:103
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:75
int msg_unread
Number of unread messages.
Definition: mailbox.h:104
&#39;NNTP&#39; (Usenet) Mailbox type
Definition: mailbox.h:52
struct AccountList accounts
List of all Accounts.
Definition: neomutt.h:39
void neomutt_mailboxlist_clear(struct MailboxList *ml)
Free a Mailbox List.
Definition: neomutt.c:134
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:96
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:86
Match any Mailbox type.
Definition: mailbox.h:45
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:619
String manipulation buffer.
Definition: buffer.h:33
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:191
Container for Accounts, Notifications.
Definition: neomutt.h:35
void mutt_buffer_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:691
NNTP-specific Account data -.
Definition: nntp.h:76
bool subscribed
Definition: nntp.h:148
char * name
A short name for the Mailbox.
Definition: mailbox.h:97
struct Mailbox * mailbox
Definition: context.h:53
enum MailboxType magic
Mailbox type.
Definition: mailbox.h:117
struct MailboxList neomutt_mailboxlist_get_all(struct NeoMutt *n, enum MailboxType magic)
Get a List of all Mailboxes.
Definition: neomutt.c:156
char * group
Definition: nntp.h:141
void * mdata
Driver specific data.
Definition: mailbox.h:148
&#39;Maildir&#39; Mailbox type
Definition: mailbox.h:51
#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:314
&#39;POP3&#39; Mailbox type
Definition: mailbox.h:55
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all all Mailboxes for new mail.
Definition: mutt_mailbox.c:126
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
unsigned int groups_num
Definition: nntp.h:99
static void browser_sort(struct BrowserState *state)
Sort the entries in the browser.
Definition: browser.c:308
bool C_ShowOnlyUnread
Config: (nntp) Only show subscribed newsgroups with unread articles.
Definition: browser.c:82
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
NNTP-specific Mailbox data -.
Definition: nntp.h:139
&#39;Notmuch&#39; (virtual) Mailbox type
Definition: mailbox.h:54
struct Buffer * pathbuf
Definition: mailbox.h:95
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:78
void ** groups_list
Definition: nntp.h:101
List of Mailboxes.
Definition: mailbox.h:157
#define TAILQ_EMPTY(head)
Definition: queue.h:715
static void init_state(struct BrowserState *state, struct Menu *menu)
Initialise a browser state.
Definition: browser.c:671
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
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:615
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:76
struct Mailbox * mailbox
Mailbox in the list.
Definition: mailbox.h:159
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 917 of file browser.c.

918 {
919 #ifdef USE_NNTP
920  if (OptNews)
921  return regexec(rx, ((struct FolderFile *) menu->data)[line].desc, 0, NULL, 0);
922 #endif
923  struct FolderFile current_ff = ((struct FolderFile *) menu->data)[line];
924  char *search_on = current_ff.desc ? current_ff.desc : current_ff.name;
925 
926  return regexec(rx, search_on, 0, NULL, 0);
927 }
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:36
void * data
extra data for the current menu
Definition: mutt_menu.h:86
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:42
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 932 of file browser.c.

933 {
934  struct Folder folder;
935 
936  folder.ff = &((struct FolderFile *) menu->data)[line];
937  folder.num = line;
938 
939 #ifdef USE_NNTP
940  if (OptNews)
941  {
942  mutt_expando_format(buf, buflen, 0, MuttIndexWindow->cols,
944  (unsigned long) &folder, MUTT_FORMAT_ARROWCURSOR);
945  }
946  else
947 #endif
948  {
949  mutt_expando_format(buf, buflen, 0, MuttIndexWindow->cols,
951  (unsigned long) &folder, MUTT_FORMAT_ARROWCURSOR);
952  }
953 }
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:841
#define NONULL(x)
Definition: string2.h:37
#define MUTT_FORMAT_ARROWCURSOR
Reserve space for arrow_cursor.
Definition: format_flags.h:35
char * C_FolderFormat
Config: printf-like format string for the browser&#39;s display of folders.
Definition: browser.c:79
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:36
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:371
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:80
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:42
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 963 of file browser.c.

964 {
965  menu->top = 0;
966  /* Reset menu position to 1.
967  * We do not risk overflow as the init_menu function changes
968  * current if it is bigger than state->entrylen. */
969  if ((mutt_str_strcmp(state->entry[0].desc, "..") == 0) ||
970  (mutt_str_strcmp(state->entry[0].desc, "../") == 0))
971  {
972  /* Skip the first entry, unless there's only one entry. */
973  menu->current = (menu->max > 1);
974  }
975  else
976  {
977  menu->current = 0;
978  }
979 }
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:615
struct FolderFile * entry
Definition: browser.h:94
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 989 of file browser.c.

991 {
992  menu->max = state->entrylen;
993 
994  if (menu->current >= menu->max)
995  menu->current = menu->max - 1;
996  if (menu->current < 0)
997  menu->current = 0;
998  if (menu->top > menu->current)
999  menu->top = 0;
1000 
1001  menu->tagged = 0;
1002 
1003 #ifdef USE_NNTP
1004  if (OptNews)
1005  {
1006  if (mailbox)
1007  snprintf(title, titlelen, _("Subscribed newsgroups"));
1008  else
1009  {
1010  snprintf(title, titlelen, _("Newsgroups on server [%s]"),
1012  }
1013  }
1014  else
1015 #endif
1016  {
1017  if (mailbox)
1018  {
1019  menu->is_mailbox_list = true;
1020  snprintf(title, titlelen, _("Mailboxes [%d]"),
1021  mutt_mailbox_check(Context ? Context->mailbox : NULL, 0));
1022  }
1023  else
1024  {
1025  struct Buffer *path = mutt_buffer_pool_get();
1026  menu->is_mailbox_list = false;
1029 #ifdef USE_IMAP
1030  if (state->imap_browse && C_ImapListSubscribed)
1031  {
1032  snprintf(title, titlelen, _("Subscribed [%s], File mask: %s"),
1033  mutt_b2s(path), NONULL(C_Mask ? C_Mask->pattern : NULL));
1034  }
1035  else
1036 #endif
1037  {
1038  snprintf(title, titlelen, _("Directory [%s], File mask: %s"),
1039  mutt_b2s(path), NONULL(C_Mask ? C_Mask->pattern : NULL));
1040  }
1041  mutt_buffer_pool_release(&path);
1042  }
1043  }
1044 
1045  /* Browser tracking feature.
1046  * The goal is to highlight the good directory if LastDir is the parent dir
1047  * of LastDirBackup (this occurs mostly when one hit "../"). It should also work
1048  * properly when the user is in examine_mailboxes-mode. */
1050  {
1051  char target_dir[PATH_MAX] = { 0 };
1052 
1053 #ifdef USE_IMAP
1054  /* Check what kind of dir LastDirBackup is. */
1056  {
1057  mutt_str_strfcpy(target_dir, mutt_b2s(LastDirBackup), sizeof(target_dir));
1058  imap_clean_path(target_dir, sizeof(target_dir));
1059  }
1060  else
1061 #endif
1062  mutt_str_strfcpy(target_dir, strrchr(mutt_b2s(LastDirBackup), '/') + 1,
1063  sizeof(target_dir));
1064 
1065  /* If we get here, it means that LastDir is the parent directory of
1066  * LastDirBackup. I.e., we're returning from a subdirectory, and we want
1067  * to position the cursor on the directory we're returning from. */
1068  bool matched = false;
1069  for (unsigned int i = 0; i < state->entrylen; i++)
1070  {
1071  if (mutt_str_strcmp(state->entry[i].name, target_dir) == 0)
1072  {
1073  menu->current = i;
1074  matched = true;
1075  break;
1076  }
1077  }
1078  if (!matched)
1079  browser_highlight_default(state, menu);
1080  }
1081  else
1082  browser_highlight_default(state, menu);
1083 
1084  menu->redraw = REDRAW_FULL;
1085 }
The "current" mailbox.
Definition: context.h:39
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:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:75
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2432
struct ConnAccount account
Definition: connection.h:36
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:86
static struct Buffer * LastDir
Definition: browser.c:108
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
Match case when comparing strings.
Definition: string2.h:67
void mutt_buffer_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:691
char host[128]
Definition: connaccount.h:36
struct Mailbox * mailbox
Definition: context.h:53
char * name
Definition: browser.h:67
#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:314
#define PATH_MAX
Definition: mutt.h:50
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all all Mailboxes for new mail.
Definition: mutt_mailbox.c:126
int top
entry that is the top of the current page
Definition: mutt_menu.h:110
static struct Buffer * LastDirBackup
Definition: browser.c:109
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:750
bool is_mailbox_list
Definition: mutt_menu.h:94
int tagged
number of tagged entries
Definition: mutt_menu.h:113
int max
the number of entries in the menu
Definition: mutt_menu.h:88
size_t entrylen
number of real entries
Definition: browser.h: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:963
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
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
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:615
struct FolderFile * entry
Definition: browser.h:94
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:76
void imap_clean_path(char *path, size_t plen)
Cleans an IMAP path using imap_fix_path.
Definition: util.c:327
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 1090 of file browser.c.

1091 {
1092  struct FolderFile *ff = &(((struct FolderFile *) menu->data)[sel]);
1093  if (S_ISDIR(ff->mode) || (S_ISLNK(ff->mode) && link_is_dir(mutt_b2s(LastDir), ff->name)))
1094  {
1095  mutt_error(_("Can't attach a directory"));
1096  return 0;
1097  }
1098 
1099  bool ot = ff->tagged;
1100  ff->tagged = ((act >= 0) ? act : !ff->tagged);
1101 
1102  return ff->tagged - ot;
1103 }
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:335
static struct Buffer * LastDir
Definition: browser.c:108
#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:84
void * data
extra data for the current menu
Definition: mutt_menu.h:86
bool tagged
Definition: browser.h:83
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 1115 of file browser.c.

1116 {
1117  if (!LastDir)
1118  {
1121  }
1122 
1124 
1125  /* Method that will fetch the parent path depending on the type of the path. */
1126  char buf[PATH_MAX];
1127  mutt_get_parent_path(mutt_b2s(LastDirBackup), buf, sizeof(buf));
1129 }
static struct Buffer * LastDir
Definition: browser.c:108
struct Buffer * mutt_buffer_alloc(size_t size)
Create a new Buffer.
Definition: buffer.c:296
#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:314
#define PATH_MAX
Definition: mutt.h:50
static struct Buffer * LastDirBackup
Definition: browser.c:109
void mutt_get_parent_path(const char *path, char *buf, size_t buflen)
Find the parent of a path (or mailbox)
Definition: muttlib.c:1600
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 1138 of file browser.c.

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

2184 {
2185  struct Buffer *f_buf = mutt_buffer_pool_get();
2186 
2187  mutt_buffer_strcpy(f_buf, NONULL(file));
2188  mutt_buffer_select_file(f_buf, flags, files, numfiles);
2189  mutt_str_strfcpy(file, mutt_b2s(f_buf), filelen);
2190 
2191  mutt_buffer_pool_release(&f_buf);
2192 }
#define NONULL(x)
Definition: string2.h:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:75
void mutt_buffer_select_file(struct Buffer *file, SelectFileFlags flags, char ***files, int *numfiles)
Let the user select a file.
Definition: browser.c:1138
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:86
String manipulation buffer.
Definition: buffer.h:33
#define mutt_b2s(buf)
Definition: buffer.h:42
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:314
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:750

Variable Documentation

bool C_BrowserAbbreviateMailboxes

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

Definition at line 78 of file browser.c.

char* C_FolderFormat

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

Definition at line 79 of file browser.c.

char* C_GroupIndexFormat

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

Definition at line 80 of file browser.c.

char* C_NewsgroupsCharset

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

Definition at line 81 of file browser.c.

bool C_ShowOnlyUnread

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

Definition at line 82 of file browser.c.

short C_SortBrowser

Config: Sort method for the browser.

Definition at line 83 of file browser.c.

char* C_VfolderFormat

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

Definition at line 84 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 86 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 96 of file browser.c.

struct Buffer* LastDir = NULL
static

Definition at line 108 of file browser.c.

struct Buffer* LastDirBackup = NULL
static

Definition at line 109 of file browser.c.