📄 wpick.c
字号:
/*
** CXL - Copyright (c) 1987-1990 by Mike Smedley - All Rights Reserved
**
** WPICK.C - allows user to select a file name
**
** This is a variation of the standard CXL wpickfil() function
*/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include "cxldef.h"
#include "cxlstr.h"
#include "cxlwin.h"
#include <direct.h>
#define findfirst(a,b,c) _dos_findfirst(a,c,b)
#define findnext(a) _dos_findnext(a)
#define ffblk _find_t
#define ff_name name
#define ff_attrib attrib
#define FA_DIREC _A_SUBDIR
static int tnumdrives;
static int compare(char **, char **);
static void disp_title(void);
static int find_first(char *, struct ffblk *, int);
static int find_next(struct ffblk *);
static void free_strings(char **, int);
static void pre_exit(char **, int);
static void reset_drive(void);
static char dspec[81];
static char fspec[81];
static char search_path[81];
static char save_path[69];
static char new_path[81];
static int save_drive;
static int gtitle;
static void (*gopen)(void);
int size;
char *
wpickfile_criteria(int srow, int scol, int erow, int ecol, int btype,
int bordattr, int winattr, int barattr, int title, char *filespec,
void (*open)(void), int (*pick_criteria)(char *))
{
static char fname[255];
int i, num_files, done, match, finished;
struct ffblk ffblk;
char **p, *q, *pfs;
match = FALSE;
/* allocate space to hold array of char pointers */
if ((p = malloc((_winfo.maxfiles + 1) * sizeof(char *))) == NULL) {
_winfo.errno = W_ALLOCERR;
return(NULL);
}
/* set static variables */
gtitle = title;
gopen = open;
/* find start of unqualified filespec */
if ((pfs = strrchr(filespec, '\\')) == NULL) {
pfs = filespec;
if (*(pfs + 1) == ':') {
pfs++;
pfs++;
}
} else
pfs++;
/* save current disk drive */
_dos_getdrive(&save_drive);
/* if drive was specified, change to it */
if (*(filespec + 1)==':')
_dos_setdrive(toupper(*filespec) - 'A' + 1, &i);
/* save current working directory */
getcwd(save_path, 68);
/* if a directory was specified, change to it */
if ((q = strrchr(strcpy(new_path, filespec), '\\')) != NULL) {
if (q == (new_path + 2))
*(q + 1) = 0;
else
*q = 0;
if (chdir(new_path)) {
reset_drive();
free(p);
_winfo.errno = W_INVPATH;
return(NULL);
}
}
/* create initial search path */
getcwd(search_path, 68);
if (*(search_path + strlen(search_path) - 1) != '\\')
strcat(search_path, "\\");
/* go back to original drive */
reset_drive();
/* go back to original path */
chdir(save_path);
do {
/* build file search filespec from search path */
strcpy(fspec, search_path);
strcat(fspec, pfs);
strupr(fspec);
/* build directory search filespec from search path */
strcpy(dspec, search_path);
strcat(dspec, "*.*");
/* find all directories in current directory, */
/* allocating an array element for each of them */
i = 0;
done = find_first(dspec, &ffblk, _A_SUBDIR);
while (!done) {
if (ffblk.ff_attrib & _A_SUBDIR) {
if (i == _winfo.maxfiles)
break;
match = TRUE;
if ((p[i] = malloc(14)) == NULL) {
pre_exit(p, i);
_winfo.errno = W_ALLOCERR;
return(NULL);
}
strncpy(p[i], ffblk.ff_name, 13);
strcat(p[i], "\\");
i++;
}
done = find_next(&ffblk);
}
/* find all files matching input filespec in current */
/* directory, allocating an array element for each */
done = find_first(fspec, &ffblk, _A_NORMAL);
if (done && !match) {
pre_exit(p, i);
_winfo.errno = W_NOMATCH;
return(NULL);
}
match = TRUE;
while (!done) {
if (i == _winfo.maxfiles)
break;
strcpy(fname, search_path);
strcat(fname, ffblk.ff_name);
{
char foo[128];
sprintf(foo, "pick_criteria = 0x%p", pick_criteria);
}
if (pick_criteria && (*pick_criteria)(fname)) {
if ((p[i] = malloc(14)) == NULL) {
pre_exit(p, i);
_winfo.errno = W_ALLOCERR;
return(NULL);
}
strncpy(p[i], ffblk.ff_name, 13);
i++;
}
done = find_next(&ffblk);
}
p[i] = NULL;
num_files=i;
/* sort files in array by swapping their pointers */
qsort(p, num_files, sizeof(char *),
(int (*)(const void *, const void *))compare);
/* let user pick a file or directory */
i = wpickstr(srow, scol, erow, ecol, btype, bordattr, winattr,
barattr, p, 0, disp_title);
/* check for error return from wpickstr() */
if (_winfo.errno) {
pre_exit(p, num_files);
return(NULL);
}
/* if a directory was selected, then modify search path. */
/* otherwise, create full pathname of selected file. */
if ((q = strrchr(p[i], '\\')) != NULL) {
finished = NO;
if (*(p[i] + 1) == '.') { /* previous directory */
*(strrchr(search_path, '\\')) = 0;
*(strrchr(search_path, '\\') + 1) = 0;
} else if (*p[i] != '.') /* subdirectory */
strcat(search_path, p[i]);
} else {
finished=YES;
strcat(search_path, p[i]);
}
/* free allocated strings */
free_strings(p, num_files);
} while (!finished);
/* free allocated char pointers */
free(p);
/* return normally */
_winfo.errno = W_NOERROR;
return(search_path);
}
/*---------------------------------------------------------------------------*/
/* this function is the compare function for qsort() */
static int
compare(char **str1, char **str2)
{
return(strcmp(*str1, *str2));
}
/*---------------------------------------------------------------------------*/
/* this function displays the title on the pick window border */
static void
disp_title(void)
{
if (gtitle)
wtitle(fspec, TCENTER, _winfo.active->battr);
if (gopen != NULL)
(*gopen)();
}
/*---------------------------------------------------------------------------*/
static long handle;
static int
find_first(char *filespec, struct ffblk *ffblk, int attrib)
{
ffblk->attrib = attrib;
return((handle = findfirst(filespec, ffblk, attrib)) == -1);
}
/*---------------------------------------------------------------------------*/
static int
find_next(struct ffblk *ffblk)
{
return(findnext(ffblk));
}
/*---------------------------------------------------------------------------*/
/* this function frees all allocated strings in the array of pointers */
static void
free_strings(char **p, int numelems)
{
int i;
for (i = 0; i < numelems; i++)
{
free(p[i]);
p[i] = NULL;
}
}
/*---------------------------------------------------------------------------*/
static void
pre_exit(char **p, int numelems)
{
free_strings(p, numelems);
free(p);
}
/*---------------------------------------------------------------------------*/
/* this function resets the current drive back to the original drive */
static void
reset_drive(void)
{
int num_drives;
_dos_setdrive(save_drive, &num_drives);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -