NeoMutt  2018-07-16 +1360-3df4a2
Teaching an old dog new tricks
DOXYGEN
browser.c File Reference

GUI component for displaying/selecting items from a list. More...

#include "config.h"
#include <dirent.h>
#include <errno.h>
#include <grp.h>
#include <limits.h>
#include <locale.h>
#include <pwd.h>
#include <regex.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include "mutt/mutt.h"
#include "config/lib.h"
#include "email/lib.h"
#include "conn/conn.h"
#include "mutt.h"
#include "browser.h"
#include "context.h"
#include "curs_lib.h"
#include "format_flags.h"
#include "globals.h"
#include "keymap.h"
#include "mailbox.h"
#include "maildir/lib.h"
#include "mutt_attach.h"
#include "mutt_menu.h"
#include "mutt_window.h"
#include "muttlib.h"
#include "mx.h"
#include "opcodes.h"
#include "options.h"
#include "sendlib.h"
#include "sort.h"
#include "imap/imap.h"
#include "nntp/nntp.h"
#include "pop/pop.h"
+ Include dependency graph for browser.c:

Go to the source code of this file.

Functions

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, 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_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 char OldLastDir [PATH_MAX] = ""
 
static char LastDir [PATH_MAX] = ""
 

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

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

117 {
118  for (size_t c = 0; c < state->entrylen; c++)
119  {
120  FREE(&((state->entry)[c].name));
121  FREE(&((state->entry)[c].desc));
122  }
123 #ifdef USE_IMAP
124  FREE(&state->folder);
125 #endif
126  FREE(&state->entry);
127 }
char * folder
Definition: browser.h:99
size_t entrylen
number of real entries
Definition: browser.h:95
#define FREE(x)
Definition: memory.h:40
struct FolderFile * entry
Definition: browser.h:94

+ Here is the caller graph for this function:

static int browser_compare_subject ( const void *  a,
const void *  b 
)
static

Compare the subject of two browser entries.

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

Definition at line 137 of file browser.c.

138 {
139  struct FolderFile *pa = (struct FolderFile *) a;
140  struct FolderFile *pb = (struct FolderFile *) b;
141 
142  /* inbox should be sorted ahead of its siblings */
143  int r = mutt_inbox_cmp(pa->name, pb->name);
144  if (r == 0)
145  r = mutt_str_strcoll(pa->name, pb->name);
146  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
147 }
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:82
char * name
Definition: browser.h:67
Browser entry representing a folder/dir.
Definition: browser.h:58
int mutt_inbox_cmp(const char *a, const char *b)
do two folders share the same path and one is an inbox
Definition: muttlib.c:1621
#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:675

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int browser_compare_desc ( const void *  a,
const void *  b 
)
static

Compare the descriptions of two browser entries.

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

Definition at line 157 of file browser.c.

158 {
159  struct FolderFile *pa = (struct FolderFile *) a;
160  struct FolderFile *pb = (struct FolderFile *) b;
161 
162  int r = mutt_str_strcoll(pa->desc, pb->desc);
163 
164  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
165 }
char * desc
Definition: browser.h:68
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:82
Browser entry representing a folder/dir.
Definition: browser.h:58
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort.h:86
int mutt_str_strcoll(const char *a, const char *b)
Collate two strings (compare using locale), safely.
Definition: string.c:675

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int browser_compare_date ( const void *  a,
const void *  b 
)
static

Compare the date of two browser entries.

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

Definition at line 175 of file browser.c.

176 {
177  struct FolderFile *pa = (struct FolderFile *) a;
178  struct FolderFile *pb = (struct FolderFile *) b;
179 
180  int r = pa->mtime - pb->mtime;
181 
182  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
183 }
time_t mtime
Definition: browser.h:62
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:82
Browser entry representing a folder/dir.
Definition: browser.h:58
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort.h:86

+ Here is the caller graph for this function:

static int browser_compare_size ( const void *  a,
const void *  b 
)
static

Compare the size of two browser entries.

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

Definition at line 193 of file browser.c.

194 {
195  struct FolderFile *pa = (struct FolderFile *) a;
196  struct FolderFile *pb = (struct FolderFile *) b;
197 
198  int r = pa->size - pb->size;
199 
200  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
201 }
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:82
off_t size
Definition: browser.h:61
Browser entry representing a folder/dir.
Definition: browser.h:58
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort.h:86

+ Here is the caller graph for this function:

static int browser_compare_count ( const void *  a,
const void *  b 
)
static

Compare the message count of two browser entries.

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

Definition at line 211 of file browser.c.

212 {
213  struct FolderFile *pa = (struct FolderFile *) a;
214  struct FolderFile *pb = (struct FolderFile *) b;
215 
216  int r = 0;
217  if (pa->has_mailbox && pb->has_mailbox)
218  r = pa->msg_count - pb->msg_count;
219  else if (pa->has_mailbox)
220  r = -1;
221  else
222  r = 1;
223 
224  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
225 }
bool has_mailbox
Definition: browser.h:81
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:82
Browser entry representing a folder/dir.
Definition: browser.h:58
int msg_count
total number of messages
Definition: browser.h:71
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort.h:86

+ Here is the caller graph for this function:

static int browser_compare_count_new ( const void *  a,
const void *  b 
)
static

Compare the new count of two browser entries.

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

Definition at line 235 of file browser.c.

236 {
237  struct FolderFile *pa = (struct FolderFile *) a;
238  struct FolderFile *pb = (struct FolderFile *) b;
239 
240  int r = 0;
241  if (pa->has_mailbox && pb->has_mailbox)
242  r = pa->msg_unread - pb->msg_unread;
243  else if (pa->has_mailbox)
244  r = -1;
245  else
246  r = 1;
247 
248  return (C_SortBrowser & SORT_REVERSE) ? -r : r;
249 }
int msg_unread
number of unread messages
Definition: browser.h:72
bool has_mailbox
Definition: browser.h:81
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:82
Browser entry representing a folder/dir.
Definition: browser.h:58
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort.h:86

+ Here is the caller graph for this function:

static int browser_compare ( const void *  a,
const void *  b 
)
static

Sort the items in the browser.

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

Wild compare function that calls the others. It's useful because it provides a way to tell "../" is always on the top of the list, independently of the sort method.

Definition at line 263 of file browser.c.

264 {
265  struct FolderFile *pa = (struct FolderFile *) a;
266  struct FolderFile *pb = (struct FolderFile *) b;
267 
268  if ((mutt_str_strcoll(pa->desc, "../") == 0) || (mutt_str_strcoll(pa->desc, "..") == 0))
269  return -1;
270  if ((mutt_str_strcoll(pb->desc, "../") == 0) || (mutt_str_strcoll(pb->desc, "..") == 0))
271  return 1;
272 
273  switch (C_SortBrowser & SORT_MASK)
274  {
275  case SORT_COUNT:
276  return browser_compare_count(a, b);
277  case SORT_DATE:
278  return browser_compare_date(a, b);
279  case SORT_DESC:
280  return browser_compare_desc(a, b);
281  case SORT_SIZE:
282  return browser_compare_size(a, b);
283  case SORT_UNREAD:
284  return browser_compare_count_new(a, b);
285  case SORT_SUBJECT:
286  default:
287  return browser_compare_subject(a, b);
288  }
289 }
static int browser_compare_date(const void *a, const void *b)
Compare the date of two browser entries.
Definition: browser.c:175
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:157
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:82
static int browser_compare_count(const void *a, const void *b)
Compare the message count of two browser entries.
Definition: browser.c:211
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:235
static int browser_compare_size(const void *a, const void *b)
Compare the size of two browser entries.
Definition: browser.c:193
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:137
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:675
#define SORT_MASK
Mask for the sort id.
Definition: sort.h:85

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void browser_sort ( struct BrowserState state)
static

Sort the entries in the browser.

Parameters
stateBrowser state

Call to qsort using browser_compare function. Some specific sort methods are not used via NNTP.

Definition at line 298 of file browser.c.

299 {
300  switch (C_SortBrowser & SORT_MASK)
301  {
302  /* Also called "I don't care"-sort-method. */
303  case SORT_ORDER:
304  return;
305 #ifdef USE_NNTP
306  case SORT_SIZE:
307  case SORT_DATE:
308  if (OptNews)
309  return;
310 #endif
311  default:
312  break;
313  }
314 
315  qsort(state->entry, state->entrylen, sizeof(struct FolderFile), browser_compare);
316 }
Sort by the date the email was sent.
Definition: sort.h:50
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:82
Browser entry representing a folder/dir.
Definition: browser.h:58
size_t entrylen
number of real entries
Definition: browser.h:95
Sort by the size of the email.
Definition: sort.h:51
static int browser_compare(const void *a, const void *b)
Sort the items in the browser.
Definition: browser.c:263
Sort by the order the messages appear in the mailbox.
Definition: sort.h:55
#define SORT_MASK
Mask for the sort id.
Definition: sort.h:85
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:42
struct FolderFile * entry
Definition: browser.h:94

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static bool link_is_dir ( const char *  folder,
const char *  path 
)
static

Does this symlink point to a directory?

Parameters
folderFolder
pathLink name
Return values
trueLinks to a directory
falseOtherwise

Definition at line 325 of file browser.c.

326 {
327  struct stat st;
328  char fullpath[PATH_MAX];
329 
330  mutt_path_concat(fullpath, folder, path, sizeof(fullpath));
331 
332  if (stat(fullpath, &st) == 0)
333  return S_ISDIR(st.st_mode);
334 
335  return false;
336 }
#define PATH_MAX
Definition: mutt.h:48
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:324

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static const char* folder_format_str ( char *  buf,
size_t  buflen,
size_t  col,
int  cols,
char  op,
const char *  src,
const char *  prec,
const char *  if_str,
const char *  else_str,
unsigned long  data,
MuttFormatFlags  flags 
)
static

Format a string for the folder browser - Implements format_t.

