Blame src/file.c

Packit 15a96c
/*
Packit 15a96c
 * file.c	Functions to handle file selector.
Packit 15a96c
 *
Packit 15a96c
 *	This file is part of the minicom communications package,
Packit 15a96c
 *	Copyright 1991-1995 Miquel van Smoorenburg.
Packit 15a96c
 *
Packit 15a96c
 *	This file created from code mostly cadged from "dial.c"
Packit 15a96c
 *	by Miquel van Smoorenburg.  Written by James S. Seymour.
Packit 15a96c
 *	Copyright (c) 1998 by James S. Seymour (jseymour@jimsun.LinxNet.com)
Packit 15a96c
 *      Some mods for i18n
Packit 15a96c
 *      Copyright (c) 1998 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
Packit 15a96c
 *
Packit 15a96c
 *	This program is free software; you can redistribute it and/or
Packit 15a96c
 *	modify it under the terms of the GNU General Public License
Packit 15a96c
 *	as published by the Free Software Foundation; either version
Packit 15a96c
 *	2 of the License, or (at your option) any later version.
Packit 15a96c
 *
Packit 15a96c
 *  You should have received a copy of the GNU General Public License along
Packit 15a96c
 *  with this program; if not, write to the Free Software Foundation, Inc.,
Packit 15a96c
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Packit 15a96c
 *
Packit 15a96c
 */
Packit 15a96c
#ifdef HAVE_CONFIG_H
Packit 15a96c
#include <config.h>
Packit 15a96c
#endif
Packit 15a96c
Packit 15a96c
#include <limits.h>
Packit 15a96c
Packit 15a96c
#include "port.h"
Packit 15a96c
#include "minicom.h"
Packit 15a96c
#include "intl.h"
Packit 15a96c
#include "getsdir.h"
Packit 15a96c
Packit 15a96c
#ifdef HAVE_UNISTD_H
Packit 15a96c
#  include <unistd.h>
Packit 15a96c
#endif
Packit 15a96c
Packit 15a96c
#define FILE_MWTR 1	/* main window top row */
Packit 15a96c
#define SUBM_OKAY 5	/* last entry in sub-menu */
Packit 15a96c
Packit 15a96c
static int nrents = 1;
Packit 15a96c
Packit 15a96c
static void file_tell(const char *s);
Packit 15a96c
static void dhili(int k);
Packit 15a96c
static void prdir(WIN *dirw, int top, int cur, GETSDIR_ENTRY *dirdat, int longest);
Packit 15a96c
static void prone(WIN *dirw, GETSDIR_ENTRY *dirdat, int longest, int inverse);
Packit 15a96c
static void *set_work_dir(void *existing, size_t min_len);
Packit 15a96c
static int  new_filedir(GETSDIR_ENTRY *dirdat, int flushit);
Packit 15a96c
static void goto_filedir(char *new_dir, int absolut);
Packit 15a96c
static int  tag_untag(char *pat, int tag);
Packit 15a96c
static char *concat_list(GETSDIR_ENTRY *d);
Packit 15a96c
Packit 15a96c
static WIN *dsub;
Packit 15a96c
static const char *const what[] =
Packit 15a96c
  {
Packit 15a96c
    /* TRANSLATORS: Translation of each of these menu items should not be
Packit 15a96c
     * longer than 7 characters. The upper-case letter is a shortcut,
Packit 15a96c
     * so keep them unique and ASCII; 'h', 'j', 'k', 'l' are reserved */
Packit 15a96c
    N_("[Goto]"), N_("[Prev]"), N_("[Show]"), N_("[Tag]"), N_("[Untag]"),
Packit 15a96c
    N_("[Okay]")
Packit 15a96c
  };
Packit 15a96c
#define WHAT_NR_OPTIONS (sizeof (what) / sizeof (*what))
Packit 15a96c
#define WHAT_WIDTH 8 /* Width of one entry */
Packit 15a96c
/* Number of bytes for <= 7 characters */
Packit 15a96c
static int what_lens[WHAT_NR_OPTIONS];
Packit 15a96c
/* Number of ' ' padding entries at left and right, left is >= 1 */
Packit 15a96c
static int what_padding[WHAT_NR_OPTIONS][2];
Packit 15a96c
static int dprev;
Packit 15a96c
Packit 15a96c
/* Little menu. */
Packit 15a96c
static const char *d_yesno[] = { N_("   Yes  "), N_("   No   "), NULL };
Packit 15a96c
Packit 15a96c
Packit 15a96c
/*
Packit 15a96c
 * Tell a little message
Packit 15a96c
 */
Packit 15a96c
static void file_tell(const char *s)
Packit 15a96c
{
Packit 15a96c
  WIN *w;
Packit 15a96c
Packit 15a96c
  w = mc_tell("%s", s);
Packit 15a96c
  sleep(1);
Packit 15a96c
  mc_wclose(w, 1);
Packit 15a96c
}
Packit 15a96c
Packit 15a96c
/* Draw an entry in the horizontal menu */
Packit 15a96c
static void horiz_draw(size_t k, char start_attr, char end_attr)
Packit 15a96c
{
Packit 15a96c
  static const char spaces[] = "        ";
Packit 15a96c
Packit 15a96c
  mc_wprintf(dsub, "%.*s", what_padding[k][0], spaces);
Packit 15a96c
  mc_wsetattr(dsub, start_attr);
Packit 15a96c
  mc_wprintf(dsub, "%.*s", what_lens[k], _(what[k]));
Packit 15a96c
  mc_wsetattr(dsub, end_attr);
Packit 15a96c
  mc_wprintf(dsub, "%.*s", what_padding[k][1], spaces);
Packit 15a96c
}
Packit 15a96c
Packit 15a96c
/*
Packit 15a96c
 * Highlight a choice in the horizontal menu.
Packit 15a96c
 */
