NeoMutt  2023-03-22
Teaching an old dog new tricks
DOXYGEN
functions.c
Go to the documentation of this file.
1
29#include "config.h"
30#include <limits.h>
31#include <stdbool.h>
32#include <stdio.h>
33#include <string.h>
34#include <sys/stat.h>
35#include "mutt/lib.h"
36#include "config/lib.h"
37#include "email/lib.h"
38#include "core/lib.h"
39#include "gui/lib.h"
40#include "mutt.h"
41#include "functions.h"
42#include "lib.h"
43#include "attach/lib.h"
44#include "enter/lib.h"
45#include "menu/lib.h"
46#include "question/lib.h"
47#include "send/lib.h"
48#include "globals.h" // IWYU pragma: keep
49#include "mutt_mailbox.h"
50#include "muttlib.h"
51#include "mx.h"
52#include "opcodes.h"
53#include "private_data.h"
54#ifdef USE_IMAP
55#include "imap/lib.h"
56#endif
57#ifdef USE_NNTP
58#include "nntp/lib.h"
59#include "nntp/adata.h"
60#include "nntp/mdata.h"
61#endif
62
63static const char *Not_available_in_this_menu = N_("Not available in this menu");
64
65static int op_subscribe_pattern(struct BrowserPrivateData *priv, int op);
66
73void destroy_state(struct BrowserState *state)
74{
75 struct FolderFile *ff = NULL;
76 ARRAY_FOREACH(ff, &state->entry)
77 {
78 FREE(&ff->name);
79 FREE(&ff->desc);
80 }
81 ARRAY_FREE(&state->entry);
82
83#ifdef USE_IMAP
84 FREE(&state->folder);
85#endif
86}
87
88// -----------------------------------------------------------------------------
89
93static int op_browser_new_file(struct BrowserPrivateData *priv, int op)
94{
95 struct Buffer *buf = mutt_buffer_pool_get();
97
98 const int rc = mutt_buffer_get_field(_("New file name: "), buf,
99 MUTT_COMP_FILE, false, NULL, NULL, NULL);
100 if (rc != 0)
101 {
103 return FR_NO_ACTION;
104 }
105
106 mutt_buffer_copy(priv->file, buf);
108 priv->done = true;
109 return FR_DONE;
110}
111
112#if defined(USE_IMAP) || defined(USE_NNTP)
120static int op_browser_subscribe(struct BrowserPrivateData *priv, int op)
121{
122 if (OptNews)
123 {
125 int index = menu_get_index(priv->menu);
126
127 if (ARRAY_EMPTY(&priv->state.entry))
128 {
129 mutt_error(_("No newsgroups match the mask"));
130 return FR_ERROR;
131 }
132
133 int rc = nntp_newsrc_parse(adata);
134 if (rc < 0)
135 return FR_ERROR;
136
137 struct FolderFile *ff = ARRAY_GET(&priv->state.entry, index);
138 if (op == OP_BROWSER_SUBSCRIBE)
139 mutt_newsgroup_subscribe(adata, ff->name);
140 else
142
143 menu_set_index(priv->menu, index + 1);
144
145 if (rc > 0)
147 nntp_newsrc_update(adata);
148 nntp_clear_cache(adata);
149 nntp_newsrc_close(adata);
150 }
151#ifdef USE_IMAP
152 else
153 {
154 char tmp2[256];
155 int index = menu_get_index(priv->menu);
156 struct FolderFile *ff = ARRAY_GET(&priv->state.entry, index);
157 mutt_str_copy(tmp2, ff->name, sizeof(tmp2));
158 mutt_expand_path(tmp2, sizeof(tmp2));
159 imap_subscribe(tmp2, (op == OP_BROWSER_SUBSCRIBE));
160 }
161#endif
162 return FR_SUCCESS;
163}
164#endif
165
169static int op_browser_tell(struct BrowserPrivateData *priv, int op)
170{
171 int index = menu_get_index(priv->menu);
172 if (ARRAY_EMPTY(&priv->state.entry))
173 return FR_ERROR;
174
175 mutt_message("%s", ARRAY_GET(&priv->state.entry, index)->name);
176 return FR_SUCCESS;
177}
178
179#ifdef USE_IMAP
183static int op_browser_toggle_lsub(struct BrowserPrivateData *priv, int op)
184{
185 bool_str_toggle(NeoMutt->sub, "imap_list_subscribed", NULL);
186
187 mutt_unget_op(OP_CHECK_NEW);
188 return FR_SUCCESS;
189}
190#endif
191
195static int op_browser_view_file(struct BrowserPrivateData *priv, int op)
196{
197 if (ARRAY_EMPTY(&priv->state.entry))
198 {
199 mutt_error(_("No files match the file mask"));
200 return FR_ERROR;
201 }
202
203 int index = menu_get_index(priv->menu);
204 struct FolderFile *ff = ARRAY_GET(&priv->state.entry, index);
205#ifdef USE_IMAP
206 if (ff->selectable)
207 {
208 mutt_buffer_strcpy(priv->file, ff->name);
209 priv->done = true;
210 return FR_DONE;
211 }
212 else
213#endif
214 if (S_ISDIR(ff->mode) ||
215 (S_ISLNK(ff->mode) && link_is_dir(mutt_buffer_string(&LastDir), ff->name)))
216 {
217 mutt_error(_("Can't view a directory"));
218 return FR_ERROR;
219 }
220 else
221 {
222 char buf2[PATH_MAX];
223
224 mutt_path_concat(buf2, mutt_buffer_string(&LastDir), ff->name, sizeof(buf2));
225 struct Body *b = mutt_make_file_attach(buf2, NeoMutt->sub);
226 if (b)
227 {
228 mutt_view_attachment(NULL, b, MUTT_VA_REGULAR, NULL, NULL, priv->menu->win);
229 mutt_body_free(&b);
231 }
232 else
233 {
234 mutt_error(_("Error trying to view file"));
235 }
236 }
237 return FR_ERROR;
238}
239
240#ifdef USE_NNTP
244static int op_catchup(struct BrowserPrivateData *priv, int op)
245{
246 if (!OptNews)
247 return FR_NOT_IMPL;
248
249 struct NntpMboxData *mdata = NULL;
250
252 if (rc < 0)
253 return FR_ERROR;
254
255 int index = menu_get_index(priv->menu);
256 struct FolderFile *ff = ARRAY_GET(&priv->state.entry, index);
257 if (op == OP_CATCHUP)
259 else
261
262 if (mdata)
263 {
265 index = menu_get_index(priv->menu) + 1;
266 if (index < priv->menu->max)
267 menu_set_index(priv->menu, index);
268 }
269
270 if (rc != 0)
272
274 return FR_ERROR;
275}
276#endif
277
285static int op_change_directory(struct BrowserPrivateData *priv, int op)
286{
287#ifdef USE_NNTP
288 if (OptNews)
289 return FR_NOT_IMPL;
290#endif
291
292 struct Buffer *buf = mutt_buffer_pool_get();
294#ifdef USE_IMAP
295 if (!priv->state.imap_browse)
296#endif
297 {
298 /* add '/' at the end of the directory name if not already there */
299 size_t len = mutt_buffer_len(buf);
300 if ((len > 0) && (mutt_buffer_string(&LastDir)[len - 1] != '/'))
301 mutt_buffer_addch(buf, '/');
302 }
303
304 if (op == OP_CHANGE_DIRECTORY)
305 {
306 int rc = mutt_buffer_get_field(_("Chdir to: "), buf, MUTT_COMP_FILE, false,
307 NULL, NULL, NULL);
308 if ((rc != 0) && mutt_buffer_is_empty(buf))
309 {
311 return FR_NO_ACTION;
312 }
313 }
314 else if (op == OP_GOTO_PARENT)
315 {
317 }
318
319 if (!mutt_buffer_is_empty(buf))
320 {
321 priv->state.is_mailbox_list = false;
323#ifdef USE_IMAP
325 {
327 destroy_state(&priv->state);
328 init_state(&priv->state, NULL);
329 priv->state.imap_browse = true;
331 browser_sort(&priv->state);
332 priv->menu->mdata = &priv->state.entry;
333 priv->menu->mdata_free = NULL; // Menu doesn't own the data
334 browser_highlight_default(&priv->state, priv->menu);
335 init_menu(&priv->state, priv->menu, priv->mailbox, priv->sbar);
336 }
337 else
338#endif
339 {
340 if (mutt_buffer_string(buf)[0] != '/')
341 {
342 /* in case dir is relative, make it relative to LastDir,
343 * not current working dir */
344 struct Buffer *tmp = mutt_buffer_pool_get();
346 mutt_buffer_copy(buf, tmp);
348 }
349 /* Resolve path from <chdir>
350 * Avoids buildup such as /a/b/../../c
351 * Symlinks are always unraveled to keep code simple */
352 if (mutt_path_realpath(buf->data) == 0)
353 {
355 return FR_ERROR;
356 }
357
358 struct stat st = { 0 };
359 if (stat(mutt_buffer_string(buf), &st) == 0)
360 {
361 if (S_ISDIR(st.st_mode))
362 {
363 destroy_state(&priv->state);
364 if (examine_directory(priv->mailbox, priv->menu, &priv->state,
366 mutt_buffer_string(priv->prefix)) == 0)
367 {
369 }
370 else
371 {
372 mutt_error(_("Error scanning directory"));
373 if (examine_directory(priv->mailbox, priv->menu, &priv->state,
375 mutt_buffer_string(priv->prefix)) == -1)
376 {
377 priv->done = true;
378 return FR_ERROR;
379 }
380 }
381 browser_highlight_default(&priv->state, priv->menu);
382 init_menu(&priv->state, priv->menu, priv->mailbox, priv->sbar);
383 }
384 else
385 {
386 mutt_error(_("%s is not a directory"), mutt_buffer_string(buf));
387 }
388 }
389 else
390 {
392 }
393 }
394 }
396 return FR_ERROR;
397}
398
399#ifdef USE_IMAP
403static int op_create_mailbox(struct BrowserPrivateData *priv, int op)
404{
405 if (!priv->state.imap_browse)
406 {
407 mutt_error(_("Create is only supported for IMAP mailboxes"));
408 return FR_ERROR;
409 }
410
412 return FR_ERROR;
413
414 /* TODO: find a way to detect if the new folder would appear in
415 * this window, and insert it without starting over. */
416 destroy_state(&priv->state);
417 init_state(&priv->state, NULL);
418 priv->state.imap_browse = true;
420 browser_sort(&priv->state);
421 priv->menu->mdata = &priv->state.entry;
422 priv->menu->mdata_free = NULL; // Menu doesn't own the data
423 browser_highlight_default(&priv->state, priv->menu);
424 init_menu(&priv->state, priv->menu, priv->mailbox, priv->sbar);
425
426 return FR_SUCCESS;
427}
428#endif
429
430#ifdef USE_IMAP
434static int op_delete_mailbox(struct BrowserPrivateData *priv, int op)
435{
436 int index = menu_get_index(priv->menu);
437 struct FolderFile *ff = ARRAY_GET(&priv->state.entry, index);
438 if (!ff->imap)
439 {
440 mutt_error(_("Delete is only supported for IMAP mailboxes"));
441 return FR_ERROR;
442 }
443
444 char msg[128] = { 0 };
445
446 // TODO(sileht): It could be better to select INBOX instead. But I
447 // don't want to manipulate Mailboxes/mailbox->account here for now.
448 // Let's just protect neomutt against crash for now. #1417
449 if (mutt_str_equal(mailbox_path(priv->mailbox), ff->name))
450 {
451 mutt_error(_("Can't delete currently selected mailbox"));
452 return FR_ERROR;
453 }
454
455 snprintf(msg, sizeof(msg), _("Really delete mailbox \"%s\"?"), ff->name);
456 if (mutt_yesorno(msg, MUTT_NO) != MUTT_YES)
457 {
458 mutt_message(_("Mailbox not deleted"));
459 return FR_NO_ACTION;
460 }
461
462 if (imap_delete_mailbox(priv->mailbox, ff->name) != 0)
463 {
464 mutt_error(_("Mailbox deletion failed"));
465 return FR_ERROR;
466 }
467
468 /* free the mailbox from the browser */
469 FREE(&ff->name);
470 FREE(&ff->desc);
471 /* and move all other entries up */
472 ARRAY_REMOVE(&priv->state.entry, ff);
473 mutt_message(_("Mailbox deleted"));
474 init_menu(&priv->state, priv->menu, priv->mailbox, priv->sbar);
475
476 return FR_SUCCESS;
477}
478#endif
479
483static int op_enter_mask(struct BrowserPrivateData *priv, int op)
484{
485 const struct Regex *c_mask = cs_subset_regex(NeoMutt->sub, "mask");
486 struct Buffer *buf = mutt_buffer_pool_get();
487 mutt_buffer_strcpy(buf, c_mask ? c_mask->pattern : NULL);
488 if (mutt_buffer_get_field(_("File Mask: "), buf, MUTT_COMP_NO_FLAGS, false,
489 NULL, NULL, NULL) != 0)
490 {
492 return FR_NO_ACTION;
493 }
494
496
497 priv->state.is_mailbox_list = false;
498 /* assume that the user wants to see everything */
499 if (mutt_buffer_is_empty(buf))
500 mutt_buffer_strcpy(buf, ".");
501
502 struct Buffer errmsg = mutt_buffer_make(256);
503 int rc = cs_subset_str_string_set(NeoMutt->sub, "mask", mutt_buffer_string(buf), &errmsg);
505 if (CSR_RESULT(rc) != CSR_SUCCESS)
506 {
507 if (!mutt_buffer_is_empty(&errmsg))
508 {
509 mutt_error("%s", mutt_buffer_string(&errmsg));
510 mutt_buffer_dealloc(&errmsg);
511 }
512 return FR_ERROR;
513 }
514 mutt_buffer_dealloc(&errmsg);
515
516 destroy_state(&priv->state);
517#ifdef USE_IMAP
518 if (priv->state.imap_browse)
519 {
520 init_state(&priv->state, NULL);
521 priv->state.imap_browse = true;
523 browser_sort(&priv->state);
524 priv->menu->mdata = &priv->state.entry;
525 priv->menu->mdata_free = NULL; // Menu doesn't own the data
526 init_menu(&priv->state, priv->menu, priv->mailbox, priv->sbar);
527 }
528 else
529#endif
530 if (examine_directory(priv->mailbox, priv->menu, &priv->state,
531 mutt_buffer_string(&LastDir), NULL) == 0)
532 {
533 init_menu(&priv->state, priv->menu, priv->mailbox, priv->sbar);
534 }
535 else
536 {
537 mutt_error(_("Error scanning directory"));
538 priv->done = true;
539 return FR_ERROR;
540 }
541 priv->kill_prefix = false;
542 if (ARRAY_EMPTY(&priv->state.entry))
543 {
544 mutt_error(_("No files match the file mask"));
545 return FR_ERROR;
546 }
547 return FR_SUCCESS;
548}
549
553static int op_exit(struct BrowserPrivateData *priv, int op)
554{
555 if (priv->multiple)
556 {
557 char **tfiles = NULL;
558
559 if (priv->menu->num_tagged)
560 {
561 *priv->numfiles = priv->menu->num_tagged;
562 tfiles = mutt_mem_calloc(*priv->numfiles, sizeof(char *));
563 size_t j = 0;
564 struct FolderFile *ff = NULL;
565 ARRAY_FOREACH(ff, &priv->state.entry)
566 {
567 if (ff->tagged)
568 {
569 struct Buffer *buf = mutt_buffer_pool_get();
572 tfiles[j++] = mutt_buffer_strdup(buf);
574 }
575 }
576 *priv->files = tfiles;
577 }
578 else if (!mutt_buffer_is_empty(priv->file)) /* no tagged entries. return selected entry */
579 {
580 *priv->numfiles = 1;
581 tfiles = mutt_mem_calloc(*priv->numfiles, sizeof(char *));
583 tfiles[0] = mutt_buffer_strdup(priv->file);
584 *priv->files = tfiles;
585 }
586 }
587
588 priv->done = true;
589 return FR_DONE;
590}
591
599static int op_generic_select_entry(struct BrowserPrivateData *priv, int op)
600{
601 if (ARRAY_EMPTY(&priv->state.entry))
602 {
603 mutt_error(_("No files match the file mask"));
604 return FR_ERROR;
605 }
606
607 int index = menu_get_index(priv->menu);
608 struct FolderFile *ff = ARRAY_GET(&priv->state.entry, index);
609 if (S_ISDIR(ff->mode) ||
610 (S_ISLNK(ff->mode) && link_is_dir(mutt_buffer_string(&LastDir), ff->name))
611#ifdef USE_IMAP
612 || ff->inferiors
613#endif
614 )
615 {
616 /* make sure this isn't a MH or maildir mailbox */
617 struct Buffer *buf = mutt_buffer_pool_get();
618 if (priv->state.is_mailbox_list)
619 {
620 mutt_buffer_strcpy(buf, ff->name);
622 }
623#ifdef USE_IMAP
624 else if (priv->state.imap_browse)
625 {
626 mutt_buffer_strcpy(buf, ff->name);
627 }
628#endif
629 else
630 {
632 }
633
636
637 if ((op == OP_DESCEND_DIRECTORY) || (type == MUTT_MAILBOX_ERROR) || (type == MUTT_UNKNOWN)
638#ifdef USE_IMAP
639 || ff->inferiors
640#endif
641 )
642 {
643 /* save the old directory */
645
646 if (mutt_str_equal(ff->name, ".."))
647 {
648 size_t lastdirlen = mutt_buffer_len(&LastDir);
649 if ((lastdirlen > 1) &&
650 mutt_str_equal("..", mutt_buffer_string(&LastDir) + lastdirlen - 2))
651 {
653 }
654 else
655 {
656 char *p = NULL;
657 if (lastdirlen > 1)
658 p = strrchr(LastDir.data + 1, '/');
659
660 if (p)
661 {
662 *p = '\0';
664 }
665 else
666 {
667 if (mutt_buffer_string(&LastDir)[0] == '/')
669 else
671 }
672 }
673 }
674 else if (priv->state.is_mailbox_list)
675 {
678 }
679#ifdef USE_IMAP
680 else if (priv->state.imap_browse)
681 {
683 /* tack on delimiter here */
684
685 /* special case "" needs no delimiter */
686 struct Url *url = url_parse(ff->name);
687 if (url && url->path && (ff->delim != '\0'))
688 {
690 }
691 url_free(&url);
692 }
693#endif
694 else
695 {
696 struct Buffer *tmp = mutt_buffer_pool_get();
700 }
701
702 destroy_state(&priv->state);
703 if (priv->kill_prefix)
704 {
706 priv->kill_prefix = false;
707 }
708 priv->state.is_mailbox_list = false;
709#ifdef USE_IMAP
710 if (priv->state.imap_browse)
711 {
712 init_state(&priv->state, NULL);
713 priv->state.imap_browse = true;
715 browser_sort(&priv->state);
716 priv->menu->mdata = &priv->state.entry;
717 priv->menu->mdata_free = NULL; // Menu doesn't own the data
718 }
719 else
720#endif
721 {
722 if (examine_directory(priv->mailbox, priv->menu, &priv->state,
724 mutt_buffer_string(priv->prefix)) == -1)
725 {
726 /* try to restore the old values */
728 if (examine_directory(priv->mailbox, priv->menu, &priv->state,
730 mutt_buffer_string(priv->prefix)) == -1)
731 {
733 priv->done = true;
734 return FR_DONE;
735 }
736 }
737 /* resolve paths navigated from GUI */
739 return FR_ERROR;
740 }
741
742 browser_highlight_default(&priv->state, priv->menu);
743 init_menu(&priv->state, priv->menu, priv->mailbox, priv->sbar);
744 priv->goto_swapper[0] = '\0';
745 return FR_SUCCESS;
746 }
747 }
748 else if (op == OP_DESCEND_DIRECTORY)
749 {
750 mutt_error(_("%s is not a directory"), ARRAY_GET(&priv->state.entry, index)->name);
751 return FR_ERROR;
752 }
753
754 if (priv->state.is_mailbox_list || OptNews) /* USE_NNTP */
755 {
756 mutt_buffer_strcpy(priv->file, ff->name);
758 }
759#ifdef USE_IMAP
760 else if (priv->state.imap_browse)
761 mutt_buffer_strcpy(priv->file, ff->name);
762#endif
763 else
764 {
766 }
767
768 return op_exit(priv, op);
769}
770
771#ifdef USE_NNTP
775static int op_load_active(struct BrowserPrivateData *priv, int op)
776{
777 if (!OptNews)
778 return FR_NOT_IMPL;
779
781
782 if (nntp_newsrc_parse(adata) < 0)
783 return FR_ERROR;
784
785 for (size_t i = 0; i < adata->groups_num; i++)
786 {
787 struct NntpMboxData *mdata = adata->groups_list[i];
788 if (mdata)
789 mdata->deleted = true;
790 }
794
795 destroy_state(&priv->state);
796 if (priv->state.is_mailbox_list)
797 {
798 examine_mailboxes(priv->mailbox, priv->menu, &priv->state);
799 }
800 else
801 {
802 if (examine_directory(priv->mailbox, priv->menu, &priv->state, NULL, NULL) == -1)
803 return FR_ERROR;
804 }
805 init_menu(&priv->state, priv->menu, priv->mailbox, priv->sbar);
806 return FR_SUCCESS;
807}
808#endif
809
813static int op_mailbox_list(struct BrowserPrivateData *priv, int op)
814{
816 return FR_SUCCESS;
817}
818
819#ifdef USE_IMAP
823static int op_rename_mailbox(struct BrowserPrivateData *priv, int op)
824{
825 int index = menu_get_index(priv->menu);
826 struct FolderFile *ff = ARRAY_GET(&priv->state.entry, index);
827 if (!ff->imap)
828 {
829 mutt_error(_("Rename is only supported for IMAP mailboxes"));
830 return FR_ERROR;
831 }
832
833 if (imap_mailbox_rename(ff->name) < 0)
834 return FR_ERROR;
835
836 destroy_state(&priv->state);
837 init_state(&priv->state, NULL);
838 priv->state.imap_browse = true;
840 browser_sort(&priv->state);
841 priv->menu->mdata = &priv->state.entry;
842 priv->menu->mdata_free = NULL; // Menu doesn't own the data
843 browser_highlight_default(&priv->state, priv->menu);
844 init_menu(&priv->state, priv->menu, priv->mailbox, priv->sbar);
845
846 return FR_SUCCESS;
847}
848#endif
849
857static int op_sort(struct BrowserPrivateData *priv, int op)
858{
859 bool resort = true;
860 int sort = -1;
861 int reverse = (op == OP_SORT_REVERSE);
862
863 switch (mutt_multi_choice(
864 (reverse) ?
865 /* L10N: The highlighted letters must match the "Sort" options */
866 _("Reverse sort by (d)ate, (a)lpha, si(z)e, d(e)scription, (c)ount, ne(w) count, or do(n)'t sort?") :
867 /* L10N: The highlighted letters must match the "Reverse Sort" options */
868 _("Sort by (d)ate, (a)lpha, si(z)e, d(e)scription, (c)ount, ne(w) count, or do(n)'t sort?"),
869 /* L10N: These must match the highlighted letters from "Sort" and "Reverse Sort" */
870 _("dazecwn")))
871 {
872 case -1: /* abort */
873 resort = false;
874 break;
875
876 case 1: /* (d)ate */
877 sort = SORT_DATE;
878 break;
879
880 case 2: /* (a)lpha */
881 sort = SORT_SUBJECT;
882 break;
883
884 case 3: /* si(z)e */
885 sort = SORT_SIZE;
886 break;
887
888 case 4: /* d(e)scription */
889 sort = SORT_DESC;
890 break;
891
892 case 5: /* (c)ount */
893 sort = SORT_COUNT;
894 break;
895
896 case 6: /* ne(w) count */
897 sort = SORT_UNREAD;
898 break;
899
900 case 7: /* do(n)'t sort */
901 sort = SORT_ORDER;
902 break;
903 }
904
905 if (!resort)
906 return FR_NO_ACTION;
907
908 sort |= reverse ? SORT_REVERSE : 0;
909 cs_subset_str_native_set(NeoMutt->sub, "sort_browser", sort, NULL);
910 browser_sort(&priv->state);
911 browser_highlight_default(&priv->state, priv->menu);
913 return FR_SUCCESS;
914}
915
916#ifdef USE_NNTP
924static int op_subscribe_pattern(struct BrowserPrivateData *priv, int op)
925{
926 if (!OptNews)
927 return FR_NOT_IMPL;
928
930 regex_t rx = { 0 };
931 int index = menu_get_index(priv->menu);
932
933 char tmp2[256];
934
935 struct Buffer *buf = mutt_buffer_pool_get();
936 if (op == OP_SUBSCRIBE_PATTERN)
937 snprintf(tmp2, sizeof(tmp2), _("Subscribe pattern: "));
938 else
939 snprintf(tmp2, sizeof(tmp2), _("Unsubscribe pattern: "));
940 /* buf comes from the buffer pool, so defaults to size 1024 */
941 if ((mutt_buffer_get_field(tmp2, buf, MUTT_COMP_PATTERN, false, NULL, NULL, NULL) != 0) ||
943 {
945 return FR_NO_ACTION;
946 }
947
948 int err = REG_COMP(&rx, buf->data, REG_NOSUB);
949 if (err != 0)
950 {
951 regerror(err, &rx, buf->data, buf->dsize);
952 regfree(&rx);
953 mutt_error("%s", mutt_buffer_string(buf));
955 return FR_ERROR;
956 }
958 index = 0;
960
961 int rc = nntp_newsrc_parse(adata);
962 if (rc < 0)
963 return FR_ERROR;
964
965 struct FolderFile *ff = NULL;
966 ARRAY_FOREACH_FROM(ff, &priv->state.entry, index)
967 {
968 if (regexec(&rx, ff->name, 0, NULL, 0) == 0)
969 {
970 if (op == OP_SUBSCRIBE_PATTERN)
971 mutt_newsgroup_subscribe(adata, ff->name);
972 else
974 }
975 }
976
977 if (op == OP_SUBSCRIBE_PATTERN)
978 {
979 for (size_t j = 0; j < adata->groups_num; j++)
980 {
981 struct NntpMboxData *mdata = adata->groups_list[j];
982 if (mdata && mdata->group && !mdata->subscribed)
983 {
984 if (regexec(&rx, mdata->group, 0, NULL, 0) == 0)
985 {
987 browser_add_folder(priv->menu, &priv->state, mdata->group, NULL, NULL, NULL, mdata);
988 }
989 }
990 }
991 init_menu(&priv->state, priv->menu, priv->mailbox, priv->sbar);
992 }
993 if (rc > 0)
998 regfree(&rx);
999 return FR_SUCCESS;
1000}
1001#endif
1002
1010static int op_toggle_mailboxes(struct BrowserPrivateData *priv, int op)
1011{
1012 if (priv->state.is_mailbox_list)
1013 {
1015 }
1016
1017 if (op == OP_TOGGLE_MAILBOXES)
1018 {
1020 }
1021
1022 if (op == OP_BROWSER_GOTO_FOLDER)
1023 {
1024 /* When in mailboxes mode, disables this feature */
1025 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
1026 if (c_folder)
1027 {
1028 mutt_debug(LL_DEBUG3, "= hit! Folder: %s, LastDir: %s\n", c_folder,
1030 if (priv->goto_swapper[0] == '\0')
1031 {
1032 if (!mutt_str_equal(mutt_buffer_string(&LastDir), c_folder))
1033 {
1034 /* Stores into goto_swapper LastDir, and swaps to `$folder` */
1036 sizeof(priv->goto_swapper));
1038 mutt_buffer_strcpy(&LastDir, c_folder);
1039 }
1040 }
1041 else
1042 {
1045 priv->goto_swapper[0] = '\0';
1046 }
1047 }
1048 }
1049 destroy_state(&priv->state);
1051 priv->kill_prefix = false;
1052
1053 if (priv->state.is_mailbox_list)
1054 {
1055 examine_mailboxes(priv->mailbox, priv->menu, &priv->state);
1056 }
1057#ifdef USE_IMAP
1059 {
1060 init_state(&priv->state, NULL);
1061 priv->state.imap_browse = true;
1063 browser_sort(&priv->state);
1064 priv->menu->mdata = &priv->state.entry;
1065 priv->menu->mdata_free = NULL; // Menu doesn't own the data
1066 }
1067#endif
1068 else if (examine_directory(priv->mailbox, priv->menu, &priv->state,
1070 mutt_buffer_string(priv->prefix)) == -1)
1071 {
1072 priv->done = true;
1073 return FR_ERROR;
1074 }
1075 init_menu(&priv->state, priv->menu, priv->mailbox, priv->sbar);
1076 if (priv->state.is_mailbox_list)
1078 return FR_ERROR;
1079}
1080
1081// -----------------------------------------------------------------------------
1082
1087 // clang-format off
1088 { OP_BROWSER_GOTO_FOLDER, op_toggle_mailboxes },
1089 { OP_BROWSER_NEW_FILE, op_browser_new_file },
1090#if defined(USE_IMAP) || defined(USE_NNTP)
1091 { OP_BROWSER_SUBSCRIBE, op_browser_subscribe },
1092#endif
1093 { OP_BROWSER_TELL, op_browser_tell },
1094#ifdef USE_IMAP
1095 { OP_BROWSER_TOGGLE_LSUB, op_browser_toggle_lsub },
1096#endif
1097#if defined(USE_IMAP) || defined(USE_NNTP)
1098 { OP_BROWSER_UNSUBSCRIBE, op_browser_subscribe },
1099#endif
1100 { OP_BROWSER_VIEW_FILE, op_browser_view_file },
1101#ifdef USE_NNTP
1102 { OP_CATCHUP, op_catchup },
1103#endif
1104 { OP_CHANGE_DIRECTORY, op_change_directory },
1105 { OP_CHECK_NEW, op_toggle_mailboxes },
1106#ifdef USE_IMAP
1107 { OP_CREATE_MAILBOX, op_create_mailbox },
1108 { OP_DELETE_MAILBOX, op_delete_mailbox },
1109#endif
1110 { OP_DESCEND_DIRECTORY, op_generic_select_entry },
1111 { OP_ENTER_MASK, op_enter_mask },
1112 { OP_EXIT, op_exit },
1113 { OP_GENERIC_SELECT_ENTRY, op_generic_select_entry },
1114 { OP_GOTO_PARENT, op_change_directory },
1115#ifdef USE_NNTP
1116 { OP_LOAD_ACTIVE, op_load_active },
1117#endif
1118 { OP_MAILBOX_LIST, op_mailbox_list },
1119#ifdef USE_IMAP
1120 { OP_RENAME_MAILBOX, op_rename_mailbox },
1121#endif
1122 { OP_SORT, op_sort },
1123 { OP_SORT_REVERSE, op_sort },
1124#ifdef USE_NNTP
1125 { OP_SUBSCRIBE_PATTERN, op_subscribe_pattern },
1126#endif
1127 { OP_TOGGLE_MAILBOXES, op_toggle_mailboxes },
1128#ifdef USE_NNTP
1129 { OP_UNCATCHUP, op_catchup },
1130 { OP_UNSUBSCRIBE_PATTERN, op_subscribe_pattern },
1131#endif
1132 { 0, NULL },
1133 // clang-format on
1134};
1135
1142int browser_function_dispatcher(struct MuttWindow *win_browser, int op)
1143{
1144 if (!win_browser)
1145 {
1147 return FR_ERROR;
1148 }
1149
1150 struct BrowserPrivateData *priv = win_browser->parent->wdata;
1151 if (!priv)
1152 return FR_ERROR;
1153
1154 int rc = FR_UNKNOWN;
1155 for (size_t i = 0; BrowserFunctions[i].op != OP_NULL; i++)
1156 {
1157 const struct BrowserFunction *fn = &BrowserFunctions[i];
1158 if (fn->op == op)
1159 {
1160 rc = fn->function(priv, op);
1161 break;
1162 }
1163 }
1164
1165 return rc;
1166}
#define ARRAY_REMOVE(head, elem)
Remove an entry from the array, shifting down the subsequent entries.
Definition: array.h:266
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:211
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition: array.h:73
#define ARRAY_FREE(head)
Release all memory.
Definition: array.h:203
#define ARRAY_FOREACH_FROM(elem, head, from)
Iterate from an index to the end.
Definition: array.h:222
#define ARRAY_GET(head, idx)
Return the element at index.
Definition: array.h:108
GUI display the mailboxes in a side panel.
int bool_str_toggle(struct ConfigSubset *sub, const char *name, struct Buffer *err)
Toggle the value of a bool.
Definition: bool.c:214
struct BrowserFunction BrowserFunctions[]
All the NeoMutt functions that the Browser supports.
Definition: functions.c:1086
static const char * Not_available_in_this_menu
Definition: functions.c:63
int browser_function_dispatcher(struct MuttWindow *win_browser, int op)
Perform a Browser function.
Definition: functions.c:1142
void destroy_state(struct BrowserState *state)
Free the BrowserState.
Definition: functions.c:73
void browser_sort(struct BrowserState *state)
Sort the entries in the browser.
Definition: sort.c:194
void init_state(struct BrowserState *state, struct Menu *menu)
Initialise a browser state.
Definition: browser.c:595
int examine_directory(struct Mailbox *m, struct Menu *menu, struct BrowserState *state, const char *dirname, const char *prefix)
Get list of all files/newsgroups with mask.
Definition: browser.c:619
void init_menu(struct BrowserState *state, struct Menu *menu, struct Mailbox *m, struct MuttWindow *sbar)
Set up a new menu.
Definition: browser.c:937
struct Buffer LastDir
Definition: browser.c:136
struct Buffer LastDirBackup
Definition: browser.c:137
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.
Definition: browser.c:542
void browser_highlight_default(struct BrowserState *state, struct Menu *menu)
Decide which browser item should be highlighted.
Definition: browser.c:911
int examine_mailboxes(struct Mailbox *m, struct Menu *menu, struct BrowserState *state)
Get list of mailboxes/subscribed newsgroups.
Definition: browser.c:747
bool link_is_dir(const char *folder, const char *path)
Does this symlink point to a directory?
Definition: browser.c:171
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:67
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:298
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:365
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:347
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:409
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:248
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:233
void mutt_buffer_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:189
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:168
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:500
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:85
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:485
size_t mutt_buffer_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition: buffer.c:427
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:78
const struct Regex * cs_subset_regex(const struct ConfigSubset *sub, const char *name)
Get a regex config item by name.
Definition: helpers.c:243
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
Convenience wrapper for the config headers.
char * HomeDir
User's home directory.
Definition: globals.c:38
#define CSR_RESULT(x)
Definition: set.h:52
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
Convenience wrapper for the core headers.
void mutt_unget_op(int op)
Return an operation to the input buffer.
Definition: curs_lib.c:531
@ FR_SUCCESS
Valid function - successfully performed.
Definition: dispatcher.h:39
@ FR_DONE
Exit the Dialog.
Definition: dispatcher.h:35
@ FR_UNKNOWN
Unknown function.
Definition: dispatcher.h:33
@ FR_ERROR
Valid function - error occurred.
Definition: dispatcher.h:38
@ FR_NOT_IMPL
Invalid function - feature not enabled.
Definition: dispatcher.h:36
@ FR_NO_ACTION
Valid function - no action performed.
Definition: dispatcher.h:37
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
Structs that make up an email.
Enter a string.
int mutt_buffer_get_field(const char *field, struct Buffer *buf, CompletionFlags complete, bool multiple, struct Mailbox *m, char ***files, int *numfiles)
Ask the user for a string.
Definition: window.c:178
bool OptNews
(pseudo) used to change reader mode
Definition: globals.c:78
static int op_browser_view_file(struct BrowserPrivateData *priv, int op)
View file - Implements browser_function_t -.
Definition: functions.c:195
static int op_browser_new_file(struct BrowserPrivateData *priv, int op)
Select a new file in this directory - Implements browser_function_t -.
Definition: functions.c:93
static int op_enter_mask(struct BrowserPrivateData *priv, int op)
Enter a file mask - Implements browser_function_t -.
Definition: functions.c:483
static int op_sort(struct BrowserPrivateData *priv, int op)
Sort messages - Implements browser_function_t -.
Definition: functions.c:857
static int op_subscribe_pattern(struct BrowserPrivateData *priv, int op)
Subscribe to newsgroups matching a pattern - Implements browser_function_t -.
Definition: functions.c:924
static int op_exit(struct BrowserPrivateData *priv, int op)
Exit this menu - Implements browser_function_t -.
Definition: functions.c:553
static int op_catchup(struct BrowserPrivateData *priv, int op)
Mark all articles in newsgroup as read - Implements browser_function_t -.
Definition: functions.c:244
static int op_rename_mailbox(struct BrowserPrivateData *priv, int op)
Rename the current mailbox (IMAP only) - Implements browser_function_t -.
Definition: functions.c:823
static int op_browser_subscribe(struct BrowserPrivateData *priv, int op)
Subscribe to current mbox (IMAP/NNTP only) - Implements browser_function_t -.
Definition: functions.c:120
static int op_browser_toggle_lsub(struct BrowserPrivateData *priv, int op)
Toggle view all/subscribed mailboxes (IMAP only) - Implements browser_function_t -.
Definition: functions.c:183
static int op_create_mailbox(struct BrowserPrivateData *priv, int op)
Create a new mailbox (IMAP only) - Implements browser_function_t -.
Definition: functions.c:403
static int op_delete_mailbox(struct BrowserPrivateData *priv, int op)
Delete the current mailbox (IMAP only) - Implements browser_function_t -.
Definition: functions.c:434
static int op_generic_select_entry(struct BrowserPrivateData *priv, int op)
Select the current entry - Implements browser_function_t -.
Definition: functions.c:599
static int op_load_active(struct BrowserPrivateData *priv, int op)
Load list of all newsgroups from NNTP server - Implements browser_function_t -.
Definition: functions.c:775
static int op_toggle_mailboxes(struct BrowserPrivateData *priv, int op)
Toggle whether to browse mailboxes or all files - Implements browser_function_t -.
Definition: functions.c:1010
static int op_browser_tell(struct BrowserPrivateData *priv, int op)
Display the currently selected file's name - Implements browser_function_t -.
Definition: functions.c:169
static int op_mailbox_list(struct BrowserPrivateData *priv, int op)
List mailboxes with new mail - Implements browser_function_t -.
Definition: functions.c:813
static int op_change_directory(struct BrowserPrivateData *priv, int op)
Change directories - Implements browser_function_t -.
Definition: functions.c:285
#define mutt_error(...)
Definition: logging.h:87
#define mutt_message(...)
Definition: logging.h:86
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
#define mutt_perror(...)
Definition: logging.h:88
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe() -.
Definition: imap.c:2401
Convenience wrapper for the gui headers.
int imap_browse(const char *path, struct BrowserState *state)
IMAP hook into the folder browser.
Definition: browse.c:182
int imap_mailbox_create(const char *path)
Create a new IMAP mailbox.
Definition: browse.c:382
int imap_mailbox_rename(const char *path)
Rename a mailbox.
Definition: browse.c:436
IMAP network mailbox.
int imap_subscribe(char *path, bool subscribe)
Subscribe to a mailbox.
Definition: imap.c:1290
int imap_delete_mailbox(struct Mailbox *m, char *path)
Delete a mailbox.
Definition: imap.c:517
@ LL_DEBUG3
Log at debug level 3.
Definition: logging.h:42
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition: mailbox.h:209
MailboxType
Supported mailbox formats.
Definition: mailbox.h:41
@ MUTT_MAILBOX_ERROR
Error occurred examining Mailbox.
Definition: mailbox.h:43
@ MUTT_IMAP
'IMAP' Mailbox type
Definition: mailbox.h:50
@ MUTT_UNKNOWN
Mailbox wasn't recognised.
Definition: mailbox.h:44
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define FREE(x)
Definition: memory.h:43
GUI present the user with a selectable list.
#define MENU_REDRAW_FULL
Redraw everything.
Definition: lib.h:60
#define MENU_REDRAW_INDEX
Redraw the index.
Definition: lib.h:57
void menu_queue_redraw(struct Menu *menu, MenuRedrawFlags redraw)
Queue a request for a redraw.
Definition: menu.c:178
int menu_get_index(struct Menu *menu)
Get the current selection in the Menu.
Definition: menu.c:154
MenuRedrawFlags menu_set_index(struct Menu *menu, int index)
Set the current selection in the Menu.
Definition: menu.c:168
Convenience wrapper for the library headers.
#define N_(a)
Definition: message.h:32
#define _(a)
Definition: message.h:28
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:351
size_t mutt_path_realpath(char *buf)
Resolve path, unraveling symlinks.
Definition: path.c:440
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:807
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:652
Many unsorted constants and some structs.
#define MUTT_COMP_PATTERN
Pattern mode (in pattern dialog)
Definition: mutt.h:64
#define MUTT_COMP_FILE
File completion (in browser)
Definition: mutt.h:58
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:55
#define PATH_MAX
Definition: mutt.h:41
int mutt_view_attachment(FILE *fp, struct Body *a, enum ViewAttachMode mode, struct Email *e, struct AttachCtx *actx, struct MuttWindow *win)
View an attachment.
Definition: mutt_attach.c:416
@ MUTT_VA_REGULAR
View using default method.
Definition: mutt_attach.h:43
bool mutt_mailbox_list(void)
List the mailboxes with new mail.
Definition: mutt_mailbox.c:243
Mailbox helper functions.
void mutt_get_parent_path(const char *path, char *buf, size_t buflen)
Find the parent of a path (or mailbox)
Definition: muttlib.c:1550
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:322
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:123
Some miscellaneous functions.
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition: mx.c:1326
API for mailboxes.
Nntp-specific Account data.
Usenet network mailbox type; talk to an NNTP server.
void nntp_clear_cache(struct NntpAccountData *adata)
Clear the NNTP cache.
Definition: newsrc.c:845
int nntp_active_fetch(struct NntpAccountData *adata, bool mark_new)
Fetch list of all newsgroups from server.
Definition: nntp.c:1957
int nntp_newsrc_parse(struct NntpAccountData *adata)
Parse .newsrc file.
Definition: newsrc.c:162
void nntp_newsrc_close(struct NntpAccountData *adata)
Unlock and close .newsrc file.
Definition: newsrc.c:118
struct NntpMboxData * mutt_newsgroup_catchup(struct Mailbox *m, struct NntpAccountData *adata, char *group)
Catchup newsgroup.
Definition: newsrc.c:1318
int nntp_newsrc_update(struct NntpAccountData *adata)
Update .newsrc file.
Definition: newsrc.c:442
struct NntpMboxData * mutt_newsgroup_subscribe(struct NntpAccountData *adata, char *group)
Subscribe newsgroup.
Definition: newsrc.c:1267
struct NntpMboxData * mutt_newsgroup_uncatchup(struct Mailbox *m, struct NntpAccountData *adata, char *group)
Uncatchup newsgroup.
Definition: newsrc.c:1357
struct NntpAccountData * CurrentNewsSrv
Current NNTP news server.
Definition: nntp.c:77
struct NntpMboxData * mutt_newsgroup_unsubscribe(struct NntpAccountData *adata, char *group)
Unsubscribe newsgroup.
Definition: newsrc.c:1291
Nntp-specific Mailbox data.
All user-callable functions.
Private state data for the Pager.
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
@ MUTT_NO
User answered 'No', or assume 'No'.
Definition: quad.h:38
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition: quad.h:39
Ask the user a question.
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:194
int mutt_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question.
Definition: question.c:54
#define REG_COMP(preg, regex, cflags)
Compile a regular expression.
Definition: regex3.h:53
Convenience wrapper for the send headers.
struct Body * mutt_make_file_attach(const char *path, struct ConfigSubset *sub)
Create a file attachment.
Definition: sendlib.c:596
Sidebar functions.
@ SORT_SUBJECT
Sort by the email's subject.
Definition: sort2.h:42
@ SORT_ORDER
Sort by the order the messages appear in the mailbox.
Definition: sort2.h:44
@ SORT_SIZE
Sort by the size of the email.
Definition: sort2.h:40
@ SORT_DESC
Sort by the folder's description.
Definition: sort2.h:59
@ SORT_DATE
Sort by the date the email was sent.
Definition: sort2.h:39
@ SORT_COUNT
Sort by number of emails in a folder.
Definition: sort2.h:54
@ SORT_UNREAD
Sort by the number of unread emails.
Definition: sort2.h:55
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:75
Key value store.
#define NONULL(x)
Definition: string2.h:37
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
The body of an email.
Definition: body.h:36
A NeoMutt function.
Definition: functions.h:44
int op
Op code, e.g. OP_MAIN_LIMIT.
Definition: functions.h:45
browser_function_t function
Function to call.
Definition: functions.h:46
Private state data for the Browser.
Definition: private_data.h:34
char *** files
Array of selected files.
Definition: private_data.h:38
struct Menu * menu
Menu.
Definition: private_data.h:43
struct Buffer * prefix
Folder prefix string.
Definition: private_data.h:49
bool kill_prefix
Prefix is in use.
Definition: private_data.h:44
bool done
Should we close the Dialog?
Definition: private_data.h:53
struct Buffer * OldLastDir
Previous to last dir.
Definition: private_data.h:48
int last_selected_mailbox
Index of last selected Mailbox.
Definition: private_data.h:50
int * numfiles
Number of selected files.
Definition: private_data.h:39
struct Mailbox * mailbox
Mailbox.
Definition: private_data.h:37
struct BrowserState state
State containing list of files/dir/mailboxes.
Definition: private_data.h:42
struct Buffer * file
Buffer for the result.
Definition: private_data.h:36
bool multiple
Allow multiple selections.
Definition: private_data.h:45
struct MuttWindow * win_browser
Browser Window.
Definition: private_data.h:52
struct MuttWindow * sbar
Status Bar.
Definition: private_data.h:51
char goto_swapper[PATH_MAX]
Saved path after <goto-folder>
Definition: private_data.h:47
State of the file/mailbox browser.
Definition: lib.h:111
char * folder
Folder name.
Definition: lib.h:115
bool is_mailbox_list
Viewing mailboxes.
Definition: lib.h:117
struct BrowserStateEntry entry
Array of files / dirs / mailboxes.
Definition: lib.h:112
bool imap_browse
IMAP folder.
Definition: lib.h:114
String manipulation buffer.
Definition: buffer.h:34
size_t dsize
Length of data.
Definition: buffer.h:37
char * data
Pointer to data.
Definition: buffer.h:35
Browser entry representing a folder/dir.
Definition: lib.h:73
bool selectable
Folder can be selected.
Definition: lib.h:92
char delim
Path delimiter.
Definition: lib.h:89
bool imap
This is an IMAP folder.
Definition: lib.h:91
char * name
Name of file/dir/mailbox.
Definition: lib.h:81
bool tagged
Folder is tagged.
Definition: lib.h:97
char * desc
Description of mailbox.
Definition: lib.h:82
mode_t mode
File permissions.
Definition: lib.h:74
bool inferiors
Folder has children.
Definition: lib.h:93
void * mdata
Driver specific data.
Definition: mailbox.h:132
struct MuttWindow * win
Window holding the Menu.
Definition: lib.h:77
int num_tagged
Number of tagged entries.
Definition: lib.h:84
void(* mdata_free)(struct Menu *menu, void **ptr)
Definition: lib.h:152
void * mdata
Private data.
Definition: lib.h:138
void * wdata
Private data.
Definition: mutt_window.h:145
struct MuttWindow * parent
Parent Window.
Definition: mutt_window.h:135
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
NNTP-specific Account data -.
Definition: adata.h:37
unsigned int groups_num
Definition: adata.h:59
void ** groups_list
Definition: adata.h:61
NNTP-specific Mailbox data -.
Definition: mdata.h:33
struct NntpAccountData * adata
Definition: mdata.h:47
Cached regular expression.
Definition: regex3.h:89
char * pattern
printable version
Definition: regex3.h:90
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition: url.h:69
char * path
Path.
Definition: url.h:75
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:305
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:408
struct Url * url_parse(const char *src)
Fill in Url.
Definition: url.c:234
void url_free(struct Url **ptr)
Free the contents of a URL.
Definition: url.c:123