home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / library / dos / tug__002 / tpdir.pas < prev    next >
Pascal/Delphi Source File  |  1988-08-14  |  12KB  |  391 lines

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