NeoMutt  2025-12-11-1039-g550ac6
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
Browser Function API

Prototype for a Browser Function. More...

Functions

static int op_browser_new_file (struct BrowserPrivateData *priv, const struct KeyEvent *event)
 Select a new file in this directory - Implements browser_function_t -.
static int op_browser_subscribe (struct BrowserPrivateData *priv, const struct KeyEvent *event)
 Subscribe to current mbox (IMAP/NNTP only) - Implements browser_function_t -.
static int op_browser_tell (struct BrowserPrivateData *priv, const struct KeyEvent *event)
 Display the currently selected file's name - Implements browser_function_t -.
static int op_browser_toggle_lsub (struct BrowserPrivateData *priv, const struct KeyEvent *event)
 Toggle view all/subscribed mailboxes (IMAP only) - Implements browser_function_t -.
static int op_browser_view_file (struct BrowserPrivateData *priv, const struct KeyEvent *event)
 View file - Implements browser_function_t -.
static int op_catchup (struct BrowserPrivateData *priv, const struct KeyEvent *event)
 Mark all articles in newsgroup as read - Implements browser_function_t -.
static int op_change_directory (struct BrowserPrivateData *priv, const struct KeyEvent *event)
 Change directories - Implements browser_function_t -.
static int op_create_mailbox (struct BrowserPrivateData *priv, const struct KeyEvent *event)
 Create a new mailbox (IMAP only) - Implements browser_function_t -.
static int op_delete_mailbox (struct BrowserPrivateData *priv, const struct KeyEvent *event)
 Delete the current mailbox (IMAP only) - Implements browser_function_t -.
static int op_browser_limit (struct BrowserPrivateData *priv, const struct KeyEvent *event)
 Limit the browser - Implements browser_function_t -.
static int op_quit (struct BrowserPrivateData *priv, const struct KeyEvent *event)
 Save changes and exit this dialog - Implements browser_function_t -.
static int op_jump (struct BrowserPrivateData *priv, const struct KeyEvent *event)
 Jump to an index number - Implements browser_function_t -.
static int op_generic_select_entry (struct BrowserPrivateData *priv, const struct KeyEvent *event)
 Select the current entry - Implements browser_function_t -.
static int op_load_active (struct BrowserPrivateData *priv, const struct KeyEvent *event)
 Load list of all newsgroups from NNTP server - Implements browser_function_t -.
static int op_mailbox_list (struct BrowserPrivateData *priv, const struct KeyEvent *event)
 List mailboxes with new mail - Implements browser_function_t -.
static int op_rename_mailbox (struct BrowserPrivateData *priv, const struct KeyEvent *event)
 Rename the current mailbox (IMAP only) - Implements browser_function_t -.
static int op_sort (struct BrowserPrivateData *priv, const struct KeyEvent *event)
 Sort messages - Implements browser_function_t -.
static int op_subscribe_pattern (struct BrowserPrivateData *priv, const struct KeyEvent *event)
 Subscribe to newsgroups matching a pattern - Implements browser_function_t -.
static int op_toggle_mailboxes (struct BrowserPrivateData *priv, const struct KeyEvent *event)
 Toggle whether to browse mailboxes or all files - Implements browser_function_t -.

Detailed Description

Prototype for a Browser Function.

Parameters
privPrivate Browser data
eventEvent to process
Return values
enumFunctionRetval
Precondition
priv is not NULL
event is not NULL

Function Documentation

◆ op_browser_new_file()

int op_browser_new_file ( struct BrowserPrivateData * priv,
const struct KeyEvent * event )
static

Select a new file in this directory - Implements browser_function_t -.

Definition at line 224 of file functions.c.

225{
227 struct Buffer *buf = buf_pool_get();
228 buf_printf(buf, "%s/", buf_string(&mod_data->last_dir));
229
230 struct FileCompletionData cdata = { false, priv->mailbox, NULL, NULL, NULL };
231 const int rc = mw_get_field(_("New file name: "), buf, MUTT_COMP_NONE,
232 HC_FILE, &CompleteMailboxOps, &cdata);
233 if (rc != 0)
234 {
235 buf_pool_release(&buf);
236 return FR_NO_ACTION;
237 }
238
239 buf_copy(priv->file, buf);
240 buf_pool_release(&buf);
241 priv->done = true;
242 return FR_DONE;
243}
const struct CompleteOps CompleteMailboxOps
Auto-Completion of Files / Mailboxes.
Definition complete.c:159
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:168
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition buffer.c:607
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
@ FR_DONE
Exit the Dialog.
Definition dispatcher.h:36
@ FR_NO_ACTION
Valid function - no action performed.
Definition dispatcher.h:38
@ MUTT_COMP_NONE
No flags are set.
Definition wdata.h:46
int mw_get_field(const char *prompt, struct Buffer *buf, CompletionFlags complete, enum HistoryClass hclass, const struct CompleteOps *comp_api, void *cdata)
Ask the user for a string -.
Definition window.c:502
@ HC_FILE
Files.
Definition lib.h:59
@ MODULE_ID_BROWSER
ModuleBrowser, Mailbox Browser
Definition module_api.h:52
#define _(a)
Definition message.h:28
void * neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
Get the private data for a Module.
Definition neomutt.c:666
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
Browser private Module data.
Definition module_data.h:32
struct Buffer last_dir
Browser: previous selected directory.
Definition module_data.h:35
bool done
Should we close the Dialog?
struct Mailbox * mailbox
Mailbox.
struct Buffer * file
Buffer for the result.
String manipulation buffer.
Definition buffer.h:36
Input for the file completion function.
Definition curs_lib.h:39
Container for Accounts, Notifications.
Definition neomutt.h:41
Here is the call graph for this function:

◆ op_browser_subscribe()

int op_browser_subscribe ( struct BrowserPrivateData * priv,
const struct KeyEvent * event )
static

Subscribe to current mbox (IMAP/NNTP only) - Implements browser_function_t -.

This function handles:

  • OP_BROWSER_SUBSCRIBE
  • OP_BROWSER_UNSUBSCRIBE

Supports repeat-count: 5<subscribe> operates on the current entry and the next 4. Overruns are silently capped at the end of the list.

Definition at line 304 of file functions.c.

