1 #define _LARGEFILE64_SOURCE /* required for GLIBC to enable stat64 and friends */
2 #include <sys/types.h>
3 #include <regex.h>
4 #include <stdio.h>
5 #include <string.h>
6 #include <sys/stat.h>
7 #include <unistd.h>
8 #include <sys/socket.h>
9 #include <netinet/in.h>
10
11 #include "mt.h"
12 #include "term.h"
13 #include "mem.h"
14 #include "utils.h"
15 #include "globals.h"
16
17
18 /** create_subwindow_list
19 * - in: int f_index window number
20 * char ***swlist pointer to an array of strings
21 * - returns: int number of elements in the array of strings
22 * this function creates for a given window (f_index) a list of subwindows:
23 * subwindows are created when you're merging the output of several files/
24 * commands
25 */
create_subwindow_list(int f_index,char *** swlist)26 int create_subwindow_list(int f_index, char ***swlist)
27 {
28 char **list = NULL;
29 int n = 0;
30 proginfo *cur = &pi[f_index];
31 int subwin = 0;
32
33 do
34 {
35 list = (char **)myrealloc(list, (n + 1) * sizeof(char *));
36
37 if (show_subwindow_id)
38 {
39 int len = strlen(cur -> filename);
40 list[n] = (char *)mymalloc(len + 1);
41 memcpy(list[n], cur -> filename, len + 1);
42 }
43 else
44 list[n] = mystrdup(cur -> filename);
45
46 n++;
47
48 cur = cur -> next;
49 subwin++;
50 }
51 while(cur);
52
53 *swlist = list;
54
55 return n;
56 }
57
generate_string(char * whereto,void ** list,selbox_type_t type,int wcols,int index)58 char generate_string(char *whereto, void **list, selbox_type_t type, int wcols, int index)
59 {
60 char invert = 0;
61
62 if (type == SEL_WIN)
63 {
64 snprintf(whereto, wcols + 1, "%02d %s", index, shorten_filename(((proginfo *)list)[index].filename, wcols));
65 invert = ((proginfo *)list)[index].hidden | ((proginfo *)list)[index].paused;
66 }
67 else if (type == SEL_SUBWIN)
68 snprintf(whereto, wcols + 1, "%02d %s", index, shorten_filename(((char **)list)[index], wcols));
69 else if (type == SEL_FILES)
70 strncpy(whereto, ((char **)list)[index], min(strlen(((char **)list)[index]), wcols) + 1);
71 else if (type == SEL_CSCHEME)
72 strncpy(whereto, ((color_scheme *)list)[index].name, min(strlen(((color_scheme *)list)[index].name), wcols) + 1);
73 else if (type == SEL_HISTORY)
74 strncpy(whereto, ((char **)list)[index], min(strlen(((char **)list)[index]), wcols) + 1);
75
76 whereto[min(strlen(whereto), wcols - 1)] = 0x00;
77
78 return invert;
79 }
80
find_sb_string(void ** list,selbox_type_t type,int nentries,char * compare_string)81 int find_sb_string(void **list, selbox_type_t type, int nentries, char *compare_string)
82 {
83 int index, len = strlen(compare_string);
84
85 for(index=0; index<nentries; index++)
86 {
87 char buffer[4096];
88
89 (void)generate_string(buffer, list, type, sizeof(buffer) - 1, index);
90
91 if (strncmp(buffer, compare_string, len) == 0)
92 return index;
93 }
94
95 return -1;
96 }
97
selection_box(void ** list,char * needs_mark,int nlines,selbox_type_t type,int what_help,char * heading)98 int selection_box(void **list, char *needs_mark, int nlines, selbox_type_t type, int what_help, char *heading)
99 {
100 NEWWIN *mywin;
101 int wlines = min(nlines, (max_y - 1) - 4);
102 int total_win_size = wlines + 4;
103 int win_width = max(32, max_x / 3);
104 int wcols = win_width - 4;
105 int pos = 0, ppos = -1, offs = 0, poffs = -1;
106 int loop = 0, sel = -1;
107 char first = 1;
108 char *dummy = (char *)mymalloc(wcols + 1);
109 int path_max = find_path_max();
110 char *selstr = (char *)mymalloc(path_max + 1), selfound = 0;
111
112 selstr[0] = 0x00;
113
114 mywin = create_popup(total_win_size, win_width);
115
116 for(;;)
117 {
118 int c;
119
120 /* draw list */
121 if (pos != ppos)
122 {
123 int entries_left = (nlines - pos);
124
125 werase(mywin -> win);
126
127 if (heading)
128 win_header(mywin, heading);
129 else if (type == SEL_WIN)
130 win_header(mywin, "Select window");
131 else if (type == SEL_SUBWIN)
132 win_header(mywin, "Select subwindow");
133 else if (type == SEL_FILES)
134 win_header(mywin, "Select file");
135 else if (type == SEL_CSCHEME)
136 win_header(mywin, "Select color scheme");
137 else if (type == SEL_HISTORY)
138 win_header(mywin, "Select string from history");
139
140 for(loop=0; loop<min(entries_left, wlines); loop++)
141 {
142 char invert = generate_string(dummy, list, type, wcols, loop + pos);
143 if (loop == offs)
144 ui_inverse_on(mywin);
145 if (invert) color_on(mywin, find_colorpair(COLOR_YELLOW, -1, 0));
146 if (needs_mark && needs_mark[loop + pos])
147 mvwprintw(mywin -> win, loop + 2, 1, "*");
148 mvwprintw(mywin -> win, loop + 2, 2, "%s", dummy);
149 if (invert) color_off(mywin, find_colorpair(COLOR_YELLOW, -1, 0));
150 if (loop == offs)
151 ui_inverse_off(mywin);
152 }
153
154 draw_border(mywin);
155
156 ppos = pos;
157 poffs = offs;
158 }
159 else if (poffs != offs)
160 {
161 int yellow_cp = find_colorpair(COLOR_YELLOW, -1, 0);
162 char invert = generate_string(dummy, list, type, wcols, poffs + pos);
163 if (invert) color_on(mywin, yellow_cp);
164 mvwprintw(mywin -> win, poffs + 2, 2, "%s", dummy);
165 if (invert) color_off(mywin, yellow_cp);
166
167 invert = generate_string(dummy, list, type, wcols, offs + pos);
168
169 ui_inverse_on(mywin);
170 if (invert) color_on(mywin, yellow_cp);
171 if (needs_mark && needs_mark[offs + pos])
172 mvwprintw(mywin -> win, loop + 2, 1, "*");
173 mvwprintw(mywin -> win, offs + 2, 2, "%s", dummy);
174 if (invert) color_off(mywin, yellow_cp);
175 ui_inverse_off(mywin);
176
177 poffs = offs;
178 }
179
180 if (first)
181 {
182 first = 0;
183 color_on(mywin, find_colorpair(COLOR_GREEN, -1, 0));
184 mvwprintw(mywin -> win, total_win_size - 2, 2, "Press ^G to abort");
185 color_off(mywin, find_colorpair(COLOR_GREEN, -1, 0));
186 }
187 else
188 {
189 int loop, len = strlen(selstr);
190
191 for(loop=0; loop<wcols; loop++)
192 mvwprintw(mywin -> win, total_win_size - 2, 1 + loop, " ");
193
194 if (!selfound) color_on(mywin, find_colorpair(COLOR_RED, -1, 0));
195 mvwprintw(mywin -> win, total_win_size - 2, 1, "%s", &selstr[max(0, len - wcols)]);
196 if (!selfound) color_off(mywin, find_colorpair(COLOR_RED, -1, 0));
197 }
198
199 mydoupdate();
200
201 c = wait_for_keypress(what_help, 0, mywin, 1);
202
203 if (c == KEY_UP)
204 {
205 if ((offs + pos) > 0)
206 {
207 if (offs)
208 offs--;
209 else
210 pos--;
211 }
212 else
213 {
214 wrong_key();
215 }
216 }
217 else if (c == KEY_DOWN)
218 {
219 if ((pos + offs) < (nlines-1))
220 {
221 if (offs < (wlines-1))
222 offs++;
223 else
224 pos++;
225 }
226 else
227 {
228 wrong_key();
229 }
230 }
231 else if (c == KEY_NPAGE)
232 {
233 if ((pos + offs) < (nlines - 1))
234 {
235 pos += min(wlines, (nlines - 1) - (pos + offs));
236 }
237 else
238 {
239 wrong_key();
240 }
241 }
242 else if (c == KEY_PPAGE)
243 {
244 if ((pos + offs - wlines) >= 0)
245 {
246 if (pos > wlines)
247 {
248 pos -= wlines;
249 }
250 else
251 {
252 pos -= (wlines - offs);
253 offs = 0;
254 }
255 }
256 else if (offs > 0)
257 {
258 offs = 0;
259 }
260 else if (pos > 0)
261 {
262 pos = 0;
263 }
264 else
265 {
266 wrong_key();
267 }
268 }
269 else if (c == KEY_ENTER || c == 13 || c == 10)
270 {
271 sel = pos + offs;
272 break;
273 }
274 else if (c == abort_key || c == -1)
275 {
276 break;
277 }
278 else if ((c > 31 && c != 127) || (c == KEY_BACKSPACE))
279 {
280 int index, curlen;
281
282 curlen = strlen(selstr);
283 if (c == KEY_BACKSPACE)
284 {
285 if (curlen > 0)
286 selstr[curlen - 1] = 0x00;
287 else
288 wrong_key();
289 }
290 else if (curlen < path_max)
291 {
292 selstr[curlen] = c;
293 selstr[curlen + 1] = 0x00;
294 }
295 else
296 wrong_key();
297
298
299 curlen = strlen(selstr);
300 if (curlen > 0)
301 {
302 index = find_sb_string(list, type, nlines, selstr);
303 if (index != -1)
304 {
305 ppos = -1;
306 sel = pos = index;
307 selfound = 1;
308 }
309 else
310 {
311 selfound = 0;
312 }
313 }
314 }
315 else
316 {
317 wrong_key();
318 }
319 }
320
321 delete_popup(mywin);
322
323 myfree(dummy);
324 myfree(selstr);
325
326 return sel;
327 }
328
select_window(int what_help,char * heading)329 int select_window(int what_help, char *heading)
330 {
331 return selection_box((void **)pi, NULL, nfd, SEL_WIN, what_help, heading);
332 }
333
select_subwindow(int f_index,int what_help,char * heading)334 proginfo * select_subwindow(int f_index, int what_help, char *heading)
335 {
336 proginfo *cur = NULL;
337 char **list;
338 int list_n, index, loop;
339
340 if (f_index == -1)
341 return NULL;
342
343 list_n = create_subwindow_list(f_index, &list);
344
345 index = selection_box((void **)list, NULL, list_n, SEL_SUBWIN, what_help, heading);
346
347 if (index != -1)
348 {
349 cur = &pi[f_index];
350 for(loop=0; loop<index; loop++)
351 {
352 cur = cur -> next;
353 }
354 }
355
356 delete_array(list, list_n);
357
358 return cur;
359 }
360
select_file(char * input,int what_help)361 char * select_file(char *input, int what_help)
362 {
363 char **list = NULL, *isdir = NULL, *path = NULL;
364 char *new_fname = NULL;
365 struct stat64 statbuf;
366 int list_n, index;
367 int strbufsize = find_path_max();
368
369 list_n = match_files(input, &path, &list, &isdir);
370 if (list_n == 0)
371 {
372 myfree(path);
373 flash();
374 return NULL;
375 }
376
377 index = selection_box((void **)list, isdir, list_n, SEL_FILES, what_help, NULL);
378 if (index != -1)
379 {
380 new_fname = (char *)mymalloc(strbufsize + 1);
381
382 snprintf(new_fname, strbufsize, "%s%s", path, list[index]);
383
384 if (stat64(new_fname, &statbuf) == -1)
385 {
386 myfree(new_fname);
387 new_fname = NULL;
388 flash();
389 }
390 else
391 {
392 if (S_ISDIR(statbuf.st_mode))
393 {
394 strncat(new_fname, "/", strbufsize);
395 }
396 }
397 }
398
399 delete_array(list, list_n);
400
401 myfree(isdir);
402 myfree(path);
403
404 return new_fname;
405 }
406