bool ClassBrowser::RecursiveSearch(const wxString& search, wxTreeCtrl* tree, const wxTreeItemId& parent, wxTreeItemId& result) { if (!parent.IsOk() || !tree) return false; // first check the parent item if (FoundMatch(search, tree, parent)) { result = parent; return true; } wxTreeItemIdValue cookie; wxTreeItemId child = tree->GetFirstChild(parent, cookie); if (!child.IsOk()) return RecursiveSearch(search, tree, FindNext(search, tree, parent), result); while (child.IsOk()) { if (FoundMatch(search, tree, child)) { result = child; return true; } if (tree->ItemHasChildren(child)) { if (RecursiveSearch(search, tree, child, result)) return true; } child = tree->GetNextChild(parent, cookie); } return RecursiveSearch(search, tree, FindNext(search, tree, parent), result); }
/** \internal Does all the actual globbing. \author Matthias Wandel ([email protected]) http://http://www.sentex.net/~mwandel/ \author Joshua Jensen ([email protected]) Matthias Wandel wrote the original C algorithm, which is contained in his Exif Jpeg header parser at http://www.sentex.net/~mwandel/jhead/ under the filename MyGlob.c. It should be noted that the MAJORITY of this function is his, albeit rebranded style-wise. I have made the following extensions: - Support for ignoring directories. - Perforce-style (and DJGPP-style) ... for recursion, instead of **. - Automatic conversion from ...Stuff to .../*Stuff. Allows lookup of files by extension, too: '....h' translates to '.../*.h'. - Ability to handle forward slashes and backslashes. - A minimal C++ class design. - Wildcard matching not based on FindFirstFile(). Should allow greater control in the future and patching in of the POSIX fnmatch() function on systems that support it. **/ void FileGlobBase::GlobHelper( const char* inPattern ) { char patternBuf[ _MAX_PATH * 2 ]; strcpy( patternBuf, inPattern ); DoRecursion: char basePath[ _MAX_PATH ]; char* basePathEndPtr = basePath; char* recurseAtPtr = NULL; // Split the path into base path and pattern to match against. bool hasWildcard = false; char* pattern; for ( pattern = patternBuf; *pattern != '\0'; ++pattern ) { char ch = *pattern; // Is it a '?' ? if ( ch == '?' ) hasWildcard = true; // Is it a '*' ? else if ( ch == '*' ) { hasWildcard = true; // Is there a '**'? if ( pattern[ 1 ] == '*' ) { // If we're just starting the pattern or the characters immediately // preceding the pattern are a drive letter ':' or a directory path // '/', then set up the internals for later recursion. if ( pattern == patternBuf || pattern[ -1 ] == '/' || pattern[ -1 ] == ':') { char ch2 = pattern[ 2 ]; if ( ch2 == '/' ) { recurseAtPtr = pattern; memcpy(pattern, pattern + 3, strlen( pattern ) - 2 ); } else if ( ch2 == '\0' ) { recurseAtPtr = pattern; *pattern = '\0'; } } } } // Is there a '/' or ':' in the pattern at this location? if ( ch == '/' || ch == ':' ) { if ( hasWildcard ) break; basePathEndPtr = &basePath[ pattern - patternBuf + 1 ]; } } // If there is no wildcard this time, then just add the current file and // get out of here. if ( !hasWildcard ) { // This should refer to a file. FoundMatch( patternBuf ); return; } // Did we make it to the end of the pattern? If so, we should match files, // since there were no slashes encountered. bool matchFiles = *pattern == '\0'; // Copy the directory down. size_t basePathLen = basePathEndPtr - basePath; strncpy( basePath, patternBuf, basePathLen ); // Copy the wildcard matching string. char matchPattern[ _MAX_PATH ]; size_t matchLen = ( pattern - patternBuf ) - basePathLen; strncpy( matchPattern, patternBuf + basePathLen, matchLen + 1 ); if ( matchPattern[ matchLen ] == '/' ) matchPattern[ matchLen ] = 0; StringList fileList; // Do the file search with *.* in the directory specified in basePattern. strcpy( basePathEndPtr, "*.*" ); // Start the find. WIN32_FIND_DATA fd; HANDLE handle = FindFirstFile( basePath, &fd ); // Clear out the *.* so we can use the original basePattern string. *basePathEndPtr = 0; // Any files found? if ( handle != INVALID_HANDLE_VALUE ) { for ( ;; ) { // Is the file a directory? if ( ( fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) && !matchFiles ) { // Do a wildcard match. if ( WildMatch( matchPattern, fd.cFileName, false ) ) { // It matched. Let's see if the file should be ignored. bool ignore = false; // Knock out "." or ".." if they haven't already been. size_t len = strlen( fd.cFileName ); fd.cFileName[ len ] = '/'; fd.cFileName[ len + 1 ] = '\0'; // See if this is a directory to ignore. ignore = MatchIgnorePattern( fd.cFileName ); fd.cFileName[ len ] = 0; // Should this file be ignored? if ( !ignore ) { // Nope. Add it to the linked list. fileList.push_back( fd.cFileName ); } } } else if ( !( fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) && matchFiles ) { // Do a wildcard match. if ( WildMatch( matchPattern, fd.cFileName, false ) ) { // It matched. Let's see if the file should be ignored. bool ignore = MatchIgnorePattern( fd.cFileName ); // Is this pattern exclusive? if ( !ignore && m_exclusiveFilePatterns.begin() != m_exclusiveFilePatterns.end() ) { ignore = !MatchExclusivePattern( fd.cFileName ); } // Should this file be ignored? if ( !ignore ) { // Nope. Add it to the linked list. fileList.push_back( fd.cFileName ); } } } // Look up the next file. if ( !FindNextFile( handle, &fd ) ) break; } // Close down the file find handle. FindClose( handle ); } // Sort the list. fileList.sort(); // Iterate the file list and either recurse or add the file as a found // file. if ( !matchFiles ) { for ( StringList::iterator it = fileList.begin(); it != fileList.end(); ++it ) { char combinedName[ _MAX_PATH * 2 ]; // Need more directories. CatPath( combinedName, basePath, (*it).c_str() ); strcat( combinedName, pattern ); GlobHelper( combinedName ); } } else // if ( !matchFiles ) { for ( StringList::iterator it = fileList.begin(); it != fileList.end(); ++it ) { char combinedName[ _MAX_PATH * 2 ]; CatPath( combinedName, basePath, (*it).c_str()); FoundMatch( combinedName ); } } // Clear out the file list, so the goto statement below can recurse // internally. fileList.clear(); // Do we need to recurse? if ( !recurseAtPtr ) return; // Copy in the new recursive pattern to match. strcpy( matchPattern, recurseAtPtr ); strcpy( recurseAtPtr, "*/**/" ); strcat( patternBuf, matchPattern ); // As this function context is no longer needed, we can just go back // to the top of it to avoid adding another context on the stack. goto DoRecursion; }