305{
307 const bool subscribe = (event->op == OP_BROWSER_SUBSCRIBE);
308 const bool tagged = priv->menu->tag_prefix && (priv->menu->num_tagged > 0);
309
310 if (ARRAY_EMPTY(&priv->state.entry))
311 {
312 mutt_error(OptNews ? _("No newsgroups match the browser limit") :
313 _("There are no mailboxes"));
314 return FR_ERROR;
315 }
316
317 struct FolderFilePtrArray ffpa = ARRAY_HEAD_INITIALIZER;
318 browser_add_selection(&ffpa, &priv->state, priv->menu, tagged, event->count);
319 if (ARRAY_EMPTY(&ffpa))
320 {
321 ARRAY_FREE(&ffpa);
322 return FR_NO_ACTION;
323 }
324 const int num = ARRAY_SIZE(&ffpa);
325
326 if (OptNews)
327 {
328 struct NntpAccountData *adata = mod_data->current_news_srv;
329 int rc = nntp_newsrc_parse(adata);
330 if (rc < 0)
331 {
332 ARRAY_FREE(&ffpa);
333 return FR_ERROR;
334 }
335
336 browser_apply_subscribe_nntp(&ffpa, adata, subscribe);
337
338 if (!tagged)
339 {
340 const int index = menu_get_index(priv->menu);
341 const int next = index + num;
342 if (next < ARRAY_SIZE(&priv->state.entry))
343 menu_set_index(priv->menu, next);
344 }
345
350 }
351 else
352 {
353 browser_apply_subscribe_imap(&ffpa, subscribe);
354 }
355
356 ARRAY_FREE(&ffpa);
357 return FR_SUCCESS;
358}
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition array.h:74
#define ARRAY_SIZE(head)
The number of elements stored.
Definition array.h:87
#define ARRAY_FREE(head)
Release all memory.
Definition array.h:209
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition array.h:58
static void browser_apply_subscribe_imap(struct FolderFilePtrArray *ffpa, bool subscribe)
Subscribe/unsubscribe to IMAP mailboxes.
Definition functions.c:275
static void browser_apply_subscribe_nntp(struct FolderFilePtrArray *ffpa, struct NntpAccountData *adata, bool subscribe)
Subscribe/unsubscribe to NNTP newsgroups.
Definition functions.c:251
static int browser_add_selection(struct FolderFilePtrArray *ffpa, struct BrowserState *state, struct Menu *menu, bool tagged, int count)
Build a working set of FolderFile pointers for an action.
Definition functions.c:183
@ FR_SUCCESS
Valid function - successfully performed.
Definition dispatcher.h:40
@ FR_ERROR
Valid function - error occurred.
Definition dispatcher.h:39
bool OptNews
(pseudo) used to change reader mode
Definition globals.c:53
#define mutt_error(...)
Definition logging2.h:94
void menu_queue_redraw(struct Menu *menu, MenuRedrawFlags redraw)
Queue a request for a redraw.
Definition menu.c:177
int menu_get_index(struct Menu *menu)
Get the current selection in the Menu.
Definition menu.c:153
@ MENU_REDRAW_FULL
Redraw everything.
Definition lib.h:64
MenuRedrawFlags menu_set_index(struct Menu *menu, int index)
Set the current selection in the Menu.
Definition menu.c:167
@ MODULE_ID_NNTP
ModuleNntp, Nntp
Definition module_api.h:83
void nntp_clear_cache(struct NntpAccountData *adata)
Clear the NNTP cache.
Definition newsrc.c:852
int nntp_newsrc_parse(struct NntpAccountData *adata)
Parse .newsrc file.
Definition newsrc.c:165
void nntp_newsrc_close(struct NntpAccountData *adata)
Unlock and close .newsrc file.
Definition newsrc.c:121
int nntp_newsrc_update(struct NntpAccountData *adata)
Update .newsrc file.
Definition newsrc.c:446
void * adata
Private data (for Mailbox backends).
Definition account.h:42
struct Menu * menu
Menu.
struct BrowserState state
State containing list of files/dir/mailboxes.
struct BrowserEntryArray entry
Array of files / dirs / mailboxes.
Definition lib.h:149
int count
Optional count prefix, e.g. 3 for 3j.
Definition get.h:78
int num_tagged
Number of tagged entries.
Definition lib.h:101
bool tag_prefix
User has pressed <tag-prefix>.
Definition lib.h:92
NNTP-specific Account data -.
Definition adata.h:36
Nntp private Module data.
Definition module_data.h:30
struct NntpAccountData * current_news_srv
Current NNTP news server.
Definition module_data.h:32
Here is the call graph for this function:

◆ op_browser_tell()

int op_browser_tell ( struct BrowserPrivateData * priv,
const struct KeyEvent * event )
static

Display the currently selected file's name - Implements browser_function_t -.

Definition at line 363 of file functions.c.

364{
365 int index = menu_get_index(priv->menu);
366 if (ARRAY_EMPTY(&priv->state.entry))
367 return FR_ERROR;
368
369 struct FolderFile *ff = ARRAY_GET(&priv->state.entry, index);
371 struct Buffer *path = buf_pool_get();
372 if (priv->state.is_mailbox_list)
373 {
374 buf_strcpy(path, ff->name);
375 expand_path(path, false);
376 }
377 else if (ff->local)
378 {
379 buf_concat_path(path, buf_string(&mod_data->last_dir), ff->name);
380 }
381 else
382 {
383 buf_strcpy(path, ff->name);
384 }
385
386 if (!ff->local)
387 {
388 struct Url *url = url_parse(buf_string(path));
389 if (url)
390 {
392 url_tobuffer(url, path, U_NONE);
393 url_free(&url);
394 }
395 }
396
399 return FR_SUCCESS;
400}
#define ARRAY_GET(head, idx)
Return the element at index.
Definition array.h:109
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:89
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:401
size_t buf_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition buffer.c:515
#define mutt_message(...)
Definition logging2.h:93
void expand_path(struct Buffer *buf, bool regex)
Create the canonical path.
Definition muttlib.c:122
bool is_mailbox_list
Viewing mailboxes.
Definition lib.h:152
Browser entry representing a folder/dir.
Definition lib.h:82
char * name
Name of file/dir/mailbox.
Definition lib.h:90
bool local
Folder is on local filesystem.
Definition lib.h:103
A parsed URL proto://user:password@host:port/path?a=1&b=2.
Definition url.h:69
char * path
Path.
Definition url.h:75
struct Url * url_parse(const char *src)
Fill in Url.
Definition url.c:242
void url_free(struct Url **ptr)
Free the contents of a URL.
Definition url.c:124
int url_tobuffer(const struct Url *url, struct Buffer *buf, uint8_t flags)
Output the URL string for a given Url object.
Definition url.c:361
#define U_NONE
No flags are set for URL parsing.
Definition url.h:49
Here is the call graph for this function:

◆ op_browser_toggle_lsub()

int op_browser_toggle_lsub ( struct BrowserPrivateData * priv,
const struct KeyEvent * event )
static

Toggle view all/subscribed mailboxes (IMAP only) - Implements browser_function_t -.

Definition at line 405 of file functions.c.

406{
407 bool_str_toggle(NeoMutt->sub, "imap_list_subscribed", NULL);
408
409 const bool c_imap_list_subscribed = cs_subset_bool(NeoMutt->sub, "imap_list_subscribed");
410 mutt_message("set imap_list_subscribed = %s", c_imap_list_subscribed ? "yes" : "no");
411
412 mutt_unget_op(OP_CHECK_NEW);
413 return FR_SUCCESS;
414}
int bool_str_toggle(struct ConfigSubset *sub, const char *name, struct Buffer *err)
Toggle the value of a bool.
Definition bool.c:231
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
void mutt_unget_op(int op)
Return an operation to the input buffer.
Definition get.c:159
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
Here is the call graph for this function:

◆ op_browser_view_file()

int op_browser_view_file ( struct BrowserPrivateData * priv,
const struct KeyEvent * event )
static

View file - Implements browser_function_t -.

Definition at line 419 of file functions.c.

