home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / TREELIST.ZIP / TREELIST.PAS
Encoding:
Pascal/Delphi Source File  |  1989-03-20  |  13.4 KB  |  342 lines

  1. program TreeList;
  2.  
  3. (* The following program performs a systematic location of all sub-     *)
  4. (* directories, and displays a Tree-like relationship between the files *)
  5. (* and the subdirectories.                                              *)
  6. (*                                                                      *)
  7. (* A few things are assumed, but may be changed, such as: The maximum   *)
  8. (* number of files in a directory is 128, the deepest level of nested   *)
  9. (* subdirectories is 8, and the maximum number of subdirectories in a   *)
  10. (* single directory is 24.  All of these may be moved up or down, as    *)
  11. (* may be required.                                                     *)
  12. (*                                                                      *)
  13. (* The program as it is written requires the usage of Turbo Pascal 3.0  *)
  14. (* and the SORT.BOX file in the Turbo Toolbox.  The main reasons for    *)
  15. (* using these two are the inclusion of Directory routines and Command  *)
  16. (* line parameter routines in version 3.0 of Turbo Pascal.  Also, the   *)
  17. (* Sort routine in the Turbo Toolbox is indeed a gem.                   *)
  18. (*                                                                      *)
  19. (* The program Syntax is as follows:                                    *)
  20. (*                                                                      *)
  21. (*    TreeList [/P][/F][/L]  where P will print the output              *)
  22. (*                                 F will list Files with the SubDir's  *)
  23. (*                                 L will list Files in long form       *)
  24. (*                                                                      *)
  25. (* As the author of this program and many others, I would like to thank *)
  26. (* Borland International for a truly great Pascal Compiler and for the  *)
  27. (* guts to buck the tide of high price ripoffs.                         *)
  28. (*                                                                      *)
  29. (* This program is hereby donated to the Public Domain, it may be       *)
  30. (* copied, and distributed as you wish, as long as this section of the  *)
  31. (* code is not removed or changed.                                      *)
  32. (*                                                                      *)
  33. (* If you use this program and feel that it has in some way made your   *)
  34. (* time more valuable, a small donation may be made to:                 *)
  35. (*                                                                      *)
  36. (*        David W. Terry                                                *)
  37. (*        3036 Putnam Ct.                                               *)
  38. (*        West Valley City, UT 84120                                    *)
  39. (*                                                                      *)
  40. (*  Copyright (C) 1985  David W. Terry                                  *)
  41.  
  42. {$C-}
  43. type
  44.   str2  = string[2];
  45.   str6  = string[6];
  46.   str9  = string[9];
  47.   str12 = string[12];
  48.   str15 = string[15];
  49.   pathtype = string[62];
  50.   FileType = record
  51.                Name: str12;
  52.                Attrib: byte;
  53.                Size: real;
  54.                Date,Time: str9;
  55.                end;
  56.   ListType = array[1..128] of FileType;
  57.   Dirtype  = array[1..8] of record
  58.                Total: byte;
  59.                Name: array[1..24] of PathType;
  60.                end;
  61.   regpack  = record
  62.                ax,bx,cx,dx,bp,si,di,ds,es,flags:integer
  63.                end;
  64. var
  65.   List,SortedList: ListType;
  66.   DirList: DirType;
  67.   DirPos,DirTotal: array[1..10] of byte;
  68.   Path: pathtype;
  69.   Total,Counter,DirLevel: byte;
  70.   recpack: regpack;
  71.   Dircty,DiskLabel,PrnLabel,Prt,Long,ShowFiles: boolean;
  72.   Spacer,Tail,LongStr: string[80];
  73.  
  74. (*-------  Sort procedures for sorting the directories  ----------------*)
  75.  
  76. {$I sort.box}
  77.  
  78. procedure InP;  { Forward Declared in SORT.BOX }
  79. begin
  80.   for Counter:=1 to Total do
  81.     SortRelease(List[Counter]);
  82.   end;  { inp }
  83.  
  84. function Less;  { Forward Declared in SORT.BOX }
  85. var
  86.   FirstFile:  FileType absolute X;
  87.   SecondFile: FileType absolute Y;
  88.  
  89. begin
  90.   Less:=FirstFile.Name<SecondFile.Name;
  91.   end;  { less }
  92.  
  93. procedure OutP;  { Forward Declared in SORT.BOX }
  94. begin
  95.   for Counter:=1 to Total do
  96.     SortReturn(SortedList[Counter]);
  97.   end;  { outp }
  98.  
  99. (*----------------------------------------------------------------------*)
  100.  
  101. (*----------  Procedure to Read the Directory  -------------------------*)
  102.  
  103. procedure Directory(FileMask: str15; var List: ListType; var Total: byte);
  104. var Dta: string[44];
  105.  
  106. function FileSize: real;           { decypher the File's Size in Bytes }
  107. var Size: real;
  108.     Byte1,Byte2,Byte3,Byte4: byte;
  109. begin
  110.   Byte1:=ord(copy(DTA,28,1));
  111.   Byte2:=ord(copy(DTA,27,1));
  112.   Byte3:=ord(copy(DTA,29,1));
  113.   Byte4:=ord(copy(DTA,30,1));
  114.   Size:=Byte1 shl 8+Byte2;
  115.   if Size<0 then Size:=Size+65536.0;   { adjust for negative values }
  116.   Size:=(Byte3 shl 8+Byte4)*256.0+Size;
  117.   FileSize:=Size;
  118.   end;  { filesize }
  119.  
  120. function FileDate: str9;         { decypher the File's Date Stamp }
  121. var Day,Month,Year: str2;
  122.     Temp: integer;
  123.     Byte1,Byte2: byte;
  124. begin
  125.   Byte1:=ord(copy(DTA,25,1));
  126.   Byte2:=ord(copy(DTA,26,1));
  127.   str(Byte1 and 31:2,Day);
  128.   Temp:=(Byte1 shr 5) and 7+(Byte2 and 1) shl 3;
  129.   str(Temp:2,Month);
  130.   str((Byte2 shr 1)+80:2,Year);
  131.   if Day[1]=' ' then Day[1]:='0';
  132.   if Year[1]=' ' then Year[1]:='0';
  133.   FileDate:=Month+'-'+Day+'-'+Year;
  134.   end;  { filedate }
  135.  
  136. function FileTime: str6;            { decypher the File's Time Stamp }
  137. var Hour,Min: str2;
  138.     Temp: integer;
  139.     AmPm: char;
  140.     Byte1,Byte2: byte;
  141. begin
  142.   Byte1:=ord(copy(DTA,23,1));
  143.   Byte2:=ord(copy(DTA,24,1));
  144.   Temp:=(Byte1 shr 5) and 7+(Byte2 and 7) shl 3;
  145.   str(Temp:2,Min);
  146.   Temp:=Byte2 shr 3;
  147.   if Temp<13 then AmPm:='a' else begin
  148.     Temp:=Temp-12;
  149.     AmPm:='p';
  150.     end;
  151.   str(Temp:2,Hour);
  152.   if Min[1]=' ' then Min[1]:='0';
  153.   FileTime:=Hour+':'+Min+AmPm;
  154.   end;  { filetime }
  155.  
  156. procedure FillRecord(RecNo: byte);        { fill List.[RecNo] with file info }
  157. begin
  158.   with List[RecNo] do begin
  159.     Name:=copy(DTA,31,13);
  160.     Attrib:=ord(copy(DTA,22,1));
  161.     Size:=FileSize;                       { Fill names shorter than 8 chars }
  162.     Date:=FileDate;                       { with spaces }
  163.     Time:=FileTime;
  164.     if (Name[1]<>'.') and (pos('.',Name)<>0) then begin
  165.       while pos('.',Name)<9 do insert(' ',Name,pos('.',Name));
  166.       end;
  167.     end;
  168.   fillchar(Dta[31],12,' ');      { clear name to prepare for next call $4F }
  169.   end;  { fillrecord }
  170.  
  171. procedure FillDirList;
  172. begin
  173.   Total:=1;
  174.   FillRecord(Total);
  175.   repeat                         { Dos call $4F is used to find the next }
  176.     recpack.Ax:=$4f shl 8;       { matching file, in this case all files }
  177.     MsDos(recpack);
  178.     if (recpack.Ax<>18) and (recpack.Ax<>2) then begin
  179.       Total:=Total+1;
  180.       FillRecord(Total);
  181.       end;                              { repeat filling until no more files }
  182.     until (recpack.flags and 1)<>0;
  183.   end;  { filldirlist }
  184.  
  185. begin  { Directory }
  186.   Total:=0;
  187.   FileMask:=FileMask+#0;
  188.   fillchar(DTA[1],44,' '); DTA[0]:=#44;
  189.   with recpack do begin                        { First, Set aside the DTA    }
  190.     Ax:=$1a shl 8;                             { or Data Transfer Area,      }
  191.     Ds:=Seg(Dta); Dx:=Ofs(Dta)+1;              { call $1A then call $4E to   }
  192.     MsDos(recpack);                            { find the First Match. Set   }
  193.     Ax:=$4e shl 8;                             { set Cx to 31 to include all }
  194.     Ds:=Seg(FileMask); Dx:=Ofs(FileMask)+1;    { hidden files. Then up above }
  195.     Cx:=31;                                    { call $4F to find subsequent }
  196.     MsDos(recpack);                            { matches, filling List.      }
  197.     if (flags and 1)=0 then FillDirList;
  198.     end;
  199.   end;  { directory }
  200.  
  201. (*----------------------------------------------------------------------*)
  202.  
  203. (*---------------  MsDos functions that Borland left out  --------------*)
  204.  
  205. function CurrentDrive: byte;     { returns the number of the current drive }
  206. begin                            { default as follows:  1=A, 2=B, 3=C      }
  207.   with Recpack do begin
  208.     Ax:=$19 shl 8;
  209.     MsDos(Recpack);
  210.     CurrentDrive:=lo(Ax)+1;
  211.     end;
  212.   end;  { currentpath }
  213.  
  214. function CurrentPath: pathtype;  { returns the current Default Path }
  215. var DirStr: pathtype;
  216. begin
  217.   GetDir(CurrentDrive,DirStr);
  218.   CurrentPath:=DirStr;
  219.   end;  { currentpath }
  220.  
  221. (*----------------------------------------------------------------------*)
  222.  
  223. (*--------  The main routines for finding and reading directories  -----*)
  224.  
  225. procedure FindDirs;
  226. var P: pathtype;
  227. begin
  228.   P:=CurrentPath; if length(P)>3 then P:=P+'\';
  229.   DirTotal[DirLevel]:=0;
  230.   for Counter:=1 to Total do                { this routine mostly does the   }
  231.     with SortedList[Counter] do begin       { work of picking out DIR's from }
  232.       DiskLabel:=((Attrib and  8)= 8);      { the main list and storing them }
  233.       Dircty:=   ((Attrib and 16)=16);      { in the DIRLIST array along     }
  234.       if DiskLabel and PrnLabel then begin  { with Total # of SubDIR's       }
  235.         TextColor(LightRed);
  236.         if pos('.',Name)<>0 then delete(Name,pos('.',Name),1);
  237.         writeln('Label for the Disk in Drive ',chr(CurrentDrive+64),': is ',Name);
  238.         if prt then writeln(lst,'Label for the Disk in Drive ',chr(CurrentDrive+64),': is ',Name);
  239.         end;
  240.       if Dircty and (Name[1]<>'.') then begin
  241.         DirTotal[DirLevel]:=DirTotal[DirLevel]+1;
  242.         DirList[DirLevel].Name[DirTotal[DirLevel]]:=P+Name;
  243.         end;
  244.       end;
  245.    end;  { finddirs }
  246.  
  247. procedure FillerUp;
  248. begin
  249.   Directory('*.*',List,Total);                 { This routine calls Directory }
  250.   if TurboSort(Sizeof(FileType))<>0 then begin { to fill LIST with a list of  }
  251.     writeln('Internal Error, Aborting!');      { files in the Directory. Then }
  252.     halt                                       { then FindDirs picks out the  }
  253.     end;                                       { subdirectories.              }
  254.   FindDirs;
  255.   end;  { fillerup }
  256.  
  257. procedure Progress;
  258. begin
  259.   if DirPos[DirLevel]<=DirTotal[DirLevel] then begin
  260.     ChDir(DirList[DirLevel].Name[DirPos[DirLevel]]);
  261.     DirPos[DirLevel]:=DirPos[DirLevel]+1;
  262.     DirLevel:=DirLevel+1; DirPos[DirLevel]:=1;
  263.     FillerUp;
  264.   end else begin                     { This routine is Recursive, and looks }
  265.     DirLevel:=DirLevel-1;            { a little complicated, but it simply  }
  266.     if DirLevel>0 then Progress;     { keeps track of the current DIR level }
  267.     end;                             { and Position in the Directory.       }
  268.   end;  { progress }
  269.  
  270. (*----------------------------------------------------------------------*)
  271.  
  272. (*----------------------  The Main Program  ----------------------------*)
  273.  
  274. begin
  275.   ClrScr; TextColor(White);
  276.   writeln('Tree Listing of Subdirectories and Files');
  277.   writeln;
  278.   if ParamCount=0 then begin
  279.       TextColor(LightCyan);
  280.       writeln('Copyright (C) 1985 by David W. Terry');
  281.       writeln;
  282.       writeln('Program Syntax is as follows:  TREELIST [/P][/F][/L]');
  283.       writeln;
  284.       writeln('   where P = Print Output on Printer');
  285.       writeln('         F = List Files along with Subdirectories');
  286.       writeln('         L = Show Long Form list of Files');
  287.       writeln;
  288.       writeln('NOTE: Subdirectories are indented from their parents.');
  289.       writeln('      Also, the Long form indicates file attributes of');
  290.       writeln('      Normal, Hidden, System, Read Only, and Archive by');
  291.       writeln('      marking them with  N,H,S,R,A  respectively');
  292.       writeln;
  293.       Prt:=False; Long:=False; ShowFiles:=False;
  294.     end else begin
  295.       Prt:=      (pos('/P',ParamStr(1))<>0) or (pos('/p',ParamStr(1))<>0);
  296.       ShowFiles:=(pos('/F',ParamStr(1))<>0) or (pos('/f',ParamStr(1))<>0);
  297.       Long:=     (pos('/L',ParamStr(1))<>0) or (pos('/l',ParamStr(1))<>0);
  298.       if Long then ShowFiles:=True;
  299.       end;
  300.   Path:=CurrentPath; ChDir('\');
  301.   TextColor(White); fillchar(Spacer[1],80,32);
  302.   DirLevel:=1; DirTotal[DirLevel]:=1; DirPos[DirLevel]:=1;
  303.   DirList[1].Name[1]:='\';
  304.   PrnLabel:=True; FillerUp; PrnLabel:=False;
  305.   repeat
  306.     TextColor(LightGreen);
  307.     Spacer[0]:=chr((DirLevel-1)*4);
  308.     writeln;
  309.     writeln(Spacer,'[',CurrentPath,']',' Files in Directory are:');
  310.     TextColor(Yellow);
  311.     if prt then begin
  312.       writeln(lst);
  313.       writeln(lst,Spacer,'[',CurrentPath,']',' Files in Directory are:'); TextColor(Yellow);
  314.       end;
  315.     if ShowFiles then for Counter:=1 to total do
  316.       with SortedList[Counter] do begin
  317.         Spacer[0]:=chr(DirLevel*4);
  318.         Tail:='-----';
  319.         if (Attrib=0)         then Tail[1]:='N';   { Normal   }
  320.         if (Attrib and  1)= 1 then Tail[2]:='R';   { ReadOnly }
  321.         if (Attrib and  2)= 2 then Tail[3]:='H';   { Hidden   }
  322.         if (Attrib and  4)= 4 then Tail[4]:='S';   { System   }
  323.         if (Attrib and 32)=32 then Tail[5]:='A';   { Archive  }
  324.         DiskLabel:=(Attrib and  8)= 8;
  325.         Dircty:=   (Attrib and 16)=16;
  326.         if (not Long) then LongStr:='' else
  327.           LongStr:=' '+Date+' '+Time+' '+Tail;
  328.         if (not DiskLabel) and (not Dircty) then begin
  329.           writeln(Spacer,'--> ',Name,Size:7:0,LongStr);
  330.           if prt then writeln(lst,Spacer,'--> ',Name,Size:7:0,LongStr);
  331.           end;
  332.         end;
  333.     Progress;
  334.     until (DirLevel=0);
  335.   ChDir(Path);
  336.   end.
  337. ,'--> ',Name,Size:7:0,LongStr);
  338.           end;
  339.         end;
  340.     Progress;
  341.     until (DirLevel=0);
  342.   C