Packit 15a96c
static void dhili(int k)
Packit 15a96c
{
Packit 15a96c
  int initial_y = (76 - (WHAT_NR_OPTIONS * WHAT_WIDTH >= 76
Packit 15a96c
	           ? 74 : WHAT_NR_OPTIONS * WHAT_WIDTH)) / 2;
Packit 15a96c
Packit 15a96c
  if (k == dprev)
Packit 15a96c
    return;
Packit 15a96c
Packit 15a96c
  if (dprev >= 0) {
Packit 15a96c
    mc_wlocate(dsub, initial_y + WHAT_WIDTH * dprev, 0);
Packit 15a96c
    if (!useattr)
Packit 15a96c
      mc_wputs(dsub, " ");
Packit 15a96c
    else
Packit 15a96c
      horiz_draw(dprev, stdattr, stdattr);
Packit 15a96c
  }
Packit 15a96c
  dprev = k;
Packit 15a96c
Packit 15a96c
  mc_wlocate(dsub, initial_y + WHAT_WIDTH * k, 0);
Packit 15a96c
  if (!useattr)
Packit 15a96c
    mc_wputs(dsub, ">");
Packit 15a96c
  else
Packit 15a96c
    horiz_draw(k, XA_REVERSE | stdattr, stdattr);
Packit 15a96c
}
Packit 15a96c
Packit 15a96c
static inline GETSDIR_ENTRY *getno(int no, GETSDIR_ENTRY *d)
Packit 15a96c
{
Packit 15a96c
  if (no >= nrents)
Packit 15a96c
    return NULL;
Packit 15a96c
  return d + no;
Packit 15a96c
}
Packit 15a96c
Packit 15a96c
/*
Packit 15a96c
 * Print the directory. Only draw from "cur" to bottom.
Packit 15a96c
 */
Packit 15a96c
static void prdir(WIN *dirw, int top, int cur,
Packit 15a96c
                  GETSDIR_ENTRY *dirdat, int longest)
Packit 15a96c
{
Packit 15a96c
  int f, start;
Packit 15a96c
  char f_str[BUFSIZ];
Packit 15a96c
  char t_str[BUFSIZ];
Packit 15a96c
Packit 15a96c
  start = cur - top;
Packit 15a96c
  dirflush = 0;
Packit 15a96c
  sprintf(f_str, " %%-%ds", longest + 2);
Packit 15a96c
  mc_wlocate(dirw, 0, start + FILE_MWTR);
Packit 15a96c
  for (f = start; f < dirw->ys - (1 + FILE_MWTR); f++) {
Packit 15a96c
    GETSDIR_ENTRY *d;
Packit 15a96c
    if (!(d = getno(f + top, dirdat)))
Packit 15a96c
      break;
Packit 15a96c
    if (d->cflags & FL_TAG)
Packit 15a96c
      mc_wsetattr(dirw, XA_REVERSE | stdattr);
Packit 15a96c
    if (S_ISDIR(d->mode)) {
Packit 15a96c
      snprintf(t_str, sizeof(t_str), "[%s]", d->fname);
Packit 15a96c
      mc_wprintf(dirw, f_str, t_str);
Packit 15a96c
    } else
Packit 15a96c
      mc_wprintf(dirw, f_str, d->fname);
Packit 15a96c
    mc_wsetattr(dirw, XA_NORMAL | stdattr);
Packit 15a96c
    mc_wputc(dirw, '\n');
Packit 15a96c
  }
Packit 15a96c
  dirflush = 1;
Packit 15a96c
  mc_wflush();
Packit 15a96c
}
Packit 15a96c
Packit 15a96c
/*
Packit 15a96c
 * Print one directory entry.
Packit 15a96c
 */
Packit 15a96c
static void prone(WIN *dirw, GETSDIR_ENTRY *dirdat, int longest, int inverse)
Packit 15a96c
{
Packit 15a96c
  char f_str[BUFSIZ];
Packit 15a96c
  char t_str[BUFSIZ];
Packit 15a96c
Packit 15a96c
  dirflush = 0;
Packit 15a96c
  sprintf(f_str, " %%-%ds", longest + 2);
Packit 15a96c
  /*
Packit 15a96c
  if (dirdat->cflags & FL_TAG)
Packit 15a96c
    mc_wsetattr(dirw, XA_REVERSE | stdattr);
Packit 15a96c
     */
Packit 15a96c
  if (inverse)
Packit 15a96c
    mc_wsetattr(dirw, XA_REVERSE | stdattr);
Packit 15a96c
  if (S_ISDIR(dirdat->mode)) {
Packit 15a96c
    snprintf(t_str, sizeof(t_str),  "[%s]", dirdat->fname);
Packit 15a96c
    mc_wprintf(dirw, f_str, t_str);
Packit 15a96c
  } else
Packit 15a96c
    mc_wprintf(dirw, f_str, dirdat->fname);
Packit 15a96c
  mc_wsetattr(dirw, XA_NORMAL | stdattr);
Packit 15a96c
  dirflush = 1;
Packit 15a96c
  mc_wflush();
Packit 15a96c
}
Packit 15a96c
Packit 15a96c
static WIN *main_w;
Packit 15a96c
static GETSDIR_ENTRY *global_dirdat;
Packit 15a96c
static int cur = 0;
Packit 15a96c
static int ocur = 0;
Packit 15a96c
static int subm = SUBM_OKAY;
Packit 15a96c
static int quit = 0;
Packit 15a96c
static int top = 0;
Packit 15a96c
static int c = 0;
Packit 15a96c
static int pgud = 0;
Packit 15a96c
static int first = 1;
Packit 15a96c
static char *s;
Packit 15a96c
static int longest;
Packit 15a96c
static char file_title[BUFSIZ];
Packit 15a96c
static char cwd_str[BUFSIZ];
Packit 15a96c
static char *prev_dir = NULL;
Packit 15a96c
static char *work_dir = NULL;
Packit 15a96c
static char *d_work_dir = NULL;
Packit 15a96c
static char *u_work_dir = NULL;
Packit 15a96c
static int min_len = 1;
Packit 15a96c
static char wc_str[128] = "";
Packit 15a96c
static char wc_mem[128] = "";
Packit 15a96c
static int tag_cnt = 0;
Packit 15a96c
static int how_many = 0;
Packit 15a96c
static int down_loading = 0;
Packit 15a96c
static char *ret_buf = NULL;
Packit 15a96c
Packit 15a96c
Packit 15a96c
/* Init up/down work directories to make sure we start from
Packit 15a96c
 * the configuration defaults on the next up/download. jl 6/2000
Packit 15a96c
 */
