08 April 2009

ANSI API functions and RichEdit

Recently someone patched the GfaWin23.Ocx DLL by replacing the "RichEd20.dll" text entry by "MsftEdit.dll" and "RichEdit20A" by "RICHEDIT50W". The patch isn't very difficult since both text entries are equally sized. The patch was made to obtain the functionallity of the RichEdit Control version 4.0 (which for some reason is called 50) by the GFA-BASIC 32 Ocx interface. By pathing the Ocx file this way, he succeeded in using the "msftEdit.dll. So far so good, but the patch raised a question for me. Why would this control only register a "RICHEDIT50W" class and not a "RICHEDIT50A" ANSI variant? What effect would that have on GFA-BASIC 32 using ANSI functions only?

Previous RichEdit control versions (3.0, 2.0) support two window classes "RichEdit20A" for ANSI systems and "RichEdit20W" for UNICODE systems. When you were compiling a program (in C/C++) for a UNICODE program you would use the "RichEdit20W" class in the CreateWindowExW() API function. GFA-BASIC 32 uses the "RichEdit20A" window class to create a RichEdit Ocx using CreateWindowExA. The properties and methods of the RichEdit Ocx are implemented by sending control messages using SendMessageA().

After patching the rich edit control is created by invoking CreateWindowExA and passing a pointer to an ANSI string containing "RICHEDIT50W". How can that work? The new control only supports wide character coding, how can it accept an ANSI string? I think I found the answer. ANSI API functions are redirected to the wide (UNICODE) variant.

When a program is specifically created as a UNICODE application (which is possible only for NT 4.0 and higher) it uses the UNICODE versions of the system API functions. All API functions have an ANSI and a UNICODE variant with different(!) entry points in the system DLLs. For instance, the SendMessage() API comes in two variants: SendMessageA() and SendMessageW(), two different functions. The xW() system functions expect strings formatted in UNICODE format. On UNICODE Windows systems (thus everything above Windows 95/98/Me) the ANSI versions of the API functions first translate a string parameter to UNICODE and then call the xW() version passing the newly created UNICODE string. This makes ANSI programs quite slow when API functions use strings (upto 3 times, see "Under the Hood 1997" by Matt Pietrek).

GFA-BASIC 32 is an ANSI program and invokes only the xA() versions of the Windows API. Therefor, on Windows NT 4 and above any string passed is converted to UNICODE before handled in the xW() version of the function. (GFA-BASIC 32 is not prepared for pure UNICODE systems, it had to run on Winddows 95 as well.) Back to the question, why does the MsftEdit.Dll accept an ANSI string in CreateWindowExA()?Because in turn the CreateWindowExA() calls CreateWindowExW() on any 'not Win95/98/Me' system passing the classname "RICHEDIT50W" as a UNICODE string. This means, according to my findings that the MsftEdit.dll won't run under Windows 95 when used from the patched GFA-BASIC 32 Ocx-dll. These Windows systems don't redirect to a wide version of the API function.

BTW It might be useful to know how GFA-BASIC loads the appropriate richedit dll. Just before a RichEdit Ocx control is created, GFA-BASIC 32 loads the appropriate library, as follows: If hLibRichEd == 0 hLibRichEd = LoadLibraryA("RichEd20.dll") If hLibRichEd == 0 hLibRichEd = LoadLibraryA("RichEd32.dll") If hLibRichEd == 0 Then RaiseErr "OutOfMemory" Endif Endif Then "RichEdit20A" is used in a CreateWindowExA() API call to create a control window of the this class.

2 comments:

  1. Hi:

    This is not strictly a comment on this post but here goes anyway. In the early 1980's, I was one of the first users of GFA Basic for the Atari ST in the UK. I still have both my old ST and the full GFA package both of which I found excellent in their day. I also still have copies of the GFA Users mag which ran in the UK. I'm planning to start using GFA Basic on my PC under Windows and would like to know if there is a version that will run under Linux without Virtual Machine software.

    Can you help?

    Cheers,

    Mike Oliver

    ReplyDelete
  2. Hi Mike,

    I'm sorry to say, but GFA-BASIC was never released for Linux, it is strictly Windows.
    When GFA-BASIC for MSDOS was first released there was a Linux annoucement for 'GfaBasix'. But at the same time Windows 3.1 became very popular and GFA choose for the GFA-BASIC for Windows 3.1 16-bit.

    Sjouke

    ReplyDelete