420{
422 if (ARRAY_EMPTY(&priv->state.entry))
423 {
424 mutt_error(_("No files match the browser limit"));
425 return FR_ERROR;
426 }
427
428 int index = menu_get_index(priv->menu);
429 struct FolderFile *ff = ARRAY_GET(&priv->state.entry, index);
430 if (ff->selectable)
431 {
432 buf_strcpy(priv->file, ff->name);
433 priv->done = true;
434 return FR_DONE;
435 }
436 else if (S_ISDIR(ff->mode) ||
437 (S_ISLNK(ff->mode) && link_is_dir(buf_string(&mod_data->last_dir), ff->name)))
438 {
439 mutt_error(_("Can't view a directory"));
440 return FR_ERROR;
441 }
442 else
443 {
444 struct Buffer *path = buf_pool_get();
445 buf_concat_path(path, buf_string(&mod_data->last_dir), ff->name);
446 struct Body *b = mutt_make_file_attach(buf_string(path), NeoMutt->sub);
447 if (b)
448 {
449 mutt_view_attachment(NULL, b, MUTT_VA_REGULAR, NULL, NULL, priv->menu->win);
450 mutt_body_free(&b);
452 }
453 else
454 {
455 mutt_error(_("Error trying to view file"));
456 }
457 buf_pool_release(&path);
458 }
459 return FR_ERROR;
460}
bool link_is_dir(const char *folder, const char *path)
Does this symlink point to a directory?
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition body.c:58
int mutt_view_attachment(FILE *fp, struct Body *b, enum ViewAttachMode mode, struct Email *e, struct AttachCtx *actx, struct MuttWindow *win)
View an attachment.
@ MUTT_VA_REGULAR
View using default method.
Definition mutt_attach.h:45
struct Body * mutt_make_file_attach(const char *path, struct ConfigSubset *sub)
Create a file attachment.
Definition sendlib.c:618
The body of an email.
Definition body.h:36
bool selectable
Folder can be selected.
Definition lib.h:100
mode_t mode
File permissions.
Definition lib.h:83
struct MuttWindow * win
Window holding the Menu.
Definition lib.h:94
Here is the call graph for this function:

◆ op_catchup()

int op_catchup ( struct BrowserPrivateData * priv,
const struct KeyEvent * event )
static

Mark all articles in newsgroup as read - Implements browser_function_t -.

This function handles:

  • OP_CATCHUP
  • OP_UNCATCHUP

Supports repeat-count: 5<catchup> operates on the current entry and the next 4. Overruns are silently capped at the end of the list.

Definition at line 502 of file functions.c.

503{
505 if (!OptNews)
506 return FR_NOT_IMPL;
507
508 int rc = nntp_newsrc_parse(mod_data->current_news_srv);
509 if (rc < 0)
510 return FR_ERROR;
511
512 if (ARRAY_EMPTY(&priv->state.entry))
513 return FR_ERROR;
514
515 const bool tagged = priv->menu->tag_prefix && (priv->menu->num_tagged > 0);
516
517 struct FolderFilePtrArray ffpa = ARRAY_HEAD_INITIALIZER;
518 browser_add_selection(&ffpa, &priv->state, priv->menu, tagged, event->count);
519 if (ARRAY_EMPTY(&ffpa))
520 {
521 ARRAY_FREE(&ffpa);
522 return FR_NO_ACTION;
523 }
524 const int num = ARRAY_SIZE(&ffpa);
525
526 struct NntpMboxData *mdata = browser_apply_catchup(&ffpa, priv->mailbox,
527 mod_data->current_news_srv,
528 (event->op == OP_CATCHUP));
529 ARRAY_FREE(&ffpa);
530
531 if (mdata)
532 {
534 if (!tagged)
535 {
536 const int next = menu_get_index(priv->menu) + num;
537 if (next < priv->menu->max)
538 menu_set_index(priv->menu, next);
539 }
540 }
541
543
545 return FR_ERROR;
546}
static struct NntpMboxData * browser_apply_catchup(struct FolderFilePtrArray *ffpa, struct Mailbox *m, struct NntpAccountData *adata, bool up)
(Un)catchup a working set of newsgroups
Definition functions.c:470
@ FR_NOT_IMPL
Invalid function - feature not enabled.
Definition dispatcher.h:37
@ MENU_REDRAW_INDEX
Redraw the index.
Definition lib.h:61
int op
Function opcode, e.g. OP_HELP.
Definition get.h:77
void * mdata
Driver specific data.
Definition mailbox.h:134
NNTP-specific Mailbox data -.
Definition mdata.h:34
Here is the call graph for this function:

◆ op_change_directory()

int op_change_directory ( struct BrowserPrivateData * priv,
const struct KeyEvent * event )
static

Change directories - Implements browser_function_t -.

This function handles:

  • OP_CHANGE_DIRECTORY
  • OP_GOTO_HOME
  • OP_GOTO_PARENT
  • OP_GOTO_ROOT

Definition at line 557 of file functions.c.