Packit 15a96c
void init_dir(char dir)
Packit 15a96c
{
Packit 15a96c
  char *p = NULL;
Packit 15a96c
Packit 15a96c
  switch (dir) {
Packit 15a96c
  case 'u':
Packit 15a96c
    p = u_work_dir;
Packit 15a96c
    u_work_dir = NULL;
Packit 15a96c
    break;
Packit 15a96c
  case 'd':
Packit 15a96c
    p = d_work_dir;
Packit 15a96c
    d_work_dir = NULL;
Packit 15a96c
    break;
Packit 15a96c
  }
Packit 15a96c
  free((void *) p);
Packit 15a96c
  return;
Packit 15a96c
}
Packit 15a96c
Packit 15a96c
static void *set_work_dir(void *existing, size_t min_len)
Packit 15a96c
{
Packit 15a96c
  void *vp = realloc(existing, min_len);
Packit 15a96c
Packit 15a96c
  if (down_loading)
Packit 15a96c
    d_work_dir = vp;
Packit 15a96c
  else
Packit 15a96c
    u_work_dir = vp;
Packit 15a96c
Packit 15a96c
  return vp;
Packit 15a96c
}
Packit 15a96c
Packit 15a96c
Packit 15a96c
/*
Packit 15a96c
 * Initialize new file directory.
Packit 15a96c
 *
Packit 15a96c
 * Sets the current working directory.  Non-0 return = no change.
Packit 15a96c
 */
