📄 dirlist.c
字号:
/*
* I wrote this function because I'm so stupid, I constantly forget
* file names and directory stuff. The main function prompts for a
* subdirectory name or a search path. The default search path is the
* cwd (current working directory). In addition to being stupid, I'm also
* lazy. If the user types a subdirectory name, I think we can assume he
* wants to list all files w/o having to type *.* Let's save the cwd on
* whatever drive the user wishes to search, so we can restore it we get
* thru dir'ing. Use the standard DOS functions to get and set directories.
*
* The search pattern can contain wild card chars, valid file names, or a
* valid subdirectory name.
*
* Being that TDE 2.2 now handles binary files, lets make .EXE and .COM files
* autoload in binary mode.
*
* Before matching files are displayed on the screen, file names are sorted
* using the easy-to-implement and fairly fast Shellsort algorithm.
*
* See:
*
* Donald Lewis Shell, _Communications of the ACM_ 2 (No. 2): 30-32, 1959.
*
* See also:
*
* Donald Ervin Knuth, _The Art of Computer Programming; Volume 3: Sorting
* and Searching_, Addison-Wesley, Reading, Mass., 1973, Chapter 5,
* "Sorting", pp 84-95. ISBN 0-201-03803-X.
*
* Robert Sedgewick, _Algorithms in C_, Addison-Wesley, Reading, Mass.,
* 1990, Chapter 8, "Elementary Sorting Methods", pp 107-111.
* ISBN 0-201-51425-7.
*
*
* New editor name: TDE, the Thomson-Davis Editor.
* Author: Frank Davis
* Date: June 5, 1991, version 1.0
* Date: July 29, 1991, version 1.1
* Date: October 5, 1991, version 1.2
* Date: January 20, 1992, version 1.3
* Date: February 17, 1992, version 1.4
* Date: April 1, 1992, version 1.5
* Date: June 5, 1992, version 2.0
* Date: October 31, 1992, version 2.1
* Date: April 1, 1993, version 2.2
* Date: June 5, 1993, version 3.0
*
* This code is released into the public domain, Frank Davis.
* You may distribute it freely.
*/
#include "tdestr.h"
#include "common.h"
#include "define.h"
#include "tdefunc.h"
/*
* Name: dir_help
* Purpose: To prompt the user and list the directory contents
* Date: February 13, 1992
* Passed: window: pointer to current window
*/
int dir_help( WINDOW *window )
{
char dname[MAX_COLS+2]; /* directory search pattern */
char stem[MAX_COLS+2]; /* directory stem */
char drive[_MAX_DRIVE]; /* splitpath drive buff */
char dir[_MAX_DIR]; /* splitpath dir buff */
char fname[_MAX_FNAME]; /* splitpath fname buff */
char ext[_MAX_EXT]; /* splitpath ext buff */
int rc;
int file_mode;
int bin_length;
int prompt_line;
if (window != NULL) {
entab_linebuff( );
if (un_copy_line( window->ll, window, TRUE ) == ERROR)
return( ERROR );
prompt_line = window->bottom_line;
} else
prompt_line = g_display.nlines;
/*
* search path or pattern
*/
dname[0] = '\0';
rc = get_name( dir1, prompt_line, dname, g_display.message_color );
if (rc == OK) {
if (validate_path( dname, stem ) == OK) {
rc = list_and_pick( dname, stem, window );
/*
* if everything is everything, load in the file selected by user.
*/
if (rc == OK) {
file_mode = TEXT;
bin_length = 0;
_splitpath( dname, drive, dir, fname, ext );
if (stricmp( ext, ".exe" ) == 0 || stricmp( ext, ".com" ) == 0) {
file_mode = BINARY;
bin_length = g_status.file_chunk;
}
if (window != NULL)
attempt_edit_display( dname, LOCAL, file_mode, bin_length );
else
attempt_edit_display( dname, GLOBAL, file_mode, bin_length );
}
} else
/*
* invalid path or file name
*/
error( WARNING,
window != NULL ? window->bottom_line : g_display.nlines, dir2 );
}
return( rc );
}
/*
* Name: validate_path
* Purpose: make sure we got a valid search pattern or subdirectory
* Date: February 13, 1992
* Passed: dname: search path entered by user
* stem: directory stem is returned
* Returns: successful or not
* Notes: we need to validate the search path or pattern. if the search
* pattern is valid, then we need to get the search stem.
* the user may enter a subdirectory or some kind of search pattern.
* if the user enters a subdirectory, then there are a few things
* we need to take care of 1) find out if the subdirectory is
* the root, 2) append a '\' to the subdirectory so we can create
* a search pattern for the subdirectory, 3) don't append '\' to
* the root, it already has a '\'.
* if the user enters a search pattern, then we need to dissect the
* search path. we must create a stem from the search pattern.
*/
int validate_path( char *dname, char *stem )
{
int rc;
DTA dta; /* temp disk transfer struct for findfirst, etc. */
int fattr;
int i;
int len;
char *p;
char temp[MAX_COLS+2]; /* directory stem */
/*
* if path name is void then the current working directory is implied.
*/
if (dname[0] == '\0') {
assert( strlen( stardotstar ) < MAX_COLS );
strcpy( dname, stardotstar );
stem[0] = '\0';
rc = OK;
} else {
/*
* get the attributes of the search pattern, so we can determine if
* this is a pattern or subdirectory.
*/
rc = get_fattr( dname, &fattr );
if (rc == OK && (fattr & SUBDIRECTORY)) {
assert( strlen( dname ) < MAX_COLS );
strcpy( stem, dname );
/*
* if this is the root directory ( \ ), don't append '\' to it.
* user entered a subdirectory - append *.* to get contents of
* subdirectory.
*/
len = strlen( stem );
if (stem[len-1] != '\\') {
strcat( stem, "\\" );
strcat( dname, "\\" );
}
strcat( dname, stardotstar );
/*
* not a subdirectory. let's see if any files match the search
* pattern.
*/
} else if (rc != ERROR) {
if ((rc = my_findfirst( &dta, dname, NORMAL | READ_ONLY | HIDDEN |
SYSTEM | SUBDIRECTORY | ARCHIVE )) == OK) {
/*
* copy dname to "temp" so we can use "temp" to find the stem.
* we need to search the pattern backwards to figure the stem.
*/
assert( strlen( dname ) < MAX_COLS );
strcpy( temp, dname );
len = strlen( dname );
for (i=len,p=temp+len; i>=0; i--) {
/*
* if we run into the '\' or the ':', then we got a stem.
*/
if (*p == '\\' || *p == ':') {
p = temp + i;
*(p+1) = '\0';
break;
/*
* if we're at the beginning of the string, stem == '\0'
*/
} else if (i == 0) {
*p = '\0';
break;
}
--p;
}
assert( strlen( temp ) < MAX_COLS );
strcpy( stem, temp );
} else
rc = ERROR;
/*
* user did not enter a valid subdirectory name or search pattern.
*/
} else
rc = ERROR;
}
return( rc );
}
/*
* Name: list_and_pick
* Purpose: To show matching file names and let user pick a file
* Date: February 13, 1992
* Passed: dname: directory search pattern
* stem: stem of directory search pattern
* window: pointer to current window
* Returns: return code from pick. rc = OK, then edit a new file.
* Notes: real work routine of this function. save the cwd and let the
* user search upwards or downwards thru the directory structure.
* since we are doing DOS directory functions, we need to check the
* return code after each DOS call for critical errors.
*/
int list_and_pick( char *dname, char *stem, WINDOW *window )
{
int rc;
DTA dta; /* disk transfer address for findfirst */
DIRECTORY dir; /* contains all info for dir display */
unsigned int cnt; /* number of matching files */
FTYPE *flist, *p; /* pointer to list of matching files */
char cwd[MAX_COLS]; /* save the current working directory in this buff */
char dbuff[MAX_COLS]; /* temporary directory buff */
char prefix[MAX_COLS]; /* directory prefix */
int change_directory = FALSE;
int stop;
int len;
int drive;
/*
* Some algorithms alloc the maximum possible number of files in
* a directory, eg. 256 or 512. Let's count the number of matching
* files so we know egxactly how much memory to request from calloc.
* Depending on the op system, disk media, disk format, or version of DOS,
* the max number of files may vary, anyway, also, additionally.
*/
rc = my_findfirst( &dta, dname, NORMAL | READ_ONLY | HIDDEN | SYSTEM |
SUBDIRECTORY | ARCHIVE );
if (rc != ERROR) {
for (cnt=1; (rc = my_findnext( &dta )) == OK;)
++cnt;
flist = (FTYPE *)calloc( cnt, sizeof(FTYPE) );
} else
flist = NULL;
if (rc != ERROR && flist != NULL) {
stop = FALSE;
/*
* If user entered drive name in search pattern, find out the drive and
* directory stem.
*/
if (stem[1] == ':') {
/*
* If the second character of the search pattern is a ':', the
* the first character of the pattern should be the drive.
* Convert drive to lower case and get a numerical representation.
* CAVEAT: In DOS v 2.x, there may be up to 63 logical drives.
* my algorithm may blow up if the number of logical drives
* is greater than 'Z'.
* For DOS >= 3, the number of drives is limited to 26, I think.
*/
drive = stem[0];
if (drive < 'a')
drive += 32;
drive = drive - 'a' + 1;
rc = get_current_directory( dbuff, drive );
if (rc == ERROR)
stop = TRUE;
else {
/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -