/* Start the help viewer. */ void do_help_void(void) { #ifndef DISABLE_HELP do_help(); #else if (currmenu == MMAIN) say_there_is_no_help(); else beep(); #endif /* !DISABLE_HELP */ }
/* Our main file browser function. path is the tilde-expanded path we * start browsing from. */ char *do_browser(char *path, DIR *dir) { char *retval = NULL; int kbinput; bool old_const_update = ISSET(CONST_UPDATE); char *prev_dir = NULL; /* The directory we were in before backing up to "..". */ char *ans = NULL; /* The last answer the user typed at the statusbar prompt. */ size_t old_selected; /* The selected file we had before the current selected file. */ functionptrtype func; /* The function of the key the user typed in. */ curs_set(0); blank_statusbar(); bottombars(MBROWSER); wnoutrefresh(bottomwin); UNSET(CONST_UPDATE); ans = mallocstrcpy(NULL, ""); change_browser_directory: /* We go here after we select a new directory. */ /* Start with no key pressed. */ kbinput = ERR; path = mallocstrassn(path, get_full_path(path)); /* Save the current path in order to be used later. */ path_save = path; assert(path != NULL && path[strlen(path) - 1] == '/'); /* Get the file list, and set longest and width in the process. */ browser_init(path, dir); assert(filelist != NULL); /* Sort the file list. */ qsort(filelist, filelist_len, sizeof(char *), diralphasort); /* If prev_dir isn't NULL, select the directory saved in it, and * then blow it away. */ if (prev_dir != NULL) { browser_select_dirname(prev_dir); free(prev_dir); prev_dir = NULL; /* Otherwise, select the first file or directory in the list. */ } else selected = 0; old_selected = (size_t)-1; titlebar(path); while (TRUE) { struct stat st; int i; size_t fileline = selected / width; /* The line number the selected file is on. */ char *new_path; /* The path we switch to at the "Go to Directory" * prompt. */ /* Display the file list if we don't have a key, or if the * selected file has changed, and set width in the process. */ if (kbinput == ERR || old_selected != selected) browser_refresh(); old_selected = selected; kbinput = get_kbinput(edit); #ifndef NANO_TINY if (kbinput == KEY_WINCH) { kbinput = ERR; curs_set(0); continue; } #endif #ifndef DISABLE_MOUSE if (kbinput == KEY_MOUSE) { int mouse_x, mouse_y; /* We can click on the edit window to select a * filename. */ if (get_mouseinput(&mouse_x, &mouse_y, TRUE) == 0 && wmouse_trafo(edit, &mouse_y, &mouse_x, FALSE)) { /* longest is the width of each column. There * are two spaces between each column. */ selected = (fileline / editwinrows) * (editwinrows * width) + (mouse_y * width) + (mouse_x / (longest + 2)); /* If they clicked beyond the end of a row, * select the last filename in that row. */ if (mouse_x > width * (longest + 2)) selected--; /* If we're off the screen, select the last filename. */ if (selected > filelist_len - 1) selected = filelist_len - 1; /* If we selected the same filename as last time, * put back the Enter key so that it's read in. */ if (old_selected == selected) unget_kbinput(sc_seq_or(do_enter, 0), FALSE, FALSE); } } #endif /* !DISABLE_MOUSE */ func = parse_browser_input(&kbinput); if (func == total_refresh) { total_redraw(); } else if (func == do_help_void) { #ifndef DISABLE_HELP do_help_void(); /* Perhaps the window dimensions have changed. */ browser_refresh(); curs_set(0); #else say_there_is_no_help(); #endif } else if (func == do_search) { /* Search for a filename. */ curs_set(1); do_filesearch(); curs_set(0); } else if (func == do_research) { /* Search for another filename. */ do_fileresearch(); } else if (func == do_page_up) { if (selected >= (editwinrows + fileline % editwinrows) * width) selected -= (editwinrows + fileline % editwinrows) * width; else selected = 0; } else if (func == do_page_down) { selected += (editwinrows - fileline % editwinrows) * width; if (selected > filelist_len - 1) selected = filelist_len - 1; } else if (func == do_first_file) { selected = 0; } else if (func == do_last_file) { selected = filelist_len - 1; } else if (func == goto_dir_void) { /* Go to a specific directory. */ curs_set(1); i = do_prompt(TRUE, #ifndef DISABLE_TABCOMP FALSE, #endif MGOTODIR, ans, #ifndef DISABLE_HISTORIES NULL, #endif /* TRANSLATORS: This is a prompt. */ browser_refresh, _("Go To Directory")); curs_set(0); bottombars(MBROWSER); /* If the directory begins with a newline (i.e. an * encoded null), treat it as though it's blank. */ if (i < 0 || *answer == '\n') { statusbar(_("Cancelled")); continue; } else if (i != 0) { /* Put back the "Go to Directory" key and save * answer in ans, so that the file list is displayed * again, the prompt is displayed again, and what we * typed before at the prompt is displayed again. */ unget_kbinput(sc_seq_or(do_gotolinecolumn_void, 0), FALSE, FALSE); ans = mallocstrcpy(ans, answer); continue; } /* Convert newlines to nulls in the directory name. */ sunder(answer); align(&answer); new_path = real_dir_from_tilde(answer); if (new_path[0] != '/') { new_path = charealloc(new_path, strlen(path) + strlen(answer) + 1); sprintf(new_path, "%s%s", path, answer); } #ifndef DISABLE_OPERATINGDIR if (check_operating_dir(new_path, FALSE)) { statusbar(_("Can't go outside of %s in restricted mode"), operating_dir); free(new_path); continue; } #endif dir = opendir(new_path); if (dir == NULL) { /* We can't open this directory for some reason. * Complain. */ statusbar(_("Error reading %s: %s"), answer, strerror(errno)); beep(); free(new_path); continue; } /* Start over again with the new path value. */ free(path); path = new_path; goto change_browser_directory; } else if (func == do_up_void) { if (selected >= width) selected -= width; } else if (func == do_down_void) { if (selected + width <= filelist_len - 1) selected += width; } else if (func == do_left) { if (selected > 0) selected--; } else if (func == do_right) { if (selected < filelist_len - 1) selected++; } else if (func == do_enter) { /* We can't move up from "/". */ if (strcmp(filelist[selected], "/..") == 0) { statusbar(_("Can't move up a directory")); beep(); continue; } #ifndef DISABLE_OPERATINGDIR /* Note: The selected file can be outside the operating * directory if it's ".." or if it's a symlink to a * directory outside the operating directory. */ if (check_operating_dir(filelist[selected], FALSE)) { statusbar(_("Can't go outside of %s in restricted mode"), operating_dir); beep(); continue; } #endif if (stat(filelist[selected], &st) == -1) { /* We can't open this file for some reason. * Complain. */ statusbar(_("Error reading %s: %s"), filelist[selected], strerror(errno)); beep(); continue; } if (!S_ISDIR(st.st_mode)) { /* We've successfully opened a file, we're done, so * get out. */ retval = mallocstrcpy(NULL, filelist[selected]); break; } else if (strcmp(tail(filelist[selected]), "..") == 0) /* We've successfully opened the parent directory, * save the current directory in prev_dir, so that * we can easily return to it by hitting Enter. */ prev_dir = mallocstrcpy(NULL, striponedir(filelist[selected])); dir = opendir(filelist[selected]); if (dir == NULL) { /* We can't open this directory for some reason. * Complain. */ statusbar(_("Error reading %s: %s"), filelist[selected], strerror(errno)); beep(); continue; } path = mallocstrcpy(path, filelist[selected]); /* Start over again with the new path value. */ goto change_browser_directory; } else if (func == do_exit) { /* Exit from the file browser. */ break; } } titlebar(NULL); edit_refresh(); curs_set(1); if (old_const_update) SET(CONST_UPDATE); free(path); free(ans); free_chararray(filelist, filelist_len); filelist = NULL; filelist_len = 0; return retval; }