Expando Description
%C Current file number
%d Date/time folder was last modified
%D Date/time folder was last modified using $$date_format.
%F File permissions
%f Filename (with suffix '/', '@' or '*')
%g Group name (or numeric gid, if missing)
%i Description of the folder
%l Number of hard links
%m Number of messages in the mailbox *
%N N if mailbox has new mail, blank otherwise
%n Number of unread messages in the mailbox *
%s Size in bytes
%t '*' if the file is tagged, blank otherwise
%u Owner name (or numeric uid, if missing)

Definition at line 358 of file browser.c.

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Add a folder to the browser list.

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

Definition at line 600 of file browser.c.

603 {
604  if (state->entrylen == state->entrymax)
605  {
606  /* need to allocate more space */
607  mutt_mem_realloc(&state->entry, sizeof(struct FolderFile) * (state->entrymax += 256));
608  memset(&state->entry[state->entrylen], 0, sizeof(struct FolderFile) * 256);
609  if (menu)
610  menu->data = state->entry;
611  }
612 
613  if (s)
614  {
615  (state->entry)[state->entrylen].mode = s->st_mode;
616  (state->entry)[state->entrylen].mtime = s->st_mtime;
617  (state->entry)[state->entrylen].size = s->st_size;
618  (state->entry)[state->entrylen].gid = s->st_gid;
619  (state->entry)[state->entrylen].uid = s->st_uid;
620  (state->entry)[state->entrylen].nlink = s->st_nlink;
621 
622  (state->entry)[state->entrylen].local = true;
623  }
624  else
625  (state->entry)[state->entrylen].local = false;
626 
627  if (m)
628  {
629  (state->entry)[state->entrylen].has_mailbox = true;
630  (state->entry)[state->entrylen].new = m->has_new;
631  (state->entry)[state->entrylen].msg_count = m->msg_count;
632  (state->entry)[state->entrylen].msg_unread = m->msg_unread;
633  }
634 
635  (state->entry)[state->entrylen].name = mutt_str_strdup(name);
636  (state->entry)[state->entrylen].desc = mutt_str_strdup(desc ? desc : name);
637 #ifdef USE_IMAP
638  (state->entry)[state->entrylen].imap = false;
639 #endif
640 #ifdef USE_NNTP
641  if (OptNews)
642  (state->entry)[state->entrylen].nd = data;
643 #endif
644  (state->entrylen)++;
645 }
mode_t mode
Definition: browser.h:60
int msg_count
total number of messages
Definition: mailbox.h:93
int msg_unread
number of unread messages
Definition: mailbox.h:94
bool has_new
mailbox has new mail
Definition: mailbox.h:90
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:124
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:383
void * data
extra data for the current menu
Definition: mutt_menu.h:86
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:42
struct FolderFile * entry
Definition: browser.h:94

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Initialise a browser state.

Parameters
stateBrowserState to initialise
menuCurrent menu

Definition at line 652 of file browser.c.

