"Martin Fuchs" martin-fuchs@gmx.net wrote:
Changelog: switch winefile to UNICODE mode
Why to go through all this pain and not just make it unicode only?
Changelog: switch winefile to UNICODE mode
Why to go through all this pain and not just make it unicode only?
First of all: Winefile was designed to be usable both in ANSI and UNICODE mode from the begin on, and I won't remove this functionality. So you can build and use it also on 8 bit systems like Win 9x. Purists may also see it as a possibility to save a view bytes of runtime memory. Think about embedded systems, where you don't have available gigs of memory.
For your standpoint this argument may be more adequate: WINE wants to be compatible to Microsoft's headers. So there also has to be a tchar.h header with all its ANSI/UNICODE functionality. You may see winefile as a test application for this header. If some thing breaks tchar.h, you might find this problem by compiling winefile.
Regards,
Martin
Dmitry,
switch winefile to UNICODE mode
Why to go through all this pain and not just make it unicode only?
currently it's impossible to compile winefile in UNICODE mode with Wine without some extra rule for unixcalls.c in the Makefile. I tried it even without using any TCHAR functions or types, but inserting include/msvcrt in the include path conflicts with inclusion of the header files I need to call the Unix file system functions (that, which I moved out of the main module into the new module unixcalls.c).
Any suggestions?
Regards,
Martin
Hi Martin,
currently it's impossible to compile winefile in UNICODE mode with Wine without some extra rule for unixcalls.c in the Makefile. I tried it even without using any TCHAR functions or types, but inserting include/msvcrt in the include path conflicts with inclusion of the header files I need to call the Unix file system functions (that, which I moved out of the main module into the new module unixcalls.c).
I assume you only need include/msvcrt for unixcalls.c to be able to include tchar.h. I assume the reason why tchar.h only works with msvcrt is that gcc uses 4 bytes for wchar_t and wcs*() functions. Although you can force gcc to use only 2 bytes (like it is the case in Windows), the glibc wcs*() will most likely not behave correctly.
So I see two solutions: (1) make a hard break and change the whole winefile to Unicode. For unixcalls.c you can rely on the Windows API for manipulating Unicode strings. Before calling the Unix functions, convert the Unicode string to Ansi using WideCharToMultiByte(). Don't forget to add "-fshort-wchar" to gcc options to get a 2 byte wchar_t.
(2) use TCHAR type. For unixcalls.c just be sure to include winnt.h (should be included automatically). It defines the TCHAR type and the TEXT() macro. For string manipulation you can again rely on the Windows API functions like lstrcpyn, lstrcat etc.
Either way you can avoid to use msvcrt for unixcalls.c.
Regards Ralf
Hello Ralf,
I assume you only need include/msvcrt for unixcalls.c to be able to include tchar.h. I assume the reason why tchar.h only works with msvcrt
No, I don't need tchar.h in 'unixcalls.c'. I only needed it for 'winefile.c'. The problem is, if I add 'include/msvcrt' to the include path, it is added to both files at the same time.
is that gcc uses 4 bytes for wchar_t and wcs*() functions. Although you can force gcc to use only 2 bytes (like it is the case in Windows), the glibc wcs*() will most likely not behave correctly.
So I see two solutions: (1) make a hard break and change the whole winefile to Unicode. For unixcalls.c you can rely on the Windows API for manipulating Unicode
I can't find a replacement for wcsrchr() in the windows API, so I have to include my own implementation in the source. There is also no equivalent of towupper(), so I have to change the pattern matching function a bit.
strings. Before calling the Unix functions, convert the Unicode string to Ansi using WideCharToMultiByte(). Don't forget to add "-fshort-wchar" to gcc options to get a 2 byte wchar_t.
I thought it is not allowed to use the "-fshort-wchar" option in Wine because not all compilers support it? If it is - using which macro should one add it to Makefile.in? Anyways - I don't need it, because there are no more literal wide string character constants.
Thanks,
Martin
So I see two solutions: (1) make a hard break and change the whole winefile to Unicode. For unixcalls.c you can rely on the Windows API for manipulating Unicode
I can't find a replacement for wcsrchr() in the windows API, so I have to include my own implementation in the source. There is also no equivalent of towupper(), so I have to change the pattern matching function a bit.
wcsrchr() is problematic, but can probalby be done with CharPrevW() loops.
CharUpperW() is towupper().
Ciao, Marcus
I can't find a replacement for wcsrchr() in the windows API, so I have to include my own implementation in the source. There is also no equivalent of towupper(), so I have to change the pattern matching function a bit.
wcsrchr() is problematic, but can probalby be done with CharPrevW() loops.
I thought it would be enough just to use "--ptr" to go back one character in UCS-16 strings. Only MBCS or UTF-8 encoded strings would need such helper functions like CharPrevW()?
CharUpperW() is towupper().
Well, CharUpper() works with strings instead of characters. So that's what I changed in the pattern matching function.
But the biggest problem I forgot about before is wsprintf(). Wine's wsprintf() implementation only handles 64 bit integer formats ("%Ld", "%Lx") when using msvcrt. So I will have to use LoadLibrary() and GetProcAddress() to call vswprintf() for this string formats.
Regards,
Martin
On Sun, Jul 03, 2005 at 01:31:06PM +0200, Martin Fuchs wrote:
I can't find a replacement for wcsrchr() in the windows API, so I have to include my own implementation in the source. There is also no equivalent of towupper(), so I have to change the pattern matching function a bit.
wcsrchr() is problematic, but can probalby be done with CharPrevW() loops.
I thought it would be enough just to use "--ptr" to go back one character in UCS-16 strings. Only MBCS or UTF-8 encoded strings would need such helper functions like CharPrevW()?
Should be, yes. Very likely CharPrevW() is just a TCHAR equivalent of CharPrevA().
CharUpperW() is towupper().
Well, CharUpper() works with strings instead of characters. So that's what I changed in the pattern matching function.
No, it also works on characters. Check MSDN. ;)
But the biggest problem I forgot about before is wsprintf(). Wine's wsprintf() implementation only handles 64 bit integer formats ("%Ld", "%Lx") when using msvcrt. So I will have to use LoadLibrary() and GetProcAddress() to call vswprintf() for this string formats.
Don't know about that.
Ciao, Marcus
CharUpperW() is towupper().
Well, CharUpper() works with strings instead of characters. So that's what I changed in the pattern matching function.
No, it also works on characters. Check MSDN. ;)
# [in/out] Pointer to a null-terminated string or specifies a single character. # If the high-order word of this parameter is zero, the low-order word must # contain a single character to be converted.
What a hack! ;-)
On Sun, 2005-07-03 at 13:31 +0200, Martin Fuchs wrote:
I thought it would be enough just to use "--ptr" to go back one character in UCS-16 strings. Only MBCS or UTF-8 encoded strings would need such helper functions like CharPrevW()?
IIRC there are these 'surrogate pairs' in which case just --ptr will not work correctly: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/indexsrv/ht...
I thought it would be enough just to use "--ptr" to go back one character in UCS-16 strings. Only MBCS or UTF-8 encoded strings would need such helper functions like CharPrevW()?
IIRC there are these 'surrogate pairs' in which case just --ptr will not work correctly: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/indexsrv/ht...
Thanks for the pointer. I found this web about UTF-16 surrogate pairs page with translation table even more enlighting: http://www.i18nguy.com/unicode/surrogatetable.html#jump
Because I'm only using the routine to search for the last dot character in strings to determine file extensions, there is no problem. The code for '.' is not present in the surrogate code range. So just advancing back in the string using pointer decreasing is enough.
Regards,
Martin
No, I don't need tchar.h in 'unixcalls.c'. I only needed it for 'winefile.c'. The problem is, if I add 'include/msvcrt' to the include path, it is added to both files at the same time.
I see. What about adding a separate rule to Makefile.in just for unixcalls.c and omit that file from C_SRC? That way you can control again which parameters will be passed to gcc. As unixcalls.c is not a "traditional" windows source file, but a bridge to the Unix system, I think that approach should be OK.
But the biggest problem I forgot about before is wsprintf(). Wine's wsprintf() implementation only handles 64 bit integer formats ("%Ld", "%Lx") when using msvcrt. So I will have to use LoadLibrary() and GetProcAddress() to call vswprintf() for this string formats.
According to MSDN, wsprintf() does not handle INT64 et all. So Wine is correct when it does not either. http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/w inui/windowsuserinterface/resources/strings/stringreference/stringfuncti ons/wsprintf.asp
So dynamically linking to msvcrt seems to be the only possible solution.
I thought it is not allowed to use the "-fshort-wchar" option in Wine because not all compilers support it? If it is - using which macro should one add it to Makefile.in? Anyways - I don't need it, because there are no more literal wide string character constants.
You are right, it is NOT allowed in Wine code since it's not portable between compilers. There WCHAR[] is the right choice. However it is for Winelib applications (at least the docs suggest it). As Winefile is on one hand a Winelib application but on the other part of the official Wine distribution, I recommend to use WCHAR[] when you need Unicode string literals - that's the safe side. ;-)
CharUpperW() ... What a hack! ;-)
There are many Windows API functions that use a similar pattern. For example the resource loading functions like LoadIcon() do the same, i.e. they interpret the given resource name as WORD if HIWORD(pszResource) is 0 or as string otherwise. That's what MAKEINTRESOURCE() is all about. I call it the C way of "function overloading". ;-)
Regards Ralf
No, I don't need tchar.h in 'unixcalls.c'. I only needed it for 'winefile.c'. The problem is, if I add 'include/msvcrt' to the include path, it is added to both files at the same time.
I see. What about adding a separate rule to Makefile.in just for unixcalls.c and omit that file from C_SRC? That way you can control again which parameters will be passed to gcc. As unixcalls.c is not a "traditional" windows source file, but a bridge to the Unix system, I think that approach should be OK.
Handling unixcalls.o separate in the makefile has been the approach in my last patch version. Alexandre was not very fond of it. ;-(
But the biggest problem I forgot about before is wsprintf(). Wine's wsprintf() implementation only handles 64 bit integer formats ("%Ld", "%Lx") when using msvcrt. So I will have to use LoadLibrary() and GetProcAddress() to call vswprintf() for this string formats.
According to MSDN, wsprintf() does not handle INT64 et all. So Wine is correct when it does not either. http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/w inui/windowsuserinterface/resources/strings/stringreference/stringfuncti ons/wsprintf.asp
May be it is not documented in MSDN. But using the format string '%I64d" on Windows works pretty well with all of the following functions:
sprintf(), swprintf(), wsprintfA(), wsprintfW()
With Winelib it seems, I have to use instead "%Ld" with sprintf() resp. swprintf() in MSVCRT.DLL.
So dynamically linking to msvcrt seems to be the only possible solution.
Yes - not very nice, but at least it works.
Regards,
Martin