Index: guitest.pm =================================================================== RCS file: /cvsroot/winguitest/Win32-GuiTest/guitest.pm,v retrieving revision 1.13 diff -u -r1.13 guitest.pm --- guitest.pm 30 May 2004 18:01:15 -0000 1.13 +++ guitest.pm 24 Jun 2004 22:27:51 -0000 @@ -94,11 +94,11 @@ %EXPORT_TAGS=( FUNC => [ qw( CheckButton ClientToScreen EnableWindow FindWindowLike - GetActiveWindow GetCaretPos GetChildDepth GetChildWindows GetClassName - GetComboContents GetComboText GetCursorPos GetDesktopWindow GetFocus - GetForegroundWindow GetListContents GetListText GetMenu GetParent + GetActiveWindow GetCaretPos GetChildDepth GetChildWindows GetClassName GetClassNameW + GetComboContents GetComboContentsW GetComboText GetComboTextW GetCursorPos GetDesktopWindow GetFocus + GetForegroundWindow GetListContents GetListContentsW GetListText GetListTextW GetMenu GetParent GetScreenRes GetSystemMenu GetWindow GetWindowID GetWindowLong - GetWindowRect GetWindowText IsCheckedButton IsChild IsGrayedButton + GetWindowRect GetWindowText GetWindowTextW IsCheckedButton IsChild IsGrayedButton IsKeyPressed IsWindow IsWindowEnabled IsWindowStyle IsWindowStyleEx IsWindowVisible MenuSelect MouseClick MouseMoveAbsPix NormToScreen PostMessage PushButton PushChildButton ScreenToClient ScreenToNorm SelectTabItem @@ -106,8 +106,8 @@ SendMessage SendMouse SendMouseMoveAbs SendMouseMoveRel SendRButtonDown SendRButtonUp SetActiveWindow SetForegroundWindow SetWindowPos ShowWindow TabCtrl_SetCurFocus TabCtrl_GetCurFocus - TabCtrl_SetCurSel TabCtrl_GetItemCount WMGetText WMSetText WaitWindow - WaitWindowLike SendRawKey WindowFromPoint + TabCtrl_SetCurSel TabCtrl_GetItemCount WMGetText WMGetTextW WMSetText WaitWindow + WaitWindowLike SendRawKey WindowFromPoint UseUnicodeFunctions )], VARS => [ qw( $debug @@ -154,6 +154,22 @@ require "Win32/GuiTest/GuiTest.pc"; +sub UseUnicodeFunctions { + no strict 'refs'; + for my $f (qw(GetClassName GetComboText GetComboContents GetListText GetListContents + GetWindowText WMGetText)) { + *{$f} = *{"${f}W"}; + } +} + +BEGIN { + my (undef, $major, undef, undef, $id) = Win32::GetOSVersion(); + if (($id > 1) && ($major > 3)) { + UseUnicodeFunctions(); + } +} + + =head2 Functions =over 4 Index: guitest.xs =================================================================== RCS file: /cvsroot/winguitest/Win32-GuiTest/guitest.xs,v retrieving revision 1.7 diff -u -r1.7 guitest.xs --- guitest.xs 29 May 2004 12:28:28 -0000 1.7 +++ guitest.xs 24 Jun 2004 22:27:51 -0000 @@ -18,6 +18,17 @@ #include #include "dibsect.h" +// For Windows 2000+, compile the Unicode functions +// in addition to single-byte-characters functions. +// TBD whether there is a more reliable way of +// predicting whether the proper Unicode support +// exists in Windows. +// (The Unicode algorithm here relies on the UTF-8 +// support in Windows' conversion functions, +// which is absent in Windows NT.) +#if WINVER >= 0x0500 +#define GUITEST_XS__DO_UNICODE +#endif #ifdef __cplusplus //extern "C" { @@ -395,6 +406,60 @@ return sv; } +#ifdef GUITEST_XS__DO_UNICODE + + +// Return Perl string (SV*) containing UTF-8 representation of a +// Windows wide-character (UCS2-LE) string. Set the Perl-string's UTF-8 flag +// optimally, i.e., only in case the resulting string actually contains +// at least one character whose UTF-8 representation takes more +// than one byte. + +SV* +ucs2le_to_sv(LPWSTR ucs2le) +{ + // Allocate UTF-8 buffer. + // It might take up to 6 bytes per character. + // Include room for terminal \0 character. + int cch = 1 + wcslen(ucs2le); + int u8_baggy_buffer_size = cch * 6; + U8 *u8_baggy_buffer = (U8*)safemalloc(u8_baggy_buffer_size); + + // Translate UCS2LE to UTF8 using Windows API + int u8cb = WideCharToMultiByte( + CP_UTF8, 0, ucs2le, cch, u8_baggy_buffer, + u8_baggy_buffer_size, NULL, NULL); + int multibyte_chars = (u8cb != cch); + + // Copy the result to a Perl string. + SV *rv = newSVpv(u8_baggy_buffer, u8cb - 1); + + // Set Perl-string's UTF8 flag iff there are actually + // any multibyte characters in the UTF8 representation. + // Leave flag off if UTF8 coincides with 7-bit ASCII. + if (multibyte_chars) + SvUTF8_on(rv); + + safefree(u8_baggy_buffer); + + return rv; +} + +SV* +GetTextHelperW(HWND hwnd, int index, UINT lenmsg, UINT textmsg) +{ + SV* sv = 0; + int len = SendMessage(hwnd, lenmsg, index, 0L); + wchar_t* text = (wchar_t*)safemalloc((len+1) * sizeof(*text)); + if (text != 0) { + SendMessageW(hwnd, textmsg, index, (LPARAM)text); + sv = ucs2le_to_sv(text); + safefree(text); + } + return sv; +} + +#endif MODULE = Win32::GuiTest PACKAGE = Win32::GuiTest @@ -561,6 +626,25 @@ OUTPUT: RETVAL +#ifdef GUITEST_XS__DO_UNICODE + +SV* +GetWindowTextW(hwnd) + HWND hwnd + CODE: + int cch_ubound; + LPWSTR ucs2le; + cch_ubound = GetWindowTextLengthW(hwnd)+1;// room for \0 + ucs2le = safemalloc(cch_ubound * sizeof(wchar_t)); + *ucs2le = L'\0'; // in case GetWindowText fails + GetWindowTextW(hwnd, ucs2le, cch_ubound); + RETVAL = ucs2le_to_sv(ucs2le); + safefree(ucs2le); + OUTPUT: + RETVAL + +#endif + SV* GetClassName(hwnd) HWND hwnd @@ -573,6 +657,22 @@ OUTPUT: RETVAL +#ifdef GUITEST_XS__DO_UNICODE + +SV* +GetClassNameW(hwnd) + HWND hwnd + CODE: + SV* sv; + wchar_t wtext[255]; + int r; + r = GetClassNameW(hwnd, wtext, (sizeof wtext)/sizeof*wtext); + RETVAL = ucs2le_to_sv(wtext); + OUTPUT: + RETVAL + +#endif + HWND GetParent(hwnd) HWND hwnd @@ -641,6 +741,28 @@ OUTPUT: RETVAL +#ifdef GUITEST_XS__DO_UNICODE + +SV* +WMGetTextW(hwnd) + HWND hwnd + CODE: + SV* sv; + wchar_t* text; + int len = SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0L); + text = (wchar_t*)safemalloc((len+1) * sizeof(*text)); + if (text != 0) { + SendMessageW(hwnd, WM_GETTEXT, (WPARAM)len + 1, (LPARAM)text); + RETVAL = ucs2le_to_sv(text); + safefree(text); + } else { + RETVAL = 0; + } + OUTPUT: + RETVAL + +#endif + int WMSetText(hwnd, text) HWND hwnd @@ -949,6 +1071,48 @@ XPUSHs(sv_2mortal(GetTextHelper(hWnd, i, LB_GETTEXTLEN, LB_GETTEXT))); } +#ifdef GUITEST_XS__DO_UNICODE + +SV* +GetComboTextW(hwnd, index) + HWND hwnd; + int index + CODE: + RETVAL = GetTextHelperW(hwnd, index, CB_GETLBTEXTLEN, CB_GETLBTEXT); + OUTPUT: + RETVAL + +SV* +GetListTextW(hwnd, index) + HWND hwnd; + int index + CODE: + RETVAL = GetTextHelperW(hwnd, index, LB_GETTEXTLEN, LB_GETTEXT); + OUTPUT: + RETVAL + +void +GetComboContentsW(hWnd) + HWND hWnd; +PPCODE: + int nelems = SendMessage(hWnd, CB_GETCOUNT, 0, 0); + int i; + for (i = 0; i < nelems; i++) { + XPUSHs(sv_2mortal(GetTextHelperW(hWnd, i, CB_GETLBTEXTLEN, CB_GETLBTEXT))); + } + +void +GetListContentsW(hWnd) + HWND hWnd; +PPCODE: + int nelems = SendMessage(hWnd, LB_GETCOUNT, 0, 0); + int i; + for (i = 0; i < nelems; i++) { + XPUSHs(sv_2mortal(GetTextHelperW(hWnd, i, LB_GETTEXTLEN, LB_GETTEXT))); + } + +#endif + BOOL IsKeyPressed(name) char* name; Index: eg/keypress.pl =================================================================== RCS file: /cvsroot/winguitest/Win32-GuiTest/eg/keypress.pl,v retrieving revision 1.3 diff -u -r1.3 keypress.pl --- eg/keypress.pl 21 Mar 2004 08:21:28 -0000 1.3 +++ eg/keypress.pl 24 Jun 2004 22:27:51 -0000 @@ -3,7 +3,7 @@ # This example shows an easy way to check for certain keystrokes. # The IsKeyPressed function takes a string with the name of the key. # This names are the same ones as for SendKeys. - +use utf8; use Win32::GuiTest qw(SendKeys IsKeyPressed); # Wait until user presses several specified keys