home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C!T ROM 2
/
ctrom_ii_b.zip
/
ctrom_ii_b
/
PROGRAM
/
C
/
FS191
/
FS2.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-02-24
|
24KB
|
854 lines
/* FS2.C
* whereis functions, remove dir functions
* MSC6
* FS 1.9.1
* 240293
* Copyright (C) M. van Breemen, 1993, All rights reserved.
*/
#include "FS.H"
/* Prototypes */
int whereis(char *searchstring, int *current_page, int *filenumber );
void outtextm( char *string );
void alert( void );
void show_error( char *message );
void wait_sec( int milliseconds );
void clear_left_button_queue( void );
void clear_right_button_queue( void );
int read_left_button_queue( int *row, int *col );
int read_right_button_queue( int *row, int *col );
void init_mouse( void );
void hide_mouse( void );
void show_mouse( void );
int mouse_button_pressed( void );
unsigned int n_kbhit( void );
void movmem(void *src, void *dest, unsigned length);
int getkey(void);
void changecursor(int insmode);
void setcursor(unsigned int shape);
int editstring(int row, int col, char *s, char *illegal, int maxlength);
char *saveScrn(void);
char *restScrn(char *saveArea);
int valid_filename( char *newname);
void shadebox( short r1, short c1, short r2, short c2 );
void shadechar( int row, int col );
int find_in_file( char *filename , char *string, int ignore_case);
int extract_directory( char *searchstring );
char *set_working_drive_and_dir( char *full_filename );
int find_name(char *fname, int *current_page, int *filenumber);
extern short int screen_bg_color;
extern short int file_color;
extern short int directory_color;
extern short int cursor_bg_color;
extern short int cursor_file_color; /* 10 bytes color info */
extern short int cursor_directory_color;
extern short int info_bg_color;
extern short int info_text_color;
extern short int error_text_color;
extern short int prompt_text_color;
extern short int hidden_file_color;
extern short int volume_label_color;
extern short int cursor_hidden_file_color;
extern short int cursor_volume_label_color;
/* global variables */
extern int number_of_files; /* number of files found */
typedef struct find_t_small {
char name [13];
char attrib;
} FIND_T_SMALL;
extern FIND_T_SMALL *find; /* pointer to the file info structures */
extern int mouse_present; /* boolean is there a mouse ? */
extern int mouse_row; /* mouse position, NOT screen rows and columns */
extern int mouse_col;
extern int max_files; /* maximal number of accessible files per directory or root, defaults to 456 */
extern int dos_error; /* set by error handler */
/*---------------------------------------------------------------------------*/
/* FF Routines taken from FFF 3.4.5, a public domain program to search files
* Author: Don A. Williams *
* CompuServ - *
* Genie - DON-WILL *
*/
#define U_ESC 1
#define U_SELECT 2
#define U_GOTO 3
#define FIND_FIRST(Name,Block,Attrib) _dos_findfirst(Name, Attrib, Block);
#define FIND_NEXT(Block) _dos_findnext(Block);
#define DIR_ENTRY find_t /* Name of the directory entry structure */
#define D_ATTRIB attrib /* Attribute field in directory entry */
#define D_NAME name /* File name field in directory entry */
typedef struct QueEntry {
struct QueEntry *Next;
char *Body;
} QUE_ENTRY;
typedef struct QueDef {
QUE_ENTRY *Head, *Current;
int Count;
} QUE_DEF;
/* Function prototypes */
int fff( char *fpattern, char *sstring, int ignore_case);
void InitQueue (QUE_DEF *Q);
QUE_ENTRY *Enque (QUE_DEF *Q, void *Body);
int WalkTree (QUE_DEF * Q, char *sstring , int ignore_case);
int SearchQ (char *Str);
int Match (char *Str, char *Pat);
static int I_Match (char *Str, char *Pat);
static int S_Match (char *S, char *P, int Anchor);
void DeleteQueue( QUE_DEF PatQue );
void clean_dir(char *path);
void do_dir(char *path);
/*----------------------------------------------------------------------*/
extern QUE_DEF PatQue;
extern char T_Path[_MAX_PATH]; /* Temporary directory path to search */
extern char V_Path[_MAX_PATH]; /* Selected file */
void DeleteQueue( QUE_DEF PatQue )
{
QUE_ENTRY *t, *u;
for (t = PatQue.Head; t != NULL;)
{
u = t->Next;
free(t->Body);
free(t);
t = u;
}
}
int fff(char *fpattern, char *sstring, int ignore_case)
{
char *p, *p2;
char scratchfpattern[_MAX_PATH];
char CurDir[_MAX_PATH]; /* Full path of the current directory */
char Path[_MAX_PATH]; /* Current directory path to search */
char Devices[16] = "";
int Result;
int i;
strcpy (scratchfpattern,fpattern);
InitQueue(&PatQue);
_getdcwd( _getdrive(), CurDir, _MAX_PATH );
strupr(CurDir);
strcpy(Path, "C:\\");
Devices[0] = (char) (_getdrive() - 1 + 'A');
Devices[1] = '\0';
/* Interpret fpattern tokens */
p = strtok( scratchfpattern, " " ); /* Find first token */
while( p != NULL )
{
if ((p2 = strchr(p, ':')) != NULL) /* process devices */
{
*p2 = '\0';
strcpy(Devices, p);
p2++; /* skip NULL */
p = p2; /* remove device */
}
if ((p2 = strrchr(p, '\\')) != NULL) /* process path */
{
*p2 = '\0';
if (p[0]=='\\') strcpy(Path,"C:");
else strcpy(Path,"C:\\");
strcat(Path, p);
if (Path[strlen(Path)-1]!='\\') strcat(Path,"\\");
p2++; /* skip backslash */
p = p2; /* remove path */
}
if (strlen(p))
{
if (strlen(p)>12)
{
DeleteQueue( PatQue );
return FAILURE; /* illegal filename length, abort */
}
if (!Enque(&PatQue, strupr(p)))
{
DeleteQueue( PatQue );
_settextposition( 8, 3 );
outtextm( "Memory exhausted, search aborted");
alert();
wait_sec(1000);
return FAILURE;
}
}
p = strtok( NULL, " " ); /* Find next token */
}
/* This does the work by walking the directory structure for each specified */
/* disk */
p = Devices;
while (*p != '\0') {
strcpy(T_Path, Path);
T_Path[0] = *p++; /* set drive */
if (Result=WalkTree(&PatQue,sstring,ignore_case)) break;
}
if (!Result)
{
_settextposition( 6, 3 );
outtextm("No more matches");
hide_mouse();
for (i=15;i<=63;i++) _outtext(" ");
show_mouse();
}
DeleteQueue( PatQue );
return (Result);
}
/*----------------------------------------------------------------------*/
/* WalkTree is a recursive routine that walks the directory structure */
/* specifed by the external T_Path. It bypasses Volume IDs and builds */
/* a linked list queue of directories that is processed after all of */
/* the file entries have been processed. */
int WalkTree (QUE_DEF *Q, char *sstring, int ignore_case)
{
int Status;
char Reply;
QUE_DEF Direc;
QUE_ENTRY *t, *u;
char *p;
struct DIR_ENTRY DirBlk; /* Directory Entry structure */
int TotalFiles = 0; /* Total files processed */
int TotalMatch = 0; /* Count of all files matched */
int operator_intervention=FALSE;
register int i;
int mouse_row, mouse_col;
int ulc_row, ulc_col, dummy; /* upper left corner row and column of window */
_gettextwindow(&ulc_row,&ulc_col,&dummy,&dummy); /* mouse coordinates are absolute! */
InitQueue(&Direc);
strcat(T_Path, "*.*");
Status = FIND_FIRST(T_Path, &DirBlk, 0xFF);
*(strrchr(T_Path, '\\') + 1) = '\0';
_settextposition( 6, 3 );
outtextm(T_Path); /* show progress */
hide_mouse();
for (i=strlen(T_Path);i<=63;i++) _outtext(" ");
show_mouse();
while (!Status && !operator_intervention)
{ /*1*/
if (n_kbhit() || mouse_button_pressed()) /* operator ESCapes */
{ /*2*/
if (n_kbhit()) Reply = (char) getkey();
else
{
if (mouse_present)
if (read_left_button_queue(&mouse_row,&mouse_col) && ((mouse_row-ulc_row+1)==8))
{
if ((mouse_col-ulc_col+1)>=54 && (mouse_col-ulc_col+1)<=66) Reply=0x1B;
else Reply='\0';
}
}
if (Reply == 0x1B) /* confirm */
{
_settextposition( 8, 3 );
outtextm("Type Y to stop searching completely");
_settextposition( 1, 1 );
Reply = (char) getkey();
_settextposition( 8, 3 );
outtextm(" ");
if (Reply=='y' || Reply=='Y') operator_intervention=U_ESC;
}
} /*2*/
if (!operator_intervention)
{
if ((DirBlk.D_ATTRIB & _A_VOLID) != 0) /* Bypass Volume Label */
{
Status = FIND_NEXT(&DirBlk);
continue;
}
}
if (!operator_intervention)
{ /*3*/
if ((DirBlk.D_ATTRIB & _A_SUBDIR) != 0) /* Process subdirectory */
{
if (DirBlk.D_NAME[0] != '.')
{
if (!Enque(&Direc, DirBlk.D_NAME))
{
_settextposition( 8, 3 );
outtextm( "Memory exhausted, search aborted");
alert();
wait_sec(1000);
operator_intervention=FAILURE;
}
}
}
else
{ /*C*/ /* Process file entry */
++TotalFiles;
if ( SearchQ(DirBlk.D_NAME) )
{ /*B*/
strcpy(V_Path, T_Path);
strcat(V_Path, DirBlk.D_NAME);
_settextposition( 6, 3 );
outtextm(V_Path); /* show filename match */
hide_mouse();
for (i=strlen(V_Path);i<=63;i++) _outtext(" ");
show_mouse();
if (strlen(sstring) ? find_in_file(V_Path,sstring, ignore_case) : TRUE)
{ /*A*/
++TotalMatch;
_settextposition( 8, 3);
outtextm("Next, Select, Goto ");
do
{
while (!n_kbhit() && !mouse_button_pressed()) /* wait */ ;
if (n_kbhit()) Reply = (char) getkey();
else
{
Reply='\0';
if (mouse_present)
if (read_left_button_queue(&mouse_row,&mouse_col) && ((mouse_row-ulc_row+1)==8))
{
if ((mouse_col-ulc_col+1)>=3 && (mouse_col-ulc_col+1)<=6)
Reply='N';
if ((mouse_col-ulc_col+1)>=9 && (mouse_col-ulc_col+1)<=14)
Reply='S';
if ((mouse_col-ulc_col+1)>=17 && (mouse_col-ulc_col+1)<=20)
Reply='G';
if ((mouse_col-ulc_col+1)>=54 && (mouse_col-ulc_col+1)<=66)
Reply=0x1B;
}
}
switch (Reply)
{
case 0x1B: _settextposition( 8, 3);
outtextm(" ");
operator_intervention=U_ESC;
break;
case 'S':
case 's': operator_intervention=U_SELECT;
break;
case 'G':
case 'g': operator_intervention=U_GOTO;
break;
default: break;
}
} while (Reply!='N' && Reply !='n' && !operator_intervention);
_settextposition( 8, 3);
outtextm(" ");
} /*A*/
} /*B*/
} /*C*/
} /*3*/
Status = FIND_NEXT(&DirBlk);
} /*1*/
/* Process any entries in the linked list of subdirectories */
if (TRUE) /* was !operator_intervention */
{
p = strrchr(T_Path, '\\') + 1; /* remove last filename */
for (t = Direc.Head; t != NULL;) /* was && !operator_intervention;) */
{
*p = '\0';
strcat(T_Path, t->Body);
strcat(T_Path, "\\");
if (!operator_intervention) /* do not expand */
operator_intervention=WalkTree(Q,sstring,ignore_case);
u = t->Next;
free(t->Body);
free(t);
t = u;
}
}
return (operator_intervention);
}
/*----------------------------------------------------------------------*/
/* SearchQ takes a file name as input and matches it against all of the */
/* patterns in the linked list of patterns built from command line */
/* arguments. The pattern list is an external. */
int SearchQ (char *Str)
{
extern QUE_DEF PatQue;
QUE_ENTRY *t;
int Result;
for (t = PatQue.Head; t != NULL; t = t->Next) {
Result = Match(Str, t->Body);
if (Result != 0) return(Result);
}
return (0);
}
/****************************************************************************
* InitQueue initializes a queue for use by the other queue functions.
***************************************************************************/
void InitQueue (QUE_DEF *Q)
{
Q->Head = Q->Current = NULL;
Q->Count = 0;
}
/****************************************************************************
* Enque creates a queue entry linked to the other entries in FIFO order
* and puts the string passed into the queue entry. It returns a pointer
* to the entry created [NULL if there is not enough memory for the entry.
***************************************************************************/
QUE_ENTRY *Enque (QUE_DEF *Q, void *Body)
{
QUE_ENTRY *p;
if ((p = malloc(sizeof(QUE_ENTRY))) == NULL ) return(NULL);
p->Next = NULL;
if ((p->Body = malloc(strlen(Body) + 1)) == NULL) return(NULL);
strcpy(p->Body, Body);
if (Q->Head == NULL) Q->Head = p;
else Q->Current->Next = p;
Q->Current = p;
++Q->Count;
return(p);
}
int Match (char *Str, char *Pat)
{
char S_Name[_MAX_PATH], S_Ext[4];
char P_Name[_MAX_PATH], P_Ext[4];
char *p1;
strupr(Pat);
if ( (p1 = strrchr(Str, '.')) != NULL ) {
*p1 = '\0';
strcpy(S_Name, Str);
strcpy(S_Ext, p1+1);
*p1 = '.';
}
else {
strcpy(S_Name, Str);
S_Ext[0] = '\0';
}
if ( (p1 = strchr(Pat, '.')) != NULL ) {
*p1 = '\0';
strcpy(P_Name, Pat);
strcpy(P_Ext, p1+1);
*p1 = '.';
}
else {
strcpy(P_Name, Pat);
strcpy(P_Ext, "*");
}
if ( !I_Match(S_Name, P_Name) ) return(0);
if ( (P_Ext[0] == '\0') && (S_Ext[0] != '\0') ) return(0);
if ( !I_Match(S_Ext, P_Ext) ) return(0);
return(1);
}
static int I_Match (char *Str, char *Pat)
{
char *p, *p1, *p2, Hold;
int t;
if ( (p1 = strchr(Pat, '*')) == NULL)
return( S_Match(Str, Pat, 1) );
if (Pat[0] != '*') {
*p1 = '\0';
t = S_Match(Str, Pat, 0);
*p1 = '*';
if (!t) return(0);
}
if (Pat[strlen(Pat)-1] != '*') {
p2 = strrchr(Pat, '*') + 1;
if (strlen(Str) < strlen(p2)) return(0);
if ( !S_Match(&Str[strlen(Str) - strlen(p2)], p2, 1) )
return(0);
}
p = Str;
while ( (p2 = strchr(++p1, '*')) != NULL ) {
*p2 = '\0';
Hold = p1[0];
while ( (p = strchr(p, Hold)) != NULL ) {
if ( S_Match(p, p1, 0) ) break;
++p;
}
if (p == NULL) return(0);
p += strlen(p1);
*p2 = '*';
p1 = p2;
}
return(1);
}
static int S_Match (char *S, char *P, int Anchor)
{
while ( (*P != '\0') && (*S != '\0') ) {
if ( (*S == *P) || (*P == '?') ) {
S++;
P++;
}
else return(0);
}
if (*P != '\0') return(0);
if ( Anchor && (*S != '\0') ) return(0);
return(1);
}
/***************************************************************************
Handles 'where is' screen
*/
int whereis(char *searchstring, int *current_page, int *filenumber)
{
static char fpattern[_MAX_PATH]={'\0'};
static char org_sstring[50]={'\0'};
char sstring[50]={'\0'};
short x,y;
char b[(9*69)+10]={ /* Buffer for string */
"╔══════════════════════════════════════════════════════════════════╗\n"
"║ WHERE IS FILE CONTAINING WHAT ║\n"
"╟──────────────────────────────────────────────────────────────────╢\n"
"║ Filename pattern: ║\n"
"║ Search string: ║\n"
"║ ║\n"
"╟──────────────────────────────────────────────────────────────────╢\n"
"║ ESC to cancel ║\n"
"╚══════════════════════════════════════════════════════════════════╝\n"
};
char *savedscreen;
int result,result2;
int i;
char *slash;
int ignore_case=FALSE;
if (!strlen(fpattern)) strcpy(fpattern,searchstring);
savedscreen=saveScrn();
y = ((25 - 9) / 2) + 1; /* 9 lines */
x = (80 - 68) / 2; /* 68 visible characters per line */
_settextcolor( (short) info_text_color );
_setbkcolor( (long) info_bg_color );
/* Use text window to place output in middle of screen. */
_settextwindow( y, x, y + 9, x + 68 );
shadebox( y, x, y + 9 - 1, x + 68 - 1 );
outtextm( b );
_settextposition( 4, 21 );
outtextm(fpattern);
_settextposition( 5, 21 );
outtextm(org_sstring);
do
{
_settextposition( 8, 3 );
outtextm("Enter a filename pattern, hit Return");
if (!(result=editstring(4, 21, fpattern, "+=[];|,<>/?\"", 46))) break;
_settextposition( 6, 3 );
outtextm("Append /I to the string to ignore case");
_settextposition( 8, 3 );
outtextm("Enter string, empty to skip IN search, hit Return");
if (!(result=editstring(5, 21, org_sstring, "", 46))) break;
_settextposition( 8, 3 );
for (i=3;i<=52;i++) _outtext(" ");
_settextposition( 6, 3 );
for (i=3;i<=52;i++) _outtext(" ");
/* default ignore_case = FALSE */
strcpy(sstring,org_sstring);
if (slash=strstr(sstring,"/I"))
{
if (slash[2]=='\0') /* sstring ENDS with /I option, otherwise part of sstring */
{
ignore_case=TRUE;
*slash='\0';
}
}
if (slash=strstr(sstring,"/i"))
{
if (slash[2]=='\0') /* sstring ENDS with /I option, otherwise part of sstring */
{
ignore_case=TRUE;
*slash='\0';
}
}
switch (result=fff(fpattern,sstring,ignore_case)) /* result in V_Path */
{
case U_ESC: _settextposition( 6, 3 );
outtextm("Last search canceled");
hide_mouse();
for (i=20;i<=63;i++) _outtext(" ");
show_mouse();
break;
case U_SELECT:
case U_GOTO: slash=set_working_drive_and_dir(V_Path); /* make drive & dir default */
/* and find filename */
if (!slash)
{
result=FAILURE;
break;
}
/* first try original searchstring */
if (!Match(slash,searchstring))
{
_settextposition( 8, 3 );
outtextm( "Mask changed to *.*" );
wait_sec(1000);
strcpy(searchstring,"*.*"); /* this should match */
extract_directory(searchstring);
result2=find_name(slash, current_page, filenumber);
} else
{
extract_directory(searchstring);
result2=find_name(slash, current_page, filenumber);
}
if (result2==FAILURE) /* find array might be full */
{
_settextcolor( (short) info_text_color );
_setbkcolor( (long) info_bg_color );
_settextposition( 8, 3 );
outtextm( "Mask changed to " );
outtextm( slash );
wait_sec(1000);
strcpy(searchstring,slash); /* this should work always */
extract_directory(searchstring);
result2=find_name(slash, current_page, filenumber);
}
if (result2==FAILURE) result=FAILURE;
break;
default: break;
}
} while (result!=U_SELECT && result!=U_GOTO && result!=FAILURE);
_settextwindow( 3, 1, 23, 80 );
_setbkcolor( (long) screen_bg_color );
savedscreen=restScrn(savedscreen);
return result;
}
/***************************************************************************
Find a string IN a file
*/
int find_in_file( char *filename , char *string, int ignore_case)
{
char *buff; /* Pointer to data buffer */
int fn; /* file handle */
long fl; /* file length */
unsigned int count=0x7fff; /* buffer size */
int found; /* True if string found */
long rsize; /* Amount of data read into buffer */
register long offset; /* Position where string code found */
char progress_char[]={ "/-\\|"};
static int progress_nr=0;
char progress_str[]={ "/\0" };
int Reply;
if (ignore_case) strupr(string);
if( (fn = open( filename, O_BINARY | O_RDONLY )) == - 1 )
{
show_error("Cannot open file ");
return FALSE;
}
/* Get size of file */
fl = filelength(fn);
if( fl < (long) count )
count = (unsigned int) fl;
/* Dynamically allocate a large file buffer. If there's not enough
* memory for it, find the largest amount available on the near heap
*/
if( (buff = (char *)malloc( (size_t)count )) == NULL )
{
count = _memmax();
if( (buff = (char *)malloc( (size_t)count )) == NULL )
{
show_error("Can't allocate memory for FIF");
close(fn);
return FALSE;
}
}
found = FALSE;
while ( !eof(fn) && !found)
{
if( (rsize = (long) read( fn, buff, count )) == FAILURE )
{
show_error("Read error ");
close(fn);
free(buff);
return FALSE;
}
if (ignore_case)
{
for (offset=0L; offset < rsize; offset++)
if (isalpha((int) buff[offset]))
buff[offset]=(char) toupper((int) buff[offset]);
}
for (offset=0L; offset <= rsize-strlen(string); offset++)
{
if (!(offset%5120L)) /* do checks after 5kb */
{ /*B*/
if (fl > 5120L) /* wheel */
{
if (progress_nr==3) progress_nr=0;
else progress_nr++;
progress_str[0]=progress_char[progress_nr];
_settextposition( 8, 3);
outtextm( progress_str );
}
if (n_kbhit())
{ /*A*/
Reply=getkey();
if (Reply==0x1B)
{
_settextposition( 8, 3);
outtextm("Canceled, skipping this file");
wait_sec(500);
_settextposition( 8, 3);
outtextm(" ");
close(fn);
free(buff);
return FALSE;
}
} /*A*/
} /*B*/
if (!strncmp(&buff[offset], string, strlen(string) ))
{
found = TRUE;
break; /* escape from FOR loop */
}
}
if (!found && !eof(fn)) /* reposition back strlen(string)-1 to recover from split search string */
{
if (lseek (fn, 1L - ((long) (strlen(string))), SEEK_CUR)==FAILURE)
{
show_error("Seek error ");
close(fn);
free(buff);
return FALSE;
}
}
}
if (fl > 2048L) /* erase wheel */
{
_settextposition( 8, 3);
outtextm( " " );
}
free(buff);
close(fn);
if (!found) return FALSE; /* String not found */
else return TRUE; /* String found */
}
/*
** Remove all files and subdirectories
** Slow but small code
** from a public domain demo by Bob Stout
*/
/*
** Clean all files from a directory
*/
void clean_dir(char *path)
{
char rmpath[_MAX_PATH], *rmfile;
char scratch[_MAX_PATH];
struct find_t fbuf;
strcpy(rmpath, path);
if ('\\' != (rmpath[strlen(rmpath) - 1]))
strcat(rmpath, "\\");
rmfile = &rmpath[strlen(rmpath)];
strcpy(rmfile, "*.*");
if (!_dos_findfirst(rmpath, _A_ARCH | _A_HIDDEN | _A_NORMAL | _A_RDONLY | _A_SYSTEM, &fbuf)) do
{
strcpy(rmfile, fbuf.name);
if (remove(rmpath))
{
strcpy(scratch,"Can't delete file ");
strcat(scratch,rmpath);
show_error(scratch);
}
} while (!_dos_findnext(&fbuf));
}
/*
** Process directories
* PLEASE PLEASE don't call with do_dir("..")
* it works fine (I know for sure): cleans up parent directory,
* which could be your complete harddisk
*/
void do_dir(char *path)
{
char search[_MAX_PATH], new[_MAX_PATH];
char scratch[_MAX_PATH];
struct find_t ff;
strcpy(search, path);
if ('\\' != (search[strlen(search) - 1]))
strcat(search, "\\");
strcat(search, "*.*");
if (!_dos_findfirst(search, 0xffff, &ff)) do
{
if (ff.attrib & _A_SUBDIR && '.' != *ff.name)
{
strcat(strcat(strcpy(new, path), "\\"), ff.name);
do_dir(new);
}
} while (!_dos_findnext(&ff));
clean_dir(path);
if (rmdir(path))
{
strcpy(scratch,"Can't delete directory ");
strcat(scratch,path);
show_error(scratch);
}
}