David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 1 | /************************************************************************** |
Benno Schulenberg | 514cd9a | 2016-08-29 17:10:49 +0200 | [diff] [blame] | 2 | * browser.c -- This file is part of GNU nano. * |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 3 | * * |
Benno Schulenberg | 7a9f4a4 | 2014-04-30 20:18:26 +0000 | [diff] [blame] | 4 | * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, * |
Benno Schulenberg | 2dc9cbe | 2015-04-08 18:40:40 +0000 | [diff] [blame] | 5 | * 2010, 2011, 2013, 2014, 2015 Free Software Foundation, Inc. * |
Benno Schulenberg | 406e524 | 2016-08-29 15:14:18 +0200 | [diff] [blame] | 6 | * Copyright (C) 2015, 2016 Benno Schulenberg * |
Benno Schulenberg | 2dc9cbe | 2015-04-08 18:40:40 +0000 | [diff] [blame] | 7 | * * |
Benno Schulenberg | 514cd9a | 2016-08-29 17:10:49 +0200 | [diff] [blame] | 8 | * GNU nano is free software: you can redistribute it and/or modify * |
| 9 | * it under the terms of the GNU General Public License as published * |
| 10 | * by the Free Software Foundation, either version 3 of the License, * |
| 11 | * or (at your option) any later version. * |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 12 | * * |
Benno Schulenberg | 514cd9a | 2016-08-29 17:10:49 +0200 | [diff] [blame] | 13 | * GNU nano is distributed in the hope that it will be useful, * |
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty * |
| 15 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * |
| 16 | * See the GNU General Public License for more details. * |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 17 | * * |
| 18 | * You should have received a copy of the GNU General Public License * |
Benno Schulenberg | 514cd9a | 2016-08-29 17:10:49 +0200 | [diff] [blame] | 19 | * along with this program. If not, see http://www.gnu.org/licenses/. * |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 20 | * * |
| 21 | **************************************************************************/ |
| 22 | |
David Lawrence Ramsey | 034b994 | 2005-12-08 02:47:10 +0000 | [diff] [blame] | 23 | #include "proto.h" |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 24 | |
Benno Schulenberg | 8cde95e | 2015-07-17 19:38:22 +0000 | [diff] [blame] | 25 | #include <stdint.h> |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 26 | #include <stdio.h> |
| 27 | #include <string.h> |
| 28 | #include <unistd.h> |
| 29 | #include <errno.h> |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 30 | |
| 31 | #ifndef DISABLE_BROWSER |
| 32 | |
David Lawrence Ramsey | 6816007 | 2006-02-18 21:32:29 +0000 | [diff] [blame] | 33 | static char **filelist = NULL; |
David Lawrence Ramsey | 9f2e3f7 | 2006-07-04 21:47:06 +0000 | [diff] [blame] | 34 | /* The list of files to display in the file browser. */ |
David Lawrence Ramsey | 6816007 | 2006-02-18 21:32:29 +0000 | [diff] [blame] | 35 | static size_t filelist_len = 0; |
| 36 | /* The number of files in the list. */ |
| 37 | static int width = 0; |
Benno Schulenberg | 892762d | 2017-01-12 18:00:54 +0100 | [diff] [blame] | 38 | /* The number of files that we can display per screen row. */ |
David Lawrence Ramsey | 6816007 | 2006-02-18 21:32:29 +0000 | [diff] [blame] | 39 | static int longest = 0; |
| 40 | /* The number of columns in the longest filename in the list. */ |
David Lawrence Ramsey | 27ad0cd | 2006-03-23 20:36:29 +0000 | [diff] [blame] | 41 | static size_t selected = 0; |
Benno Schulenberg | 2dc9cbe | 2015-04-08 18:40:40 +0000 | [diff] [blame] | 42 | /* The currently selected filename in the list; zero-based. */ |
David Lawrence Ramsey | 6816007 | 2006-02-18 21:32:29 +0000 | [diff] [blame] | 43 | |
David Lawrence Ramsey | 6e1cd2d | 2007-01-11 21:47:06 +0000 | [diff] [blame] | 44 | /* Our main file browser function. path is the tilde-expanded path we |
David Lawrence Ramsey | 46c29c4 | 2006-07-02 15:54:14 +0000 | [diff] [blame] | 45 | * start browsing from. */ |
Rishabh Dave | bd3f156 | 2016-05-25 11:16:58 +0200 | [diff] [blame] | 46 | char *do_browser(char *path) |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 47 | { |
Rishabh Dave | 8fa72fb | 2016-07-13 14:31:25 +0530 | [diff] [blame] | 48 | char *retval = NULL; |
David Lawrence Ramsey | 6816007 | 2006-02-18 21:32:29 +0000 | [diff] [blame] | 49 | int kbinput; |
Benno Schulenberg | c6ec435 | 2016-05-10 17:46:26 +0200 | [diff] [blame] | 50 | char *present_name = NULL; |
| 51 | /* The name of the currently selected file, or of the directory we |
| 52 | * were in before backing up to "..". */ |
David Lawrence Ramsey | 60d22f0 | 2006-07-05 02:24:23 +0000 | [diff] [blame] | 53 | size_t old_selected; |
Benno Schulenberg | c6ec435 | 2016-05-10 17:46:26 +0200 | [diff] [blame] | 54 | /* The number of the selected file before the current selected file. */ |
Benno Schulenberg | 6418ffa | 2014-07-02 09:29:05 +0000 | [diff] [blame] | 55 | functionptrtype func; |
| 56 | /* The function of the key the user typed in. */ |
Benno Schulenberg | a730b25 | 2016-07-02 13:07:34 +0200 | [diff] [blame] | 57 | DIR *dir; |
| 58 | /* The directory whose contents we are showing. */ |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 59 | |
Benno Schulenberg | 568d2a3 | 2016-02-13 19:41:12 +0000 | [diff] [blame] | 60 | /* Don't show a cursor in the file list. */ |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 61 | curs_set(0); |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 62 | |
Benno Schulenberg | c6ec435 | 2016-05-10 17:46:26 +0200 | [diff] [blame] | 63 | read_directory_contents: |
Rishabh Dave | 8a5b4f6 | 2016-05-10 16:40:01 +0200 | [diff] [blame] | 64 | /* We come here when we refresh or select a new directory. */ |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 65 | |
Benno Schulenberg | 8b28de1 | 2016-07-13 15:04:40 +0200 | [diff] [blame] | 66 | path = free_and_assign(path, get_full_path(path)); |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 67 | |
Rishabh Dave | 8fa72fb | 2016-07-13 14:31:25 +0530 | [diff] [blame] | 68 | if (path != NULL) |
Benno Schulenberg | 956fead | 2016-06-03 12:12:45 +0200 | [diff] [blame] | 69 | dir = opendir(path); |
| 70 | |
| 71 | if (path == NULL || dir == NULL) { |
David Lawrence Ramsey | b5400ff | 2016-11-30 10:20:30 -0600 | [diff] [blame] | 72 | statusline(ALERT, _("Cannot open directory: %s"), strerror(errno)); |
Benno Schulenberg | 956fead | 2016-06-03 12:12:45 +0200 | [diff] [blame] | 73 | /* If we don't have a file list yet, there is nothing to show. */ |
| 74 | if (filelist == NULL) { |
| 75 | napms(1200); |
| 76 | lastmessage = HUSH; |
| 77 | free(path); |
| 78 | free(present_name); |
| 79 | return NULL; |
| 80 | } |
| 81 | path = mallocstrcpy(path, present_path); |
| 82 | present_name = mallocstrcpy(present_name, filelist[selected]); |
| 83 | } |
Benno Schulenberg | 75d64e6 | 2015-05-28 13:02:29 +0000 | [diff] [blame] | 84 | |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 85 | assert(path != NULL && path[strlen(path) - 1] == '/'); |
| 86 | |
Benno Schulenberg | 956fead | 2016-06-03 12:12:45 +0200 | [diff] [blame] | 87 | if (dir != NULL) { |
| 88 | /* Get the file list, and set longest and width in the process. */ |
| 89 | read_the_list(path, dir); |
| 90 | closedir(dir); |
| 91 | dir = NULL; |
| 92 | } |
Rishabh Dave | bd3f156 | 2016-05-25 11:16:58 +0200 | [diff] [blame] | 93 | |
Benno Schulenberg | c6ec435 | 2016-05-10 17:46:26 +0200 | [diff] [blame] | 94 | /* If given, reselect the present_name and then discard it. */ |
| 95 | if (present_name != NULL) { |
| 96 | browser_select_dirname(present_name); |
David Lawrence Ramsey | c0ba4bf | 2006-07-05 01:10:18 +0000 | [diff] [blame] | 97 | |
Benno Schulenberg | c6ec435 | 2016-05-10 17:46:26 +0200 | [diff] [blame] | 98 | free(present_name); |
| 99 | present_name = NULL; |
David Lawrence Ramsey | 2f7c1a0 | 2006-07-05 02:05:24 +0000 | [diff] [blame] | 100 | /* Otherwise, select the first file or directory in the list. */ |
| 101 | } else |
| 102 | selected = 0; |
David Lawrence Ramsey | c0ba4bf | 2006-07-05 01:10:18 +0000 | [diff] [blame] | 103 | |
David Lawrence Ramsey | 60d22f0 | 2006-07-05 02:24:23 +0000 | [diff] [blame] | 104 | old_selected = (size_t)-1; |
| 105 | |
Benno Schulenberg | 956fead | 2016-06-03 12:12:45 +0200 | [diff] [blame] | 106 | present_path = mallocstrcpy(present_path, path); |
| 107 | |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 108 | titlebar(path); |
| 109 | |
Benno Schulenberg | 64039e9 | 2014-06-22 21:21:00 +0000 | [diff] [blame] | 110 | while (TRUE) { |
Benno Schulenberg | 568d2a3 | 2016-02-13 19:41:12 +0000 | [diff] [blame] | 111 | /* Make sure that the cursor is off. */ |
| 112 | curs_set(0); |
Benno Schulenberg | c8f530a | 2016-05-19 20:43:08 +0200 | [diff] [blame] | 113 | lastmessage = HUSH; |
Benno Schulenberg | 568d2a3 | 2016-02-13 19:41:12 +0000 | [diff] [blame] | 114 | |
Benno Schulenberg | 9106cc8 | 2016-05-08 12:01:33 +0200 | [diff] [blame] | 115 | bottombars(MBROWSER); |
| 116 | |
Benno Schulenberg | d9d8eb2 | 2016-06-29 21:22:38 +0200 | [diff] [blame] | 117 | /* Display (or redisplay) the file list if the list itself or |
| 118 | * the selected file has changed. */ |
| 119 | if (old_selected != selected) |
David Lawrence Ramsey | c0ba4bf | 2006-07-05 01:10:18 +0000 | [diff] [blame] | 120 | browser_refresh(); |
David Lawrence Ramsey | a43b108 | 2006-06-30 22:28:37 +0000 | [diff] [blame] | 121 | |
David Lawrence Ramsey | 60d22f0 | 2006-07-05 02:24:23 +0000 | [diff] [blame] | 122 | old_selected = selected; |
| 123 | |
Benno Schulenberg | 7e5324d | 2014-06-30 18:04:33 +0000 | [diff] [blame] | 124 | kbinput = get_kbinput(edit); |
Chris Allegretta | c0b7872 | 2008-03-11 04:52:57 +0000 | [diff] [blame] | 125 | |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 126 | #ifndef DISABLE_MOUSE |
Benno Schulenberg | 1de337d | 2014-06-04 16:02:51 +0000 | [diff] [blame] | 127 | if (kbinput == KEY_MOUSE) { |
Benno Schulenberg | 492e9f6 | 2014-06-20 10:48:26 +0000 | [diff] [blame] | 128 | int mouse_x, mouse_y; |
David Lawrence Ramsey | 2f94f42 | 2006-06-28 22:38:11 +0000 | [diff] [blame] | 129 | |
Benno Schulenberg | b7f1136 | 2016-05-11 10:00:09 +0200 | [diff] [blame] | 130 | /* We can click on the edit window to select a filename. */ |
Benno Schulenberg | 492e9f6 | 2014-06-20 10:48:26 +0000 | [diff] [blame] | 131 | if (get_mouseinput(&mouse_x, &mouse_y, TRUE) == 0 && |
Benno Schulenberg | b7f1136 | 2016-05-11 10:00:09 +0200 | [diff] [blame] | 132 | wmouse_trafo(edit, &mouse_y, &mouse_x, FALSE)) { |
Benno Schulenberg | 492e9f6 | 2014-06-20 10:48:26 +0000 | [diff] [blame] | 133 | /* longest is the width of each column. There |
| 134 | * are two spaces between each column. */ |
Benno Schulenberg | d7d3a87 | 2016-05-17 18:22:42 +0200 | [diff] [blame] | 135 | selected = selected - selected % (editwinrows * width) + |
Benno Schulenberg | b7f1136 | 2016-05-11 10:00:09 +0200 | [diff] [blame] | 136 | (mouse_y * width) + (mouse_x / (longest + 2)); |
David Lawrence Ramsey | 2f94f42 | 2006-06-28 22:38:11 +0000 | [diff] [blame] | 137 | |
Benno Schulenberg | 492e9f6 | 2014-06-20 10:48:26 +0000 | [diff] [blame] | 138 | /* If they clicked beyond the end of a row, |
Benno Schulenberg | 25ce5f6 | 2015-04-07 08:23:52 +0000 | [diff] [blame] | 139 | * select the last filename in that row. */ |
Benno Schulenberg | 492e9f6 | 2014-06-20 10:48:26 +0000 | [diff] [blame] | 140 | if (mouse_x > width * (longest + 2)) |
| 141 | selected--; |
David Lawrence Ramsey | 2f94f42 | 2006-06-28 22:38:11 +0000 | [diff] [blame] | 142 | |
Benno Schulenberg | b7f1136 | 2016-05-11 10:00:09 +0200 | [diff] [blame] | 143 | /* If we're beyond the list, select the last filename. */ |
Benno Schulenberg | 492e9f6 | 2014-06-20 10:48:26 +0000 | [diff] [blame] | 144 | if (selected > filelist_len - 1) |
| 145 | selected = filelist_len - 1; |
David Lawrence Ramsey | bc7dc36 | 2006-07-05 02:34:37 +0000 | [diff] [blame] | 146 | |
Benno Schulenberg | b7f1136 | 2016-05-11 10:00:09 +0200 | [diff] [blame] | 147 | /* If we selected the same filename as last time, fake a |
| 148 | * press of the Enter key so that the file is read in. */ |
Benno Schulenberg | 492e9f6 | 2014-06-20 10:48:26 +0000 | [diff] [blame] | 149 | if (old_selected == selected) |
Benno Schulenberg | 8bf8682 | 2016-12-22 12:13:03 +0100 | [diff] [blame] | 150 | unget_kbinput(KEY_ENTER, FALSE); |
Benno Schulenberg | 492e9f6 | 2014-06-20 10:48:26 +0000 | [diff] [blame] | 151 | } |
Benno Schulenberg | c03ce95 | 2016-05-17 17:49:15 +0200 | [diff] [blame] | 152 | |
| 153 | continue; |
Chris Allegretta | c0b7872 | 2008-03-11 04:52:57 +0000 | [diff] [blame] | 154 | } |
David Lawrence Ramsey | 0ec909c | 2006-05-06 15:07:26 +0000 | [diff] [blame] | 155 | #endif /* !DISABLE_MOUSE */ |
Chris Allegretta | c0b7872 | 2008-03-11 04:52:57 +0000 | [diff] [blame] | 156 | |
Benno Schulenberg | 6418ffa | 2014-07-02 09:29:05 +0000 | [diff] [blame] | 157 | func = parse_browser_input(&kbinput); |
Chris Allegretta | c0b7872 | 2008-03-11 04:52:57 +0000 | [diff] [blame] | 158 | |
Benno Schulenberg | 6418ffa | 2014-07-02 09:29:05 +0000 | [diff] [blame] | 159 | if (func == total_refresh) { |
Benno Schulenberg | 492e9f6 | 2014-06-20 10:48:26 +0000 | [diff] [blame] | 160 | total_redraw(); |
Benno Schulenberg | eedec06 | 2016-05-17 12:48:47 +0200 | [diff] [blame] | 161 | #ifndef NANO_TINY |
Benno Schulenberg | d9aad92 | 2016-06-28 11:11:19 +0200 | [diff] [blame] | 162 | /* Simulate a window resize to force a directory reread. */ |
Benno Schulenberg | c6ec435 | 2016-05-10 17:46:26 +0200 | [diff] [blame] | 163 | kbinput = KEY_WINCH; |
Benno Schulenberg | eedec06 | 2016-05-17 12:48:47 +0200 | [diff] [blame] | 164 | #endif |
Benno Schulenberg | 6418ffa | 2014-07-02 09:29:05 +0000 | [diff] [blame] | 165 | } else if (func == do_help_void) { |
David Lawrence Ramsey | 0ec909c | 2006-05-06 15:07:26 +0000 | [diff] [blame] | 166 | #ifndef DISABLE_HELP |
Benno Schulenberg | 55543ad | 2014-03-26 20:48:51 +0000 | [diff] [blame] | 167 | do_help_void(); |
Benno Schulenberg | eedec06 | 2016-05-17 12:48:47 +0200 | [diff] [blame] | 168 | #ifndef NANO_TINY |
Benno Schulenberg | d9aad92 | 2016-06-28 11:11:19 +0200 | [diff] [blame] | 169 | /* The window dimensions might have changed, so act as if. */ |
Benno Schulenberg | 813f9f7 | 2016-02-13 16:42:30 +0000 | [diff] [blame] | 170 | kbinput = KEY_WINCH; |
Benno Schulenberg | eedec06 | 2016-05-17 12:48:47 +0200 | [diff] [blame] | 171 | #endif |
David Lawrence Ramsey | 0ec909c | 2006-05-06 15:07:26 +0000 | [diff] [blame] | 172 | #else |
Benno Schulenberg | 6847616 | 2015-07-30 18:10:16 +0000 | [diff] [blame] | 173 | say_there_is_no_help(); |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 174 | #endif |
Benno Schulenberg | 6418ffa | 2014-07-02 09:29:05 +0000 | [diff] [blame] | 175 | } else if (func == do_search) { |
Benno Schulenberg | 492e9f6 | 2014-06-20 10:48:26 +0000 | [diff] [blame] | 176 | /* Search for a filename. */ |
Benno Schulenberg | 492e9f6 | 2014-06-20 10:48:26 +0000 | [diff] [blame] | 177 | do_filesearch(); |
Benno Schulenberg | 6418ffa | 2014-07-02 09:29:05 +0000 | [diff] [blame] | 178 | } else if (func == do_research) { |
Benno Schulenberg | 492e9f6 | 2014-06-20 10:48:26 +0000 | [diff] [blame] | 179 | /* Search for another filename. */ |
| 180 | do_fileresearch(); |
Benno Schulenberg | 8b636de | 2016-07-01 12:41:35 +0200 | [diff] [blame] | 181 | } else if (func == do_left) { |
| 182 | if (selected > 0) |
| 183 | selected--; |
| 184 | } else if (func == do_right) { |
| 185 | if (selected < filelist_len - 1) |
| 186 | selected++; |
| 187 | #ifndef NANO_TINY |
| 188 | } else if (func == do_prev_word_void) { |
| 189 | selected -= (selected % width); |
| 190 | } else if (func == do_next_word_void) { |
| 191 | selected += width - 1 - (selected % width); |
| 192 | if (selected >= filelist_len) |
| 193 | selected = filelist_len - 1; |
| 194 | #endif |
| 195 | } else if (func == do_up_void) { |
| 196 | if (selected >= width) |
| 197 | selected -= width; |
| 198 | } else if (func == do_down_void) { |
| 199 | if (selected + width <= filelist_len - 1) |
| 200 | selected += width; |
Benno Schulenberg | 6418ffa | 2014-07-02 09:29:05 +0000 | [diff] [blame] | 201 | } else if (func == do_page_up) { |
Benno Schulenberg | 58404e4 | 2016-05-11 13:29:38 +0200 | [diff] [blame] | 202 | if (selected < width) |
Benno Schulenberg | 492e9f6 | 2014-06-20 10:48:26 +0000 | [diff] [blame] | 203 | selected = 0; |
Benno Schulenberg | 58404e4 | 2016-05-11 13:29:38 +0200 | [diff] [blame] | 204 | else if (selected < editwinrows * width) |
| 205 | selected = selected % width; |
| 206 | else |
| 207 | selected -= editwinrows * width; |
Benno Schulenberg | 6418ffa | 2014-07-02 09:29:05 +0000 | [diff] [blame] | 208 | } else if (func == do_page_down) { |
Benno Schulenberg | 58404e4 | 2016-05-11 13:29:38 +0200 | [diff] [blame] | 209 | if (selected + width >= filelist_len - 1) |
Benno Schulenberg | 492e9f6 | 2014-06-20 10:48:26 +0000 | [diff] [blame] | 210 | selected = filelist_len - 1; |
Benno Schulenberg | 58404e4 | 2016-05-11 13:29:38 +0200 | [diff] [blame] | 211 | else if (selected + editwinrows * width >= filelist_len) |
| 212 | selected = (selected + editwinrows * width - filelist_len) % |
| 213 | width + filelist_len - width; |
| 214 | else |
| 215 | selected += editwinrows * width; |
Benno Schulenberg | 6418ffa | 2014-07-02 09:29:05 +0000 | [diff] [blame] | 216 | } else if (func == do_first_file) { |
Benno Schulenberg | 0c0fbd5 | 2014-06-25 09:05:55 +0000 | [diff] [blame] | 217 | selected = 0; |
Benno Schulenberg | 6418ffa | 2014-07-02 09:29:05 +0000 | [diff] [blame] | 218 | } else if (func == do_last_file) { |
Benno Schulenberg | 0c0fbd5 | 2014-06-25 09:05:55 +0000 | [diff] [blame] | 219 | selected = filelist_len - 1; |
Benno Schulenberg | 6418ffa | 2014-07-02 09:29:05 +0000 | [diff] [blame] | 220 | } else if (func == goto_dir_void) { |
Benno Schulenberg | b7f1136 | 2016-05-11 10:00:09 +0200 | [diff] [blame] | 221 | /* Ask for the directory to go to. */ |
Benno Schulenberg | fd0589d | 2017-01-02 21:12:44 +0100 | [diff] [blame] | 222 | int i = do_prompt(TRUE, FALSE, MGOTODIR, NULL, |
Benno Schulenberg | b341f29 | 2014-06-19 20:05:24 +0000 | [diff] [blame] | 223 | #ifndef DISABLE_HISTORIES |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 224 | NULL, |
| 225 | #endif |
Benno Schulenberg | a2d74f7 | 2014-05-28 14:34:11 +0000 | [diff] [blame] | 226 | /* TRANSLATORS: This is a prompt. */ |
Benno Schulenberg | ec17322 | 2014-05-28 13:27:33 +0000 | [diff] [blame] | 227 | browser_refresh, _("Go To Directory")); |
Benno Schulenberg | f8c33e8 | 2016-07-01 12:22:44 +0200 | [diff] [blame] | 228 | |
Benno Schulenberg | e6350aa | 2016-12-20 21:41:37 +0100 | [diff] [blame] | 229 | if (i < 0) { |
Benno Schulenberg | 492e9f6 | 2014-06-20 10:48:26 +0000 | [diff] [blame] | 230 | statusbar(_("Cancelled")); |
Benno Schulenberg | 492e9f6 | 2014-06-20 10:48:26 +0000 | [diff] [blame] | 231 | continue; |
Benno Schulenberg | 492e9f6 | 2014-06-20 10:48:26 +0000 | [diff] [blame] | 232 | } |
David Lawrence Ramsey | c0dcdf4 | 2006-02-08 19:27:02 +0000 | [diff] [blame] | 233 | |
Benno Schulenberg | 8b28de1 | 2016-07-13 15:04:40 +0200 | [diff] [blame] | 234 | path = free_and_assign(path, real_dir_from_tilde(answer)); |
Benno Schulenberg | 492e9f6 | 2014-06-20 10:48:26 +0000 | [diff] [blame] | 235 | |
Rishabh Dave | 8fa72fb | 2016-07-13 14:31:25 +0530 | [diff] [blame] | 236 | /* If the given path is relative, join it with the current path. */ |
| 237 | if (*path != '/') { |
| 238 | path = charealloc(path, strlen(present_path) + |
| 239 | strlen(answer) + 1); |
| 240 | sprintf(path, "%s%s", present_path, answer); |
Benno Schulenberg | 492e9f6 | 2014-06-20 10:48:26 +0000 | [diff] [blame] | 241 | } |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 242 | |
| 243 | #ifndef DISABLE_OPERATINGDIR |
Rishabh Dave | 8fa72fb | 2016-07-13 14:31:25 +0530 | [diff] [blame] | 244 | if (check_operating_dir(path, FALSE)) { |
Benno Schulenberg | c0c3073 | 2016-06-24 09:19:23 +0200 | [diff] [blame] | 245 | /* TRANSLATORS: This refers to the confining effect of the |
| 246 | * option --operatingdir, not of --restricted. */ |
| 247 | statusline(ALERT, _("Can't go outside of %s"), |
| 248 | full_operating_dir); |
Rishabh Dave | 8fa72fb | 2016-07-13 14:31:25 +0530 | [diff] [blame] | 249 | path = mallocstrcpy(path, present_path); |
Benno Schulenberg | 492e9f6 | 2014-06-20 10:48:26 +0000 | [diff] [blame] | 250 | continue; |
| 251 | } |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 252 | #endif |
Benno Schulenberg | 03a81aa | 2016-07-03 16:18:26 +0200 | [diff] [blame] | 253 | /* Snip any trailing slashes, so the name can be compared. */ |
Rishabh Dave | 8fa72fb | 2016-07-13 14:31:25 +0530 | [diff] [blame] | 254 | while (strlen(path) > 1 && path[strlen(path) - 1] == '/') |
| 255 | path[strlen(path) - 1] = '\0'; |
Rishabh Dave | 4957c11 | 2016-07-01 19:24:28 +0530 | [diff] [blame] | 256 | |
Rishabh Dave | 559858a | 2016-06-21 19:11:40 +0200 | [diff] [blame] | 257 | /* In case the specified directory cannot be entered, select it |
| 258 | * (if it is in the current list) so it will be highlighted. */ |
| 259 | for (i = 0; i < filelist_len; i++) |
Rishabh Dave | 8fa72fb | 2016-07-13 14:31:25 +0530 | [diff] [blame] | 260 | if (strcmp(filelist[i], path) == 0) |
Rishabh Dave | 559858a | 2016-06-21 19:11:40 +0200 | [diff] [blame] | 261 | selected = i; |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 262 | |
Rishabh Dave | 559858a | 2016-06-21 19:11:40 +0200 | [diff] [blame] | 263 | /* Try opening and reading the specified directory. */ |
Benno Schulenberg | c6ec435 | 2016-05-10 17:46:26 +0200 | [diff] [blame] | 264 | goto read_directory_contents; |
Benno Schulenberg | bde996d | 2015-11-11 19:56:35 +0000 | [diff] [blame] | 265 | } else if (func == do_enter) { |
Benno Schulenberg | f8c33e8 | 2016-07-01 12:22:44 +0200 | [diff] [blame] | 266 | struct stat st; |
| 267 | |
Benno Schulenberg | aeab800 | 2016-07-01 12:34:33 +0200 | [diff] [blame] | 268 | /* It isn't possible to move up from the root directory. */ |
Benno Schulenberg | 492e9f6 | 2014-06-20 10:48:26 +0000 | [diff] [blame] | 269 | if (strcmp(filelist[selected], "/..") == 0) { |
Benno Schulenberg | 2535f51 | 2016-04-30 17:31:43 +0200 | [diff] [blame] | 270 | statusline(ALERT, _("Can't move up a directory")); |
Benno Schulenberg | 492e9f6 | 2014-06-20 10:48:26 +0000 | [diff] [blame] | 271 | continue; |
| 272 | } |
David Lawrence Ramsey | 0ec909c | 2006-05-06 15:07:26 +0000 | [diff] [blame] | 273 | |
| 274 | #ifndef DISABLE_OPERATINGDIR |
Benno Schulenberg | 492e9f6 | 2014-06-20 10:48:26 +0000 | [diff] [blame] | 275 | /* Note: The selected file can be outside the operating |
| 276 | * directory if it's ".." or if it's a symlink to a |
| 277 | * directory outside the operating directory. */ |
| 278 | if (check_operating_dir(filelist[selected], FALSE)) { |
Benno Schulenberg | c0c3073 | 2016-06-24 09:19:23 +0200 | [diff] [blame] | 279 | statusline(ALERT, _("Can't go outside of %s"), |
| 280 | full_operating_dir); |
Benno Schulenberg | 492e9f6 | 2014-06-20 10:48:26 +0000 | [diff] [blame] | 281 | continue; |
| 282 | } |
David Lawrence Ramsey | 0ec909c | 2006-05-06 15:07:26 +0000 | [diff] [blame] | 283 | #endif |
Benno Schulenberg | aeab800 | 2016-07-01 12:34:33 +0200 | [diff] [blame] | 284 | /* If for some reason the file is inaccessible, complain. */ |
Benno Schulenberg | 492e9f6 | 2014-06-20 10:48:26 +0000 | [diff] [blame] | 285 | if (stat(filelist[selected], &st) == -1) { |
Benno Schulenberg | 17cf833 | 2016-05-30 09:09:36 +0200 | [diff] [blame] | 286 | statusline(ALERT, _("Error reading %s: %s"), |
Benno Schulenberg | 492e9f6 | 2014-06-20 10:48:26 +0000 | [diff] [blame] | 287 | filelist[selected], strerror(errno)); |
Benno Schulenberg | 17cf833 | 2016-05-30 09:09:36 +0200 | [diff] [blame] | 288 | continue; |
Benno Schulenberg | 492e9f6 | 2014-06-20 10:48:26 +0000 | [diff] [blame] | 289 | } |
David Lawrence Ramsey | 0ec909c | 2006-05-06 15:07:26 +0000 | [diff] [blame] | 290 | |
Benno Schulenberg | aeab800 | 2016-07-01 12:34:33 +0200 | [diff] [blame] | 291 | /* If it isn't a directory, a file was selected -- we're done. */ |
Benno Schulenberg | 492e9f6 | 2014-06-20 10:48:26 +0000 | [diff] [blame] | 292 | if (!S_ISDIR(st.st_mode)) { |
| 293 | retval = mallocstrcpy(NULL, filelist[selected]); |
Benno Schulenberg | 64039e9 | 2014-06-22 21:21:00 +0000 | [diff] [blame] | 294 | break; |
Benno Schulenberg | 3b8989b | 2016-02-25 14:08:47 +0000 | [diff] [blame] | 295 | } |
David Lawrence Ramsey | 0ec909c | 2006-05-06 15:07:26 +0000 | [diff] [blame] | 296 | |
Benno Schulenberg | 956fead | 2016-06-03 12:12:45 +0200 | [diff] [blame] | 297 | /* If we are moving up one level, remember where we came from, so |
Benno Schulenberg | 3b8989b | 2016-02-25 14:08:47 +0000 | [diff] [blame] | 298 | * this directory can be highlighted and easily reentered. */ |
| 299 | if (strcmp(tail(filelist[selected]), "..") == 0) |
Benno Schulenberg | c6ec435 | 2016-05-10 17:46:26 +0200 | [diff] [blame] | 300 | present_name = striponedir(filelist[selected]); |
Benno Schulenberg | 3b8989b | 2016-02-25 14:08:47 +0000 | [diff] [blame] | 301 | |
Benno Schulenberg | 956fead | 2016-06-03 12:12:45 +0200 | [diff] [blame] | 302 | /* Try opening and reading the selected directory. */ |
Rishabh Dave | 8fa72fb | 2016-07-13 14:31:25 +0530 | [diff] [blame] | 303 | path = mallocstrcpy(path, filelist[selected]); |
Benno Schulenberg | c6ec435 | 2016-05-10 17:46:26 +0200 | [diff] [blame] | 304 | goto read_directory_contents; |
Benno Schulenberg | 6418ffa | 2014-07-02 09:29:05 +0000 | [diff] [blame] | 305 | } else if (func == do_exit) { |
Benno Schulenberg | 64039e9 | 2014-06-22 21:21:00 +0000 | [diff] [blame] | 306 | /* Exit from the file browser. */ |
| 307 | break; |
Benno Schulenberg | d9d8eb2 | 2016-06-29 21:22:38 +0200 | [diff] [blame] | 308 | #ifndef NANO_TINY |
| 309 | } else if (kbinput == KEY_WINCH) { |
| 310 | ; |
| 311 | #endif |
Benno Schulenberg | e0c4f9c | 2016-04-27 14:37:31 +0200 | [diff] [blame] | 312 | } else |
| 313 | unbound_key(kbinput); |
Benno Schulenberg | d9d8eb2 | 2016-06-29 21:22:38 +0200 | [diff] [blame] | 314 | |
| 315 | #ifndef NANO_TINY |
| 316 | /* If the window resized, refresh the file list. */ |
| 317 | if (kbinput == KEY_WINCH) { |
| 318 | /* Remember the selected file, to be able to reselect it. */ |
Benno Schulenberg | 62eeda3 | 2016-07-11 20:39:53 +0200 | [diff] [blame] | 319 | present_name = mallocstrcpy(NULL, filelist[selected]); |
Benno Schulenberg | d9d8eb2 | 2016-06-29 21:22:38 +0200 | [diff] [blame] | 320 | /* Reread the contents of the current directory. */ |
Benno Schulenberg | d9d8eb2 | 2016-06-29 21:22:38 +0200 | [diff] [blame] | 321 | goto read_directory_contents; |
| 322 | } |
| 323 | #endif |
David Lawrence Ramsey | a43b108 | 2006-06-30 22:28:37 +0000 | [diff] [blame] | 324 | } |
Benno Schulenberg | 2cd21da | 2016-05-15 11:17:55 +0200 | [diff] [blame] | 325 | |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 326 | titlebar(NULL); |
| 327 | edit_refresh(); |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 328 | |
David Lawrence Ramsey | b08c9f0 | 2006-07-11 18:12:24 +0000 | [diff] [blame] | 329 | free(path); |
David Lawrence Ramsey | b08c9f0 | 2006-07-11 18:12:24 +0000 | [diff] [blame] | 330 | |
| 331 | free_chararray(filelist, filelist_len); |
| 332 | filelist = NULL; |
| 333 | filelist_len = 0; |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 334 | |
| 335 | return retval; |
| 336 | } |
| 337 | |
David Lawrence Ramsey | 31efe99 | 2006-05-10 16:03:59 +0000 | [diff] [blame] | 338 | /* The file browser front end. We check to see if inpath has a |
| 339 | * directory in it. If it does, we start do_browser() from there. |
| 340 | * Otherwise, we start do_browser() from the current directory. */ |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 341 | char *do_browse_from(const char *inpath) |
| 342 | { |
| 343 | struct stat st; |
| 344 | char *path; |
| 345 | /* This holds the tilde-expanded version of inpath. */ |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 346 | |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 347 | path = real_dir_from_tilde(inpath); |
| 348 | |
| 349 | /* Perhaps path is a directory. If so, we'll pass it to |
| 350 | * do_browser(). Or perhaps path is a directory / a file. If so, |
| 351 | * we'll try stripping off the last path element and passing it to |
| 352 | * do_browser(). Or perhaps path doesn't have a directory portion |
| 353 | * at all. If so, we'll just pass the current directory to |
| 354 | * do_browser(). */ |
| 355 | if (stat(path, &st) == -1 || !S_ISDIR(st.st_mode)) { |
Benno Schulenberg | 8b28de1 | 2016-07-13 15:04:40 +0200 | [diff] [blame] | 356 | path = free_and_assign(path, striponedir(path)); |
David Lawrence Ramsey | 2458b29 | 2006-06-30 14:21:29 +0000 | [diff] [blame] | 357 | |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 358 | if (stat(path, &st) == -1 || !S_ISDIR(st.st_mode)) { |
Benno Schulenberg | 2e75c22 | 2016-05-21 21:29:54 +0200 | [diff] [blame] | 359 | char * currentdir = charalloc(PATH_MAX + 1); |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 360 | |
Benno Schulenberg | 2e75c22 | 2016-05-21 21:29:54 +0200 | [diff] [blame] | 361 | free(path); |
| 362 | path = getcwd(currentdir, PATH_MAX + 1); |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 363 | |
Benno Schulenberg | 9576eb6 | 2016-05-21 21:23:49 +0200 | [diff] [blame] | 364 | if (path == NULL) { |
Benno Schulenberg | 2e75c22 | 2016-05-21 21:29:54 +0200 | [diff] [blame] | 365 | free(currentdir); |
David Lawrence Ramsey | b5400ff | 2016-11-30 10:20:30 -0600 | [diff] [blame] | 366 | statusline(MILD, _("The working directory has disappeared")); |
Benno Schulenberg | 9576eb6 | 2016-05-21 21:23:49 +0200 | [diff] [blame] | 367 | beep(); |
| 368 | napms(1200); |
| 369 | return NULL; |
Benno Schulenberg | d7af590 | 2016-12-16 21:28:28 +0100 | [diff] [blame] | 370 | } |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 371 | } |
| 372 | } |
| 373 | |
| 374 | #ifndef DISABLE_OPERATINGDIR |
| 375 | /* If the resulting path isn't in the operating directory, use |
| 376 | * the operating directory instead. */ |
David Lawrence Ramsey | a7bdd2e | 2006-07-05 03:38:49 +0000 | [diff] [blame] | 377 | if (check_operating_dir(path, FALSE)) |
| 378 | path = mallocstrcpy(path, operating_dir); |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 379 | #endif |
| 380 | |
Rishabh Dave | bd3f156 | 2016-05-25 11:16:58 +0200 | [diff] [blame] | 381 | return do_browser(path); |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 382 | } |
| 383 | |
David Lawrence Ramsey | 6816007 | 2006-02-18 21:32:29 +0000 | [diff] [blame] | 384 | /* Set filelist to the list of files contained in the directory path, |
David Lawrence Ramsey | 2f7c1a0 | 2006-07-05 02:05:24 +0000 | [diff] [blame] | 385 | * set filelist_len to the number of files in that list, set longest to |
David Lawrence Ramsey | 4953e49 | 2006-07-05 03:24:39 +0000 | [diff] [blame] | 386 | * the width in columns of the longest filename in that list (between 15 |
David Lawrence Ramsey | f1a8e72 | 2006-07-05 05:14:11 +0000 | [diff] [blame] | 387 | * and COLS), and set width to the number of files that we can display |
Benno Schulenberg | 892762d | 2017-01-12 18:00:54 +0100 | [diff] [blame] | 388 | * per screen row. And sort the list too. */ |
Benno Schulenberg | d3bd855 | 2016-05-25 12:09:22 +0200 | [diff] [blame] | 389 | void read_the_list(const char *path, DIR *dir) |
David Lawrence Ramsey | 6816007 | 2006-02-18 21:32:29 +0000 | [diff] [blame] | 390 | { |
| 391 | const struct dirent *nextdir; |
David Lawrence Ramsey | f1a8e72 | 2006-07-05 05:14:11 +0000 | [diff] [blame] | 392 | size_t i = 0, path_len = strlen(path); |
David Lawrence Ramsey | 6816007 | 2006-02-18 21:32:29 +0000 | [diff] [blame] | 393 | |
David Lawrence Ramsey | 2f7c1a0 | 2006-07-05 02:05:24 +0000 | [diff] [blame] | 394 | assert(path != NULL && path[strlen(path) - 1] == '/' && dir != NULL); |
David Lawrence Ramsey | 6816007 | 2006-02-18 21:32:29 +0000 | [diff] [blame] | 395 | |
| 396 | longest = 0; |
| 397 | |
Benno Schulenberg | 8a058d1 | 2015-08-13 18:22:29 +0000 | [diff] [blame] | 398 | /* Find the length of the longest filename in the current folder. */ |
David Lawrence Ramsey | 6816007 | 2006-02-18 21:32:29 +0000 | [diff] [blame] | 399 | while ((nextdir = readdir(dir)) != NULL) { |
Benno Schulenberg | 8a058d1 | 2015-08-13 18:22:29 +0000 | [diff] [blame] | 400 | size_t name_len = strlenpt(nextdir->d_name); |
David Lawrence Ramsey | 6816007 | 2006-02-18 21:32:29 +0000 | [diff] [blame] | 401 | |
Benno Schulenberg | 8a058d1 | 2015-08-13 18:22:29 +0000 | [diff] [blame] | 402 | if (name_len > longest) |
| 403 | longest = name_len; |
David Lawrence Ramsey | 2f7c1a0 | 2006-07-05 02:05:24 +0000 | [diff] [blame] | 404 | |
| 405 | i++; |
David Lawrence Ramsey | 6816007 | 2006-02-18 21:32:29 +0000 | [diff] [blame] | 406 | } |
| 407 | |
Benno Schulenberg | 8a058d1 | 2015-08-13 18:22:29 +0000 | [diff] [blame] | 408 | /* Put 10 characters' worth of blank space between columns of filenames |
David Lawrence Ramsey | 224b6d5 | 2006-07-02 20:56:34 +0000 | [diff] [blame] | 409 | * in the list whenever possible, as Pico does. */ |
David Lawrence Ramsey | 5ee89c6 | 2006-07-02 20:41:21 +0000 | [diff] [blame] | 410 | longest += 10; |
David Lawrence Ramsey | 6816007 | 2006-02-18 21:32:29 +0000 | [diff] [blame] | 411 | |
Benno Schulenberg | d3bd855 | 2016-05-25 12:09:22 +0200 | [diff] [blame] | 412 | /* If needed, make room for ".. (parent dir)". */ |
Benno Schulenberg | 8a058d1 | 2015-08-13 18:22:29 +0000 | [diff] [blame] | 413 | if (longest < 15) |
| 414 | longest = 15; |
Benno Schulenberg | d3bd855 | 2016-05-25 12:09:22 +0200 | [diff] [blame] | 415 | /* Make sure we're not wider than the window. */ |
Benno Schulenberg | 8a058d1 | 2015-08-13 18:22:29 +0000 | [diff] [blame] | 416 | if (longest > COLS) |
| 417 | longest = COLS; |
| 418 | |
| 419 | rewinddir(dir); |
| 420 | |
Benno Schulenberg | 42ac536 | 2015-11-30 16:44:44 +0000 | [diff] [blame] | 421 | free_chararray(filelist, filelist_len); |
David Lawrence Ramsey | 87b37bd | 2006-07-11 17:25:12 +0000 | [diff] [blame] | 422 | |
| 423 | filelist_len = i; |
| 424 | |
David Lawrence Ramsey | 6816007 | 2006-02-18 21:32:29 +0000 | [diff] [blame] | 425 | filelist = (char **)nmalloc(filelist_len * sizeof(char *)); |
| 426 | |
David Lawrence Ramsey | 6816007 | 2006-02-18 21:32:29 +0000 | [diff] [blame] | 427 | i = 0; |
| 428 | |
| 429 | while ((nextdir = readdir(dir)) != NULL && i < filelist_len) { |
| 430 | /* Don't show the "." entry. */ |
| 431 | if (strcmp(nextdir->d_name, ".") == 0) |
Benno Schulenberg | a8a23ab | 2014-06-10 19:12:14 +0000 | [diff] [blame] | 432 | continue; |
David Lawrence Ramsey | 6816007 | 2006-02-18 21:32:29 +0000 | [diff] [blame] | 433 | |
| 434 | filelist[i] = charalloc(path_len + strlen(nextdir->d_name) + 1); |
| 435 | sprintf(filelist[i], "%s%s", path, nextdir->d_name); |
David Lawrence Ramsey | 2f7c1a0 | 2006-07-05 02:05:24 +0000 | [diff] [blame] | 436 | |
David Lawrence Ramsey | 6816007 | 2006-02-18 21:32:29 +0000 | [diff] [blame] | 437 | i++; |
| 438 | } |
| 439 | |
| 440 | /* Maybe the number of files in the directory changed between the |
| 441 | * first time we scanned and the second. i is the actual length of |
| 442 | * filelist, so record it. */ |
| 443 | filelist_len = i; |
David Lawrence Ramsey | 2f7c1a0 | 2006-07-05 02:05:24 +0000 | [diff] [blame] | 444 | |
Benno Schulenberg | d3bd855 | 2016-05-25 12:09:22 +0200 | [diff] [blame] | 445 | assert(filelist != NULL); |
| 446 | |
| 447 | /* Sort the list of names. */ |
| 448 | qsort(filelist, filelist_len, sizeof(char *), diralphasort); |
| 449 | |
Benno Schulenberg | 8ddc5e7 | 2016-05-10 21:04:33 +0200 | [diff] [blame] | 450 | /* Calculate how many files fit on a line -- feigning room for two |
| 451 | * spaces beyond the right edge, and adding two spaces of padding |
| 452 | * between columns. */ |
| 453 | width = (COLS + 2) / (longest + 2); |
David Lawrence Ramsey | 6816007 | 2006-02-18 21:32:29 +0000 | [diff] [blame] | 454 | } |
| 455 | |
Benno Schulenberg | 6418ffa | 2014-07-02 09:29:05 +0000 | [diff] [blame] | 456 | /* Return the function that is bound to the given key, accepting certain |
| 457 | * plain characters too, for compatibility with Pico. */ |
| 458 | functionptrtype parse_browser_input(int *kbinput) |
David Lawrence Ramsey | 91a2a69 | 2006-02-07 04:41:44 +0000 | [diff] [blame] | 459 | { |
Benno Schulenberg | 7e5324d | 2014-06-30 18:04:33 +0000 | [diff] [blame] | 460 | if (!meta_key) { |
David Lawrence Ramsey | 91a2a69 | 2006-02-07 04:41:44 +0000 | [diff] [blame] | 461 | switch (*kbinput) { |
| 462 | case ' ': |
Benno Schulenberg | 6418ffa | 2014-07-02 09:29:05 +0000 | [diff] [blame] | 463 | return do_page_down; |
David Lawrence Ramsey | 91a2a69 | 2006-02-07 04:41:44 +0000 | [diff] [blame] | 464 | case '-': |
Benno Schulenberg | 6418ffa | 2014-07-02 09:29:05 +0000 | [diff] [blame] | 465 | return do_page_up; |
David Lawrence Ramsey | 91a2a69 | 2006-02-07 04:41:44 +0000 | [diff] [blame] | 466 | case '?': |
Benno Schulenberg | 6418ffa | 2014-07-02 09:29:05 +0000 | [diff] [blame] | 467 | return do_help_void; |
David Lawrence Ramsey | 91a2a69 | 2006-02-07 04:41:44 +0000 | [diff] [blame] | 468 | case 'E': |
| 469 | case 'e': |
Benno Schulenberg | 6418ffa | 2014-07-02 09:29:05 +0000 | [diff] [blame] | 470 | return do_exit; |
David Lawrence Ramsey | 91a2a69 | 2006-02-07 04:41:44 +0000 | [diff] [blame] | 471 | case 'G': |
| 472 | case 'g': |
Benno Schulenberg | 6418ffa | 2014-07-02 09:29:05 +0000 | [diff] [blame] | 473 | return goto_dir_void; |
David Lawrence Ramsey | 91a2a69 | 2006-02-07 04:41:44 +0000 | [diff] [blame] | 474 | case 'S': |
| 475 | case 's': |
Benno Schulenberg | bde996d | 2015-11-11 19:56:35 +0000 | [diff] [blame] | 476 | return do_enter; |
David Lawrence Ramsey | e38b808 | 2006-03-30 07:03:04 +0000 | [diff] [blame] | 477 | case 'W': |
| 478 | case 'w': |
Benno Schulenberg | 6418ffa | 2014-07-02 09:29:05 +0000 | [diff] [blame] | 479 | return do_search; |
David Lawrence Ramsey | 91a2a69 | 2006-02-07 04:41:44 +0000 | [diff] [blame] | 480 | } |
| 481 | } |
Benno Schulenberg | 6418ffa | 2014-07-02 09:29:05 +0000 | [diff] [blame] | 482 | return func_from_key(kbinput); |
David Lawrence Ramsey | 91a2a69 | 2006-02-07 04:41:44 +0000 | [diff] [blame] | 483 | } |
| 484 | |
Benno Schulenberg | 892762d | 2017-01-12 18:00:54 +0100 | [diff] [blame] | 485 | /* Set width to the number of files that we can display per screen row, |
| 486 | * if necessary, and display the list of files. */ |
David Lawrence Ramsey | 6816007 | 2006-02-18 21:32:29 +0000 | [diff] [blame] | 487 | void browser_refresh(void) |
David Lawrence Ramsey | d4bae13 | 2006-02-09 23:26:26 +0000 | [diff] [blame] | 488 | { |
David Lawrence Ramsey | b0c1bc2 | 2006-06-29 15:46:05 +0000 | [diff] [blame] | 489 | size_t i; |
Benno Schulenberg | 892762d | 2017-01-12 18:00:54 +0100 | [diff] [blame] | 490 | int row = 0, col = 0; |
| 491 | /* The current row and column while the list is getting displayed. */ |
| 492 | int the_row = 0, the_column = 0; |
| 493 | /* The row and column of the selected item. */ |
Benno Schulenberg | b55e8d7 | 2016-03-21 20:49:29 +0000 | [diff] [blame] | 494 | char *info; |
Benno Schulenberg | a338798 | 2015-05-03 13:56:51 +0000 | [diff] [blame] | 495 | /* The additional information that we'll display about a file. */ |
David Lawrence Ramsey | 99c87cc | 2006-06-30 02:44:11 +0000 | [diff] [blame] | 496 | |
Benno Schulenberg | e255627 | 2016-04-30 21:22:16 +0200 | [diff] [blame] | 497 | titlebar(present_path); |
David Lawrence Ramsey | d4bae13 | 2006-02-09 23:26:26 +0000 | [diff] [blame] | 498 | blank_edit(); |
| 499 | |
| 500 | wmove(edit, 0, 0); |
| 501 | |
Benno Schulenberg | d7d3a87 | 2016-05-17 18:22:42 +0200 | [diff] [blame] | 502 | i = selected - selected % (editwinrows * width); |
David Lawrence Ramsey | b0c1bc2 | 2006-06-29 15:46:05 +0000 | [diff] [blame] | 503 | |
Benno Schulenberg | 892762d | 2017-01-12 18:00:54 +0100 | [diff] [blame] | 504 | for (; i < filelist_len && row < editwinrows; i++) { |
David Lawrence Ramsey | 99c87cc | 2006-06-30 02:44:11 +0000 | [diff] [blame] | 505 | struct stat st; |
Benno Schulenberg | b55e8d7 | 2016-03-21 20:49:29 +0000 | [diff] [blame] | 506 | const char *thename = tail(filelist[i]); |
David Lawrence Ramsey | a0283b7 | 2006-07-04 03:49:15 +0000 | [diff] [blame] | 507 | /* The filename we display, minus the path. */ |
Benno Schulenberg | b55e8d7 | 2016-03-21 20:49:29 +0000 | [diff] [blame] | 508 | size_t namelen = strlenpt(thename); |
David Lawrence Ramsey | a0283b7 | 2006-07-04 03:49:15 +0000 | [diff] [blame] | 509 | /* The length of the filename in columns. */ |
Benno Schulenberg | b55e8d7 | 2016-03-21 20:49:29 +0000 | [diff] [blame] | 510 | size_t infolen; |
David Lawrence Ramsey | 458d004 | 2006-07-04 21:46:34 +0000 | [diff] [blame] | 511 | /* The length of the file information in columns. */ |
Benno Schulenberg | b55e8d7 | 2016-03-21 20:49:29 +0000 | [diff] [blame] | 512 | int infomaxlen = 7; |
Benno Schulenberg | 09e95b2 | 2016-09-11 11:26:09 +0200 | [diff] [blame] | 513 | /* The maximum length of the file information in columns: |
| 514 | * normally seven, but will be twelve for "(parent dir)". */ |
Benno Schulenberg | b55e8d7 | 2016-03-21 20:49:29 +0000 | [diff] [blame] | 515 | bool dots = (COLS >= 15 && namelen >= longest - infomaxlen); |
Benno Schulenberg | 09e95b2 | 2016-09-11 11:26:09 +0200 | [diff] [blame] | 516 | /* Whether to put an ellipsis before the filename? We don't |
| 517 | * waste space on dots when there are fewer than 15 columns. */ |
| 518 | char *disp = display_string(thename, dots ? |
| 519 | namelen + infomaxlen + 4 - longest : 0, longest, FALSE); |
| 520 | /* The filename (or a fragment of it) in displayable format. |
| 521 | * When a fragment, account for dots plus one space padding. */ |
David Lawrence Ramsey | d4bae13 | 2006-02-09 23:26:26 +0000 | [diff] [blame] | 522 | |
Benno Schulenberg | b92d35d | 2016-09-11 09:41:09 +0200 | [diff] [blame] | 523 | /* If this is the selected item, start its highlighting, and |
| 524 | * remember its location to be able to place the cursor on it. */ |
| 525 | if (i == selected) { |
Benno Schulenberg | c970035 | 2014-05-04 08:53:06 +0000 | [diff] [blame] | 526 | wattron(edit, hilite_attribute); |
Benno Schulenberg | 892762d | 2017-01-12 18:00:54 +0100 | [diff] [blame] | 527 | the_row = row; |
Benno Schulenberg | b92d35d | 2016-09-11 09:41:09 +0200 | [diff] [blame] | 528 | the_column = col; |
| 529 | } |
David Lawrence Ramsey | d4bae13 | 2006-02-09 23:26:26 +0000 | [diff] [blame] | 530 | |
Benno Schulenberg | 892762d | 2017-01-12 18:00:54 +0100 | [diff] [blame] | 531 | blank_row(edit, row, col, longest); |
David Lawrence Ramsey | 85ffaee | 2006-07-02 18:29:49 +0000 | [diff] [blame] | 532 | |
Benno Schulenberg | 09e95b2 | 2016-09-11 11:26:09 +0200 | [diff] [blame] | 533 | /* If the name is too long, we display something like "...ename". */ |
David Lawrence Ramsey | 85ffaee | 2006-07-02 18:29:49 +0000 | [diff] [blame] | 534 | if (dots) |
Benno Schulenberg | 892762d | 2017-01-12 18:00:54 +0100 | [diff] [blame] | 535 | mvwaddstr(edit, row, col, "..."); |
| 536 | mvwaddstr(edit, row, dots ? col + 3 : col, disp); |
David Lawrence Ramsey | 85ffaee | 2006-07-02 18:29:49 +0000 | [diff] [blame] | 537 | |
David Lawrence Ramsey | d4bae13 | 2006-02-09 23:26:26 +0000 | [diff] [blame] | 538 | free(disp); |
| 539 | |
| 540 | col += longest; |
David Lawrence Ramsey | d4bae13 | 2006-02-09 23:26:26 +0000 | [diff] [blame] | 541 | |
Benno Schulenberg | 09e95b2 | 2016-09-11 11:26:09 +0200 | [diff] [blame] | 542 | /* Show information about the file: "--" for symlinks (except when |
| 543 | * they point to a directory) and for files that have disappeared, |
| 544 | * "(dir)" for directories, and the file size for normal files. */ |
David Lawrence Ramsey | d4bae13 | 2006-02-09 23:26:26 +0000 | [diff] [blame] | 545 | if (lstat(filelist[i], &st) == -1 || S_ISLNK(st.st_mode)) { |
David Lawrence Ramsey | 99c87cc | 2006-06-30 02:44:11 +0000 | [diff] [blame] | 546 | if (stat(filelist[i], &st) == -1 || !S_ISDIR(st.st_mode)) |
Benno Schulenberg | b55e8d7 | 2016-03-21 20:49:29 +0000 | [diff] [blame] | 547 | info = mallocstrcpy(NULL, "--"); |
David Lawrence Ramsey | 99c87cc | 2006-06-30 02:44:11 +0000 | [diff] [blame] | 548 | else |
Benno Schulenberg | a338798 | 2015-05-03 13:56:51 +0000 | [diff] [blame] | 549 | /* TRANSLATORS: Try to keep this at most 7 characters. */ |
Benno Schulenberg | b55e8d7 | 2016-03-21 20:49:29 +0000 | [diff] [blame] | 550 | info = mallocstrcpy(NULL, _("(dir)")); |
David Lawrence Ramsey | 458d004 | 2006-07-04 21:46:34 +0000 | [diff] [blame] | 551 | } else if (S_ISDIR(st.st_mode)) { |
Benno Schulenberg | b55e8d7 | 2016-03-21 20:49:29 +0000 | [diff] [blame] | 552 | if (strcmp(thename, "..") == 0) { |
Benno Schulenberg | a338798 | 2015-05-03 13:56:51 +0000 | [diff] [blame] | 553 | /* TRANSLATORS: Try to keep this at most 12 characters. */ |
Benno Schulenberg | b55e8d7 | 2016-03-21 20:49:29 +0000 | [diff] [blame] | 554 | info = mallocstrcpy(NULL, _("(parent dir)")); |
| 555 | infomaxlen = 12; |
David Lawrence Ramsey | 458d004 | 2006-07-04 21:46:34 +0000 | [diff] [blame] | 556 | } else |
Benno Schulenberg | b55e8d7 | 2016-03-21 20:49:29 +0000 | [diff] [blame] | 557 | info = mallocstrcpy(NULL, _("(dir)")); |
David Lawrence Ramsey | 458d004 | 2006-07-04 21:46:34 +0000 | [diff] [blame] | 558 | } else { |
Benno Schulenberg | 8cde95e | 2015-07-17 19:38:22 +0000 | [diff] [blame] | 559 | off_t result = st.st_size; |
David Lawrence Ramsey | afa1542 | 2006-07-04 22:17:39 +0000 | [diff] [blame] | 560 | char modifier; |
| 561 | |
Benno Schulenberg | b55e8d7 | 2016-03-21 20:49:29 +0000 | [diff] [blame] | 562 | info = charalloc(infomaxlen + 1); |
David Lawrence Ramsey | d4bae13 | 2006-02-09 23:26:26 +0000 | [diff] [blame] | 563 | |
Benno Schulenberg | 09e95b2 | 2016-09-11 11:26:09 +0200 | [diff] [blame] | 564 | /* Massage the file size into a human-readable form. */ |
David Lawrence Ramsey | afa1542 | 2006-07-04 22:17:39 +0000 | [diff] [blame] | 565 | if (st.st_size < (1 << 10)) |
Benno Schulenberg | 55d1e1a | 2015-05-08 19:35:47 +0000 | [diff] [blame] | 566 | modifier = ' '; /* bytes */ |
David Lawrence Ramsey | afa1542 | 2006-07-04 22:17:39 +0000 | [diff] [blame] | 567 | else if (st.st_size < (1 << 20)) { |
| 568 | result >>= 10; |
Benno Schulenberg | 55d1e1a | 2015-05-08 19:35:47 +0000 | [diff] [blame] | 569 | modifier = 'K'; /* kilobytes */ |
David Lawrence Ramsey | afa1542 | 2006-07-04 22:17:39 +0000 | [diff] [blame] | 570 | } else if (st.st_size < (1 << 30)) { |
| 571 | result >>= 20; |
Benno Schulenberg | 55d1e1a | 2015-05-08 19:35:47 +0000 | [diff] [blame] | 572 | modifier = 'M'; /* megabytes */ |
David Lawrence Ramsey | afa1542 | 2006-07-04 22:17:39 +0000 | [diff] [blame] | 573 | } else { |
| 574 | result >>= 30; |
Benno Schulenberg | 55d1e1a | 2015-05-08 19:35:47 +0000 | [diff] [blame] | 575 | modifier = 'G'; /* gigabytes */ |
David Lawrence Ramsey | afa1542 | 2006-07-04 22:17:39 +0000 | [diff] [blame] | 576 | } |
| 577 | |
Benno Schulenberg | 09e95b2 | 2016-09-11 11:26:09 +0200 | [diff] [blame] | 578 | /* Show the size if less than a terabyte, else show "(huge)". */ |
Benno Schulenberg | 8cde95e | 2015-07-17 19:38:22 +0000 | [diff] [blame] | 579 | if (result < (1 << 10)) |
Benno Schulenberg | b55e8d7 | 2016-03-21 20:49:29 +0000 | [diff] [blame] | 580 | sprintf(info, "%4ju %cB", (intmax_t)result, modifier); |
Benno Schulenberg | 55d1e1a | 2015-05-08 19:35:47 +0000 | [diff] [blame] | 581 | else |
| 582 | /* TRANSLATORS: Try to keep this at most 7 characters. |
| 583 | * If necessary, you can leave out the parentheses. */ |
Benno Schulenberg | b55e8d7 | 2016-03-21 20:49:29 +0000 | [diff] [blame] | 584 | info = mallocstrcpy(info, _("(huge)")); |
David Lawrence Ramsey | 99c87cc | 2006-06-30 02:44:11 +0000 | [diff] [blame] | 585 | } |
| 586 | |
Benno Schulenberg | b55e8d7 | 2016-03-21 20:49:29 +0000 | [diff] [blame] | 587 | /* Make sure info takes up no more than infomaxlen columns. */ |
| 588 | infolen = strlenpt(info); |
| 589 | if (infolen > infomaxlen) { |
| 590 | null_at(&info, actual_x(info, infomaxlen)); |
| 591 | infolen = infomaxlen; |
David Lawrence Ramsey | 458d004 | 2006-07-04 21:46:34 +0000 | [diff] [blame] | 592 | } |
| 593 | |
Benno Schulenberg | 892762d | 2017-01-12 18:00:54 +0100 | [diff] [blame] | 594 | mvwaddstr(edit, row, col - infolen, info); |
David Lawrence Ramsey | d4bae13 | 2006-02-09 23:26:26 +0000 | [diff] [blame] | 595 | |
Benno Schulenberg | b92d35d | 2016-09-11 09:41:09 +0200 | [diff] [blame] | 596 | /* If this is the selected item, finish its highlighting. */ |
David Lawrence Ramsey | d4bae13 | 2006-02-09 23:26:26 +0000 | [diff] [blame] | 597 | if (i == selected) |
Benno Schulenberg | c970035 | 2014-05-04 08:53:06 +0000 | [diff] [blame] | 598 | wattroff(edit, hilite_attribute); |
David Lawrence Ramsey | d4bae13 | 2006-02-09 23:26:26 +0000 | [diff] [blame] | 599 | |
Benno Schulenberg | b55e8d7 | 2016-03-21 20:49:29 +0000 | [diff] [blame] | 600 | free(info); |
David Lawrence Ramsey | 99c87cc | 2006-06-30 02:44:11 +0000 | [diff] [blame] | 601 | |
David Lawrence Ramsey | d4bae13 | 2006-02-09 23:26:26 +0000 | [diff] [blame] | 602 | /* Add some space between the columns. */ |
| 603 | col += 2; |
| 604 | |
Benno Schulenberg | 892762d | 2017-01-12 18:00:54 +0100 | [diff] [blame] | 605 | /* If the next entry isn't going to fit on the current row, |
| 606 | * move to the next row. */ |
David Lawrence Ramsey | d4bae13 | 2006-02-09 23:26:26 +0000 | [diff] [blame] | 607 | if (col > COLS - longest) { |
Benno Schulenberg | 892762d | 2017-01-12 18:00:54 +0100 | [diff] [blame] | 608 | row++; |
David Lawrence Ramsey | d4bae13 | 2006-02-09 23:26:26 +0000 | [diff] [blame] | 609 | col = 0; |
David Lawrence Ramsey | d4bae13 | 2006-02-09 23:26:26 +0000 | [diff] [blame] | 610 | } |
David Lawrence Ramsey | d4bae13 | 2006-02-09 23:26:26 +0000 | [diff] [blame] | 611 | } |
| 612 | |
Benno Schulenberg | b92d35d | 2016-09-11 09:41:09 +0200 | [diff] [blame] | 613 | /* If requested, put the cursor on the selected item and switch it on. */ |
| 614 | if (ISSET(SHOW_CURSOR)) { |
Benno Schulenberg | 892762d | 2017-01-12 18:00:54 +0100 | [diff] [blame] | 615 | wmove(edit, the_row, the_column); |
Benno Schulenberg | b92d35d | 2016-09-11 09:41:09 +0200 | [diff] [blame] | 616 | curs_set(1); |
| 617 | } |
| 618 | |
David Lawrence Ramsey | d4bae13 | 2006-02-09 23:26:26 +0000 | [diff] [blame] | 619 | wnoutrefresh(edit); |
| 620 | } |
| 621 | |
Benno Schulenberg | 2dc9cbe | 2015-04-08 18:40:40 +0000 | [diff] [blame] | 622 | /* Look for needle. If we find it, set selected to its location. |
| 623 | * Note that needle must be an exact match for a file in the list. */ |
| 624 | void browser_select_dirname(const char *needle) |
David Lawrence Ramsey | d040377 | 2006-06-30 06:41:31 +0000 | [diff] [blame] | 625 | { |
Benno Schulenberg | 2dc9cbe | 2015-04-08 18:40:40 +0000 | [diff] [blame] | 626 | size_t looking_at = 0; |
David Lawrence Ramsey | d040377 | 2006-06-30 06:41:31 +0000 | [diff] [blame] | 627 | |
Benno Schulenberg | 2dc9cbe | 2015-04-08 18:40:40 +0000 | [diff] [blame] | 628 | for (; looking_at < filelist_len; looking_at++) { |
| 629 | if (strcmp(filelist[looking_at], needle) == 0) { |
| 630 | selected = looking_at; |
David Lawrence Ramsey | d040377 | 2006-06-30 06:41:31 +0000 | [diff] [blame] | 631 | break; |
| 632 | } |
| 633 | } |
Rishabh Dave | 8a5b4f6 | 2016-05-10 16:40:01 +0200 | [diff] [blame] | 634 | |
| 635 | /* If the sought name isn't found, move the highlight so that the |
| 636 | * changed selection will be noticed. */ |
Benno Schulenberg | c6ec435 | 2016-05-10 17:46:26 +0200 | [diff] [blame] | 637 | if (looking_at == filelist_len) { |
Rishabh Dave | 8a5b4f6 | 2016-05-10 16:40:01 +0200 | [diff] [blame] | 638 | --selected; |
Benno Schulenberg | c6ec435 | 2016-05-10 17:46:26 +0200 | [diff] [blame] | 639 | |
| 640 | /* Make sure we stay within the available range. */ |
| 641 | if (selected >= filelist_len) |
| 642 | selected = filelist_len - 1; |
| 643 | } |
David Lawrence Ramsey | d040377 | 2006-06-30 06:41:31 +0000 | [diff] [blame] | 644 | } |
| 645 | |
Benno Schulenberg | 4e5ea18 | 2015-04-12 09:04:30 +0000 | [diff] [blame] | 646 | /* Set up the system variables for a filename search. Return -1 or -2 if |
| 647 | * the search should be canceled (due to Cancel or a blank search string), |
| 648 | * return 0 when we have a string, and return a positive value when some |
| 649 | * function was run. */ |
David Lawrence Ramsey | e38b808 | 2006-03-30 07:03:04 +0000 | [diff] [blame] | 650 | int filesearch_init(void) |
| 651 | { |
Benno Schulenberg | 99d2358 | 2015-04-12 08:31:53 +0000 | [diff] [blame] | 652 | int input; |
David Lawrence Ramsey | e38b808 | 2006-03-30 07:03:04 +0000 | [diff] [blame] | 653 | char *buf; |
David Lawrence Ramsey | e38b808 | 2006-03-30 07:03:04 +0000 | [diff] [blame] | 654 | |
Benno Schulenberg | 1d3d307 | 2016-05-27 21:31:55 +0200 | [diff] [blame] | 655 | if (*last_search != '\0') { |
David Lawrence Ramsey | e38b808 | 2006-03-30 07:03:04 +0000 | [diff] [blame] | 656 | char *disp = display_string(last_search, 0, COLS / 3, FALSE); |
| 657 | |
| 658 | buf = charalloc(strlen(disp) + 7); |
Benno Schulenberg | 25ce5f6 | 2015-04-07 08:23:52 +0000 | [diff] [blame] | 659 | /* We use (COLS / 3) here because we need to see more on the line. */ |
David Lawrence Ramsey | e38b808 | 2006-03-30 07:03:04 +0000 | [diff] [blame] | 660 | sprintf(buf, " [%s%s]", disp, |
| 661 | (strlenpt(last_search) > COLS / 3) ? "..." : ""); |
| 662 | free(disp); |
| 663 | } else |
| 664 | buf = mallocstrcpy(NULL, ""); |
| 665 | |
| 666 | /* This is now one simple call. It just does a lot. */ |
Benno Schulenberg | fd0589d | 2017-01-02 21:12:44 +0100 | [diff] [blame] | 667 | input = do_prompt(FALSE, FALSE, MWHEREISFILE, NULL, |
Benno Schulenberg | b341f29 | 2014-06-19 20:05:24 +0000 | [diff] [blame] | 668 | #ifndef DISABLE_HISTORIES |
Benno Schulenberg | b77b139 | 2016-08-26 12:18:04 +0200 | [diff] [blame] | 669 | &search_history, |
David Lawrence Ramsey | e38b808 | 2006-03-30 07:03:04 +0000 | [diff] [blame] | 670 | #endif |
Benno Schulenberg | b77b139 | 2016-08-26 12:18:04 +0200 | [diff] [blame] | 671 | browser_refresh, "%s%s", _("Search"), buf); |
David Lawrence Ramsey | e38b808 | 2006-03-30 07:03:04 +0000 | [diff] [blame] | 672 | |
| 673 | /* Release buf now that we don't need it anymore. */ |
| 674 | free(buf); |
| 675 | |
Benno Schulenberg | 99d2358 | 2015-04-12 08:31:53 +0000 | [diff] [blame] | 676 | /* If only Enter was pressed but we have a previous string, it's okay. */ |
| 677 | if (input == -2 && *last_search != '\0') |
| 678 | return 0; |
David Lawrence Ramsey | e38b808 | 2006-03-30 07:03:04 +0000 | [diff] [blame] | 679 | |
Benno Schulenberg | 99d2358 | 2015-04-12 08:31:53 +0000 | [diff] [blame] | 680 | /* Otherwise negative inputs are a bailout. */ |
| 681 | if (input < 0) |
| 682 | statusbar(_("Cancelled")); |
| 683 | |
Benno Schulenberg | 99d2358 | 2015-04-12 08:31:53 +0000 | [diff] [blame] | 684 | return input; |
David Lawrence Ramsey | e38b808 | 2006-03-30 07:03:04 +0000 | [diff] [blame] | 685 | } |
| 686 | |
Benno Schulenberg | d517705 | 2015-04-07 13:34:12 +0000 | [diff] [blame] | 687 | /* Look for the given needle in the list of files. */ |
| 688 | void findnextfile(const char *needle) |
David Lawrence Ramsey | e38b808 | 2006-03-30 07:03:04 +0000 | [diff] [blame] | 689 | { |
Benno Schulenberg | 2dc9cbe | 2015-04-08 18:40:40 +0000 | [diff] [blame] | 690 | size_t looking_at = selected; |
Benno Schulenberg | d517705 | 2015-04-07 13:34:12 +0000 | [diff] [blame] | 691 | /* The location in the file list of the filename we're looking at. */ |
Benno Schulenberg | 3ea8f42 | 2016-04-29 17:20:59 +0200 | [diff] [blame] | 692 | const char *thename; |
| 693 | /* The plain filename, without the path. */ |
Benno Schulenberg | 6bdcc8f | 2015-04-21 17:27:33 +0000 | [diff] [blame] | 694 | unsigned stash[sizeof(flags) / sizeof(flags[0])]; |
| 695 | /* A storage place for the current flag settings. */ |
| 696 | |
| 697 | /* Save the settings of all flags. */ |
| 698 | memcpy(stash, flags, sizeof(flags)); |
| 699 | |
Benno Schulenberg | 588daf9 | 2016-12-25 13:11:17 +0100 | [diff] [blame] | 700 | /* Search forward, case insensitive, and without regexes. */ |
Benno Schulenberg | 6bdcc8f | 2015-04-21 17:27:33 +0000 | [diff] [blame] | 701 | UNSET(BACKWARDS_SEARCH); |
| 702 | UNSET(CASE_SENSITIVE); |
| 703 | UNSET(USE_REGEXP); |
David Lawrence Ramsey | e38b808 | 2006-03-30 07:03:04 +0000 | [diff] [blame] | 704 | |
Benno Schulenberg | d517705 | 2015-04-07 13:34:12 +0000 | [diff] [blame] | 705 | /* Step through each filename in the list until a match is found or |
| 706 | * we've come back to the point where we started. */ |
David Lawrence Ramsey | e38b808 | 2006-03-30 07:03:04 +0000 | [diff] [blame] | 707 | while (TRUE) { |
Benno Schulenberg | 3ea8f42 | 2016-04-29 17:20:59 +0200 | [diff] [blame] | 708 | /* Move to the next filename in the list, or back to the first. */ |
Benno Schulenberg | 2dc9cbe | 2015-04-08 18:40:40 +0000 | [diff] [blame] | 709 | if (looking_at < filelist_len - 1) |
| 710 | looking_at++; |
Benno Schulenberg | b095725 | 2014-07-01 16:24:01 +0000 | [diff] [blame] | 711 | else { |
Benno Schulenberg | 2dc9cbe | 2015-04-08 18:40:40 +0000 | [diff] [blame] | 712 | looking_at = 0; |
Benno Schulenberg | b095725 | 2014-07-01 16:24:01 +0000 | [diff] [blame] | 713 | statusbar(_("Search Wrapped")); |
David Lawrence Ramsey | e38b808 | 2006-03-30 07:03:04 +0000 | [diff] [blame] | 714 | } |
David Lawrence Ramsey | e38b808 | 2006-03-30 07:03:04 +0000 | [diff] [blame] | 715 | |
Benno Schulenberg | 3ea8f42 | 2016-04-29 17:20:59 +0200 | [diff] [blame] | 716 | /* Get the bare filename, without the path. */ |
Benno Schulenberg | b55e8d7 | 2016-03-21 20:49:29 +0000 | [diff] [blame] | 717 | thename = tail(filelist[looking_at]); |
Benno Schulenberg | 3ea8f42 | 2016-04-29 17:20:59 +0200 | [diff] [blame] | 718 | |
| 719 | /* If the needle matches, we're done. And if we're back at the file |
| 720 | * where we started, it is the only occurrence. */ |
| 721 | if (strstrwrapper(thename, needle, thename)) { |
Benno Schulenberg | cdcd365 | 2016-05-17 11:33:21 +0200 | [diff] [blame] | 722 | if (looking_at == selected) |
Benno Schulenberg | 3ea8f42 | 2016-04-29 17:20:59 +0200 | [diff] [blame] | 723 | statusbar(_("This is the only occurrence")); |
Benno Schulenberg | cdcd365 | 2016-05-17 11:33:21 +0200 | [diff] [blame] | 724 | break; |
Benno Schulenberg | 3ea8f42 | 2016-04-29 17:20:59 +0200 | [diff] [blame] | 725 | } |
| 726 | |
| 727 | /* If we're back at the beginning and didn't find any match... */ |
| 728 | if (looking_at == selected) { |
| 729 | not_found_msg(needle); |
| 730 | break; |
| 731 | } |
David Lawrence Ramsey | e38b808 | 2006-03-30 07:03:04 +0000 | [diff] [blame] | 732 | } |
| 733 | |
Benno Schulenberg | 6bdcc8f | 2015-04-21 17:27:33 +0000 | [diff] [blame] | 734 | /* Restore the settings of all flags. */ |
| 735 | memcpy(flags, stash, sizeof(flags)); |
| 736 | |
Benno Schulenberg | d517705 | 2015-04-07 13:34:12 +0000 | [diff] [blame] | 737 | /* Select the one we've found. */ |
Benno Schulenberg | 2dc9cbe | 2015-04-08 18:40:40 +0000 | [diff] [blame] | 738 | selected = looking_at; |
David Lawrence Ramsey | e38b808 | 2006-03-30 07:03:04 +0000 | [diff] [blame] | 739 | } |
| 740 | |
David Lawrence Ramsey | e38b808 | 2006-03-30 07:03:04 +0000 | [diff] [blame] | 741 | /* Search for a filename. */ |
| 742 | void do_filesearch(void) |
| 743 | { |
Benno Schulenberg | 9106cc8 | 2016-05-08 12:01:33 +0200 | [diff] [blame] | 744 | /* If the user cancelled or jumped to first or last file, don't search. */ |
| 745 | if (filesearch_init() != 0) |
David Lawrence Ramsey | e38b808 | 2006-03-30 07:03:04 +0000 | [diff] [blame] | 746 | return; |
| 747 | |
| 748 | /* If answer is now "", copy last_search into answer. */ |
David Lawrence Ramsey | 1904f51 | 2007-07-01 21:33:17 +0000 | [diff] [blame] | 749 | if (*answer == '\0') |
David Lawrence Ramsey | e38b808 | 2006-03-30 07:03:04 +0000 | [diff] [blame] | 750 | answer = mallocstrcpy(answer, last_search); |
| 751 | else |
| 752 | last_search = mallocstrcpy(last_search, answer); |
| 753 | |
Benno Schulenberg | b341f29 | 2014-06-19 20:05:24 +0000 | [diff] [blame] | 754 | #ifndef DISABLE_HISTORIES |
Benno Schulenberg | 1d3d307 | 2016-05-27 21:31:55 +0200 | [diff] [blame] | 755 | /* If answer is not empty, add the string to the search history list. */ |
| 756 | if (*answer != '\0') |
David Lawrence Ramsey | e38b808 | 2006-03-30 07:03:04 +0000 | [diff] [blame] | 757 | update_history(&search_history, answer); |
| 758 | #endif |
| 759 | |
Benno Schulenberg | d517705 | 2015-04-07 13:34:12 +0000 | [diff] [blame] | 760 | findnextfile(answer); |
David Lawrence Ramsey | e38b808 | 2006-03-30 07:03:04 +0000 | [diff] [blame] | 761 | } |
| 762 | |
Benno Schulenberg | 1d3d307 | 2016-05-27 21:31:55 +0200 | [diff] [blame] | 763 | /* Search again for the last given filename, without prompting. */ |
David Lawrence Ramsey | e38b808 | 2006-03-30 07:03:04 +0000 | [diff] [blame] | 764 | void do_fileresearch(void) |
| 765 | { |
Benno Schulenberg | 1d3d307 | 2016-05-27 21:31:55 +0200 | [diff] [blame] | 766 | if (*last_search == '\0') |
Benno Schulenberg | d517705 | 2015-04-07 13:34:12 +0000 | [diff] [blame] | 767 | statusbar(_("No current search pattern")); |
| 768 | else |
| 769 | findnextfile(last_search); |
David Lawrence Ramsey | e38b808 | 2006-03-30 07:03:04 +0000 | [diff] [blame] | 770 | } |
| 771 | |
David Lawrence Ramsey | ef45a25 | 2006-06-30 05:12:53 +0000 | [diff] [blame] | 772 | /* Select the first file in the list. */ |
David Lawrence Ramsey | e38b808 | 2006-03-30 07:03:04 +0000 | [diff] [blame] | 773 | void do_first_file(void) |
| 774 | { |
| 775 | selected = 0; |
| 776 | } |
| 777 | |
David Lawrence Ramsey | ef45a25 | 2006-06-30 05:12:53 +0000 | [diff] [blame] | 778 | /* Select the last file in the list. */ |
David Lawrence Ramsey | e38b808 | 2006-03-30 07:03:04 +0000 | [diff] [blame] | 779 | void do_last_file(void) |
| 780 | { |
| 781 | selected = filelist_len - 1; |
| 782 | } |
| 783 | |
David Lawrence Ramsey | a4e92c8 | 2006-06-30 14:14:40 +0000 | [diff] [blame] | 784 | /* Strip one directory from the end of path, and return the stripped |
| 785 | * path. The returned string is dynamically allocated, and should be |
| 786 | * freed. */ |
| 787 | char *striponedir(const char *path) |
David Lawrence Ramsey | 64844b6 | 2005-11-05 20:04:16 +0000 | [diff] [blame] | 788 | { |
David Lawrence Ramsey | a4e92c8 | 2006-06-30 14:14:40 +0000 | [diff] [blame] | 789 | char *retval, *tmp; |
David Lawrence Ramsey | 64844b6 | 2005-11-05 20:04:16 +0000 | [diff] [blame] | 790 | |
David Lawrence Ramsey | a4e92c8 | 2006-06-30 14:14:40 +0000 | [diff] [blame] | 791 | retval = mallocstrcpy(NULL, path); |
| 792 | |
| 793 | tmp = strrchr(retval, '/'); |
David Lawrence Ramsey | 64844b6 | 2005-11-05 20:04:16 +0000 | [diff] [blame] | 794 | |
| 795 | if (tmp != NULL) |
Benno Schulenberg | a65ef42 | 2014-03-17 21:36:37 +0000 | [diff] [blame] | 796 | null_at(&retval, tmp - retval); |
David Lawrence Ramsey | a4e92c8 | 2006-06-30 14:14:40 +0000 | [diff] [blame] | 797 | |
| 798 | return retval; |
David Lawrence Ramsey | 64844b6 | 2005-11-05 20:04:16 +0000 | [diff] [blame] | 799 | } |
| 800 | |
David Lawrence Ramsey | 43fff01 | 2005-11-05 20:01:11 +0000 | [diff] [blame] | 801 | #endif /* !DISABLE_BROWSER */ |