258 lines
6.6 KiB
C++
258 lines
6.6 KiB
C++
// This may look like C code, but it is really -*- C++ -*-
|
|
|
|
// ------------------------------------------------------------------
|
|
// The Goldware Library
|
|
// Copyright (C) 1990-1999 Odinn Sorensen
|
|
// Copyright (C) 1999-2000 Alexander S. Aganichev
|
|
// ------------------------------------------------------------------
|
|
// This library is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU Library General Public
|
|
// License as published by the Free Software Foundation; either
|
|
// version 2 of the License, or (at your option) any later version.
|
|
//
|
|
// This library is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
// Library General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Library General Public
|
|
// License along with this program; if not, write to the Free
|
|
// Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
// MA 02111-1307, USA
|
|
// ------------------------------------------------------------------
|
|
// $Id$
|
|
// ------------------------------------------------------------------
|
|
// Allows user to select a file name.
|
|
// ------------------------------------------------------------------
|
|
|
|
#include <gctype.h>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <gmemdbg.h>
|
|
#include <gfilutil.h>
|
|
#include <gwildmat.h>
|
|
#include <gwinall.h>
|
|
#include <gfilutil.h>
|
|
#include <gdirposx.h>
|
|
#include <gstrall.h>
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
static bool path_in_title, case_sensitive;
|
|
static VfvCP open_function = NULL;
|
|
static char* cwdp;
|
|
static char* tcwdp;
|
|
static char* namextp;
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
// this function is the compare function for qsort()
|
|
|
|
static int compare(const char** str1, const char** str2) {
|
|
|
|
// Sort with directories first
|
|
bool dir1 = !!strchr(*str1, GOLD_SLASH_CHR);
|
|
bool dir2 = !!strchr(*str2, GOLD_SLASH_CHR);
|
|
int cmp = compare_two(dir2, dir1);
|
|
if(cmp != 0)
|
|
return cmp;
|
|
|
|
Path p1, p2;
|
|
strcpy(p1, *str1); if(dir1) { p1[strlen(p1)-1] = NUL; }
|
|
strcpy(p2, *str2); if(dir2) { p2[strlen(p2)-1] = NUL; }
|
|
|
|
if(case_sensitive)
|
|
return strcmp(p1, p2);
|
|
else {
|
|
cmp = stricmp(p1, p2);
|
|
if(cmp == 0)
|
|
cmp = strcmp(p1, p2);
|
|
}
|
|
|
|
return cmp;
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
// this function displays the title on the pick window border
|
|
|
|
static void disp_title() {
|
|
|
|
if(path_in_title) {
|
|
char buf[sizeof(Path)+2];
|
|
strcpy(buf, " ");
|
|
PathCopy(buf+1, cwdp);
|
|
strcat(buf, namextp);
|
|
strcat(buf, " ");
|
|
|
|
wtitle(buf, TCENTER, gwin.active->battr);
|
|
}
|
|
|
|
if(open_function)
|
|
(*open_function)();
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
// this function frees all allocated strings in the array of pointers
|
|
|
|
static void free_strings(char** p, int numelems) {
|
|
|
|
for(int i=0;i<numelems;i++)
|
|
throw_xfree(p[i]);
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
static void pre_exit(char** p, int numelems) {
|
|
|
|
free_strings(p,numelems);
|
|
throw_xfree(p);
|
|
gchdir(tcwdp);
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
char* wpickfile(int srow, int scol, int erow, int ecol, int btype, int bordattr, int winattr, int barattr, bool title, const char* filespec, char* selectedfile, VfvCP open, bool casesens) {
|
|
|
|
Path cwd, dir, namext, tcwd, path, spec;
|
|
|
|
cwdp = cwd;
|
|
tcwdp = tcwd;
|
|
namextp = namext;
|
|
|
|
// allocate space to hold array of char pointers
|
|
int allocated = 100;
|
|
char** p = (char**)throw_xmalloc(allocated*sizeof(char*));
|
|
|
|
// set static variables
|
|
open_function = open;
|
|
path_in_title = title;
|
|
case_sensitive = casesens;
|
|
|
|
// save current working directory
|
|
getcwd(tcwd, GMAXPATH);
|
|
|
|
// if drive was specified, change to it
|
|
char* q = strcpy(spec, filespec);
|
|
|
|
// split up input filespec into its current
|
|
// working directory and filename/extension
|
|
char* r = strrchr(q, GOLD_SLASH_CHR);
|
|
#if defined(__HAVE_DRIVES__)
|
|
if(r == NULL)
|
|
if(q[1] == ':')
|
|
r = q + 1;
|
|
#endif
|
|
if(r == NULL) {
|
|
*dir = NUL;
|
|
strcpy(namext, q);
|
|
}
|
|
else {
|
|
strins(" ", ++r, 0);
|
|
*r++ = NUL;
|
|
strcpy(dir, q);
|
|
strcpy(namext, r);
|
|
}
|
|
|
|
bool finished;
|
|
int picked, files;
|
|
|
|
do {
|
|
|
|
// if directory was specified, change to it
|
|
if(*dir) {
|
|
if(gchdir(dir)) {
|
|
pre_exit(p, 0);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
// get current working directory
|
|
getcwd(cwd, GMAXPATH);
|
|
strcpy(dir, cwd);
|
|
|
|
// find all directories plus all files matching input filespec in
|
|
// current directory, allocating an array element for each
|
|
files = 0;
|
|
picked = -1;
|
|
gposixdir d(dir);
|
|
const gdirentry *de;
|
|
if(d.ok) {
|
|
while((de = d.nextentry()) != NULL) {
|
|
const char* name = NULL;
|
|
if(de->is_directory()) {
|
|
if(de->name != ".") {
|
|
strcpy(stpcpy(path, de->name.c_str()), GOLD_SLASH_STR);
|
|
name = path;
|
|
}
|
|
}
|
|
else if(de->is_file()) {
|
|
if(case_sensitive ? gwildmat(de->name.c_str(), namext) : gwildmati(de->name.c_str(), namext))
|
|
name = de->name.c_str();
|
|
}
|
|
if(name) {
|
|
p[files] = throw_xstrdup(name);
|
|
files++;
|
|
if(files == allocated-1) {
|
|
allocated *= 2;
|
|
p = (char**)throw_xrealloc(p, allocated*sizeof(char*));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
p[files] = NULL;
|
|
|
|
// sort files in array by swapping their pointers
|
|
qsort(p, files, sizeof(char*), (StdCmpCP)compare);
|
|
|
|
// let user pick file
|
|
if(files)
|
|
picked = wpickstr(srow, scol, erow, ecol, btype, bordattr, winattr, barattr, p, 0, disp_title);
|
|
if(picked == -1 or files == 0) {
|
|
pre_exit(p, files);
|
|
return NULL;
|
|
}
|
|
|
|
// see if a directory was selected. if so save
|
|
// directory name, otherwise build whole path name
|
|
q = strchr(p[picked], GOLD_SLASH_CHR);
|
|
if(q) {
|
|
finished = false;
|
|
strcpy(dir, p[picked]);
|
|
r = strrchr(dir, GOLD_SLASH_CHR);
|
|
if(r)
|
|
*r = NUL;
|
|
*q = NUL;
|
|
}
|
|
else {
|
|
finished = true;
|
|
PathCopy(path, cwd);
|
|
strcat(path, p[picked]);
|
|
}
|
|
|
|
// free allocated strings
|
|
free_strings(p, files);
|
|
|
|
// if a directory was selected, go back and do again
|
|
} while(not finished);
|
|
|
|
// change back to current drive and directory
|
|
gchdir(tcwd);
|
|
|
|
// free allocated char pointers
|
|
throw_xfree(p);
|
|
|
|
// return normally
|
|
strcpy(selectedfile, path);
|
|
return selectedfile;
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|