1 /*
2 * file.c Functions to handle file selector.
3 *
4 * This file is part of the minicom communications package,
5 * Copyright 1991-1995 Miquel van Smoorenburg.
6 *
7 * This file created from code mostly cadged from "dial.c"
8 * by Miquel van Smoorenburg. Written by James S. Seymour.
9 * Copyright (c) 1998 by James S. Seymour (jseymour@jimsun.LinxNet.com)
10 * Some mods for i18n
11 * Copyright (c) 1998 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version
16 * 2 of the License, or (at your option) any later version.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 */
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <limits.h>
28
29 #include "port.h"
30 #include "minicom.h"
31 #include "intl.h"
32 #include "getsdir.h"
33
34 #ifdef HAVE_UNISTD_H
35 # include <unistd.h>
36 #endif
37
38 #define FILE_MWTR 1 /* main window top row */
39 #define SUBM_OKAY 5 /* last entry in sub-menu */
40
41 static int nrents = 1;
42
43 static void file_tell(const char *s);
44 static void dhili(int k);
45 static void prdir(WIN *dirw, int top, int cur, GETSDIR_ENTRY *dirdat, int longest);
46 static void prone(WIN *dirw, GETSDIR_ENTRY *dirdat, int longest, int inverse);
47 static void *set_work_dir(void *existing, size_t min_len);
48 static int new_filedir(GETSDIR_ENTRY *dirdat, int flushit);
49 static void goto_filedir(char *new_dir, int absolut);
50 static int tag_untag(char *pat, int tag);
51 static char *concat_list(GETSDIR_ENTRY *d);
52
53 static WIN *dsub;
54 static const char *const what[] =
55 {
56 /* TRANSLATORS: Translation of each of these menu items should not be
57 * longer than 7 characters. The upper-case letter is a shortcut,
58 * so keep them unique and ASCII; 'h', 'j', 'k', 'l' are reserved */
59 N_("[Goto]"), N_("[Prev]"), N_("[Show]"), N_("[Tag]"), N_("[Untag]"),
60 N_("[Okay]")
61 };
62 #define WHAT_NR_OPTIONS (sizeof (what) / sizeof (*what))
63 #define WHAT_WIDTH 8 /* Width of one entry */
64 /* Number of bytes for <= 7 characters */
65 static int what_lens[WHAT_NR_OPTIONS];
66 /* Number of ' ' padding entries at left and right, left is >= 1 */
67 static int what_padding[WHAT_NR_OPTIONS][2];
68 static int dprev;
69
70 /* Little menu. */
71 static const char *d_yesno[] = { N_(" Yes "), N_(" No "), NULL };
72
73
74 /*
75 * Tell a little message
76 */
file_tell(const char * s)77 static void file_tell(const char *s)
78 {
79 WIN *w;
80
81 w = mc_tell("%s", s);
82 sleep(1);
83 mc_wclose(w, 1);
84 }
85
86 /* Draw an entry in the horizontal menu */
horiz_draw(size_t k,char start_attr,char end_attr)87 static void horiz_draw(size_t k, char start_attr, char end_attr)
88 {
89 static const char spaces[] = " ";
90
91 mc_wprintf(dsub, "%.*s", what_padding[k][0], spaces);
92 mc_wsetattr(dsub, start_attr);
93 mc_wprintf(dsub, "%.*s", what_lens[k], _(what[k]));
94 mc_wsetattr(dsub, end_attr);
95 mc_wprintf(dsub, "%.*s", what_padding[k][1], spaces);
96 }
97
98 /*
99 * Highlight a choice in the horizontal menu.
100 */
dhili(int k)101 static void dhili(int k)
102 {
103 int initial_y = (76 - (WHAT_NR_OPTIONS * WHAT_WIDTH >= 76
104 ? 74 : WHAT_NR_OPTIONS * WHAT_WIDTH)) / 2;
105
106 if (k == dprev)
107 return;
108
109 if (dprev >= 0) {
110 mc_wlocate(dsub, initial_y + WHAT_WIDTH * dprev, 0);
111 if (!useattr)
112 mc_wputs(dsub, " ");
113 else
114 horiz_draw(dprev, stdattr, stdattr);
115 }
116 dprev = k;
117
118 mc_wlocate(dsub, initial_y + WHAT_WIDTH * k, 0);
119 if (!useattr)
120 mc_wputs(dsub, ">");
121 else
122 horiz_draw(k, XA_REVERSE | stdattr, stdattr);
123 }
124
getno(int no,GETSDIR_ENTRY * d)125 static inline GETSDIR_ENTRY *getno(int no, GETSDIR_ENTRY *d)
126 {
127 if (no >= nrents)
128 return NULL;
129 return d + no;
130 }
131
132 /*
133 * Print the directory. Only draw from "cur" to bottom.
134 */
prdir(WIN * dirw,int top,int cur,GETSDIR_ENTRY * dirdat,int longest)135 static void prdir(WIN *dirw, int top, int cur,
136 GETSDIR_ENTRY *dirdat, int longest)
137 {
138 int f, start;
139 char f_str[BUFSIZ];
140 char t_str[BUFSIZ];
141
142 start = cur - top;
143 dirflush = 0;
144 sprintf(f_str, " %%-%ds", longest + 2);
145 mc_wlocate(dirw, 0, start + FILE_MWTR);
146 for (f = start; f < dirw->ys - (1 + FILE_MWTR); f++) {
147 GETSDIR_ENTRY *d;
148 if (!(d = getno(f + top, dirdat)))
149 break;
150 if (d->cflags & FL_TAG)
151 mc_wsetattr(dirw, XA_REVERSE | stdattr);
152 if (S_ISDIR(d->mode)) {
153 snprintf(t_str, sizeof(t_str), "[%s]", d->fname);
154 mc_wprintf(dirw, f_str, t_str);
155 } else
156 mc_wprintf(dirw, f_str, d->fname);
157 mc_wsetattr(dirw, XA_NORMAL | stdattr);
158 mc_wputc(dirw, '\n');
159 }
160 dirflush = 1;
161 mc_wflush();
162 }
163
164 /*
165 * Print one directory entry.
166 */
prone(WIN * dirw,GETSDIR_ENTRY * dirdat,int longest,int inverse)167 static void prone(WIN *dirw, GETSDIR_ENTRY *dirdat, int longest, int inverse)
168 {
169 char f_str[BUFSIZ];
170 char t_str[BUFSIZ];
171
172 dirflush = 0;
173 sprintf(f_str, " %%-%ds", longest + 2);
174 /*
175 if (dirdat->cflags & FL_TAG)
176 mc_wsetattr(dirw, XA_REVERSE | stdattr);
177 */
178 if (inverse)
179 mc_wsetattr(dirw, XA_REVERSE | stdattr);
180 if (S_ISDIR(dirdat->mode)) {
181 snprintf(t_str, sizeof(t_str), "[%s]", dirdat->fname);
182 mc_wprintf(dirw, f_str, t_str);
183 } else
184 mc_wprintf(dirw, f_str, dirdat->fname);
185 mc_wsetattr(dirw, XA_NORMAL | stdattr);
186 dirflush = 1;
187 mc_wflush();
188 }
189
190 static WIN *main_w;
191 static GETSDIR_ENTRY *global_dirdat;
192 static int cur = 0;
193 static int ocur = 0;
194 static int subm = SUBM_OKAY;
195 static int quit = 0;
196 static int top = 0;
197 static int c = 0;
198 static int pgud = 0;
199 static int first = 1;
200 static char *s;
201 static int longest;
202 static char file_title[BUFSIZ];
203 static char cwd_str[BUFSIZ];
204 static char *prev_dir = NULL;
205 static char *work_dir = NULL;
206 static char *d_work_dir = NULL;
207 static char *u_work_dir = NULL;
208 static int min_len = 1;
209 static char wc_str[128] = "";
210 static char wc_mem[128] = "";
211 static int tag_cnt = 0;
212 static int how_many = 0;
213 static int down_loading = 0;
214 static char *ret_buf = NULL;
215
216
217 /* Init up/down work directories to make sure we start from
218 * the configuration defaults on the next up/download. jl 6/2000
219 */
init_dir(char dir)220 void init_dir(char dir)
221 {
222 char *p = NULL;
223
224 switch (dir) {
225 case 'u':
226 p = u_work_dir;
227 u_work_dir = NULL;
228 break;
229 case 'd':
230 p = d_work_dir;
231 d_work_dir = NULL;
232 break;
233 }
234 free((void *) p);
235 return;
236 }
237
set_work_dir(void * existing,size_t min_len)238 static void *set_work_dir(void *existing, size_t min_len)
239 {
240 void *vp = realloc(existing, min_len);
241
242 if (down_loading)
243 d_work_dir = vp;
244 else
245 u_work_dir = vp;
246
247 return vp;
248 }
249
250
251 /*
252 * Initialize new file directory.
253 *
254 * Sets the current working directory. Non-0 return = no change.
255 */
new_filedir(GETSDIR_ENTRY * dirdat,int flushit)256 static int new_filedir(GETSDIR_ENTRY *dirdat, int flushit)
257 {
258 static size_t dp_len = 0;
259 static char cwd_str_fmt[BUFSIZ] = "";
260 size_t new_dp_len, fmt_len;
261 char disp_dir[80];
262 int initial_y = (76 - (WHAT_NR_OPTIONS * WHAT_WIDTH >= 76
263 ? 74 : WHAT_NR_OPTIONS * WHAT_WIDTH)) / 2;
264 size_t i;
265 char * new_prev_dir;
266
267 cur = 0;
268 ocur = 0;
269 subm = SUBM_OKAY;
270 quit = 0;
271 top = 0;
272 c = 0;
273 pgud = 0;
274 first = 1;
275 min_len = 1;
276 dprev = -1;
277 tag_cnt = 0;
278
279 /*
280 * get last directory
281 */
282 work_dir = down_loading ? d_work_dir : u_work_dir;
283
284 /*
285 * init working directory to default?
286 */
287 if (work_dir == NULL) {
288 char *s = down_loading? P_DOWNDIR : P_UPDIR;
289 min_len = 1;
290
291 if (*s != '/')
292 min_len += strlen(homedir) + 1;
293 min_len += strlen(s);
294 if (min_len < BUFSIZ)
295 min_len = BUFSIZ;
296
297 work_dir = set_work_dir(NULL, min_len);
298
299 if (*s == '/')
300 strncpy(work_dir, s, min_len);
301 else
302 snprintf(work_dir, min_len, "%s/%s", homedir, s);
303 }
304 /* lop-off trailing "/" for consistency */
305 if (strlen(work_dir) > 1 && work_dir[strlen(work_dir) - 1] == '/')
306 work_dir[strlen(work_dir) - 1] = (char)0;
307
308 /* get the current working directory, which will become the prev_dir, on success */
309 new_prev_dir = getcwd(NULL, BUFSIZ);
310 if (!new_prev_dir)
311 return -1;
312
313 if (!access(work_dir, R_OK | X_OK) && !chdir(work_dir)) {
314 /* was able to change to new working directory */
315 free(prev_dir);
316 prev_dir = new_prev_dir;
317 }
318 else {
319 /* Could not change to the new working directory */
320 mc_wbell();
321 werror(
322 _("Could not change to directory %s (%s)"),
323 work_dir,
324 strerror(errno));
325
326 /* restore the previous working directory */
327 free(work_dir);
328 work_dir = set_work_dir(new_prev_dir, strlen(new_prev_dir));
329 }
330
331 /* All right, draw the file directory! */
332
333 if (flushit) {
334 dirflush = 0;
335 mc_winclr(main_w);
336 mc_wredraw(main_w, 1);
337 }
338
339 mc_wcursor(main_w, CNORMAL);
340
341 {
342 char *s;
343
344 if (down_loading) {
345 if (how_many < 0)
346 s = _("Select one or more files for download");
347 else if (how_many)
348 s = _("Select a file for download");
349 else
350 s = _("Select a directory for download");
351 } else {
352 if (how_many < 0)
353 s = _("Select one or more files for upload");
354 else if (how_many)
355 s = _("Select a file for upload");
356 else
357 s = _("Select a directory for upload");
358 }
359 snprintf(file_title, sizeof(file_title), "%s", s);
360 }
361
362 mc_wtitle(main_w, TMID, file_title);
363 if ((new_dp_len = strlen(work_dir)) > dp_len) {
364 dp_len = new_dp_len;
365 snprintf(cwd_str_fmt, sizeof(cwd_str_fmt),
366 _("Directory: %%-%ds"), (int)dp_len);
367 }
368 new_dp_len = mbslen (work_dir);
369 if (new_dp_len + (fmt_len = mbslen(cwd_str_fmt)) > 75) {
370 size_t i;
371 char *tmp_dir = work_dir;
372
373 /* We want the last 73 characters */
374 for (i = 0; 73 + i < new_dp_len + fmt_len; i++) {
375 wchar_t wc;
376
377 tmp_dir += one_mbtowc(&wc, work_dir, MB_LEN_MAX);
378 }
379 snprintf(disp_dir, sizeof(disp_dir), "...%s", tmp_dir);
380 snprintf(cwd_str, sizeof(cwd_str), cwd_str_fmt, disp_dir);
381 } else
382 snprintf(cwd_str, sizeof(cwd_str), cwd_str_fmt, work_dir);
383
384 mc_wlocate(main_w, 0, 0);
385 mc_wputs(main_w, cwd_str);
386
387 for (i = 0; i < WHAT_NR_OPTIONS; i++) {
388 const char *str, *c;
389 size_t j;
390
391 str = _(what[i]);
392 c = str;
393 for (j = 0; j < WHAT_WIDTH - 1 && *c != 0; j++) {
394 wchar_t wc;
395 c += one_mbtowc (&wc, c, MB_LEN_MAX);
396 }
397 what_lens[i] = c - str;
398 j = WHAT_WIDTH - j; /* Characters left for padding */
399 what_padding[i][1] = j / 2; /* Rounding down */
400 what_padding[i][0] = j - what_padding[i][1]; /* >= 1 */
401 }
402 mc_wlocate(dsub, initial_y, 0);
403 for (i = 0; i < WHAT_NR_OPTIONS; i++)
404 horiz_draw(i, mc_wgetattr(dsub), mc_wgetattr(dsub));
405
406 mc_wsetregion(main_w, 1, main_w->ys - FILE_MWTR);
407 main_w->doscroll = 0;
408
409 /* old dir to discard? */
410 free(dirdat);
411 dirdat = NULL;
412
413 /* get sorted directory */
414 if ((nrents = getsdir(".", wc_str,
415 GETSDIR_PARNT|GETSDIR_NSORT|GETSDIR_DIRSF,
416 0, &dirdat, &longest)) < 0) {
417 /* we really want to announce the error here!!! */
418 mc_wclose(main_w, 1);
419 mc_wclose(dsub, 1);
420 free(dirdat);
421 dirdat = NULL;
422 return -1;
423 }
424
425 global_dirdat = dirdat; // Hmm...
426
427 prdir(main_w, top, top, dirdat, longest);
428 mc_wlocate(main_w, initial_y, main_w->ys - FILE_MWTR);
429 mc_wputs(main_w, _("( Escape to exit, Space to tag )"));
430 dhili(subm);
431 /* this really needs to go in dhili !!!*/
432 mc_wlocate(main_w, 0, cur + FILE_MWTR - top);
433 if (flushit) {
434 dirflush = 1;
435 mc_wredraw(dsub, 1);
436 }
437
438 return 0;
439 }
440
441
442 /*
443 * Goto a new directory
444 */
goto_filedir(char * new_dir,int absolut)445 static void goto_filedir(char *new_dir, int absolut)
446 {
447 if (strcmp(new_dir, "..") == 0) {
448 if (strcmp(work_dir, "/")) {
449 char *sp = strrchr(work_dir, '/');
450 *sp = (char)0;
451 if (strlen(work_dir) == 0)
452 strcpy(work_dir, "/");
453 } else {
454 file_tell(_("Can't back up!"));
455 return;
456 }
457 } else if (!absolut) {
458 int new_len = strlen(work_dir) + 1; /* + '/' */
459 if ((new_len += strlen(new_dir) + 1) > min_len) {
460 min_len = new_len;
461 work_dir = set_work_dir(work_dir, min_len);
462 }
463 if (strcmp(work_dir, "/") != 0)
464 strcat(work_dir, "/");
465 strcat(work_dir, new_dir);
466 } else {
467 int new_len = 1;
468 if (*new_dir != '/')
469 new_len += strlen(homedir) + 1;
470 new_len += strlen(new_dir);
471 if (min_len < new_len)
472 min_len = new_len;
473
474 work_dir = set_work_dir(work_dir, min_len);
475
476 if (*new_dir == '/')
477 strncpy(work_dir, new_dir, min_len);
478 else
479 snprintf(work_dir, min_len, "%s/%s", homedir, new_dir);
480 }
481 new_filedir(global_dirdat, 1);
482 }
483
484
485 /*
486 * Initialize the file directory.
487 */
init_filedir(void)488 static int init_filedir(void)
489 {
490 int x1, x2;
491 int retstat = -1;
492
493 dirflush = 0;
494 x1 = (COLS / 2) - 37;
495 x2 = (COLS / 2) + 37;
496 dsub = mc_wopen(x1 - 1, LINES - 3, x2 + 1, LINES - 3, BNONE,
497 stdattr, mfcolor, mbcolor, 0, 0, 1);
498 main_w = mc_wopen(x1, 2, x2, LINES - 6, BSINGLE, stdattr, mfcolor,
499 mbcolor, 0, 0, 1);
500
501 if (ret_buf != NULL ||
502 (retstat = ((ret_buf = (char *)malloc(BUFSIZ)) == NULL)? -1 : 0) == 0) {
503 retstat = new_filedir(NULL, 0);
504 dirflush = 1;
505 mc_wredraw(dsub, 1);
506 }
507 return retstat;
508 }
509
510
tag_untag(char * pat,int tag)511 static int tag_untag(char *pat, int tag)
512 {
513 GETSDIR_ENTRY *d = global_dirdat;
514 int indxr, cntr;
515
516 if (nrents < 1)
517 return 0;
518
519 for (indxr = nrents, cntr = 0; indxr; --indxr, ++d)
520 if (S_ISREG(d->mode) && wildmat(d->fname, pat)) {
521 if (tag) {
522 d->cflags |= FL_TAG;
523 ++cntr;
524 } else if (d->cflags & FL_TAG) {
525 d->cflags &= ~FL_TAG;
526 ++cntr;
527 }
528 }
529
530 return cntr;
531 }
532
533
534 /*
535 * concatenate tagged files into a buffer
536 */
concat_list(GETSDIR_ENTRY * dirdat)537 static char *concat_list(GETSDIR_ENTRY *dirdat)
538 {
539 GETSDIR_ENTRY *d;
540 int indxr, len;
541 int i;
542 char *j;
543
544 d = dirdat;
545 for (indxr = nrents, len = 0; indxr; --indxr, ++d)
546 if (d->cflags & FL_TAG)
547 len += strlen(d->fname) + 1;
548
549 if (len) {
550 if (len > BUFSIZ) {
551 if ((ret_buf = (char *)realloc(ret_buf, len)) == NULL) {
552 file_tell(_("Too many files tagged - buffer would overflow"));
553 return NULL;
554 }
555 }
556
557 *ret_buf = (char)0;
558 d = dirdat;
559 for (indxr = nrents; indxr; --indxr, ++d)
560 if (d->cflags & FL_TAG) {
561 /* this could be *much* more efficient */
562 for (i = strlen(ret_buf), j = d->fname; *j; j++) {
563 if (*j == ' ') {
564 if ((ret_buf = (char*)realloc(ret_buf, ++len)) == NULL) {
565 file_tell(_("Too many files tagged - buffer would overflow"));
566 return(NULL);
567 }
568 ret_buf[i++] = '\\';
569 }
570 ret_buf[i++] = *j;
571 }
572 ret_buf[i++] = ' ';
573 ret_buf[i] = '\0';
574 }
575
576 ret_buf[strlen(ret_buf) - 1] = (char)0;
577 return ret_buf;
578 }
579
580 return NULL;
581 }
582
583
584 /*
585 * Draw the file directory.
586 *
587 * howmany - How many files can be selected
588 * 0 = none (for directory selection only, as in "rz")
589 * 1 = one (for single-file up-/down-loads, as in "rx")
590 * -1 = any number (for multiple files, as in "sz")
591 *
592 * downloading - Is this for download selection?
593 * 0 = no
594 * 1 = yes - when single file selected, see if it exists
595 */
filedir(int howmany,int downloading)596 char * filedir(int howmany, int downloading)
597 {
598 time_t click_time = (time_t) 0;
599 size_t i;
600
601 how_many = howmany;
602 down_loading = downloading;
603 init_filedir();
604
605 again:
606 mc_wlocate(main_w, 0, cur + FILE_MWTR - top);
607 if (first) {
608 mc_wredraw(main_w, 1);
609 first = 0;
610 }
611 while (!quit) {
612 GETSDIR_ENTRY *d = getno(cur, global_dirdat);
613 /*
614 if(S_ISDIR(d->mode))
615 prone(main_w, d, longest, 0);
616 */
617 switch (c = wxgetch()) {
618 case K_UP:
619 case 'k':
620 /*
621 if(S_ISDIR(d->mode))
622 prone(main_w, d, longest, 1);
623 */
624 cur -= cur > 0;
625 break;
626 case K_DN:
627 case 'j':
628 /*
629 if(S_ISDIR(d->mode))
630 prone(main_w, d, longest, 1);
631 */
632 cur += cur < nrents - 1;
633 break;
634 case K_LT:
635 case 'h':
636 subm--;
637 if (subm < 0)
638 subm = SUBM_OKAY;
639 break;
640 case K_RT:
641 case 'l':
642 subm = (subm + 1) % 6;
643 break;
644 case K_PGUP:
645 case '\002': /* Control-B */
646 pgud = 1;
647 quit = 1;
648 break;
649 case K_PGDN:
650 case '\006': /* Control-F */
651 pgud = 2;
652 quit = 1;
653 break;
654 case ' ': /* Tag if not directory */
655 if (S_ISDIR(d->mode)) {
656 time_t this_time = time((time_t *)NULL);
657 if (this_time - click_time < 2) {
658 GETSDIR_ENTRY *d2 = getno(cur, global_dirdat);
659 goto_filedir(d2->fname, 0);
660 click_time = (time_t)0;
661 } else
662 click_time = this_time;
663 }
664 else {
665 if (how_many) {
666 if ((d->cflags ^= FL_TAG) & FL_TAG) {
667 if (tag_cnt && how_many == 1) {
668 d->cflags &= ~FL_TAG;
669 file_tell(_("Can select only one!"));
670 break;
671 }
672 ++tag_cnt;
673 } else
674 --tag_cnt;
675 mc_wlocate(main_w, 0, cur + FILE_MWTR - top);
676 prone(main_w, d, longest, d->cflags & FL_TAG);
677 mc_wputc(main_w, '\n');
678 cur += cur < nrents - 1;
679 }
680 }
681 break;
682
683 case '\033':
684 case '\r':
685 case '\n':
686 quit = 1;
687 break;
688
689 default:
690 for (i = 0; i < WHAT_NR_OPTIONS; i++) {
691 if (strchr (_(what[i]), toupper (c)) != NULL) {
692 subm = i;
693 c = '\n';
694 quit = 1;
695 break;
696 }
697 }
698
699 break;
700 }
701
702 if (c != ' ')
703 click_time = (time_t)0;
704
705 if (cur < top) {
706 top--;
707 prdir(main_w, top, top, global_dirdat, longest);
708 }
709 if (cur - top > main_w->ys - (2 + FILE_MWTR)) {
710 top++;
711 prdir(main_w, top, top, global_dirdat, longest);
712 }
713 /*
714 if(cur != ocur)
715 mc_wlocate(main_w, 0, cur + FILE_MWTR - top);
716 */
717
718 ocur = cur;
719 dhili(subm);
720 /* this really needs to go in dhili !!!*/
721 mc_wlocate(main_w, 0, cur + FILE_MWTR - top);
722 }
723
724 quit = 0;
725 /* ESC means quit */
726 if (c == '\033') {
727 mc_wclose(main_w, 1);
728 mc_wclose(dsub, 1);
729 free(global_dirdat);
730 global_dirdat = NULL;
731 return NULL;
732 }
733 /* Page up or down ? */
734 if (pgud == 1) { /* Page up */
735 ocur = top;
736 top -= main_w->ys - (1 + FILE_MWTR);
737 if (top < 0)
738 top = 0;
739 cur = top;
740 pgud = 0;
741 if (ocur != top)
742 prdir(main_w, top, cur, global_dirdat, longest);
743 ocur = cur;
744 goto again;
745 }
746 if (pgud == 2) { /* Page down */
747 ocur = top;
748 if (top < nrents - main_w->ys + (1 + FILE_MWTR)) {
749 top += main_w->ys - (1 + FILE_MWTR);
750 if (top > nrents - main_w->ys + (1 + FILE_MWTR)) {
751 top = nrents - main_w->ys + (1 + FILE_MWTR);
752 }
753 cur = top;
754 } else
755 cur = nrents - 1;
756 pgud = 0;
757 if (ocur != top)
758 prdir(main_w, top, cur, global_dirdat, longest);
759 ocur = cur;
760 goto again;
761 }
762
763 if (c =='\r' || c == '\n') {
764 switch(subm) {
765 case 0:
766 /* Goto directory */
767 {
768 char buf[128];
769 char *s;
770 strncpy(buf, down_loading? P_DOWNDIR : P_UPDIR, sizeof(buf) -1);
771 s = input(_("Goto directory:"), buf);
772 /* if(s == NULL || *s == (char) 0) */
773 if (s == NULL)
774 break;
775 goto_filedir(buf, 1);
776 }
777 break;
778 case 1:
779 /* Previous directory */
780 goto_filedir(prev_dir, 1);
781 break;
782 case 2:
783 /* File (wildcard) spec */
784 {
785 char *s = input(_("Filename pattern:"), wc_mem);
786 if (s == NULL || *s == (char) 0)
787 break;
788 strcpy(wc_str, wc_mem);
789 new_filedir(global_dirdat, 1);
790 wc_str[0] = (char)0;
791 }
792 break;
793 case 3:
794 /* Tag */
795 if (how_many == 1)
796 file_tell(_("Can select only one!"));
797 else if (how_many == -1) {
798 char tag_buf[128];
799 char *s;
800 strncpy(tag_buf, wc_mem, 128);
801
802 s = input(_("Tag pattern:"), tag_buf);
803 if (s != NULL && *s != (char)0) {
804 int newly_tagged;
805 if ((newly_tagged = tag_untag(tag_buf, 1)) == 0) {
806 file_tell(_("No file(s) tagged"));
807 goto tag_end;
808 }
809 tag_cnt += newly_tagged;
810 prdir(main_w, top, top, global_dirdat, longest);
811 }
812 }
813 tag_end:
814 break;
815 case 4:
816 /* Untag */
817 {
818 char tag_buf[128];
819 char *s;
820 int untagged;
821 strncpy(tag_buf, wc_mem, 128);
822
823 s = input(_("Untag pattern:"), tag_buf);
824 if (s == NULL || *s == (char)0)
825 goto untag_end;
826 if ((untagged = tag_untag(tag_buf, 0)) == 0) {
827 file_tell(_("No file(s) untagged"));
828 goto untag_end;
829 }
830 tag_cnt -= untagged;
831 prdir(main_w, top, top, global_dirdat, longest);
832 }
833 untag_end:
834 break;
835 case 5:
836 {
837 /* Done */
838 char *ret_ptr = NULL; /* failsafe: assume failure */
839
840 if (how_many != 0 && !tag_cnt) {
841
842 while (1) {
843 s = input(_("No file selected - enter filename:"),
844 ret_buf);
845 if (s != NULL && *s != (char) 0) {
846 int f_exist = access(ret_buf, F_OK);
847 if (down_loading) {
848 if (f_exist != -1) {
849 /* ask 'em if they're *sure* */
850 char buf[BUFSIZ];
851
852 snprintf(buf, sizeof(buf),
853 _("File: \"%s\" exists! Overwrite?"), ret_buf);
854 if (ask(buf, d_yesno) == 0) {
855 ret_ptr = ret_buf;
856 break;
857 }
858 } else {
859 ret_ptr = ret_buf;
860 break;
861 }
862 } else {
863 if (f_exist == -1)
864 file_tell(_("no such file!"));
865 else {
866 ret_ptr = ret_buf;
867 break;
868 }
869 }
870 } else {
871 /* maybe want to ask: "abort?", here */
872 goto again;
873 }
874 }
875 }
876 else {
877 /* put 'em in a buffer for return */
878 if (how_many == 0) {
879 /* current working directory */
880 ret_ptr = work_dir;
881 } else {
882 ret_ptr = concat_list(global_dirdat);
883 }
884 }
885
886 mc_wclose(main_w, 1);
887 mc_wclose(dsub, 1);
888 free(global_dirdat);
889 global_dirdat = NULL;
890 return ret_ptr;
891 }
892 break;
893 default:
894 /* should "beep", I guess (? shouldn't get here) */
895 file_tell("BEEP!");
896 break;
897 } /* switch */
898 }
899
900 goto again;
901 }
902