231 lines
6.0 KiB
C++
231 lines
6.0 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 <algorithm>
|
|
#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 IfcpCP open_function = NULL;
|
|
static char* cwdp;
|
|
static char* tcwdp;
|
|
static char* namextp;
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
// this function is the compare function for std::sort()
|
|
|
|
static bool compare(const std::string str1, const std::string str2)
|
|
{
|
|
// Sort with directories first
|
|
bool dir1 = !!strchr(str1.c_str(), GOLD_SLASH_CHR);
|
|
bool dir2 = !!strchr(str2.c_str(), GOLD_SLASH_CHR);
|
|
if (dir1 && !dir2) return true;
|
|
if (!dir1 && dir2) return false;
|
|
|
|
std::string s1 = dir1 ? str1.substr(0, str1.length()-1) : str1;
|
|
std::string s2 = dir2 ? str2.substr(0, str2.length()-1) : str2;
|
|
|
|
int cmp;
|
|
if (case_sensitive)
|
|
cmp = strcmp(s1.c_str(), s2.c_str());
|
|
else
|
|
{
|
|
cmp = stricmp(s1.c_str(), s2.c_str());
|
|
if (cmp == 0)
|
|
cmp = strcmp(s1.c_str(), s2.c_str());
|
|
}
|
|
|
|
return (cmp < 0);
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
// this function displays the title on the pick window border
|
|
|
|
static void disp_title() {
|
|
|
|
char buf[sizeof(Path)+2];
|
|
|
|
if(path_in_title or open_function) {
|
|
strcpy(buf, " ");
|
|
PathCopy(buf+1, cwdp);
|
|
strcat(buf, namextp);
|
|
strcat(buf, " ");
|
|
}
|
|
|
|
if(path_in_title) {
|
|
wtitle(buf, TCENTER, gwin.active->battr);
|
|
}
|
|
|
|
if(open_function) {
|
|
(*open_function)(buf);
|
|
}
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
bool wpickfile(int srow, int scol, int erow, int ecol, int btype, vattr bordattr, vattr winattr, vattr barattr, bool title, std::string &filespec, IfcpCP open, bool casesens)
|
|
{
|
|
Path cwd, dir, namext, tcwd, path, spec;
|
|
|
|
cwdp = cwd;
|
|
tcwdp = tcwd;
|
|
namextp = namext;
|
|
|
|
// 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 = strxcpy(spec, filespec.c_str(), sizeof(Path));
|
|
|
|
// 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;
|
|
|
|
do
|
|
{
|
|
// if directory was specified, change to it
|
|
if (*dir && gchdir(dir))
|
|
{
|
|
gchdir(tcwdp);
|
|
return false;
|
|
}
|
|
|
|
// 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
|
|
picked = -1;
|
|
gposixdir d(dir);
|
|
gstrarray strarr;
|
|
const gdirentry *de;
|
|
|
|
if (d.ok)
|
|
{
|
|
while((de = d.nextentry()) != NULL)
|
|
{
|
|
const char* name = NULL;
|
|
if (de->is_directory())
|
|
{
|
|
if(de->name != ".") {
|
|
strxmerge(path, sizeof(Path), de->name.c_str(), GOLD_SLASH_STR, NULL);
|
|
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) strarr.push_back(name);
|
|
}
|
|
}
|
|
|
|
// sort files in array by swapping their pointers
|
|
std::sort(strarr.begin(), strarr.end(), compare);
|
|
|
|
// let user pick file
|
|
if (strarr.size())
|
|
{
|
|
picked = wpickstr(srow, scol, erow, ecol, btype, bordattr, winattr, barattr, strarr, 0, disp_title);
|
|
}
|
|
|
|
if (picked == -1 or !strarr.size())
|
|
{
|
|
gchdir(tcwdp);
|
|
return false;
|
|
}
|
|
|
|
// see if a directory was selected. if so save
|
|
// directory name, otherwise build whole path name
|
|
const char *slash = strchr(strarr[picked].c_str(), GOLD_SLASH_CHR);
|
|
if (slash)
|
|
{
|
|
finished = false;
|
|
strcpy(dir, strarr[picked].c_str());
|
|
r = strrchr(dir, GOLD_SLASH_CHR);
|
|
if (r) *r = NUL;
|
|
}
|
|
else {
|
|
finished = true;
|
|
PathCopy(filespec, cwd);
|
|
filespec += strarr[picked].c_str();
|
|
}
|
|
|
|
strarr.clear();
|
|
}
|
|
while(not finished); // if a directory was selected, go back and do again
|
|
|
|
gchdir(tcwd); // change back to current drive and directory
|
|
return true; // return normally
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|