/*
* TREE command for MS-DOS
*
* This command is virtually identical to the MS-DOS TREE command,
* except that it expands the current directory path instead of
* showing '.' in the display.
*
* Copyright 1995 Dave Dunfield
* Freely distributable.
*/
#include <stdio.h>
#include <file.h>
#define DIRS 500 /* Depth of directory stacking */
#define DEPTH 50 /* Depth of scanner recursion */
char
*parg = 0, /* Path argument */
path[66], /* Final path specification */
full = 0, /* Full listing specified */
dirstack[DIRS][13], /* Stack of directory names */
*actstack[DEPTH]; /* Stack of active levels */
char
*Vline = "\xB3\x20\x20", /* Vertical line */
*Vtee = "\xC3\xC4\xC4", /* Vertical/Horizonal tee */
*Corn = "\xC0\xC4\xC4", /* Vertical/Horizontal corner */
*Hline = "\xC4\xC4\xC4"; /* Horisontal line */
unsigned
dirptr = 0, /* Directory stacking level */
level = 0; /* Function recursion level */
static char help_text[] = { "\n\
Graphically displays the directory structure of a drive or path.\n\n\
TREE [drive:][path] [/F] [/A]\n\n\
/F Displays the names of the files in each directory.\n\
/A Uses ASCII instead of extended characters.\n\n\
Copyright 1995 Dave Dunfield - Freely distributable.\n" };
/*
* Handle a single directory, recurse to do others
*/
void tree_path(void)
{
unsigned plen, dirbase, i, j, k, attrs;
char name[13], *ptr;
/* Get all sibdirectory names in this dir */
dirbase = dirptr;
plen = strlen(path);
strcpy(path+plen, "*.*");
if(!find_first(path, -1, name, &k, &k, &attrs, &k, &k)) do {
if((attrs & DIRECTORY) && (*name != '.')) {
strcpy(dirstack[dirptr++], name);
continue; } }
while(!find_next(name, &k, &k, &attrs, &k, &k));
/* Display files in this dir if required */
actstack[level++] = (dirbase == dirptr) ? " " : Vline;
if(full) {
i = 0;
if(!find_first(path, -1, name, &k, &k, &attrs, &k, &k)) do {
if(attrs & (DIRECTORY|VOLUME))
continue;
for(j=0; j < level; ++j)
fputs(actstack[j], stdout);
i = -1;
printf("%s\n", name); }
while(!find_next(name, &k, &k, &attrs, &k, &k));
if(i) {
for(j=0; j < level; ++j)
fputs(actstack[j], stdout);
putc('\n', stdout); } }
/* Report of no subdirectories exist */
if((dirbase == dirptr) && (level == 1))
printf("No sub-directories exist\n");
/* Recurse into subdirectories */
for(i=dirbase; i < dirptr; ++i) {
actstack[level-1] = ((i+1) != dirptr) ? Vtee : Corn;
for(j=0; j < level; ++j)
fputs(actstack[j], stdout);
actstack[level-1] = ((i+1) != dirptr) ? Vline : " ";
printf("%s\n", ptr = dirstack[i]);
strcpy(path+plen, ptr);
strcat(path, "\\");
tree_path(); }
/* Restore entry conditions and exit */
path[plen] = 0;
dirptr = dirbase;
--level;
}
/*
* Main program - parse arguments & start recursive procedure
*/
main(int argc, char *argv[])
{
int i;
char *ptr, c;
for(i=1; i < argc; ++i) {
ptr = argv[i];
while(*ptr) switch (c = *ptr++) {
case '/' : /* Option switch */
switch(c = toupper(*ptr++)) {
case 'A' : /* Ascii - switch BOX characters */
Vline = "| ";
Vtee = "+--";
Corn = "\\--";
Hline = "---";
continue;
case 'F' : /* Select FULL mode */
full = -1;
continue;
case '?' : /* Help request */
fputs(help_text, stdout);
exit(0); }
printf("Invalid switch - /%c\n", c);
exit(-1);
default: /* Pathname */
if(parg) {
printf("Too many parameters - %s\n", argv[i]);
exit(-1); }
parg = argv[i];
ptr = ""; } }
/* If no path specified, default to current */
if(!parg) {
*(parg = help_text) = '\\';
getdir(help_text+1); }
/* If no drive name specified, obtain current drive */
if(parg[1] == ':')
strcpy(path, parg);
else {
*path = get_drive() + 'A';
path[1] = ':';
strcpy(path+2, parg); }
/* Display volume label of disk */
printf("Directory PATH listing");
*help_text = *path;
strcpy(help_text+1, ":\\*.*");
if(!find_first(help_text, VOLUME, ptr = help_text, &i, &i, &i, &i, &i)) {
printf(" for volume ");
while(c = *ptr++)
if(c != '.')
putc(c, stdout); }
/* Display path and append backslash if not given */
printf("\n%s\n", path);
switch(path[strlen(path)-1]) {
default:
strcat(path, "\\");
case ':' :
case '\\' : }
/* Perform recursive function */
tree_path();
}