Просмотр кода
Идентификатор: b57d0dcf Описание: Код загружен: 28 июня 2011, 07:08 (Gooddy)
function ExpandFileNameCase(const FileName: string; out MatchFound: TFilenameCaseMatch): string; var SR: TSearchRec; FullPath, Name: string; Temp: Integer; FoundOne: Boolean; {$IFDEF LINUX} Scans: Byte; FirstLetter, TestLetter: string; {$ENDIF} begin Result := ExpandFileName(FileName); FullPath := ExtractFilePath(Result); Name := ExtractFileName(Result); MatchFound := mkNone; // if FullPath is not the root directory (portable) if not SameFileName(FullPath, IncludeTrailingPathDelimiter(ExtractFileDrive(FullPath))) then begin // Does the path need case-sensitive work? Temp := FindFirst(FullPath, faAnyFile, SR); FindClose(SR); // close search before going recursive if Temp <> 0 then begin FullPath := ExcludeTrailingPathDelimiter(FullPath); FullPath := ExpandFileNameCase(FullPath, MatchFound); if MatchFound = mkNone then Exit; // if we can't find the path, we certainly can't find the file! FullPath := IncludeTrailingPathDelimiter(FullPath); end; end; // Path is validated / adjusted. Now for the file itself try if FindFirst(FullPath + Name, faAnyFile, SR)= 0 then // exact match on filename begin if not (MatchFound in [mkSingleMatch, mkAmbiguous]) then // path might have been inexact MatchFound := mkExactMatch; Result := FullPath + SR.Name; Exit; end; finally FindClose(SR); end; FoundOne := False; // Windows should never get to here except for file-not-found {$IFDEF LINUX} { Scan the directory. To minimize the number of filenames tested, scan the directory using upper/lowercase first letter + wildcard. This results in two scans of the directory (particularly on Linux) but vastly reduces the number of times we have to perform an expensive locale-charset case-insensitive string compare. } // First, scan for lowercase first letter FirstLetter := AnsiLowerCase(Name[1]); for Scans := 0 to 1 do begin Temp := FindFirst(FullPath + FirstLetter + '*', faAnyFile, SR); while Temp = 0 do begin if AnsiSameText(SR.Name, Name) then begin if FoundOne then begin // this is the second match MatchFound := mkAmbiguous; Exit; end else begin FoundOne := True; Result := FullPath + SR.Name; end; end; Temp := FindNext(SR); end; FindClose(SR); TestLetter := AnsiUpperCase(Name[1]); if TestLetter = FirstLetter then Break; FirstLetter := TestLetter; end; {$ENDIF} if MatchFound <> mkAmbiguous then begin if FoundOne then MatchFound := mkSingleMatch else MatchFound := mkNone; end; end;