2 * Copyright notice from original mutt:
3 * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
5 * This file is part of mutt-ng, see http://www.muttng.org/.
6 * It's licensed under the GNU General Public License,
7 * please see the file GPL in the top level source directory.
10 #include <lib-lib/lib-lib.h>
16 #include <lib-ui/lib-ui.h>
17 #include <lib-ui/enter.h>
18 #include <lib-ui/menu.h>
19 #include <lib-mx/mx.h>
27 #include <imap/imap.h>
29 typedef struct folder_t {
30 struct folder_file *ff;
34 static char LastDir[_POSIX_PATH_MAX] = "";
35 static char LastDirBackup[_POSIX_PATH_MAX] = "";
37 /* Frees up the memory allocated for the local-global variables. */
38 static void destroy_state (struct browser_state *state)
42 for (c = 0; c < state->entrylen; c++) {
43 p_delete(&state->entry[c].name);
44 p_delete(&state->entry[c].desc);
45 p_delete(&state->entry[c].st);
47 p_delete(&state->folder);
48 p_delete(&state->entry);
51 static int browser_compare_subject (const void *a, const void *b)
53 struct folder_file *pa = (struct folder_file *) a;
54 struct folder_file *pb = (struct folder_file *) b;
56 int r = strcoll(NONULL(pa->name), NONULL(pb->name));
58 return ((BrowserSort & SORT_REVERSE) ? -r : r);
61 static int browser_compare_date (const void *a, const void *b)
63 struct folder_file *pa = (struct folder_file *) a;
64 struct folder_file *pb = (struct folder_file *) b;
66 int r = pa->mtime - pb->mtime;
68 return ((BrowserSort & SORT_REVERSE) ? -r : r);
71 static int browser_compare_size (const void *a, const void *b)
73 struct folder_file *pa = (struct folder_file *) a;
74 struct folder_file *pb = (struct folder_file *) b;
76 int r = pa->size - pb->size;
78 return ((BrowserSort & SORT_REVERSE) ? -r : r);
81 static void browser_sort (struct browser_state *state)
83 int (*f) (const void *, const void *);
85 switch (BrowserSort & SORT_MASK) {
89 f = browser_compare_date;
92 f = browser_compare_size;
96 f = browser_compare_subject;
99 qsort (state->entry, state->entrylen, sizeof (struct folder_file), f);
102 static int link_is_dir (const char *folder, const char *path)
105 char fullpath[_POSIX_PATH_MAX];
107 mutt_concat_path(fullpath, sizeof(fullpath), folder, path);
109 if (stat (fullpath, &st) == 0)
110 return (S_ISDIR (st.st_mode));
116 folder_format_str(char *dest, ssize_t destlen, char op,
117 const char *src, const char *fmt,
118 const char *ifstr, const char *elstr,
119 anytype data, format_flag flags)
121 char fn[STRING], tmp[STRING], permission[11], date[16];
124 FOLDER *folder = data.ptr;
127 int optional = (flags & M_FORMAT_OPTIONAL);
131 snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
132 snprintf (dest, destlen, tmp, folder->num + 1);
136 if (folder->ff->st != NULL) {
139 tnow - folder->ff->st->st_mtime <
140 31536000 ? "%b %d %H:%M" : "%b %d %Y";
141 strftime (date, sizeof (date), t_fmt,
142 localtime (&folder->ff->st->st_mtime));
143 mutt_format_s (dest, destlen, fmt, date);
146 mutt_format_s (dest, destlen, fmt, "");
153 if (folder->ff->imap)
154 s = NONULL(folder->ff->desc);
156 s = NONULL(folder->ff->name);
158 snprintf (fn, sizeof (fn), "%s%s", s,
159 folder->ff->st ? (S_ISLNK (folder->ff->st->st_mode) ? "@" :
160 (S_ISDIR (folder->ff->st->st_mode) ? "/" :
161 ((folder->ff->st->st_mode & S_IXUSR) !=
162 0 ? "*" : ""))) : "");
164 mutt_format_s (dest, destlen, fmt, fn);
168 if (folder->ff->st != NULL) {
169 snprintf (permission, sizeof (permission), "%c%c%c%c%c%c%c%c%c%c",
170 S_ISDIR(folder->ff->st-> st_mode)
171 ? 'd' : (S_ISLNK(folder->ff->st-> st_mode) ? 'l' : '-'),
172 (folder->ff->st->st_mode & S_IRUSR) != 0 ? 'r' : '-',
173 (folder->ff->st->st_mode & S_IWUSR) != 0 ? 'w' : '-',
174 (folder->ff->st->st_mode & S_ISUID) !=
175 0 ? 's' : (folder->ff->st->st_mode & S_IXUSR) !=
177 (folder->ff->st->st_mode & S_IRGRP) != 0 ? 'r' : '-',
178 (folder->ff->st->st_mode & S_IWGRP) != 0 ? 'w' : '-',
179 (folder->ff->st->st_mode & S_ISGID) !=
180 0 ? 's' : (folder->ff->st->st_mode & S_IXGRP) !=
182 (folder->ff->st->st_mode & S_IROTH) != 0 ? 'r' : '-',
183 (folder->ff->st->st_mode & S_IWOTH) != 0 ? 'w' : '-',
184 (folder->ff->st->st_mode & S_ISVTX) !=
185 0 ? 't' : (folder->ff->st->st_mode & S_IXOTH) !=
187 mutt_format_s (dest, destlen, fmt, permission);
189 else if (folder->ff->imap) {
190 /* mark folders with subfolders AND mail */
191 snprintf (permission, sizeof (permission), "IMAP %c",
192 (folder->ff->inferiors
193 && folder->ff->selectable) ? '+' : ' ');
194 mutt_format_s (dest, destlen, fmt, permission);
197 mutt_format_s (dest, destlen, fmt, "");
201 if (folder->ff->st != NULL) {
202 if ((gr = getgrgid (folder->ff->st->st_gid)))
203 mutt_format_s (dest, destlen, fmt, gr->gr_name);
205 snprintf (tmp, sizeof (tmp), "%%%sld", fmt);
206 snprintf (dest, destlen, tmp, folder->ff->st->st_gid);
210 mutt_format_s (dest, destlen, fmt, "");
214 if (folder->ff->st != NULL) {
215 snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
216 snprintf (dest, destlen, tmp, folder->ff->st->st_nlink);
219 mutt_format_s (dest, destlen, fmt, "");
223 if (imap_is_magic (folder->ff->desc, NULL) == M_IMAP) {
225 snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
226 snprintf (dest, destlen, tmp, folder->ff->new);
228 else if (!folder->ff->new)
232 snprintf (tmp, sizeof (tmp), "%%%sc", fmt);
233 snprintf (dest, destlen, tmp, folder->ff->new ? 'N' : ' ');
237 if (folder->ff->st != NULL) {
238 snprintf (tmp, sizeof (tmp), "%%%sld", fmt);
239 snprintf (dest, destlen, tmp, (long) folder->ff->st->st_size);
242 mutt_format_s (dest, destlen, fmt, "");
246 snprintf (tmp, sizeof (tmp), "%%%sc", fmt);
247 snprintf (dest, destlen, tmp, folder->ff->tagged ? '*' : ' ');
251 if (folder->ff->st != NULL) {
252 if ((pw = getpwuid (folder->ff->st->st_uid)))
253 mutt_format_s (dest, destlen, fmt, pw->pw_name);
255 snprintf (tmp, sizeof (tmp), "%%%sld", fmt);
256 snprintf (dest, destlen, tmp, folder->ff->st->st_uid);
260 mutt_format_s (dest, destlen, fmt, "");
264 snprintf (tmp, sizeof (tmp), "%%%sc", fmt);
265 snprintf (dest, destlen, tmp, op);
270 if (flags & M_FORMAT_OPTIONAL)
271 m_strformat(dest, destlen, 0, optional ? ifstr : elstr,
272 folder_format_str, data, 0);
278 static void add_folder (MUTTMENU * m, struct browser_state *state,
279 const char *name, const struct stat *s, int new)
281 if (state->entrylen == state->entrymax) {
282 /* need to allocate more space */
283 p_realloc(&state->entry, state->entrymax += 256);
284 p_clear(&state->entry[state->entrylen], 256);
286 m->data = state->entry;
290 (state->entry)[state->entrylen].mode = s->st_mode;
291 (state->entry)[state->entrylen].mtime = s->st_mtime;
292 (state->entry)[state->entrylen].size = s->st_size;
293 (state->entry)[state->entrylen].st = p_dup(s, 1);
296 (state->entry)[state->entrylen].new = new;
297 (state->entry)[state->entrylen].name = m_strdup(name);
298 (state->entry)[state->entrylen].desc = m_strdup(name);
299 (state->entry)[state->entrylen].imap = 0;
303 static void init_state (struct browser_state *state, MUTTMENU * menu)
306 state->entrymax = 256;
307 state->entry = p_new(struct folder_file, state->entrymax);
308 state->imap_browse = 0;
310 menu->data = state->entry;
313 /* get list of all files/newsgroups with mask */
314 static int examine_directory (MUTTMENU * menu, struct browser_state *state,
315 char *d, const char *prefix)
321 char buffer[_POSIX_PATH_MAX + STRING];
324 while (stat (d, &s) == -1) {
325 if (errno == ENOENT) {
326 /* The last used directory is deleted, try to use the parent dir. */
327 char *c = strrchr (d, '/');
338 if (!S_ISDIR (s.st_mode)) {
339 mutt_error (_("%s is not a directory."), d);
345 if ((dp = opendir (d)) == NULL) {
350 init_state (state, menu);
352 while ((de = readdir (dp)) != NULL) {
353 if (m_strcmp(de->d_name, ".") == 0)
354 continue; /* we don't need . */
356 if (m_strncmp(prefix, de->d_name, m_strlen(prefix)) != 0)
358 if (!((regexec (Mask.rx, de->d_name, 0, NULL, 0) == 0) ^ Mask.neg))
361 mutt_concat_path(buffer, sizeof(buffer), d, de->d_name);
362 if (lstat (buffer, &s) == -1)
365 if ((!S_ISREG (s.st_mode)) && (!S_ISDIR (s.st_mode)) &&
366 (!S_ISLNK (s.st_mode)))
369 i = buffy_lookup (buffer);
370 add_folder (menu, state, de->d_name, &s, i >= 0 ? Incoming.arr[i]->new : 0);
374 browser_sort (state);
378 /* get list of mailboxes/subscribed newsgroups */
379 static int examine_mailboxes (MUTTMENU * menu, struct browser_state *state)
382 char buffer[LONG_STRING];
390 init_state (state, menu);
392 for (i = 0; i < Incoming.len; i++) {
393 tmp = Incoming.arr[i];
394 tmp->magic = mx_get_magic (tmp->path);
395 if (tmp->magic == M_IMAP) {
396 add_folder (menu, state, tmp->path, NULL, tmp->new);
399 if (tmp->magic == M_POP) {
400 add_folder (menu, state, tmp->path, NULL, tmp->new);
403 if (lstat (tmp->path, &s) == -1)
406 if ((!S_ISREG (s.st_mode)) && (!S_ISDIR (s.st_mode)) &&
407 (!S_ISLNK (s.st_mode)))
410 m_strcpy(buffer, sizeof(buffer), NONULL(tmp->path));
411 mutt_pretty_mailbox (buffer);
412 add_folder (menu, state, buffer, &s, tmp->new);
415 browser_sort (state);
419 static int select_file_search (MUTTMENU * menu, regex_t * re, int n)
422 (re, ((struct folder_file *) menu->data)[n].name, 0, NULL, 0));
425 static void folder_entry (char *s, ssize_t slen, MUTTMENU * menu, int num)
429 folder.ff = &((struct folder_file *) menu->data)[num];
432 m_strformat(s, slen, getmaxx(main_w), FolderFormat, folder_format_str,
436 static void init_menu (struct browser_state *state, MUTTMENU * menu,
437 char *title, ssize_t titlelen, int buffy)
439 char path[_POSIX_PATH_MAX];
441 menu->max = state->entrylen;
443 if (menu->current >= menu->max)
444 menu->current = menu->max - 1;
445 if (menu->current < 0)
447 if (menu->top > menu->current)
453 snprintf(title, titlelen, _("Mailboxes [%d]"), buffy_check(0));
455 m_strcpy(path, sizeof(path), LastDir);
456 mutt_pretty_mailbox (path);
457 if (state->imap_browse && option (OPTIMAPLSUB))
458 snprintf (title, titlelen, _("Subscribed [%s], File mask: %s"),
459 path, NONULL (Mask.pattern));
461 snprintf (title, titlelen, _("Directory [%s], File mask: %s"),
462 path, NONULL (Mask.pattern));
464 menu->redraw = REDRAW_FULL;
467 static int file_tag (MUTTMENU * menu, int n, int m)
469 struct folder_file *ff = &(((struct folder_file *) menu->data)[n]);
472 if (S_ISDIR (ff->mode)
473 || (S_ISLNK (ff->mode) && link_is_dir (LastDir, ff->name))) {
474 mutt_error _("Can't attach a directory!");
480 ff->tagged = (m >= 0 ? m : !ff->tagged);
482 return ff->tagged - ot;
485 void mutt_select_file (char *f, ssize_t flen, int flags, char ***files,
488 char buf[_POSIX_PATH_MAX];
489 char prefix[_POSIX_PATH_MAX] = "";
491 struct browser_state state;
494 int i, killPrefix = 0;
495 int multiple = (flags & M_SEL_MULTI) ? 1 : 0;
496 int folder = (flags & M_SEL_FOLDER) ? 1 : 0;
497 int buffy = (flags & M_SEL_BUFFY) ? 1 : 0;
499 buffy = buffy && folder;
504 m_strcpy(LastDirBackup, sizeof(LastDirBackup), LastDir);
507 mutt_expand_path (f, flen);
508 if (imap_is_magic (f, NULL) == M_IMAP) {
509 init_state (&state, NULL);
510 state.imap_browse = 1;
511 if (!imap_browse (f, &state))
512 m_strcpy(LastDir, sizeof(LastDir), state.folder);
515 for (i = m_strlen(f) - 1; i > 0 && f[i] != '/'; i--);
518 i = MIN(ssizeof(LastDir) - 1, i);
519 m_strcpy(LastDir, sizeof(LastDir), f);
522 getcwd(LastDir, sizeof(LastDir));
523 m_strcat(LastDir, sizeof(LastDir), "/");
524 m_strncat(LastDir, sizeof(LastDir), f, i);
529 m_strcpy(LastDir, sizeof(LastDir), "/");
531 getcwd (LastDir, sizeof (LastDir));
534 if (i <= 0 && f[0] != '/')
535 m_strcpy(prefix, sizeof(prefix), f);
537 m_strcpy(prefix, sizeof(prefix), f + i + 1);
543 getcwd (LastDir, sizeof (LastDir));
544 else if (!LastDir[0])
545 m_strcpy(LastDir, sizeof(LastDir), NONULL(Maildir));
547 if (!buffy && imap_is_magic (LastDir, NULL) == M_IMAP) {
548 init_state (&state, NULL);
549 state.imap_browse = 1;
550 imap_browse (LastDir, &state);
551 browser_sort (&state);
558 if (examine_mailboxes (NULL, &state) == -1)
562 if (!state.imap_browse)
563 if (examine_directory (NULL, &state, LastDir, prefix) == -1)
566 menu = mutt_new_menu ();
567 menu->menu = MENU_FOLDER;
568 menu->make_entry = folder_entry;
569 menu->search = select_file_search;
571 menu->data = state.entry;
573 menu->tag = file_tag;
574 init_menu (&state, menu, title, sizeof (title), buffy);
577 switch (i = mutt_menuLoop (menu)) {
578 case OP_GENERIC_SELECT_ENTRY:
580 if (!state.entrylen) {
581 mutt_error _("No files match the file mask");
586 if (S_ISDIR (state.entry[menu->current].mode) ||
587 (S_ISLNK (state.entry[menu->current].mode) &&
588 link_is_dir (LastDir, state.entry[menu->current].name))
589 || state.entry[menu->current].inferiors
591 /* make sure this isn't a MH or maildir mailbox */
593 m_strcpy(buf, sizeof(buf), state.entry[menu->current].name);
594 mutt_expand_path (buf, sizeof (buf));
596 else if (state.imap_browse) {
597 m_strcpy(buf, sizeof(buf), state.entry[menu->current].name);
600 mutt_concat_path(buf, sizeof(buf), LastDir,
601 state.entry[menu->current].name);
603 if ((mx_get_magic (buf) <= 0)
604 || state.entry[menu->current].inferiors)
606 char OldLastDir[_POSIX_PATH_MAX];
608 /* save the old directory */
609 m_strcpy(OldLastDir, sizeof(OldLastDir), LastDir);
611 if (m_strcmp(state.entry[menu->current].name, "..") == 0) {
612 if (m_strcmp("..", LastDir + m_strlen(LastDir) - 2) == 0)
613 m_strcat(LastDir, sizeof(LastDir), "/..");
615 char *p = strrchr (LastDir + 1, '/');
620 if (LastDir[0] == '/')
623 m_strcat(LastDir, sizeof(LastDir), "/..");
628 m_strcpy(LastDir, sizeof(LastDir),
629 state.entry[menu->current].name);
630 mutt_expand_path (LastDir, sizeof (LastDir));
632 else if (state.imap_browse) {
636 m_strcpy(LastDir, sizeof(LastDir),
637 state.entry[menu->current].name);
638 /* tack on delimiter here */
639 n = m_strlen(LastDir) + 1;
641 /* special case "" needs no delimiter */
642 url_parse_ciss (&url, state.entry[menu->current].name);
644 (state.entry[menu->current].delim != '\0') &&
645 (n < ssizeof (LastDir))) {
647 LastDir[n - 1] = state.entry[menu->current].delim;
651 char tmp[_POSIX_PATH_MAX];
653 mutt_concat_path(tmp, sizeof(tmp), LastDir,
654 state.entry[menu->current].name);
655 m_strcpy(LastDir, sizeof(LastDir), tmp);
658 destroy_state (&state);
664 if (state.imap_browse) {
665 init_state (&state, NULL);
666 state.imap_browse = 1;
667 imap_browse (LastDir, &state);
668 browser_sort (&state);
669 menu->data = state.entry;
672 if (examine_directory (menu, &state, LastDir, prefix) == -1) {
673 /* try to restore the old values */
674 m_strcpy(LastDir, sizeof(LastDir), OldLastDir);
675 if (examine_directory (menu, &state, LastDir, prefix) == -1) {
676 m_strcpy(LastDir, sizeof(LastDir), NONULL(mod_core.homedir));
682 init_menu (&state, menu, title, sizeof (title), buffy);
688 m_strcpy(f, flen, state.entry[menu->current].name);
689 mutt_expand_path (f, flen);
691 else if (state.imap_browse)
692 m_strcpy(f, flen, state.entry[menu->current].name);
694 mutt_concat_path(f, flen, LastDir, state.entry[menu->current].name);
696 /* Fall through to OP_EXIT */
706 *numfiles = menu->tagged;
707 tfiles = p_new(char *, *numfiles);
708 for (h = 0, j = 0; h < state.entrylen; i++) {
709 struct folder_file ff = state.entry[i];
710 char full[_POSIX_PATH_MAX];
713 mutt_concat_path(full, sizeof(full), LastDir, ff.name);
714 mutt_expand_path (full, sizeof (full));
715 tfiles[j++] = m_strdup(full);
720 else if (f[0]) { /* no tagged entries. return selected entry */
722 tfiles = p_new(char *, *numfiles);
723 mutt_expand_path (f, flen);
724 tfiles[0] = m_strdup(f);
729 destroy_state (&state);
730 mutt_menuDestroy (&menu);
733 case OP_BROWSER_TELL:
735 mutt_message ("%s", state.entry[menu->current].name);
738 case OP_BROWSER_TOGGLE_LSUB:
739 if (option (OPTIMAPLSUB)) {
740 unset_option (OPTIMAPLSUB);
743 set_option (OPTIMAPLSUB);
745 mutt_ungetch (0, OP_CHECK_NEW);
748 case OP_CREATE_MAILBOX:
749 if (!state.imap_browse)
750 mutt_error (_("Create is only supported for IMAP mailboxes"));
752 imap_mailbox_create (LastDir);
753 /* TODO: find a way to detect if the new folder would appear in
754 * this window, and insert it without starting over. */
755 destroy_state (&state);
756 init_state (&state, NULL);
757 state.imap_browse = 1;
758 imap_browse (LastDir, &state);
759 browser_sort (&state);
760 menu->data = state.entry;
763 init_menu (&state, menu, title, sizeof (title), buffy);
764 MAYBE_REDRAW (menu->redraw);
768 case OP_RENAME_MAILBOX:
769 if (!state.entry[menu->current].imap)
770 mutt_error (_("Rename is only supported for IMAP mailboxes"));
772 int nentry = menu->current;
774 if (imap_mailbox_rename (state.entry[nentry].name) >= 0) {
775 destroy_state (&state);
776 init_state (&state, NULL);
777 state.imap_browse = 1;
778 imap_browse (LastDir, &state);
779 browser_sort (&state);
780 menu->data = state.entry;
783 init_menu (&state, menu, title, sizeof (title), buffy);
784 MAYBE_REDRAW (menu->redraw);
789 case OP_DELETE_MAILBOX:
790 if (!state.entry[menu->current].imap)
791 mutt_error (_("Delete is only supported for IMAP mailboxes"));
795 int nentry = menu->current;
797 imap_parse_path (state.entry[nentry].name, &mx);
798 snprintf (msg, sizeof (msg), _("Really delete mailbox \"%s\"?"),
800 if (mutt_yesorno (msg, M_NO) == M_YES) {
801 if (!imap_delete_mailbox (Context, mx)) {
802 /* free the mailbox from the browser */
803 p_delete(&((state.entry)[nentry].name));
804 p_delete(&((state.entry)[nentry].desc));
805 /* and move all other entries up */
806 if (nentry + 1 < state.entrylen)
807 memmove (state.entry + nentry, state.entry + nentry + 1,
808 sizeof (struct folder_file) * (state.entrylen -
811 mutt_message _("Mailbox deleted.");
813 init_menu (&state, menu, title, sizeof (title), buffy);
814 MAYBE_REDRAW (menu->redraw);
818 mutt_message _("Mailbox not deleted.");
823 case OP_CHANGE_DIRECTORY:
824 m_strcpy(buf, sizeof(buf), LastDir);
825 if (!state.imap_browse)
827 /* add '/' at the end of the directory name if not already there */
828 ssize_t len = m_strlen(LastDir);
830 if (len && LastDir[len - 1] != '/' && ssizeof(buf) > len)
834 if (mutt_get_field (_("Chdir to: "), buf, sizeof (buf), M_FILE) == 0 &&
837 mutt_expand_path (buf, sizeof (buf));
838 if (imap_is_magic (buf, NULL) == M_IMAP) {
839 m_strcpy(LastDir, sizeof(LastDir), buf);
840 destroy_state (&state);
841 init_state (&state, NULL);
842 state.imap_browse = 1;
843 imap_browse (LastDir, &state);
844 browser_sort (&state);
845 menu->data = state.entry;
848 init_menu (&state, menu, title, sizeof (title), buffy);
851 if (stat (buf, &st) == 0) {
852 if (S_ISDIR (st.st_mode)) {
853 destroy_state (&state);
854 if (examine_directory (menu, &state, buf, prefix) == 0)
855 m_strcpy(LastDir, sizeof(LastDir), buf);
857 mutt_error _("Error scanning directory.");
859 if (examine_directory (menu, &state, LastDir, prefix) == -1) {
860 mutt_menuDestroy (&menu);
866 init_menu (&state, menu, title, sizeof (title), buffy);
869 mutt_error (_("%s is not a directory."), buf);
874 MAYBE_REDRAW (menu->redraw);
879 m_strcpy(buf, sizeof(buf), NONULL(Mask.pattern));
880 if (mutt_get_field (_("File Mask: "), buf, sizeof (buf), 0) == 0) {
881 regex_t *rx = p_new(regex_t, 1);
886 /* assume that the user wants to see everything */
888 m_strcpy(buf, sizeof(buf), ".");
891 s = vskipspaces(s + 1);
895 if ((err = REGCOMP (rx, s, REG_NOSUB)) != 0) {
896 regerror (err, rx, buf, sizeof (buf));
899 mutt_error ("%s", buf);
902 m_strreplace(&Mask.pattern, buf);
908 destroy_state (&state);
909 if (state.imap_browse) {
910 init_state (&state, NULL);
911 state.imap_browse = 1;
912 imap_browse (LastDir, &state);
913 browser_sort (&state);
914 menu->data = state.entry;
915 init_menu (&state, menu, title, sizeof (title), buffy);
918 if (examine_directory (menu, &state, LastDir, NULL) == 0)
919 init_menu (&state, menu, title, sizeof (title), buffy);
921 mutt_error _("Error scanning directory.");
923 mutt_menuDestroy (&menu);
927 if (!state.entrylen) {
928 mutt_error _("No files match the file mask");
934 MAYBE_REDRAW (menu->redraw);
938 case OP_SORT_REVERSE:
942 int reverse = (i == OP_SORT_REVERSE);
944 switch (mutt_multi_choice ((reverse) ?
946 ("Reverse sort by (d)ate, (a)lpha, si(z)e or do(n)'t sort? ")
949 ("Sort by (d)ate, (a)lpha, si(z)e or do(n)'t sort? "),
956 BrowserSort = SORT_DATE;
959 case 2: /* (a)lpha */
960 BrowserSort = SORT_SUBJECT;
964 BrowserSort = SORT_SIZE;
967 case 4: /* do(n)'t sort */
968 BrowserSort = SORT_ORDER;
973 BrowserSort |= reverse ? SORT_REVERSE : 0;
974 browser_sort (&state);
975 menu->redraw = REDRAW_FULL;
980 case OP_TOGGLE_MAILBOXES:
984 destroy_state (&state);
989 if (examine_mailboxes (menu, &state) == -1)
992 else if (imap_is_magic (LastDir, NULL) == M_IMAP) {
993 init_state (&state, NULL);
994 state.imap_browse = 1;
995 imap_browse (LastDir, &state);
996 browser_sort (&state);
997 menu->data = state.entry;
999 else if (examine_directory (menu, &state, LastDir, prefix) == -1)
1001 init_menu (&state, menu, title, sizeof (title), buffy);
1005 if (option (OPTFORCEBUFFYCHECK))
1010 case OP_BROWSER_NEW_FILE:
1012 snprintf (buf, sizeof (buf), "%s/", LastDir);
1013 if (mutt_get_field (_("New file name: "), buf, sizeof (buf), M_FILE) ==
1015 m_strcpy(f, flen, buf);
1016 destroy_state (&state);
1017 mutt_menuDestroy (&menu);
1020 MAYBE_REDRAW (menu->redraw);
1023 case OP_BROWSER_VIEW_FILE:
1024 if (!state.entrylen) {
1025 mutt_error _("No files match the file mask");
1030 if (state.entry[menu->current].selectable) {
1031 m_strcpy(f, flen, state.entry[menu->current].name);
1032 destroy_state (&state);
1033 mutt_menuDestroy (&menu);
1037 if (S_ISDIR (state.entry[menu->current].mode) ||
1038 (S_ISLNK (state.entry[menu->current].mode) &&
1039 link_is_dir (LastDir, state.entry[menu->current].name))) {
1040 mutt_error _("Can't view a directory");
1046 char nbuf[_POSIX_PATH_MAX];
1048 mutt_concat_path(nbuf, sizeof(nbuf), LastDir,
1049 state.entry[menu->current].name);
1050 b = mutt_make_file_attach (nbuf);
1052 mutt_view_attachment (NULL, b, M_REGULAR, NULL, NULL, 0);
1054 menu->redraw = REDRAW_FULL;
1057 mutt_error _("Error trying to view file");
1061 case OP_BROWSER_SUBSCRIBE:
1062 case OP_BROWSER_UNSUBSCRIBE:
1063 if (i == OP_BROWSER_SUBSCRIBE)
1064 imap_subscribe (state.entry[menu->current].name, 1);
1066 imap_subscribe (state.entry[menu->current].name, 0);
1073 m_strcpy(LastDir, sizeof(LastDir), LastDirBackup);