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-ui/lib-ui.h>
16 #include <lib-mx/mx.h>
25 #include <imap/imap.h>
27 typedef struct folder_t {
28 struct folder_file *ff;
32 static char LastDir[_POSIX_PATH_MAX] = "";
33 static char LastDirBackup[_POSIX_PATH_MAX] = "";
35 /* Frees up the memory allocated for the local-global variables. */
36 static void destroy_state (struct browser_state *state)
40 for (c = 0; c < state->entrylen; c++) {
41 p_delete(&state->entry[c].name);
42 p_delete(&state->entry[c].desc);
43 p_delete(&state->entry[c].st);
45 p_delete(&state->folder);
46 p_delete(&state->entry);
49 static int browser_compare_subject (const void *a, const void *b)
51 struct folder_file *pa = (struct folder_file *) a;
52 struct folder_file *pb = (struct folder_file *) b;
54 int r = strcoll(NONULL(pa->name), NONULL(pb->name));
56 return ((BrowserSort & SORT_REVERSE) ? -r : r);
59 static int browser_compare_date (const void *a, const void *b)
61 struct folder_file *pa = (struct folder_file *) a;
62 struct folder_file *pb = (struct folder_file *) b;
64 int r = pa->mtime - pb->mtime;
66 return ((BrowserSort & SORT_REVERSE) ? -r : r);
69 static int browser_compare_size (const void *a, const void *b)
71 struct folder_file *pa = (struct folder_file *) a;
72 struct folder_file *pb = (struct folder_file *) b;
74 int r = pa->size - pb->size;
76 return ((BrowserSort & SORT_REVERSE) ? -r : r);
79 static void browser_sort (struct browser_state *state)
81 int (*f) (const void *, const void *);
83 switch (BrowserSort & SORT_MASK) {
87 f = browser_compare_date;
90 f = browser_compare_size;
94 f = browser_compare_subject;
97 qsort (state->entry, state->entrylen, sizeof (struct folder_file), f);
100 static int link_is_dir (const char *folder, const char *path)
103 char fullpath[_POSIX_PATH_MAX];
105 mutt_concat_path(fullpath, sizeof(fullpath), folder, path);
107 if (stat (fullpath, &st) == 0)
108 return (S_ISDIR (st.st_mode));
114 folder_format_str(char *dest, ssize_t destlen, char op,
115 const char *src, const char *fmt,
116 const char *ifstr, const char *elstr,
117 anytype data, format_flag flags)
119 char fn[STRING], tmp[STRING], permission[11], date[16];
122 FOLDER *folder = data.ptr;
125 int optional = (flags & M_FORMAT_OPTIONAL);
129 snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
130 snprintf (dest, destlen, tmp, folder->num + 1);
134 if (folder->ff->st != NULL) {
137 tnow - folder->ff->st->st_mtime <
138 31536000 ? "%b %d %H:%M" : "%b %d %Y";
139 strftime (date, sizeof (date), t_fmt,
140 localtime (&folder->ff->st->st_mtime));
141 mutt_format_s (dest, destlen, fmt, date);
144 mutt_format_s (dest, destlen, fmt, "");
151 if (folder->ff->imap)
152 s = NONULL(folder->ff->desc);
154 s = NONULL(folder->ff->name);
156 snprintf (fn, sizeof (fn), "%s%s", s,
157 folder->ff->st ? (S_ISLNK (folder->ff->st->st_mode) ? "@" :
158 (S_ISDIR (folder->ff->st->st_mode) ? "/" :
159 ((folder->ff->st->st_mode & S_IXUSR) !=
160 0 ? "*" : ""))) : "");
162 mutt_format_s (dest, destlen, fmt, fn);
166 if (folder->ff->st != NULL) {
167 snprintf (permission, sizeof (permission), "%c%c%c%c%c%c%c%c%c%c",
168 S_ISDIR(folder->ff->st-> st_mode)
169 ? 'd' : (S_ISLNK(folder->ff->st-> st_mode) ? 'l' : '-'),
170 (folder->ff->st->st_mode & S_IRUSR) != 0 ? 'r' : '-',
171 (folder->ff->st->st_mode & S_IWUSR) != 0 ? 'w' : '-',
172 (folder->ff->st->st_mode & S_ISUID) !=
173 0 ? 's' : (folder->ff->st->st_mode & S_IXUSR) !=
175 (folder->ff->st->st_mode & S_IRGRP) != 0 ? 'r' : '-',
176 (folder->ff->st->st_mode & S_IWGRP) != 0 ? 'w' : '-',
177 (folder->ff->st->st_mode & S_ISGID) !=
178 0 ? 's' : (folder->ff->st->st_mode & S_IXGRP) !=
180 (folder->ff->st->st_mode & S_IROTH) != 0 ? 'r' : '-',
181 (folder->ff->st->st_mode & S_IWOTH) != 0 ? 'w' : '-',
182 (folder->ff->st->st_mode & S_ISVTX) !=
183 0 ? 't' : (folder->ff->st->st_mode & S_IXOTH) !=
185 mutt_format_s (dest, destlen, fmt, permission);
187 else if (folder->ff->imap) {
188 /* mark folders with subfolders AND mail */
189 snprintf (permission, sizeof (permission), "IMAP %c",
190 (folder->ff->inferiors
191 && folder->ff->selectable) ? '+' : ' ');
192 mutt_format_s (dest, destlen, fmt, permission);
195 mutt_format_s (dest, destlen, fmt, "");
199 if (folder->ff->st != NULL) {
200 if ((gr = getgrgid (folder->ff->st->st_gid)))
201 mutt_format_s (dest, destlen, fmt, gr->gr_name);
203 snprintf (tmp, sizeof (tmp), "%%%sld", fmt);
204 snprintf (dest, destlen, tmp, folder->ff->st->st_gid);
208 mutt_format_s (dest, destlen, fmt, "");
212 if (folder->ff->st != NULL) {
213 snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
214 snprintf (dest, destlen, tmp, folder->ff->st->st_nlink);
217 mutt_format_s (dest, destlen, fmt, "");
221 if (imap_is_magic (folder->ff->desc, NULL) == M_IMAP) {
223 snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
224 snprintf (dest, destlen, tmp, folder->ff->new);
226 else if (!folder->ff->new)
230 snprintf (tmp, sizeof (tmp), "%%%sc", fmt);
231 snprintf (dest, destlen, tmp, folder->ff->new ? 'N' : ' ');
235 if (folder->ff->st != NULL) {
236 snprintf (tmp, sizeof (tmp), "%%%sld", fmt);
237 snprintf (dest, destlen, tmp, (long) folder->ff->st->st_size);
240 mutt_format_s (dest, destlen, fmt, "");
244 snprintf (tmp, sizeof (tmp), "%%%sc", fmt);
245 snprintf (dest, destlen, tmp, folder->ff->tagged ? '*' : ' ');
249 if (folder->ff->st != NULL) {
250 if ((pw = getpwuid (folder->ff->st->st_uid)))
251 mutt_format_s (dest, destlen, fmt, pw->pw_name);
253 snprintf (tmp, sizeof (tmp), "%%%sld", fmt);
254 snprintf (dest, destlen, tmp, folder->ff->st->st_uid);
258 mutt_format_s (dest, destlen, fmt, "");
262 snprintf (tmp, sizeof (tmp), "%%%sc", fmt);
263 snprintf (dest, destlen, tmp, op);
268 if (flags & M_FORMAT_OPTIONAL)
269 m_strformat(dest, destlen, 0, optional ? ifstr : elstr,
270 folder_format_str, data, 0);
276 static void add_folder (MUTTMENU * m, struct browser_state *state,
277 const char *name, const struct stat *s, int new)
279 if (state->entrylen == state->entrymax) {
280 /* need to allocate more space */
281 p_realloc(&state->entry, state->entrymax += 256);
282 p_clear(&state->entry[state->entrylen], 256);
284 m->data = state->entry;
288 (state->entry)[state->entrylen].mode = s->st_mode;
289 (state->entry)[state->entrylen].mtime = s->st_mtime;
290 (state->entry)[state->entrylen].size = s->st_size;
291 (state->entry)[state->entrylen].st = p_dup(s, 1);
294 (state->entry)[state->entrylen].new = new;
295 (state->entry)[state->entrylen].name = m_strdup(name);
296 (state->entry)[state->entrylen].desc = m_strdup(name);
297 (state->entry)[state->entrylen].imap = 0;
301 static void init_state (struct browser_state *state, MUTTMENU * menu)
304 state->entrymax = 256;
305 state->entry = p_new(struct folder_file, state->entrymax);
306 state->imap_browse = 0;
308 menu->data = state->entry;
311 /* get list of all files/newsgroups with mask */
312 static int examine_directory (MUTTMENU * menu, struct browser_state *state,
313 char *d, const char *prefix)
319 char buffer[_POSIX_PATH_MAX + STRING];
322 while (stat (d, &s) == -1) {
323 if (errno == ENOENT) {
324 /* The last used directory is deleted, try to use the parent dir. */
325 char *c = strrchr (d, '/');
336 if (!S_ISDIR (s.st_mode)) {
337 mutt_error (_("%s is not a directory."), d);
343 if ((dp = opendir (d)) == NULL) {
348 init_state (state, menu);
350 while ((de = readdir (dp)) != NULL) {
351 if (m_strcmp(de->d_name, ".") == 0)
352 continue; /* we don't need . */
354 if (m_strncmp(prefix, de->d_name, m_strlen(prefix)) != 0)
356 if (!((regexec (Mask.rx, de->d_name, 0, NULL, 0) == 0) ^ Mask.neg))
359 mutt_concat_path(buffer, sizeof(buffer), d, de->d_name);
360 if (lstat (buffer, &s) == -1)
363 if ((!S_ISREG (s.st_mode)) && (!S_ISDIR (s.st_mode)) &&
364 (!S_ISLNK (s.st_mode)))
367 i = buffy_lookup (buffer);
368 add_folder (menu, state, de->d_name, &s, i >= 0 ? Incoming.arr[i]->new : 0);
372 browser_sort (state);
376 /* get list of mailboxes/subscribed newsgroups */
377 static int examine_mailboxes (MUTTMENU * menu, struct browser_state *state)
380 char buffer[LONG_STRING];
388 init_state (state, menu);
390 for (i = 0; i < Incoming.len; i++) {
391 tmp = Incoming.arr[i];
392 tmp->magic = mx_get_magic (tmp->path);
393 if (tmp->magic == M_IMAP) {
394 add_folder (menu, state, tmp->path, NULL, tmp->new);
397 if (tmp->magic == M_POP) {
398 add_folder (menu, state, tmp->path, NULL, tmp->new);
401 if (lstat (tmp->path, &s) == -1)
404 if ((!S_ISREG (s.st_mode)) && (!S_ISDIR (s.st_mode)) &&
405 (!S_ISLNK (s.st_mode)))
408 m_strcpy(buffer, sizeof(buffer), NONULL(tmp->path));
409 mutt_pretty_mailbox (buffer);
410 add_folder (menu, state, buffer, &s, tmp->new);
413 browser_sort (state);
417 static int select_file_search (MUTTMENU * menu, regex_t * re, int n)
420 (re, ((struct folder_file *) menu->data)[n].name, 0, NULL, 0));
423 static void folder_entry (char *s, ssize_t slen, MUTTMENU * menu, int num)
427 folder.ff = &((struct folder_file *) menu->data)[num];
430 m_strformat(s, slen, getmaxx(main_w), FolderFormat, folder_format_str,
434 static void init_menu (struct browser_state *state, MUTTMENU * menu,
435 char *title, ssize_t titlelen, int buffy)
437 char path[_POSIX_PATH_MAX];
439 menu->max = state->entrylen;
441 if (menu->current >= menu->max)
442 menu->current = menu->max - 1;
443 if (menu->current < 0)
445 if (menu->top > menu->current)
451 snprintf(title, titlelen, _("Mailboxes [%d]"), buffy_check(0));
453 m_strcpy(path, sizeof(path), LastDir);
454 mutt_pretty_mailbox (path);
455 if (state->imap_browse && option (OPTIMAPLSUB))
456 snprintf (title, titlelen, _("Subscribed [%s], File mask: %s"),
457 path, NONULL (Mask.pattern));
459 snprintf (title, titlelen, _("Directory [%s], File mask: %s"),
460 path, NONULL (Mask.pattern));
462 menu->redraw = REDRAW_FULL;
465 static int file_tag (MUTTMENU * menu, int n, int m)
467 struct folder_file *ff = &(((struct folder_file *) menu->data)[n]);
470 if (S_ISDIR (ff->mode)
471 || (S_ISLNK (ff->mode) && link_is_dir (LastDir, ff->name))) {
472 mutt_error _("Can't attach a directory!");
478 ff->tagged = (m >= 0 ? m : !ff->tagged);
480 return ff->tagged - ot;
483 void mutt_select_file (char *f, ssize_t flen, int flags, char ***files,
486 char buf[_POSIX_PATH_MAX];
487 char prefix[_POSIX_PATH_MAX] = "";
489 struct browser_state state;
492 int i, killPrefix = 0;
493 int multiple = (flags & M_SEL_MULTI) ? 1 : 0;
494 int folder = (flags & M_SEL_FOLDER) ? 1 : 0;
495 int buffy = (flags & M_SEL_BUFFY) ? 1 : 0;
497 buffy = buffy && folder;
502 m_strcpy(LastDirBackup, sizeof(LastDirBackup), LastDir);
505 mutt_expand_path (f, flen);
506 if (imap_is_magic (f, NULL) == M_IMAP) {
507 init_state (&state, NULL);
508 state.imap_browse = 1;
509 if (!imap_browse (f, &state))
510 m_strcpy(LastDir, sizeof(LastDir), state.folder);
513 for (i = m_strlen(f) - 1; i > 0 && f[i] != '/'; i--);
516 i = MIN(ssizeof(LastDir) - 1, i);
517 m_strcpy(LastDir, sizeof(LastDir), f);
520 getcwd(LastDir, sizeof(LastDir));
521 m_strcat(LastDir, sizeof(LastDir), "/");
522 m_strncat(LastDir, sizeof(LastDir), f, i);
527 m_strcpy(LastDir, sizeof(LastDir), "/");
529 getcwd (LastDir, sizeof (LastDir));
532 if (i <= 0 && f[0] != '/')
533 m_strcpy(prefix, sizeof(prefix), f);
535 m_strcpy(prefix, sizeof(prefix), f + i + 1);
541 getcwd (LastDir, sizeof (LastDir));
542 else if (!LastDir[0])
543 m_strcpy(LastDir, sizeof(LastDir), NONULL(Maildir));
545 if (!buffy && imap_is_magic (LastDir, NULL) == M_IMAP) {
546 init_state (&state, NULL);
547 state.imap_browse = 1;
548 imap_browse (LastDir, &state);
549 browser_sort (&state);
556 if (examine_mailboxes (NULL, &state) == -1)
560 if (!state.imap_browse)
561 if (examine_directory (NULL, &state, LastDir, prefix) == -1)
564 menu = mutt_new_menu ();
565 menu->menu = MENU_FOLDER;
566 menu->make_entry = folder_entry;
567 menu->search = select_file_search;
569 menu->data = state.entry;
571 menu->tag = file_tag;
572 init_menu (&state, menu, title, sizeof (title), buffy);
575 switch (i = mutt_menuLoop (menu)) {
576 case OP_GENERIC_SELECT_ENTRY:
578 if (!state.entrylen) {
579 mutt_error _("No files match the file mask");
584 if (S_ISDIR (state.entry[menu->current].mode) ||
585 (S_ISLNK (state.entry[menu->current].mode) &&
586 link_is_dir (LastDir, state.entry[menu->current].name))
587 || state.entry[menu->current].inferiors
589 /* make sure this isn't a MH or maildir mailbox */
591 m_strcpy(buf, sizeof(buf), state.entry[menu->current].name);
592 mutt_expand_path (buf, sizeof (buf));
594 else if (state.imap_browse) {
595 m_strcpy(buf, sizeof(buf), state.entry[menu->current].name);
598 mutt_concat_path(buf, sizeof(buf), LastDir,
599 state.entry[menu->current].name);
601 if ((mx_get_magic (buf) <= 0)
602 || state.entry[menu->current].inferiors)
604 char OldLastDir[_POSIX_PATH_MAX];
606 /* save the old directory */
607 m_strcpy(OldLastDir, sizeof(OldLastDir), LastDir);
609 if (m_strcmp(state.entry[menu->current].name, "..") == 0) {
610 if (m_strcmp("..", LastDir + m_strlen(LastDir) - 2) == 0)
611 m_strcat(LastDir, sizeof(LastDir), "/..");
613 char *p = strrchr (LastDir + 1, '/');
618 if (LastDir[0] == '/')
621 m_strcat(LastDir, sizeof(LastDir), "/..");
626 m_strcpy(LastDir, sizeof(LastDir),
627 state.entry[menu->current].name);
628 mutt_expand_path (LastDir, sizeof (LastDir));
630 else if (state.imap_browse) {
634 m_strcpy(LastDir, sizeof(LastDir),
635 state.entry[menu->current].name);
636 /* tack on delimiter here */
637 n = m_strlen(LastDir) + 1;
639 /* special case "" needs no delimiter */
640 url_parse_ciss (&url, state.entry[menu->current].name);
642 (state.entry[menu->current].delim != '\0') &&
643 (n < ssizeof (LastDir))) {
645 LastDir[n - 1] = state.entry[menu->current].delim;
649 char tmp[_POSIX_PATH_MAX];
651 mutt_concat_path(tmp, sizeof(tmp), LastDir,
652 state.entry[menu->current].name);
653 m_strcpy(LastDir, sizeof(LastDir), tmp);
656 destroy_state (&state);
662 if (state.imap_browse) {
663 init_state (&state, NULL);
664 state.imap_browse = 1;
665 imap_browse (LastDir, &state);
666 browser_sort (&state);
667 menu->data = state.entry;
670 if (examine_directory (menu, &state, LastDir, prefix) == -1) {
671 /* try to restore the old values */
672 m_strcpy(LastDir, sizeof(LastDir), OldLastDir);
673 if (examine_directory (menu, &state, LastDir, prefix) == -1) {
674 m_strcpy(LastDir, sizeof(LastDir), NONULL(mod_core.homedir));
680 init_menu (&state, menu, title, sizeof (title), buffy);
686 m_strcpy(f, flen, state.entry[menu->current].name);
687 mutt_expand_path (f, flen);
689 else if (state.imap_browse)
690 m_strcpy(f, flen, state.entry[menu->current].name);
692 mutt_concat_path(f, flen, LastDir, state.entry[menu->current].name);
694 /* Fall through to OP_EXIT */
704 *numfiles = menu->tagged;
705 tfiles = p_new(char *, *numfiles);
706 for (h = 0, j = 0; h < state.entrylen; i++) {
707 struct folder_file ff = state.entry[i];
708 char full[_POSIX_PATH_MAX];
711 mutt_concat_path(full, sizeof(full), LastDir, ff.name);
712 mutt_expand_path (full, sizeof (full));
713 tfiles[j++] = m_strdup(full);
718 else if (f[0]) { /* no tagged entries. return selected entry */
720 tfiles = p_new(char *, *numfiles);
721 mutt_expand_path (f, flen);
722 tfiles[0] = m_strdup(f);
727 destroy_state (&state);
728 mutt_menuDestroy (&menu);
731 case OP_BROWSER_TELL:
733 mutt_message ("%s", state.entry[menu->current].name);
736 case OP_BROWSER_TOGGLE_LSUB:
737 if (option (OPTIMAPLSUB)) {
738 unset_option (OPTIMAPLSUB);
741 set_option (OPTIMAPLSUB);
743 mutt_ungetch (0, OP_CHECK_NEW);
746 case OP_CREATE_MAILBOX:
747 if (!state.imap_browse)
748 mutt_error (_("Create is only supported for IMAP mailboxes"));
750 imap_mailbox_create (LastDir);
751 /* TODO: find a way to detect if the new folder would appear in
752 * this window, and insert it without starting over. */
753 destroy_state (&state);
754 init_state (&state, NULL);
755 state.imap_browse = 1;
756 imap_browse (LastDir, &state);
757 browser_sort (&state);
758 menu->data = state.entry;
761 init_menu (&state, menu, title, sizeof (title), buffy);
762 MAYBE_REDRAW (menu->redraw);
766 case OP_RENAME_MAILBOX:
767 if (!state.entry[menu->current].imap)
768 mutt_error (_("Rename is only supported for IMAP mailboxes"));
770 int nentry = menu->current;
772 if (imap_mailbox_rename (state.entry[nentry].name) >= 0) {
773 destroy_state (&state);
774 init_state (&state, NULL);
775 state.imap_browse = 1;
776 imap_browse (LastDir, &state);
777 browser_sort (&state);
778 menu->data = state.entry;
781 init_menu (&state, menu, title, sizeof (title), buffy);
782 MAYBE_REDRAW (menu->redraw);
787 case OP_DELETE_MAILBOX:
788 if (!state.entry[menu->current].imap)
789 mutt_error (_("Delete is only supported for IMAP mailboxes"));
793 int nentry = menu->current;
795 imap_parse_path (state.entry[nentry].name, &mx);
796 snprintf (msg, sizeof (msg), _("Really delete mailbox \"%s\"?"),
798 if (mutt_yesorno (msg, M_NO) == M_YES) {
799 if (!imap_delete_mailbox (Context, mx)) {
800 /* free the mailbox from the browser */
801 p_delete(&((state.entry)[nentry].name));
802 p_delete(&((state.entry)[nentry].desc));
803 /* and move all other entries up */
804 if (nentry + 1 < state.entrylen)
805 memmove (state.entry + nentry, state.entry + nentry + 1,
806 sizeof (struct folder_file) * (state.entrylen -
809 mutt_message _("Mailbox deleted.");
811 init_menu (&state, menu, title, sizeof (title), buffy);
812 MAYBE_REDRAW (menu->redraw);
816 mutt_message _("Mailbox not deleted.");
821 case OP_CHANGE_DIRECTORY:
822 m_strcpy(buf, sizeof(buf), LastDir);
823 if (!state.imap_browse)
825 /* add '/' at the end of the directory name if not already there */
826 ssize_t len = m_strlen(LastDir);
828 if (len && LastDir[len - 1] != '/' && ssizeof(buf) > len)
832 if (mutt_get_field (_("Chdir to: "), buf, sizeof (buf), M_FILE) == 0 &&
835 mutt_expand_path (buf, sizeof (buf));
836 if (imap_is_magic (buf, NULL) == M_IMAP) {
837 m_strcpy(LastDir, sizeof(LastDir), buf);
838 destroy_state (&state);
839 init_state (&state, NULL);
840 state.imap_browse = 1;
841 imap_browse (LastDir, &state);
842 browser_sort (&state);
843 menu->data = state.entry;
846 init_menu (&state, menu, title, sizeof (title), buffy);
849 if (stat (buf, &st) == 0) {
850 if (S_ISDIR (st.st_mode)) {
851 destroy_state (&state);
852 if (examine_directory (menu, &state, buf, prefix) == 0)
853 m_strcpy(LastDir, sizeof(LastDir), buf);
855 mutt_error _("Error scanning directory.");
857 if (examine_directory (menu, &state, LastDir, prefix) == -1) {
858 mutt_menuDestroy (&menu);
864 init_menu (&state, menu, title, sizeof (title), buffy);
867 mutt_error (_("%s is not a directory."), buf);
872 MAYBE_REDRAW (menu->redraw);
877 m_strcpy(buf, sizeof(buf), NONULL(Mask.pattern));
878 if (mutt_get_field (_("File Mask: "), buf, sizeof (buf), 0) == 0) {
879 regex_t *rx = p_new(regex_t, 1);
884 /* assume that the user wants to see everything */
886 m_strcpy(buf, sizeof(buf), ".");
889 s = vskipspaces(s + 1);
893 if ((err = REGCOMP (rx, s, REG_NOSUB)) != 0) {
894 regerror (err, rx, buf, sizeof (buf));
897 mutt_error ("%s", buf);
900 m_strreplace(&Mask.pattern, buf);
906 destroy_state (&state);
907 if (state.imap_browse) {
908 init_state (&state, NULL);
909 state.imap_browse = 1;
910 imap_browse (LastDir, &state);
911 browser_sort (&state);
912 menu->data = state.entry;
913 init_menu (&state, menu, title, sizeof (title), buffy);
916 if (examine_directory (menu, &state, LastDir, NULL) == 0)
917 init_menu (&state, menu, title, sizeof (title), buffy);
919 mutt_error _("Error scanning directory.");
921 mutt_menuDestroy (&menu);
925 if (!state.entrylen) {
926 mutt_error _("No files match the file mask");
932 MAYBE_REDRAW (menu->redraw);
936 case OP_SORT_REVERSE:
940 int reverse = (i == OP_SORT_REVERSE);
942 switch (mutt_multi_choice ((reverse) ?
944 ("Reverse sort by (d)ate, (a)lpha, si(z)e or do(n)'t sort? ")
947 ("Sort by (d)ate, (a)lpha, si(z)e or do(n)'t sort? "),
954 BrowserSort = SORT_DATE;
957 case 2: /* (a)lpha */
958 BrowserSort = SORT_SUBJECT;
962 BrowserSort = SORT_SIZE;
965 case 4: /* do(n)'t sort */
966 BrowserSort = SORT_ORDER;
971 BrowserSort |= reverse ? SORT_REVERSE : 0;
972 browser_sort (&state);
973 menu->redraw = REDRAW_FULL;
978 case OP_TOGGLE_MAILBOXES:
982 destroy_state (&state);
987 if (examine_mailboxes (menu, &state) == -1)
990 else if (imap_is_magic (LastDir, NULL) == M_IMAP) {
991 init_state (&state, NULL);
992 state.imap_browse = 1;
993 imap_browse (LastDir, &state);
994 browser_sort (&state);
995 menu->data = state.entry;
997 else if (examine_directory (menu, &state, LastDir, prefix) == -1)
999 init_menu (&state, menu, title, sizeof (title), buffy);
1003 if (option (OPTFORCEBUFFYCHECK))
1008 case OP_BROWSER_NEW_FILE:
1010 snprintf (buf, sizeof (buf), "%s/", LastDir);
1011 if (mutt_get_field (_("New file name: "), buf, sizeof (buf), M_FILE) ==
1013 m_strcpy(f, flen, buf);
1014 destroy_state (&state);
1015 mutt_menuDestroy (&menu);
1018 MAYBE_REDRAW (menu->redraw);
1021 case OP_BROWSER_VIEW_FILE:
1022 if (!state.entrylen) {
1023 mutt_error _("No files match the file mask");
1028 if (state.entry[menu->current].selectable) {
1029 m_strcpy(f, flen, state.entry[menu->current].name);
1030 destroy_state (&state);
1031 mutt_menuDestroy (&menu);
1035 if (S_ISDIR (state.entry[menu->current].mode) ||
1036 (S_ISLNK (state.entry[menu->current].mode) &&
1037 link_is_dir (LastDir, state.entry[menu->current].name))) {
1038 mutt_error _("Can't view a directory");
1044 char nbuf[_POSIX_PATH_MAX];
1046 mutt_concat_path(nbuf, sizeof(nbuf), LastDir,
1047 state.entry[menu->current].name);
1048 b = mutt_make_file_attach (nbuf);
1050 mutt_view_attachment (NULL, b, M_REGULAR, NULL, NULL, 0);
1052 menu->redraw = REDRAW_FULL;
1055 mutt_error _("Error trying to view file");
1059 case OP_BROWSER_SUBSCRIBE:
1060 case OP_BROWSER_UNSUBSCRIBE:
1061 if (i == OP_BROWSER_SUBSCRIBE)
1062 imap_subscribe (state.entry[menu->current].name, 1);
1064 imap_subscribe (state.entry[menu->current].name, 0);
1071 m_strcpy(LastDir, sizeof(LastDir), LastDirBackup);