home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / library / dos / packer / arc / arctool / tpdir.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1988-09-29  |  10.0 KB  |  354 lines

  1. {
  2.                        F i l e    I n f o r m a t i o n
  3.  
  4. * DESCRIPTION
  5. This program requires the use of units from the commercial product Turbo
  6. Professional 4.0, by TurboPower Software. It demonstrates two new units.
  7. The TPPICK unit offers general-purpose scrolling "pick" windows, which
  8. allow the user to scroll through a list of strings and select one to
  9. return to the calling program. The TPDIR unit offers a popup directory
  10. unit, useful wherever user entry of filenames is required.
  11. (DEMO1.PAS and DEMO1.EXE need to renamed to DEMO.PAS and DEMO.EXE. They
  12. were renamed due to like filenames on the same disk).
  13.  
  14. * ASSOCIATED FILES
  15. TPDIR.PAS
  16. DEMO1.PAS
  17. DEMO1.EXE
  18. TPDIR.TPU
  19. TPPICK.PAS
  20. TPPICK.TPU
  21.  
  22. }
  23. {
  24. Copyright (c) 1987 by TurboPower Software. May be freely used by and
  25. distributed to owners of Turbo Professional 4.0.
  26. }
  27.  
  28. {$R-,I-,S-,V-}
  29.  
  30. unit TPDir;
  31.   {-Use a pick window to select a filename}
  32.  
  33. interface
  34.  
  35. uses
  36.   Dos,
  37.   TPString,
  38.   TPCrt,
  39.   TPWindow,
  40.   TPPick;
  41.  
  42. type
  43.   DirColorType = (WindowAttr, FrameAttr, HeaderAttr, SelectAttr);
  44.   DirColorArray = array[DirColorType] of Byte;
  45.  
  46. const
  47.   {Programs can modify these constants to change TPDIR behavior}
  48.   DirMonocColors : DirColorArray = ($07, $07, $0F, $70);
  49.   DirColorColors : DirColorArray = ($1B, $17, $30, $7E);
  50.   XLow : Byte = 60;          {Position of pick window}
  51.   YLow : Byte = 2;
  52.   YHigh : Byte = 25;
  53.   {XHigh is determined automatically}
  54.   FileAttr : Byte = Directory; {File selection attribute}
  55.  
  56. function GetFileName(Mask : string; var FileName : string) : Word;
  57.   {-Given a mask (which may or may not contain wildcards),
  58.     popup a directory window, let user choose, and return pathname.
  59.     Returns zero for success, non-zero for error.
  60.     Error codes:
  61.       0 = Success
  62.       1 = Path not found
  63.       2 = No matching files
  64.       3 = Attempt to use popup in unsupported video mode
  65.       4 = Insufficient memory
  66.     else  Turbo critical error code
  67.   }
  68.  
  69.   {=========================================================================}
  70.  
  71. implementation
  72.  
  73. const
  74.   MaxFiles = 500; {Absolute maximum number of files found in one directory}
  75. type
  76.   FileString = string[13]; {Has space for \ following subdirectory names}
  77.   FileArray = array[1..MaxFiles] of FileString;
  78. var
  79.   F : ^FileArray;     {Pointer to file array}
  80.   MaxNumFiles : Word; {Maximum number of files we have memory space for}
  81.   NumFiles : Word;    {Actual number of files found}
  82.   Frec : SearchRec;   {Used in directory operations}
  83.  
  84.   function StUpcase(S : string) : string;
  85.     {-Uppercase a string}
  86.   var
  87.     i:integer;
  88.   begin
  89.     for i:=1 to length(s) do
  90.       s[i] := upcase(s[i]);
  91.     StUpcase := s;
  92.   end;
  93.  
  94.   function HasWildCards(Mask : string) : Boolean;
  95.     {-Return true if Mask has DOS wildcards}
  96.   begin
  97.     HasWildCards := (pos('*', Mask) <> 0) or (pos('?', Mask) <> 0);
  98.   end;
  99.  
  100.   function EndsPathDelim(Mask : string) : Boolean;
  101.     {-Return true if Mask ends in a DOS path delimiter}
  102.   begin
  103.     case Mask[Length(Mask)] of
  104.       #0, ':', '\' : EndsPathDelim := True;
  105.     else
  106.       EndsPathDelim := False;
  107.     end;
  108.   end;
  109.  
  110.   function AddFilePath(Mask : string; Fname : FileString) : string;
  111.     {-Concatenate a filemask and filename}
  112.   var
  113.     Mlen : byte absolute Mask;
  114.     Flen : byte absolute Fname;
  115.   begin
  116.     if EndsPathDelim(Mask) then begin
  117.       if ((Fname = '..\') and (Mlen > 2) and
  118.          (Mask[Mlen] = '\') and (Mask[Mlen-1] <> '.')) then begin
  119.         {Remove last subdirectory}
  120.         repeat
  121.           dec(Mlen);
  122.         until EndsPathDelim(Mask);
  123.         AddFilePath := Mask;
  124.       end else
  125.         AddFilePath := Mask+Fname
  126.     end else
  127.       AddFilePath := Mask+'\'+Fname;
  128.   end;
  129.  
  130.   function AddWildCard(Mask : string) : string;
  131.     {-Add a default wild card to Mask if it needs it}
  132.   begin
  133.     if HasWildCards(Mask) then
  134.       AddWildCard := Mask
  135.     else
  136.       AddWildCard := AddFilePath(Mask, '*.*');
  137.   end;
  138.  
  139.   function FindFiles(SearchMask : string; FileAttr : Byte) : Word;
  140.     {-Add any matched files to File arrays}
  141.   begin
  142.     FindFirst(SearchMask, FileAttr, Frec);
  143.     while (DosError = 0) and (NumFiles < MaxNumFiles) do begin
  144.       with Frec do
  145.         if (Attr and Directory) = (FileAttr and Directory) then
  146.           {Matches directory type}
  147.           if Name <> '.' then begin
  148.             Inc(NumFiles);
  149.             if Attr and Directory <> 0 then
  150.               F^[NumFiles] := Name+'\'
  151.             else
  152.               F^[NumFiles] := Name;
  153.           end;
  154.       FindNext(Frec);
  155.     end;
  156.     case DosError of
  157.       3, 18 : FindFiles := 0;
  158.     else
  159.       FindFiles := DosError;
  160.     end;
  161.   end;
  162.  
  163.   procedure SwapItem(I, J : Word);
  164.     {-Swap two sort items}
  165.   var
  166.     TmpF : FileString;
  167.   begin
  168.     TmpF := F^[J];
  169.     F^[J] := F^[I];
  170.     F^[I] := TmpF;
  171.   end;
  172.  
  173.   procedure ShellSort(NumFiles : Word);
  174.     {-Shellsort the directory entries}
  175.   var
  176.     Offset, I, J, K : Word;
  177.     InOrder : Boolean;
  178.   begin
  179.     Offset := NumFiles;
  180.     while Offset > 1 do begin
  181.       Offset := Offset shr 1;
  182.       K := NumFiles-Offset;
  183.       repeat
  184.         InOrder := True;
  185.         for J := 1 to K do begin
  186.           I := J+Offset;
  187.           if F^[I] < F^[J] then begin
  188.             SwapItem(I, J);
  189.             InOrder := False;
  190.           end;
  191.         end;
  192.       until InOrder;
  193.     end;
  194.   end;
  195.  
  196.   {$F+}
  197.   function SendFileName(Item : word) : string;
  198.     {-Pass each file name to the pick unit}
  199.   begin
  200.     SendFileName := F^[Item];
  201.   end;
  202.   {$F-}
  203.  
  204.   function GetFileName(Mask : string; var FileName : string) : Word;
  205.     {-Get a filename from a user mask}
  206.   label
  207.     ExitPoint;
  208.   var
  209.     PickChar : Char;
  210.     Done : Boolean;
  211.     XHigh : Byte;
  212.     Choice : Word;
  213.     Status : Word;
  214.     Memory : LongInt;
  215.     VA : DirColorArray;
  216.     SearchMask : string;
  217.     PathName : string;
  218.     WildCard : FileString;
  219.   begin
  220.  
  221.     {Assume success}
  222.     GetFileName := 0;
  223.     FileName := '';
  224.  
  225.     {Get the default searchmask}
  226.     Mask := StUpcase(Mask);
  227.     SearchMask := AddWildCard(Mask);
  228.  
  229.     {See if mask specifies a subdirectory}
  230.     if (Length(Mask) <> 0) and not HasWildCards(Mask) then begin
  231.       FindFirst(SearchMask, FileAttr, Frec);
  232.       case DosError of
  233.         0 : ;                {Files found, it is a subdirectory}
  234.         3 :                  {Path not found, invalid subdirectory}
  235.           begin
  236.             {See if Mask itself is a valid path}
  237.             FindFirst(Mask, FileAttr, Frec);
  238.             case DosError of
  239.               3 : GetFileName := 1; {Path not found}
  240.             else
  241.               FileName := Mask; {New or existing file}
  242.             end;
  243.             exit;
  244.           end;
  245.         18 :                 {No more files, not a subdirectory}
  246.           begin
  247.             case Mask[Length(Mask)] of
  248.               ':', '\' : GetFileName := 2; {No matching files}
  249.             else
  250.               FileName := Mask; {New or existing file}
  251.             end;
  252.             Exit;
  253.           end;
  254.       else
  255.         GetFileName := DosError; {DOS critical error}
  256.         Exit;
  257.       end;
  258.     end;
  259.  
  260.     {Initialize display colors}
  261.     case LastMode and $FF of
  262.       0, 2, 7 : VA := DirMonocColors;
  263.       1, 3 : VA := DirColorColors;
  264.     else
  265.       {Unsupported video mode}
  266.       GetFileName := 3;
  267.       Exit;
  268.     end;
  269.  
  270.     {Get space for file array - reserve 2000 bytes for popup window}
  271.     Memory := MaxAvail-2000;
  272.     if Memory > MaxFiles*SizeOf(FileString) then
  273.       {Room for MaxFiles}
  274.       MaxNumFiles := MaxFiles
  275.     else begin
  276.       {Limited space available}
  277.       MaxNumFiles := Memory div SizeOf(FileString);
  278.       if MaxFiles < 2 then begin
  279.         GetFileName := 4; {Insufficient memory}
  280.         Exit;
  281.       end;
  282.     end;
  283.     GetMem(F, MaxNumFiles*SizeOf(FileString));
  284.  
  285.     Done := False;
  286.     repeat
  287.  
  288.       {Separate wildcard from pathname}
  289.       WildCard := JustFilename(SearchMask);
  290.       PathName := copy(SearchMask, 1, length(SearchMask)-length(WildCard));
  291.  
  292.       {Build the file array}
  293.       NumFiles := 0;
  294.       {Find non-subdirectories}
  295.       Status := FindFiles(SearchMask, FileAttr and not Directory);
  296.       {Find subdirectories}
  297.       if Status = 0 then
  298.         if (FileAttr and Directory) <> 0 then
  299.           Status := FindFiles(AddWildCard(PathName), FileAttr);
  300.       if Status <> 0 then begin
  301.         GetFileName := Status;
  302.         goto ExitPoint;
  303.       end;
  304.  
  305.       if NumFiles = 0 then begin
  306.         {No files found}
  307.         Done := True;
  308.         GetFileName := 2; {No matching files}
  309.  
  310.       end else begin
  311.         {Sort the directory}
  312.         ShellSort(NumFiles);
  313.  
  314.         {Choose the window width}
  315.         if SizeOf(FileString) >= Length(SearchMask)+3 then
  316.           XHigh := XLow+SizeOf(FileString)+2
  317.         else
  318.           XHigh := XLow+Length(SearchMask)+5;
  319.  
  320.         {Pick from the directory}
  321.         if PickWindow(@SendFileName, NumFiles, XLow, YLow, XHigh, YHigh, True,
  322.                       VA[WindowAttr], VA[FrameAttr], VA[HeaderAttr], VA[SelectAttr],
  323.                       ' '+SearchMask+' ', [#13, #27], Choice, PickChar) then
  324.         begin
  325.           case PickChar of
  326.             #27 :          {User pressed Escape - return empty file name}
  327.               Done := True;
  328.             #13 :          {User pressed Enter}
  329.               if F^[Choice][length(F^[Choice])] = '\' then begin
  330.                 {Selected a subdirectory}
  331.                 Mask := AddFilePath(PathName, F^[Choice]);
  332.                 SearchMask := AddFilePath(Mask, WildCard);
  333.               end else begin
  334.                 {Not a directory}
  335.                 FileName := AddFilePath(PathName, F^[Choice]);
  336.                 Done := True;
  337.               end;
  338.           end;
  339.         end else begin
  340.           {Error occurred in PickWindow - most likely insufficient memory}
  341.           GetFileName := 4;
  342.           Done := True;
  343.         end;
  344.       end;
  345.     until Done;
  346.  
  347. ExitPoint:
  348.     {Free the memory space used for file array}
  349.     FreeMem(F, MaxNumFiles*SizeOf(FileString));
  350.   end;
  351.  
  352. end.
  353. 
  354.