Packit 15a96c
static int new_filedir(GETSDIR_ENTRY *dirdat, int flushit)
Packit 15a96c
{
Packit 15a96c
  static size_t dp_len = 0;
Packit 15a96c
  static char cwd_str_fmt[BUFSIZ] = "";
Packit 15a96c
  size_t new_dp_len, fmt_len;
Packit 15a96c
  char disp_dir[80];
Packit 15a96c
  int initial_y = (76 - (WHAT_NR_OPTIONS * WHAT_WIDTH >= 76
Packit 15a96c
                   ? 74 : WHAT_NR_OPTIONS * WHAT_WIDTH)) / 2;
Packit 15a96c
  size_t i;
Packit 15a96c
  char * new_prev_dir;
Packit 15a96c
Packit 15a96c
  cur      =  0;
Packit 15a96c
  ocur     =  0;
Packit 15a96c
  subm     =  SUBM_OKAY;
Packit 15a96c
  quit     =  0;
Packit 15a96c
  top      =  0;
Packit 15a96c
  c        =  0;
Packit 15a96c
  pgud     =  0;
Packit 15a96c
  first    =  1;
Packit 15a96c
  min_len  =  1;
Packit 15a96c
  dprev    = -1;
Packit 15a96c
  tag_cnt  =  0;
Packit 15a96c
Packit 15a96c
  /*
Packit 15a96c
   * get last directory
Packit 15a96c
   */
Packit 15a96c
  work_dir = down_loading ? d_work_dir : u_work_dir;
Packit 15a96c
Packit 15a96c
  /*
Packit 15a96c
   * init working directory to default?
Packit 15a96c
   */
Packit 15a96c
  if (work_dir == NULL) {
Packit 15a96c
    char *s = down_loading? P_DOWNDIR : P_UPDIR;
Packit 15a96c
    min_len = 1;
Packit 15a96c
Packit 15a96c
    if (*s != '/')
Packit 15a96c
      min_len += strlen(homedir) + 1;
Packit 15a96c
    min_len += strlen(s);
Packit 15a96c
    if (min_len < BUFSIZ)
Packit 15a96c
      min_len = BUFSIZ;
Packit 15a96c
Packit 15a96c
    work_dir = set_work_dir(NULL, min_len);
Packit 15a96c
Packit 15a96c
    if (*s == '/')
Packit 15a96c
      strncpy(work_dir, s, min_len);
Packit 15a96c
    else
Packit 15a96c
      snprintf(work_dir, min_len, "%s/%s", homedir, s);
Packit 15a96c
  }
Packit 15a96c
  /* lop-off trailing "/" for consistency */
Packit 15a96c
  if (strlen(work_dir) > 1 && work_dir[strlen(work_dir) - 1] == '/')
Packit 15a96c
    work_dir[strlen(work_dir) - 1] = (char)0;
Packit 15a96c
Packit 15a96c
  /* get the current working directory, which will become the prev_dir, on success */
Packit 15a96c
  new_prev_dir = getcwd(NULL, BUFSIZ);
Packit 15a96c
  if (!new_prev_dir)
Packit 15a96c
    return -1;
Packit 15a96c
Packit 15a96c
  if (!access(work_dir, R_OK | X_OK) && !chdir(work_dir)) {
Packit 15a96c
    /* was able to change to new working directory */
Packit 15a96c
    free(prev_dir);
Packit 15a96c
    prev_dir = new_prev_dir;
Packit 15a96c
  }
Packit 15a96c
  else {
Packit 15a96c
    /* Could not change to the new working directory */
Packit 15a96c
    mc_wbell();
Packit 15a96c
    werror(
Packit 15a96c
        _("Could not change to directory %s (%s)"), 
Packit 15a96c
        work_dir,
Packit 15a96c
        strerror(errno));
Packit 15a96c
Packit 15a96c
    /* restore the previous working directory */
Packit 15a96c
    free(work_dir);
Packit 15a96c
    work_dir = set_work_dir(new_prev_dir, strlen(new_prev_dir));
Packit 15a96c
  }
Packit 15a96c
Packit 15a96c
  /* All right, draw the file directory! */
Packit 15a96c
Packit 15a96c
  if (flushit) {
Packit 15a96c
    dirflush = 0;
Packit 15a96c
    mc_winclr(main_w);
Packit 15a96c
    mc_wredraw(main_w, 1);
Packit 15a96c
  }
Packit 15a96c
Packit 15a96c
  mc_wcursor(main_w, CNORMAL);
Packit 15a96c
Packit 15a96c
  {
Packit 15a96c
    char *s;
Packit 15a96c
Packit 15a96c
    if (down_loading) {
Packit 15a96c
      if (how_many < 0)
Packit 15a96c
        s = _("Select one or more files for download");
Packit 15a96c
      else if (how_many)
Packit 15a96c
	s = _("Select a file for download");
Packit 15a96c
      else
Packit 15a96c
	s = _("Select a directory for download");
Packit 15a96c
    } else {
Packit 15a96c
      if (how_many < 0)
Packit 15a96c
        s = _("Select one or more files for upload");
Packit 15a96c
      else if (how_many)
Packit 15a96c
	s = _("Select a file for upload");
Packit 15a96c
      else
Packit 15a96c
	s = _("Select a directory for upload");
Packit 15a96c
    }
Packit 15a96c
    snprintf(file_title, sizeof(file_title), "%s", s);
Packit 15a96c
  }
Packit 15a96c
Packit 15a96c
  mc_wtitle(main_w, TMID, file_title);
Packit 15a96c
  if ((new_dp_len = strlen(work_dir)) > dp_len) {
Packit 15a96c
    dp_len = new_dp_len;
Packit 15a96c
    snprintf(cwd_str_fmt, sizeof(cwd_str_fmt),
Packit 15a96c
             _("Directory: %%-%ds"), (int)dp_len);
Packit 15a96c
  }
Packit 15a96c
  new_dp_len = mbslen (work_dir);
Packit 15a96c
  if (new_dp_len + (fmt_len = mbslen(cwd_str_fmt)) > 75) {
Packit 15a96c
    size_t i;
Packit 15a96c
    char *tmp_dir = work_dir;
Packit 15a96c
Packit 15a96c
    /* We want the last 73 characters */
Packit 15a96c
    for (i = 0; 73 + i < new_dp_len + fmt_len; i++) {
Packit 15a96c
      wchar_t wc;
Packit 15a96c
Packit 15a96c
      tmp_dir += one_mbtowc(&wc, work_dir, MB_LEN_MAX);
Packit 15a96c
    }
Packit 15a96c
    snprintf(disp_dir, sizeof(disp_dir), "...%s", tmp_dir);
Packit 15a96c
    snprintf(cwd_str, sizeof(cwd_str), cwd_str_fmt, disp_dir);
Packit 15a96c
  } else
Packit 15a96c
    snprintf(cwd_str, sizeof(cwd_str), cwd_str_fmt, work_dir);
Packit 15a96c
Packit 15a96c
  mc_wlocate(main_w, 0, 0);
Packit 15a96c
  mc_wputs(main_w, cwd_str);
Packit 15a96c
Packit 15a96c
  for (i = 0; i < WHAT_NR_OPTIONS; i++) {
Packit 15a96c
    const char *str, *c;
Packit 15a96c
    size_t j;
Packit 15a96c
Packit 15a96c
    str = _(what[i]);
Packit 15a96c
    c = str;
Packit 15a96c
    for (j = 0; j < WHAT_WIDTH - 1 && *c != 0; j++) {
Packit 15a96c
      wchar_t wc;
Packit 15a96c
      c += one_mbtowc (&wc, c, MB_LEN_MAX);
Packit 15a96c
    }
Packit 15a96c
    what_lens[i] = c - str;
Packit 15a96c
    j = WHAT_WIDTH - j; /* Characters left for padding */
Packit 15a96c
    what_padding[i][1] = j / 2; /* Rounding down */
Packit 15a96c
    what_padding[i][0] = j - what_padding[i][1]; /* >= 1 */
Packit 15a96c
  }
Packit 15a96c
  mc_wlocate(dsub, initial_y, 0);
Packit 15a96c
  for (i = 0; i < WHAT_NR_OPTIONS; i++)
Packit 15a96c
    horiz_draw(i, mc_wgetattr(dsub), mc_wgetattr(dsub));
Packit 15a96c
Packit 15a96c
  mc_wsetregion(main_w, 1, main_w->ys - FILE_MWTR);
Packit 15a96c
  main_w->doscroll = 0;
Packit 15a96c
Packit 15a96c
  /* old dir to discard? */
Packit 15a96c
  free(dirdat);
Packit 15a96c
  dirdat = NULL;
Packit 15a96c
Packit 15a96c
  /* get sorted directory */
Packit 15a96c
  if ((nrents = getsdir(".", wc_str,
Packit 15a96c
                        GETSDIR_PARNT|GETSDIR_NSORT|GETSDIR_DIRSF,
Packit 15a96c
                        0, &dirdat, &longest)) < 0) {
Packit 15a96c
    /* we really want to announce the error here!!! */
Packit 15a96c
    mc_wclose(main_w, 1);
Packit 15a96c
    mc_wclose(dsub, 1);
Packit 15a96c
    free(dirdat);
Packit 15a96c
    dirdat = NULL;
Packit 15a96c
    return -1;
Packit 15a96c
  }
Packit 15a96c
Packit 15a96c
  global_dirdat = dirdat; // Hmm...
Packit 15a96c
Packit 15a96c
  prdir(main_w, top, top, dirdat, longest);
Packit 15a96c
  mc_wlocate(main_w, initial_y, main_w->ys - FILE_MWTR);
Packit 15a96c
  mc_wputs(main_w, _("( Escape to exit, Space to tag )"));
Packit 15a96c
  dhili(subm);
Packit 15a96c
  /* this really needs to go in dhili !!!*/
Packit 15a96c
  mc_wlocate(main_w, 0, cur + FILE_MWTR - top);
Packit 15a96c
  if (flushit) {
Packit 15a96c
    dirflush = 1;
Packit 15a96c
    mc_wredraw(dsub, 1);
Packit 15a96c
  }
Packit 15a96c
Packit 15a96c
  return 0;
Packit 15a96c
}
Packit 15a96c
Packit 15a96c
Packit 15a96c
/*
Packit 15a96c
 * Goto a new directory
Packit 15a96c
 */