558{
560 if (OptNews)
561 return FR_NOT_IMPL;
562
563 struct Buffer *buf = buf_pool_get();
564 buf_copy(buf, &mod_data->last_dir);
565 if (!priv->state.imap_browse)
566 {
567 /* add '/' at the end of the directory name if not already there */
568 size_t len = buf_len(buf);
569 if ((len > 0) && (buf_string(&mod_data->last_dir)[len - 1] != '/'))
570 buf_addch(buf, '/');
571 }
572
573 const int op = event->op;
574 if (op == OP_CHANGE_DIRECTORY)
575 {
576 struct FileCompletionData cdata = { false, priv->mailbox, NULL, NULL, NULL };
577 int rc = mw_get_field(_("Chdir to: "), buf, MUTT_COMP_NONE, HC_FILE,
578 &CompleteMailboxOps, &cdata);
579 if ((rc != 0) && buf_is_empty(buf))
580 {
581 buf_pool_release(&buf);
582 return FR_NO_ACTION;
583 }
584 }
585 else if (op == OP_GOTO_PARENT)
586 {
587 const int count = MAX(event->count, 1);
588 for (int i = 0; i < count; i++)
589 {
590 char prev[PATH_MAX] = { 0 };
591 mutt_str_copy(prev, buf_string(buf), sizeof(prev));
592 mutt_get_parent_path(buf_string(buf), buf->data, buf->dsize);
593 if (mutt_str_equal(buf_string(buf), prev))
594 break;
595 }
596 }
597 else if (op == OP_GOTO_HOME)
598 {
600 }
601 else if (op == OP_GOTO_ROOT)
602 {
603 buf_strcpy(buf, "/");
604 }
605
606 if (!buf_is_empty(buf))
607 {
608 priv->state.is_mailbox_list = false;
609 expand_path(buf, false);
610 if (imap_path_probe(buf_string(buf), NULL) == MUTT_IMAP)
611 {
612 buf_copy(&mod_data->last_dir, buf);
613 destroy_state(&priv->state);
614 init_state(&priv->state);
615 priv->state.imap_browse = true;
616 imap_browse(buf_string(&mod_data->last_dir), &priv->state);
617 browser_sort(&priv->state);
618 browser_highlight_default(&priv->state, priv->menu);
619 init_menu(&priv->state, priv->menu, priv->mailbox, priv->sbar);
620 }
621 else
622 {
623 if (buf_string(buf)[0] != '/')
624 {
625 /* in case dir is relative, make it relative to LastDir,
626 * not current working dir */
627 struct Buffer *tmp = buf_pool_get();
628 buf_concat_path(tmp, buf_string(&mod_data->last_dir), buf_string(buf));
629 buf_copy(buf, tmp);
630 buf_pool_release(&tmp);
631 }
632 /* Resolve path from <chdir>
633 * Avoids buildup such as /a/b/../../c
634 * Symlinks are always unraveled to keep code simple */
635 if (mutt_path_realpath(buf) == 0)
636 {
637 mutt_perror("%s", buf_string(buf));
638 buf_pool_release(&buf);
639 return FR_ERROR;
640 }
641
642 struct stat st = { 0 };
643 if (stat(buf_string(buf), &st) == 0)
644 {
645 if (S_ISDIR(st.st_mode))
646 {
647 destroy_state(&priv->state);
648 if (examine_directory(priv->mailbox, priv->menu, &priv->state,
649 buf_string(buf), buf_string(priv->prefix)) == 0)
650 {
651 buf_copy(&mod_data->last_dir, buf);
652 }
653 else
654 {
655 mutt_error(_("Error scanning directory"));
656 if (examine_directory(priv->mailbox, priv->menu, &priv->state,
657 buf_string(&mod_data->last_dir),
658 buf_string(priv->prefix)) == -1)
659 {
660 priv->done = true;
661 return FR_ERROR;
662 }
663 }
664 browser_highlight_default(&priv->state, priv->menu);
665 init_menu(&priv->state, priv->menu, priv->mailbox, priv->sbar);
666 }
667 else
668 {
669 mutt_error(_("%s is not a directory"), buf_string(buf));
670 }
671 }
672 else
673 {
674 mutt_perror("%s", buf_string(buf));
675 }
676 }
677 }
678 buf_pool_release(&buf);
679 return FR_ERROR;
680}
int imap_browse(const char *path, struct BrowserState *state)
IMAP hook into the folder browser.
Definition browse.c:196
void destroy_state(struct BrowserState *state)
Free the BrowserState.
Definition functions.c:154
void browser_sort(struct BrowserState *state)
Sort the entries in the browser.
Definition sort.c:186
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition buffer.c:497
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:298
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition buffer.c:248
@ MUTT_IMAP
'IMAP' Mailbox type
Definition mailbox.h:49
int examine_directory(struct Mailbox *m, struct Menu *menu, struct BrowserState *state, const char *dirname, const char *prefix)
Get list of all files/newsgroups matching the browser limit.
void init_menu(struct BrowserState *state, struct Menu *menu, struct Mailbox *m, struct MuttWindow *sbar)
Set up a new menu.
void init_state(struct BrowserState *state)
Initialise a browser state.
void browser_highlight_default(struct BrowserState *state, struct Menu *menu)
Decide which browser item should be highlighted.
#define mutt_perror(...)
Definition logging2.h:95
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox?
Definition imap.c:2683
#define MAX(a, b)
Return the maximum of two values.
Definition memory.h:38
size_t mutt_path_realpath(struct Buffer *path)
Resolve path, unraveling symlinks.
Definition path.c:377
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:666
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination).
Definition string.c:587
#define PATH_MAX
Definition mutt.h:49
void mutt_get_parent_path(const char *path, char *buf, size_t buflen)
Find the parent of a path (or mailbox).
Definition muttlib.c:875
struct Buffer * prefix
Folder prefix string.
struct MuttWindow * sbar
Status Bar.
bool imap_browse
IMAP folder.
Definition lib.h:150
size_t dsize
Length of data.
Definition buffer.h:39
char * data
Pointer to data.
Definition buffer.h:37
char * home_dir
User's home directory.
Definition neomutt.h:55
Here is the call graph for this function:

◆ op_create_mailbox()

int op_create_mailbox ( struct BrowserPrivateData * priv,
const struct KeyEvent * event )
static

Create a new mailbox (IMAP only) - Implements browser_function_t -.

Definition at line 685 of file functions.c.

686{
688 if (!priv->state.imap_browse)
689 {
690 mutt_error(_("Create is only supported for IMAP mailboxes"));
691 return FR_ERROR;
692 }
693
694 if (imap_mailbox_create(buf_string(&mod_data->last_dir)) != 0)
695 return FR_ERROR;
696
697 /* TODO: find a way to detect if the new folder would appear in
698 * this window, and insert it without starting over. */
699 destroy_state(&priv->state);
700 init_state(&priv->state);
701 priv->state.imap_browse = true;
702 imap_browse(buf_string(&mod_data->last_dir), &priv->state);
703 browser_sort(&priv->state);
704 browser_highlight_default(&priv->state, priv->menu);
705 init_menu(&priv->state, priv->menu, priv->mailbox, priv->sbar);
706
707 return FR_SUCCESS;
708}
int imap_mailbox_create(const char *path)
Create a new IMAP mailbox.
Definition browse.c:393
Here is the call graph for this function:

◆ op_delete_mailbox()

int op_delete_mailbox ( struct BrowserPrivateData * priv,
const struct KeyEvent * event )
static

Delete the current mailbox (IMAP only) - Implements browser_function_t -.

Supports repeat-count: 5<delete-mailbox> deletes the current entry and the next 4. Overruns are silently capped at the end of the list.

Definition at line 759 of file functions.c.

760{
761 if (ARRAY_EMPTY(&priv->state.entry))
762 return FR_ERROR;
763
764 const bool tagged = priv->menu->tag_prefix && (priv->menu->num_tagged > 0);
765
766 struct FolderFilePtrArray ffpa = ARRAY_HEAD_INITIALIZER;
767 browser_add_selection(&ffpa, &priv->state, priv->menu, tagged, event->count);
768 if (ARRAY_EMPTY(&ffpa))
769 {
770 ARRAY_FREE(&ffpa);
771 return FR_NO_ACTION;
772 }
773
774 // Pre-flight validation
775 struct FolderFile **ffp = NULL;
776 ARRAY_FOREACH(ffp, &ffpa)
777 {
778 struct FolderFile *ff = *ffp;
779 if (!ff->imap)
780 {
781 mutt_error(_("Delete is only supported for IMAP mailboxes"));
782 ARRAY_FREE(&ffpa);
783 return FR_ERROR;
784 }
785 // TODO(sileht): It could be better to select INBOX instead. But I
786 // don't want to manipulate Mailboxes/mailbox->account here for now.
787 // Let's just protect neomutt against crash for now. #1417
788 if (mutt_str_equal(mailbox_path(priv->mailbox), ff->name))
789 {
790 mutt_error(_("Can't delete currently selected mailbox"));
791 ARRAY_FREE(&ffpa);
792 return FR_ERROR;
793 }
794 }
795
796 const int num = ARRAY_SIZE(&ffpa);
797 char msg[128] = { 0 };
798 if (num > 1)
799 {
800 snprintf(msg, sizeof(msg), _("Really delete %d tagged mailboxes?"), num);
801 }
802 else
803 {
804 struct FolderFile *ff = *ARRAY_FIRST(&ffpa);
805 snprintf(msg, sizeof(msg), _("Really delete mailbox \"%s\"?"), ff->name);
806 }
807 if (query_yesorno(msg, MUTT_NO) != MUTT_YES)
808 {
809 mutt_message(_("Mailbox not deleted"));
810 ARRAY_FREE(&ffpa);
811 return FR_NO_ACTION;
812 }
813
814 int failed = 0;
815 const int deleted = browser_apply_delete_mailbox(&ffpa, &priv->state,
816 priv->mailbox, &failed);
817 ARRAY_FREE(&ffpa);
818
819 if (failed > 0)
820 mutt_error(_("Mailbox deletion failed"));
821 else if (num > 1)
822 mutt_message(_("%d mailboxes deleted"), deleted);
823 else if (deleted == 1)
824 mutt_message(_("Mailbox deleted"));
825
826 init_menu(&priv->state, priv->menu, priv->mailbox, priv->sbar);
827 return failed ? FR_ERROR : FR_SUCCESS;
828}
#define ARRAY_FIRST(head)
Convenience method to get the first element.
Definition array.h:136
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:223
static int browser_apply_delete_mailbox(struct FolderFilePtrArray *ffpa, struct BrowserState *state, struct Mailbox *m, int *num_failed)
Delete a working set of IMAP mailboxes.
Definition functions.c:721
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition mailbox.h:216
@ MUTT_NO
User answered 'No', or assume 'No'.
Definition quad.h:38
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition quad.h:39
enum QuadOption query_yesorno(const char *prompt, enum QuadOption def)
Ask the user a Yes/No question.
Definition question.c:329
bool imap
This is an IMAP folder.
Definition lib.h:99
Here is the call graph for this function:

