X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/885b88a2575bafdd064a778e867dd89783309f90..ba8c878f957da36c14879b747a2d54d7fe01baa8:/src/msw/utils.cpp diff --git a/src/msw/utils.cpp b/src/msw/utils.cpp index 74117167a3..4e674fcbde 100644 --- a/src/msw/utils.cpp +++ b/src/msw/utils.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: msw/utils.cpp +// Name: src/msw/utils.cpp // Purpose: Various utilities // Author: Julian Smart // Modified by: @@ -31,24 +31,31 @@ #include "wx/log.h" #endif //WX_PRECOMP +#include "wx/msw/registry.h" #include "wx/apptrait.h" +#include "wx/dynlib.h" #include "wx/dynload.h" +#include "wx/scopeguard.h" #include "wx/confbase.h" // for wxExpandEnvVars() #include "wx/msw/private.h" // includes -#include "wx/msw/missing.h" // CHARSET_HANGUL +#include "wx/msw/missing.h" // for CHARSET_HANGUL + +#if defined(__CYGWIN__) + //CYGWIN gives annoying warning about runtime stuff if we don't do this +# define USE_SYS_TYPES_FD_SET +# include +#endif -#if defined(__GNUWIN32_OLD__) || defined(__WXWINCE__) \ - || defined(__CYGWIN32__) +// Doesn't work with Cygwin at present +#if wxUSE_SOCKETS && (defined(__GNUWIN32_OLD__) || defined(__WXWINCE__) || defined(__CYGWIN32__)) // apparently we need to include winsock.h to get WSADATA and other stuff // used in wxGetFullHostName() with the old mingw32 versions #include #endif -#include "wx/timer.h" - -#if !defined(__GNUWIN32__) && !defined(__SALFORDC__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__) +#if !defined(__GNUWIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__) #include #ifndef __MWERKS__ @@ -102,8 +109,13 @@ // ---------------------------------------------------------------------------- // In the WIN.INI file +#if (!defined(USE_NET_API) && !defined(__WXWINCE__)) || defined(__WXMICROWIN__) static const wxChar WX_SECTION[] = wxT("wxWindows"); +#endif + +#if (!defined(USE_NET_API) && !defined(__WXWINCE__)) static const wxChar eUSERNAME[] = wxT("UserName"); +#endif // ============================================================================ // implementation @@ -114,9 +126,11 @@ static const wxChar eUSERNAME[] = wxT("UserName"); // ---------------------------------------------------------------------------- // Get hostname only (without domain name) -bool wxGetHostName(wxChar *buf, int maxSize) +bool wxGetHostName(wxChar *WXUNUSED_IN_WINCE(buf), + int WXUNUSED_IN_WINCE(maxSize)) { #if defined(__WXWINCE__) + // TODO-CE return false; #elif defined(__WIN32__) && !defined(__WXMICROWIN__) DWORD nSize = maxSize; @@ -144,7 +158,7 @@ bool wxGetHostName(wxChar *buf, int maxSize) // get full hostname (with domain name if possible) bool wxGetFullHostName(wxChar *buf, int maxSize) { -#if !defined( __WXMICROWIN__) && wxUSE_DYNAMIC_LOADER +#if !defined( __WXMICROWIN__) && wxUSE_DYNLIB_CLASS && wxUSE_SOCKETS // TODO should use GetComputerNameEx() when available // we don't want to always link with Winsock DLL as we might not use it at @@ -226,9 +240,11 @@ bool wxGetFullHostName(wxChar *buf, int maxSize) } // Get user ID e.g. jacs -bool wxGetUserId(wxChar *buf, int maxSize) +bool wxGetUserId(wxChar *WXUNUSED_IN_WINCE(buf), + int WXUNUSED_IN_WINCE(maxSize)) { #if defined(__WXWINCE__) + // TODO-CE return false; #elif defined(__WIN32__) && !defined(__WXMICROWIN__) DWORD nSize = maxSize; @@ -250,8 +266,8 @@ bool wxGetUserId(wxChar *buf, int maxSize) // Can't assume we have NIS (PC-NFS) or some other ID daemon // So we ... - if ( (user = wxGetenv(wxT("USER"))) == NULL && - (user = wxGetenv(wxT("LOGNAME"))) == NULL ) + if ( (user = wxGetenv(wxT("USER"))) == NULL && + (user = wxGetenv(wxT("LOGNAME"))) == NULL ) { // Use wxWidgets configuration data (comming soon) GetProfileString(WX_SECTION, eUSERID, default_id, buf, maxSize - 1); @@ -268,8 +284,19 @@ bool wxGetUserId(wxChar *buf, int maxSize) // Get user name e.g. Julian Smart bool wxGetUserName(wxChar *buf, int maxSize) { -#if defined(__WXWINCE__) - return false; + wxCHECK_MSG( buf && ( maxSize > 0 ), false, + _T("empty buffer in wxGetUserName") ); +#if defined(__WXWINCE__) && wxUSE_REGKEY + wxLogNull noLog; + wxRegKey key(wxRegKey::HKCU, wxT("ControlPanel\\Owner")); + if(!key.Open(wxRegKey::Read)) + return false; + wxString name; + if(!key.QueryValue(wxT("Owner"),name)) + return false; + wxStrncpy(buf, name.c_str(), maxSize-1); + buf[maxSize-1] = _T('\0'); + return true; #elif defined(USE_NET_API) CHAR szUserName[256]; if ( !wxGetUserId(szUserName, WXSIZEOF(szUserName)) ) @@ -349,9 +376,9 @@ error: { wxStrncpy(buf, wxT("Unknown User"), maxSize); } -#endif // Win32/16 return true; +#endif // Win32/16 } const wxChar* wxGetHomeDir(wxString *pstr) @@ -359,7 +386,7 @@ const wxChar* wxGetHomeDir(wxString *pstr) wxString& strDir = *pstr; // first branch is for Cygwin -#if defined(__UNIX__) +#if defined(__UNIX__) && !defined(__WINE__) const wxChar *szHome = wxGetenv("HOME"); if ( szHome == NULL ) { // we're homeless... @@ -380,7 +407,7 @@ const wxChar* wxGetHomeDir(wxString *pstr) strDir = windowsPath; #endif #elif defined(__WXWINCE__) - // Nothing + strDir = wxT("\\"); #else strDir.clear(); @@ -440,29 +467,22 @@ const wxChar* wxGetHomeDir(wxString *pstr) return strDir.c_str(); } -wxChar *wxGetUserHome(const wxString& WXUNUSED(user)) +wxString wxGetUserHome(const wxString& user) { - // VZ: the old code here never worked for user != "" anyhow! Moreover, it - // returned sometimes a malloc()'d pointer, sometimes a pointer to a - // static buffer and sometimes I don't even know what. - static wxString s_home; + wxString home; - return (wxChar *)wxGetHomeDir(&s_home); -} + if ( user.empty() || user == wxGetUserId() ) + wxGetHomeDir(&home); -bool wxDirExists(const wxString& dir) -{ -#ifdef __WXMICROWIN__ - return wxPathExist(dir); -#elif defined(__WIN32__) - DWORD attribs = GetFileAttributes(dir); - return ((attribs != (DWORD)-1) && (attribs & FILE_ATTRIBUTE_DIRECTORY)); -#endif // Win32/__WXMICROWIN__ + return home; } -bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree) +bool wxGetDiskSpace(const wxString& WXUNUSED_IN_WINCE(path), + wxDiskspaceSize_t *WXUNUSED_IN_WINCE(pTotal), + wxDiskspaceSize_t *WXUNUSED_IN_WINCE(pFree)) { #ifdef __WXWINCE__ + // TODO-CE return false; #else if ( path.empty() ) @@ -494,7 +514,7 @@ bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree) ULARGE_INTEGER bytesFree, bytesTotal; // may pass the path as is, GetDiskFreeSpaceEx() is smart enough - if ( !pGetDiskFreeSpaceEx(path, + if ( !pGetDiskFreeSpaceEx(path.fn_str(), &bytesFree, &bytesTotal, NULL) ) @@ -514,12 +534,20 @@ bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree) #endif if ( pTotal ) { - *pTotal = wxLongLong(UL(bytesTotal).HighPart, UL(bytesTotal).LowPart); +#if wxUSE_LONGLONG + *pTotal = wxDiskspaceSize_t(UL(bytesTotal).HighPart, UL(bytesTotal).LowPart); +#else + *pTotal = wxDiskspaceSize_t(UL(bytesTotal).LowPart); +#endif } if ( pFree ) { +#if wxUSE_LONGLONG *pFree = wxLongLong(UL(bytesFree).HighPart, UL(bytesFree).LowPart); +#else + *pFree = wxDiskspaceSize_t(UL(bytesFree).LowPart); +#endif } } else @@ -536,7 +564,7 @@ bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree) // FIXME: this is wrong, we should extract the root drive from path // instead, but this is the job for wxFileName... - if ( !::GetDiskFreeSpace(path, + if ( !::GetDiskFreeSpace(path.fn_str(), &lSectorsPerCluster, &lBytesPerSector, &lNumberOfFreeClusters, @@ -547,7 +575,7 @@ bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree) return false; } - wxLongLong lBytesPerCluster = lSectorsPerCluster; + wxDiskspaceSize_t lBytesPerCluster = (wxDiskspaceSize_t) lSectorsPerCluster; lBytesPerCluster *= lBytesPerSector; if ( pTotal ) @@ -572,13 +600,15 @@ bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree) // env vars // ---------------------------------------------------------------------------- -bool wxGetEnv(const wxString& var, wxString *value) +bool wxGetEnv(const wxString& WXUNUSED_IN_WINCE(var), + wxString *WXUNUSED_IN_WINCE(value)) { #ifdef __WXWINCE__ + // no environment variables under CE return false; #else // Win32 // first get the size of the buffer - DWORD dwRet = ::GetEnvironmentVariable(var, NULL, 0); + DWORD dwRet = ::GetEnvironmentVariable(var.wx_str(), NULL, 0); if ( !dwRet ) { // this means that there is no such variable @@ -587,7 +617,8 @@ bool wxGetEnv(const wxString& var, wxString *value) if ( value ) { - (void)::GetEnvironmentVariable(var, wxStringBuffer(*value, dwRet), + (void)::GetEnvironmentVariable(var.wx_str(), + wxStringBuffer(*value, dwRet), dwRet); } @@ -595,12 +626,16 @@ bool wxGetEnv(const wxString& var, wxString *value) #endif // WinCE/32 } -bool wxSetEnv(const wxString& var, const wxChar *value) +bool wxDoSetEnv(const wxString& WXUNUSED_IN_WINCE(var), + const wxChar *WXUNUSED_IN_WINCE(value)) { // some compilers have putenv() or _putenv() or _wputenv() but it's better // to always use Win32 function directly instead of dealing with them -#if defined(__WIN32__) && !defined(__WXWINCE__) - if ( !::SetEnvironmentVariable(var, value) ) +#ifdef __WXWINCE__ + // no environment variables under CE + return false; +#else + if ( !::SetEnvironmentVariable(var.wx_str(), value) ) { wxLogLastError(_T("SetEnvironmentVariable")); @@ -608,11 +643,19 @@ bool wxSetEnv(const wxString& var, const wxChar *value) } return true; -#else // no way to set env vars - return false; #endif } +bool wxSetEnv(const wxString& variable, const wxString& value) +{ + return wxDoSetEnv(variable, value.wx_str()); +} + +bool wxUnsetEnv(const wxString& variable) +{ + return wxDoSetEnv(variable, NULL); +} + // ---------------------------------------------------------------------------- // process management // ---------------------------------------------------------------------------- @@ -658,7 +701,7 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags) { if (flags & wxKILL_CHILDREN) wxKillAllChildren(pid, sig, krc); - + // get the process handle to operate on HANDLE hProcess = ::OpenProcess(SYNCHRONIZE | PROCESS_TERMINATE | @@ -669,19 +712,19 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags) { if ( krc ) { - if ( ::GetLastError() == ERROR_ACCESS_DENIED ) - { - *krc = wxKILL_ACCESS_DENIED; - } - else - { - *krc = wxKILL_NO_PROCESS; - } + // recognize wxKILL_ACCESS_DENIED as special because this doesn't + // mean that the process doesn't exist and this is important for + // wxProcess::Exists() + *krc = ::GetLastError() == ERROR_ACCESS_DENIED + ? wxKILL_ACCESS_DENIED + : wxKILL_NO_PROCESS; } return -1; } + wxON_BLOCK_EXIT1(::CloseHandle, hProcess); + bool ok = true; switch ( sig ) { @@ -704,7 +747,9 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags) case wxSIGNONE: // do nothing, we just want to test for process existence - break; + if ( krc ) + *krc = wxKILL_OK; + return 0; default: // any other signal means "terminate" @@ -713,7 +758,7 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags) params.pid = (DWORD)pid; // EnumWindows() has nice semantics: it returns 0 if it found - // something or if an error occured and non zero if it + // something or if an error occurred and non zero if it // enumerated all the window if ( !::EnumWindows(wxEnumFindByPidProc, (LPARAM)¶ms) ) { @@ -722,7 +767,7 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags) { // tell the app to close // - // NB: this is the harshest way, the app won't have + // NB: this is the harshest way, the app won't have an // opportunity to save any files, for example, but // this is probably what we want here. If not we // can also use SendMesageTimeout(WM_CLOSE) @@ -741,9 +786,7 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags) else // no windows for this PID { if ( krc ) - { *krc = wxKILL_ERROR; - } ok = false; } @@ -751,8 +794,7 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags) } // the return code - DWORD rc; - + DWORD rc wxDUMMY_INITIALIZE(0); if ( ok ) { // as we wait for a short time, we can use just WaitForSingleObject() @@ -777,114 +819,78 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags) case WAIT_TIMEOUT: if ( krc ) - { *krc = wxKILL_ERROR; - } rc = STILL_ACTIVE; break; } } - else // !ok - { - // just to suppress the warnings about uninitialized variable - rc = 0; - } - ::CloseHandle(hProcess); // the return code is the same as from Unix kill(): 0 if killed // successfully or -1 on error - // - // be careful to interpret rc correctly: for wxSIGNONE we return success if - // the process exists, for all the other sig values -- if it doesn't - if ( ok && - ((sig == wxSIGNONE) == (rc == STILL_ACTIVE)) ) - { - if ( krc ) - { - *krc = wxKILL_OK; - } + if ( !ok || rc == STILL_ACTIVE ) + return -1; - return 0; - } + if ( krc ) + *krc = wxKILL_OK; - // error - return -1; + return 0; } -HANDLE (WINAPI *lpfCreateToolhelp32Snapshot)(DWORD,DWORD) ; -BOOL (WINAPI *lpfProcess32First)(HANDLE,LPPROCESSENTRY32) ; -BOOL (WINAPI *lpfProcess32Next)(HANDLE,LPPROCESSENTRY32) ; - +typedef HANDLE (WINAPI *CreateToolhelp32Snapshot_t)(DWORD,DWORD); +typedef BOOL (WINAPI *Process32_t)(HANDLE,LPPROCESSENTRY32); + +CreateToolhelp32Snapshot_t lpfCreateToolhelp32Snapshot; +Process32_t lpfProcess32First, lpfProcess32Next; + static void InitToolHelp32() { static bool s_initToolHelpDone = false; - + if (s_initToolHelpDone) return; - + s_initToolHelpDone = true; lpfCreateToolhelp32Snapshot = NULL; lpfProcess32First = NULL; lpfProcess32Next = NULL; - - HINSTANCE hInstLib = LoadLibraryA( "Kernel32.DLL" ) ; - if( hInstLib == NULL ) - return ; - + +#if wxUSE_DYNLIB_CLASS + + wxDynamicLibrary dllKernel(_T("kernel32.dll"), wxDL_VERBATIM); + // Get procedure addresses. // We are linking to these functions of Kernel32 // explicitly, because otherwise a module using // this code would fail to load under Windows NT, // which does not have the Toolhelp32 // functions in the Kernel 32. - lpfCreateToolhelp32Snapshot= - (HANDLE(WINAPI *)(DWORD,DWORD)) - GetProcAddress( hInstLib, -#ifdef __WXWINCE__ - wxT("CreateToolhelp32Snapshot") -#else - "CreateToolhelp32Snapshot" -#endif - ) ; - - lpfProcess32First= - (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32)) - GetProcAddress( hInstLib, -#ifdef __WXWINCE__ - wxT("Process32First") -#else - "Process32First" -#endif - ) ; + lpfCreateToolhelp32Snapshot = + (CreateToolhelp32Snapshot_t)dllKernel.RawGetSymbol(_T("CreateToolhelp32Snapshot")); - lpfProcess32Next= - (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32)) - GetProcAddress( hInstLib, -#ifdef __WXWINCE__ - wxT("Process32Next") -#else - "Process32Next" -#endif - ) ; + lpfProcess32First = + (Process32_t)dllKernel.RawGetSymbol(_T("Process32First")); + + lpfProcess32Next = + (Process32_t)dllKernel.RawGetSymbol(_T("Process32Next")); - FreeLibrary( hInstLib ) ; +#endif // wxUSE_DYNLIB_CLASS } // By John Skiff int wxKillAllChildren(long pid, wxSignal sig, wxKillError *krc) { InitToolHelp32(); - + if (krc) *krc = wxKILL_OK; - + // If not implemented for this platform (e.g. NT 4.0), silently ignore if (!lpfCreateToolhelp32Snapshot || !lpfProcess32First || !lpfProcess32Next) return 0; - + // Take a snapshot of all processes in the system. HANDLE hProcessSnap = lpfCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hProcessSnap == INVALID_HANDLE_VALUE) { @@ -892,11 +898,12 @@ int wxKillAllChildren(long pid, wxSignal sig, wxKillError *krc) *krc = wxKILL_ERROR; return -1; } - + //Fill in the size of the structure before using it. - PROCESSENTRY32 pe = {0}; + PROCESSENTRY32 pe; + wxZeroMemory(pe); pe.dwSize = sizeof(PROCESSENTRY32); - + // Walk the snapshot of the processes, and for each process, // kill it if its parent is pid. if (!lpfProcess32First(hProcessSnap, &pe)) { @@ -906,15 +913,15 @@ int wxKillAllChildren(long pid, wxSignal sig, wxKillError *krc) CloseHandle (hProcessSnap); return -1; } - + do { if (pe.th32ParentProcessID == (DWORD) pid) { if (wxKill(pe.th32ProcessID, sig, krc)) return -1; } } while (lpfProcess32Next (hProcessSnap, &pe)); - - + + return 0; } @@ -946,14 +953,15 @@ bool wxShell(const wxString& command) } // Shutdown or reboot the PC -bool wxShutdown(wxShutdownFlags wFlags) +bool wxShutdown(wxShutdownFlags WXUNUSED_IN_WINCE(wFlags)) { #ifdef __WXWINCE__ + // TODO-CE return false; #elif defined(__WIN32__) bool bOK = true; - if ( wxGetOsVersion(NULL, NULL) == wxWINDOWS_NT ) // if is NT or 2K + if ( wxGetOsVersion(NULL, NULL) == wxOS_WINDOWS_NT ) // if is NT or 2K { // Get a token for this process. HANDLE hToken; @@ -1010,15 +1018,18 @@ bool wxShutdown(wxShutdownFlags wFlags) // ---------------------------------------------------------------------------- // Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX) -long wxGetFreeMemory() +wxMemorySize wxGetFreeMemory() { -#if defined(__WIN32__) && !defined(__BORLANDC__) +#if defined(__WIN64__) + MEMORYSTATUSEX memStatex; + memStatex.dwLength = sizeof (memStatex); + ::GlobalMemoryStatusEx (&memStatex); + return (wxMemorySize)memStatex.ullAvailPhys; +#else /* if defined(__WIN32__) */ MEMORYSTATUS memStatus; memStatus.dwLength = sizeof(MEMORYSTATUS); - GlobalMemoryStatus(&memStatus); - return memStatus.dwAvailPhys; -#else - return (long)GetFreeSpace(0); + ::GlobalMemoryStatus(&memStatus); + return (wxMemorySize)memStatus.dwAvailPhys; #endif } @@ -1033,6 +1044,29 @@ void wxBell() ::MessageBeep((UINT)-1); // default sound } +bool wxIsDebuggerRunning() +{ +#if wxUSE_DYNLIB_CLASS + // IsDebuggerPresent() is not available under Win95, so load it dynamically + wxDynamicLibrary dll(_T("kernel32.dll"), wxDL_VERBATIM); + + typedef BOOL (WINAPI *IsDebuggerPresent_t)(); + if ( !dll.HasSymbol(_T("IsDebuggerPresent")) ) + { + // no way to know, assume no + return false; + } + + return (*(IsDebuggerPresent_t)dll.GetSymbol(_T("IsDebuggerPresent")))() != 0; +#else + return false; +#endif +} + +// ---------------------------------------------------------------------------- +// OS version +// ---------------------------------------------------------------------------- + wxString wxGetOsDescription() { wxString str; @@ -1045,6 +1079,13 @@ wxString wxGetOsDescription() { switch ( info.dwPlatformId ) { +#ifdef VER_PLATFORM_WIN32_CE + case VER_PLATFORM_WIN32_CE: + str.Printf(_("Windows CE (%d.%d)"), + info.dwMajorVersion, + info.dwMinorVersion); + break; +#endif case VER_PLATFORM_WIN32s: str = _("Win32s on Windows 3.1"); break; @@ -1108,7 +1149,7 @@ wxString wxGetOsDescription() break; } } - if ( wxIsEmpty(str) ) + if ( str.empty() ) { str.Printf(_("Windows NT %lu.%lu (build %lu"), info.dwMajorVersion, @@ -1131,56 +1172,150 @@ wxString wxGetOsDescription() return str; } -wxToolkitInfo& wxAppTraits::GetToolkitInfo() +bool wxIsPlatform64Bit() +{ +#if defined(_WIN64) + return true; // 64-bit programs run only on Win64 +#elif wxUSE_DYNLIB_CLASS // Win32 + // 32-bit programs run on both 32-bit and 64-bit Windows so check + typedef BOOL (WINAPI *IsWow64Process_t)(HANDLE, BOOL *); + + wxDynamicLibrary dllKernel32(_T("kernel32.dll")); + IsWow64Process_t pfnIsWow64Process = + (IsWow64Process_t)dllKernel32.RawGetSymbol(_T("IsWow64Process")); + + BOOL wow64 = FALSE; + if ( pfnIsWow64Process ) + { + pfnIsWow64Process(::GetCurrentProcess(), &wow64); + } + //else: running under a system without Win64 support + + return wow64 != FALSE; +#else + return false; +#endif // Win64/Win32 +} + +wxOperatingSystemId wxGetOsVersion(int *verMaj, int *verMin) { - // cache the version info, it's not going to change - // - // NB: this is MT-safe, we may use these static vars from different threads - // but as they always have the same value it doesn't matter - static int s_ver = -1, - s_major = -1, - s_minor = -1; - - if ( s_ver == -1 ) + static struct + { + // this may be false, true or -1 if we tried to initialize but failed + int initialized; + + wxOperatingSystemId os; + + int verMaj, + verMin; + } s_version; + + // query the OS info only once as it's not supposed to change + if ( !s_version.initialized ) { OSVERSIONINFO info; wxZeroMemory(info); - - s_ver = wxWINDOWS; - info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + info.dwOSVersionInfoSize = sizeof(info); if ( ::GetVersionEx(&info) ) { - s_major = info.dwMajorVersion; - s_minor = info.dwMinorVersion; + s_version.initialized = true; +#if defined(__WXWINCE__) + s_version.os = wxOS_WINDOWS_CE; +#elif defined(__WXMICROWIN__) + s_version.os = wxOS_WINDOWS_MICRO; +#else // "normal" desktop Windows system, use run-time detection switch ( info.dwPlatformId ) { - case VER_PLATFORM_WIN32s: - s_ver = wxWIN32S; + case VER_PLATFORM_WIN32_NT: + s_version.os = wxOS_WINDOWS_NT; break; case VER_PLATFORM_WIN32_WINDOWS: - s_ver = wxWIN95; + s_version.os = wxOS_WINDOWS_9X; break; + } +#endif // Windows versions - case VER_PLATFORM_WIN32_NT: - s_ver = wxWINDOWS_NT; - break; -#ifdef __WXWINCE__ - case VER_PLATFORM_WIN32_CE: - s_ver = wxWINDOWS_CE; + s_version.verMaj = info.dwMajorVersion; + s_version.verMin = info.dwMinorVersion; + } + else // GetVersionEx() failed + { + s_version.initialized = -1; + } + } + + if ( s_version.initialized == 1 ) + { + if ( verMaj ) + *verMaj = s_version.verMaj; + if ( verMin ) + *verMin = s_version.verMin; + } + + // this works even if we were not initialized successfully as the initial + // values of this field is 0 which is wxOS_UNKNOWN and exactly what we need + return s_version.os; +} + +wxWinVersion wxGetWinVersion() +{ + int verMaj, + verMin; + switch ( wxGetOsVersion(&verMaj, &verMin) ) + { + case wxOS_WINDOWS_9X: + if ( verMaj == 4 ) + { + switch ( verMin ) + { + case 0: + return wxWinVersion_95; + + case 10: + return wxWinVersion_98; + + case 90: + return wxWinVersion_ME; + } + } + break; + + case wxOS_WINDOWS_NT: + switch ( verMaj ) + { + case 3: + return wxWinVersion_NT3; + + case 4: + return wxWinVersion_NT4; + + case 5: + switch ( verMin ) + { + case 0: + return wxWinVersion_2000; + + case 1: + return wxWinVersion_XP; + + case 2: + return wxWinVersion_2003; + } break; -#endif + + case 6: + return wxWinVersion_NT6; } - } + break; + + default: + // Do nothing just to silence GCC warning + break; } - static wxToolkitInfo info; - info.versionMajor = s_major; - info.versionMinor = s_minor; - info.os = s_ver; - info.name = _T("wxBase"); - return info; + return wxWinVersion_Unknown; } // ---------------------------------------------------------------------------- @@ -1228,8 +1363,10 @@ extern WXDLLIMPEXP_BASE long wxEncodingToCharset(wxFontEncoding encoding) case wxFONTENCODING_CP936: return GB2312_CHARSET; +#ifndef __WXWINCE__ case wxFONTENCODING_CP949: return HANGUL_CHARSET; +#endif case wxFONTENCODING_CP950: return CHINESEBIG5_CHARSET; @@ -1279,32 +1416,94 @@ extern WXDLLIMPEXP_BASE long wxEncodingToCharset(wxFontEncoding encoding) extern WXDLLIMPEXP_BASE long wxEncodingToCodepage(wxFontEncoding encoding) { - // translate encoding into the Windows CHARSET - long charset = wxEncodingToCharset(encoding); - if ( charset == -1 ) - return -1; + // There don't seem to be symbolic names for + // these under Windows so I just copied the + // values from MSDN. + + unsigned int ret; - // translate CHARSET to code page - CHARSETINFO csetInfo; - if ( !::TranslateCharsetInfo((DWORD *)(DWORD)charset, - &csetInfo, - TCI_SRCCHARSET) ) + switch (encoding) { - wxLogLastError(_T("TranslateCharsetInfo(TCI_SRCCHARSET)")); + case wxFONTENCODING_ISO8859_1: ret = 28591; break; + case wxFONTENCODING_ISO8859_2: ret = 28592; break; + case wxFONTENCODING_ISO8859_3: ret = 28593; break; + case wxFONTENCODING_ISO8859_4: ret = 28594; break; + case wxFONTENCODING_ISO8859_5: ret = 28595; break; + case wxFONTENCODING_ISO8859_6: ret = 28596; break; + case wxFONTENCODING_ISO8859_7: ret = 28597; break; + case wxFONTENCODING_ISO8859_8: ret = 28598; break; + case wxFONTENCODING_ISO8859_9: ret = 28599; break; + case wxFONTENCODING_ISO8859_10: ret = 28600; break; + case wxFONTENCODING_ISO8859_11: ret = 874; break; + // case wxFONTENCODING_ISO8859_12, // doesn't exist currently, but put it + case wxFONTENCODING_ISO8859_13: ret = 28603; break; + // case wxFONTENCODING_ISO8859_14: ret = 28604; break; // no correspondence on Windows + case wxFONTENCODING_ISO8859_15: ret = 28605; break; + + case wxFONTENCODING_KOI8: ret = 20866; break; + case wxFONTENCODING_KOI8_U: ret = 21866; break; + + case wxFONTENCODING_CP437: ret = 437; break; + case wxFONTENCODING_CP850: ret = 850; break; + case wxFONTENCODING_CP852: ret = 852; break; + case wxFONTENCODING_CP855: ret = 855; break; + case wxFONTENCODING_CP866: ret = 866; break; + case wxFONTENCODING_CP874: ret = 874; break; + case wxFONTENCODING_CP932: ret = 932; break; + case wxFONTENCODING_CP936: ret = 936; break; + case wxFONTENCODING_CP949: ret = 949; break; + case wxFONTENCODING_CP950: ret = 950; break; + case wxFONTENCODING_CP1250: ret = 1250; break; + case wxFONTENCODING_CP1251: ret = 1251; break; + case wxFONTENCODING_CP1252: ret = 1252; break; + case wxFONTENCODING_CP1253: ret = 1253; break; + case wxFONTENCODING_CP1254: ret = 1254; break; + case wxFONTENCODING_CP1255: ret = 1255; break; + case wxFONTENCODING_CP1256: ret = 1256; break; + case wxFONTENCODING_CP1257: ret = 1257; break; + + case wxFONTENCODING_EUC_JP: ret = 20932; break; + + case wxFONTENCODING_MACROMAN: ret = 10000; break; + case wxFONTENCODING_MACJAPANESE: ret = 10001; break; + case wxFONTENCODING_MACCHINESETRAD: ret = 10002; break; + case wxFONTENCODING_MACKOREAN: ret = 10003; break; + case wxFONTENCODING_MACARABIC: ret = 10004; break; + case wxFONTENCODING_MACHEBREW: ret = 10005; break; + case wxFONTENCODING_MACGREEK: ret = 10006; break; + case wxFONTENCODING_MACCYRILLIC: ret = 10007; break; + case wxFONTENCODING_MACTHAI: ret = 10021; break; + case wxFONTENCODING_MACCHINESESIMP: ret = 10008; break; + case wxFONTENCODING_MACCENTRALEUR: ret = 10029; break; + case wxFONTENCODING_MACCROATIAN: ret = 10082; break; + case wxFONTENCODING_MACICELANDIC: ret = 10079; break; + case wxFONTENCODING_MACROMANIAN: ret = 10009; break; + + case wxFONTENCODING_ISO2022_JP: ret = 50222; break; + + case wxFONTENCODING_UTF7: ret = 65000; break; + case wxFONTENCODING_UTF8: ret = 65001; break; + + default: return -1; + } + if (::IsValidCodePage(ret) == 0) return -1; - } - return csetInfo.ciACP; + CPINFO info; + if (::GetCPInfo(ret, &info) == 0) + return -1; + + return (long) ret; } -extern long wxCharsetToCodepage(const wxChar *name) +extern long wxCharsetToCodepage(const char *name) { // first get the font encoding for this charset if ( !name ) return -1; - wxFontEncoding enc = wxFontMapper::Get()->CharsetToEncoding(name, false); + wxFontEncoding enc = wxFontMapperBase::Get()->CharsetToEncoding(name, false); if ( enc == wxFONTENCODING_SYSTEM ) return -1; @@ -1317,13 +1516,14 @@ extern long wxCharsetToCodepage(const wxChar *name) #include "wx/msw/registry.h" // this should work if Internet Exploiter is installed -extern long wxCharsetToCodepage(const wxChar *name) +extern long wxCharsetToCodepage(const char *name) { if (!name) return GetACP(); long CP = -1; +#if wxUSE_REGKEY wxString path(wxT("MIME\\Database\\Charset\\")); wxString cn(name); @@ -1349,6 +1549,7 @@ extern long wxCharsetToCodepage(const wxChar *name) !key.QueryValue(wxT("AliasForCharset"), cn)) break; } +#endif // wxUSE_REGKEY return CP; } @@ -1364,7 +1565,7 @@ extern long wxCharsetToCodepage(const wxChar *name) Windows class unregistration). pclassname is a pointer to a caller stored classname, which must initially be - NULL. classname is the desired wndclass classname. If function succesfully + NULL. classname is the desired wndclass classname. If function successfully registers the class, pclassname will be set to classname. */ extern "C" WXDLLIMPEXP_BASE HWND @@ -1413,4 +1614,3 @@ wxCreateHiddenWindow(LPCTSTR *pclassname, LPCTSTR classname, WNDPROC wndproc) return hwnd; } -