[TFindFile] Request for Unicode version

Please post bug reports, feature requests, or any question regarding the DELPHI AREA projects here.

[TFindFile] Request for Unicode version

Postby avushoi » March 2nd, 2009, 6:48 pm

I want to request an unicode version of TFindFile.

Little description:
I made an aplication with TTntEdit (from TntWare Delphi Unicode Controls) using Delphi 7. The TTntEdit is used for inputting the directory path. This is the piece of code to connect the TTnTEdit to the TFindFile component:

Code: Select all
// txtFolder1 is the TTntEdit and assume the property Text contains unicode chars
FindFile1.Criteria.Files.Location := txtFolder1.Text;
FindFile1.Execute;
...


The event "FindFile1FileMatch" is not called at all since the Text contain unicode. So I hope you can make the unicode version of TFindFile since I'm stuck at here.

Thx in adv.

Btw, why the registration activation took such a long time? I thought I was rejected.
avushoi
Active Member
Active Member
 
Posts: 8
Joined: March 1st, 2009, 5:07 pm

Re: [TFindFile] Request for Unicode version

Postby Kambiz » March 3rd, 2009, 4:52 pm

Because the component is already updated for Delphi 2009, only substituting Char to WideChar, String to WideString, and TStringList to TntStringList makes it Unicode ready.

I did the substitutions but didn't test it. Please give me a favor and inform me about the result.
Attachments
FindFileW.pas
Unicode version of TFindFile
(50.17 KiB) Downloaded 138 times
Kambiz
User avatar
Kambiz
Administrator
Administrator
 
Posts: 2429
Joined: March 7th, 2003, 7:10 pm

Re: [TFindFile] Request for Unicode version

Postby Kambiz » March 3rd, 2009, 4:56 pm

Regarding registration, the delay is because of spammers. Sorry for the inconvenience.
Kambiz
User avatar
Kambiz
Administrator
Administrator
 
Posts: 2429
Joined: March 7th, 2003, 7:10 pm

Re: [TFindFile] Request for Unicode version

Postby avushoi » March 3rd, 2009, 7:10 pm

ok, I've downloaded the code. I will try it and inform you later.

umm, btw, your avatar... is that really your photo?
avushoi
Active Member
Active Member
 
Posts: 8
Joined: March 1st, 2009, 5:07 pm

Re: [TFindFile] Request for Unicode version

Postby Kambiz » March 4th, 2009, 2:36 am

I guess it is two or three years younger than me. :)
Kambiz
User avatar
Kambiz
Administrator
Administrator
 
Posts: 2429
Joined: March 7th, 2003, 7:10 pm

Re: [TFindFile] Request for Unicode version

Postby avushoi » March 4th, 2009, 5:14 pm

ok, I had done my software with TFindFileW. Whew...

However, your FindFileW.pas is stil lack of some changes.
Around line 991:
Code: Select all
  Result := ExpandUNCFileName(Trim(Result));
  {$IFDEF COMPILER7_UP}
  Result := IncludeTrailingPathDelimiter(Result);
  {$ELSE}
  Result := IncludeTrailingBackslash(Result);


The corrections:
IncludeTrailingPathDelimiter -> WideIncludeTrailingPathDelimiter
IncludeTrailingBackslash -> WideIncludeTrailingBackslash

But for "ExpandUNCFileName", I couldn't find the TTnt version, so I change it with "WideExpandFileName" for temporary. I' was thinking to create the unicode version of "ExpandUNCFileName" from delphi source code, but it's too hard, the code involves some windows network API functions. Could you help me with this?

I also replaced all words of "TFindFile" to "TFindFileW". Especially in this line:
Code: Select all
RegisterComponents('Delphi Area', [TFindFile]);

so I can have 2 TFindFile in the pallete.

My modified FindFileW.pas is in attachment.

I have some questions:
* The "Threaded" property of TFindFile, if I set it to true, does it make the finding process more faster?

* I found out that some delphi 7 functions from system & sysutils unit such as: Delete, Copy, StrToIntDef, etc, can accept widestring whereas the delphi 7 help doesn't mention the functions support widestring input. Could you give me explanation about this?

* The unicode text couldn't displayed correctly when I use function ShowMessage, where MessageBoxW could. The unicode char was showed as question mark, i.e. C:\???\. I saw in the delphi 7 documentation, the function showmessage has the overloaded version that accept widestring. I've already tried to type-cast the input, i.e.: Showmessage(WideString(str)), but still no avail. Do you know what's the cause?

Thx in adv,
Keep up the good work.
Attachments
TFindFileW.zip
(10.01 KiB) Downloaded 119 times
avushoi
Active Member
Active Member
 
Posts: 8
Joined: March 1st, 2009, 5:07 pm