◆ op_browser_limit()

int op_browser_limit ( struct BrowserPrivateData * priv,
const struct KeyEvent * event )
static

Limit the browser - Implements browser_function_t -.

Definition at line 833 of file functions.c.

834{
836 const struct Regex *c_browser_limit = cs_subset_regex(NeoMutt->sub, "browser_limit");
837 struct Buffer *buf = buf_pool_get();
838 buf_strcpy(buf, c_browser_limit ? c_browser_limit->pattern : NULL);
839 if (mw_get_field(_("Limit: "), buf, MUTT_COMP_NONE, HC_OTHER, NULL, NULL) != 0)
840 {
841 buf_pool_release(&buf);
842 return FR_NO_ACTION;
843 }
844
845 buf_fix_dptr(buf);
846
847 priv->state.is_mailbox_list = false;
848 /* assume that the user wants to see everything */
849 if (buf_is_empty(buf))
850 buf_strcpy(buf, ".");
851
852 struct Buffer *errmsg = buf_pool_get();
853 int rc = cs_subset_str_string_set(NeoMutt->sub, "browser_limit", buf_string(buf), errmsg);
854 buf_pool_release(&buf);
855 if (CSR_RESULT(rc) != CSR_SUCCESS)
856 {
857 if (!buf_is_empty(errmsg))
858 {
859 mutt_error("%s", buf_string(errmsg));
860 buf_pool_release(&errmsg);
861 }
862 return FR_ERROR;
863 }
864 buf_pool_release(&errmsg);
865
866 destroy_state(&priv->state);
867 if (priv->state.imap_browse)
868 {
869 init_state(&priv->state);
870 priv->state.imap_browse = true;
871 imap_browse(buf_string(&mod_data->last_dir), &priv->state);
872 browser_sort(&priv->state);
873 init_menu(&priv->state, priv->menu, priv->mailbox, priv->sbar);
874 }
875 else if (examine_directory(priv->mailbox, priv->menu, &priv->state,
876 buf_string(&mod_data->last_dir), NULL) == 0)
877 {
878 init_menu(&priv->state, priv->menu, priv->mailbox, priv->sbar);
879 }
880 else
881 {
882 mutt_error(_("Error scanning directory"));
883 priv->done = true;
884 return FR_ERROR;
885 }
886 priv->kill_prefix = false;
887 if (ARRAY_EMPTY(&priv->state.entry))
888 {
889 mutt_error(_("No files match the browser limit"));
890 return FR_ERROR;
891 }
892 return FR_SUCCESS;
893}
void buf_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition buffer.c:189
const struct Regex * cs_subset_regex(const struct ConfigSubset *sub, const char *name)
Get a regex config item by name.
Definition helpers.c:217
#define CSR_RESULT(x)
Extract the result code from CSR_* flags.
Definition set.h:53
#define CSR_SUCCESS
Action completed successfully.
Definition set.h:33
@ HC_OTHER
Miscellaneous strings.
Definition lib.h:61
bool kill_prefix
Prefix is in use.
Cached regular expression.
Definition regex3.h:85
char * pattern
printable version
Definition regex3.h:86
int cs_subset_str_string_set(const struct ConfigSubset *sub, const char *name, const char *value, struct Buffer *err)
Set a config item by string.
Definition subset.c:392
Here is the call graph for this function:

◆ op_quit()

int op_quit ( struct BrowserPrivateData * priv,
const struct KeyEvent * event )
static

Save changes and exit this dialog - Implements browser_function_t -.

Definition at line 898 of file functions.c.

899{
901 if (priv->multiple)
902 {
903 char **tfiles = NULL;
904
905 if (priv->menu->tag_prefix && (priv->menu->num_tagged != 0))
906 {
907 *priv->numfiles = priv->menu->num_tagged;
908 tfiles = MUTT_MEM_CALLOC(*priv->numfiles, char *);
909 size_t j = 0;
910 struct FolderFile *ff = NULL;
911 ARRAY_FOREACH(ff, &priv->state.entry)
912 {
913 if (ff->tagged)
914 {
915 struct Buffer *buf = buf_pool_get();
916 buf_concat_path(buf, buf_string(&mod_data->last_dir), ff->name);
917 expand_path(buf, false);
918 tfiles[j++] = buf_strdup(buf);
919 buf_pool_release(&buf);
920 }
921 }
922 *priv->files = tfiles;
923 }
924 else if (!buf_is_empty(priv->file)) /* no tagged entries. return selected entry */
925 {
926 *priv->numfiles = 1;
927 tfiles = MUTT_MEM_CALLOC(*priv->numfiles, char *);
928 expand_path(priv->file, false);
929 tfiles[0] = buf_strdup(priv->file);
930 *priv->files = tfiles;
931 }
932 }
933
934 priv->done = true;
935 return FR_DONE;
936}
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition buffer.c:577
#define MUTT_MEM_CALLOC(n, type)
Definition memory.h:52
char *** files
Array of selected files.
int * numfiles
Number of selected files.
bool multiple
Allow multiple selections.
bool tagged
Folder is tagged.
Definition lib.h:106
Here is the call graph for this function:

◆ op_jump()

int op_jump ( struct BrowserPrivateData * priv,
const struct KeyEvent * event )
static

Jump to an index number - Implements browser_function_t -.

Definition at line 941 of file functions.c.

942{
943 int num = event->count;
944
945 if (num == 0)
946 return FR_NO_ACTION;
947
948 struct Menu *menu = priv->menu;
949
950 if ((num < 1) || (num > menu->max))
951 {
952 mutt_warning(_("Invalid message number"));
953 return FR_ERROR;
954 }
955
956 menu_set_index(menu, num - 1); // Num is 1-based
957 return FR_SUCCESS;
958}
#define mutt_warning(...)
Definition logging2.h:92
Definition lib.h:86
int max
Number of entries in the menu.
Definition lib.h:88
Here is the call graph for this function:

