home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C!T ROM 2
/
ctrom_ii_b.zip
/
ctrom_ii_b
/
PROGRAM
/
C
/
FS191
/
FS1.C
< prev
next >
Wrap
Text File
|
1993-02-24
|
83KB
|
2,670 lines
/* FS1.C
* handle_dir functions
* MSC6
* FS 1.9.1
* 240293
* Copyright (C) M. van Breemen, 1993, All rights reserved.
*/
#include "FS.H"
#include "XSPAWN.H"
/* Prototypes */
int whereis(char *searchstring, int *current_page, int *filenumber );
int find_name(char *fname, int *current_page, int *filenumber);
void outtextm( char *string );
int handle_dir( char *searchstring, char *selected , int safe_mode);
char filename( int filenumber, int mode );
void fileinfo( int filenumber );
char *timestr( unsigned d, char *buf );
char *datestr( unsigned d, char *buf );
void set_cursor( int filenumber );
void clear_remaining( int filenumber );
int extract_directory( char *searchstring );
void show_dir_page( int page );
void kader( void );
void alert( void );
void helpscreen( void );
void aboutscreen( void );
void show_error( char *message );
void wait_sec( int milliseconds );
int rename_file( int filenumber);
int rename_volume_label( int filenumber);
void _far hhandler( unsigned deverr, unsigned doserr, unsigned _far *hdr );
int _bios_str( char *p );
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 );
void perform_repaint(int current_page, int filenumber);
void c_pgup( int *current_page, int *filenumber);
void c_pgdn( int *current_page, int *filenumber);
void find_first(char chr, int *currentpage, int *filenumber);
void c_home( int *current_page, int *filenumber);
void c_end( int *current_page, int *filenumber);
void c_cup( int *current_page, int *filenumber);
void c_cdn( int *current_page, int *filenumber);
void c_cri( int *current_page, int *filenumber);
void c_cle( int *current_page, int *filenumber);
int _cdecl cmpgle( const void *elem1, const void *elem2 );
unsigned int n_kbhit( void );
int show_file(char *filename);
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);
int edit(char *title, char *string, int length , char *illegal);
int copy_file( int filenumber);
int make_directory( void );
int ed_attributes( int filenumber);
int copy( char *oldname, char *newname );
char *saveScrn(void);
char *restScrn(char *saveArea);
void show_path( void );
int valid_filename( char *newname);
int freespace( char *linebuf );
void working( int mode );
void shadebox( short r1, short c1, short r2, short c2 );
void shadechar( int row, int col );
char *set_working_drive_and_dir( char *full_filename );
int find_in_file( char *filename , char *string, int ignore_case);
void do_dir(char *path);
void find_parent( int *current_page, int *filenumber, char *searchstring);
int getdrv(void);
int chdrv(int drive);
int drvalid(int drive);
char *FilGetVolid( unsigned char Drive );
int FilSetVolid( unsigned char Drive, char *Volid );
int FilDelVolid( unsigned char Drive );
void ScrPutS(char *String, unsigned char Attr,
unsigned char Row, unsigned char Col);
int ask_drive_number(char *message);
/* global variables */
unsigned short int checkpoint1[3]= { 0xFEFF, 0xFCFD, 0xFAFB }; /* Backword FFFEFDFCFBFA */
short int screen_bg_color = BLUE;
short int file_color = WHITE;
short int directory_color = YELLOW;
short int cursor_bg_color = RED;
short int cursor_file_color = WHITE; /* 14 bytes color info */
short int cursor_directory_color = YELLOW;
short int info_bg_color = GREEN;
short int info_text_color = BRIGHTWHITE;
short int error_text_color = LIGHTRED;
short int prompt_text_color = YELLOW;
short int hidden_file_color = BRIGHTWHITE;
short int hidden_directory_color = LIGHTGREEN;
short int volume_label_color = CYAN;
short int cursor_hidden_file_color = BRIGHTWHITE;
short int cursor_hidden_directory_color= LIGHTGREEN;
short int cursor_volume_label_color = CYAN;
unsigned short int checkpoint2[3]= { 0xFBFA, 0xFDFC, 0xFFFE }; /* Backword FAFBFCFDFEFF */
static struct { /* FCB for volume label functions */
unsigned char Extcode;
char Res1[5];
unsigned char Code;
unsigned char OldDrive;
char OldName[11];
char Res2[5];
char NewName[11];
char Res3[9];
} DirFcb = {0xFF,"",0x10,0,"","","",""},
VolFcb = {0xFF,"",0x08,0,"???????????","","",""};
static struct { /* DTA for volume label functions */
char Res1[8]; /* reserved */
char OldVolid[11]; /* filled in by DOS */
char Res2[5]; /* reserved */
char NewVolid[11]; /* used by FilSetVolid */
char Res3[9]; /* reserved */
} Dta;
int number_of_files; /* number of files found */
typedef struct find_t_small {
char name [13];
char attrib;
} FIND_T_SMALL;
FIND_T_SMALL *find; /* pointer to the file info structures */
int mouse_present; /* boolean is there a mouse ? */
int mouse_row=0; /* mouse position, NOT screen rows and columns */
int mouse_col=0;
int max_files; /* maximal number of accessible files per directory or root, defaults to 456 */
int dos_error; /* set by error handler */
int dos_retries; /* set by error handler */
/* volume label functions taken from 'Systems Programming in Microsoft C, Michael J. Young */
char *FilGetVolid( unsigned char Drive )
{
int ErrorCode;
union REGS Reg;
Reg.x.dx = (unsigned int) &Dta;
Reg.h.ah = 0x1A;
int86(0x21, &Reg, &Reg);
VolFcb.OldDrive = Drive;
Reg.x.dx = (unsigned int) &VolFcb;
Reg.h.ah = 0x11;
int86(0x21, &Reg, &Reg);
ErrorCode = Reg.h.al;
if (ErrorCode == 0) return (Dta.OldVolid);
else return (NULL);
}
int FilSetVolid( unsigned char Drive, char *Volid )
{
register int i;
int ErrorCode;
union REGS Reg;
if (FilGetVolid(Drive)==NULL)
{
for (i=0;i<11;++i)
if (*Volid=='\0') VolFcb.OldName[i]= ' ';
else VolFcb.OldName[i]= *Volid++;
Reg.x.dx=(unsigned int) &VolFcb;
Reg.h.ah=0x16;
int86(0x21, &Reg, &Reg);
ErrorCode=Reg.h.al;
if (ErrorCode==0) return (NOERROR);
else return (NOCREAT);
}
else
{
for (i=0;i<11;++i)
if (*Volid=='\0') Dta.NewVolid[i]= ' ';
else Dta.NewVolid[i]= *Volid++;
Reg.x.dx=(unsigned int) &Dta;
Reg.h.ah=0x17;
int86(0x21, &Reg, &Reg);
ErrorCode=Reg.h.al;
if (ErrorCode==0) return (NOERROR);
else return (NOREN);
}
}
int FilDelVolid( unsigned char Drive )
{
int ErrorCode;
union REGS Reg;
if (FilGetVolid ( Drive )==NULL)
{
return (NOVOL);
}
else
{
Reg.x.dx=(unsigned int) &Dta;
Reg.h.ah=0x13;
int86(0x21, &Reg,&Reg);
ErrorCode=Reg.h.al;
if (ErrorCode==0) return (NOERROR);
else return (NODEL);
}
}
/*---------------------------------------------------------------------------*/
/* 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);
/*----------------------------------------------------------------------*/
QUE_DEF PatQue;
char T_Path[_MAX_PATH]; /* Temporary directory path to search */
char V_Path[_MAX_PATH]; /* Selected file */
/**************************************************************************
Find and put cursor on file with matching name
*/
int find_name(char *fname, int *current_page, int *filenumber)
{
register int counter;
int result=FAILURE;
if (!number_of_files) return (result);
for (counter=1;counter<=number_of_files;counter++)
if (!strcmp(find[counter].name,fname))
{
result=SUCCESS;
break;
}
if (result==SUCCESS)
{
*filenumber=counter;
*current_page=((counter%114) ? counter/114 : counter/114 - 1);
}
return (result);
}
/*************************************************************************
hide mouse, _outtext, show_mouse
*/
void outtextm( char *string )
{
hide_mouse();
_outtext(string);
show_mouse();
}
/*************************************************************************
Returns F for normal file, D for directory, V for volume label, H for hidden file.
Displays Filename if mode != NOREPAINT
*/
char filename( int filenumber, int mode )
{
char type, namebuf[14];
static struct videoconfig vc={0,0,0,0,0,0,0,0,0,0,0};
if (!vc.numcolors) _getvideoconfig( &vc ); /* initialize on first call */
if (vc.mode==_TEXTMONO)
sprintf( namebuf, "%c%-12s",
(find[filenumber].attrib & _A_HIDDEN) ? '' : ' ',
find[filenumber].name);
else sprintf( namebuf, "%-12s ",find[filenumber].name);
if( find[filenumber].attrib & _A_SUBDIR ) type='D'; /* directory */
else if( find[filenumber].attrib & _A_VOLID ) type='V'; /* volume label */
else type='F'; /* normal file */
switch (mode)
{
case NOREPAINT: break;
case CURSOR: set_cursor( filenumber );
switch (type)
{
case 'D': if (find[filenumber].attrib & _A_HIDDEN) _settextcolor( (short) cursor_hidden_directory_color );
else _settextcolor( (short) cursor_directory_color );
break;
case 'V': _settextcolor( (short) cursor_volume_label_color );
break;
case 'F': if (find[filenumber].attrib & _A_HIDDEN) _settextcolor( (short) cursor_hidden_file_color );
else _settextcolor( (short) cursor_file_color );
break;
}
_setbkcolor( (long) cursor_bg_color );
outtextm( namebuf );
_setbkcolor( (long) screen_bg_color );
break;
case NORMAL: set_cursor( filenumber );
switch (type)
{
case 'D': if (find[filenumber].attrib & _A_HIDDEN) _settextcolor( (short) hidden_directory_color );
else _settextcolor( (short) directory_color );
break;
case 'V': _settextcolor( (short) volume_label_color );
break;
case 'F': if (find[filenumber].attrib & _A_HIDDEN) _settextcolor( (short) hidden_file_color );
else _settextcolor( (short) file_color );
break;
}
_setbkcolor( (long) screen_bg_color );
outtextm( namebuf );
break;
}
return (type);
}
/***************************************************************************
Displays information about a file.
*/
void fileinfo( int filenumber )
{
char timebuf[6], datebuf[9], attrbuf[5], namebuf[13], sizebuf[9], type;
struct find_t pfind;
short x,y,c;
char b[8*29+10]; /* Buffer for string */
char *savedscreen;
int key=0;
/* get full file information */
if (_dos_findfirst( find[filenumber].name, 0xffff, &pfind )) /* not succeeded, get out */
{
show_error("Cannot get the information for this file ");
return;
}
savedscreen=saveScrn();
y = ((25 - 8) / 2) + 1; /* 8 lines, add 1 to center in FS window */
x = ((80 - 28) / 2); /* 28 visible characters per line */
datestr( pfind.wr_date, datebuf );
timestr( pfind.wr_time, timebuf );
sprintf( attrbuf, "%c%c%c%c",
(pfind.attrib & _A_RDONLY) ? 'R' : '_',
(pfind.attrib & _A_HIDDEN) ? 'H' : '_',
(pfind.attrib & _A_SYSTEM) ? 'S' : '_',
(pfind.attrib & _A_ARCH) ? 'A' : '_' );
sprintf( sizebuf, "%ld", pfind.size);
sprintf( namebuf, "%-12s", pfind.name);
if( pfind.attrib & _A_SUBDIR ) type='D'; /* directory */
else if( pfind.attrib & _A_VOLID ) type='V'; /* volume label */
else type='F'; /* normal file */
_settextcolor( (short) info_text_color );
_setbkcolor( (long) info_bg_color );
/* Use text window to place output in middle of screen */
/* The window is 1 position larger than the output string. */
_settextwindow( y, x, y + 8, x + 28 );
shadebox( y, x, y + 8 - 1 , x + 28 - 1 );
/* Write all information to a string, then output string. */
c = sprintf( b , "╔══════════════════════════╗\n");
c += sprintf( b + c, "║ Filename : %-12s ║\n",namebuf);
c += sprintf( b + c, "║ Size : %-12s ║\n",sizebuf);
c += sprintf( b + c, "║ Date : %-12s ║\n",datebuf);
c += sprintf( b + c, "║ Time : %-12s ║\n",timebuf);
c += sprintf( b + c, "║ Attributes: %-12s ║\n",attrbuf);
c += sprintf( b + c, "║ Type : ");
switch (type)
{
case 'F': c += sprintf( b + c, "%-12s ║\n","File");
break;
case 'D': c += sprintf( b + c, "%-12s ║\n","Directory");
break;
case 'V': c += sprintf( b + c, "%-12s ║\n","Volume label");
break;
}
c += sprintf( b + c, "╚══════════════════════════╝\n");
outtextm( b );
while (!(key=n_kbhit()) && !mouse_button_pressed()) /* wait */ ;
_settextwindow( 3, 1, 23, 80 );
_setbkcolor( (long) screen_bg_color );
savedscreen=restScrn(savedscreen);
if ((key & 0x00FF)==ESC) getkey(); /* trash ESC */
}
/***************************************************************************
* Takes unsigned time in the format: fedcba9876543210
* s=2 sec incr, m=0-59, h=23 hhhhhmmmmmmsssss
* Changes to a 5-byte string (ignore seconds): hh:mm
*/
char *timestr( unsigned t, char *buf )
{
int h = (t >> 11) & 0x1f, m = (t >> 5) & 0x3f;
sprintf( buf, "%2.2d:%02.2d", h, m ); return buf;
}
/**************************************************************************
* Takes unsigned date in the format: fedcba9876543210
* d=1-31, m=1-12, y=0-119 (1980-2099) yyyyyyymmmmddddd
* Changes to a 8-byte string: mm/dd/yy
*/
char *datestr( unsigned d, char *buf )
{
sprintf( buf, "%2.2d/%02.2d/%02.2d",
d & 0x1f, (d >> 5) & 0x0f, (d >> 9) + 80 );
return buf;
}
/***************************************************************************
* Calculate page, line, column from filenumber and sets cursor position
* Displays page number if this is changed
* pagelayout: 6 columns of 19 files per page, 114 files per page,
* starting at window line 1, column width 13 (position 1,14,27...)
* filenumber= 1,2,...
* page = 0,1,...
* line = 2,3,...,21
* column = 2,15,28,41,54,67
*/
void set_cursor( int filenumber )
{
int line, column, relfilenumber, old_page, old_max_page;
char linebuf[10];
static int page=-1;
static int max_page=-1;
old_page=page;
old_max_page=max_page;
max_page=((number_of_files%114) ? number_of_files/114 : number_of_files/114 - 1);
line=((filenumber%19) ? filenumber%19 : 19) + 1;
page=((filenumber%114) ? filenumber/114 : filenumber/114 - 1);
relfilenumber=(filenumber - page*114);
column=((relfilenumber%19) ? relfilenumber/19 : relfilenumber/19 - 1) * 13 + 2;
if (old_page!=page || old_max_page!=max_page)
{
sprintf(linebuf,"%d/%d╞══",page+1,max_page+1);
_settextposition( 1, 72 );
_settextcolor( (short) file_color );
_setbkcolor( (long) screen_bg_color );
outtextm(linebuf);
}
_settextposition( line, column );
}
/**************************************************************************
Clear remaining directory page by displaying blank names, starting with
filenumber+1
*/
void clear_remaining( int filenumber )
{
register int line, column, relfilenumber;
int page;
page=((filenumber%114) ? filenumber/114 : filenumber/114 - 1);
relfilenumber=(filenumber - page*114);
_setbkcolor( (long) screen_bg_color );
_settextcolor( (short) file_color );
while (relfilenumber < 114 )
{
filenumber++;
relfilenumber++;
line=((filenumber%19) ? filenumber%19 : 19) + 1;
column=((relfilenumber%19) ? relfilenumber/19 : relfilenumber/19 - 1) * 13 + 2;
_settextposition( line, column );
outtextm( " " );
}
}
/***************************************************************************
* Compares and returns greater than (1), less than (-1), or equal to (0).
* This function is called by qsort.
*/
int _cdecl cmpgle( const void *elem1, const void *elem2 )
{
const struct find_t_small *e1, *e2;
e1=elem1;
e2=elem2;
return strcmp(e1->name,e2->name);
}
/***************************************************************************
Fills find structure and sets number_of_files global. Filters files with
searchstring mask. Skips "." directory and volume label. Sorts find structure
*/
int extract_directory( char *searchstring )
{
struct find_t findtemp;
char type;
number_of_files=0;
working(TRUE);
/* Find first matching file, then find additional matches. */
if( !_dos_findfirst( "*.*\0", _A_ARCH | _A_HIDDEN | _A_NORMAL | _A_RDONLY |
_A_SUBDIR | _A_SYSTEM | _A_VOLID, &findtemp ) )
{
if( findtemp.attrib & _A_SUBDIR ) type='D'; /* directory */
else if( findtemp.attrib & _A_VOLID ) type='V'; /* volume label */
else type='F'; /* normal file (and hidden file) */
if (findtemp.name[0]=='.' && findtemp.name[1]=='\0' && type== 'D') type='N'; /* null dir */
if (type=='F' || type=='D' || type=='V')
{
strcpy(find[++number_of_files].name,findtemp.name);
find[number_of_files].attrib=findtemp.attrib;
}
if (type=='F' && strlen(searchstring) && !Match(findtemp.name,searchstring)) number_of_files--;
while( !_dos_findnext( &findtemp ) && (number_of_files < max_files ))
{
if( findtemp.attrib & _A_SUBDIR ) type='D'; /* directory */
else if( findtemp.attrib & _A_VOLID ) type='V'; /* volume label */
else type='F'; /* normal file */
if (findtemp.name[0]=='.' && findtemp.name[1]=='\0' && type== 'D') type='N'; /* null dir */
if (type=='F' || type=='D' || type=='V')
{
strcpy(find[++number_of_files].name,findtemp.name);
find[number_of_files].attrib=findtemp.attrib;
}
if (type=='F' && strlen(searchstring) && !Match(findtemp.name,searchstring)) number_of_files--;
}
}
working(FALSE);
if (!number_of_files)
{
show_error( "No files found " );
find[1].attrib='\0';
find[1].name[0]='\0';
return FAILURE;
}
qsort( (void *) (&(find[1])), (size_t) number_of_files,
(size_t) sizeof(FIND_T_SMALL), cmpgle);
return SUCCESS;
}
/****************************************************************************
Display the filenames of one page
*/
void show_dir_page( int page )
{
register int filenumber;
for (filenumber=1 + page*114; filenumber<=(114 + page*114) && filenumber<=number_of_files; filenumber++)
{
filename( filenumber, NORMAL );
}
clear_remaining( filenumber-1 );
}
/****************************************************************************
Draw the border lines
*/
void kader( void )
{
int line;
_settextwindow( 3, 1, 24, 80 ); /* prevent scroll-up */
_settextcolor( (short) file_color );
_settextposition( 1, 1 );
hide_mouse();
_outtext("╔════════════╡ ╞════════════════════════════════════════════════════╡ ╞════╗");
for (line=2;line<=20;line++)
{
_settextposition( line, 1 );
_outtext("║");
_settextposition( line, 80 );
_outtext("║");
}
_settextposition( 21, 1 );
_outtext("╚══════════════════════════════════════════════════════════════════════════════╝");
if (number_of_files==max_files)
{
_settextposition( 21,3 );
_outtext( "File table full");
}
show_mouse();
_settextwindow( 3, 1, 23, 80 );
}
/**************************************************************************
Beep
*/
void alert( void )
{
_bios_str( "\007" );
} /* end alert */
/****************************************************************************
* Handler to deal with hard error codes. Since DOS is not reentrant,
* it is not safe to use DOS calls for doing I/O within the DOS Critical
* Error Handler (int 24h) used by _harderr. Therefore, screen output and
* keyboard input must be done through the BIOS.
*/
void _far hhandler( unsigned deverr, unsigned doserr, unsigned _far *hdr )
{
int ch;
unsigned char row=3;
int itel,itel2;
static char buf[200], tmpbuf[10];
/* save error code */
dos_error=doserr;
strcpy( buf, " Device error code: " );
strcat( buf, itoa( deverr, tmpbuf, 10 ) );
strcat( buf, " " );
ScrPutS( buf, 0x0f, row++, 1);
strcpy( buf, " DOS error code : " );
strcat( buf, itoa( doserr, tmpbuf, 10 ) );
strcat( buf, " " );
ScrPutS( buf, 0x0f, row++, 1);
strcpy( buf, " (F) for Fail, any other key for Retry ? " );
ScrPutS( buf, 0x0f, row++, 1);
_bios_str( "\007" );
ch = _bios_keybrd( _KEYBRD_READ ) & 0x00ff;
switch( ch )
{
case 'F':
case 'f': /* Return to DOS with error code */
dos_retries=0;
for (itel=3;itel<=6;itel++) /* blank screen segment */
for (itel2=1;itel2<=41;itel2++)
ScrPutS( " ", ((unsigned char) (screen_bg_color * 16)),
(unsigned char) itel,(unsigned char) itel2);
_hardretn( doserr );
default: /* Try again */
dos_retries++;
strcpy( buf, " Retrying");
for (itel=0;itel<dos_retries;itel++) strcat( buf,".");
ScrPutS( buf, 0x0f, row++, 1);
_hardresume( _HARDERR_RETRY );
}
}
/****************************************************************************
* Display a string using BIOS interrupt 0x0e (Write TTY). Return length
* of string displayed.
*/
int _bios_str( char *p )
{
union REGS inregs, outregs;
char *start = p;
inregs.h.ah = 0x0e;
for( ; *p; p++ )
{
inregs.h.al = *p;
int86( 0x10, &inregs, &outregs );
}
return p - start;
}
/*************************************************************************
Display an error message, wait one second and blank out message
*/
void show_error( char *message )
{
alert();
_settextcolor( (short) error_text_color );
_settextposition( 23,1 );
outtextm( message );
wait_sec(1000);
_settextcolor( (short) file_color );
_settextposition( 23, 1 );
outtextm("╚══════════════════════════════════════════════════════════════════════════════");
_settextposition(1,1);
}
/*************************************************************************
wait, suspend program
*/
void wait_sec( int milliseconds )
{
clock_t cstart;
cstart=clock();
while ( (clock()-cstart) < (clock_t) (CLOCKS_PER_SEC/1000) * (clock_t) milliseconds) ;
}
/****************************************************************************
Displays help information
*/
void helpscreen( void )
{
short x,y;
int key=0;
char b[(18*55)+10]={ /* Buffer for string */
"╔════════════════════════════════════════════════════╗\n"
"║ FS 1.9.1 (C) Copyright M.C.J. van Breemen, 1993 ║\n"
"╟────────────────────────────────────────────────────╢\n"
"║ \x1B\x17\x1A Move cursor Del Delete file/dir/label ║\n"
"║ Return Select file / I File information ║\n"
"║ Change directory D Select drive ║\n"
"║ PgUp Previous screen R Rename file/dir/label ║\n"
"║ PgDn Next screen S Show file ║\n"
"║ Home First file C Copy file ║\n"
"║ End Last file M Change selection mask ║\n"
"║ T Top directory X Temporary exit to DOS ║\n"
"║ U Up one dir. E Execute file ║\n"
"║ Alt-AZ Go to filename A Change attributes ║\n"
"║ / Refresh screen N Create directory ║\n"
"║ L Exit & keep dir. V Create volume label ║\n"
"║ Esc Exit / Cancel F Disk space free ║\n"
"║ P About the program W Where is file ║\n"
"╚════════════════════════════════════════════════════╝\n"
};
char *savedscreen;
savedscreen=saveScrn();
y = ((25 - 18) / 2) + 1; /* 18 lines */
x = (80 - 54) / 2; /* 54 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 + 18, x + 54 );
shadebox( y, x, y + 18 - 1 , x + 54 - 1 );
outtextm( b );
while (!(key=n_kbhit()) && !mouse_button_pressed()) /* wait */ ;
_settextwindow( 3, 1, 23, 80 );
_setbkcolor( (long) screen_bg_color );
savedscreen=restScrn(savedscreen);
if ((key & 0x00FF)==ESC) getkey(); /* trash ESC */
}
/****************************************************************************
Displays program information
*/
void aboutscreen( void )
{
short x,y;
int key=0;
char b[(15*53)+10]={ /* Buffer for string */
"╔══════════════════════════════════════════════════╗\n"
"║ ║\n"
"║ File Selector, Version 1.9.1 ║\n"
"║ Copyright (C) 1993 by M.C.J. van Breemen ║\n"
"║ ║\n"
"║ Release date: 24-FEB-1993 ║\n"
"║ ║\n"
"║ Program designed and written by: ║\n"
"║ ║\n"
"║ Maarten van Breemen ║\n"
"║ Combinatiepolder 13 ║\n"
"║ 5235 TR 's-Hertogenbosch ║\n"
"║ The Netherlands ║\n"
"║ ║\n"
"╚══════════════════════════════════════════════════╝\n"
};
char *savedscreen;
savedscreen=saveScrn();
y = ((25 - 15) / 2) + 1; /* 15 lines */
x = (80 - 52) / 2; /* 52 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 + 15, x + 52 );
shadebox( y, x, y + 15 - 1, x + 52 - 1 );
outtextm( b );
while (!(key=n_kbhit()) && !mouse_button_pressed()) /* wait */ ;
_settextwindow( 3, 1, 23, 80 );
_setbkcolor( (long) screen_bg_color );
savedscreen=restScrn(savedscreen);
if ((key & 0x00FF)==ESC) getkey(); /* trash ESC */
}
/*************************************************************************
Mouse
*/
void clear_left_button_queue( void )
{
union REGS in_regs, out_regs;
in_regs.x.bx = 0; /* Clear left button queue */
in_regs.x.ax = 5;
int86(0x33, &in_regs, &out_regs);
}
/*************************************************************************
Mouse
*/
void clear_right_button_queue( void )
{
union REGS in_regs, out_regs;
in_regs.x.bx = 1; /* Clear right button queue */
in_regs.x.ax = 5;
int86(0x33, &in_regs, &out_regs);
}
/*************************************************************************
Mouse
* Read left button queue
* Return 0 if no left button pressed
* 1 if pressed but on new position
* 2 if re-pressed on old position within 0.75 second
*/
int read_left_button_queue( int *row, int *col )
{
union REGS in_regs, out_regs;
static int lastrow, lastcol, number_times;
static clock_t cstart;
in_regs.x.bx = 0;
in_regs.x.ax = 5;
int86(0x33, &in_regs, &out_regs);
number_times = out_regs.x.bx;
*row = out_regs.x.dx / 8 + 1;
*col = out_regs.x.cx / 8 + 1;
if (!number_times) return 0;
if (lastrow==*row && lastcol==*col && ((clock()-cstart) < (clock_t) CLOCKS_PER_SEC*2/3))
{
clear_left_button_queue();
cstart=clock();
return 2;
}
lastrow = *row;
lastcol = *col;
clear_left_button_queue();
cstart=clock();
return 1;
}
/*************************************************************************
Mouse
* Read right button queue
* Return 0 if no right button pressed
* 1 if pressed but on new position
* 2 if re-pressed on old position within 0.75 second
*/
int read_right_button_queue( int *row, int *col )
{
union REGS in_regs, out_regs;
static int lastrow, lastcol, number_times;
static clock_t cstart;
in_regs.x.bx = 1;
in_regs.x.ax = 5;
int86(0x33, &in_regs, &out_regs);
number_times = out_regs.x.bx;
*row = out_regs.x.dx / 8 + 1;
*col = out_regs.x.cx / 8 + 1;
if (!number_times) return 0;
if (lastrow==*row && lastcol==*col && ((clock()-cstart) < (clock_t) CLOCKS_PER_SEC*2/3))
{
clear_right_button_queue();
cstart=clock();
return 2;
}
lastrow = *row;
lastcol = *col;
clear_right_button_queue();
cstart=clock();
return 1;
}
/*********************************************************************88
Mouse
*/
void init_mouse( void )
{
union REGS in_regs, out_regs;
int top, bottom, left, right;
in_regs.x.ax = 0; /* Initialize mouse */
int86(0x33, &in_regs, &out_regs);
if (!out_regs.x.ax)
{
mouse_present=FALSE;
return;
} else mouse_present=TRUE;
right = 79; /* Restrict cursor horizontally */
left = 2;
in_regs.x.cx = 8 * (right - 1);
in_regs.x.dx = 8 * (left - 1);
in_regs.x.ax = 7;
int86(0x33, &in_regs, &out_regs);
top = 4; /* Restrict cursor vertically */
bottom = 22;
in_regs.x.cx = 8 * (top - 1);
in_regs.x.dx = 8 * (bottom - 1);
in_regs.x.ax = 8;
int86(0x33, &in_regs, &out_regs);
clear_left_button_queue();
if (mouse_col) /* re-position mouse */
{
in_regs.x.cx = mouse_col;
in_regs.x.dx = mouse_row;
in_regs.x.ax = 4;
int86(0x33, &in_regs, &out_regs);
}
show_mouse();
}
/***************************************************************************8
Mouse
*/
void hide_mouse( void )
{
union REGS in_regs, out_regs;
if (!mouse_present) return;
/* first save mouse position for possible future mouse_init */
in_regs.x.ax = 3;
int86(0x33, &in_regs, &out_regs);
mouse_col = out_regs.x.cx;
mouse_row = out_regs.x.dx;
in_regs.x.ax = 2; /* Hide mouse cursor */
int86(0x33, &in_regs, &out_regs);
}
/***************************************************************************8
Mouse
*/
void show_mouse( void )
{
union REGS in_regs, out_regs;
if (!mouse_present) return;
in_regs.x.ax = 1; /* Show mouse cursor */
int86(0x33, &in_regs, &out_regs);
}
/*************************************************************************
Mouse
* Status mouse buttons
* Return 0 if no button pressed
* else something is in queue
*/
int mouse_button_pressed( void )
{
union REGS in_regs, out_regs;
in_regs.x.bx = 0;
in_regs.x.ax = 3;
int86(0x33, &in_regs, &out_regs);
return( out_regs.x.bx );
}
/***************************************************************************
Common redraw functions
*/
void perform_repaint(int current_page, int filenumber)
{
char linebuf[81];
int page, max_page;
max_page=((number_of_files%114) ? number_of_files/114 : number_of_files/114 - 1);
page=((filenumber%114) ? filenumber/114 : filenumber/114 - 1);
_setbkcolor( (long) screen_bg_color );
_settextcolor( (short) file_color );
_clearscreen( _GWINDOW );
kader();
show_path();
show_dir_page( current_page );
_setbkcolor( (long) screen_bg_color );
_settextcolor( (short) file_color );
sprintf(linebuf,"%d/%d",page+1,max_page+1);
_settextposition( 1, 72 );
outtextm( linebuf );
filename( filenumber, CURSOR ); /* emphasize file under cursor */
}
/**************************************************************************
Cursor movement key handler, page down
*/
void c_pgdn( int *current_page, int *filenumber)
{
int max_page;
max_page=((number_of_files%114) ? number_of_files/114 : number_of_files/114 - 1);
if (*current_page<max_page) (*current_page)++;
else *current_page=0;
show_dir_page( *current_page );
*filenumber=((*current_page)*114+1);
filename( *filenumber, CURSOR );
}
/**************************************************************************
Cursor movement key handler, page up
*/
void c_pgup( int *current_page, int *filenumber)
{
int max_page;
max_page=((number_of_files%114) ? number_of_files/114 : number_of_files/114 - 1);
if (*current_page>0) (*current_page)--;
else *current_page=max_page;
show_dir_page( *current_page );
*filenumber=((*current_page)*114+1);
filename( *filenumber, CURSOR );
}
/**************************************************************************
Cursor movement key handler, home
*/
void c_home( int *current_page, int *filenumber)
{
*current_page=0;
show_dir_page( *current_page );
*filenumber=((*current_page)*114+1);
filename( *filenumber, CURSOR );
}
/**************************************************************************
Find and display file with starting character chr
*/
void find_first(char chr, int *current_page, int *filenumber)
{
register int counter;
int old_page;
int old_filenumber;
if (!number_of_files) return;
old_page=*current_page;
old_filenumber=*filenumber;
for (counter=1;counter<number_of_files;counter++) /* should end at last file */
if (find[counter].name[0]>=chr) break;
*filenumber=counter;
*current_page=((counter%114) ? counter/114 : counter/114 - 1);
if (*current_page!=old_page) perform_repaint(*current_page,*filenumber);
else
{
if (*filenumber!=old_filenumber)
{
filename( old_filenumber, NORMAL );
filename( *filenumber, CURSOR );
}
}
}
/**************************************************************************
Cursor movement key handler, end
*/
void c_end( int *current_page, int *filenumber)
{
int max_page;
max_page=((number_of_files%114) ? number_of_files/114 : number_of_files/114 - 1);
*current_page=max_page;
show_dir_page( *current_page );
*filenumber=((*current_page)*114+114);
*filenumber=(*filenumber<number_of_files) ? *filenumber : number_of_files;
filename( *filenumber, CURSOR );
}
/**************************************************************************
Cursor movement key handler, up arrow
*/
void c_cup( int *current_page, int *filenumber)
{
int old_filenumber;
old_filenumber=*filenumber;
if (*filenumber>((*current_page)*114+1)) (*filenumber)--;
else
{
*filenumber=((*current_page)*114+114);
*filenumber=(*filenumber<number_of_files) ? *filenumber : number_of_files;
}
if (*filenumber!=old_filenumber)
{
filename( old_filenumber, NORMAL );
filename( *filenumber, CURSOR );
}
}
/**************************************************************************
Cursor movement key handler, down arrow
*/
void c_cdn( int *current_page, int *filenumber)
{
int old_filenumber;
old_filenumber=*filenumber;
if (*filenumber<((*current_page)*114+114) &&
*filenumber<number_of_files) (*filenumber)++;
else *filenumber=((*current_page)*114+1);
filename( old_filenumber, NORMAL );
filename( *filenumber, CURSOR );
}
/**************************************************************************
Cursor movement key handler , right arrow
*/
void c_cri( int *current_page, int *filenumber)
{
int old_filenumber;
old_filenumber=*filenumber;
if ((*filenumber <= ((*current_page)*114+95)) &&
((*filenumber+19) <= number_of_files)) (*filenumber)+=19;
else
{
(*filenumber)%=19;
if (!(*filenumber)) *filenumber=19;
(*filenumber)+=((*current_page)*114);
}
if (*filenumber!=old_filenumber)
{
filename( old_filenumber, NORMAL );
filename( *filenumber, CURSOR );
}
}
/**************************************************************************
Cursor movement key handler, left arrow
*/
void c_cle( int *current_page, int *filenumber)
{
int old_filenumber;
int maxcolumnnumber;
old_filenumber=*filenumber;
if (*filenumber>=((*current_page)*114+1)+19) (*filenumber)-=19;
else
{
maxcolumnnumber=5;
while ((*filenumber+maxcolumnnumber*19)>number_of_files) maxcolumnnumber--;
(*filenumber)+=maxcolumnnumber*19;
}
if (*filenumber!=old_filenumber)
{
filename( old_filenumber, NORMAL );
filename( *filenumber, CURSOR );
}
}
/***********************************************************************
returns 0 if no key waiting, key code if key waiting
*/
unsigned int n_kbhit()
{
int kread = _KEYBRD_READ;
int kready = _KEYBRD_READY;
int kshiftstatus = _KEYBRD_SHIFTSTATUS;
/* If bit 4 of the byte at 0x0040:0x0096 is set, the new keyboard
* is present.
*/
if( peek( 0x00400096 ) & 0x10 )
{
kread = _NKEYBRD_READ;
kready = _NKEYBRD_READY;
kshiftstatus = _NKEYBRD_SHIFTSTATUS;
}
return _bios_keybrd( kready );
}
/************************************************************************
Entry point of directory handler
Globals: find, files structure
number_of_files
colors
Returns SUCCESS if a valid choice has been made, else EXIT_RESTORE if ESCaped
or EXIT_KEEP if Leaved
Passes selected file in string selected
*/
int handle_dir( char *searchstr, char *selected , int safe_mode)
{
int key;
int repaint;
static int current_page=0;
static int filenumber=1;
int old_filenumber;
short oldfgd; /* old foreground color */
long oldbgd; /* old background color */
struct rccoord oldpos;
short oldcursor; /* old cursor shape */
int olddrive, lastdrive, tempdrive, newdrive;
char oldcwd[_MAX_PATH];
static char searchstring[13]={"\0"};
int row, col; /* mouse variables */
int finished;
struct videoconfig vc;
char scratch[ _MAX_PATH ]; /* scratch string space */
int exit_and_keep=FALSE; /* boolean for 'l' function */
char *dummyspace; /* memory reserved for saveScrn */
struct diskfree_t drvinfo;
char comspec[_MAX_PATH];
strcpy(comspec,getenv("COMSPEC"));
if (!strlen(comspec)) strcpy(comspec,"COMMAND"); /* default program to run is COMMAND.COM */
/* Save original foreground, background, and text position. */
init_mouse();
oldfgd = _gettextcolor();
oldbgd = _getbkcolor();
oldpos = _gettextposition();
oldcursor=_gettextcursor();
_settextcursor( 0x2000 );
_settextwindow( 3, 1, 23, 80 );
_getvideoconfig( &vc );
if (vc.mode==_TEXTMONO)
{
screen_bg_color = M_BLACK_BG;
file_color = M_GRAY;
directory_color = M_WHITE;
cursor_bg_color = M_BLACK_BG;
cursor_file_color = M_GRAY_UNDL;
cursor_directory_color = M_WHITE_UNDL;
info_bg_color = M_BLACK_BG;
info_text_color = M_WHITE;
error_text_color = M_WHITE;
prompt_text_color = M_WHITE;
hidden_file_color = M_GRAY;
hidden_directory_color = M_WHITE;
volume_label_color = M_GRAY;
cursor_hidden_file_color = M_GRAY_UNDL;
cursor_hidden_directory_color= M_WHITE_UNDL;
cursor_volume_label_color = M_GRAY_UNDL;
}
if (!strlen(searchstring)) strcpy(searchstring,searchstr); /* keep old definition */
if (!strlen(searchstring)) strcpy(searchstring,"*.*");
find=(FIND_T_SMALL *) 0L;
if (max_files<=0) max_files=MAX_FILES;
dummyspace = (char *) malloc (4096 + 1024); /* alloceer ruimte voor screen saves + 1k extra voor fff enzo */
if( !(find = (FIND_T_SMALL *)calloc( (size_t) max_files + 2, (size_t) sizeof(FIND_T_SMALL) )) )
{
if (dummyspace) free(dummyspace);
_settextwindow( 1, 1, 25, 80 );
_settextposition( oldpos.row, oldpos.col );
_settextcursor( oldcursor );
printf("Cannot allocate memory for %d files",max_files);
alert();
wait_sec(1000);
return FAILURE;
}
if (dummyspace) free(dummyspace); /* hoppa, we hebben weer lucht */
/* Install our hard error handler. */
_harderr( hhandler );
/* Save current drive and current working directory. */
olddrive = lastdrive = _getdrive();
getcwd( oldcwd, _MAX_PATH );
repaint=TRUE;
extract_directory( searchstring );
if (filenumber>number_of_files) /* can we restore the cursor ? */
{
current_page=0; /* no */
filenumber=1;
}
finished=FALSE;
do
{
dos_error=0;
dos_retries=0;
if (repaint)
{
/* maak kader repaint */
perform_repaint(current_page, filenumber);
repaint=FALSE;
}
if (mouse_present)
{
switch (read_left_button_queue(&row,&col))
{
case 0: break;
case 1: if (!number_of_files) break;
old_filenumber=filenumber;
filenumber=(row-4)+(current_page*114+1)+((col-2)/13)*19;
if (filenumber>number_of_files) filenumber=old_filenumber;
if (filenumber!=old_filenumber)
{
filename( old_filenumber, NORMAL );
filename( filenumber, CURSOR );
}
break;
case 2: if (!number_of_files) break;
old_filenumber=filenumber;
filenumber=(row-4)+(current_page*114+1)+((col-2)/13)*19;
if (filenumber<=number_of_files)
{
if (filename( filenumber, NOREPAINT )=='D')
{
repaint=TRUE;
if (!strcmp(find[filenumber].name,"..")) /* going up */
{
find_parent( ¤t_page, &filenumber, searchstring);
}
else /* going down */
{
chdir( find[filenumber].name );
extract_directory( searchstring );
current_page=0;
filenumber=1;
}
} else finished=TRUE; /* add normal file handling here */
} else filenumber=old_filenumber;
break;
}
if (read_right_button_queue(&row,&col) && number_of_files) /* right button */
{
_getdcwd( _getdrive(), scratch, _MAX_PATH );
if (strlen(scratch)>3)
{
repaint=TRUE;
find_parent( ¤t_page, &filenumber,searchstring);
}
}
}
if (n_kbhit() && !finished)
{
key = getkey();
if (key<256) key = tolower(key);
if (key=='l' && !safe_mode) /* leave FS here */
{
exit_and_keep=TRUE;
key=ESC;
}
if (key==ESC) break; /* ESC, exit do while TRUE loop */
repaint=FALSE;
switch (key)
{
case 'i': if (number_of_files) fileinfo( filenumber );
break;
case 'h':
case '?': helpscreen();
break;
case 'p': aboutscreen();
break;
case 'a': if (safe_mode) break;
if (number_of_files)
switch (ed_attributes(filenumber))
{
case FAILURE: show_error("Cannot change the attributes ");
break;
case SUCCESS: repaint=TRUE;
extract_directory( searchstring );
if (filenumber > number_of_files)
{
filenumber=1;
current_page=0;
}
break;
case NOCHANGE: break;
}
break;
case K_PGDN: if (number_of_files) c_pgdn( ¤t_page, &filenumber);
break;
case K_PGUP: if (number_of_files) c_pgup( ¤t_page, &filenumber);
break;
case K_HOME: if (number_of_files) c_home( ¤t_page, &filenumber);
break;
case K_END: if (number_of_files) c_end( ¤t_page, &filenumber);
break;
case K_CUP: if (number_of_files) c_cup( ¤t_page, &filenumber);
break;
case K_CDN: if (number_of_files) c_cdn( ¤t_page, &filenumber);
break;
case K_CRI: if (number_of_files) c_cri( ¤t_page, &filenumber);
break;
case K_CLE: if (number_of_files) c_cle( ¤t_page, &filenumber);
break;
case '\r': if (!number_of_files) break;
repaint=TRUE;
if (filename( filenumber, NOREPAINT )=='D')
{
if (!strcmp(find[filenumber].name,"..")) /* going up */
{
find_parent( ¤t_page, &filenumber,searchstring);
}
else /* going down */
{
chdir( find[filenumber].name );
extract_directory( searchstring );
current_page=0;
filenumber=1;
}
} else finished=TRUE; /* add normal file handling here */
break;
case 'u': if (!number_of_files) break;
_getdcwd( _getdrive(), scratch, _MAX_PATH );
if (strlen(scratch)>3)
{
repaint=TRUE;
find_parent( ¤t_page, &filenumber,searchstring);
}
break;
case 't': if (!number_of_files) break;
_getdcwd( _getdrive(), scratch, _MAX_PATH );
if (strlen(scratch)>3)
{
repaint=TRUE;
scratch[0]= (char) (_getdrive() - 1 + 'A');
scratch[1]=':';
scratch[2]='\\';
scratch[3]='\0';
chdir( scratch );
extract_directory( searchstring );
current_page=0;
filenumber=1;
}
break;
case 'x': if (safe_mode) break;
hide_mouse();
_settextcolor( oldfgd );
_setbkcolor( oldbgd );
_clearscreen( _GCLEARSCREEN );
_settextcursor( oldcursor );
lastdrive = _getdrive();
strcpy(scratch,"PROMPT=Type EXIT to return to FS$_$p$g");
putenv(scratch);
if (!_swap) xsystem(comspec);
else system(comspec);
_harderr( hhandler );
init_mouse();
_settextcursor( 0x2000 );
_chdrive( lastdrive );
extract_directory( searchstring );
if (filenumber>number_of_files) /* can we restore the cursor ? */
{
current_page=0;
filenumber=1;
}
repaint=TRUE;
break;
case 'f': if (freespace( scratch )==SUCCESS)
{
_settextposition( 23, 26 );
_settextcolor( (short) prompt_text_color );
outtextm( scratch );
while (!n_kbhit() && !mouse_button_pressed()) /* wait */ ;
_settextposition( 23, 26 );
_settextcolor( (short) file_color );
outtextm("══════════════════════════════");
}
break;
case 'd': newdrive=ask_drive_number(" Type new drive letter or ESC ");
if (newdrive!=-1)
{
dos_error=0;
dos_retries=0;
lastdrive = tempdrive = _getdrive(); /* start excessive error checking to prevent */
if (_chdrive( newdrive)) /* triggering the dos error handler */
{
show_error("No such drive "); /* first check */
_chdrive( lastdrive );
} else lastdrive= newdrive;
dos_error=0;
dos_retries=0;
do
{
if (!drvalid(lastdrive-1) || dos_error) /* second check */
{
dos_error=0;
dos_retries=0;
show_error("Cannot select this drive ");
lastdrive=tempdrive;
newdrive=ask_drive_number(" Enter a valid drive letter or ESC "); /* ask for a valid drive */
if (newdrive!=-1) lastdrive=newdrive; /* try this one or go back to the initial drive (tempdrive) */
_chdrive( lastdrive ); /* force to a valid drive */
}
else
{
_dos_getdiskfree( lastdrive, &drvinfo ); /* third check, try to access the disk */
if (dos_error)
{
dos_error=0;
dos_retries=0;
show_error("Cannot select this drive ");
lastdrive=tempdrive;
newdrive=ask_drive_number(" Enter a valid drive letter or ESC "); /* ask for a valid drive */
if (newdrive!=-1) lastdrive=newdrive; /* try this one or go back to the initial drive (tempdrive) */
_chdrive( lastdrive ); /* force to a valid drive */
}
}
} while (dos_error);
extract_directory( searchstring );
current_page=0;
filenumber=1;
repaint=TRUE;
}
else
{
_settextposition( 23, 25 );
outtextm("══════════════════════════════");
}
break;
case K_DEL: if (safe_mode) break;
if (!number_of_files) break;
if (!strcmp(find[filenumber].name,"..")) break; /* this could give you a lot of free space */
_settextposition( 23, 17 );
_settextcolor( (short) prompt_text_color );
outtextm(" Type Y to delete or any other key to cancel ");
_settextcolor( (short) file_color );
_settextposition( 1, 1 ); /* prevent scroll-up from dos error */
key = getkey();
if (key=='y' || key=='Y')
{
if (filename( filenumber, NOREPAINT )=='D')
{
if (rmdir(find[filenumber].name)) /* first try normal delete, will fail if not empty */
{ /* then try to clean up */
_settextposition( 23, 4 );
_settextcolor( (short) prompt_text_color );
outtextm(" Directory contains files. Type Y to delete all or any other key to cancel ");
_settextcolor( (short) file_color );
_settextposition( 1, 1 ); /* prevent scroll-up from dos error */
key = getkey();
if (key=='y' || key=='Y')
{
do_dir(find[filenumber].name);
}
}
}
else
{
if (filename( filenumber, NOREPAINT )=='V')
{
if (FilDelVolid( (unsigned char) _getdrive() )==NODEL)
show_error("Cannot delete this volume label ");
}
else
{
if (unlink(find[filenumber].name))
show_error("Cannot delete this file ");
}
}
extract_directory( searchstring );
if (filenumber > number_of_files)
{
filenumber=1;
current_page=0;
}
repaint=TRUE;
} else
{
_settextposition( 23, 17 );
_settextcolor( (short) file_color );
outtextm("═════════════════════════════════════════════");
}
break;
case '/': repaint=TRUE;
extract_directory( searchstring );
if (filenumber > number_of_files)
{
filenumber=1;
current_page=0;
}
break;
case 'v': if (safe_mode) break;
switch (rename_volume_label(0)) /* use dummy zero index */
{
case FAILURE: show_error("Cannot create this volume label ");
break;
case SUCCESS: repaint=TRUE;
extract_directory( searchstring );
if (filenumber > number_of_files)
{
filenumber=1;
current_page=0;
}
break;
case NOCHANGE: break;
}
break;
case 's': hide_mouse();
if (number_of_files)
if (show_file( find[filenumber].name)==SUCCESS)
repaint=TRUE;
show_mouse();
break;
case 'e': if (safe_mode) break;
if (!number_of_files) break;
hide_mouse();
repaint=TRUE;
_settextcolor( oldfgd );
_setbkcolor( oldbgd );
_settextcursor( oldcursor );
lastdrive = _getdrive();
if (!_swap) xsystem(find[filenumber].name);
else system(find[filenumber].name);
_settextcolor( (short) prompt_text_color );
_setbkcolor( (long) screen_bg_color );
_settextposition( 23, 25 );
outtextm(" Press any key to continue ");
getkey();
_harderr( hhandler );
init_mouse();
_settextcursor( 0x2000 );
extract_directory( searchstring );
if (filenumber>number_of_files) /* can we restore the cursor ? */
{
current_page=0;
filenumber=1;
}
break;
case 'm': strcpy(scratch,searchstring);
if (edit("Enter a filename mask, ESC to cancel",searchstring, 12,":\\ +=[];|,<>/\""))
{
if (strcmp(searchstring,scratch))
{
extract_directory( searchstring );
if (filenumber>number_of_files) /* can we restore the cursor ? */
{
current_page=0;
filenumber=1;
}
repaint=TRUE;
}
}
break;
case 'r': if (safe_mode) break;
if (number_of_files)
{
if (filename( filenumber, NOREPAINT )=='V')
{
switch (rename_volume_label(filenumber))
{
case FAILURE: show_error("Cannot rename this volume label ");
break;
case SUCCESS: repaint=TRUE;
extract_directory( searchstring );
if (filenumber > number_of_files)
{
filenumber=1;
current_page=0;
}
break;
case NOCHANGE: break;
}
}
else switch (rename_file(filenumber)) /* file or dir */
{
case FAILURE: show_error("Cannot rename this file ");
break;
case SUCCESS: repaint=TRUE;
extract_directory( searchstring );
if (filenumber > number_of_files)
{
filenumber=1;
current_page=0;
}
break;
case NOCHANGE: break;
}
}
break;
case 'n': if (safe_mode) break;
switch (make_directory())
{
case FAILURE: show_error("Cannot create this directory ");
break;
case SUCCESS: repaint=TRUE;
extract_directory( searchstring );
if (filenumber > number_of_files)
{
filenumber=1;
current_page=0;
}
break;
case NOCHANGE: break;
}
break;
case 'w': switch (whereis(searchstring, ¤t_page, &filenumber))
{
case U_SELECT: finished=TRUE;
break;
case U_GOTO: repaint=TRUE;
break;
case FAILURE: repaint=TRUE;
show_error( "File find failed ");
extract_directory( searchstring );
if (filenumber > number_of_files)
{
filenumber=1;
current_page=0;
}
break;
case U_ESC: break;
}
break;
case 'c': if (safe_mode) break;
if (number_of_files)
switch (copy_file(filenumber))
{
case FAILURE: show_error("Cannot copy this file ");
break;
case SUCCESS: repaint=TRUE;
extract_directory( searchstring );
if (filenumber > number_of_files)
{
filenumber=1;
current_page=0;
}
break;
case NOCHANGE: break;
}
break;
case SCAN_A: find_first('A',¤t_page, &filenumber);
break;
case SCAN_B: find_first('B',¤t_page, &filenumber);
break;
case SCAN_C: find_first('C',¤t_page, &filenumber);
break;
case SCAN_D: find_first('D',¤t_page, &filenumber);
break;
case SCAN_E: find_first('E',¤t_page, &filenumber);
break;
case SCAN_F: find_first('F',¤t_page, &filenumber);
break;
case SCAN_G: find_first('G',¤t_page, &filenumber);
break;
case SCAN_H: find_first('H',¤t_page, &filenumber);
break;
case SCAN_I: find_first('I',¤t_page, &filenumber);
break;
case SCAN_J: find_first('J',¤t_page, &filenumber);
break;
case SCAN_K: find_first('K',¤t_page, &filenumber);
break;
case SCAN_L: find_first('L',¤t_page, &filenumber);
break;
case SCAN_M: find_first('M',¤t_page, &filenumber);
break;
case SCAN_N: find_first('N',¤t_page, &filenumber);
break;
case SCAN_O: find_first('O',¤t_page, &filenumber);
break;
case SCAN_P: find_first('P',¤t_page, &filenumber);
break;
case SCAN_Q: find_first('Q',¤t_page, &filenumber);
break;
case SCAN_R: find_first('R',¤t_page, &filenumber);
break;
case SCAN_S: find_first('S',¤t_page, &filenumber);
break;
case SCAN_T: find_first('T',¤t_page, &filenumber);
break;
case SCAN_U: find_first('U',¤t_page, &filenumber);
break;
case SCAN_V: find_first('V',¤t_page, &filenumber);
break;
case SCAN_W: find_first('W',¤t_page, &filenumber);
break;
case SCAN_X: find_first('X',¤t_page, &filenumber);
break;
case SCAN_Y: find_first('Y',¤t_page, &filenumber);
break;
case SCAN_Z: find_first('Z',¤t_page, &filenumber);
break;
case '!': sprintf(scratch,"Memory free: %u ", _memmax()); /* debug info */
show_error( scratch );
break;
default: break;
} /* switch */
} /* kbhit */
} while (!finished);
if (key!=ESC || finished) /* do not miss the mouse selection */
{
/* construct filename */
lastdrive = _getdrive();
_getdcwd( lastdrive, selected, _MAX_PATH );
if (selected[strlen(selected)-1]!='\\') strcat(selected,"\\");
strcat(selected,find[filenumber].name);
}
if (!exit_and_keep) /* restore old situation */
{
_chdrive( olddrive );
chdir( oldcwd );
}
hide_mouse();
/* Restore original foreground and background. */
_settextcolor( oldfgd );
_setbkcolor( oldbgd );
_clearscreen( _GWINDOW );
_settextwindow( 1, 1, 25, 80 );
_settextposition( oldpos.row, oldpos.col );
_settextcursor( oldcursor );
if (find) free( find );
if (key==ESC && !finished)
{
if (exit_and_keep) return EXIT_KEEP;
else return EXIT_RESTORE;
}
else return SUCCESS;
} /* end handle_dir */
/****************************************************************************
renames file
*/
int rename_file( int filenumber)
{
char newname[50];
strcpy(newname,find[filenumber].name);
if (edit("Rename: Enter a new filename, ESC to cancel",newname,48," +=[];|,<>/?*\""))
{
if (!strlen(newname)) return NOCHANGE; /* null filename */
if (!valid_filename(newname)) return FAILURE; /* invalid filename */
if (strcmp(find[filenumber].name,newname))
if (rename(find[filenumber].name,newname)) return FAILURE;
else return SUCCESS; /* rename succeeded */
}
return NOCHANGE; /* ESCaped */
}
/****************************************************************************
renames volume_label
*/
int rename_volume_label( int filenumber)
{
char newname[50];
char *p;
strcpy(newname,find[filenumber].name);
if (p=strrchr(newname,'.')) memmove( p, p+1, strlen(p+1)+1); /* remove . */
if (edit("Enter a new volume label, ESC to cancel",newname,11,"+=[];|,.<>/?*\\:()&^\""))
{
if (!strlen(newname)) return NOCHANGE; /* null filename */
strupr(newname);
if (strcmp(find[filenumber].name,newname))
if (FilSetVolid( (unsigned char) _getdrive() ,newname)!=NOERROR) return FAILURE;
else return SUCCESS; /* rename succeeded */
}
return NOCHANGE; /* ESCaped */
}
/*************************************************************************
Change file attributes
*/
int ed_attributes( int filenumber)
{
char attrbuf[5];
unsigned int fattr;
strcpy( attrbuf, "");
if (find[filenumber].attrib & _A_RDONLY) strcat(attrbuf,"R");
if (find[filenumber].attrib & _A_HIDDEN) strcat(attrbuf,"H");
if (find[filenumber].attrib & _A_SYSTEM) strcat(attrbuf,"S");
if (find[filenumber].attrib & _A_ARCH) strcat(attrbuf,"A");
if (edit("(R)eadonly, (H)idden, (S)ystem, (A)rchive",attrbuf,4,
" !@#$%^&*()+-_=[]{};:'\"\\|`~,<.>/?1234567890BCEDFGIJKLMNOPQTUVWXYZbcdefgijklmnopqtuvwxyz"))
{
fattr=0;
strlwr(attrbuf);
if (strchr(attrbuf, 'r')) fattr|=_A_RDONLY;
if (strchr(attrbuf, 'h')) fattr|=_A_HIDDEN;
if (strchr(attrbuf, 's')) fattr|=_A_SYSTEM;
if (strchr(attrbuf, 'a')) fattr|=_A_ARCH;
if ((find[filenumber].attrib & (_A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_ARCH)) != (char) fattr)
if (_dos_setfileattr( find[filenumber].name, fattr)) return FAILURE;
else return SUCCESS;
}
return NOCHANGE;
}
/***************************************************************************
Copy file
*/
int copy_file( int filenumber)
{
char newname[50];
strcpy(newname,find[filenumber].name);
if (edit("Copy: Enter a new filename, ESC to cancel",newname,48," +=[];|,<>/?*\""))
{
if (!strlen(newname)) return NOCHANGE;
if (!valid_filename(newname)) return FAILURE;
if (strcmp(find[filenumber].name,newname))
if (copy(find[filenumber].name,newname)) return FAILURE;
else return SUCCESS;
}
return NOCHANGE;
}
/**************************************************************************
mkdir
*/
int make_directory( void )
{
char newname[14];
strcpy(newname,"");
if (edit("Create: Enter a new directory name, ESC to cancel",newname,12," +=[];|,<>/?*\""))
{
if (!strlen(newname)) return NOCHANGE;
if (!valid_filename(newname)) return FAILURE;
if (mkdir(newname)) return FAILURE;
else return SUCCESS;
}
return NOCHANGE;
}
/**********************************************************************
* Copies one file to another (both specified by path). Dynamically
* allocates memory for the file buffer. Prompts before overwriting
* existing file. Returns 0 if successful, otherwise an error number.
*/
int copy( char *source, char *target )
{
char *buf;
int hsource, htarget, ch;
unsigned count = 0xff00;
/* Open source file and create target, overwriting if necessary. */
if( (hsource = open( source, O_BINARY | O_RDONLY )) == - 1 )
return errno;
htarget = open( target, O_BINARY | O_WRONLY | O_CREAT | O_EXCL,
S_IREAD | S_IWRITE );
if( errno == EEXIST )
{
_settextposition( 23, 25 );
_settextcolor( (short) prompt_text_color );
outtextm(" Target exists. Overwrite ? ");
_settextcolor( (short) file_color );
_settextposition( 1, 1 ); /* prevent scroll-up from dos error */
ch = getkey();
if (ch=='y' || ch=='Y')
htarget = open( target, O_BINARY | O_WRONLY | O_CREAT | O_TRUNC,
S_IREAD | S_IWRITE );
}
if( htarget == -1 )
return errno;
if( filelength( hsource ) < (long) count )
count = (int)filelength( hsource );
/* Dynamically allocate a large file buffer. If there's not enough
* memory for it, find the largest amount available on the near heap
* and allocate that. This can't fail, no matter what the memory model.
*/
if( (buf = (char *)malloc( (size_t)count )) == NULL )
{
count = _memmax();
if( (buf = (char *)malloc( (size_t)count )) == NULL )
{
show_error("Cannot allocate memory for copy");
return ENOMEM;
}
}
/* Read-write until there's nothing left. */
while( !eof( hsource ) )
{
/* Read and write input. */
if( (count = read( hsource, buf, count )) == -1 )
return errno;
if( (count = write( htarget, buf, count )) == - 1 )
return errno;
}
/* Close files and release memory. */
close( hsource );
close( htarget );
free( buf );
return 0;
}
/**************************************************************************
display file contents page by page on screen
*/
int show_file(char *filename)
{
FILE *stream;
int key;
int line;
char buf[85];
if ((stream=fopen(filename,"rt")) == NULL )
{
show_error("Cannot show this file ");
return FAILURE;
}
_settextcolor( (short) file_color );
_setbkcolor( (long) screen_bg_color );
_clearscreen( _GWINDOW );
_settextposition( 1, 1 );
line=0;
while (fgets( buf, 80, stream ))
{
line++;
_outtext(buf);
if (line==20)
{
line=0;
_settextcolor( (short) prompt_text_color );
_outtext("*** Press Esc to cancel, any other key to continue ***");
_settextcolor( (short) file_color );
if ((key=getkey())==ESC) break;
_outtext("\n");
}
}
if (key!=ESC)
{
_settextcolor( (short) prompt_text_color );
_outtext("\n*** Press any key to continue ***");
getkey();
}
fclose(stream);
_settextcolor( (short) file_color );
return SUCCESS;
}
/***************************************************************************
Displays common edit screen
Returns FALSE if ESCaped
*/
int edit(char *title, char *string, int length , char *illegal)
{
char scratch[_MAX_PATH];
short x,y;
char b[(5*53)+10]={ /* Buffer for string */
"╔══════════════════════════════════════════════════╗\n"
"║ ║\n"
"╟──────────────────────────────────────────────────╢\n"
"║ ║\n"
"╚══════════════════════════════════════════════════╝\n"
};
int result;
char *savedscreen;
strcpy(scratch,string);
savedscreen=saveScrn();
y = ((25 - 5) / 2) + 1; /* 5 lines */
x = (80 - 52) / 2; /* 52 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 + 5, x + 52 );
shadebox( y, x, y + 5 - 1, x + 52 - 1 );
outtextm( b );
_settextposition( 2, 3 );
outtextm(title);
if (editstring(4, 3, scratch, illegal , length))
{
strcpy(string,scratch);
result=TRUE;
}
else result=FALSE;
_settextwindow( 3, 1, 23, 80 );
_setbkcolor( (long) screen_bg_color );
savedscreen=restScrn(savedscreen);
return result;
}
/**************************************************************************
Converting from TC style
*/
void movmem(void *src, void *dest, unsigned length)
{
memmove(dest, src, length);
}
/***************************************************************************
Returns ASCII or scancode + 256 if no ASCII
*/
int getkey(void)
{
int kread = _KEYBRD_READ;
int kready = _KEYBRD_READY;
int kshiftstatus = _KEYBRD_SHIFTSTATUS;
unsigned key;
int lo, hi;
/* If bit 4 of the byte at 0x0040:0x0096 is set, the new keyboard
* is present.
*/
if( peek( 0x00400096 ) & 0x10 )
{
kread = _NKEYBRD_READ;
kready = _NKEYBRD_READY;
kshiftstatus = _NKEYBRD_SHIFTSTATUS;
}
key=_bios_keybrd( kread );
lo = key & 0X00FF;
hi = (key & 0XFF00) >> 8;
return((lo == 0 || lo == 0xE0 ) ? hi + 256 : lo);
}
/****************************************************************************
Changes the text cursor shape based on the current insert mode
*/
void changecursor(int insmode)
{
if (insmode)
setcursor( 0x090C);
else setcursor(0x0A0C);
} /* changecursor */
/***************************************************************************
Sets the shape of the text cursor
*/
void setcursor(unsigned int shape)
{
union REGS reg;
reg.h.ah = 1;
reg.x.cx = shape;
int86(0X10, ®, ®);
} /* setcursor */
/****************************************************************************
Allows the user to edit a string with only certain characters allowed -
Returns TRUE if ESC was not pressed, FALSE is ESC was pressed.
*/
int editstring(int row, int col, char *s, char *illegal, int maxlength)
{
int c, len = strlen(s), pos = len;
static int insert=TRUE;
register int tel;
int mouse_row, mouse_col;
int ulc_row, ulc_col, dummy; /* upper left corner row and column of window */
int update=TRUE;
changecursor(insert);
_gettextwindow(&ulc_row,&ulc_col,&dummy,&dummy); /* mouse coordinates are absolute! */
do
{
if (update)
{
_settextposition( row, col );
hide_mouse();
_outtext(s);
for (tel=len;tel<=maxlength;tel++) _outtext(" ");
show_mouse();
_settextposition( row, col + pos );
update=FALSE;
}
if (mouse_present)
if (read_left_button_queue(&mouse_row,&mouse_col))
{
if (((mouse_row-ulc_row+1)==row) &&
((mouse_col-ulc_col+1)<=(col+len)) &&
((mouse_col-ulc_col+1)>=col))
{
pos=(mouse_col-ulc_col+1)-col;
update=TRUE;
} else alert();
}
if (n_kbhit())
{
update=TRUE;
switch(c = getkey())
{
case K_HOME:
pos = 0;
break;
case K_END:
pos = len;
break;
case K_INS:
insert = !insert;
changecursor(insert);
break;
case K_CLE:
if (pos > 0)
pos--;
break;
case K_CRI:
if (pos < len)
pos++;
break;
case BS :
if (pos > 0)
{
movmem(&s[pos], &s[pos - 1], len - pos + 1);
pos--;
len--;
}
break;
case K_DEL:
if (pos < len)
{
movmem(&s[pos + 1], &s[pos], len - pos);
len--;
}
break;
case CR :
break;
case ESC :
len = 0;
break;
default :
if (((illegal[0] == 0) || (strchr(illegal, c) == NULL)) &&
((c >= ' ') && (c <= '~')))
{
if (insert && len < maxlength)
{
memmove(&s[pos + 1], &s[pos], len - pos + 1);
len++;
s[pos++] = (char) c;
}
if (!insert && pos < maxlength)
{
if ((pos >= len) && (len < maxlength)) len++;
s[pos++] = (char) c;
}
}
break;
} /* switch */
}
s[len] = 0;
}
while ((c != CR) && (c != ESC));
changecursor(FALSE);
setcursor(0x2000);
return(c != ESC);
} /* editstring */
/****************************************************************************
save screen image , return pointer to allocated memory
*/
char *saveScrn (void)
{
unsigned srcSeg;
char *saveArea;
struct videoconfig vc;
struct SREGS segregs;
segread( &segregs );
saveArea = (char *) malloc (4096); /* alloceer ruimte */
if (!saveArea)
{
show_error("Cannot allocate memory for screen save");
return (char *) 0L;
}
_getvideoconfig( &vc );
if (vc.mode== _TEXTMONO)
srcSeg = 0xB000; /* monochroom scherm */
else
srcSeg = 0xB800; /* grafische text buffer */
hide_mouse();
movedata (srcSeg, 0, segregs.ss, (unsigned) saveArea, 4096);
show_mouse();
return (saveArea); /* return pointer !!!! */
}
/***************************************************************************
restore screen if saveArea != NULL
Return NULL pointer for update of saveArea to prevent multiple restores
Memory is freed so else garbage would be restored if saveScrn and restScrn
are not balanced
*/
char *restScrn(char *saveArea)
{
unsigned destSeg;
struct videoconfig vc;
struct SREGS segregs;
if (!saveArea) return (char *) 0L;
segread( &segregs );
_getvideoconfig( &vc );
if (vc.mode== _TEXTMONO)
destSeg = 0xB000;
else
destSeg = 0xB800;
hide_mouse();
movedata ( segregs.ss, (unsigned) saveArea, destSeg, 0, 4096);
show_mouse();
free (saveArea);
return (char *) 0L;
}
/****************************************************************************
Display current drive and working directory
*/
void show_path( void ) /* this HAS some impact, searches disk on each call */
{
char linebuf[_MAX_PATH];
strcpy(linebuf,"");
if (!_getdcwd( _getdrive(), linebuf, _MAX_PATH )) strcpy(linebuf,"");
strlwr(linebuf);
if (strlen(linebuf) >= 54)
{
linebuf[53]='';
linebuf[54]='\0';
}
strcat(linebuf,"╞");
while (strlen(linebuf)<56) strcat(linebuf,"═");
_settextposition( 1, 15 );
_settextcolor( (short) file_color );
_setbkcolor( (long) screen_bg_color );
outtextm(linebuf);
}
/***************************************************************************
Check a full filename on illegal characters, name length, extension
length, drive letter
*/
int valid_filename( char *newname)
{
char linebuf[_MAX_PATH];
char *chrpointer;
char illegal[20]={"\" +=[];|,<>/?*\\"};
int length;
register int teller;
strcpy(linebuf,newname);
if (strchr(illegal, linebuf[strlen(linebuf)-1])) return FALSE; /* check last character */
if (strchr(linebuf,':')) /* check drive */
{
if ((strchr(linebuf, ':') - linebuf)!=1) return FALSE; /* check place of : */
linebuf[0] = (char) tolower((int) linebuf[0]);
if ((linebuf[0] < 'a') || (linebuf[0] > 'z')) return FALSE;
strcpy(linebuf,linebuf+2); /* remove drive */
}
chrpointer = strtok( linebuf, "\\" ); /* Find first token */
while( chrpointer != NULL )
{
chrpointer = strchr(linebuf,'.'); /* check extension */
if (chrpointer)
{
if ((length=strlen(chrpointer+1))>3) return FALSE; /* check size */
for (teller=0;teller<length;teller++)
if (strchr(illegal, *(chrpointer + 1 + teller))) return FALSE; /* check each character */
*chrpointer = '\0'; /* remove extension */
}
chrpointer = strrchr(linebuf,'\\'); /* check name */
if (!chrpointer) chrpointer=linebuf; /* no slash, start with first character */
if (chrpointer)
{
if ((length=strlen(chrpointer+1))>8) return FALSE; /* check size */
for (teller=0;teller<length;teller++)
if (strchr(illegal, *(chrpointer + 1 + teller))) return FALSE; /* check each character */
*chrpointer = '\0'; /* remove name */
}
chrpointer = strtok( NULL, "\\" ); /* Find next token */
}
return TRUE;
}
/***************************************************************************
Build a string with disk space free on current drive
*/
int freespace( char *linebuf )
{
int lastdrive;
char scratch[_MAX_PATH];
struct diskfree_t drvinfo;
register int tel;
int tel2;
dos_error=0;
dos_retries=0;
lastdrive = _getdrive();
if (!drvalid(lastdrive-1)) return FAILURE;
_dos_getdiskfree( lastdrive, &drvinfo ); /* try to access the disk */
if (dos_error) return FAILURE;
sprintf( scratch,"%ld",
(long)drvinfo.avail_clusters *
drvinfo.sectors_per_cluster *
drvinfo.bytes_per_sector );
strrev( scratch );
linebuf[0]='\0';
tel2=0;
for (tel=0;tel<(int) strlen(scratch);tel++)
{
if (tel && !(tel%3)) linebuf[tel2++]=','; /* thousands separator */
linebuf[tel2++]=scratch[tel];
}
if (linebuf[tel2-1]==',') linebuf[tel2-1]='\0'; /* blank trailing ',' */
else linebuf[tel2]='\0'; /* terminate string */
strrev( linebuf );
strcpy( scratch,linebuf );
strcpy( linebuf," Disk space free: ");
strcat( linebuf,scratch );
strcat( linebuf," " );
return SUCCESS;
}
void working( int mode )
{
_settextposition( 1, 1 );
_settextcolor( (short) file_color );
_setbkcolor( screen_bg_color );
if (mode) outtextm( "" );
else outtextm( "╔" );
}
/***************************************************************************
* Put shading under and at the right side of a box, if in COLOR mode
*/
void shadebox( short r1, short c1, short r2, short c2 )
{
struct videoconfig vc;
short int row, col;
_getvideoconfig( &vc );
if (vc.mode== _TEXTMONO) return; /* monochroom scherm */
hide_mouse();
for (row=r1+1;row<=r2+1;row++)
{
shadechar(row,c2+1);
shadechar(row,c2+2);
}
for (col=c1+1;col<=c2+1;col++) shadechar(r2+1,col);
show_mouse();
}
/***************************************************************************
* Direct video write, shade a character
*/
#define MAKELONG(a, b) ((long)(((unsigned)a) \
| ((unsigned long)((unsigned)b)) << 16))
#define COLORTEXT_BUFFER 0XB800
void shadechar( int row, int col )
/* row : row of location 1 to 25 */
/* col : column of location 1 to 80 */
/* attrib : standard character attribute */
{
unsigned int offset; /* Offset from the segment address of
the desired video page */
char far *y; /* Long Pointer to the position in memory
where we will put the character and
it's attribute (next byte) */
int pageno; /* page number to load character into (0 to 3) */
char attrib; /* standard character attribute */
pageno=0;
attrib=0x08; /* background=black, textcolor=dark grey */
row--; /* coord 1,1 is 0,0 for the function logic */
col--;
if (row<0 || row >24) return; /* clip to screen boundary */
if (col<0 || col >79) return;
/* Calc the in-page offset w/page number offset and segment address */
offset = (unsigned int) ((row * 160 )+(col*2)+(pageno*4096));
/* Set the attribute byte. See a DOS programmers reference for
more information on video attributes. */
offset++;
y = (char far *)MAKELONG( offset, COLORTEXT_BUFFER);
*y = attrib;
}
/* set working drive and directory and return a pointer to the first
* character of the filename
*/
char *set_working_drive_and_dir( char *full_filename )
{
char scratch[_MAX_PATH];
char *slash;
strcpy(scratch,full_filename); /* make drive & dir default */
strupr(scratch);
if (slash=strrchr(scratch, (int) '\\')) *slash='\0'; /* remove filename */
else if (slash=strrchr(scratch, (int) ':')) *slash='\0'; /* maybe in format A:FILE.EXT */
if (strlen(scratch)==1) strcat(scratch,":"); /* top directory ? */
if (strlen(scratch)==2) strcat(scratch,"\\"); /* top directory ? */
if (scratch[1]==':') _chdrive(scratch[0]-'A'+1);
chdir(scratch);
/* find filename */
if (slash=strrchr(full_filename, (int) '\\')) return slash+1; /* in format A:\FILE.EXT */
else if (slash=strrchr(scratch, (int) ':')) return slash+1; /* maybe in format A:FILE.EXT */
return 0L;
}
/**************************************************************************
Change to parent directory and place cursor
*/
void find_parent( int *current_page, int *filenumber, char *searchstring)
{
register int counter;
char linebuf[_MAX_PATH];
char *p;
_getdcwd( _getdrive(), linebuf, _MAX_PATH );
if (p=strrchr(linebuf,'\\'))
{
memmove( linebuf, p+1, strlen(p+1)+1);
} else return; /* do nothing */
if (!strlen(linebuf)) return; /* do nothing, already in root */
chdir( ".." );
extract_directory( searchstring );
if (!number_of_files)
{
*current_page=0;
*filenumber=1;
}
else
{
for (counter=1;counter<number_of_files;counter++) /* should end at last file */
if (!strcmp(find[counter].name,linebuf)) break;
*filenumber=counter;
*current_page=((counter%114) ? counter/114 : counter/114 - 1);
}
}
/*
** DRVALID.C - validate disk drives
** Original Copyright 1988-1991 by Bob Stout as part of
** the MicroFirm Function Library (MFL)
**
** This subset version is functionally identical to the
** version originally published by the author in Tech Specialist
** magazine and is donated to the public domain.
*/
/*
** getdrv()
**
** Just as getcwd() returns the default directory, getdrv() returns
** the current drive.
**
** Arguments: None.
**
** Returns: Current drive (0 = A:, 1 = B:, etc.)
**
** Side effects: none
*/
int getdrv(void)
{
union REGS regs;
regs.h.ah = 0x19;
intdos(®s, ®s);
return (regs.h.al);
}
/*
** chdrv()
**
** Like chdir(), except changes drives rather than directories.
**
** Arguments: 1 - target drive (0 = A:, 1 = B:, etc.)
**
** Returns: SUCCESS or ERROR
**
** Side effects: none
*/
int chdrv(int drive)
{
union REGS regs;
regs.h.ah = 0x0e;
regs.h.dl = (char)drive;
intdos(®s, ®s);
if (drive != getdrv())
return ERROR;
else return SUCCESS;
}
/*
** drvalid()
**
** Verifies whether a logical disk drive is available without
** triggering the DOS critical error handler.
**
** Arguments: 1 - target drive (0 = A;, 1 = B:, etc.)
**
** Returns: TRUE - drive is valid
** FALSE - drive is invalid
**
** Side effects: none
*/
int drvalid(int drive)
{
int original, result;
original = getdrv();
result = (SUCCESS == chdrv(drive));
chdrv(original);
return result;
}
void ScrPutS (char *String, unsigned char Attr,
unsigned char Row, unsigned char Col)
{
register unsigned char A;
unsigned char far *PtrVideoMode = (unsigned char far *) 0x00400049;
unsigned char far *Video;
A = Attr;
FP_SEG (Video) = (*PtrVideoMode == 7) ? 0xb000 : 0xb800;
FP_OFF (Video) = Row*160+Col*2;
while (*String)
{
*Video++ = *String++;
*Video++ = A;
}
}
/* Ask for a drive */
/* In: key a..z pressed */
/* Out: drive number A=1, B=2 etc. or -1 if ESCaped */
int ask_drive_number( char * message)
{
int key;
do
{
_settextposition( 23, 25 );
_settextcolor( (short) prompt_text_color );
outtextm(message);
_settextcolor( (short) file_color );
_settextposition( 1, 1 ); /* prevent scroll-up from dos error */
key = getkey();
if (key<256) key = tolower(key);
} while (((key < 'a') || (key > 'z')) &&(key != ESC));
if (key!=ESC) return ( key - 'a' + 1);
else return -1;
}