Packit 15a96c
static void goto_filedir(char *new_dir, int absolut)
Packit 15a96c
{
Packit 15a96c
  if (strcmp(new_dir, "..") == 0) {
Packit 15a96c
    if (strcmp(work_dir, "/")) {
Packit 15a96c
      char *sp = strrchr(work_dir, '/');
Packit 15a96c
      *sp = (char)0;
Packit 15a96c
      if (strlen(work_dir) == 0)
Packit 15a96c
        strcpy(work_dir, "/");
Packit 15a96c
    } else {
Packit 15a96c
      file_tell(_("Can't back up!"));
Packit 15a96c
      return;
Packit 15a96c
    }
Packit 15a96c
  } else if (!absolut) {
Packit 15a96c
    int new_len = strlen(work_dir) + 1;	/* + '/' */
Packit 15a96c
    if ((new_len += strlen(new_dir) + 1) > min_len) {
Packit 15a96c
      min_len = new_len;
Packit 15a96c
      work_dir = set_work_dir(work_dir, min_len);
Packit 15a96c
    }
Packit 15a96c
    if (strcmp(work_dir, "/") != 0)
Packit 15a96c
      strcat(work_dir, "/");
Packit 15a96c
    strcat(work_dir, new_dir);
Packit 15a96c
  } else {
Packit 15a96c
    int new_len = 1;
Packit 15a96c
    if (*new_dir != '/')
Packit 15a96c
      new_len += strlen(homedir) + 1;
Packit 15a96c
    new_len += strlen(new_dir);
Packit 15a96c
    if (min_len < new_len)
Packit 15a96c
      min_len = new_len;
Packit 15a96c
Packit 15a96c
    work_dir = set_work_dir(work_dir, min_len);
Packit 15a96c
Packit 15a96c
    if (*new_dir == '/')
Packit 15a96c
      strncpy(work_dir, new_dir, min_len);
Packit 15a96c
    else
Packit 15a96c
      snprintf(work_dir, min_len, "%s/%s", homedir, new_dir);
Packit 15a96c
  }
Packit 15a96c
  new_filedir(global_dirdat, 1);
Packit 15a96c
}
Packit 15a96c
Packit 15a96c
Packit 15a96c
/*
Packit 15a96c
 * Initialize the file directory.
Packit 15a96c
 */
Packit 15a96c
static int init_filedir(void)
Packit 15a96c
{
Packit 15a96c
  int x1, x2;
Packit 15a96c
  int retstat = -1;
Packit 15a96c
Packit 15a96c
  dirflush = 0;
Packit 15a96c
  x1 = (COLS / 2) - 37;
Packit 15a96c
  x2 = (COLS / 2) + 37;
Packit 15a96c
  dsub = mc_wopen(x1 - 1, LINES - 3, x2 + 1, LINES - 3, BNONE, 
Packit 15a96c
               stdattr, mfcolor, mbcolor, 0, 0, 1);
Packit 15a96c
  main_w = mc_wopen(x1, 2, x2, LINES - 6, BSINGLE, stdattr, mfcolor,
Packit 15a96c
                 mbcolor, 0, 0, 1);
Packit 15a96c
Packit 15a96c
  if (ret_buf != NULL ||
Packit 15a96c
      (retstat = ((ret_buf = (char *)malloc(BUFSIZ)) == NULL)? -1 : 0) == 0) {
Packit 15a96c
    retstat = new_filedir(NULL, 0);
Packit 15a96c
    dirflush = 1;
Packit 15a96c
    mc_wredraw(dsub, 1);
Packit 15a96c
  }
Packit 15a96c
  return retstat;
Packit 15a96c
}
Packit 15a96c
Packit 15a96c
Packit 15a96c
static int tag_untag(char *pat, int tag)
Packit 15a96c
{
Packit 15a96c
  GETSDIR_ENTRY *d = global_dirdat;
Packit 15a96c
  int indxr, cntr;
Packit 15a96c
Packit 15a96c
  if (nrents < 1)
Packit 15a96c
    return 0;
Packit 15a96c
Packit 15a96c
  for (indxr = nrents, cntr = 0; indxr; --indxr, ++d)
Packit 15a96c
    if (S_ISREG(d->mode) && wildmat(d->fname, pat)) {
Packit 15a96c
      if (tag) {
Packit 15a96c
        d->cflags |= FL_TAG;
Packit 15a96c
        ++cntr;
Packit 15a96c
      } else if (d->cflags & FL_TAG) {
Packit 15a96c
        d->cflags &= ~FL_TAG;
Packit 15a96c
        ++cntr;
Packit 15a96c
      }
Packit 15a96c
    }
Packit 15a96c
Packit 15a96c
  return cntr;
Packit 15a96c
}
Packit 15a96c
Packit 15a96c
Packit 15a96c
/*
Packit 15a96c
 * concatenate tagged files into a buffer
Packit 15a96c
 */