◆ op_generic_select_entry()

int op_generic_select_entry ( struct BrowserPrivateData * priv,
const struct KeyEvent * event )
static

Select the current entry - Implements browser_function_t -.

This function handles:

  • OP_DESCEND_DIRECTORY
  • OP_GENERIC_SELECT_ENTRY

Definition at line 967 of file functions.c.

968{
969 if (event->count > 0)
970 return op_jump(priv, event);
971
973 if (ARRAY_EMPTY(&priv->state.entry))
974 {
975 mutt_warning(_("No files match the browser limit"));
976 return FR_ERROR;
977 }
978
979 const int op = event->op;
980 int index = menu_get_index(priv->menu);
981 struct FolderFile *ff = ARRAY_GET(&priv->state.entry, index);
982 if ((priv->menu->tag_prefix) && (op == OP_GENERIC_SELECT_ENTRY))
983 {
984 // Do nothing
985 }
986 else if (S_ISDIR(ff->mode) ||
987 (S_ISLNK(ff->mode) && link_is_dir(buf_string(&mod_data->last_dir), ff->name)) ||
988 ff->inferiors)
989 {
990 /* make sure this isn't a MH or maildir mailbox */
991 struct Buffer *buf = buf_pool_get();
992 if (priv->state.is_mailbox_list)
993 {
994 buf_strcpy(buf, ff->name);
995 expand_path(buf, false);
996 }
997 else if (priv->state.imap_browse)
998 {
999 buf_strcpy(buf, ff->name);
1000 }
1001 else
1002 {
1003 buf_concat_path(buf, buf_string(&mod_data->last_dir), ff->name);
1004 }
1005
1006 enum MailboxType type = mx_path_probe(buf_string(buf));
1007 buf_pool_release(&buf);
1008
1009 if ((op == OP_DESCEND_DIRECTORY) || (type == MUTT_MAILBOX_ERROR) ||
1010 (type == MUTT_UNKNOWN) || ff->inferiors)
1011 {
1012 /* save the old directory */
1013 buf_copy(priv->old_last_dir, &mod_data->last_dir);
1014
1015 if (mutt_str_equal(ff->name, ".."))
1016 {
1017 size_t lastdirlen = buf_len(&mod_data->last_dir);
1018 if ((lastdirlen > 1) &&
1019 mutt_str_equal("..", buf_string(&mod_data->last_dir) + lastdirlen - 2))
1020 {
1021 buf_addstr(&mod_data->last_dir, "/..");
1022 }
1023 else
1024 {
1025 char *p = NULL;
1026 if (lastdirlen > 1)
1027 p = strrchr(mod_data->last_dir.data + 1, '/');
1028
1029 if (p)
1030 {
1031 *p = '\0';
1032 buf_fix_dptr(&mod_data->last_dir);
1033 }
1034 else
1035 {
1036 if (buf_string(&mod_data->last_dir)[0] == '/')
1037 buf_strcpy(&mod_data->last_dir, "/");
1038 else
1039 buf_addstr(&mod_data->last_dir, "/..");
1040 }
1041 }
1042 }
1043 else if (priv->state.is_mailbox_list)
1044 {
1045 buf_strcpy(&mod_data->last_dir, ff->name);
1046 expand_path(&mod_data->last_dir, false);
1047 }
1048 else if (priv->state.imap_browse)
1049 {
1050 buf_strcpy(&mod_data->last_dir, ff->name);
1051 /* tack on delimiter here */
1052
1053 /* special case "" needs no delimiter */
1054 struct Url *url = url_parse(ff->name);
1055 if (url && url->path && (ff->delim != '\0'))
1056 {
1057 buf_addch(&mod_data->last_dir, ff->delim);
1058 }
1059 url_free(&url);
1060 }
1061 else
1062 {
1063 struct Buffer *tmp = buf_pool_get();
1064 buf_concat_path(tmp, buf_string(&mod_data->last_dir), ff->name);
1065 buf_copy(&mod_data->last_dir, tmp);
1066 buf_pool_release(&tmp);
1067 }
1068
1069 destroy_state(&priv->state);
1070 if (priv->kill_prefix)
1071 {
1072 buf_reset(priv->prefix);
1073 priv->kill_prefix = false;
1074 }
1075 priv->state.is_mailbox_list = false;
1076 if (priv->state.imap_browse)
1077 {
1078 init_state(&priv->state);
1079 priv->state.imap_browse = true;
1080 imap_browse(buf_string(&mod_data->last_dir), &priv->state);
1081 browser_sort(&priv->state);
1082 }
1083 else
1084 {
1085 if (examine_directory(priv->mailbox, priv->menu, &priv->state,
1086 buf_string(&mod_data->last_dir),
1087 buf_string(priv->prefix)) == -1)
1088 {
1089 /* try to restore the old values */
1090 buf_copy(&mod_data->last_dir, priv->old_last_dir);
1091 if (examine_directory(priv->mailbox, priv->menu, &priv->state,
1092 buf_string(&mod_data->last_dir),
1093 buf_string(priv->prefix)) == -1)
1094 {
1095 buf_strcpy(&mod_data->last_dir, NeoMutt->home_dir);
1096 priv->done = true;
1097 return FR_DONE;
1098 }
1099 }
1100 /* resolve paths navigated from GUI */
1101 if (mutt_path_realpath(&mod_data->last_dir) == 0)
1102 return FR_ERROR;
1103 }
1104
1105 browser_highlight_default(&priv->state, priv->menu);
1106 init_menu(&priv->state, priv->menu, priv->mailbox, priv->sbar);
1107 priv->goto_swapper[0] = '\0';
1108 return FR_SUCCESS;
1109 }
1110 }
1111 else if (op == OP_DESCEND_DIRECTORY)
1112 {
1113 mutt_error(_("%s is not a directory"), ARRAY_GET(&priv->state.entry, index)->name);
1114 return FR_ERROR;
1115 }
1116
1117 if (priv->state.is_mailbox_list || OptNews)
1118 {
1119 buf_strcpy(priv->file, ff->name);
1120 expand_path(priv->file, false);
1121 }
1122 else if (priv->state.imap_browse)
1123 {
1124 buf_strcpy(priv->file, ff->name);
1125 }
1126 else
1127 {
1128 buf_concat_path(priv->file, buf_string(&mod_data->last_dir), ff->name);
1129 }
1130
1131 return op_quit(priv, event);
1132}
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition buffer.c:233
MailboxType
Supported mailbox formats.
Definition mailbox.h:40
@ MUTT_MAILBOX_ERROR
Error occurred examining Mailbox.
Definition mailbox.h:42
@ MUTT_UNKNOWN
Mailbox wasn't recognised.
Definition mailbox.h:43
static int op_quit(struct AliasFunctionData *fdata, const struct KeyEvent *event)
Save changes and exit this dialog - Implements alias_function_t -.
Definition functions.c:308
static int op_jump(struct AliasFunctionData *fdata, const struct KeyEvent *event)
Jump to an index number - Implements alias_function_t -.
Definition functions.c:316
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition mx.c:1326
struct Buffer * old_last_dir
Previous to last dir.
char goto_swapper[PATH_MAX]
Saved path after <goto-folder>.
char delim
Path delimiter.
Definition lib.h:97
bool inferiors
Folder has children.
Definition lib.h:101
Here is the call graph for this function:

