+ char OldLastDir[_POSIX_PATH_MAX];
+
+ /* save the old directory */
+ m_strcpy(OldLastDir, sizeof(OldLastDir), LastDir);
+
+ if (m_strcmp(state.entry[menu->current].name, "..") == 0) {
+ if (m_strcmp("..", LastDir + m_strlen(LastDir) - 2) == 0)
+ m_strcat(LastDir, sizeof(LastDir), "/..");
+ else {
+ char *p = strrchr (LastDir + 1, '/');
+
+ if (p)
+ *p = 0;
+ else {
+ if (LastDir[0] == '/')
+ LastDir[1] = 0;
+ else
+ m_strcat(LastDir, sizeof(LastDir), "/..");
+ }
+ }
+ }
+ else if (buffy) {
+ m_strcpy(LastDir, sizeof(LastDir),
+ state.entry[menu->current].name);
+ mutt_expand_path (LastDir, sizeof (LastDir));
+ }
+ else if (state.imap_browse) {
+ int n;
+ ciss_url_t url;
+
+ m_strcpy(LastDir, sizeof(LastDir),
+ state.entry[menu->current].name);
+ /* tack on delimiter here */
+ n = m_strlen(LastDir) + 1;
+
+ /* special case "" needs no delimiter */
+ url_parse_ciss (&url, state.entry[menu->current].name);
+ if (url.path &&
+ (state.entry[menu->current].delim != '\0') &&
+ (n < ssizeof (LastDir))) {
+ LastDir[n] = '\0';
+ LastDir[n - 1] = state.entry[menu->current].delim;
+ }
+ }
+ else {
+ char tmp[_POSIX_PATH_MAX];
+
+ mutt_concat_path(tmp, sizeof(tmp), LastDir,
+ state.entry[menu->current].name);
+ m_strcpy(LastDir, sizeof(LastDir), tmp);
+ }
+
+ destroy_state (&state);
+ if (killPrefix) {
+ prefix[0] = 0;
+ killPrefix = 0;
+ }
+ buffy = 0;
+ if (state.imap_browse) {
+ init_state (&state, NULL);
+ state.imap_browse = 1;
+ imap_browse (LastDir, &state);
+ browser_sort (&state);
+ menu->data = state.entry;
+ }
+ else
+ if (examine_directory (menu, &state, LastDir, prefix) == -1) {
+ /* try to restore the old values */
+ m_strcpy(LastDir, sizeof(LastDir), OldLastDir);
+ if (examine_directory (menu, &state, LastDir, prefix) == -1) {
+ m_strcpy(LastDir, sizeof(LastDir), NONULL(mod_core.homedir));
+ goto bail;
+ }
+ }
+ menu->current = 0;
+ menu->top = 0;
+ init_menu (&state, menu, title, sizeof (title), buffy);
+ break;
+ }
+ }
+
+ if (buffy) {
+ m_strcpy(f, flen, state.entry[menu->current].name);
+ mutt_expand_path (f, flen);
+ }
+ else if (state.imap_browse)
+ m_strcpy(f, flen, state.entry[menu->current].name);
+ else
+ mutt_concat_path(f, flen, LastDir, state.entry[menu->current].name);
+
+ /* Fall through to OP_EXIT */
+
+ case OP_EXIT:
+
+ if (multiple) {
+ char **tfiles;
+ int j;
+ int h;
+
+ if (menu->tagged) {
+ *numfiles = menu->tagged;
+ tfiles = p_new(char *, *numfiles);
+ for (h = 0, j = 0; h < state.entrylen; i++) {
+ struct folder_file ff = state.entry[i];
+ char full[_POSIX_PATH_MAX];
+
+ if (ff.tagged) {
+ mutt_concat_path(full, sizeof(full), LastDir, ff.name);
+ mutt_expand_path (full, sizeof (full));
+ tfiles[j++] = m_strdup(full);
+ }
+ }
+ *files = tfiles;
+ }
+ else if (f[0]) { /* no tagged entries. return selected entry */
+ *numfiles = 1;
+ tfiles = p_new(char *, *numfiles);
+ mutt_expand_path (f, flen);
+ tfiles[0] = m_strdup(f);
+ *files = tfiles;
+ }
+ }
+
+ destroy_state (&state);
+ mutt_menuDestroy (&menu);
+ goto bail;
+
+ case OP_BROWSER_TELL:
+ if (state.entrylen)
+ mutt_message ("%s", state.entry[menu->current].name);
+ break;
+
+ case OP_BROWSER_TOGGLE_LSUB:
+ if (option (OPTIMAPLSUB)) {
+ unset_option (OPTIMAPLSUB);
+ }
+ else {
+ set_option (OPTIMAPLSUB);
+ }
+ mutt_ungetch (0, OP_CHECK_NEW);
+ break;
+
+ case OP_CREATE_MAILBOX:
+ if (!state.imap_browse)
+ mutt_error (_("Create is only supported for IMAP mailboxes"));
+ else {
+ imap_mailbox_create (LastDir);
+ /* TODO: find a way to detect if the new folder would appear in
+ * this window, and insert it without starting over. */
+ destroy_state (&state);
+ init_state (&state, NULL);
+ state.imap_browse = 1;
+ imap_browse (LastDir, &state);
+ browser_sort (&state);
+ menu->data = state.entry;
+ menu->current = 0;
+ menu->top = 0;
+ init_menu (&state, menu, title, sizeof (title), buffy);
+ MAYBE_REDRAW (menu->redraw);
+ }
+ break;
+
+ case OP_RENAME_MAILBOX:
+ if (!state.entry[menu->current].imap)
+ mutt_error (_("Rename is only supported for IMAP mailboxes"));
+ else {
+ int nentry = menu->current;
+
+ if (imap_mailbox_rename (state.entry[nentry].name) >= 0) {
+ destroy_state (&state);
+ init_state (&state, NULL);
+ state.imap_browse = 1;
+ imap_browse (LastDir, &state);
+ browser_sort (&state);
+ menu->data = state.entry;
+ menu->current = 0;
+ menu->top = 0;
+ init_menu (&state, menu, title, sizeof (title), buffy);
+ MAYBE_REDRAW (menu->redraw);
+ }
+ }
+ break;
+
+ case OP_DELETE_MAILBOX:
+ if (!state.entry[menu->current].imap)
+ mutt_error (_("Delete is only supported for IMAP mailboxes"));
+ else {
+ char msg[STRING];
+ IMAP_MBOX mx;
+ int nentry = menu->current;
+
+ imap_parse_path (state.entry[nentry].name, &mx);
+ snprintf (msg, sizeof (msg), _("Really delete mailbox \"%s\"?"),
+ mx.mbox);
+ if (mutt_yesorno (msg, M_NO) == M_YES) {
+ if (!imap_delete_mailbox (Context, mx)) {
+ /* free the mailbox from the browser */
+ p_delete(&((state.entry)[nentry].name));
+ p_delete(&((state.entry)[nentry].desc));
+ /* and move all other entries up */
+ if (nentry + 1 < state.entrylen)
+ memmove (state.entry + nentry, state.entry + nentry + 1,
+ sizeof (struct folder_file) * (state.entrylen -
+ (nentry + 1)));
+ state.entrylen--;
+ mutt_message _("Mailbox deleted.");
+
+ init_menu (&state, menu, title, sizeof (title), buffy);
+ MAYBE_REDRAW (menu->redraw);
+ }
+ }
+ else
+ mutt_message _("Mailbox not deleted.");
+ p_delete(&mx.mbox);
+ }
+ break;
+
+ case OP_CHANGE_DIRECTORY:
+ m_strcpy(buf, sizeof(buf), LastDir);
+ if (!state.imap_browse)
+ {
+ /* add '/' at the end of the directory name if not already there */
+ ssize_t len = m_strlen(LastDir);
+
+ if (len && LastDir[len - 1] != '/' && ssizeof(buf) > len)
+ buf[len] = '/';
+ }
+
+ if (mutt_get_field (_("Chdir to: "), buf, sizeof (buf), M_FILE) == 0 &&
+ buf[0]) {
+ buffy = 0;
+ mutt_expand_path (buf, sizeof (buf));
+ if (imap_is_magic (buf, NULL) == M_IMAP) {
+ m_strcpy(LastDir, sizeof(LastDir), buf);
+ destroy_state (&state);
+ init_state (&state, NULL);
+ state.imap_browse = 1;
+ imap_browse (LastDir, &state);
+ browser_sort (&state);
+ menu->data = state.entry;
+ menu->current = 0;
+ menu->top = 0;
+ init_menu (&state, menu, title, sizeof (title), buffy);
+ }
+ else
+ if (stat (buf, &st) == 0) {
+ if (S_ISDIR (st.st_mode)) {
+ destroy_state (&state);
+ if (examine_directory (menu, &state, buf, prefix) == 0)
+ m_strcpy(LastDir, sizeof(LastDir), buf);
+ else {
+ mutt_error _("Error scanning directory.");
+
+ if (examine_directory (menu, &state, LastDir, prefix) == -1) {
+ mutt_menuDestroy (&menu);
+ goto bail;
+ }
+ }
+ menu->current = 0;
+ menu->top = 0;
+ init_menu (&state, menu, title, sizeof (title), buffy);
+ }
+ else
+ mutt_error (_("%s is not a directory."), buf);
+ }
+ else
+ mutt_perror (buf);
+ }
+ MAYBE_REDRAW (menu->redraw);
+ break;
+
+ case OP_ENTER_MASK:
+
+ m_strcpy(buf, sizeof(buf), NONULL(Mask.pattern));
+ if (mutt_get_field (_("File Mask: "), buf, sizeof (buf), 0) == 0) {
+ regex_t *rx = p_new(regex_t, 1);
+ char *s = buf;
+ int neg = 0, err;
+
+ buffy = 0;
+ /* assume that the user wants to see everything */
+ if (!buf[0])
+ m_strcpy(buf, sizeof(buf), ".");
+ s = vskipspaces(s);
+ if (*s == '!') {
+ s = vskipspaces(s + 1);
+ neg = 1;
+ }
+
+ if ((err = REGCOMP (rx, s, REG_NOSUB)) != 0) {
+ regerror (err, rx, buf, sizeof (buf));
+ regfree (rx);
+ p_delete(&rx);
+ mutt_error ("%s", buf);
+ }
+ else {
+ m_strreplace(&Mask.pattern, buf);
+ regfree (Mask.rx);
+ p_delete(&Mask.rx);
+ Mask.rx = rx;
+ Mask.neg = neg;
+
+ destroy_state (&state);
+ if (state.imap_browse) {
+ init_state (&state, NULL);
+ state.imap_browse = 1;
+ imap_browse (LastDir, &state);
+ browser_sort (&state);
+ menu->data = state.entry;
+ init_menu (&state, menu, title, sizeof (title), buffy);
+ }
+ else
+ if (examine_directory (menu, &state, LastDir, NULL) == 0)
+ init_menu (&state, menu, title, sizeof (title), buffy);
+ else {
+ mutt_error _("Error scanning directory.");
+
+ mutt_menuDestroy (&menu);
+ goto bail;
+ }
+ killPrefix = 0;
+ if (!state.entrylen) {
+ mutt_error _("No files match the file mask");
+
+ break;
+ }
+ }
+ }
+ MAYBE_REDRAW (menu->redraw);
+ break;
+
+ case OP_SORT:
+ case OP_SORT_REVERSE:
+
+ {
+ int resort = 1;
+ int reverse = (i == OP_SORT_REVERSE);
+
+ switch (mutt_multi_choice ((reverse) ?
+ _
+ ("Reverse sort by (d)ate, (a)lpha, si(z)e or do(n)'t sort? ")
+ :
+ _
+ ("Sort by (d)ate, (a)lpha, si(z)e or do(n)'t sort? "),
+ _("dazn"))) {
+ case -1: /* abort */
+ resort = 0;
+ break;
+
+ case 1: /* (d)ate */
+ BrowserSort = SORT_DATE;
+ break;
+
+ case 2: /* (a)lpha */
+ BrowserSort = SORT_SUBJECT;
+ break;
+
+ case 3: /* si(z)e */
+ BrowserSort = SORT_SIZE;
+ break;
+
+ case 4: /* do(n)'t sort */
+ BrowserSort = SORT_ORDER;
+ resort = 0;
+ break;
+ }
+ if (resort) {
+ BrowserSort |= reverse ? SORT_REVERSE : 0;
+ browser_sort (&state);
+ menu->redraw = REDRAW_FULL;