Packit 15a96c
static char *concat_list(GETSDIR_ENTRY *dirdat)
Packit 15a96c
{
Packit 15a96c
  GETSDIR_ENTRY *d;
Packit 15a96c
  int indxr, len;
Packit 15a96c
  int i;
Packit 15a96c
  char *j;
Packit 15a96c
Packit 15a96c
  d = dirdat;
Packit 15a96c
  for (indxr = nrents, len = 0; indxr; --indxr, ++d)
Packit 15a96c
    if (d->cflags & FL_TAG)
Packit 15a96c
      len += strlen(d->fname) + 1;
Packit 15a96c
Packit 15a96c
  if (len) {
Packit 15a96c
    if (len > BUFSIZ) {
Packit 15a96c
      if ((ret_buf = (char *)realloc(ret_buf, len)) == NULL) {
Packit 15a96c
        file_tell(_("Too many files tagged - buffer would overflow"));
Packit 15a96c
        return NULL;
Packit 15a96c
      }
Packit 15a96c
    }
Packit 15a96c
Packit 15a96c
    *ret_buf = (char)0;
Packit 15a96c
    d = dirdat;
Packit 15a96c
    for (indxr = nrents; indxr; --indxr, ++d)
Packit 15a96c
      if (d->cflags & FL_TAG) {
Packit 15a96c
        /* this could be *much* more efficient */
Packit 15a96c
        for (i = strlen(ret_buf), j = d->fname; *j; j++) {
Packit 15a96c
          if (*j == ' ') {
Packit 15a96c
            if ((ret_buf = (char*)realloc(ret_buf, ++len)) == NULL) {
Packit 15a96c
              file_tell(_("Too many files tagged - buffer would overflow"));
Packit 15a96c
              return(NULL);
Packit 15a96c
            }
Packit 15a96c
            ret_buf[i++] = '\\';
Packit 15a96c
          }
Packit 15a96c
          ret_buf[i++] = *j;
Packit 15a96c
        }
Packit 15a96c
        ret_buf[i++] = ' ';
Packit 15a96c
        ret_buf[i]   = '\0';
Packit 15a96c
      }
Packit 15a96c
Packit 15a96c
    ret_buf[strlen(ret_buf) - 1] = (char)0;
Packit 15a96c
    return ret_buf;
Packit 15a96c
  }
Packit 15a96c
Packit 15a96c
  return NULL;
Packit 15a96c
}
Packit 15a96c
Packit 15a96c
Packit 15a96c
/*
Packit 15a96c
 * Draw the file directory.
Packit 15a96c
 *
Packit 15a96c
 *      howmany - How many files can be selected
Packit 15a96c
 *		      0 = none (for directory selection only, as in "rz")
Packit 15a96c
 *		      1 = one  (for single-file up-/down-loads, as in "rx")
Packit 15a96c
 *		     -1 = any number (for multiple files, as in "sz")
Packit 15a96c
 *
Packit 15a96c
 *    downloading - Is this for download selection?
Packit 15a96c
 *		      0 = no
Packit 15a96c
 *		      1 = yes - when single file selected, see if it exists
Packit 15a96c
 */