◆ op_load_active()

int op_load_active ( struct BrowserPrivateData * priv,
const struct KeyEvent * event )
static

Load list of all newsgroups from NNTP server - Implements browser_function_t -.

Definition at line 1137 of file functions.c.

1138{
1140 if (!OptNews)
1141 return FR_NOT_IMPL;
1142
1143 struct NntpAccountData *adata = mod_data->current_news_srv;
1144
1145 if (nntp_newsrc_parse(adata) < 0)
1146 return FR_ERROR;
1147
1148 for (size_t i = 0; i < adata->groups_num; i++)
1149 {
1150 struct NntpMboxData *mdata = adata->groups_list[i];
1151 if (mdata)
1152 mdata->deleted = true;
1153 }
1154 nntp_active_fetch(adata, true);
1157
1158 destroy_state(&priv->state);
1159 if (priv->state.is_mailbox_list)
1160 {
1161 examine_mailboxes(priv->mailbox, priv->menu, &priv->state);
1162 }
1163 else
1164 {
1165 if (examine_directory(priv->mailbox, priv->menu, &priv->state, NULL, NULL) == -1)
1166 return FR_ERROR;
1167 }
1168 init_menu(&priv->state, priv->menu, priv->mailbox, priv->sbar);
1169 return FR_SUCCESS;
1170}
int examine_mailboxes(struct Mailbox *m, struct Menu *menu, struct BrowserState *state)
Get list of mailboxes/subscribed newsgroups.
int nntp_active_fetch(struct NntpAccountData *adata, bool mark_new)
Fetch list of all newsgroups from server.
Definition nntp.c:2048
struct NntpMboxData ** groups_list
List of newsgroups.
Definition adata.h:60
bool deleted
Newsgroup is deleted.
Definition mdata.h:45
struct NntpAccountData * adata
Account data.
Definition mdata.h:48
Here is the call graph for this function:

◆ op_mailbox_list()

int op_mailbox_list ( struct BrowserPrivateData * priv,
const struct KeyEvent * event )
static

List mailboxes with new mail - Implements browser_function_t -.

Definition at line 1175 of file functions.c.

1176{
1178 return FR_SUCCESS;
1179}
bool mutt_mailbox_list(void)
Show a message with the list of mailboxes with new mail.
Here is the call graph for this function:

◆ op_rename_mailbox()

int op_rename_mailbox ( struct BrowserPrivateData * priv,
const struct KeyEvent * event )
static

Rename the current mailbox (IMAP only) - Implements browser_function_t -.

Definition at line 1184 of file functions.c.

1185{
1187 if (ARRAY_EMPTY(&priv->state.entry))
1188 return FR_ERROR;
1189
1190 int index = menu_get_index(priv->menu);
1191 struct FolderFile *ff = ARRAY_GET(&priv->state.entry, index);
1192 if (!ff->imap)
1193 {
1194 mutt_error(_("Rename is only supported for IMAP mailboxes"));
1195 return FR_ERROR;
1196 }
1197
1198 if (imap_mailbox_rename(ff->name) < 0)
1199 return FR_ERROR;
1200
1201 destroy_state(&priv->state);
1202 init_state(&priv->state);
1203 priv->state.imap_browse = true;
1204 imap_browse(buf_string(&mod_data->last_dir), &priv->state);
1205 browser_sort(&priv->state);
1206 browser_highlight_default(&priv->state, priv->menu);
1207 init_menu(&priv->state, priv->menu, priv->mailbox, priv->sbar);
1208
1209 return FR_SUCCESS;
1210}
int imap_mailbox_rename(const char *path)
Rename a mailbox.
Definition browse.c:448
Here is the call graph for this function:

◆ op_sort()

int op_sort ( struct BrowserPrivateData * priv,
const struct KeyEvent * event )
static

Sort messages - Implements browser_function_t -.

This function handles:

  • OP_SORT
  • OP_SORT_REVERSE

Definition at line 1219 of file functions.c.

1220{
1221 bool resort = true;
1222 int sort = -1;
1223 const int op = event->op;
1224 int reverse = (op == OP_SORT_REVERSE);
1225
1226 switch (mw_multi_choice((reverse) ?
1227 /* L10N: The highlighted letters must match the "Sort" options */
1228 _("Reverse sort by (d)ate, (a)lpha, si(z)e, d(e)scription, (c)ount, ne(w) count, or do(n)'t sort?") :
1229 /* L10N: The highlighted letters must match the "Reverse Sort" options */
1230 _("Sort by (d)ate, (a)lpha, si(z)e, d(e)scription, (c)ount, ne(w) count, or do(n)'t sort?"),
1231 /* L10N: These must match the highlighted letters from "Sort" and "Reverse Sort" */
1232 _("dazecwn")))
1233 {
1234 case -1: /* abort */
1235 resort = false;
1236 break;
1237
1238 case 1: /* (d)ate */
1239 sort = BROWSER_SORT_DATE;
1240 break;
1241
1242 case 2: /* (a)lpha */
1243 sort = BROWSER_SORT_ALPHA;
1244 break;
1245
1246 case 3: /* si(z)e */
1247 sort = BROWSER_SORT_SIZE;
1248 break;
1249
1250 case 4: /* d(e)scription */
1251 sort = BROWSER_SORT_DESC;
1252 break;
1253
1254 case 5: /* (c)ount */
1255 sort = BROWSER_SORT_COUNT;
1256 break;
1257
1258 case 6: /* ne(w) count */
1259 sort = BROWSER_SORT_NEW;
1260 break;
1261
1262 case 7: /* do(n)'t sort */
1263 sort = BROWSER_SORT_UNSORTED;
1264 break;
1265
1266 default:
1267 resort = false;
1268 break;
1269 }
1270
1271 if (!resort)
1272 return FR_NO_ACTION;
1273
1274 sort |= reverse ? SORT_REVERSE : 0;
1275 cs_subset_str_native_set(NeoMutt->sub, "browser_sort", sort, NULL);
1276 browser_sort(&priv->state);
1277 browser_highlight_default(&priv->state, priv->menu);
1279 return FR_SUCCESS;
1280}
@ BROWSER_SORT_ALPHA
Sort by name.
Definition sort.h:31
@ BROWSER_SORT_UNSORTED
Sort into the raw order.
Definition sort.h:37
@ BROWSER_SORT_COUNT
Sort by total message count.
Definition sort.h:32
@ BROWSER_SORT_DATE
Sort by date.
Definition sort.h:33
@ BROWSER_SORT_NEW
Sort by count of new messages.
Definition sort.h:35
@ BROWSER_SORT_SIZE
Sort by size.
Definition sort.h:36
@ BROWSER_SORT_DESC
Sort by description.
Definition sort.h:34
#define SORT_REVERSE
Reverse the order of the sort.
Definition sort.h:40
int mw_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question -.
Definition question.c:62
int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
Definition subset.c:303
Here is the call graph for this function:

◆ op_subscribe_pattern()

int op_subscribe_pattern ( struct BrowserPrivateData * priv,
const struct KeyEvent * event )
static

Subscribe to newsgroups matching a pattern - Implements browser_function_t -.