653 {
654  state->entrylen = 0;
655  state->entrymax = 256;
656  state->entry = mutt_mem_calloc(state->entrymax, sizeof(struct FolderFile));
657 #ifdef USE_IMAP
658  state->imap_browse = false;
659 #endif
660  if (menu)
661  menu->data = state->entry;
662 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:51
unsigned int entrymax
max entry
Definition: browser.h:96
Browser entry representing a folder/dir.
Definition: browser.h:58
size_t entrylen
number of real entries
Definition: browser.h:95
void * data
extra data for the current menu
Definition: mutt_menu.h:86
bool imap_browse
Definition: browser.h:98
struct FolderFile * entry
Definition: browser.h:94

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int examine_directory ( struct Menu menu,
struct BrowserState state,
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 673 of file browser.c.

675 {
676 #ifdef USE_NNTP
677  if (OptNews)
678  {
680 
681  init_state(state, menu);
682 
683  for (unsigned int i = 0; i < adata->groups_num; i++)
684  {
685  struct NntpMboxData *mdata = adata->groups_list[i];
686  if (!mdata)
687  continue;
688  if (prefix && *prefix && !mutt_str_startswith(mdata->group, prefix, CASE_MATCH))
689  continue;
690  if (C_Mask && C_Mask->regex &&
691  !((regexec(C_Mask->regex, mdata->group, 0, NULL, 0) == 0) ^ C_Mask->not))
692  {
693  continue;
694  }
695  add_folder(menu, state, mdata->group, NULL, NULL, NULL, mdata);
696  }
697  }
698  else
699 #endif /* USE_NNTP */
700  {
701  struct stat s;
702  DIR *dp = NULL;
703  struct dirent *de = NULL;
704  char buf[PATH_MAX + 128];
705 
706  while (stat(d, &s) == -1)
707  {
708  if (errno == ENOENT)
709  {
710  /* The last used directory is deleted, try to use the parent dir. */
711  char *c = strrchr(d, '/');
712 
713  if (c && (c > d))
714  {
715  *c = '\0';
716  continue;
717  }
718  }
719  mutt_perror(d);
720  return -1;
721  }
722 
723  if (!S_ISDIR(s.st_mode))
724  {
725  mutt_error(_("%s is not a directory"), d);
726  return -1;
727  }
728 
730 
731  dp = opendir(d);
732  if (!dp)
733  {
734  mutt_perror(d);
735  return -1;
736  }
737 
738  init_state(state, menu);
739 
740  while ((de = readdir(dp)))
741  {
742  if (mutt_str_strcmp(de->d_name, ".") == 0)
743  continue; /* we don't need . */
744 
745  if (prefix && *prefix && !mutt_str_startswith(de->d_name, prefix, CASE_MATCH))
746  {
747  continue;
748  }
749  if (C_Mask && C_Mask->regex &&
750  !((regexec(C_Mask->regex, de->d_name, 0, NULL, 0) == 0) ^ C_Mask->not))
751  {
752  continue;
753  }
754 
755  mutt_path_concat(buf, d, de->d_name, sizeof(buf));
756  if (lstat(buf, &s) == -1)
757  continue;
758 
759  /* No size for directories or symlinks */
760  if (S_ISDIR(s.st_mode) || S_ISLNK(s.st_mode))
761  s.st_size = 0;
762  else if (!S_ISREG(s.st_mode))
763  continue;
764 
765  struct MailboxNode *np = NULL;
766  STAILQ_FOREACH(np, &AllMailboxes, entries)
767  {
768  if (mutt_str_strcmp(buf, np->mailbox->path) != 0)
769  break;
770  }
771 
772  if (np && Context &&
774  {
777  }
778  add_folder(menu, state, de->d_name, NULL, &s, np ? np->mailbox : NULL, NULL);
779  }
780  closedir(dp);
781  }
782  browser_sort(state);
783  return 0;
784 }
The "current" mailbox.
Definition: context.h:37
bool not
do not match
Definition: regex3.h:61
int msg_count
total number of messages
Definition: mailbox.h:93
#define mutt_perror(...)
Definition: logging.h:89
int msg_unread
number of unread messages
Definition: mailbox.h:94
regex_t * regex
compiled expression
Definition: regex3.h:60
static void add_folder(struct Menu *menu, struct BrowserState *state, const char *name, const char *desc, const struct stat *s, struct Mailbox *m, void *data)
Add a folder to the browser list.
Definition: browser.c:600
#define _(a)
Definition: message.h:28
Match case when comparing strings.
Definition: string2.h:66
NNTP-specific Account data -.
Definition: nntp.h:76
struct Mailbox * mailbox
Definition: context.h:51
char * group
Definition: nntp.h:141
void * mdata
driver specific data
Definition: mailbox.h:137
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all AllMailboxes for new mail.
Definition: mailbox.c:336
#define PATH_MAX
Definition: mutt.h:48
void * adata
Definition: account.h:41
unsigned int groups_num
Definition: nntp.h:99
static void browser_sort(struct BrowserState *state)
Sort the entries in the browser.
Definition: browser.c:298
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
NNTP-specific Mailbox data -.
Definition: nntp.h:139
struct MailboxList AllMailboxes
List of all Mailboxes.
Definition: mailbox.c:86
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:165
char path[PATH_MAX]
Definition: mailbox.h:85
#define mutt_error(...)
Definition: logging.h:88
WHERE struct Regex * C_Mask
Config: Only display files/dirs matching this regex in the browser.
Definition: globals.h:184
void ** groups_list
Definition: nntp.h:101
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:324
List of Mailboxes.
Definition: mailbox.h:147
char realpath[PATH_MAX]
used for duplicate detection, context comparison, and the sidebar
Definition: mailbox.h:86
static void init_state(struct BrowserState *state, struct Menu *menu)
Initialise a browser state.
Definition: browser.c:652
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:611
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:79
struct Mailbox * mailbox
Definition: mailbox.h:149

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int examine_mailboxes ( struct Menu menu,
struct BrowserState state 
)
static

Get list of mailboxes/subscribed newsgroups.

Parameters
menuCurrent menu
stateState of browser
Return values
0Success
-1Error

Definition at line 793 of file browser.c.

794 {
795  struct stat s;
796 
797 #ifdef USE_NNTP
798  if (OptNews)
799  {
801 
802  init_state(state, menu);
803 
804  for (unsigned int i = 0; i < adata->groups_num; i++)
805  {
806  struct NntpMboxData *mdata = adata->groups_list[i];
807  if (mdata && (mdata->new || (mdata->subscribed && (mdata->unread || !C_ShowOnlyUnread))))
808  {
809  add_folder(menu, state, mdata->group, NULL, NULL, NULL, mdata);
810  }
811  }
812  }
813  else
814 #endif
815  {
816  init_state(state, menu);
817 
819  return -1;
821 
822  struct MailboxNode *np = NULL;
823  STAILQ_FOREACH(np, &AllMailboxes, entries)
824  {
826  {
829  }
830 
831  char buf[PATH_MAX];
832  mutt_str_strfcpy(buf, np->mailbox->path, sizeof(buf));
834  mutt_pretty_mailbox(buf, sizeof(buf));
835 
836  switch (np->mailbox->magic)
837  {
838  case MUTT_IMAP:
839  case MUTT_POP:
840  add_folder(menu, state, buf, np->mailbox->desc, NULL, np->mailbox, NULL);
841  continue;
842  case MUTT_NOTMUCH:
843  case MUTT_NNTP:
844  add_folder(menu, state, np->mailbox->path, np->mailbox->desc, NULL,
845  np->mailbox, NULL);
846  continue;
847  default: /* Continue */
848  break;
849  }
850 
851  if (lstat(np->mailbox->path, &s) == -1)
852  continue;
853 
854  if ((!S_ISREG(s.st_mode)) && (!S_ISDIR(s.st_mode)) && (!S_ISLNK(s.st_mode)))
855  continue;
856 
857  if (np->mailbox->magic == MUTT_MAILDIR)
858  {
859  struct stat st2;
860  char md[PATH_MAX];
861 
862  snprintf(md, sizeof(md), "%s/new", np->mailbox->path);
863  if (stat(md, &s) < 0)
864  s.st_mtime = 0;
865  snprintf(md, sizeof(md), "%s/cur", np->mailbox->path);
866  if (stat(md, &st2) < 0)
867  st2.st_mtime = 0;
868  if (st2.st_mtime > s.st_mtime)
869  s.st_mtime = st2.st_mtime;
870  }
871 
872  add_folder(menu, state, buf, np->mailbox->desc, &s, np->mailbox, NULL);
873  }
874  }
875  browser_sort(state);
876  return 0;
877 }
The "current" mailbox.
Definition: context.h:37
&#39;Notmuch&#39; (virtual) Mailbox type
Definition: magic.h:43
int msg_count
total number of messages
Definition: mailbox.h:93
int msg_unread
number of unread messages
Definition: mailbox.h:94
&#39;NNTP&#39; (Usenet) Mailbox type
Definition: magic.h:41
void mutt_pretty_mailbox(char *s, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:605
&#39;Maildir&#39; Mailbox type
Definition: magic.h:40
char * desc
Definition: mailbox.h:88
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:600
&#39;IMAP&#39; Mailbox type
Definition: magic.h:42
NNTP-specific Account data -.
Definition: nntp.h:76
bool subscribed
Definition: nntp.h:148
struct Mailbox * mailbox
Definition: context.h:51
enum MailboxType magic
mailbox type
Definition: mailbox.h:106
char * group
Definition: nntp.h:141
void * mdata
driver specific data
Definition: mailbox.h:137
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all AllMailboxes for new mail.
Definition: mailbox.c:336
#define PATH_MAX
Definition: mutt.h:48
void * adata
Definition: account.h:41
bool new
Definition: nntp.h:149
unsigned int groups_num
Definition: nntp.h:99
static void browser_sort(struct BrowserState *state)
Sort the entries in the browser.
Definition: browser.c:298
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:741
bool C_ShowOnlyUnread
Config: (nntp) Only show subscribed newsgroups with unread articles.
Definition: browser.c:81
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
NNTP-specific Mailbox data -.
Definition: nntp.h:139
struct MailboxList AllMailboxes
List of all Mailboxes.
Definition: mailbox.c:86
char path[PATH_MAX]
Definition: mailbox.h:85
anum_t unread
Definition: nntp.h:147
bool C_BrowserAbbreviateMailboxes
Config: Abbreviate mailboxes using &#39;~&#39; and &#39;=&#39; in the browser.
Definition: browser.c:77
void ** groups_list
Definition: nntp.h:101
#define STAILQ_EMPTY(head)
Definition: queue.h:346
List of Mailboxes.
Definition: mailbox.h:147
char realpath[PATH_MAX]
used for duplicate detection, context comparison, and the sidebar
Definition: mailbox.h:86
static void init_state(struct BrowserState *state, struct Menu *menu)
Initialise a browser state.
Definition: browser.c:652
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:611
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:79
&#39;POP3&#39; Mailbox type
Definition: magic.h:44
struct Mailbox * mailbox
Definition: mailbox.h:149

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int select_file_search ( struct Menu menu,
regex_t *  rx,
int  line 
)
static

Menu search callback for matching files - Implements Menu::menu_search()

Definition at line 882 of file browser.c.

883 {
884 #ifdef USE_NNTP
885  if (OptNews)
886  return regexec(rx, ((struct FolderFile *) menu->data)[line].desc, 0, NULL, 0);
887 #endif
888  struct FolderFile current_ff = ((struct FolderFile *) menu->data)[line];
889  char *search_on = current_ff.desc ? current_ff.desc : current_ff.name;
890 
891  return regexec(rx, search_on, 0, NULL, 0);
892 }
char * desc
Definition: browser.h:68
char * name
Definition: browser.h:67
const char * line
Definition: common.c:35
Browser entry representing a folder/dir.
Definition: browser.h:58
void * data
extra data for the current menu
Definition: mutt_menu.h:86
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:42

+ Here is the caller graph for this function:

static void folder_make_entry ( char *  buf,
size_t  buflen,
struct Menu menu,
int  line 
)
static

Format a menu item for the folder browser - Implements Menu::menu_make_entry()

Definition at line 897 of file browser.c.

898 {
899  struct Folder folder;
900 
901  folder.ff = &((struct FolderFile *) menu->data)[line];
902  folder.num = line;
903 
904 #ifdef USE_NNTP
905  if (OptNews)
906  {
907  mutt_expando_format(buf, buflen, 0, MuttIndexWindow->cols,
909  (unsigned long) &folder, MUTT_FORMAT_ARROWCURSOR);
910  }
911  else
912 #endif
913  {
914  mutt_expando_format(buf, buflen, 0, MuttIndexWindow->cols,
916  (unsigned long) &folder, MUTT_FORMAT_ARROWCURSOR);
917  }
918 }
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:811
#define NONULL(x)
Definition: string2.h:36
#define MUTT_FORMAT_ARROWCURSOR
Reserve space for arrow_cursor.
Definition: format_flags.h:35
char * C_FolderFormat
Config: printf-like format string for the browser&#39;s display of folders.
Definition: browser.c:78
struct FolderFile * ff
Definition: browser.h:51
const char * line
Definition: common.c:35
A folder/dir in the browser.
Definition: browser.h:49
Browser entry representing a folder/dir.
Definition: browser.h:58
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:358
const char * group_index_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, unsigned long data, MuttFormatFlags flags)
Format a string for the newsgroup menu - Implements format_t.
Definition: browse.c:54
void * data
extra data for the current menu
Definition: mutt_menu.h:86
char * C_GroupIndexFormat
Config: (nntp) printf-like format string for the browser&#39;s display of newsgroups. ...
Definition: browser.c:79
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:42

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Decide which browser item should be highlighted.

Parameters
stateBrowser state
menuCurrent Menu

This function takes a menu and a state and defines the current entry that should be highlighted.

Definition at line 928 of file browser.c.

929 {
930  menu->top = 0;
931  /* Reset menu position to 1.
932  * We do not risk overflow as the init_menu function changes
933  * current if it is bigger than state->entrylen. */
934  if ((mutt_str_strcmp(state->entry[0].desc, "..") == 0) ||
935  (mutt_str_strcmp(state->entry[0].desc, "../") == 0))
936  {
937  /* Skip the first entry, unless there's only one entry. */
938  menu->current = (menu->max > 1);
939  }
940  else
941  {
942  menu->current = 0;
943  }
944 }
char * desc
Definition: browser.h:68
int top
entry that is the top of the current page
Definition: mutt_menu.h:109
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:611
struct FolderFile * entry
Definition: browser.h:94

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void init_menu ( struct BrowserState state,
struct Menu menu,
char *  title,
size_t  titlelen,
bool  mailbox 
)
static

Set up a new menu.

Parameters
stateBrowser state
menuCurrent menu
titleBuffer for the title
titlelenLength of buffer
mailboxIf true, select mailboxes

Definition at line 954 of file browser.c.

956 {
957  menu->max = state->entrylen;
958 
959  if (menu->current >= menu->max)
960  menu->current = menu->max - 1;
961  if (menu->current < 0)
962  menu->current = 0;
963  if (menu->top > menu->current)
964  menu->top = 0;
965 
966  menu->tagged = 0;
967 
968 #ifdef USE_NNTP
969  if (OptNews)
970  {
971  if (mailbox)
972  snprintf(title, titlelen, _("Subscribed newsgroups"));
973  else
974  {
975  snprintf(title, titlelen, _("Newsgroups on server [%s]"),
977  }
978  }
979  else
980 #endif
981  {
982  if (mailbox)
983  {
984  menu->is_mailbox_list = true;
985  snprintf(title, titlelen, _("Mailboxes [%d]"),
986  mutt_mailbox_check(Context ? Context->mailbox : NULL, 0));
987  }
988  else
989  {
990  char path[PATH_MAX];
991  menu->is_mailbox_list = false;
992  mutt_str_strfcpy(path, LastDir, sizeof(path));
993  mutt_pretty_mailbox(path, sizeof(path));
994  snprintf(title, titlelen, _("Directory [%s], File mask: %s"), path,
995  NONULL(C_Mask ? C_Mask->pattern : NULL));
996  }
997  }
998 
999  /* Browser tracking feature.
1000  * The goal is to highlight the good directory if LastDir is the parent dir
1001  * of OldLastDir (this occurs mostly when one hit "../"). It should also work
1002  * properly when the user is in examine_mailboxes-mode. */
1004  {
1005  char target_dir[PATH_MAX] = "";
1006 
1007 #ifdef USE_IMAP
1008  /* Check what kind of dir OldLastDir is. */
1009  if (imap_path_probe(OldLastDir, NULL) == MUTT_IMAP)
1010  {
1011  mutt_str_strfcpy(target_dir, OldLastDir, sizeof(target_dir));
1012  imap_clean_path(target_dir, sizeof(target_dir));
1013  }
1014  else
1015 #endif
1016  mutt_str_strfcpy(target_dir, strrchr(OldLastDir, '/') + 1, sizeof(target_dir));
1017 
1018  /* If we get here, it means that LastDir is the parent directory of
1019  * OldLastDir. I.e., we're returning from a subdirectory, and we want
1020  * to position the cursor on the directory we're returning from. */
1021  bool matched = false;
1022  for (unsigned int i = 0; i < state->entrylen; i++)
1023  {
1024  if (mutt_str_strcmp(state->entry[i].name, target_dir) == 0)
1025  {
1026  menu->current = i;
1027  matched = true;
1028  break;
1029  }
1030  }
1031  if (!matched)
1032  browser_highlight_default(state, menu);
1033  }
1034  else
1035  browser_highlight_default(state, menu);
1036 
1037  menu->redraw = REDRAW_FULL;
1038 }
The "current" mailbox.
Definition: context.h:37
#define REDRAW_FULL
Redraw everything.
Definition: mutt_menu.h:47
#define NONULL(x)
Definition: string2.h:36
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2454
struct ConnAccount account
Definition: connection.h:36
static char OldLastDir[PATH_MAX]
Definition: browser.c:107
void mutt_pretty_mailbox(char *s, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:605
#define _(a)
Definition: message.h:28
static char LastDir[PATH_MAX]
Definition: browser.c:108
&#39;IMAP&#39; Mailbox type
Definition: magic.h:42
Match case when comparing strings.
Definition: string2.h:66
char host[128]
Definition: connaccount.h:36
struct Mailbox * mailbox
Definition: context.h:51
char * name
Definition: browser.h:67
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all AllMailboxes for new mail.
Definition: mailbox.c:336
#define PATH_MAX
Definition: mutt.h:48
int top
entry that is the top of the current page
Definition: mutt_menu.h: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:741
bool is_mailbox_list
Definition: mutt_menu.h:94
int tagged
number of tagged entries
Definition: mutt_menu.h:112
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:165
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:928
WHERE struct Regex * C_Mask
Config: Only display files/dirs matching this regex in the browser.
Definition: globals.h:184
int current
current entry
Definition: mutt_menu.h:87
char * pattern
printable version
Definition: regex3.h:59
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:611
struct FolderFile * entry
Definition: browser.h:94
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:79
void imap_clean_path(char *path, size_t plen)
Cleans an IMAP path using imap_fix_path.
Definition: util.c:328

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int file_tag ( struct Menu menu,
int  sel,
int  act 
)
static

Tag an entry in the menu - Implements Menu::menu_tag()

Definition at line 1043 of file browser.c.

1044 {
1045  struct FolderFile *ff = &(((struct FolderFile *) menu->data)[sel]);
1046  if (S_ISDIR(ff->mode) || (S_ISLNK(ff->mode) && link_is_dir(LastDir, ff->name)))
1047  {
1048  mutt_error(_("Can't attach a directory"));
1049  return 0;
1050  }
1051 
1052  bool ot = ff->tagged;
1053  ff->tagged = ((act >= 0) ? act : !ff->tagged);
1054 
1055  return ff->tagged - ot;
1056 }
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:325
#define _(a)
Definition: message.h:28
static char LastDir[PATH_MAX]
Definition: browser.c:108
char * name
Definition: browser.h:67
Browser entry representing a folder/dir.
Definition: browser.h:58
#define mutt_error(...)
Definition: logging.h:88
void * data
extra data for the current menu
Definition: mutt_menu.h:86
bool tagged
Definition: browser.h:83

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_browser_select_dir ( const char *  f)

Remember the last directory selected.

Parameters
fDirectory name to save

This function helps the browser to know which directory has been selected. It should be called anywhere a confirm hit is done to open a new directory/file which is a maildir/mbox.

We could check if the sort method is appropriate with this feature.

Definition at line 1068 of file browser.c.

1069 {
1070  mutt_str_strfcpy(OldLastDir, f, sizeof(OldLastDir));
1071 
1072  /* Method that will fetch the parent path depending on the
1073  * type of the path. */
1075 }
static char OldLastDir[PATH_MAX]
Definition: browser.c:107
static char LastDir[PATH_MAX]
Definition: browser.c:108
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:741
void mutt_get_parent_path(char *path, char *buf, size_t buflen)
Find the parent of a path (or mailbox)
Definition: muttlib.c:1566

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Let the user select a file.

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

Definition at line 1085 of file browser.c.

1087 {
1088  char buf[PATH_MAX];
1089  char prefix[PATH_MAX] = "";
1090  char helpstr[1024];
1091  char title[256];
1092  struct BrowserState state = { 0 };
1093  struct Menu *menu = NULL;
1094  bool kill_prefix = false;
1095  bool multiple = (flags & MUTT_SEL_MULTI);
1096  bool folder = (flags & MUTT_SEL_FOLDER);
1097  bool mailbox = (flags & MUTT_SEL_MAILBOX);
1098 
1099  /* Keeps in memory the directory we were in when hitting '='
1100  * to go directly to $folder (#C_Folder) */
1101  char goto_swapper[PATH_MAX] = "";
1102 
1103  mailbox = mailbox && folder;
1104 
1105 #ifdef USE_NNTP
1106  if (OptNews)
1107  {
1108  if (file[0] != '\0')
1109  mutt_str_strfcpy(prefix, file, sizeof(prefix));
1110  else
1111  {
1113 
1114  /* default state for news reader mode is browse subscribed newsgroups */
1115  mailbox = false;
1116  for (size_t i = 0; i < adata->groups_num; i++)
1117  {
1118  struct NntpMboxData *mdata = adata->groups_list[i];
1119  if (mdata && mdata->subscribed)
1120  {
1121  mailbox = true;
1122  break;
1123  }
1124  }
1125  }
1126  }
1127  else
1128 #endif
1129  if (file[0] != '\0')
1130  {
1131  mutt_expand_path(file, filelen);
1132 #ifdef USE_IMAP
1133  if (imap_path_probe(file, NULL) == MUTT_IMAP)
1134  {
1135  init_state(&state, NULL);
1136  state.imap_browse = true;
1137  if (imap_browse(file, &state) == 0)
1138  {
1139  mutt_str_strfcpy(LastDir, state.folder, sizeof(LastDir));
1140  browser_sort(&state);
1141  }
1142  }
1143  else
1144  {
1145 #endif
1146  int i;
1147  for (i = mutt_str_strlen(file) - 1; (i > 0) && (file[i] != '/'); i--)
1148  ;
1149  if (i > 0)
1150  {
1151  if (file[0] == '/')
1152  {
1153  if (i > (sizeof(LastDir) - 1))
1154  i = sizeof(LastDir) - 1;
1155  strncpy(LastDir, file, i);
1156  LastDir[i] = 0;
1157  }
1158  else
1159  {
1160  getcwd(LastDir, sizeof(LastDir));
1161  mutt_str_strcat(LastDir, sizeof(LastDir), "/");
1162  mutt_str_strncat(LastDir, sizeof(LastDir), file, i);
1163  }
1164  }
1165  else
1166  {
1167  if (file[0] == '/')
1168  strcpy(LastDir, "/");
1169  else
1170  getcwd(LastDir, sizeof(LastDir));
1171  }
1172 
1173  if ((i <= 0) && (file[0] != '/'))
1174  mutt_str_strfcpy(prefix, file, sizeof(prefix));
1175  else
1176  mutt_str_strfcpy(prefix, file + i + 1, sizeof(prefix));
1177  kill_prefix = true;
1178 #ifdef USE_IMAP
1179  }
1180 #endif
1181  }
1182  else
1183  {
1184  if (!folder)
1185  getcwd(LastDir, sizeof(LastDir));
1186  else
1187  {
1188  /* Whether we use the tracking feature of the browser depends
1189  * on which sort method we chose to use. This variable is defined
1190  * only to help readability of the code. */
1191  bool browser_track = false;
1192 
1193  switch (C_SortBrowser & SORT_MASK)
1194  {
1195  case SORT_DESC:
1196  case SORT_SUBJECT:
1197  case SORT_ORDER:
1198  browser_track = true;
1199  break;
1200  }
1201 
1202  /* We use mutt_browser_select_dir to initialize the two
1203  * variables (LastDir, OldLastDir) at the appropriate
1204  * values.
1205  *
1206  * We do it only when LastDir is not set (first pass there)
1207  * or when CurrentFolder and OldLastDir are not the same.
1208  * This code is executed only when we list files, not when
1209  * we press up/down keys to navigate in a displayed list.
1210  *
1211  * We only do this when CurrentFolder has been set (ie, not
1212  * when listing folders on startup with "neomutt -y").
1213  *
1214  * This tracker is only used when browser_track is true,
1215  * meaning only with sort methods SUBJECT/DESC for now. */
1216  if (CurrentFolder)
1217  {
1218  if (LastDir[0] == '\0')
1219  {
1220  /* If browsing in "local"-mode, than we chose to define LastDir to
1221  * MailDir */
1222  switch (mx_path_probe(CurrentFolder, NULL))
1223  {
1224  case MUTT_IMAP:
1225  case MUTT_MAILDIR:
1226  case MUTT_MBOX:
1227  case MUTT_MH:
1228  case MUTT_MMDF:
1229  if (C_Folder)
1231  else if (C_Spoolfile)
1233  break;
1234  default:
1236  break;
1237  }
1238  }
1239  else if (mutt_str_strcmp(CurrentFolder, OldLastDir) != 0)
1240  {
1242  }
1243  }
1244 
1245  /* When browser tracking feature is disabled, shoot a 0
1246  * on first char of OldLastDir to make it useless. */
1247  if (!browser_track)
1248  OldLastDir[0] = '\0';
1249  }
1250 
1251 #ifdef USE_IMAP
1252  if (!mailbox && (imap_path_probe(LastDir, NULL) == MUTT_IMAP))
1253  {
1254  init_state(&state, NULL);
1255  state.imap_browse = true;
1256  imap_browse(LastDir, &state);
1257  browser_sort(&state);
1258  }
1259  else
1260 #endif
1261  {
1262  size_t i = mutt_str_strlen(LastDir);
1263  while ((i > 0) && (LastDir[--i] == '/'))
1264  LastDir[i] = '\0';
1265  if (LastDir[0] == '\0')
1266  getcwd(LastDir, sizeof(LastDir));
1267  }
1268  }
1269 
1270  file[0] = '\0';
1271 
1272  if (mailbox)
1273  {
1274  examine_mailboxes(NULL, &state);
1275  }
1276  else
1277 #ifdef USE_IMAP
1278  if (!state.imap_browse)
1279 #endif
1280  {
1281  if (examine_directory(NULL, &state, LastDir, prefix) == -1)
1282  goto bail;
1283  }
1284  menu = mutt_menu_new(MENU_FOLDER);
1287  menu->title = title;
1288  menu->data = state.entry;
1289  if (multiple)
1290  menu->menu_tag = file_tag;
1291 
1293  menu->help = mutt_compile_help(helpstr, sizeof(helpstr), MENU_FOLDER,
1294 #ifdef USE_NNTP
1296 #endif
1297  FolderHelp);
1298  mutt_menu_push_current(menu);
1299 
1300  init_menu(&state, menu, title, sizeof(title), mailbox);
1301 
1302  int op;
1303  while (true)
1304  {
1305  switch (op = mutt_menu_loop(menu))
1306  {
1307  case OP_DESCEND_DIRECTORY:
1308  case OP_GENERIC_SELECT_ENTRY:
1309 
1310  if (state.entrylen == 0)
1311  {
1312  mutt_error(_("No files match the file mask"));
1313  break;
1314  }
1315  else if (op == OP_DESCEND_DIRECTORY)
1316  {
1317  mutt_error(_("%s is not a directory"), state.entry[menu->current].name);
1318  break;
1319  }
1320 
1321  if (S_ISDIR(state.entry[menu->current].mode) ||
1322  (S_ISLNK(state.entry[menu->current].mode) &&
1323  link_is_dir(LastDir, state.entry[menu->current].name))
1324 #ifdef USE_IMAP
1325  || state.entry[menu->current].inferiors
1326 #endif
1327  )
1328  {
1329  /* make sure this isn't a MH or maildir mailbox */
1330  if (mailbox)
1331  {
1332  mutt_str_strfcpy(buf, state.entry[menu->current].name, sizeof(buf));
1333  mutt_expand_path(buf, sizeof(buf));
1334  }
1335 #ifdef USE_IMAP
1336  else if (state.imap_browse)
1337  {
1338  mutt_str_strfcpy(buf, state.entry[menu->current].name, sizeof(buf));
1339  }
1340 #endif
1341  else
1342  {
1343  mutt_path_concat(buf, LastDir, state.entry[menu->current].name, sizeof(buf));
1344  }
1345 
1346  enum MailboxType magic = mx_path_probe(buf, NULL);
1347  if ((op == OP_DESCEND_DIRECTORY) || (magic == MUTT_MAILBOX_ERROR) ||
1348  (magic == MUTT_UNKNOWN)
1349 #ifdef USE_IMAP
1350  || state.entry[menu->current].inferiors
1351 #endif
1352  )
1353  {
1354  /* save the old directory */
1356 
1357  if (mutt_str_strcmp(state.entry[menu->current].name, "..") == 0)
1358  {
1359  if (mutt_str_strcmp("..", LastDir + mutt_str_strlen(LastDir) - 2) == 0)
1360  strcat(LastDir, "/..");
1361  else
1362  {
1363  char *p = strrchr(LastDir + 1, '/');
1364 
1365  if (p)
1366  *p = '\0';
1367  else
1368  {
1369  if (LastDir[0] == '/')
1370  LastDir[1] = '\0';
1371  else
1372  strcat(LastDir, "/..");
1373  }
1374  }
1375  }
1376  else if (mailbox)
1377  {
1378  mutt_str_strfcpy(LastDir, state.entry[menu->current].name, sizeof(LastDir));
1379  mutt_expand_path(LastDir, sizeof(LastDir));
1380  }
1381 #ifdef USE_IMAP
1382  else if (state.imap_browse)
1383  {
1384  mutt_str_strfcpy(LastDir, state.entry[menu->current].name, sizeof(LastDir));
1385  /* tack on delimiter here */
1386  int n = strlen(LastDir) + 1;
1387 
1388  /* special case "" needs no delimiter */
1389  struct Url *url = url_parse(state.entry[menu->current].name);
1390  if (url->path && (state.entry[menu->current].delim != '\0') &&
1391  (n < sizeof(LastDir)))
1392  {
1393  LastDir[n] = '\0';
1394  LastDir[n - 1] = state.entry[menu->current].delim;
1395  }
1396  url_free(&url);
1397  }
1398 #endif
1399  else
1400  {
1401  char tmp[PATH_MAX];
1402  mutt_path_concat(tmp, LastDir, state.entry[menu->current].name, sizeof(tmp));
1403  mutt_str_strfcpy(LastDir, tmp, sizeof(LastDir));
1404  }
1405 
1406  destroy_state(&state);
1407  if (kill_prefix)
1408  {
1409  prefix[0] = '\0';
1410  kill_prefix = false;
1411  }
1412  mailbox = false;
1413 #ifdef USE_IMAP
1414  if (state.imap_browse)
1415  {
1416  init_state(&state, NULL);
1417  state.imap_browse = true;
1418  imap_browse(LastDir, &state);
1419  browser_sort(&state);
1420  menu->data = state.entry;
1421  }
1422  else
1423 #endif
1424  {
1425  if (examine_directory(menu, &state, LastDir, prefix) == -1)
1426  {
1427  /* try to restore the old values */
1429  if (examine_directory(menu, &state, LastDir, prefix) == -1)
1430  {
1432  goto bail;
1433  }
1434  }
1435  /* resolve paths navigated from GUI */
1436  if (mutt_path_realpath(LastDir) == 0)
1437  break;
1438  }
1439 
1440  browser_highlight_default(&state, menu);
1441  init_menu(&state, menu, title, sizeof(title), mailbox);
1442  if (goto_swapper[0])
1443  goto_swapper[0] = '\0';
1444  break;
1445  }
1446  }
1447 
1448  if (mailbox || OptNews) /* USE_NNTP */
1449  {
1450  mutt_str_strfcpy(file, state.entry[menu->current].name, filelen);
1451  mutt_expand_path(file, filelen);
1452  }
1453 #ifdef USE_IMAP
1454  else if (state.imap_browse)
1455  mutt_str_strfcpy(file, state.entry[menu->current].name, filelen);
1456 #endif
1457  else
1458  mutt_path_concat(file, LastDir, state.entry[menu->current].name, filelen);
1459  /* fallthrough */
1460 
1461  case OP_EXIT:
1462 
1463  if (multiple)
1464  {
1465  char **tfiles = NULL;
1466 
1467  if (menu->tagged)
1468  {
1469  *numfiles = menu->tagged;
1470  tfiles = mutt_mem_calloc(*numfiles, sizeof(char *));
1471  for (int i = 0, j = 0; i < state.entrylen; i++)
1472  {
1473  struct FolderFile ff = state.entry[i];
1474  if (ff.tagged)
1475  {
1476  char full[PATH_MAX];
1477  mutt_path_concat(full, LastDir, ff.name, sizeof(full));
1478  mutt_expand_path(full, sizeof(full));
1479  tfiles[j++] = mutt_str_strdup(full);
1480  }
1481  }
1482  *files = tfiles;
1483  }
1484  else if (file[0] != '\0') /* no tagged entries. return selected entry */
1485  {
1486  *numfiles = 1;
1487  tfiles = mutt_mem_calloc(*numfiles, sizeof(char *));
1488  mutt_expand_path(file, filelen);
1489  tfiles[0] = mutt_str_strdup(file);
1490  *files = tfiles;
1491  }
1492  }
1493 
1494  destroy_state(&state);
1495  goto bail;
1496 
1497  case OP_BROWSER_TELL:
1498  if (state.entrylen)
1499  mutt_message("%s", state.entry[menu->current].name);
1500  break;
1501 
1502 #ifdef USE_IMAP
1503  case OP_BROWSER_TOGGLE_LSUB:
1504  bool_str_toggle(Config, "imap_list_subscribed", NULL);
1505 
1506  mutt_unget_event(0, OP_CHECK_NEW);
1507  break;
1508 
1509  case OP_CREATE_MAILBOX:
1510  if (!state.imap_browse)
1511  {
1512  mutt_error(_("Create is only supported for IMAP mailboxes"));
1513  break;
1514  }
1515 
1516  if (imap_mailbox_create(LastDir) == 0)
1517  {
1518  /* TODO: find a way to detect if the new folder would appear in
1519  * this window, and insert it without starting over. */
1520  destroy_state(&state);
1521  init_state(&state, NULL);
1522  state.imap_browse = true;
1523  imap_browse(LastDir, &state);
1524  browser_sort(&state);
1525  menu->data = state.entry;
1526  browser_highlight_default(&state, menu);
1527  init_menu(&state, menu, title, sizeof(title), mailbox);
1528  }
1529  /* else leave error on screen */
1530  break;
1531 
1532  case OP_RENAME_MAILBOX:
1533  if (!state.entry[menu->current].imap)
1534  mutt_error(_("Rename is only supported for IMAP mailboxes"));
1535  else
1536  {
1537  int nentry = menu->current;
1538 
1539  if (imap_mailbox_rename(state.entry[nentry].name) >= 0)
1540  {
1541  destroy_state(&state);
1542  init_state(&state, NULL);
1543  state.imap_browse = true;
1544  imap_browse(LastDir, &state);
1545  browser_sort(&state);
1546  menu->data = state.entry;
1547  browser_highlight_default(&state, menu);
1548  init_menu(&state, menu, title, sizeof(title), mailbox);
1549  }
1550  }
1551  break;
1552 
1553  case OP_DELETE_MAILBOX:
1554  if (!state.entry[menu->current].imap)
1555  mutt_error(_("Delete is only supported for IMAP mailboxes"));
1556  else
1557  {
1558  char msg[128];
1559  int nentry = menu->current;
1560 
1561  // TODO(sileht): It could be better to select INBOX instead. But I
1562  // don't want to manipulate Context/AllMailboxes/mailbox->account here for now.
1563  // Let's just protect neomutt against crash for now. #1417
1564  if (mutt_str_strcmp(Context->mailbox->path, state.entry[nentry].name) == 0)
1565  {
1566  mutt_error(_("Can't delete currently selected mailbox"));
1567  break;
1568  }
1569 
1570  snprintf(msg, sizeof(msg), _("Really delete mailbox \"%s\"?"),
1571  state.entry[nentry].name);
1572  if (mutt_yesorno(msg, MUTT_NO) == MUTT_YES)
1573  {
1574  if (imap_delete_mailbox(Context->mailbox, state.entry[nentry].name) == 0)
1575  {
1576  /* free the mailbox from the browser */
1577  FREE(&((state.entry)[nentry].name));
1578  FREE(&((state.entry)[nentry].desc));
1579  /* and move all other entries up */
1580  if ((nentry + 1) < state.entrylen)
1581  {
1582  memmove(state.entry + nentry, state.entry + nentry + 1,
1583  sizeof(struct FolderFile) * (state.entrylen - (nentry + 1)));
1584  }
1585  memset(&state.entry[state.entrylen - 1], 0, sizeof(struct FolderFile));
1586  state.entrylen--;
1587  mutt_message(_("Mailbox deleted"));
1588  init_menu(&state, menu, title, sizeof(title), mailbox);
1589  }
1590  else
1591  mutt_error(_("Mailbox deletion failed"));
1592  }
1593  else
1594  mutt_message(_("Mailbox not deleted"));
1595  }
1596  break;
1597 #endif
1598 
1599  case OP_GOTO_PARENT:
1600  case OP_CHANGE_DIRECTORY:
1601 
1602 #ifdef USE_NNTP
1603  if (OptNews)
1604  break;
1605 #endif
1606 
1607  mutt_str_strfcpy(buf, LastDir, sizeof(buf));
1608 #ifdef USE_IMAP
1609  if (!state.imap_browse)
1610 #endif
1611  {
1612  /* add '/' at the end of the directory name if not already there */
1613  size_t len = mutt_str_strlen(buf);
1614  if ((len > 0) && (buf[len - 1] != '/') && (sizeof(buf) > (len + 1)))
1615  {
1616  buf[len] = '/';
1617  buf[len + 1] = '\0';
1618  }
1619  }
1620 
1621  if (op == OP_CHANGE_DIRECTORY)
1622  {
1623  int ret = mutt_get_field(_("Chdir to: "), buf, sizeof(buf), MUTT_FILE);
1624  if (ret != 0)
1625  break;
1626  }
1627  else if (op == OP_GOTO_PARENT)
1628  mutt_get_parent_path(buf, buf, sizeof(buf));
1629 
1630  if (buf[0] != '\0')
1631  {
1632  mailbox = false;
1633  mutt_expand_path(buf, sizeof(buf));
1634 #ifdef USE_IMAP
1635  if (imap_path_probe(buf, NULL) == MUTT_IMAP)
1636  {
1637  mutt_str_strfcpy(LastDir, buf, sizeof(LastDir));
1638  destroy_state(&state);
1639  init_state(&state, NULL);
1640  state.imap_browse = true;
1641  imap_browse(LastDir, &state);
1642  browser_sort(&state);
1643  menu->data = state.entry;
1644  browser_highlight_default(&state, menu);
1645  init_menu(&state, menu, title, sizeof(title), mailbox);
1646  }
1647  else
1648 #endif
1649  {
1650  if (*buf != '/')
1651  {
1652  /* in case dir is relative, make it relative to LastDir,
1653  * not current working dir */
1654  char tmp[PATH_MAX];
1655  mutt_path_concat(tmp, LastDir, buf, sizeof(tmp));
1656  mutt_str_strfcpy(buf, tmp, sizeof(buf));
1657  }
1658  /* Resolve path from <chdir>
1659  * Avoids buildup such as /a/b/../../c
1660  * Symlinks are always unraveled to keep code simple */
1661  if (mutt_path_realpath(buf) == 0)
1662  break;
1663 
1664  struct stat st;
1665  if (stat(buf, &st) == 0)
1666  {
1667  if (S_ISDIR(st.st_mode))
1668  {
1669  destroy_state(&state);
1670  if (examine_directory(menu, &state, buf, prefix) == 0)
1671  mutt_str_strfcpy(LastDir, buf, sizeof(LastDir));
1672  else
1673  {
1674  mutt_error(_("Error scanning directory"));
1675  if (examine_directory(menu, &state, LastDir, prefix) == -1)
1676  {
1677  goto bail;
1678  }
1679  }
1680  browser_highlight_default(&state, menu);
1681  init_menu(&state, menu, title, sizeof(title), mailbox);
1682  }
1683  else
1684  mutt_error(_("%s is not a directory"), buf);
1685  }
1686  else
1687  mutt_perror(buf);
1688  }
1689  }
1690  break;
1691 
1692  case OP_ENTER_MASK:
1693  {
1694  mutt_str_strfcpy(buf, C_Mask ? C_Mask->pattern : NULL, sizeof(buf));
1695  if (mutt_get_field(_("File Mask: "), buf, sizeof(buf), 0) != 0)
1696  break;
1697 
1698  mailbox = false;
1699  /* assume that the user wants to see everything */
1700  if (buf[0] == '\0')
1701  mutt_str_strfcpy(buf, ".", sizeof(buf));
1702 
1703  struct Buffer errmsg = { 0 };
1704  int rc = cs_str_string_set(Config, "mask", buf, NULL);
1705  if (CSR_RESULT(rc) != CSR_SUCCESS)
1706  {
1707  if (!mutt_buffer_is_empty(&errmsg))
1708  {
1709  mutt_error("%s", errmsg.data);
1710  FREE(&errmsg.data);
1711  }
1712  break;
1713  }
1714 
1715  destroy_state(&state);
1716 #ifdef USE_IMAP
1717  if (state.imap_browse)
1718  {
1719  init_state(&state, NULL);
1720  state.imap_browse = true;
1721  imap_browse(LastDir, &state);
1722  browser_sort(&state);
1723  menu->data = state.entry;
1724  init_menu(&state, menu, title, sizeof(title), mailbox);
1725  }
1726  else
1727 #endif
1728  if (examine_directory(menu, &state, LastDir, NULL) == 0)
1729  init_menu(&state, menu, title, sizeof(title), mailbox);
1730  else
1731  {
1732  mutt_error(_("Error scanning directory"));
1733  goto bail;
1734  }
1735  kill_prefix = false;
1736  if (state.entrylen == 0)
1737  {
1738  mutt_error(_("No files match the file mask"));
1739  break;
1740  }
1741  break;
1742  }
1743 
1744  case OP_SORT:
1745  case OP_SORT_REVERSE:
1746 
1747  {
1748  bool resort = true;
1749  int sort = -1;
1750  int reverse = (op == OP_SORT_REVERSE);
1751 
1752  switch (mutt_multi_choice(
1753  (reverse) ?
1754  /* L10N: The highlighted letters must match the "Sort" options */
1755  _("Reverse sort by (d)ate, (a)lpha, si(z)e, d(e)scription, "
1756  "(c)ount, ne(w) count, or do(n)'t sort? ") :
1757  /* L10N: The highlighted letters must match the "Reverse Sort" options */
1758  _("Sort by (d)ate, (a)lpha, si(z)e, d(e)scription, (c)ount, "
1759  "ne(w) count, or do(n)'t sort? "),
1760  /* L10N: These must match the highlighted letters from "Sort" and "Reverse Sort" */
1761  _("dazecwn")))
1762  {
1763  case -1: /* abort */
1764  resort = false;
1765  break;
1766 
1767  case 1: /* (d)ate */
1768  sort = SORT_DATE;
1769  break;
1770 
1771  case 2: /* (a)lpha */
1772  sort = SORT_SUBJECT;
1773  break;
1774 
1775  case 3: /* si(z)e */
1776  sort = SORT_SIZE;
1777  break;
1778 
1779  case 4: /* d(e)scription */
1780  sort = SORT_DESC;
1781  break;
1782 
1783  case 5: /* (c)ount */
1784  sort = SORT_COUNT;
1785  break;
1786 
1787  case 6: /* ne(w) count */
1788  sort = SORT_UNREAD;
1789  break;
1790 
1791  case 7: /* do(n)'t sort */
1792  sort = SORT_ORDER;
1793  resort = false;
1794  break;
1795  }
1796  if (resort)
1797  {
1798  sort |= reverse ? SORT_REVERSE : 0;
1799  cs_str_native_set(Config, "sort_browser", sort, NULL);
1800  browser_sort(&state);
1801  browser_highlight_default(&state, menu);
1802  menu->redraw = REDRAW_FULL;
1803  }
1804  else
1805  {
1806  cs_str_native_set(Config, "sort_browser", sort, NULL);
1807  }
1808  break;
1809  }
1810 
1811  case OP_TOGGLE_MAILBOXES:
1812  case OP_BROWSER_GOTO_FOLDER:
1813  case OP_CHECK_NEW:
1814  if (op == OP_TOGGLE_MAILBOXES)
1815  mailbox = !mailbox;
1816 
1817  if (op == OP_BROWSER_GOTO_FOLDER)
1818  {
1819  /* When in mailboxes mode, disables this feature */
1820  if (C_Folder)
1821  {
1822  mutt_debug(LL_DEBUG3, "= hit! Folder: %s, LastDir: %s\n", C_Folder, LastDir);
1823  if (goto_swapper[0] == '\0')
1824  {
1825  if (mutt_str_strcmp(LastDir, C_Folder) != 0)
1826  {
1827  /* Stores into goto_swapper LastDir, and swaps to C_Folder */
1828  mutt_str_strfcpy(goto_swapper, LastDir, sizeof(goto_swapper));
1831  }
1832  }
1833  else
1834  {
1836  mutt_str_strfcpy(LastDir, goto_swapper, sizeof(LastDir));
1837  goto_swapper[0] = '\0';
1838  }
1839  }
1840  }
1841  destroy_state(&state);
1842  prefix[0] = '\0';
1843  kill_prefix = false;
1844 
1845  if (mailbox)
1846  {
1847  examine_mailboxes(menu, &state);
1848  }
1849 #ifdef USE_IMAP
1850  else if (imap_path_probe(LastDir, NULL) == MUTT_IMAP)
1851  {
1852  init_state(&state, NULL);
1853  state.imap_browse = true;
1854  imap_browse(LastDir, &state);
1855  browser_sort(&state);
1856  menu->data = state.entry;
1857  }
1858 #endif
1859  else if (examine_directory(menu, &state, LastDir, prefix) == -1)
1860  goto bail;
1861  init_menu(&state, menu, title, sizeof(title), mailbox);
1862  break;
1863 
1864  case OP_MAILBOX_LIST:
1866  break;
1867 
1868  case OP_BROWSER_NEW_FILE:
1869  snprintf(buf, sizeof(buf), "%s/", LastDir);
1870  if (mutt_get_field(_("New file name: "), buf, sizeof(buf), MUTT_FILE) == 0)
1871  {
1872  mutt_str_strfcpy(file, buf, filelen);
1873  destroy_state(&state);
1874  goto bail;
1875  }
1876  break;
1877 
1878  case OP_BROWSER_VIEW_FILE:
1879  if (state.entrylen == 0)
1880  {
1881  mutt_error(_("No files match the file mask"));
1882  break;
1883  }
1884 
1885 #ifdef USE_IMAP
1886  if (state.entry[menu->current].selectable)
1887  {
1888  mutt_str_strfcpy(file, state.entry[menu->current].name, filelen);
1889  destroy_state(&state);
1890  goto bail;
1891  }
1892  else
1893 #endif
1894  if (S_ISDIR(state.entry[menu->current].mode) ||
1895  (S_ISLNK(state.entry[menu->current].mode) &&
1896  link_is_dir(LastDir, state.entry[menu->current].name)))
1897  {
1898  mutt_error(_("Can't view a directory"));
1899  break;
1900  }
1901  else
1902  {
1903  char buf2[PATH_MAX];
1904 
1905  mutt_path_concat(buf2, LastDir, state.entry[menu->current].name, sizeof(buf2));
1906  struct Body *b = mutt_make_file_attach(buf2);
1907  if (b)
1908  {
1909  mutt_view_attachment(NULL, b, MUTT_VA_REGULAR, NULL, NULL);
1910  mutt_body_free(&b);
1911  menu->redraw = REDRAW_FULL;
1912  }
1913  else
1914  mutt_error(_("Error trying to view file"));
1915  }
1916  break;
1917 
1918 #ifdef USE_NNTP
1919  case OP_CATCHUP:
1920  case OP_UNCATCHUP:
1921  if (OptNews)
1922  {
1923  struct FolderFile *ff = &state.entry[menu->current];
1924  struct NntpMboxData *mdata = NULL;
1925 
1927  if (rc < 0)
1928  break;
1929 
1930  if (op == OP_CATCHUP)
1932  else
1934 
1935  if (mdata)
1936  {
1938  if ((menu->current + 1) < menu->max)
1939  menu->current++;
1940  menu->redraw = REDRAW_MOTION_RESYNC;
1941  }
1942  if (rc)
1943  menu->redraw = REDRAW_INDEX;
1945  }
1946  break;
1947 
1948  case OP_LOAD_ACTIVE:
1949  if (OptNews)
1950  {
1951  struct NntpAccountData *adata = CurrentNewsSrv;
1952 
1953  if (nntp_newsrc_parse(adata) < 0)
1954  break;
1955 
1956  for (size_t i = 0; i < adata->groups_num; i++)
1957  {
1958  struct NntpMboxData *mdata = adata->groups_list[i];
1959  if (mdata)
1960  mdata->deleted = true;
1961  }
1962  nntp_active_fetch(adata, true);
1963  nntp_newsrc_update(adata);
1964  nntp_newsrc_close(adata);
1965 
1966  destroy_state(&state);
1967  if (mailbox)
1968  examine_mailboxes(menu, &state);
1969  else
1970  {
1971  if (examine_directory(menu, &state, NULL, NULL) == -1)
1972  break;
1973  }
1974  init_menu(&state, menu, title, sizeof(title), mailbox);
1975  }
1976  break;
1977 #endif /* USE_NNTP */
1978 
1979 #if defined(USE_IMAP) || defined(USE_NNTP)
1980  case OP_BROWSER_SUBSCRIBE:
1981  case OP_BROWSER_UNSUBSCRIBE:
1982 #endif
1983 #ifdef USE_NNTP
1984  case OP_SUBSCRIBE_PATTERN:
1985  case OP_UNSUBSCRIBE_PATTERN:
1986  if (OptNews)
1987  {
1988  struct NntpAccountData *adata = CurrentNewsSrv;
1989  regex_t rx;
1990  memset(&rx, 0, sizeof(rx));
1991  char *s = buf;
1992  int i = menu->current;
1993 
1994  if ((op == OP_SUBSCRIBE_PATTERN) || (op == OP_UNSUBSCRIBE_PATTERN))
1995  {
1996  char tmp[256];
1997 
1998  buf[0] = '\0';
1999  if (op == OP_SUBSCRIBE_PATTERN)
2000  snprintf(tmp, sizeof(tmp), _("Subscribe pattern: "));
2001  else
2002  snprintf(tmp, sizeof(tmp), _("Unsubscribe pattern: "));
2003  if ((mutt_get_field(tmp, buf, sizeof(buf), 0) != 0) || (buf[0] == '\0'))
2004  {
2005  break;
2006  }
2007 
2008  int err = REGCOMP(&rx, s, REG_NOSUB);
2009  if (err != 0)
2010  {
2011  regerror(err, &rx, buf, sizeof(buf));
2012  regfree(&rx);
2013  mutt_error("%s", buf);
2014  break;
2015  }
2016  menu->redraw = REDRAW_FULL;
2017  i = 0;
2018  }
2019  else if (state.entrylen == 0)
2020  {
2021  mutt_error(_("No newsgroups match the mask"));
2022  break;
2023  }
2024 
2025  int rc = nntp_newsrc_parse(adata);
2026  if (rc < 0)
2027  break;
2028 
2029  for (; i < state.entrylen; i++)
2030  {
2031  struct FolderFile *ff = &state.entry[i];
2032 
2033  if ((op == OP_BROWSER_SUBSCRIBE) || (op == OP_BROWSER_UNSUBSCRIBE) ||
2034  (regexec(&rx, ff->name, 0, NULL, 0) == 0))
2035  {
2036  if ((op == OP_BROWSER_SUBSCRIBE) || (op == OP_SUBSCRIBE_PATTERN))
2037  mutt_newsgroup_subscribe(adata, ff->name);
2038  else
2039  mutt_newsgroup_unsubscribe(adata, ff->name);
2040  }
2041  if ((op == OP_BROWSER_SUBSCRIBE) || (op == OP_BROWSER_UNSUBSCRIBE))
2042  {
2043  if ((menu->current + 1) < menu->max)
2044  menu->current++;
2045  menu->redraw = REDRAW_MOTION_RESYNC;
2046  break;
2047  }
2048  }
2049  if (op == OP_SUBSCRIBE_PATTERN)
2050  {
2051  for (size_t j = 0; adata && (j < adata->groups_num); j++)
2052  {
2053  struct NntpMboxData *mdata = adata->groups_list[j];
2054  if (mdata && mdata->group && !mdata->subscribed)
2055  {
2056  if (regexec(&rx, mdata->group, 0, NULL, 0) == 0)
2057  {
2058  mutt_newsgroup_subscribe(adata, mdata->group);
2059  add_folder(menu, &state, mdata->group, NULL, NULL, NULL, mdata);
2060  }
2061  }
2062  }
2063  init_menu(&state, menu, title, sizeof(title), mailbox);
2064  }
2065  if (rc > 0)
2066  menu->redraw = REDRAW_FULL;
2067  nntp_newsrc_update(adata);
2068  nntp_clear_cache(adata);
2069  nntp_newsrc_close(adata);
2070  if ((op != OP_BROWSER_SUBSCRIBE) && (op != OP_BROWSER_UNSUBSCRIBE))
2071  regfree(&rx);
2072  }
2073 #ifdef USE_IMAP
2074  else
2075 #endif /* USE_IMAP && USE_NNTP */
2076 #endif /* USE_NNTP */
2077 #ifdef USE_IMAP
2078  {
2079  char tmp[256];
2080  mutt_str_strfcpy(tmp, state.entry[menu->current].name, sizeof(tmp));
2081  mutt_expand_path(tmp, sizeof(tmp));
2082  imap_subscribe(tmp, (op == OP_BROWSER_SUBSCRIBE));
2083  }
2084 #endif /* USE_IMAP */
2085  }
2086  }
2087 
2088 bail:
2089 
2090  if (menu)
2091  {
2092  mutt_menu_pop_current(menu);
2093  mutt_menu_destroy(&menu);
2094  }
2095 
2096  if (goto_swapper[0])
2097  goto_swapper[0] = '\0';
2098 }
struct Url url
Definition: url.c:45
mode_t mode
Definition: browser.h:60
The "current" mailbox.
Definition: context.h:37
Sort by the date the email was sent.
Definition: sort.h:50
#define REDRAW_FULL
Redraw everything.
Definition: mutt_menu.h:47
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:51
static bool link_is_dir(const char *folder, const char *path)
Does this symlink point to a directory?
Definition: browser.c:325
#define mutt_perror(...)
Definition: logging.h:89
struct NntpMboxData * mutt_newsgroup_catchup(struct Mailbox *m, struct NntpAccountData *adata, char *group)
Catchup newsgroup.
Definition: newsrc.c:1280
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:2454
static void destroy_state(struct BrowserState *state)
Free the BrowserState.
Definition: browser.c:116
static char OldLastDir[PATH_MAX]
Definition: browser.c:107
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:654
#define mutt_message(...)
Definition: logging.h:87
int imap_delete_mailbox(struct Mailbox *m, char *path)
Delete a mailbox.
Definition: imap.c:638
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition: url.h:67
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
&#39;Maildir&#39; Mailbox type
Definition: magic.h:40
int nntp_active_fetch(struct NntpAccountData *adata, bool new)
Fetch list of all newsgroups from server.
Definition: nntp.c:2062
static int file_tag(struct Menu *menu, int sel, int act)
Tag an entry in the menu - Implements Menu::menu_tag()
Definition: browser.c:1043
struct Url * url_parse(const char *src)
Fill in Url.
Definition: url.c:162
State of the file/mailbox browser.
Definition: browser.h:92
&#39;mmdf&#39; Mailbox type
Definition: magic.h:38
General file/mailbox browser.
Definition: keymap.h:72
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:600
void nntp_clear_cache(struct NntpAccountData *adata)
Clear the NNTP cache.
Definition: newsrc.c:842
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:668
#define _(a)
Definition: message.h:28
WHERE struct ConfigSet * Config
Wrapper around the user&#39;s config settings.
Definition: globals.h:39
static char LastDir[PATH_MAX]
Definition: browser.c:108
int imap_mailbox_create(const char *path)
Create a new IMAP mailbox.
Definition: browse.c:364
&#39;IMAP&#39; Mailbox type
Definition: magic.h:42
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:662
int menu
menu definition for keymap entries.
Definition: mutt_menu.h:90
short C_SortBrowser
Config: Sort method for the browser.
Definition: browser.c:82
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:897
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:882
char * mutt_str_strncat(char *d, size_t l, const char *s, size_t sl)
Concatenate two strings.
Definition: string.c:430
void url_free(struct Url **u)
Free the contents of a URL.
Definition: url.c:289
void(* menu_make_entry)(char *buf, size_t buflen, struct Menu *menu, int line)
Format a item for a menu.
Definition: mutt_menu.h:121
NNTP-specific Account data -.
Definition: nntp.h:76
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:77
bool subscribed
Definition: nntp.h:148
The body of an email.
Definition: body.h:34
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
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:157
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:330
struct Mailbox * mailbox
Definition: context.h:51
struct Body * mutt_make_file_attach(const char *path)
Create a file attachment.
Definition: sendlib.c:1591
enum MailboxType magic
mailbox type
Definition: mailbox.h:106
static int examine_mailboxes(struct Menu *menu, struct BrowserState *state)
Get list of mailboxes/subscribed newsgroups.
Definition: browser.c:793
char * name
Definition: browser.h:67
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:1316
size_t mutt_path_realpath(char *buf)
resolve path, unraveling symlinks
Definition: path.c:456
WHERE char * CurrentFolder
Currently selected mailbox.
Definition: globals.h:53
bool imap
Definition: browser.h:77
void * mdata
driver specific data
Definition: mailbox.h:137
#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
int mutt_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question.
Definition: curs_lib.c:792
Browser entry representing a folder/dir.
Definition: browser.h:58
&#39;mbox&#39; Mailbox type
Definition: magic.h:37
WHERE char * C_Folder
Config: Base folder for a set of mailboxes.
Definition: globals.h:122
#define PATH_MAX
Definition: mutt.h:48
MailboxType
Supported mailbox formats.
Definition: magic.h:33
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:38
void * adata
Definition: account.h:41
struct NntpMboxData * mutt_newsgroup_unsubscribe(struct NntpAccountData *adata, char *group)
Unsubscribe newsgroup.
Definition: newsrc.c:1252
char * data
pointer to data
Definition: buffer.h:35
unsigned int groups_num
Definition: nntp.h:99
static void browser_sort(struct BrowserState *state)
Sort the entries in the browser.
Definition: browser.c:298
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:741
Sort by the number of unread emails.
Definition: sort.h:66
Error occurred examining mailbox.
Definition: magic.h:35
#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:163
int tagged
number of tagged entries
Definition: mutt_menu.h:112
#define MUTT_FILE
Do file completion.
Definition: mutt.h:62
void nntp_newsrc_close(struct NntpAccountData *adata)
Unlock and close .newsrc file.
Definition: newsrc.c:122
char * path
Definition: url.h:74
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:138
size_t entrylen
number of real entries
Definition: browser.h:95
char path[PATH_MAX]
Definition: mailbox.h:85
MuttRedrawFlags redraw
when to redraw the screen
Definition: mutt_menu.h:89
int(* menu_search)(struct Menu *menu, regex_t *rx, int line)
Search a menu for a item matching a regex.
Definition: mutt_menu.h:130
#define MUTT_SEL_MAILBOX
Select a mailbox.
Definition: browser.h:42
char * title
the title of this menu
Definition: mutt_menu.h:84
bool mutt_mailbox_list(void)
List the mailboxes with new mail.
Definition: mailbox.c:395
char * mutt_str_strcat(char *buf, size_t buflen, const char *s)
Concatenate two strings.
Definition: string.c:401
static void browser_highlight_default(struct BrowserState *state, struct Menu *menu)
Decide which browser item should be highlighted.
Definition: browser.c:928
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
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:150
void mutt_browser_select_dir(const char *f)
Remember the last directory selected.
Definition: browser.c:1068
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:954
Mailbox wasn&#39;t recognised.
Definition: magic.h:36
#define REDRAW_INDEX
Redraw the index.
Definition: mutt_menu.h:42
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:383
static int examine_directory(struct Menu *menu, struct BrowserState *state, char *d, const char *prefix)
Get list of all files/newsgroups with mask.
Definition: browser.c:673
#define mutt_error(...)
Definition: logging.h:88
WHERE struct Regex * C_Mask
Config: Only display files/dirs matching this regex in the browser.
Definition: globals.h:184
&#39;MH&#39; Mailbox type
Definition: magic.h:39
void ** groups_list
Definition: nntp.h:101
int imap_browse(char *path, struct BrowserState *state)
IMAP hook into the folder browser.
Definition: browse.c:183
#define FREE(x)
Definition: memory.h:40
int imap_mailbox_rename(const char *path)
Rename a mailbox.
Definition: browse.c:416
void * data
extra data for the current menu
Definition: mutt_menu.h:86
char * mutt_path_concat(char *d, const char *dir, const char *fname, size_t l)
Join a directory name and a filename.
Definition: path.c:324
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
#define REGCOMP(preg, regex, cflags)
Compile a regular expression.
Definition: regex3.h:52
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:243
#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:439
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:379
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:652
bool inferiors
Definition: browser.h:79
static const struct Mapping FolderHelp[]
Definition: browser.c:85
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:285
enum MailboxType mx_path_probe(const char *path, struct stat *st)
Find a mailbox that understands a path.
Definition: mx.c:1207
static struct Mapping FolderNewsHelp[]
Definition: browser.c:95
bool imap_browse
Definition: browser.h:98
Sort by the order the messages appear in the mailbox.
Definition: sort.h:55
#define SORT_MASK
Mask for the sort id.
Definition: sort.h:85
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:1226
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:611
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:79
int imap_subscribe(char *path, bool subscribe)
Subscribe to a mailbox.
Definition: imap.c:1392
void mutt_get_parent_path(char *path, char *buf, size_t buflen)
Find the parent of a path (or mailbox)
Definition: muttlib.c:1566
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:798

+ Here is the caller graph for this function:

Variable Documentation

bool C_BrowserAbbreviateMailboxes

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

Definition at line 77 of file browser.c.

char* C_FolderFormat

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

Definition at line 78 of file browser.c.

char* C_GroupIndexFormat

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

Definition at line 79 of file browser.c.

char* C_NewsgroupsCharset

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

Definition at line 80 of file browser.c.

bool C_ShowOnlyUnread

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

Definition at line 81 of file browser.c.

short C_SortBrowser

Config: Sort method for the browser.

Definition at line 82 of file browser.c.

char* C_VfolderFormat

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

Definition at line 83 of file browser.c.

const struct Mapping FolderHelp[]
static
Initial value:
= {
{ N_("Exit"), OP_EXIT },
{ N_("Chdir"), OP_CHANGE_DIRECTORY },
{ N_("Goto"), OP_BROWSER_GOTO_FOLDER },
{ N_("Mask"), OP_ENTER_MASK },
{ N_("Help"), OP_HELP },
{ NULL, 0 },
}
#define N_(a)
Definition: message.h:32

Definition at line 85 of file browser.c.

struct Mapping FolderNewsHelp[]
static
Initial value:
= {
{ N_("Exit"), OP_EXIT },
{ N_("List"), OP_TOGGLE_MAILBOXES },
{ N_("Subscribe"), OP_BROWSER_SUBSCRIBE },
{ N_("Unsubscribe"), OP_BROWSER_UNSUBSCRIBE },
{ N_("Catchup"), OP_CATCHUP },
{ N_("Mask"), OP_ENTER_MASK },
{ N_("Help"), OP_HELP },
{ NULL, 0 },
}
#define N_(a)
Definition: message.h:32

Definition at line 95 of file browser.c.

char OldLastDir[PATH_MAX] = ""
static

Definition at line 107 of file browser.c.

char LastDir[PATH_MAX] = ""
static

Definition at line 108 of file browser.c.