Packit 15a96c
char * filedir(int howmany, int downloading)
Packit 15a96c
{
Packit 15a96c
  time_t click_time = (time_t) 0;
Packit 15a96c
  size_t i;
Packit 15a96c
Packit 15a96c
  how_many = howmany;
Packit 15a96c
  down_loading = downloading;
Packit 15a96c
  init_filedir();
Packit 15a96c
Packit 15a96c
again:
Packit 15a96c
  mc_wlocate(main_w, 0, cur + FILE_MWTR - top);
Packit 15a96c
  if (first) {
Packit 15a96c
    mc_wredraw(main_w, 1);
Packit 15a96c
    first = 0;
Packit 15a96c
  }
Packit 15a96c
  while (!quit) {
Packit 15a96c
    GETSDIR_ENTRY *d = getno(cur, global_dirdat);
Packit 15a96c
    /*
Packit 15a96c
       if(S_ISDIR(d->mode))
Packit 15a96c
       prone(main_w, d, longest, 0);	
Packit 15a96c
       */
Packit 15a96c
    switch (c = wxgetch()) {
Packit 15a96c
      case K_UP:
Packit 15a96c
      case 'k':
Packit 15a96c
        /*
Packit 15a96c
         if(S_ISDIR(d->mode))
Packit 15a96c
         prone(main_w, d, longest, 1);	
Packit 15a96c
         */
Packit 15a96c
        cur -= cur > 0;
Packit 15a96c
        break;
Packit 15a96c
      case K_DN:
Packit 15a96c
      case 'j':
Packit 15a96c
        /*
Packit 15a96c
         if(S_ISDIR(d->mode))
Packit 15a96c
         prone(main_w, d, longest, 1);
Packit 15a96c
         */
Packit 15a96c
        cur += cur < nrents - 1;
Packit 15a96c
        break;
Packit 15a96c
      case K_LT:
Packit 15a96c
      case 'h':
Packit 15a96c
        subm--;
Packit 15a96c
        if (subm < 0)
Packit 15a96c
          subm = SUBM_OKAY;
Packit 15a96c
        break;
Packit 15a96c
      case K_RT:
Packit 15a96c
      case 'l':
Packit 15a96c
        subm = (subm + 1) % 6;
Packit 15a96c
        break;
Packit 15a96c
      case K_PGUP:
Packit 15a96c
      case '\002': /* Control-B */
Packit 15a96c
        pgud = 1;
Packit 15a96c
        quit = 1;
Packit 15a96c
        break;
Packit 15a96c
      case K_PGDN:
Packit 15a96c
      case '\006': /* Control-F */
Packit 15a96c
        pgud = 2;
Packit 15a96c
        quit = 1;
Packit 15a96c
        break;
Packit 15a96c
      case ' ':    /* Tag if not directory */
Packit 15a96c
        if (S_ISDIR(d->mode)) {
Packit 15a96c
          time_t this_time = time((time_t *)NULL);
Packit 15a96c
          if (this_time - click_time < 2) {
Packit 15a96c
            GETSDIR_ENTRY *d2 = getno(cur, global_dirdat);
Packit 15a96c
            goto_filedir(d2->fname, 0);
Packit 15a96c
            click_time = (time_t)0;
Packit 15a96c
          } else
Packit 15a96c
            click_time = this_time;
Packit 15a96c
        }
Packit 15a96c
        else {
Packit 15a96c
          if (how_many) {
Packit 15a96c
            if ((d->cflags ^= FL_TAG) & FL_TAG) {
Packit 15a96c
              if (tag_cnt && how_many == 1) {
Packit 15a96c
                d->cflags &= ~FL_TAG;
Packit 15a96c
                file_tell(_("Can select only one!"));
Packit 15a96c
                break;
Packit 15a96c
              }
Packit 15a96c
              ++tag_cnt;
Packit 15a96c
            } else
Packit 15a96c
              --tag_cnt;
Packit 15a96c
            mc_wlocate(main_w, 0, cur + FILE_MWTR - top);
Packit 15a96c
            prone(main_w, d, longest, d->cflags & FL_TAG);
Packit 15a96c
            mc_wputc(main_w, '\n');
Packit 15a96c
            cur += cur < nrents - 1;
Packit 15a96c
          }
Packit 15a96c
        }
Packit 15a96c
        break;
Packit 15a96c
Packit 15a96c
      case '\033':
Packit 15a96c
      case '\r':
Packit 15a96c
      case '\n':
Packit 15a96c
        quit = 1;
Packit 15a96c
        break;
Packit 15a96c
Packit 15a96c
      default:
Packit 15a96c
	for (i = 0; i < WHAT_NR_OPTIONS; i++) {
Packit 15a96c
	  if (strchr (_(what[i]), toupper (c)) != NULL) {
Packit 15a96c
	    subm = i;
Packit 15a96c
	    c = '\n';
Packit 15a96c
	    quit = 1;
Packit 15a96c
	    break;
Packit 15a96c
	  }
Packit 15a96c
	 }
Packit 15a96c
Packit 15a96c
        break;
Packit 15a96c
    }
Packit 15a96c
Packit 15a96c
    if (c != ' ')
Packit 15a96c
      click_time = (time_t)0;
Packit 15a96c
Packit 15a96c
    if (cur < top) {
Packit 15a96c
      top--;
Packit 15a96c
      prdir(main_w, top, top, global_dirdat, longest);
Packit 15a96c
    }
Packit 15a96c
    if (cur - top > main_w->ys - (2 + FILE_MWTR)) {
Packit 15a96c
      top++;
Packit 15a96c
      prdir(main_w, top, top, global_dirdat, longest);
Packit 15a96c
    }
Packit 15a96c
    /*
Packit 15a96c
     if(cur != ocur)
Packit 15a96c
     mc_wlocate(main_w, 0, cur + FILE_MWTR - top);
Packit 15a96c
     */
Packit 15a96c
Packit 15a96c
    ocur = cur;
Packit 15a96c
    dhili(subm);
Packit 15a96c
    /* this really needs to go in dhili !!!*/
Packit 15a96c
    mc_wlocate(main_w, 0, cur + FILE_MWTR - top);
Packit 15a96c
  }
Packit 15a96c
Packit 15a96c
  quit = 0;
Packit 15a96c
  /* ESC means quit */
Packit 15a96c
  if (c == '\033') {
Packit 15a96c
    mc_wclose(main_w, 1);
Packit 15a96c
    mc_wclose(dsub, 1);
Packit 15a96c
    free(global_dirdat);
Packit 15a96c
    global_dirdat = NULL;
Packit 15a96c
    return NULL;
Packit 15a96c
  }
Packit 15a96c
  /* Page up or down ? */
Packit 15a96c
  if (pgud == 1) { /* Page up */
Packit 15a96c
    ocur = top;
Packit 15a96c
    top -= main_w->ys - (1 + FILE_MWTR);
Packit 15a96c
    if (top < 0)
Packit 15a96c
      top = 0;
Packit 15a96c
    cur = top;
Packit 15a96c
    pgud = 0;
Packit 15a96c
    if (ocur != top)
Packit 15a96c
      prdir(main_w, top, cur, global_dirdat, longest);
Packit 15a96c
    ocur = cur;
Packit 15a96c
    goto again;
Packit 15a96c
  }
Packit 15a96c
  if (pgud == 2) { /* Page down */
Packit 15a96c
    ocur = top;
Packit 15a96c
    if (top < nrents - main_w->ys + (1 + FILE_MWTR)) {
Packit 15a96c
      top += main_w->ys - (1 + FILE_MWTR);
Packit 15a96c
      if (top > nrents - main_w->ys + (1 + FILE_MWTR)) {
Packit 15a96c
        top = nrents - main_w->ys + (1 + FILE_MWTR);
Packit 15a96c
      }
Packit 15a96c
      cur = top;
Packit 15a96c
    } else
Packit 15a96c
      cur = nrents - 1;
Packit 15a96c
    pgud = 0;
Packit 15a96c
    if (ocur != top)
Packit 15a96c
      prdir(main_w, top, cur, global_dirdat, longest);
Packit 15a96c
    ocur = cur;
Packit 15a96c
    goto again;
Packit 15a96c
  }
Packit 15a96c
Packit 15a96c
  if (c =='\r' || c == '\n') {
Packit 15a96c
    switch(subm) {
Packit 15a96c
      case 0:
Packit 15a96c
        /* Goto directory */
Packit 15a96c
        {
Packit 15a96c
          char buf[128];
Packit 15a96c
          char *s;
Packit 15a96c
          strncpy(buf, down_loading? P_DOWNDIR : P_UPDIR, sizeof(buf) -1);
Packit 15a96c
          s = input(_("Goto directory:"), buf);
Packit 15a96c
          /* if(s == NULL || *s == (char) 0) */
Packit 15a96c
          if (s == NULL)
Packit 15a96c
            break;
Packit 15a96c
          goto_filedir(buf, 1);
Packit 15a96c
        }
Packit 15a96c
        break;
Packit 15a96c
      case 1:
Packit 15a96c
        /* Previous directory */
Packit 15a96c
        goto_filedir(prev_dir, 1);
Packit 15a96c
        break;
Packit 15a96c
      case 2:
Packit 15a96c
        /* File (wildcard) spec */
Packit 15a96c
        {
Packit 15a96c
          char *s = input(_("Filename pattern:"), wc_mem);
Packit 15a96c
          if (s == NULL || *s == (char) 0)
Packit 15a96c
            break;
Packit 15a96c
          strcpy(wc_str, wc_mem);
Packit 15a96c
          new_filedir(global_dirdat, 1);
Packit 15a96c
          wc_str[0] = (char)0;
Packit 15a96c
        }
Packit 15a96c
        break;
Packit 15a96c
      case 3:
Packit 15a96c
        /* Tag */
Packit 15a96c
        if (how_many == 1)
Packit 15a96c
          file_tell(_("Can select only one!"));
Packit 15a96c
        else if (how_many == -1) {
Packit 15a96c
          char tag_buf[128];
Packit 15a96c
          char *s;
Packit 15a96c
          strncpy(tag_buf, wc_mem, 128);
Packit 15a96c
Packit 15a96c
          s = input(_("Tag pattern:"), tag_buf);
Packit 15a96c
          if (s != NULL && *s != (char)0) {
Packit 15a96c
            int newly_tagged;
Packit 15a96c
            if ((newly_tagged = tag_untag(tag_buf, 1)) == 0) {
Packit 15a96c
              file_tell(_("No file(s) tagged"));
Packit 15a96c
              goto tag_end;
Packit 15a96c
            }
Packit 15a96c
            tag_cnt += newly_tagged;
Packit 15a96c
            prdir(main_w, top, top, global_dirdat, longest);  
Packit 15a96c
          }
Packit 15a96c
        }
Packit 15a96c
tag_end:
Packit 15a96c
        break;
Packit 15a96c
      case 4:
Packit 15a96c
        /* Untag */
Packit 15a96c
        {
Packit 15a96c
          char tag_buf[128];
Packit 15a96c
          char *s;
Packit 15a96c
          int untagged;
Packit 15a96c
          strncpy(tag_buf, wc_mem, 128);
Packit 15a96c
Packit 15a96c
          s = input(_("Untag pattern:"), tag_buf);
Packit 15a96c
          if (s == NULL || *s == (char)0)
Packit 15a96c
            goto untag_end;
Packit 15a96c
          if ((untagged = tag_untag(tag_buf, 0)) == 0) {
Packit 15a96c
            file_tell(_("No file(s) untagged"));
Packit 15a96c
            goto untag_end;
Packit 15a96c
          }
Packit 15a96c
          tag_cnt -= untagged;
Packit 15a96c
          prdir(main_w, top, top, global_dirdat, longest);  
Packit 15a96c
        }
Packit 15a96c
untag_end:
Packit 15a96c
        break;
Packit 15a96c
      case 5:
Packit 15a96c
        {
Packit 15a96c
          /* Done */
Packit 15a96c
          char *ret_ptr = NULL;	/* failsafe: assume failure */
Packit 15a96c
Packit 15a96c
          if (how_many != 0 && !tag_cnt) {
Packit 15a96c
Packit 15a96c
            while (1) {
Packit 15a96c
              s = input(_("No file selected - enter filename:"),
Packit 15a96c
                        ret_buf);
Packit 15a96c
              if (s != NULL && *s != (char) 0) {
Packit 15a96c
                int f_exist = access(ret_buf, F_OK);
Packit 15a96c
                if (down_loading) {
Packit 15a96c
                  if (f_exist != -1) {
Packit 15a96c
                    /* ask 'em if they're *sure* */
Packit 15a96c
                    char buf[BUFSIZ];
Packit 15a96c
Packit 15a96c
                    snprintf(buf, sizeof(buf), 
Packit 15a96c
                             _("File: \"%s\" exists! Overwrite?"), ret_buf);
Packit 15a96c
                    if (ask(buf, d_yesno) == 0) {
Packit 15a96c
                      ret_ptr = ret_buf;
Packit 15a96c
                      break;
Packit 15a96c
                    }
Packit 15a96c
                  } else {
Packit 15a96c
                    ret_ptr = ret_buf;
Packit 15a96c
                    break;
Packit 15a96c
                  }
Packit 15a96c
                } else {
Packit 15a96c
                  if (f_exist == -1)
Packit 15a96c
                    file_tell(_("no such file!"));
Packit 15a96c
                  else {
Packit 15a96c
                    ret_ptr = ret_buf;
Packit 15a96c
                    break;
Packit 15a96c
                  }
Packit 15a96c
                }
Packit 15a96c
              } else {
Packit 15a96c
                /* maybe want to ask: "abort?", here */
Packit 15a96c
                goto again;
Packit 15a96c
              }
Packit 15a96c
            }
Packit 15a96c
          }
Packit 15a96c
          else {
Packit 15a96c
            /* put 'em in a buffer for return */
Packit 15a96c
            if (how_many == 0) {
Packit 15a96c
              /* current working directory */
Packit 15a96c
              ret_ptr = work_dir;
Packit 15a96c
            } else {
Packit 15a96c
              ret_ptr = concat_list(global_dirdat);
Packit 15a96c
            }
Packit 15a96c
          }
Packit 15a96c
Packit 15a96c
          mc_wclose(main_w, 1);
Packit 15a96c
          mc_wclose(dsub, 1);
Packit 15a96c
          free(global_dirdat);
Packit 15a96c
	  global_dirdat = NULL;
Packit 15a96c
          return ret_ptr;
Packit 15a96c
        }
Packit 15a96c
        break;
Packit 15a96c
      default:
Packit 15a96c
        /* should "beep", I guess (? shouldn't get here) */
Packit 15a96c
        file_tell("BEEP!");
Packit 15a96c
        break;
Packit 15a96c
    } /* switch */
Packit 15a96c
  }
Packit 15a96c
Packit 15a96c
  goto again;
Packit 15a96c
}