1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Plugin/Wildcard Search

Discussion in 'T&T - Plugins' started by nchernoff, Jun 6, 2008.

  1. nchernoff

    nchernoff Administrator
    Staff Member

    Joined:
    May 16, 2008
    Messages:
    42
    Likes Received:
    2
    Most of the time 4NT and Take Command handles files and almost all file handling commands accept wild card searches. For this 4NT and Take Command have a more powerful pattern matcher then the one used by Windows. The following Ada example show how to use 4NT and Take Command wild cards in your plug-in.

    Description

    The description — unlike the source below — is "work in progress" and not yet finished.

    Line 119 — 120

    The procedure takes a string with a search pattern of the type dir/pattern &ndash with both dir and pattern beeing optional and a call back function which will be called for each file found.

    Line 122 — 123

    Commented out is the function entry and exit trace which can be used for debuggin purpouse. Commented out since the function has no known bugs.

    Line 125 — 127

    In order to perform a wild card search we have to separate the directoy from the pattern. Since a directory in Windows NT can be 215 utf-16 characters in size a static sized buffer is not appropiate and we first determine the lenght needed.

    Then we define two variables to hold the directory and pattern part. If you use C check if your C compiler supports alloca – It will make things easier for you. If you use Delphi you will need bite the bullet and use heap memory.

    Line 135 — 136

    As mentioned we are now going to split the directory and the file name. We employ two function from the TcmdLib for this.

    Line 139 — 146

    In case there has been no pattern we change the pattern to "*" – all files.

    Line 153 — 157

    Since we want to use the wild card matcher from the TcmdLib we request all files from directory to match them against the pattern. The Win32.Winbase.FindFirstFileW functions returns a handle for further searches and the first result.

    Line 159 — 166

    When the handle returned was not valid we raise an exception. I use a function from my trace library so additinal trace info is written when trace is active.

    Line 169 — 173

    We use the TcmdLib to find out if the current file is a match enableing fBrackets to patterns like [0-9] are matched.

    Line 174

    The code was formated automaticly using gnat pretty which works well most of the time but sometimes leaves stange artefacts like this loonly 0.

    Line 176 — 177

    We call the call back procedure for the file found. The call back function will perform any further action we desire. We also increase the file counter by one.

    Line 179 — 182

    The Win32.Winbase.FindNextFileW will get the next match or return Win32.FALSE if there is not further match – in which case we leave the loop.

    Line 187 — 193

    If no file was found we raise an exeption with the error message "No Files found.".

    Line 187 — 194

    We are finished and return to the calling function or procedure.

    Ada Code

    One could probably use use clauses and refrain from using named parameters to make the code smaller - but I am more into readability then dense coding.

    Code:
    118    procedure Wildcard_Search
    119      (Directory_Pattern : in Win32.WCHAR_Array;
    120       Process           : not null access procedure (Directory_Entry : in Win32.WCHAR_Array))
    121    is
    122       --  Trace : constant TakeCmd.Trace.Object := TakeCmd.Trace.Function_Trace
    123       --  (TakeCmd.Trace.Entity); pragma Unreferenced (Trace);
    124
    125       Directory_Length : constant Interfaces.C.int := PathLength (Directory_Pattern);
    126       Directory        : aliased Win32.WCHAR_Array (1 .. Integer (Directory_Length) + 1);
    127       Pattern          : aliased File_Name;
    128       Dummy            : Win32.PWSTR;
    129       Files_Found      : Natural                   := 0;
    130
    131       pragma Warnings (Off, Dummy);
    132       pragma Warnings (Off, Directory);
    133       pragma Warnings (Off, Pattern);
    134    begin
    135       Dummy := PathPart (pszName => Directory_Pattern, pszPath => Win32.Addr (Directory));
    136       Dummy :=
    137          FilenamePart (pszName => Directory_Pattern, pszFilenamePart => Win32.Addr (Pattern));
    138
    139       Fix_Pattern : declare
    140          Pattern_Length : constant Interfaces.C.int :=
    141             Win32.Winbase.lstrlenW (Win32.Addr (Pattern));
    142       begin
    143          if Pattern_Length = 0 then
    144             Pattern := (1 => '*', others => Win32.Wide_Nul);
    145          end if;
    146       end Fix_Pattern;
    147
    148       Find_Files : declare
    149          use type Win32.Winnt.HANDLE;
    150          use type Win32.BOOL;
    151
    152          Data   : aliased Win32.Winbase.WIN32_FIND_DATAW;
    153          Handle : constant Win32.Winnt.HANDLE :=
    154             Win32.Winbase.FindFirstFileW
    155               (lpFileName     =>
    156                   Win32.Addr (Directory (1 .. Directory'Last - 1) & "*" & Win32.Wide_Nul),
    157                lpFindFileData => Data'Unchecked_Access);
    158       begin
    159          if Handle = Win32.Winbase.INVALID_HANDLE_VALUE then
    160            TakeCmd.Trace.Raise_Exception
    161               (Raising => Win32_Error'Identity,
    162                Message => ": FindFirstFileW: " &
    163                           Win32.DWORD'Image (Win32.Winbase.GetLastError) &
    164                           ". ",
    165                Entity  => TakeCmd.Trace.Entity,
    166                Source  => TakeCmd.Trace.Source);
    167          else
    168             Process_Files : loop
    169                if WildcardComparison
    170                      (pszWildName => Win32.Addr (Pattern),
    171                       pszFileName => Win32.Addr (Data.cFileName),
    172                       fExtension  => 0,
    173                       fBrackets   => 1) =
    174                   0
    175                then
    176                   Process (Directory (1 .. Directory'Last - 1) & Data.cFileName);
    177                   Files_Found := Files_Found + 1;
    178                end if;
    179                exit Process_Files when Win32.Winbase.FindNextFileW
    180                                           (hFindFile      => Handle,
    181                                            lpFindFileData => Data'Unchecked_Access) /=
    182                                        Win32.TRUE;
    183             end loop Process_Files;
    184          end if;
    185       end Find_Files;
    186
    187       if Files_Found = 0 then
    188          TakeCmd.Trace.Raise_Exception
    189            (Raising => Name_Error'Identity,
    190             Message => "No Files found.",
    191             Entity  => TakeCmd.Trace.Entity,
    192             Source  => TakeCmd.Trace.Source);
    193       end if;
    194       return;
    195    end Wildcard_Search;
     

Share This Page