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