Re: [TFindFile] Request for Unicode version

Postby Kambiz » March 5th, 2009, 6:20 am

Here you are.

  • Threaded search is a bit slower.
  • Some functions like Delete and Copy which work on both arrays and strings works on widestrings too.
    Some functions like StrToInt only accepts AnsiStrings and if you pass a WideString to them, the compiler implicitly converts it to AnsiString. But the result is the same because for example Latin digits are Latin digits anyway.
    If any other function accepts Unicode strings, in the help mentioned that "This function works for multi-byte character systems (MBCS)".
  • You have to choose a font that supports Unicode characters. Characters missing in a font will be displayed as question mark.
Attachments
FindFileW.zip
(11.14 KiB) Downloaded 114 times
Kambiz
User avatar
Kambiz
Administrator
Administrator
 
Posts: 2429
Joined: March 7th, 2003, 7:10 pm

Re: [TFindFile] Request for Unicode version

Postby avushoi » March 5th, 2009, 7:49 am

Thx, I will inspect your new source code.

You have to choose a font that supports Unicode characters. Characters missing in a font will be displayed as question mark.

How to choose a font?
Why font in ShowMessage is different with the font in MessageBox?

If you don't mind I need your advice:
I create these 2 functions to calculate file size from a file path given input. Between them, which is more faster and best to use? Do you know other best alternative for this function?
Code: Select all
function GetSizeOfFile(const FileName: string): Int64;
var
  Handle: THandle;
  FindData: TWin32FindData;
  Size: TULargeInteger;
begin
  Result := 0;
  Handle := FindFirstFile(PChar(FileName), FindData);
  if Handle <> INVALID_HANDLE_VALUE then
  begin
    Windows.FindClose(Handle);
    Size.LowPart := FindData.nFileSizeLow;
    Size.HighPart := FindData.nFileSizeHigh;
    Result := Size.QuadPart;
  end
  else
    RaiseLastOSError;
end;

function GetSizeOfFile2(const FileName: string): Int64;
var
  Handle: THandle;
  Size: TULargeInteger;
begin
  Result := 0;
  Handle := CreateFile(PChar(FileName), GENERIC_READ, FILE_SHARE_READ, nil,
    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  if Handle <> INVALID_HANDLE_VALUE then begin
    Size.LowPart := GetFileSize(Handle, @Size.HighPart);
    Result := Size.QuadPart;
    CloseHandle(Handle);
  end else
    RaiseLastOSError;
end;


Is it right to use RaiseLastOSError instead of returning error code?
If there are some things wrong in my code, don't hesitate to tell me.

Thx.
avushoi
Active Member
Active Member
 
Posts: 8
Joined: March 1st, 2009, 5:07 pm

Re: [TFindFile] Request for Unicode version

Postby Kambiz » March 5th, 2009, 11:32 am

MessageBox is a Windows API but ShowMessage is a Delphi function that displays a dialog with one TLabel and TButton on it. None of the label and the button are Unicode enabled and font is the default Delphi font which is 'Ms Sans Serif'. I personally write my own ShowMessage function.

The second function seems to be faster but you don't know until you run a test.

Choosing between raising an exception or returning an error code highly depends on your coding logic. Sometime an exception is more convenient and sometimes an error code. But in case of getting file size, I prefer to return -1 on error because if GetFileSize fails too, it returns -1.
Kambiz
User avatar
Kambiz
Administrator
Administrator
 
Posts: 2429
Joined: March 7th, 2003, 7:10 pm

Re: [TFindFile] Request for Unicode version

Postby avushoi » March 5th, 2009, 3:35 pm

Thx for the help.

I've made a little modifications in your code. I removed the function "WideExpandFileName" since it's already exist in TTnt code. Then I changed the name "GetUniversalName" to "WideGetUniversalName".

I've some questions regarding the code:
What are the function "InitFastContentSearch" and "WildcardMatches" used for? Could you explain the "Character Map" technique?

What is the purpose of these lines:
Code: Select all
{$IFNDEF COMPILER6_UP}
uses Forms;
{$ENDIF}


If the TFindFile is updated, would you update the TFindFileW too?
Attachments
FindFileW.pas
(52.77 KiB) Downloaded 122 times
avushoi
Active Member
Active Member
 
Posts: 8
Joined: March 1st, 2009, 5:07 pm

Re: [TFindFile] Request for Unicode version

Postby Kambiz » March 5th, 2009, 6:14 pm

Thank you so much for your help. I will keep FindFileW updated.

WildcardMatches is used for comparing file paths against filters (Criteria.Files.Filters property).

For case insensitive comparison, instead of converting each character to lowercase (or uppercase), I use an array for mapping characters to their lowercase.

Of course there are six kind of such arrays. These are for case sensitive, case insenstive, and whole word searches on Ansi and Unicode contents.

Code: Select all
// These arrays map each character to itself for case sensitive search
AnsiCharMap: array [AnsiChar] of AnsiChar;       
WideCharMap: array [WideChar] of WideChar;

// These arrays map each character to its lowercase for case insensitive search
AnsiLowerCharMap: array [AnsiChar] of AnsiChar; 
WideLowerCharMap: array [WideChar] of WideChar;

// These arrays map alphanumeric characters to false and other characters to true, used for whole word search
AnsiIsDelimiter: array[AnsiChar] of Boolean;
WideIsDelimiter: array[WideChar] of Boolean;


When a case sensitive search is requested, I pass AnsiLowerCharMap/WideLowerCharMap to the search function. Otherwise, I pass AnsiCharMap/WideCharMap to the search function. So, it doesn't matter which kind of search you choose, the search speed is the same.

The InitFastContentSearch procedure initializes the above arrays with the appropriate values once during application lifetime.

I hope I could describe the technique.
Kambiz
User avatar
Kambiz
Administrator
Administrator
 
Posts: 2429
Joined: March 7th, 2003, 7:10 pm

Re: [TFindFile] Request for Unicode version

Postby Kambiz » March 6th, 2009, 6:00 am

I forgot to tell about:

Code: Select all
{$IFNDEF COMPILER6_UP}
uses Forms;
{$ENDIF}


In Delphi 5 and earlier, AllocateWnd and DeallocateWnd are declared in Forms unit. However, in the newer versions of Delphi these declarations has been moved to Classes unit.
Kambiz
User avatar
Kambiz
Administrator
Administrator
 
Posts: 2429
Joined: March 7th, 2003, 7:10 pm

Re: [TFindFile] Request for Unicode version

Postby avushoi » March 6th, 2009, 1:18 pm

What's the purpose & benefit of using the character mapping? If I don't use character mapping, what's the common technique people use?

Some questions again:
* Do you know another good unicode delphi component unit besides TntUnicodeControls? Do you use TntUnicodeControls too in your application?

I forget to tell you that I'm using TntUnicodeControls v2.3.0 (old freeware). The latest version (now shareware) might already have defined "WideExpandUNCFileName".

I'm thinking that isn't it better if FindFileW depends on a free-and-still-updated unicode library? Or maybe better if the "WideXXX" functions are written into FindFileW.pas to lessen dependency to 3rd party unit file or make a unit file to hold the unicode functions and included by FindFileW.pas.

* Do you ever use delphi 2009? Is Delphi 2009 better than Delphi 7? If so, do you think that I should switch to Delphi 2009?

It's me that should thank to you.
You're very kind to lend your little time to help me.
Btw, I like this smily: \:D/
avushoi
Active Member
Active Member
 
Posts: 8
Joined: March 1st, 2009, 5:07 pm

Re: [TFindFile] Request for Unicode version

Postby Kambiz » March 6th, 2009, 4:29 pm

By using character mapping we do case insensitive character comparison as:

Code: Select all
if LowerCharMap[C1] = LowerCharMap[C2] then
  // do something

without it we have to use something like:

Code: Select all
if UpCase(C1) = UpCase[C2] then
  // do something

The first method is more efficient.


Delphi 2009 is the best Delphi ever but I stuck to Delphi 7 and TntUnicodeControls v2.3.0 because it is cheaper to use what already we have.

There is also another Unicode library which is just a single unit written by Mike Lischke. Because it's free and simple, I am going to use it for FindFileW.
Kambiz
User avatar
Kambiz
Administrator
Administrator
 
Posts: 2429
Joined: March 7th, 2003, 7:10 pm

Re: [TFindFile] Request for Unicode version

Postby avushoi » March 10th, 2009, 1:16 pm

Once again, thx for your replies.

Delphi 2009 is the best Delphi ever but I stuck to Delphi 7 and TntUnicodeControls v2.3.0 because it is cheaper to use what already we have.

Do you plan to replace the delphi 7 with delphi 2009 in the future?

There is also another Unicode library which is just a single unit written by Mike Lischke. Because it's free and simple, I am going to use it for FindFileW.

Good decision.

Are you going to include the FindFileW with FindFile together or separated?
Which page that I should check for the later FindFileW release?

I have a question below that not related to programming, you don't need to answer it if you don't want to.
Are you really iranian? Because you looks like mexican in your avatar.
avushoi
Active Member
Active Member
 
Posts: 8
Joined: March 1st, 2009, 5:07 pm

Next

Return to DELPHI AREA Projects

Who is online

Users browsing this forum: No registered users and 3 guests

cron