From Code to Community: Sponsoring The Perl and Raku Conference 2025 Learn more

/*---------------------------------------------------------*/
/* */
/*---------------------------------------------------------*/
/*
* Turbo Vision - Version 2.0
*
* Copyright (c) 1994 by Borland International
* All Rights Reserved.
*
*/
#define Uses_TKeys
#define Uses_TApplication
#define Uses_TEvent
#define Uses_TRect
#define Uses_TDialog
#define Uses_TStaticText
#define Uses_TButton
#define Uses_TMenuBar
#define Uses_TSubMenu
#define Uses_TMenuItem
#define Uses_TStatusLine
#define Uses_TStatusItem
#define Uses_TStatusDef
#define Uses_TDeskTop
#define Uses_TOutline
#define Uses_TScrollBar
#define Uses_TParamText
#define Uses_TScreen
#define Uses_TText
#include <tvision/tv.h>
#include <dos.h>
#include <string.h>
#include <stdio.h>
#include <strstrea.h>
const int cmDirTree = 100;
const int cmAbout = 101;
const int cmNewDirFocused = 102;
#ifdef __BORLANDC__
// This is merely for aesthetic purposes.
#define sep "\\"
#else
#define sep "/"
#endif
class QuickMessage: public TWindow
{
TParamText *currentDir;
public:
QuickMessage( const char *drive ):
TWindowInit( TWindow::initFrame ),
TWindow( TRect( 15,8,65,19 ), "Please Wait...", 0 ) {
flags = 0; // no move, close, grow or zoom
options |= ofCentered;
palette = wpGrayWindow;
char temp[64];
ostrstream os( temp, sizeof( temp ) );
os << "Scanning Drive '" << drive << "'\n" << ends;
insert( new TStaticText( TRect( 2,2,48,3 ), temp ) );
currentDir = new TParamText( TRect( 2,3,48,9 ) );
insert( currentDir );
}
virtual void handleEvent( TEvent &event ) {
TWindow::handleEvent( event );
}
void setCurrentDir( char *newDir ) {
currentDir->setText( newDir );
TScreen::flushScreen();
}
};
class TDirOutline: public TOutline {
public:
TDirOutline( const TRect &bounds, TScrollBar *hsb, TScrollBar *vsb, TNode *root ):
TOutline( bounds, hsb, vsb, root ) {}
virtual void focused( int i ) {
foc=i;
message( owner, evCommand, cmNewDirFocused, 0 );
}
static Boolean isParent( TOutlineViewer *, TNode *cur, int, int, long, ushort, void * );
TNode *getParent( TNode *child ) {
return firstThat( isParent, child );
}
void getCurrentPath( char *buffer, short bufferSize );
};
Boolean TDirOutline::isParent( TOutlineViewer *, TNode *cur, int, int, long, ushort, void *arg ) {
TNode *parentSearch = (TNode*)arg;
TNode *temp = cur->childList;
while (temp!=0) {
if (temp==parentSearch)
return True;
temp=temp->next;
}
return False;
}
void TDirOutline::getCurrentPath( char *buffer, short bufferSize ) {
char temp1[128], temp2[128];
TNode *current = getNode( foc );
TNode *root = getRoot();
temp1[0] = 0;
temp1[sizeof(temp1) - 1] = 0;
temp2[sizeof(temp2) - 1] = 0;
buffer[bufferSize - 1] = 0;
while (current!=root) {
strncpy(temp2, temp1, sizeof(temp2) - 1);
strncpy(temp1, current->text, sizeof(temp1) - 1);
strncat(temp1, sep, sizeof(temp1) - 1);
strncat(temp1, temp2, sizeof(temp1) - 1);
current = getParent( current );
}
strncpy(buffer, root->text, bufferSize - 1);
char last = buffer[strlen(buffer) - 1];
if (last != '/' && last != '\\')
strncat(buffer, sep, bufferSize - 1);
strncat(buffer, temp1, bufferSize - 1);
}
TNode *getDirList( const char *path, QuickMessage *qm = 0 ) {
TNode *dirList = 0,
*current = 0;
char searchPath[128] = {0};
find_t searchRec;
int result;
TNode *temp;
ostrstream os( searchPath, sizeof( searchPath )-1 );
os << path << sep "*.*" << ends;
result = _dos_findfirst( searchPath, 0xff, &searchRec );
while (result==0) {
if (searchRec.name[0]!='.') {
if (searchRec.attrib & FA_DIREC) {
os.seekp(0);
os << path << *sep << searchRec.name << ends;
// Strings may become equal when searchPath is full.
if (strcmp(path, searchPath) == 0)
break;
qm->setCurrentDir(searchPath);
temp = new TNode( searchRec.name, getDirList(searchPath,qm), 0, False );
if (current) {
current->next = temp;
current=current->next;
} else
current = dirList = temp;
}
}
result = _dos_findnext( &searchRec );
}
return dirList;
}
class TFilePane: public TScroller {
char **files;
short fileCount;
public:
TFilePane( const TRect &bounds, TScrollBar *hsb, TScrollBar *vsb ):
TScroller( bounds, hsb, vsb ) {
fileCount=0;
files=0;
}
~TFilePane() {
deleteFiles();
}
void newDir( const char *path );
virtual void draw();
void deleteFiles();
};
void TFilePane::draw() {
TDrawBuffer dBuf;
short i;
for (i=0;i<size.y;i++) {
dBuf.moveChar(0, ' ', getColor(0x0101), (short)size.x );
if ((fileCount==0)&&(i==0))
dBuf.moveStr( 2, "<no files>", getColor(0x0101) );
if ((i+delta.y)<fileCount)
dBuf.moveStr( 2, files[i+delta.y], getColor(0x0101), (short)size.x, (short)delta.x );
writeLine( 0, i, (short)size.x, 1, dBuf );
}
}
static char *formatFileRow( char buf[128], const find_t &searchRec ) {
sprintf(buf, " %8ld %2d-%02d-%02d %2d:%02d %c%c%c%c",
(long) searchRec.size,
((searchRec.wr_date & 0x01E0) >> 5),
(searchRec.wr_date & 0x001F),
((searchRec.wr_date >> 9)+1980)%100,
((searchRec.wr_time & 0xF800) >> 11)%13,
((searchRec.wr_time & 0x07E0) >> 5),
searchRec.attrib & FA_ARCH ? 'a' : '\xFA',
searchRec.attrib & FA_RDONLY ? 'r' : '\xFA',
searchRec.attrib & FA_SYSTEM ? 's' : '\xFA',
searchRec.attrib & FA_HIDDEN ? 'h' : '\xFA');
size_t bufLen = strlen(buf) + 1;
size_t nameLen, nameWidth;
TText::scroll( searchRec.name, 18, False, nameLen, nameWidth );
size_t namePad = 18 - nameWidth;
char *row = new char[nameLen + namePad + bufLen];
memcpy( row, searchRec.name, nameLen );
memset( row + nameLen, ' ', namePad );
memcpy( row + nameLen + namePad, buf, bufLen );
return row;
}
void TFilePane::newDir( const char *path ) {
char searchPath[128] = {0};
find_t searchRec;
int result;
short i;
deleteFiles();
ostrstream os( searchPath, sizeof( searchPath )-1 );
os << path << "*.*" << ends;
result = _dos_findfirst( searchPath, 0xff, &searchRec );
while (result==0) {
if (!(searchRec.attrib & FA_DIREC))
fileCount++;
result=_dos_findnext( &searchRec );
}
files = new char *[fileCount];
result = _dos_findfirst( searchPath, 0xff, &searchRec );
i=0;
while (result==0) {
if (!(searchRec.attrib & FA_DIREC))
files[i++] = formatFileRow( searchPath, searchRec );
result=_dos_findnext( &searchRec );
}
if (fileCount==0)
setLimit( 1, 1 );
else
setLimit( strwidth(files[0]) + 2, fileCount );
drawView();
}
void TFilePane::deleteFiles() {
short i;
for (i=0;i<fileCount;i++)
delete[] files[i];
delete[] files;
fileCount=0;
}
class TDirWindow: public TWindow {
char *drive;
TNode *dirTree;
TDirOutline *ol;
TFilePane *fp;
TScrollBar *hsb, *vsb;
public:
TDirWindow( const char *driveInit ):
TWindowInit( TWindow::initFrame ),
TWindow( TRect( 1,1,76,21 ), driveInit, 0 ) {
drive = newStr( driveInit );
vsb = new TScrollBar( TRect( 74,1,75,15 ) );
hsb = new TScrollBar( TRect( 22,15,73,16 ) );
fp = new TFilePane( TRect( 21,1,74,15 ), hsb, vsb );
fp->options |= ofFramed;
fp->growMode = gfGrowHiY | gfGrowHiX | gfFixed;
insert( hsb );
insert( vsb );
insert( fp );
vsb = new TScrollBar( TRect( 20,1,21,19 ) );
hsb = new TScrollBar( TRect( 2,19,19,20 ) );
QuickMessage *qm = new QuickMessage( drive );
TProgram::deskTop->insert( qm );
dirTree = new TNode( drive, getDirList( drive, qm ), 0, True );
TProgram::deskTop->remove( qm );
destroy(qm);
ol = new TDirOutline( TRect( 1,1,20,19 ), hsb, vsb, dirTree );
ol->options |= ofFramed;
ol->growMode = gfGrowHiY | gfFixed;
vsb->growMode = gfGrowHiY;
hsb->growMode = gfGrowHiY | gfGrowLoY;
insert( hsb );
insert( vsb );
insert( ol );
char path[128];
ol->getCurrentPath( path, 128 );
fp->newDir( path );
}
~TDirWindow() {
delete[] drive;
}
virtual void handleEvent( TEvent &event ) {
char buffer[128];
if ((event.what == evCommand) &&
(event.message.command == cmNewDirFocused )) {
ol->getCurrentPath(buffer,128);
fp->newDir(buffer);
delete[] (char *) title;
title = newStr(buffer);
clearEvent(event);
((TView *)frame)->drawView();
}
TWindow::handleEvent( event );
}
virtual void sizeLimits( TPoint &min, TPoint &max ) {
min.x = 40;
min.y = 10;
max = owner->size;
}
};
class TDirApp : public TApplication
{
char *drive;
public:
TDirApp( const char *driveInit );
~TDirApp();
virtual void handleEvent( TEvent& event );
static TMenuBar *initMenuBar( TRect );
static TStatusLine *initStatusLine( TRect );
void aboutBox( void );
};
TDirApp::TDirApp( const char *driveInit ) :
TProgInit( &TDirApp::initStatusLine,
&TDirApp::initMenuBar,
&TDirApp::initDeskTop
)
{
drive = newStr(driveInit);
insertWindow( new TDirWindow( driveInit ) );
}
TDirApp::~TDirApp()
{
delete[] drive;
}
void TDirApp::handleEvent( TEvent& event )
{
TApplication::handleEvent( event );
if( event.what == evCommand )
{
switch( event.message.command )
{
case cmAbout:
aboutBox();
clearEvent( event );
break;
case cmDirTree:
insertWindow( new TDirWindow( drive ) );
clearEvent( event );
break;
default:
break;
}
}
}
TMenuBar *TDirApp::initMenuBar( TRect r )
{
r.b.y = r.a.y+1;
return new TMenuBar( r,
*new TSubMenu( "~\xF0~", kbAltSpace ) +
*new TMenuItem( "~A~bout...", cmAbout, kbAltA ) +
*new TSubMenu( "~F~ile", kbAltF ) +
*new TMenuItem( "~N~ew Window...", cmDirTree, kbAltN ) +
newLine() +
*new TMenuItem( "E~x~it", cmQuit, cmQuit, hcNoContext, "Alt-X" )
);
}
TStatusLine *TDirApp::initStatusLine( TRect r )
{
r.a.y = r.b.y-1;
return new TStatusLine( r,
*new TStatusDef( 0, 0xFFFF ) +
*new TStatusItem( "~Alt-X~ Exit", kbAltX, cmQuit ) +
*new TStatusItem( 0, kbF10, cmMenu )
);
}
void TDirApp::aboutBox( void ) {
TDialog *aboutBox = new TDialog(TRect(0, 0, 39, 11), "About");
aboutBox->insert(
new TStaticText(TRect(9, 2, 30, 7),
"\003Outline Viewer Demo\n\n" // These strings will be
"\003Copyright (c) 1994\n\n" // The \003 centers the line.
"\003Borland International"
)
);
aboutBox->insert(
new TButton(TRect(14, 8, 25, 10), " OK", cmOK, bfDefault)
);
aboutBox->options |= ofCentered;
executeDialog(aboutBox);
}
int main( int argc, char *argv[] )
{
TDirApp *dirApp = new TDirApp( argc == 2 ? argv[1] : ".");
dirApp->run();
TObject::destroy(dirApp);
return 0;
}