This function handles:

  • OP_SUBSCRIBE_PATTERN
  • OP_UNSUBSCRIBE_PATTERN

Definition at line 1289 of file functions.c.

1290{
1292 if (!OptNews)
1293 return FR_NOT_IMPL;
1294
1295 struct NntpAccountData *adata = mod_data->current_news_srv;
1296 regex_t rx = { 0 };
1297 int index = menu_get_index(priv->menu);
1298
1299 char tmp2[256] = { 0 };
1300
1301 const int op = event->op;
1302 struct Buffer *buf = buf_pool_get();
1303 if (op == OP_SUBSCRIBE_PATTERN)
1304 snprintf(tmp2, sizeof(tmp2), _("Subscribe pattern: "));
1305 else
1306 snprintf(tmp2, sizeof(tmp2), _("Unsubscribe pattern: "));
1307 /* buf comes from the buffer pool, so defaults to size 1024 */
1308 if ((mw_get_field(tmp2, buf, MUTT_COMP_NONE, HC_PATTERN, &CompletePatternOps, NULL) != 0) ||
1309 buf_is_empty(buf))
1310 {
1311 buf_pool_release(&buf);
1312 return FR_NO_ACTION;
1313 }
1314
1315 int err = REG_COMP(&rx, buf->data, REG_NOSUB);
1316 if (err != 0)
1317 {
1318 regerror(err, &rx, buf->data, buf->dsize);
1319 regfree(&rx);
1320 mutt_error("%s", buf_string(buf));
1321 buf_pool_release(&buf);
1322 return FR_ERROR;
1323 }
1325 index = 0;
1326 buf_pool_release(&buf);
1327
1328 int rc = nntp_newsrc_parse(adata);
1329 if (rc < 0)
1330 return FR_ERROR;
1331
1332 struct FolderFile *ff = NULL;
1333 ARRAY_FOREACH_FROM(ff, &priv->state.entry, index)
1334 {
1335 if (regexec(&rx, ff->name, 0, NULL, 0) == 0)
1336 {
1337 if (op == OP_SUBSCRIBE_PATTERN)
1338 mutt_newsgroup_subscribe(adata, ff->name);
1339 else
1340 mutt_newsgroup_unsubscribe(adata, ff->name);
1341 }
1342 }
1343
1344 if (op == OP_SUBSCRIBE_PATTERN)
1345 {
1346 for (size_t j = 0; j < adata->groups_num; j++)
1347 {
1348 struct NntpMboxData *mdata = adata->groups_list[j];
1349 if (mdata && mdata->group && !mdata->subscribed)
1350 {
1351 if (regexec(&rx, mdata->group, 0, NULL, 0) == 0)
1352 {
1354 browser_add_folder(priv->menu, &priv->state, mdata->group, NULL, NULL, NULL, mdata);
1355 }
1356 }
1357 }
1358 init_menu(&priv->state, priv->menu, priv->mailbox, priv->sbar);
1359 }
1360 if (rc > 0)
1365 regfree(&rx);
1366 return FR_SUCCESS;
1367}
#define ARRAY_FOREACH_FROM(elem, head, from)
Iterate from an index to the end.
Definition array.h:235
void browser_add_folder(const struct Menu *menu, struct BrowserState *state, const char *name, const char *desc, const struct stat *st, struct Mailbox *m, void *data)
Add a folder to the browser list.
@ HC_PATTERN
Patterns.
Definition lib.h:60
struct NntpMboxData * mutt_newsgroup_subscribe(struct NntpAccountData *adata, char *group)
Subscribe newsgroup.
Definition newsrc.c:1188
struct NntpMboxData * mutt_newsgroup_unsubscribe(struct NntpAccountData *adata, char *group)
Unsubscribe newsgroup.
Definition newsrc.c:1212
const struct CompleteOps CompletePatternOps
Auto-Completion of Patterns.
Definition complete.c:98
#define REG_COMP(preg, regex, cflags)
Compile a regular expression.
Definition regex3.h:49
unsigned int groups_num
Number of newsgroups.
Definition adata.h:58
Here is the call graph for this function:

◆ op_toggle_mailboxes()

int op_toggle_mailboxes ( struct BrowserPrivateData * priv,
const struct KeyEvent * event )
static

Toggle whether to browse mailboxes or all files - Implements browser_function_t -.

This function handles:

  • OP_BROWSER_GOTO_FOLDER
  • OP_CHECK_NEW
  • OP_TOGGLE_MAILBOXES

Definition at line 1377 of file functions.c.

1378{
1380 if (priv->state.is_mailbox_list)
1381 {
1383 }
1384
1385 const int op = event->op;
1386 if (op == OP_TOGGLE_MAILBOXES)
1387 {
1389 }
1390
1391 if (op == OP_BROWSER_GOTO_FOLDER)
1392 {
1393 /* When in mailboxes mode, disables this feature */
1394 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
1395 if (c_folder)
1396 {
1397 mutt_debug(LL_DEBUG3, "= hit! Folder: %s, LastDir: %s\n", c_folder,
1398 buf_string(&mod_data->last_dir));
1399 if (priv->goto_swapper[0] == '\0')
1400 {
1401 if (!mutt_str_equal(buf_string(&mod_data->last_dir), c_folder))
1402 {
1403 /* Stores into goto_swapper LastDir, and swaps to `$folder` */
1404 mutt_str_copy(priv->goto_swapper, buf_string(&mod_data->last_dir),
1405 sizeof(priv->goto_swapper));
1406 buf_copy(&mod_data->last_dir_backup, &mod_data->last_dir);
1407 buf_strcpy(&mod_data->last_dir, c_folder);
1408 }
1409 }
1410 else
1411 {
1412 buf_copy(&mod_data->last_dir_backup, &mod_data->last_dir);
1413 buf_strcpy(&mod_data->last_dir, priv->goto_swapper);
1414 priv->goto_swapper[0] = '\0';
1415 }
1416 }
1417 }
1418 destroy_state(&priv->state);
1419 buf_reset(priv->prefix);
1420 priv->kill_prefix = false;
1421
1422 if (priv->state.is_mailbox_list)
1423 {
1424 examine_mailboxes(priv->mailbox, priv->menu, &priv->state);
1425 }
1426 else if (imap_path_probe(buf_string(&mod_data->last_dir), NULL) == MUTT_IMAP)
1427 {
1428 init_state(&priv->state);
1429 priv->state.imap_browse = true;
1430 imap_browse(buf_string(&mod_data->last_dir), &priv->state);
1431 browser_sort(&priv->state);
1432 }
1433 else if (examine_directory(priv->mailbox, priv->menu, &priv->state,
1434 buf_string(&mod_data->last_dir),
1435 buf_string(priv->prefix)) == -1)
1436 {
1437 priv->done = true;
1438 return FR_ERROR;
1439 }
1440 init_menu(&priv->state, priv->menu, priv->mailbox, priv->sbar);
1441 if (priv->state.is_mailbox_list)
1443 return FR_ERROR;
1444}
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
@ LL_DEBUG3
Log at debug level 3.
Definition logging2.h:47
struct Buffer last_dir_backup
Browser: backup copy of the current directory.
Definition module_data.h:36
int last_selected_mailbox
Index of last selected Mailbox.
Here is the call graph for this function: