home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / library / dos / t_power / tpdir.pas < prev    next >
Pascal/Delphi Source File  |  1988-02-16  |  10KB  |  353 lines

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