Blame


1 71ee1627 2014-11-07 marcelgmr #include <stdlib.h>
2 bae1431c 2014-11-07 marcelgmr #include <stdint.h>
3 6beff8a2 2014-11-08 marcelgmr #include <ctype.h>
4 6beff8a2 2014-11-08 marcelgmr #include <string.h>
5 5f52c474 2014-11-08 marcelgmr #include <sys/types.h> /* pid_t, ... */
6 71ee1627 2014-11-07 marcelgmr #include <stdio.h> /* FILENAME_MAX */
7 71ee1627 2014-11-07 marcelgmr #include <locale.h> /* setlocale(), LC_ALL */
8 71ee1627 2014-11-07 marcelgmr #include <unistd.h> /* chdir(), getcwd() */
9 71ee1627 2014-11-07 marcelgmr #include <dirent.h> /* DIR, struct dirent, opendir(), ... */
10 71ee1627 2014-11-07 marcelgmr #include <sys/stat.h>
11 71ee1627 2014-11-07 marcelgmr #include <sys/wait.h> /* waitpid() */
12 71ee1627 2014-11-07 marcelgmr #include <curses.h>
13 71ee1627 2014-11-07 marcelgmr
14 71ee1627 2014-11-07 marcelgmr #include "config.h"
15 71ee1627 2014-11-07 marcelgmr
16 576e768d 2014-11-08 marcelgmr #define ROWSZ 256
17 576e768d 2014-11-08 marcelgmr char ROW[ROWSZ];
18 a17e36e3 2014-11-07 marcelgmr #define STATUSSZ 256
19 a17e36e3 2014-11-07 marcelgmr char STATUS[STATUSSZ];
20 a17e36e3 2014-11-07 marcelgmr #define SEARCHSZ 256
21 a17e36e3 2014-11-07 marcelgmr char SEARCH[SEARCHSZ];
22 71ee1627 2014-11-07 marcelgmr #define MAXARGS 256
23 71ee1627 2014-11-07 marcelgmr char *args[MAXARGS];
24 71ee1627 2014-11-07 marcelgmr
25 a17e36e3 2014-11-07 marcelgmr typedef enum {DEFAULT, RED, GREEN, YELLOW, BLUE, CYAN, MAGENTA, WHITE} color_t;
26 71ee1627 2014-11-07 marcelgmr
27 f05efd9e 2014-11-07 marcelgmr #define HEIGHT (LINES-4)
28 f05efd9e 2014-11-07 marcelgmr
29 bae1431c 2014-11-07 marcelgmr #define SHOW_FILES 0x01u
30 bae1431c 2014-11-07 marcelgmr #define SHOW_DIRS 0x02u
31 bae1431c 2014-11-07 marcelgmr #define SHOW_HIDDEN 0x04u
32 bae1431c 2014-11-07 marcelgmr
33 576e768d 2014-11-08 marcelgmr typedef struct {
34 576e768d 2014-11-08 marcelgmr char *name;
35 576e768d 2014-11-08 marcelgmr off_t size;
36 576e768d 2014-11-08 marcelgmr } row_t;
37 576e768d 2014-11-08 marcelgmr
38 f05efd9e 2014-11-07 marcelgmr struct rover_t {
39 ada8fba9 2014-11-09 marcelgmr int tab;
40 71ee1627 2014-11-07 marcelgmr int nfiles;
41 ada8fba9 2014-11-09 marcelgmr int scroll[10];
42 ada8fba9 2014-11-09 marcelgmr int fsel[10];
43 47e9f26d 2014-11-09 marcelgmr uint8_t flags[10];
44 576e768d 2014-11-08 marcelgmr row_t *rows;
45 71ee1627 2014-11-07 marcelgmr WINDOW *window;
46 ada8fba9 2014-11-09 marcelgmr char cwd[10][FILENAME_MAX];
47 f05efd9e 2014-11-07 marcelgmr } rover;
48 71ee1627 2014-11-07 marcelgmr
49 576e768d 2014-11-08 marcelgmr #define FNAME(I) rover.rows[I].name
50 576e768d 2014-11-08 marcelgmr #define FSIZE(I) rover.rows[I].size
51 ada8fba9 2014-11-09 marcelgmr #define SCROLL rover.scroll[rover.tab]
52 ada8fba9 2014-11-09 marcelgmr #define FSEL rover.fsel[rover.tab]
53 47e9f26d 2014-11-09 marcelgmr #define FLAGS rover.flags[rover.tab]
54 ada8fba9 2014-11-09 marcelgmr #define CWD rover.cwd[rover.tab]
55 576e768d 2014-11-08 marcelgmr
56 71ee1627 2014-11-07 marcelgmr static int
57 576e768d 2014-11-08 marcelgmr rowcmp(const void *a, const void *b)
58 71ee1627 2014-11-07 marcelgmr {
59 71ee1627 2014-11-07 marcelgmr int isdir1, isdir2, cmpdir;
60 576e768d 2014-11-08 marcelgmr const row_t *r1 = a;
61 576e768d 2014-11-08 marcelgmr const row_t *r2 = b;
62 576e768d 2014-11-08 marcelgmr isdir1 = strchr(r1->name, '/') != NULL;
63 576e768d 2014-11-08 marcelgmr isdir2 = strchr(r2->name, '/') != NULL;
64 71ee1627 2014-11-07 marcelgmr cmpdir = isdir2 - isdir1;
65 576e768d 2014-11-08 marcelgmr return cmpdir ? cmpdir : strcoll(r1->name, r2->name);
66 71ee1627 2014-11-07 marcelgmr }
67 71ee1627 2014-11-07 marcelgmr
68 576e768d 2014-11-08 marcelgmr void
69 576e768d 2014-11-08 marcelgmr free_rows(row_t **rowsp, int nfiles)
70 576e768d 2014-11-08 marcelgmr {
71 576e768d 2014-11-08 marcelgmr int i;
72 576e768d 2014-11-08 marcelgmr
73 576e768d 2014-11-08 marcelgmr for (i = 0; i < nfiles; i++)
74 576e768d 2014-11-08 marcelgmr free((*rowsp)[i].name);
75 576e768d 2014-11-08 marcelgmr free(*rowsp);
76 576e768d 2014-11-08 marcelgmr *rowsp = NULL;
77 576e768d 2014-11-08 marcelgmr }
78 576e768d 2014-11-08 marcelgmr
79 71ee1627 2014-11-07 marcelgmr int
80 576e768d 2014-11-08 marcelgmr ls(char *path, row_t **rowsp, uint8_t flags)
81 71ee1627 2014-11-07 marcelgmr {
82 71ee1627 2014-11-07 marcelgmr DIR *dp;
83 71ee1627 2014-11-07 marcelgmr struct dirent *ep;
84 71ee1627 2014-11-07 marcelgmr struct stat statbuf;
85 576e768d 2014-11-08 marcelgmr row_t *rows;
86 71ee1627 2014-11-07 marcelgmr int i, n;
87 71ee1627 2014-11-07 marcelgmr
88 71ee1627 2014-11-07 marcelgmr if((dp = opendir(path)) == NULL)
89 71ee1627 2014-11-07 marcelgmr return -1;
90 71ee1627 2014-11-07 marcelgmr n = -2; /* We don't want the entries "." and "..". */
91 71ee1627 2014-11-07 marcelgmr while (readdir(dp)) n++;
92 71ee1627 2014-11-07 marcelgmr rewinddir(dp);
93 576e768d 2014-11-08 marcelgmr rows = (row_t *) malloc(n * sizeof(row_t));
94 71ee1627 2014-11-07 marcelgmr i = 0;
95 71ee1627 2014-11-07 marcelgmr while ((ep = readdir(dp))) {
96 f05efd9e 2014-11-07 marcelgmr if (!strcmp(ep->d_name, ".") || !strcmp(ep->d_name, ".."))
97 71ee1627 2014-11-07 marcelgmr continue;
98 bae1431c 2014-11-07 marcelgmr if (!(flags & SHOW_HIDDEN) && ep->d_name[0] == '.')
99 bae1431c 2014-11-07 marcelgmr continue;
100 71ee1627 2014-11-07 marcelgmr /* FIXME: ANSI C doesn't have lstat(). How do we handle symlinks? */
101 ea0214c3 2014-11-09 marcelgmr stat(ep->d_name, &statbuf);
102 bae1431c 2014-11-07 marcelgmr if (S_ISDIR(statbuf.st_mode)) {
103 bae1431c 2014-11-07 marcelgmr if (flags & SHOW_DIRS) {
104 576e768d 2014-11-08 marcelgmr rows[i].name = (char *) malloc(strlen(ep->d_name) + 2);
105 576e768d 2014-11-08 marcelgmr strcpy(rows[i].name, ep->d_name);
106 576e768d 2014-11-08 marcelgmr strcat(rows[i].name, "/");
107 bae1431c 2014-11-07 marcelgmr i++;
108 bae1431c 2014-11-07 marcelgmr }
109 bae1431c 2014-11-07 marcelgmr }
110 bae1431c 2014-11-07 marcelgmr else if (flags & SHOW_FILES) {
111 576e768d 2014-11-08 marcelgmr rows[i].name = (char *) malloc(strlen(ep->d_name) + 1);
112 576e768d 2014-11-08 marcelgmr strcpy(rows[i].name, ep->d_name);
113 576e768d 2014-11-08 marcelgmr rows[i].size = statbuf.st_size;
114 bae1431c 2014-11-07 marcelgmr i++;
115 bae1431c 2014-11-07 marcelgmr }
116 71ee1627 2014-11-07 marcelgmr }
117 bae1431c 2014-11-07 marcelgmr n = i; /* Ignore unused space in array caused by filters. */
118 576e768d 2014-11-08 marcelgmr qsort(rows, n, sizeof(row_t), rowcmp);
119 ea0214c3 2014-11-09 marcelgmr closedir(dp);
120 576e768d 2014-11-08 marcelgmr *rowsp = rows;
121 71ee1627 2014-11-07 marcelgmr return n;
122 71ee1627 2014-11-07 marcelgmr }
123 71ee1627 2014-11-07 marcelgmr
124 71ee1627 2014-11-07 marcelgmr static void
125 f05efd9e 2014-11-07 marcelgmr clean_term()
126 71ee1627 2014-11-07 marcelgmr {
127 71ee1627 2014-11-07 marcelgmr endwin();
128 71ee1627 2014-11-07 marcelgmr }
129 71ee1627 2014-11-07 marcelgmr
130 e1c42cfe 2014-11-11 marcelgmr void handle_winch(int sig);
131 e1c42cfe 2014-11-11 marcelgmr
132 71ee1627 2014-11-07 marcelgmr static void
133 f05efd9e 2014-11-07 marcelgmr init_term()
134 71ee1627 2014-11-07 marcelgmr {
135 e1c42cfe 2014-11-11 marcelgmr struct sigaction sa;
136 e1c42cfe 2014-11-11 marcelgmr
137 71ee1627 2014-11-07 marcelgmr setlocale(LC_ALL, "");
138 71ee1627 2014-11-07 marcelgmr initscr();
139 71ee1627 2014-11-07 marcelgmr cbreak(); /* Get one character at a time. */
140 71ee1627 2014-11-07 marcelgmr noecho();
141 71ee1627 2014-11-07 marcelgmr nonl(); /* No NL->CR/NL on output. */
142 71ee1627 2014-11-07 marcelgmr intrflush(stdscr, FALSE);
143 71ee1627 2014-11-07 marcelgmr keypad(stdscr, TRUE);
144 71ee1627 2014-11-07 marcelgmr curs_set(FALSE); /* Hide blinking cursor. */
145 e1c42cfe 2014-11-11 marcelgmr memset(&sa, 0, sizeof(struct sigaction));
146 e1c42cfe 2014-11-11 marcelgmr sa.sa_handler = handle_winch;
147 e1c42cfe 2014-11-11 marcelgmr sigaction(SIGWINCH, &sa, NULL);
148 71ee1627 2014-11-07 marcelgmr if (has_colors()) {
149 71ee1627 2014-11-07 marcelgmr start_color();
150 71ee1627 2014-11-07 marcelgmr init_pair(RED, COLOR_RED, COLOR_BLACK);
151 71ee1627 2014-11-07 marcelgmr init_pair(GREEN, COLOR_GREEN, COLOR_BLACK);
152 71ee1627 2014-11-07 marcelgmr init_pair(YELLOW, COLOR_YELLOW,COLOR_BLACK);
153 71ee1627 2014-11-07 marcelgmr init_pair(BLUE, COLOR_BLUE, COLOR_BLACK);
154 71ee1627 2014-11-07 marcelgmr init_pair(CYAN, COLOR_CYAN, COLOR_BLACK);
155 71ee1627 2014-11-07 marcelgmr init_pair(MAGENTA, COLOR_MAGENTA, COLOR_BLACK);
156 71ee1627 2014-11-07 marcelgmr init_pair(WHITE, COLOR_WHITE, COLOR_BLACK);
157 71ee1627 2014-11-07 marcelgmr }
158 f05efd9e 2014-11-07 marcelgmr atexit(clean_term);
159 71ee1627 2014-11-07 marcelgmr }
160 71ee1627 2014-11-07 marcelgmr
161 71ee1627 2014-11-07 marcelgmr static void
162 71ee1627 2014-11-07 marcelgmr update_browser()
163 71ee1627 2014-11-07 marcelgmr {
164 222db952 2014-11-08 marcelgmr int i, j;
165 576e768d 2014-11-08 marcelgmr int ishidden, isdir;
166 71ee1627 2014-11-07 marcelgmr
167 ada8fba9 2014-11-09 marcelgmr for (i = 0, j = SCROLL; i < HEIGHT && j < rover.nfiles; i++, j++) {
168 576e768d 2014-11-08 marcelgmr ishidden = FNAME(j)[0] == '.';
169 576e768d 2014-11-08 marcelgmr isdir = strchr(FNAME(j), '/') != NULL;
170 ada8fba9 2014-11-09 marcelgmr if (j == FSEL)
171 f05efd9e 2014-11-07 marcelgmr wattr_on(rover.window, A_REVERSE, NULL);
172 576e768d 2014-11-08 marcelgmr if (ishidden)
173 37233869 2014-11-07 marcelgmr wcolor_set(rover.window, RVC_HIDDEN, NULL);
174 576e768d 2014-11-08 marcelgmr else if (isdir)
175 37233869 2014-11-07 marcelgmr wcolor_set(rover.window, RVC_DIR, NULL);
176 37233869 2014-11-07 marcelgmr else
177 37233869 2014-11-07 marcelgmr wcolor_set(rover.window, RVC_FILE, NULL);
178 576e768d 2014-11-08 marcelgmr if (!isdir)
179 576e768d 2014-11-08 marcelgmr sprintf(ROW, "%s%*d", FNAME(j),
180 576e768d 2014-11-08 marcelgmr COLS - strlen(FNAME(j)) - 2, (int) FSIZE(j));
181 576e768d 2014-11-08 marcelgmr else
182 576e768d 2014-11-08 marcelgmr strcpy(ROW, FNAME(j));
183 a81852bf 2014-11-08 marcelgmr mvwhline(rover.window, i + 1, 1, ' ', COLS - 2);
184 a81852bf 2014-11-08 marcelgmr mvwaddnstr(rover.window, i + 1, 1, ROW, COLS - 2);
185 37233869 2014-11-07 marcelgmr wcolor_set(rover.window, DEFAULT, NULL);
186 ada8fba9 2014-11-09 marcelgmr if (j == FSEL)
187 f05efd9e 2014-11-07 marcelgmr wattr_off(rover.window, A_REVERSE, NULL);
188 a81852bf 2014-11-08 marcelgmr }
189 a81852bf 2014-11-08 marcelgmr if (rover.nfiles > HEIGHT) {
190 a81852bf 2014-11-08 marcelgmr int center, height;
191 ada8fba9 2014-11-09 marcelgmr center = (SCROLL + (HEIGHT >> 1)) * HEIGHT / rover.nfiles;
192 a81852bf 2014-11-08 marcelgmr height = (HEIGHT-1) * HEIGHT / rover.nfiles;
193 a81852bf 2014-11-08 marcelgmr if (!height) height = 1;
194 a81852bf 2014-11-08 marcelgmr wcolor_set(rover.window, RVC_BORDER, NULL);
195 a81852bf 2014-11-08 marcelgmr wborder(rover.window, 0, 0, 0, 0, 0, 0, 0, 0);
196 2a2b72b6 2014-11-08 marcelgmr wcolor_set(rover.window, RVC_SCROLLBAR, NULL);
197 a81852bf 2014-11-08 marcelgmr mvwvline(rover.window, center-(height>>1)+1, COLS-1, ACS_CKBOARD, height);
198 a81852bf 2014-11-08 marcelgmr wcolor_set(rover.window, DEFAULT, NULL);
199 71ee1627 2014-11-07 marcelgmr }
200 f05efd9e 2014-11-07 marcelgmr wrefresh(rover.window);
201 47e9f26d 2014-11-09 marcelgmr STATUS[0] = FLAGS & SHOW_FILES ? 'F' : ' ';
202 47e9f26d 2014-11-09 marcelgmr STATUS[1] = FLAGS & SHOW_DIRS ? 'D' : ' ';
203 47e9f26d 2014-11-09 marcelgmr STATUS[2] = FLAGS & SHOW_HIDDEN ? 'H' : ' ';
204 bb90b2d2 2014-11-08 marcelgmr if (!rover.nfiles)
205 222db952 2014-11-08 marcelgmr strcpy(ROW, "0/0");
206 bb90b2d2 2014-11-08 marcelgmr else
207 ada8fba9 2014-11-09 marcelgmr sprintf(ROW, "%d/%d", FSEL + 1, rover.nfiles);
208 222db952 2014-11-08 marcelgmr sprintf(STATUS+3, "%*s", 12, ROW);
209 e1f31679 2014-11-07 marcelgmr color_set(RVC_STATUS, NULL);
210 222db952 2014-11-08 marcelgmr mvaddstr(LINES - 1, COLS - 15, STATUS);
211 e1f31679 2014-11-07 marcelgmr color_set(DEFAULT, NULL);
212 71ee1627 2014-11-07 marcelgmr refresh();
213 71ee1627 2014-11-07 marcelgmr }
214 71ee1627 2014-11-07 marcelgmr
215 ada8fba9 2014-11-09 marcelgmr /* NOTE: The caller needs to write the new path to CWD
216 71ee1627 2014-11-07 marcelgmr * *before* calling this function. */
217 71ee1627 2014-11-07 marcelgmr static void
218 ada8fba9 2014-11-09 marcelgmr cd(int reset)
219 71ee1627 2014-11-07 marcelgmr {
220 ada8fba9 2014-11-09 marcelgmr if (reset)
221 ada8fba9 2014-11-09 marcelgmr FSEL = SCROLL = 0;
222 ea0214c3 2014-11-09 marcelgmr chdir(CWD);
223 ea0214c3 2014-11-09 marcelgmr mvhline(0, 0, ' ', COLS);
224 e1f31679 2014-11-07 marcelgmr color_set(RVC_CWD, NULL);
225 ea0214c3 2014-11-09 marcelgmr mvaddnstr(0, 0, CWD, COLS);
226 e1f31679 2014-11-07 marcelgmr color_set(DEFAULT, NULL);
227 ada8fba9 2014-11-09 marcelgmr move(0, COLS-2);
228 ada8fba9 2014-11-09 marcelgmr attr_on(A_BOLD, NULL);
229 1c86f4eb 2014-11-09 marcelgmr color_set(RVC_TABNUM, NULL);
230 ada8fba9 2014-11-09 marcelgmr echochar(rover.tab + '0');
231 1c86f4eb 2014-11-09 marcelgmr color_set(DEFAULT, NULL);
232 ada8fba9 2014-11-09 marcelgmr attr_off(A_BOLD, NULL);
233 f05efd9e 2014-11-07 marcelgmr if (rover.nfiles)
234 576e768d 2014-11-08 marcelgmr free_rows(&rover.rows, rover.nfiles);
235 47e9f26d 2014-11-09 marcelgmr rover.nfiles = ls(CWD, &rover.rows, FLAGS);
236 ea0214c3 2014-11-09 marcelgmr wclear(rover.window);
237 37233869 2014-11-07 marcelgmr wcolor_set(rover.window, RVC_BORDER, NULL);
238 f05efd9e 2014-11-07 marcelgmr wborder(rover.window, 0, 0, 0, 0, 0, 0, 0, 0);
239 37233869 2014-11-07 marcelgmr wcolor_set(rover.window, DEFAULT, NULL);
240 71ee1627 2014-11-07 marcelgmr update_browser();
241 71ee1627 2014-11-07 marcelgmr }
242 71ee1627 2014-11-07 marcelgmr
243 71ee1627 2014-11-07 marcelgmr static void
244 71ee1627 2014-11-07 marcelgmr spawn()
245 71ee1627 2014-11-07 marcelgmr {
246 71ee1627 2014-11-07 marcelgmr pid_t pid;
247 71ee1627 2014-11-07 marcelgmr int status;
248 71ee1627 2014-11-07 marcelgmr
249 71ee1627 2014-11-07 marcelgmr pid = fork();
250 71ee1627 2014-11-07 marcelgmr if (pid > 0) {
251 71ee1627 2014-11-07 marcelgmr /* fork() succeeded. */
252 f05efd9e 2014-11-07 marcelgmr clean_term();
253 ea0214c3 2014-11-09 marcelgmr waitpid(pid, &status, 0);
254 f05efd9e 2014-11-07 marcelgmr init_term();
255 71ee1627 2014-11-07 marcelgmr doupdate();
256 71ee1627 2014-11-07 marcelgmr }
257 71ee1627 2014-11-07 marcelgmr else if (pid == 0) {
258 71ee1627 2014-11-07 marcelgmr /* Child process. */
259 71ee1627 2014-11-07 marcelgmr execvp(args[0], args);
260 411ec846 2014-11-08 marcelgmr }
261 411ec846 2014-11-08 marcelgmr }
262 411ec846 2014-11-08 marcelgmr
263 411ec846 2014-11-08 marcelgmr /* Interactive getstr(). */
264 411ec846 2014-11-08 marcelgmr int
265 411ec846 2014-11-08 marcelgmr igetstr(char *buffer, int maxlen)
266 411ec846 2014-11-08 marcelgmr {
267 411ec846 2014-11-08 marcelgmr int ch, length;
268 411ec846 2014-11-08 marcelgmr
269 411ec846 2014-11-08 marcelgmr length = strlen(buffer);
270 411ec846 2014-11-08 marcelgmr ch = getch();
271 411ec846 2014-11-08 marcelgmr if (ch == '\r' || ch == '\n' || ch == KEY_DOWN || ch == KEY_ENTER)
272 411ec846 2014-11-08 marcelgmr return 0;
273 411ec846 2014-11-08 marcelgmr else if (ch == erasechar() || ch == KEY_LEFT || ch == KEY_BACKSPACE) {
274 411ec846 2014-11-08 marcelgmr if (length)
275 411ec846 2014-11-08 marcelgmr buffer[--length] = '\0';
276 411ec846 2014-11-08 marcelgmr }
277 411ec846 2014-11-08 marcelgmr else if (ch == killchar()) {
278 411ec846 2014-11-08 marcelgmr length = 0;
279 411ec846 2014-11-08 marcelgmr buffer[0] = '\0';
280 71ee1627 2014-11-07 marcelgmr }
281 411ec846 2014-11-08 marcelgmr else if (length < maxlen - 1 && isprint(ch)) {
282 411ec846 2014-11-08 marcelgmr buffer[length++] = ch;
283 411ec846 2014-11-08 marcelgmr buffer[length] = '\0';
284 411ec846 2014-11-08 marcelgmr }
285 411ec846 2014-11-08 marcelgmr return 1;
286 71ee1627 2014-11-07 marcelgmr }
287 71ee1627 2014-11-07 marcelgmr
288 e1c42cfe 2014-11-11 marcelgmr void
289 e1c42cfe 2014-11-11 marcelgmr handle_winch(int sig)
290 e1c42cfe 2014-11-11 marcelgmr {
291 e1c42cfe 2014-11-11 marcelgmr (void) sig;
292 e1c42cfe 2014-11-11 marcelgmr delwin(rover.window);
293 e1c42cfe 2014-11-11 marcelgmr endwin();
294 e1c42cfe 2014-11-11 marcelgmr refresh();
295 e1c42cfe 2014-11-11 marcelgmr clear();
296 e1c42cfe 2014-11-11 marcelgmr rover.window = subwin(stdscr, LINES - 2, COLS, 1, 0);
297 e1c42cfe 2014-11-11 marcelgmr cd(0);
298 e1c42cfe 2014-11-11 marcelgmr }
299 e1c42cfe 2014-11-11 marcelgmr
300 71ee1627 2014-11-07 marcelgmr int
301 38a357b6 2014-11-09 marcelgmr main(int argc, char *argv[])
302 71ee1627 2014-11-07 marcelgmr {
303 ada8fba9 2014-11-09 marcelgmr int i, ch;
304 ada8fba9 2014-11-09 marcelgmr char *program, *key;
305 38a357b6 2014-11-09 marcelgmr DIR *d;
306 71ee1627 2014-11-07 marcelgmr
307 f05efd9e 2014-11-07 marcelgmr init_term();
308 71ee1627 2014-11-07 marcelgmr /* Avoid invalid free() calls in cd() by zeroing the tally. */
309 f05efd9e 2014-11-07 marcelgmr rover.nfiles = 0;
310 47e9f26d 2014-11-09 marcelgmr for (i = 0; i < 10; i++) {
311 47e9f26d 2014-11-09 marcelgmr rover.fsel[i] = rover.scroll[i] = 0;
312 47e9f26d 2014-11-09 marcelgmr rover.flags[i] = SHOW_FILES | SHOW_DIRS;
313 47e9f26d 2014-11-09 marcelgmr }
314 ada8fba9 2014-11-09 marcelgmr strcpy(rover.cwd[0], getenv("HOME"));
315 38a357b6 2014-11-09 marcelgmr for (i = 1; i < argc && i < 10; i++) {
316 38a357b6 2014-11-09 marcelgmr d = opendir(argv[i]);
317 38a357b6 2014-11-09 marcelgmr if (d) {
318 38a357b6 2014-11-09 marcelgmr strcpy(rover.cwd[i], argv[i]);
319 38a357b6 2014-11-09 marcelgmr closedir(d);
320 38a357b6 2014-11-09 marcelgmr }
321 38a357b6 2014-11-09 marcelgmr else strcpy(rover.cwd[i], rover.cwd[0]);
322 38a357b6 2014-11-09 marcelgmr }
323 38a357b6 2014-11-09 marcelgmr getcwd(rover.cwd[i], FILENAME_MAX);
324 38a357b6 2014-11-09 marcelgmr for (i++; i < 10; i++)
325 38a357b6 2014-11-09 marcelgmr strcpy(rover.cwd[i], rover.cwd[i-1]);
326 38a357b6 2014-11-09 marcelgmr for (i = 0; i < 10; i++)
327 38a357b6 2014-11-09 marcelgmr if (rover.cwd[i][strlen(rover.cwd[i]) - 1] != '/')
328 38a357b6 2014-11-09 marcelgmr strcat(rover.cwd[i], "/");
329 ada8fba9 2014-11-09 marcelgmr rover.tab = 1;
330 ada8fba9 2014-11-09 marcelgmr rover.window = subwin(stdscr, LINES - 2, COLS, 1, 0);
331 ada8fba9 2014-11-09 marcelgmr cd(1);
332 0b301167 2014-11-07 marcelgmr while (1) {
333 ada8fba9 2014-11-09 marcelgmr ch = getch();
334 ada8fba9 2014-11-09 marcelgmr key = keyname(ch);
335 0b301167 2014-11-07 marcelgmr if (!strcmp(key, RVK_QUIT))
336 0b301167 2014-11-07 marcelgmr break;
337 ada8fba9 2014-11-09 marcelgmr else if (ch >= '0' && ch <= '9') {
338 ada8fba9 2014-11-09 marcelgmr rover.tab = ch - '0';
339 ada8fba9 2014-11-09 marcelgmr cd(0);
340 ada8fba9 2014-11-09 marcelgmr }
341 0b301167 2014-11-07 marcelgmr else if (!strcmp(key, RVK_DOWN)) {
342 bb90b2d2 2014-11-08 marcelgmr if (!rover.nfiles) continue;
343 ada8fba9 2014-11-09 marcelgmr if (FSEL == rover.nfiles - 1)
344 ada8fba9 2014-11-09 marcelgmr SCROLL = FSEL = 0;
345 bb90b2d2 2014-11-08 marcelgmr else {
346 ada8fba9 2014-11-09 marcelgmr FSEL++;
347 ada8fba9 2014-11-09 marcelgmr if ((FSEL - SCROLL) == HEIGHT)
348 ada8fba9 2014-11-09 marcelgmr SCROLL++;
349 71ee1627 2014-11-07 marcelgmr }
350 71ee1627 2014-11-07 marcelgmr update_browser();
351 0b301167 2014-11-07 marcelgmr }
352 0b301167 2014-11-07 marcelgmr else if (!strcmp(key, RVK_UP)) {
353 bb90b2d2 2014-11-08 marcelgmr if (!rover.nfiles) continue;
354 ada8fba9 2014-11-09 marcelgmr if (FSEL == 0) {
355 ada8fba9 2014-11-09 marcelgmr FSEL = rover.nfiles - 1;
356 ada8fba9 2014-11-09 marcelgmr SCROLL = rover.nfiles - HEIGHT;
357 ada8fba9 2014-11-09 marcelgmr if (SCROLL < 0)
358 ada8fba9 2014-11-09 marcelgmr SCROLL = 0;
359 71ee1627 2014-11-07 marcelgmr }
360 bb90b2d2 2014-11-08 marcelgmr else {
361 ada8fba9 2014-11-09 marcelgmr FSEL--;
362 ada8fba9 2014-11-09 marcelgmr if (FSEL < SCROLL)
363 ada8fba9 2014-11-09 marcelgmr SCROLL--;
364 71ee1627 2014-11-07 marcelgmr }
365 71ee1627 2014-11-07 marcelgmr update_browser();
366 0b301167 2014-11-07 marcelgmr }
367 0b301167 2014-11-07 marcelgmr else if (!strcmp(key, RVK_JUMP_DOWN)) {
368 bb90b2d2 2014-11-08 marcelgmr if (!rover.nfiles) continue;
369 ada8fba9 2014-11-09 marcelgmr FSEL += RV_JUMP;
370 ada8fba9 2014-11-09 marcelgmr if (FSEL >= rover.nfiles)
371 ada8fba9 2014-11-09 marcelgmr FSEL = rover.nfiles - 1;
372 f05efd9e 2014-11-07 marcelgmr if (rover.nfiles > HEIGHT) {
373 ada8fba9 2014-11-09 marcelgmr SCROLL += RV_JUMP;
374 ada8fba9 2014-11-09 marcelgmr if (SCROLL > rover.nfiles - HEIGHT)
375 ada8fba9 2014-11-09 marcelgmr SCROLL = rover.nfiles - HEIGHT;
376 71ee1627 2014-11-07 marcelgmr }
377 71ee1627 2014-11-07 marcelgmr update_browser();
378 0b301167 2014-11-07 marcelgmr }
379 0b301167 2014-11-07 marcelgmr else if (!strcmp(key, RVK_JUMP_UP)) {
380 bb90b2d2 2014-11-08 marcelgmr if (!rover.nfiles) continue;
381 ada8fba9 2014-11-09 marcelgmr FSEL -= RV_JUMP;
382 ada8fba9 2014-11-09 marcelgmr if (FSEL < 0)
383 ada8fba9 2014-11-09 marcelgmr FSEL = 0;
384 ada8fba9 2014-11-09 marcelgmr SCROLL -= RV_JUMP;
385 ada8fba9 2014-11-09 marcelgmr if (SCROLL < 0)
386 ada8fba9 2014-11-09 marcelgmr SCROLL = 0;
387 71ee1627 2014-11-07 marcelgmr update_browser();
388 0b301167 2014-11-07 marcelgmr }
389 0b301167 2014-11-07 marcelgmr else if (!strcmp(key, RVK_CD_DOWN)) {
390 bb90b2d2 2014-11-08 marcelgmr if (!rover.nfiles) continue;
391 ada8fba9 2014-11-09 marcelgmr if (strchr(FNAME(FSEL), '/') == NULL)
392 71ee1627 2014-11-07 marcelgmr continue;
393 ada8fba9 2014-11-09 marcelgmr strcat(CWD, FNAME(FSEL));
394 ada8fba9 2014-11-09 marcelgmr cd(1);
395 0b301167 2014-11-07 marcelgmr }
396 0b301167 2014-11-07 marcelgmr else if (!strcmp(key, RVK_CD_UP)) {
397 45020106 2014-11-08 marcelgmr char *dirname, first;
398 ada8fba9 2014-11-09 marcelgmr if (strlen(CWD) == 1)
399 71ee1627 2014-11-07 marcelgmr continue;
400 ada8fba9 2014-11-09 marcelgmr CWD[strlen(CWD) - 1] = '\0';
401 ada8fba9 2014-11-09 marcelgmr dirname = strrchr(CWD, '/') + 1;
402 45020106 2014-11-08 marcelgmr first = dirname[0];
403 45020106 2014-11-08 marcelgmr dirname[0] = '\0';
404 ada8fba9 2014-11-09 marcelgmr cd(1);
405 47e9f26d 2014-11-09 marcelgmr if ((FLAGS & SHOW_DIRS) &&
406 47e9f26d 2014-11-09 marcelgmr ((FLAGS & SHOW_HIDDEN) || (first != '.'))
407 45020106 2014-11-08 marcelgmr ) {
408 45020106 2014-11-08 marcelgmr dirname[0] = first;
409 45020106 2014-11-08 marcelgmr dirname[strlen(dirname)] = '/';
410 ada8fba9 2014-11-09 marcelgmr while (strcmp(FNAME(FSEL), dirname))
411 ada8fba9 2014-11-09 marcelgmr FSEL++;
412 45020106 2014-11-08 marcelgmr if (rover.nfiles > HEIGHT) {
413 ada8fba9 2014-11-09 marcelgmr SCROLL = FSEL - (HEIGHT >> 1);
414 ada8fba9 2014-11-09 marcelgmr if (SCROLL < 0)
415 ada8fba9 2014-11-09 marcelgmr SCROLL = 0;
416 ada8fba9 2014-11-09 marcelgmr if (SCROLL > rover.nfiles - HEIGHT)
417 ada8fba9 2014-11-09 marcelgmr SCROLL = rover.nfiles - HEIGHT;
418 45020106 2014-11-08 marcelgmr }
419 45020106 2014-11-08 marcelgmr dirname[0] = '\0';
420 45020106 2014-11-08 marcelgmr update_browser();
421 45020106 2014-11-08 marcelgmr }
422 0b301167 2014-11-07 marcelgmr }
423 0b301167 2014-11-07 marcelgmr else if (!strcmp(key, RVK_HOME)) {
424 ada8fba9 2014-11-09 marcelgmr strcpy(CWD, getenv("HOME"));
425 ada8fba9 2014-11-09 marcelgmr if (CWD[strlen(CWD) - 1] != '/')
426 ada8fba9 2014-11-09 marcelgmr strcat(CWD, "/");
427 ada8fba9 2014-11-09 marcelgmr cd(1);
428 0b301167 2014-11-07 marcelgmr }
429 0b301167 2014-11-07 marcelgmr else if (!strcmp(key, RVK_SHELL)) {
430 71ee1627 2014-11-07 marcelgmr program = getenv("SHELL");
431 71ee1627 2014-11-07 marcelgmr if (program) {
432 71ee1627 2014-11-07 marcelgmr args[0] = program;
433 71ee1627 2014-11-07 marcelgmr args[1] = NULL;
434 71ee1627 2014-11-07 marcelgmr spawn();
435 71ee1627 2014-11-07 marcelgmr }
436 0b301167 2014-11-07 marcelgmr }
437 4b66a2c4 2014-11-07 marcelgmr else if (!strcmp(key, RVK_VIEW)) {
438 bb90b2d2 2014-11-08 marcelgmr if (!rover.nfiles) continue;
439 ada8fba9 2014-11-09 marcelgmr if (strchr(FNAME(FSEL), '/') != NULL)
440 4b66a2c4 2014-11-07 marcelgmr continue;
441 4b66a2c4 2014-11-07 marcelgmr program = getenv("PAGER");
442 4b66a2c4 2014-11-07 marcelgmr if (program) {
443 4b66a2c4 2014-11-07 marcelgmr args[0] = program;
444 ada8fba9 2014-11-09 marcelgmr args[1] = FNAME(FSEL);
445 4b66a2c4 2014-11-07 marcelgmr args[2] = NULL;
446 4b66a2c4 2014-11-07 marcelgmr spawn();
447 4b66a2c4 2014-11-07 marcelgmr }
448 4b66a2c4 2014-11-07 marcelgmr }
449 0b301167 2014-11-07 marcelgmr else if (!strcmp(key, RVK_EDIT)) {
450 bb90b2d2 2014-11-08 marcelgmr if (!rover.nfiles) continue;
451 ada8fba9 2014-11-09 marcelgmr if (strchr(FNAME(FSEL), '/') != NULL)
452 71ee1627 2014-11-07 marcelgmr continue;
453 71ee1627 2014-11-07 marcelgmr program = getenv("EDITOR");
454 71ee1627 2014-11-07 marcelgmr if (program) {
455 71ee1627 2014-11-07 marcelgmr args[0] = program;
456 ada8fba9 2014-11-09 marcelgmr args[1] = FNAME(FSEL);
457 71ee1627 2014-11-07 marcelgmr args[2] = NULL;
458 71ee1627 2014-11-07 marcelgmr spawn();
459 71ee1627 2014-11-07 marcelgmr }
460 0b301167 2014-11-07 marcelgmr }
461 a17e36e3 2014-11-07 marcelgmr else if (!strcmp(key, RVK_SEARCH)) {
462 411ec846 2014-11-08 marcelgmr int oldsel, oldscroll;
463 bb90b2d2 2014-11-08 marcelgmr if (!rover.nfiles) continue;
464 ada8fba9 2014-11-09 marcelgmr oldsel = FSEL;
465 ada8fba9 2014-11-09 marcelgmr oldscroll = SCROLL;
466 a17e36e3 2014-11-07 marcelgmr *SEARCH = '\0';
467 1c86f4eb 2014-11-09 marcelgmr color_set(RVC_PROMPT, NULL);
468 411ec846 2014-11-08 marcelgmr mvaddstr(LINES - 1, 0, "search: ");
469 1c86f4eb 2014-11-09 marcelgmr color_set(DEFAULT, NULL);
470 411ec846 2014-11-08 marcelgmr while (igetstr(SEARCH, SEARCHSZ)) {
471 411ec846 2014-11-08 marcelgmr int length, sel;
472 411ec846 2014-11-08 marcelgmr color_t color;
473 411ec846 2014-11-08 marcelgmr length = strlen(SEARCH);
474 a17e36e3 2014-11-07 marcelgmr if (length) {
475 f05efd9e 2014-11-07 marcelgmr for (sel = 0; sel < rover.nfiles; sel++)
476 576e768d 2014-11-08 marcelgmr if (!strncmp(FNAME(sel), SEARCH, length))
477 a17e36e3 2014-11-07 marcelgmr break;
478 f05efd9e 2014-11-07 marcelgmr if (sel < rover.nfiles) {
479 a17e36e3 2014-11-07 marcelgmr color = GREEN;
480 ada8fba9 2014-11-09 marcelgmr FSEL = sel;
481 f05efd9e 2014-11-07 marcelgmr if (rover.nfiles > HEIGHT) {
482 89cfd83b 2014-11-08 marcelgmr if (sel < 3)
483 ada8fba9 2014-11-09 marcelgmr SCROLL = 0;
484 89cfd83b 2014-11-08 marcelgmr else if (sel - 3 > rover.nfiles - HEIGHT)
485 ada8fba9 2014-11-09 marcelgmr SCROLL = rover.nfiles - HEIGHT;
486 a17e36e3 2014-11-07 marcelgmr else
487 ada8fba9 2014-11-09 marcelgmr SCROLL = sel - 3;
488 a17e36e3 2014-11-07 marcelgmr }
489 a17e36e3 2014-11-07 marcelgmr }
490 a17e36e3 2014-11-07 marcelgmr else
491 a17e36e3 2014-11-07 marcelgmr color = RED;
492 a17e36e3 2014-11-07 marcelgmr }
493 411ec846 2014-11-08 marcelgmr else {
494 ada8fba9 2014-11-09 marcelgmr FSEL = oldsel;
495 ada8fba9 2014-11-09 marcelgmr SCROLL = oldscroll;
496 411ec846 2014-11-08 marcelgmr }
497 a17e36e3 2014-11-07 marcelgmr update_browser();
498 411ec846 2014-11-08 marcelgmr strcat(SEARCH, " ");
499 a17e36e3 2014-11-07 marcelgmr color_set(color, NULL);
500 921aeceb 2014-11-07 marcelgmr mvaddstr(LINES - 1, 8, SEARCH);
501 a17e36e3 2014-11-07 marcelgmr color_set(DEFAULT, NULL);
502 411ec846 2014-11-08 marcelgmr SEARCH[length] = '\0';
503 a17e36e3 2014-11-07 marcelgmr }
504 a17e36e3 2014-11-07 marcelgmr move(LINES - 1, 0);
505 a17e36e3 2014-11-07 marcelgmr clrtoeol();
506 a17e36e3 2014-11-07 marcelgmr update_browser();
507 a17e36e3 2014-11-07 marcelgmr }
508 bae1431c 2014-11-07 marcelgmr else if (!strcmp(key, RVK_TG_FILES)) {
509 47e9f26d 2014-11-09 marcelgmr FLAGS ^= SHOW_FILES;
510 ada8fba9 2014-11-09 marcelgmr cd(1);
511 bae1431c 2014-11-07 marcelgmr }
512 bae1431c 2014-11-07 marcelgmr else if (!strcmp(key, RVK_TG_DIRS)) {
513 47e9f26d 2014-11-09 marcelgmr FLAGS ^= SHOW_DIRS;
514 ada8fba9 2014-11-09 marcelgmr cd(1);
515 bae1431c 2014-11-07 marcelgmr }
516 bae1431c 2014-11-07 marcelgmr else if (!strcmp(key, RVK_TG_HIDDEN)) {
517 47e9f26d 2014-11-09 marcelgmr FLAGS ^= SHOW_HIDDEN;
518 ada8fba9 2014-11-09 marcelgmr cd(1);
519 bae1431c 2014-11-07 marcelgmr }
520 71ee1627 2014-11-07 marcelgmr }
521 576e768d 2014-11-08 marcelgmr if (rover.nfiles) {
522 576e768d 2014-11-08 marcelgmr free_rows(&rover.rows, rover.nfiles);
523 576e768d 2014-11-08 marcelgmr }
524 f05efd9e 2014-11-07 marcelgmr delwin(rover.window);
525 71ee1627 2014-11-07 marcelgmr return 0;
526 71ee1627 2014-11-07 marcelgmr }