home *** CD-ROM | disk | FTP | other *** search
/ Zodiac Super OZ / MEDIADEPOT.ISO / FILES / 16 / FREEDOS.ZIP / FD_A4PRE.ZIP / SOURCE / MICROC.ZIP / TREE.C < prev    next >
C/C++ Source or Header  |  1995-06-23  |  8KB  |  319 lines

  1. /*
  2.     tree - A graphical directory path lister.
  3.     Copyright (C) 1995 Robert C. Schanke
  4.  
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation; either version 2 of the License, or
  8.     (at your option) any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19.  
  20.  
  21. /*---------------------------- Include Files ------------------------------*/
  22.  
  23. #include <stdio.h>
  24. #include <file.h>
  25. #include "freedos.h"
  26.  
  27. /*--------------------------------- Defines -------------------------------*/
  28.  
  29. #define MAX_RECURSE 10
  30.  
  31. /*---------------------------- Global Variables ---------------------------*/
  32.  
  33. char current_dir[64];                /* String to hold the directory we are
  34.                      currently in. */
  35.  
  36. int eol[MAX_RECURSE];                /* End of List marker for sub-dirs */
  37.  
  38. struct FF_block nextfile[MAX_RECURSE]; /* One ahead file buffers */
  39.  
  40. int lastlevel;                       /* 'How far in where we' marker */
  41.  
  42. char drive;                          /* Char for drive & file path */
  43.  
  44. /*------------------------ Start of Code ----------------------------------*/
  45.  
  46. /*
  47. ** Standard usage routine ...
  48. */
  49.  
  50. void usage (void) {
  51.    printp ("TREE", "Graphical display of recursive sub-directories.");
  52.    printu ("TREE", "[directory]");
  53.    exit (1);
  54. }
  55.  
  56. /*
  57. ** print_list is the routine which draws the 'lines' for the subdirectories
  58. */
  59.  
  60. void print_list(char name[255], int level) {
  61.  
  62.    int cnt;                                 /* Our counter */
  63.  
  64.    for (cnt=0; cnt < level; cnt++)          /* move over to current level*/
  65.        if (!eol[cnt])                       /* Are dirs from above? */
  66.        printf("│   ");                  /* Yeah, draw the line */
  67.        else
  68.        printf("    ");                  /* No, just space over */
  69.  
  70.    if (!eol[level])                         /* Are ther more files here? */
  71.        printf("├───");                      /* Yeah, draw line down */
  72.    else
  73.        printf("└───");                      /* No, just draw accross */
  74.  
  75.    printf("%s\n",name);                     /* Print the name of the dir */
  76.  
  77.    lastlevel = level;                       /* Set new last level */
  78. }
  79.  
  80. /*
  81. ** build_tree routine is the heart of the program. It reads the directories
  82. ** into a one directory buffer. This buffer is so we can tell if we are
  83. ** at the last directory or not.
  84. */
  85.  
  86. void build_tree(char *dir, int recurse) {
  87.  
  88.  
  89.    char where[64];                          /* working directory name II */
  90.    struct FF_block file;                      /* Working directory physical */
  91.    char cur_dir[64];                        /* working directory name */
  92.  
  93.    int cnt;                                 /* counter */
  94.  
  95.    strcpy(where,dir);                       /* copy passed dir to where */
  96.    strcat(where,"*.*");                     /* append a *.* */
  97.  
  98. /*
  99. ** Get the first directory from this level. And set the end of list flag
  100. ** eol to 0 if end, -1 if more.
  101. */
  102.  
  103.  
  104.    eol[recurse] = findfirst(where, nextfile[recurse], DIRECTORY);
  105.  
  106. /*
  107. ** Keep reading until we find another sub directory. This will be
  108. ** the '..' directory.
  109. */
  110.  
  111.    if (!eol[recurse])
  112.    do {
  113.        eol[recurse] = findnext (nextfile[recurse]);
  114.    } while ((nextfile[recurse].FF_attrib != DIRECTORY) && (!eol[recurse]));
  115.  
  116. /*
  117. ** Keep reading until we find another sub directory. This will be
  118. ** the first to place in our buffer.
  119. */
  120.  
  121.    if (!eol[recurse])
  122.    do {
  123.        eol[recurse] = findnext(nextfile[recurse]);
  124.    } while ((nextfile[recurse].FF_attrib != DIRECTORY) && (!eol[recurse]));
  125.    else
  126.        printf("There are no sub-directories.\n");
  127.  
  128. /*
  129. ** Ok, if we didn't run out of subdirectories already, ie a hard disk
  130. ** with no subdirectories, lets go ahead and list them
  131. */
  132.  
  133.    if (!eol[recurse])
  134.  
  135. /*
  136. ** While we aren't at the end of the first one lets keep going
  137. */
  138.  
  139.    do {
  140.  
  141. /*
  142. ** get the next file from the buffer
  143. */
  144.  
  145.        memcpy (file, nextfile[recurse], sizeof(file));
  146.  
  147. /*
  148. ** Read next directory, or stop if we run out of them
  149. */
  150.  
  151.        do {
  152.       eol[recurse] = findnext (nextfile[recurse]);
  153.        } while ((nextfile[recurse].FF_attrib != DIRECTORY) && (!eol[recurse]));
  154.  
  155. /*
  156. ** Send the file to the print_list for formated output
  157. */
  158.  
  159.        print_list(file.FF_name,recurse);
  160.  
  161. /*
  162. ** Copy the the directory to the variable cur_dir
  163. */
  164.        strcpy(cur_dir,dir);
  165.  
  166. /*
  167. ** Append the next directory to cur_dir
  168. */
  169.  
  170.        strcat(cur_dir,file.FF_name);
  171. /*
  172. ** Append an '\' and a NULL to cur_dir
  173. */
  174.  
  175.        strcat(cur_dir,"\\\0");
  176.  
  177. /*
  178. ** Call build_dir again with the new cur_dir and new level
  179. */
  180.  
  181.        build_tree(cur_dir,recurse+1);
  182.  
  183.    } while (!eol[recurse]);
  184. }
  185.  
  186. /*
  187. ** Initialize variables
  188. */
  189.  
  190. void init(void) {
  191.  
  192. /*
  193. ** Initialize variables
  194. */
  195.  
  196.    eol[0] = 0;
  197.    lastlevel = 0;
  198. }
  199.  
  200. /*
  201. ** Function to extract the volume label, and display the header
  202. ** of output
  203. */
  204.  
  205. void header(void) {
  206.  
  207.    struct FF_block vol;                       /* Drive Volume structure */
  208.    char volume[13];                         /* String for drives Volume */
  209.    int cnt;                                 /* A counter */
  210.    char buf[6];
  211.  
  212. /*
  213. ** format the drive letter into the format x:\*.* where x is the drive letter.
  214. */
  215.    sprintf(buf,"%c:\*.*",drive);
  216.  
  217. /*
  218. ** Get the volume if the drive has one and put it into vol
  219. */
  220.  
  221.    eol[0] = findfirst(buf, vol, VOLUME);
  222.  
  223. /*
  224. ** If there was a volume, lets get rid of the . and make it one
  225. ** continuous 11 character string/
  226. */
  227.  
  228.    if (!eol[0]) {
  229.        if (strlen(vol.FF_name) > 8) {
  230.        for (cnt=0; cnt < 8; cnt++)
  231.            volume[cnt] = vol.FF_name[cnt];
  232.        for (cnt=9; cnt < 12; cnt++)
  233.            volume[cnt-1] = vol.FF_name[cnt];
  234.        } else
  235.       strcpy(volume,vol.FF_name);
  236.        volume[11] = '\0';
  237.    }
  238.  
  239. /*
  240. ** Ok, if we have a volume, let's print it out, otherwise don't
  241. ** worry about printint it out.
  242. */
  243.  
  244.    if (!eol[0])
  245.        printf("Directory PATH listing for Volume %s\n%c:.\n",volume,drive);
  246.    else
  247.        printf("Directory PATH listing\n%c:.\n",drive);
  248. }
  249.  
  250. /*
  251. ** The main function
  252. */
  253.  
  254. void main(int argc, char *argv[]) {
  255.  
  256. /*
  257. ** Did the user pass a /?
  258. */
  259.  
  260.    if ((argv[1][0] == '/') && (argv[1][1] == '?'))
  261.        usage();                             /* Yeah, so tell 'em how to use */
  262.  
  263.    if (argc == 1) {                         /* Did they pass something else? */
  264.  
  265.        getdir(current_dir);            /* No, get current directory */
  266.  
  267.        if (strlen(current_dir)==0)          /* if nothing, we are in root */
  268.        strcpy(current_dir,"\\\0");      /* format it out to '\' */
  269.        else {                               /* otherwise.... */
  270.        getdir(current_dir+1);      /* get it a 1 byte offset */
  271.        strcat(current_dir,"\\\0");      /* add a trailing '\' */
  272.        current_dir[0]='\\';             /* add a leading '\' */
  273.        }
  274.  
  275. /*
  276. ** Get the current logical disk number, and add 65 to get a drive letter
  277. */
  278.        drive = get_drive()+'A';
  279.    } else {                                 /* Something passed */
  280.  
  281.        strcpy(current_dir,argv[1]);         /* Move it to current_dir string */
  282.  
  283. /*
  284. ** If no trailing '\' put one on there.
  285. */
  286.  
  287.        if (current_dir[strlen(current_dir)-1] != '\\')
  288.       strcat(current_dir,"\\");
  289.  
  290. /*
  291. ** Extract drive letter from current_dir if it's given, otherwise return
  292. ** current drive letter.
  293. */
  294.  
  295.       if (current_dir[1] != ':')
  296.      drive = get_drive()+'A';
  297.       else
  298.      drive = current_dir[0];
  299.  
  300. /*
  301. ** If the drive letter was taken from current_dir and is lower case,
  302. ** make it upper case for looks.
  303. */
  304.  
  305.    if (drive > 96)
  306.        drive = (drive - 32);
  307.  
  308.    }
  309.  
  310.    init();                                  /* Initialize the variables */
  311.  
  312.    header();                                /* Display our header */
  313.  
  314.    build_tree(current_dir,0);               /* Start display tree at level 0 */
  315.  
  316.    exit(1);
  317. }
  318.  
  319.