1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     Various utilities 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart and Markus Holzem 
   9 // Licence:     wxWindows license 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  21 // #pragma implementation "utils.h"   // Note: this is done in utilscmn.cpp now. 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  37     #include "wx/cursor.h" 
  41 // In some mingws there is a missing extern "C" int the winsock header, 
  42 // so we put it here just to be safe. Note that this must appear _before_ 
  43 // #include "wx/msw/private.h" which itself includes <windows.h>, as this 
  44 // one in turn includes <winsock.h> unless we define WIN32_LEAN_AND_MEAN. 
  46 #if defined(__WIN32__) && !defined(__TWIN32__) && !defined(__WXMICROWIN__) && ! (defined(__GNUWIN32__) && !defined(__MINGW32__)) 
  48     #include <winsock.h>    // we use socket functions in wxGetFullHostName() 
  52 #include "wx/msw/private.h"     // includes <windows.h> 
  56 #if !defined(__GNUWIN32__) && !defined(__WXWINE__) && !defined(__SALFORDC__) && !defined(__WXMICROWIN__) 
  64 #if defined(__CYGWIN__) && !defined(__TWIN32__) 
  65     #include <sys/unistd.h> 
  67     #include <sys/cygwin.h> // for cygwin_conv_to_full_win32_path() 
  70 #ifdef __BORLANDC__ // Please someone tell me which version of Borland needs 
  71                     // this (3.1 I believe) and how to test for it. 
  72                     // If this works for Borland 4.0 as well, then no worries. 
  76 // VZ: there is some code using NetXXX() functions to get the full user name: 
  77 //     I don't think it's a good idea because they don't work under Win95 and 
  78 //     seem to return the same as wxGetUserId() under NT. If you really want 
  79 //     to use them, just #define USE_NET_API 
  86 #if defined(__WIN32__) && !defined(__WXWINE__) && !defined(__WXMICROWIN__) 
  95     #if !(defined(_MSC_VER) && (_MSC_VER > 800)) 
 100 //// BEGIN for console support: VC++ only 
 103 #include "wx/msw/msvcrt.h" 
 107 #include "wx/ioswrap.h" 
 109 /* Need to undef new if including crtdbg.h */ 
 118 #  if defined(__WXDEBUG__) && wxUSE_GLOBAL_MEMORY_OPERATORS && wxUSE_DEBUG_NEW_ALWAYS 
 119 #  define new new(__TFILE__,__LINE__) 
 124 /// END for console support 
 126 // ---------------------------------------------------------------------------- 
 128 // ---------------------------------------------------------------------------- 
 130 // In the WIN.INI file 
 131 static const wxChar WX_SECTION
[] = wxT("wxWindows"); 
 132 static const wxChar eUSERNAME
[]  = wxT("UserName"); 
 134 // these are only used under Win16 
 135 #if !defined(__WIN32__) && !defined(__WXMICROWIN__) 
 136 static const wxChar eHOSTNAME
[]  = wxT("HostName"); 
 137 static const wxChar eUSERID
[]    = wxT("UserId"); 
 140 #ifndef __WXMICROWIN__ 
 142 // ============================================================================ 
 144 // ============================================================================ 
 146 // ---------------------------------------------------------------------------- 
 147 // get host name and related 
 148 // ---------------------------------------------------------------------------- 
 150 // Get hostname only (without domain name) 
 151 bool wxGetHostName(wxChar 
*buf
, int maxSize
) 
 153 #if defined(__WIN32__) && !defined(__TWIN32__) && !defined(__WXMICROWIN__) 
 154     DWORD nSize 
= maxSize
; 
 155     if ( !::GetComputerName(buf
, &nSize
) ) 
 157         wxLogLastError(wxT("GetComputerName")); 
 165     const wxChar 
*default_host 
= wxT("noname"); 
 167     if ((sysname 
= wxGetenv(wxT("SYSTEM_NAME"))) == NULL
) { 
 168         GetProfileString(WX_SECTION
, eHOSTNAME
, default_host
, buf
, maxSize 
- 1); 
 170         wxStrncpy(buf
, sysname
, maxSize 
- 1); 
 171     buf
[maxSize
] = wxT('\0'); 
 172     return *buf 
? TRUE 
: FALSE
; 
 176 // get full hostname (with domain name if possible) 
 177 bool wxGetFullHostName(wxChar 
*buf
, int maxSize
) 
 179 #if defined(__WIN32__) && !defined(__TWIN32__) && !defined(__WXMICROWIN__) && ! (defined(__GNUWIN32__) && !defined(__MINGW32__)) 
 180     // TODO should use GetComputerNameEx() when available 
 182     if ( WSAStartup(MAKEWORD(1, 1), &wsa
) == 0 ) 
 186         if ( gethostname(bufA
, WXSIZEOF(bufA
)) == 0 ) 
 188             // gethostname() won't usually include the DNS domain name, for 
 189             // this we need to work a bit more 
 190             if ( !strchr(bufA
, '.') ) 
 192                 struct hostent 
*pHostEnt 
=  gethostbyname(bufA
); 
 196                     // Windows will use DNS internally now 
 197                     pHostEnt 
= gethostbyaddr(pHostEnt
->h_addr
, 4, PF_INET
); 
 202                     host 
= pHostEnt
->h_name
; 
 211             wxStrncpy(buf
, host
, maxSize
); 
 218     return wxGetHostName(buf
, maxSize
); 
 221 // Get user ID e.g. jacs 
 222 bool wxGetUserId(wxChar 
*buf
, int maxSize
) 
 224 #if defined(__WIN32__) && !defined(__win32s__) && !defined(__TWIN32__) && !defined(__WXMICROWIN__) 
 225     DWORD nSize 
= maxSize
; 
 226     if ( ::GetUserName(buf
, &nSize
) == 0 ) 
 228         // actually, it does happen on Win9x if the user didn't log on 
 229         DWORD res 
= ::GetEnvironmentVariable(wxT("username"), buf
, maxSize
); 
 238 #else   // Win16 or Win32s 
 240     const wxChar 
*default_id 
= wxT("anonymous"); 
 242     // Can't assume we have NIS (PC-NFS) or some other ID daemon 
 244     if (  (user 
= wxGetenv(wxT("USER"))) == NULL 
&& 
 245             (user 
= wxGetenv(wxT("LOGNAME"))) == NULL 
) 
 247         // Use wxWindows configuration data (comming soon) 
 248         GetProfileString(WX_SECTION
, eUSERID
, default_id
, buf
, maxSize 
- 1); 
 252         wxStrncpy(buf
, user
, maxSize 
- 1); 
 255     return *buf 
? TRUE 
: FALSE
; 
 259 // Get user name e.g. Julian Smart 
 260 bool wxGetUserName(wxChar 
*buf
, int maxSize
) 
 262 #if wxUSE_PENWINDOWS && !defined(__WATCOMC__) && !defined(__GNUWIN32__) 
 263     extern HANDLE g_hPenWin
; // PenWindows Running? 
 266         // PenWindows Does have a user concept! 
 267         // Get the current owner of the recognizer 
 268         GetPrivateProfileString("Current", "User", default_name
, wxBuffer
, maxSize 
- 1, "PENWIN.INI"); 
 269         strncpy(buf
, wxBuffer
, maxSize 
- 1); 
 275         CHAR szUserName
[256]; 
 276         if ( !wxGetUserId(szUserName
, WXSIZEOF(szUserName
)) ) 
 279         // TODO how to get the domain name? 
 282         // the code is based on the MSDN example (also see KB article Q119670) 
 283         WCHAR wszUserName
[256];          // Unicode user name 
 284         WCHAR wszDomain
[256]; 
 287         USER_INFO_2 
*ui2
;         // User structure 
 289         // Convert ANSI user name and domain to Unicode 
 290         MultiByteToWideChar( CP_ACP
, 0, szUserName
, strlen(szUserName
)+1, 
 291                 wszUserName
, WXSIZEOF(wszUserName
) ); 
 292         MultiByteToWideChar( CP_ACP
, 0, szDomain
, strlen(szDomain
)+1, 
 293                 wszDomain
, WXSIZEOF(wszDomain
) ); 
 295         // Get the computer name of a DC for the domain. 
 296         if ( NetGetDCName( NULL
, wszDomain
, &ComputerName 
) != NERR_Success 
) 
 298             wxLogError(wxT("Can not find domain controller")); 
 303         // Look up the user on the DC 
 304         NET_API_STATUS status 
= NetUserGetInfo( (LPWSTR
)ComputerName
, 
 305                 (LPWSTR
)&wszUserName
, 
 306                 2, // level - we want USER_INFO_2 
 314             case NERR_InvalidComputer
: 
 315                 wxLogError(wxT("Invalid domain controller name.")); 
 319             case NERR_UserNotFound
: 
 320                 wxLogError(wxT("Invalid user name '%s'."), szUserName
); 
 325                 wxLogSysError(wxT("Can't get information about user")); 
 330         // Convert the Unicode full name to ANSI 
 331         WideCharToMultiByte( CP_ACP
, 0, ui2
->usri2_full_name
, -1, 
 332                 buf
, maxSize
, NULL
, NULL 
); 
 337         wxLogError(wxT("Couldn't look up full user name.")); 
 340 #else  // !USE_NET_API 
 341         // Could use NIS, MS-Mail or other site specific programs 
 342         // Use wxWindows configuration data 
 343         bool ok 
= GetProfileString(WX_SECTION
, eUSERNAME
, wxT(""), buf
, maxSize 
- 1) != 0; 
 346             ok 
= wxGetUserId(buf
, maxSize
); 
 351             wxStrncpy(buf
, wxT("Unknown User"), maxSize
); 
 359 const wxChar
* wxGetHomeDir(wxString 
*pstr
) 
 361   wxString
& strDir 
= *pstr
; 
 363   #if defined(__UNIX__) && !defined(__TWIN32__) 
 364     const wxChar 
*szHome 
= wxGetenv("HOME"); 
 365     if ( szHome 
== NULL 
) { 
 367       wxLogWarning(_("can't find user's HOME, using current directory.")); 
 373     // add a trailing slash if needed 
 374     if ( strDir
.Last() != wxT('/') ) 
 378       // Cygwin returns unix type path but that does not work well 
 379       static wxChar windowsPath
[MAX_PATH
]; 
 380       cygwin_conv_to_full_win32_path(strDir
, windowsPath
); 
 381       strDir 
= windowsPath
; 
 385       const wxChar 
*szHome 
= wxGetenv(wxT("HOMEDRIVE")); 
 386       if ( szHome 
!= NULL 
) 
 388       szHome 
= wxGetenv(wxT("HOMEPATH")); 
 389       if ( szHome 
!= NULL 
) { 
 392         // the idea is that under NT these variables have default values 
 393         // of "%systemdrive%:" and "\\". As we don't want to create our 
 394         // config files in the root directory of the system drive, we will 
 395         // create it in our program's dir. However, if the user took care 
 396         // to set HOMEPATH to something other than "\\", we suppose that he 
 397         // knows what he is doing and use the supplied value. 
 398         if ( wxStrcmp(szHome
, wxT("\\")) != 0 ) 
 399           return strDir
.c_str(); 
 403       // Win16 has no idea about home, so use the working directory instead 
 406     // 260 was taken from windef.h 
 412     ::GetModuleFileName(::GetModuleHandle(NULL
), 
 413                         strPath
.GetWriteBuf(MAX_PATH
), MAX_PATH
); 
 414     strPath
.UngetWriteBuf(); 
 416     // extract the dir name 
 417     wxSplitPath(strPath
, &strDir
, NULL
, NULL
); 
 421   return strDir
.c_str(); 
 424 wxChar 
*wxGetUserHome(const wxString
& WXUNUSED(user
)) 
 426     // VZ: the old code here never worked for user != "" anyhow! Moreover, it 
 427     //     returned sometimes a malloc()'d pointer, sometimes a pointer to a 
 428     //     static buffer and sometimes I don't even know what. 
 429     static wxString s_home
; 
 431     return (wxChar 
*)wxGetHomeDir(&s_home
); 
 434 bool wxDirExists(const wxString
& dir
) 
 436 #ifdef __WXMICROWIN__ 
 437     return wxPathExist(dir
); 
 438 #elif defined(__WIN32__) 
 439     DWORD attribs 
= GetFileAttributes(dir
); 
 440     return ((attribs 
!= (DWORD
)-1) && (attribs 
& FILE_ATTRIBUTE_DIRECTORY
)); 
 443         struct ffblk fileInfo
; 
 445         struct find_t fileInfo
; 
 447     // In Borland findfirst has a different argument 
 448     // ordering from _dos_findfirst. But _dos_findfirst 
 449     // _should_ be ok in both MS and Borland... why not? 
 451         return (findfirst(dir
, &fileInfo
, _A_SUBDIR
) == 0 && 
 452                (fileInfo
.ff_attrib 
& _A_SUBDIR
) != 0); 
 454         return (_dos_findfirst(dir
, _A_SUBDIR
, &fileInfo
) == 0) && 
 455                ((fileInfo
.attrib 
& _A_SUBDIR
) != 0); 
 460 bool wxGetDiskSpace(const wxString
& path
, wxLongLong 
*pTotal
, wxLongLong 
*pFree
) 
 465 // old w32api don't have ULARGE_INTEGER 
 466 #if defined(__WIN32__) && \ 
 467     (!defined(__GNUWIN32__) || wxCHECK_W32API_VERSION( 0, 3 )) 
 468     // GetDiskFreeSpaceEx() is not available under original Win95, check for 
 470     typedef BOOL (WINAPI 
*GetDiskFreeSpaceEx_t
)(LPCTSTR
, 
 476         pGetDiskFreeSpaceEx 
= (GetDiskFreeSpaceEx_t
)::GetProcAddress
 
 478                                 ::GetModuleHandle(_T("kernel32.dll")), 
 480                                 "GetDiskFreeSpaceExW" 
 482                                 "GetDiskFreeSpaceExA" 
 486     if ( pGetDiskFreeSpaceEx 
) 
 488         ULARGE_INTEGER bytesFree
, bytesTotal
; 
 490         // may pass the path as is, GetDiskFreeSpaceEx() is smart enough 
 491         if ( !pGetDiskFreeSpaceEx(path
, 
 496             wxLogLastError(_T("GetDiskFreeSpaceEx")); 
 503             *pTotal 
= wxLongLong(bytesTotal
.HighPart
, bytesTotal
.LowPart
); 
 508             *pFree 
= wxLongLong(bytesFree
.HighPart
, bytesFree
.LowPart
); 
 514         // there's a problem with drives larger than 2GB, GetDiskFreeSpaceEx() 
 515         // should be used instead - but if it's not available, fall back on 
 516         // GetDiskFreeSpace() nevertheless... 
 518         DWORD lSectorsPerCluster
, 
 520               lNumberOfFreeClusters
, 
 521               lTotalNumberOfClusters
; 
 523         // FIXME: this is wrong, we should extract the root drive from path 
 524         //        instead, but this is the job for wxFileName... 
 525         if ( !::GetDiskFreeSpace(path
, 
 528                                  &lNumberOfFreeClusters
, 
 529                                  &lTotalNumberOfClusters
) ) 
 531             wxLogLastError(_T("GetDiskFreeSpace")); 
 536         wxLongLong lBytesPerCluster 
= lSectorsPerCluster
; 
 537         lBytesPerCluster 
*= lBytesPerSector
; 
 541             *pTotal 
= lBytesPerCluster
; 
 542             *pTotal 
*= lTotalNumberOfClusters
; 
 547             *pFree 
= lBytesPerCluster
; 
 548             *pFree 
*= lNumberOfFreeClusters
; 
 555 // ---------------------------------------------------------------------------- 
 557 // ---------------------------------------------------------------------------- 
 559 bool wxGetEnv(const wxString
& var
, wxString 
*value
) 
 562     const wxChar
* ret 
= wxGetenv(var
); 
 571     // first get the size of the buffer 
 572     DWORD dwRet 
= ::GetEnvironmentVariable(var
, NULL
, 0); 
 575         // this means that there is no such variable 
 581         (void)::GetEnvironmentVariable(var
, value
->GetWriteBuf(dwRet
), dwRet
); 
 582         value
->UngetWriteBuf(); 
 589 bool wxSetEnv(const wxString
& var
, const wxChar 
*value
) 
 591     // some compilers have putenv() or _putenv() or _wputenv() but it's better 
 592     // to always use Win32 function directly instead of dealing with them 
 593 #if defined(__WIN32__) 
 594     if ( !::SetEnvironmentVariable(var
, value
) ) 
 596         wxLogLastError(_T("SetEnvironmentVariable")); 
 602 #else // no way to set env vars 
 607 // ---------------------------------------------------------------------------- 
 608 // process management 
 609 // ---------------------------------------------------------------------------- 
 613 // structure used to pass parameters from wxKill() to wxEnumFindByPidProc() 
 614 struct wxFindByPidParams
 
 616     wxFindByPidParams() { hwnd 
= 0; pid 
= 0; } 
 618     // the HWND used to return the result 
 621     // the PID we're looking from 
 625 // wxKill helper: EnumWindows() callback which is used to find the first (top 
 626 // level) window belonging to the given process 
 627 BOOL CALLBACK 
wxEnumFindByPidProc(HWND hwnd
, LPARAM lParam
) 
 630     (void)::GetWindowThreadProcessId(hwnd
, &pid
); 
 632     wxFindByPidParams 
*params 
= (wxFindByPidParams 
*)lParam
; 
 633     if ( pid 
== params
->pid 
) 
 635         // remember the window we found 
 638         // return FALSE to stop the enumeration 
 642     // continue enumeration 
 648 int wxKill(long pid
, wxSignal sig
, wxKillError 
*krc
) 
 651     // get the process handle to operate on 
 652     HANDLE hProcess 
= ::OpenProcess(SYNCHRONIZE 
| 
 654                                     PROCESS_QUERY_INFORMATION
, 
 655                                     FALSE
, // not inheritable 
 657     if ( hProcess 
== NULL 
) 
 661             if ( ::GetLastError() == ERROR_ACCESS_DENIED 
) 
 663                 *krc 
= wxKILL_ACCESS_DENIED
; 
 667                 *krc 
= wxKILL_NO_PROCESS
; 
 678             // kill the process forcefully returning -1 as error code 
 679             if ( !::TerminateProcess(hProcess
, (UINT
)-1) ) 
 681                 wxLogSysError(_("Failed to kill process %d"), pid
); 
 685                     // this is not supposed to happen if we could open the 
 695             // do nothing, we just want to test for process existence 
 699             // any other signal means "terminate" 
 701                 wxFindByPidParams params
; 
 702                 params
.pid 
= (DWORD
)pid
; 
 704                 // EnumWindows() has nice semantics: it returns 0 if it found 
 705                 // something or if an error occured and non zero if it 
 706                 // enumerated all the window 
 707                 if ( !::EnumWindows(wxEnumFindByPidProc
, (LPARAM
)¶ms
) ) 
 709                     // did we find any window? 
 712                         // tell the app to close 
 714                         // NB: this is the harshest way, the app won't have 
 715                         //     opportunity to save any files, for example, but 
 716                         //     this is probably what we want here. If not we 
 717                         //     can also use SendMesageTimeout(WM_CLOSE) 
 718                         if ( !::PostMessage(params
.hwnd
, WM_QUIT
, 0, 0) ) 
 720                             wxLogLastError(_T("PostMessage(WM_QUIT)")); 
 723                     else // it was an error then 
 725                         wxLogLastError(_T("EnumWindows")); 
 730                 else // no windows for this PID 
 747         // as we wait for a short time, we can use just WaitForSingleObject() 
 748         // and not MsgWaitForMultipleObjects() 
 749         switch ( ::WaitForSingleObject(hProcess
, 500 /* msec */) ) 
 752                 // process terminated 
 753                 if ( !::GetExitCodeProcess(hProcess
, &rc
) ) 
 755                     wxLogLastError(_T("GetExitCodeProcess")); 
 760                 wxFAIL_MSG( _T("unexpected WaitForSingleObject() return") ); 
 764                 wxLogLastError(_T("WaitForSingleObject")); 
 779         // just to suppress the warnings about uninitialized variable 
 783     ::CloseHandle(hProcess
); 
 785     // the return code is the same as from Unix kill(): 0 if killed 
 786     // successfully or -1 on error 
 787     if ( sig 
== wxSIGNONE 
) 
 789         if ( ok 
&& rc 
== STILL_ACTIVE 
) 
 791             // there is such process => success 
 797         if ( ok 
&& rc 
!= STILL_ACTIVE 
) 
 804     wxFAIL_MSG( _T("not implemented") ); 
 805 #endif // Win32/Win16 
 811 // Execute a program in an Interactive Shell 
 812 bool wxShell(const wxString
& command
) 
 814     wxChar 
*shell 
= wxGetenv(wxT("COMSPEC")); 
 816         shell 
= wxT("\\COMMAND.COM"); 
 826         // pass the command to execute to the command processor 
 827         cmd
.Printf(wxT("%s /c %s"), shell
, command
.c_str()); 
 830     return wxExecute(cmd
, TRUE 
/* sync */) != 0; 
 833 // ---------------------------------------------------------------------------- 
 835 // ---------------------------------------------------------------------------- 
 837 // Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX) 
 838 long wxGetFreeMemory() 
 840 #if defined(__WIN32__) && !defined(__BORLANDC__) && !defined(__TWIN32__) 
 841     MEMORYSTATUS memStatus
; 
 842     memStatus
.dwLength 
= sizeof(MEMORYSTATUS
); 
 843     GlobalMemoryStatus(&memStatus
); 
 844     return memStatus
.dwAvailPhys
; 
 846     return (long)GetFreeSpace(0); 
 853     ::MessageBeep((UINT
)-1);        // default sound 
 856 wxString 
wxGetOsDescription() 
 864     info
.dwOSVersionInfoSize 
= sizeof(OSVERSIONINFO
); 
 865     if ( ::GetVersionEx(&info
) ) 
 867         switch ( info
.dwPlatformId 
) 
 869             case VER_PLATFORM_WIN32s
: 
 870                 str 
= _("Win32s on Windows 3.1"); 
 873             case VER_PLATFORM_WIN32_WINDOWS
: 
 874                 str
.Printf(_("Windows 9%c"), 
 875                            info
.dwMinorVersion 
== 0 ? _T('5') : _T('8')); 
 876                 if ( !wxIsEmpty(info
.szCSDVersion
) ) 
 878                     str 
<< _T(" (") << info
.szCSDVersion 
<< _T(')'); 
 882             case VER_PLATFORM_WIN32_NT
: 
 883                 str
.Printf(_T("Windows NT %lu.%lu (build %lu"), 
 887                 if ( !wxIsEmpty(info
.szCSDVersion
) ) 
 889                     str 
<< _T(", ") << info
.szCSDVersion
; 
 897         wxFAIL_MSG( _T("GetVersionEx() failed") ); // should never happen 
 902     return _("Windows 3.1"); 
 906 int wxGetOsVersion(int *majorVsn
, int *minorVsn
) 
 908 #if defined(__WIN32__) && !defined(__SC__) 
 912     info
.dwOSVersionInfoSize 
= sizeof(OSVERSIONINFO
); 
 913     if ( ::GetVersionEx(&info
) ) 
 916             *majorVsn 
= info
.dwMajorVersion
; 
 918             *minorVsn 
= info
.dwMinorVersion
; 
 920         switch ( info
.dwPlatformId 
) 
 922             case VER_PLATFORM_WIN32s
: 
 925             case VER_PLATFORM_WIN32_WINDOWS
: 
 928             case VER_PLATFORM_WIN32_NT
: 
 933     return wxWINDOWS
; // error if we get here, return generic value 
 935     int retValue 
= wxWINDOWS
; 
 936     #ifdef __WINDOWS_386__ 
 939         #if !defined(__WATCOMC__) && !defined(GNUWIN32) && wxUSE_PENWINDOWS 
 940             extern HANDLE g_hPenWin
; 
 941             retValue 
= g_hPenWin 
? wxPENWINDOWS 
: wxWINDOWS
; 
 954 // ---------------------------------------------------------------------------- 
 956 // ---------------------------------------------------------------------------- 
 962 // Sleep for nSecs seconds. Attempt a Windows implementation using timers. 
 963 static bool gs_inTimer 
= FALSE
; 
 965 class wxSleepTimer 
: public wxTimer
 
 968     virtual void Notify() 
 975 static wxTimer 
*wxTheSleepTimer 
= NULL
; 
 977 void wxUsleep(unsigned long milliseconds
) 
 980     ::Sleep(milliseconds
); 
 985     wxTheSleepTimer 
= new wxSleepTimer
; 
 987     wxTheSleepTimer
->Start(milliseconds
); 
 990         if (wxTheApp
->Pending()) 
 991             wxTheApp
->Dispatch(); 
 993     delete wxTheSleepTimer
; 
 994     wxTheSleepTimer 
= NULL
; 
 995 #endif // Win32/!Win32 
 998 void wxSleep(int nSecs
) 
1003     wxTheSleepTimer 
= new wxSleepTimer
; 
1005     wxTheSleepTimer
->Start(nSecs
*1000); 
1008         if (wxTheApp
->Pending()) 
1009             wxTheApp
->Dispatch(); 
1011     delete wxTheSleepTimer
; 
1012     wxTheSleepTimer 
= NULL
; 
1015 // Consume all events until no more left 
1016 void wxFlushEvents() 
1021 #endif // wxUSE_TIMER 
1023 #elif defined(__WIN32__) // wxUSE_GUI 
1025 void wxUsleep(unsigned long milliseconds
) 
1027     ::Sleep(milliseconds
); 
1030 void wxSleep(int nSecs
) 
1032     wxUsleep(1000*nSecs
); 
1035 #endif // wxUSE_GUI/!wxUSE_GUI 
1036 #endif // __WXMICROWIN__ 
1038 // ---------------------------------------------------------------------------- 
1039 // deprecated (in favour of wxLog) log functions 
1040 // ---------------------------------------------------------------------------- 
1044 // Output a debug mess., in a system dependent fashion. 
1045 #ifndef __WXMICROWIN__ 
1046 void wxDebugMsg(const wxChar 
*fmt 
...) 
1049   static wxChar buffer
[512]; 
1051   if (!wxTheApp
->GetWantDebugOutput()) 
1056   wvsprintf(buffer
,fmt
,ap
) ; 
1057   OutputDebugString((LPCTSTR
)buffer
) ; 
1062 // Non-fatal error: pop up message box and (possibly) continue 
1063 void wxError(const wxString
& msg
, const wxString
& title
) 
1065   wxSprintf(wxBuffer
, wxT("%s\nContinue?"), WXSTRINGCAST msg
); 
1066   if (MessageBox(NULL
, (LPCTSTR
)wxBuffer
, (LPCTSTR
)WXSTRINGCAST title
, 
1067              MB_ICONSTOP 
| MB_YESNO
) == IDNO
) 
1071 // Fatal error: pop up message box and abort 
1072 void wxFatalError(const wxString
& msg
, const wxString
& title
) 
1074   wxSprintf(wxBuffer
, wxT("%s: %s"), WXSTRINGCAST title
, WXSTRINGCAST msg
); 
1075   FatalAppExit(0, (LPCTSTR
)wxBuffer
); 
1077 #endif // __WXMICROWIN__ 
1079 // ---------------------------------------------------------------------------- 
1080 // functions to work with .INI files 
1081 // ---------------------------------------------------------------------------- 
1083 // Reading and writing resources (eg WIN.INI, .Xdefaults) 
1085 bool wxWriteResource(const wxString
& section
, const wxString
& entry
, const wxString
& value
, const wxString
& file
) 
1087   if (file 
!= wxT("")) 
1088 // Don't know what the correct cast should be, but it doesn't 
1089 // compile in BC++/16-bit without this cast. 
1090 #if !defined(__WIN32__) 
1091     return (WritePrivateProfileString((const char*) section
, (const char*) entry
, (const char*) value
, (const char*) file
) != 0); 
1093     return (WritePrivateProfileString((LPCTSTR
)WXSTRINGCAST section
, (LPCTSTR
)WXSTRINGCAST entry
, (LPCTSTR
)value
, (LPCTSTR
)WXSTRINGCAST file
) != 0); 
1096     return (WriteProfileString((LPCTSTR
)WXSTRINGCAST section
, (LPCTSTR
)WXSTRINGCAST entry
, (LPCTSTR
)WXSTRINGCAST value
) != 0); 
1099 bool wxWriteResource(const wxString
& section
, const wxString
& entry
, float value
, const wxString
& file
) 
1102     buf
.Printf(wxT("%.4f"), value
); 
1104     return wxWriteResource(section
, entry
, buf
, file
); 
1107 bool wxWriteResource(const wxString
& section
, const wxString
& entry
, long value
, const wxString
& file
) 
1110     buf
.Printf(wxT("%ld"), value
); 
1112     return wxWriteResource(section
, entry
, buf
, file
); 
1115 bool wxWriteResource(const wxString
& section
, const wxString
& entry
, int value
, const wxString
& file
) 
1118     buf
.Printf(wxT("%d"), value
); 
1120     return wxWriteResource(section
, entry
, buf
, file
); 
1123 bool wxGetResource(const wxString
& section
, const wxString
& entry
, wxChar 
**value
, const wxString
& file
) 
1125     static const wxChar defunkt
[] = wxT("$$default"); 
1126     if (file 
!= wxT("")) 
1128         int n 
= GetPrivateProfileString((LPCTSTR
)WXSTRINGCAST section
, (LPCTSTR
)WXSTRINGCAST entry
, (LPCTSTR
)defunkt
, 
1129                 (LPTSTR
)wxBuffer
, 1000, (LPCTSTR
)WXSTRINGCAST file
); 
1130         if (n 
== 0 || wxStrcmp(wxBuffer
, defunkt
) == 0) 
1135         int n 
= GetProfileString((LPCTSTR
)WXSTRINGCAST section
, (LPCTSTR
)WXSTRINGCAST entry
, (LPCTSTR
)defunkt
, 
1136                 (LPTSTR
)wxBuffer
, 1000); 
1137         if (n 
== 0 || wxStrcmp(wxBuffer
, defunkt
) == 0) 
1140     if (*value
) delete[] (*value
); 
1141     *value 
= copystring(wxBuffer
); 
1145 bool wxGetResource(const wxString
& section
, const wxString
& entry
, float *value
, const wxString
& file
) 
1148     bool succ 
= wxGetResource(section
, entry
, (wxChar 
**)&s
, file
); 
1151         *value 
= (float)wxStrtod(s
, NULL
); 
1158 bool wxGetResource(const wxString
& section
, const wxString
& entry
, long *value
, const wxString
& file
) 
1161     bool succ 
= wxGetResource(section
, entry
, (wxChar 
**)&s
, file
); 
1164         *value 
= wxStrtol(s
, NULL
, 10); 
1171 bool wxGetResource(const wxString
& section
, const wxString
& entry
, int *value
, const wxString
& file
) 
1174     bool succ 
= wxGetResource(section
, entry
, (wxChar 
**)&s
, file
); 
1177         *value 
= (int)wxStrtol(s
, NULL
, 10); 
1183 #endif // wxUSE_RESOURCES 
1185 // --------------------------------------------------------------------------- 
1186 // helper functions for showing a "busy" cursor 
1187 // --------------------------------------------------------------------------- 
1189 static HCURSOR gs_wxBusyCursor 
= 0;     // new, busy cursor 
1190 static HCURSOR gs_wxBusyCursorOld 
= 0;  // old cursor 
1191 static int gs_wxBusyCursorCount 
= 0; 
1193 extern HCURSOR 
wxGetCurrentBusyCursor() 
1195     return gs_wxBusyCursor
; 
1198 // Set the cursor to the busy cursor for all windows 
1199 void wxBeginBusyCursor(wxCursor 
*cursor
) 
1201     if ( gs_wxBusyCursorCount
++ == 0 ) 
1203         gs_wxBusyCursor 
= (HCURSOR
)cursor
->GetHCURSOR(); 
1204 #ifndef __WXMICROWIN__ 
1205         gs_wxBusyCursorOld 
= ::SetCursor(gs_wxBusyCursor
); 
1208     //else: nothing to do, already set 
1211 // Restore cursor to normal 
1212 void wxEndBusyCursor() 
1214     wxCHECK_RET( gs_wxBusyCursorCount 
> 0, 
1215                  wxT("no matching wxBeginBusyCursor() for wxEndBusyCursor()") ); 
1217     if ( --gs_wxBusyCursorCount 
== 0 ) 
1219 #ifndef __WXMICROWIN__ 
1220         ::SetCursor(gs_wxBusyCursorOld
); 
1222         gs_wxBusyCursorOld 
= 0; 
1226 // TRUE if we're between the above two calls 
1229   return gs_wxBusyCursorCount 
> 0; 
1232 // Check whether this window wants to process messages, e.g. Stop button 
1233 // in long calculations. 
1234 bool wxCheckForInterrupt(wxWindow 
*wnd
) 
1236     wxCHECK( wnd
, FALSE 
); 
1239     while ( ::PeekMessage(&msg
, GetHwndOf(wnd
), 0, 0, PM_REMOVE
) ) 
1241         ::TranslateMessage(&msg
); 
1242         ::DispatchMessage(&msg
); 
1248 // MSW only: get user-defined resource from the .res file. 
1249 // Returns NULL or newly-allocated memory, so use delete[] to clean up. 
1251 #ifndef __WXMICROWIN__ 
1252 wxChar 
*wxLoadUserResource(const wxString
& resourceName
, const wxString
& resourceType
) 
1254     HRSRC hResource 
= ::FindResource(wxGetInstance(), resourceName
, resourceType
); 
1255     if ( hResource 
== 0 ) 
1258     HGLOBAL hData 
= ::LoadResource(wxGetInstance(), hResource
); 
1262     wxChar 
*theText 
= (wxChar 
*)::LockResource(hData
); 
1266     // Not all compilers put a zero at the end of the resource (e.g. BC++ doesn't). 
1267     // so we need to find the length of the resource. 
1268     int len 
= ::SizeofResource(wxGetInstance(), hResource
); 
1269     wxChar  
*s 
= new wxChar
[len
+1]; 
1270     wxStrncpy(s
,theText
,len
); 
1273     // wxChar *s = copystring(theText); 
1275     // Obsolete in WIN32 
1277     UnlockResource(hData
); 
1281     //  GlobalFree(hData); 
1285 #endif // __WXMICROWIN__ 
1287 // ---------------------------------------------------------------------------- 
1289 // ---------------------------------------------------------------------------- 
1291 // See also the wxGetMousePosition in window.cpp 
1292 // Deprecated: use wxPoint wxGetMousePosition() instead 
1293 void wxGetMousePosition( int* x
, int* y 
) 
1296     GetCursorPos( & pt 
); 
1301 // Return TRUE if we have a colour display 
1302 bool wxColourDisplay() 
1304 #ifdef __WXMICROWIN__ 
1308     // this function is called from wxDC ctor so it is called a *lot* of times 
1309     // hence we optimize it a bit but doign the check only once 
1311     // this should be MT safe as only the GUI thread (holding the GUI mutex) 
1313     static int s_isColour 
= -1; 
1315     if ( s_isColour 
== -1 ) 
1318         int noCols 
= ::GetDeviceCaps(dc
, NUMCOLORS
); 
1320         s_isColour 
= (noCols 
== -1) || (noCols 
> 2); 
1323     return s_isColour 
!= 0; 
1327 // Returns depth of screen 
1328 int wxDisplayDepth() 
1331     return GetDeviceCaps(dc
, PLANES
) * GetDeviceCaps(dc
, BITSPIXEL
); 
1334 // Get size of display 
1335 void wxDisplaySize(int *width
, int *height
) 
1337 #ifdef __WXMICROWIN__ 
1339     HWND hWnd 
= GetDesktopWindow(); 
1340     ::GetWindowRect(hWnd
, & rect
); 
1343         *width 
= rect
.right 
- rect
.left
; 
1345         *height 
= rect
.bottom 
- rect
.top
; 
1346 #else // !__WXMICROWIN__ 
1350         *width 
= ::GetDeviceCaps(dc
, HORZRES
); 
1352         *height 
= ::GetDeviceCaps(dc
, VERTRES
); 
1353 #endif // __WXMICROWIN__/!__WXMICROWIN__ 
1356 void wxDisplaySizeMM(int *width
, int *height
) 
1358 #ifdef __WXMICROWIN__ 
1368         *width 
= ::GetDeviceCaps(dc
, HORZSIZE
); 
1370         *height 
= ::GetDeviceCaps(dc
, VERTSIZE
); 
1374 void wxClientDisplayRect(int *x
, int *y
, int *width
, int *height
) 
1376 #if defined(__WIN16__) || defined(__WXMICROWIN__) 
1378     wxDisplaySize(width
, height
); 
1380     // Determine the desktop dimensions minus the taskbar and any other 
1381     // special decorations... 
1384     SystemParametersInfo(SPI_GETWORKAREA
, 0, &r
, 0); 
1387     if (width
)  *width 
= r
.right 
- r
.left
; 
1388     if (height
) *height 
= r
.bottom 
- r
.top
; 
1392 // --------------------------------------------------------------------------- 
1393 // window information functions 
1394 // --------------------------------------------------------------------------- 
1396 wxString WXDLLEXPORT 
wxGetWindowText(WXHWND hWnd
) 
1402         int len 
= GetWindowTextLength((HWND
)hWnd
) + 1; 
1403         ::GetWindowText((HWND
)hWnd
, str
.GetWriteBuf(len
), len
); 
1404         str
.UngetWriteBuf(); 
1410 wxString WXDLLEXPORT 
wxGetWindowClass(WXHWND hWnd
) 
1415 #ifndef __WXMICROWIN__ 
1418         int len 
= 256; // some starting value 
1422             int count 
= ::GetClassName((HWND
)hWnd
, str
.GetWriteBuf(len
), len
); 
1424             str
.UngetWriteBuf(); 
1427                 // the class name might have been truncated, retry with larger 
1437 #endif // !__WXMICROWIN__ 
1442 WXWORD WXDLLEXPORT 
wxGetWindowId(WXHWND hWnd
) 
1445     return (WXWORD
)GetWindowWord((HWND
)hWnd
, GWW_ID
); 
1447     return (WXWORD
)GetWindowLong((HWND
)hWnd
, GWL_ID
); 
1455 // ---------------------------------------------------------------------------- 
1457 // ---------------------------------------------------------------------------- 
1459 extern void PixelToHIMETRIC(LONG 
*x
, LONG 
*y
) 
1463     int iWidthMM 
= GetDeviceCaps(hdcRef
, HORZSIZE
), 
1464         iHeightMM 
= GetDeviceCaps(hdcRef
, VERTSIZE
), 
1465         iWidthPels 
= GetDeviceCaps(hdcRef
, HORZRES
), 
1466         iHeightPels 
= GetDeviceCaps(hdcRef
, VERTRES
); 
1468     *x 
*= (iWidthMM 
* 100); 
1470     *y 
*= (iHeightMM 
* 100); 
1474 extern void HIMETRICToPixel(LONG 
*x
, LONG 
*y
) 
1478     int iWidthMM 
= GetDeviceCaps(hdcRef
, HORZSIZE
), 
1479         iHeightMM 
= GetDeviceCaps(hdcRef
, VERTSIZE
), 
1480         iWidthPels 
= GetDeviceCaps(hdcRef
, HORZRES
), 
1481         iHeightPels 
= GetDeviceCaps(hdcRef
, VERTRES
); 
1484     *x 
/= (iWidthMM 
* 100); 
1486     *y 
/= (iHeightMM 
* 100); 
1491 #ifdef __WXMICROWIN__ 
1492 int wxGetOsVersion(int *majorVsn
, int *minorVsn
) 
1495     if (majorVsn
) *majorVsn 
= 0; 
1496     if (minorVsn
) *minorVsn 
= 0; 
1499 #endif // __WXMICROWIN__ 
1501 // ---------------------------------------------------------------------------- 
1502 // Win32 codepage conversion functions 
1503 // ---------------------------------------------------------------------------- 
1505 #if defined(__WIN32__) && !defined(__WXMICROWIN__) 
1507 // wxGetNativeFontEncoding() doesn't exist neither in wxBase nor in wxUniv 
1508 #if wxUSE_GUI && !defined(__WXUNIVERSAL__) 
1510 #include "wx/fontmap.h" 
1512 // VZ: the new version of wxCharsetToCodepage() is more politically correct 
1513 //     and should work on other Windows versions as well but the old version is 
1514 //     still needed for !wxUSE_FONTMAP || !wxUSE_GUI case 
1516 extern long wxEncodingToCodepage(wxFontEncoding encoding
) 
1518     // translate encoding into the Windows CHARSET 
1519     wxNativeEncodingInfo natveEncInfo
; 
1520     if ( !wxGetNativeFontEncoding(encoding
, &natveEncInfo
) ) 
1523     // translate CHARSET to code page 
1524     CHARSETINFO csetInfo
; 
1525     if ( !::TranslateCharsetInfo((DWORD 
*)(DWORD
)natveEncInfo
.charset
, 
1529         wxLogLastError(_T("TranslateCharsetInfo(TCI_SRCCHARSET)")); 
1534     return csetInfo
.ciACP
; 
1539 extern long wxCharsetToCodepage(const wxChar 
*name
) 
1541     // first get the font encoding for this charset 
1545     wxFontEncoding enc 
= wxTheFontMapper
->CharsetToEncoding(name
, FALSE
); 
1546     if ( enc 
== wxFONTENCODING_SYSTEM 
) 
1549     // the use the helper function 
1550     return wxEncodingToCodepage(enc
); 
1553 #endif // wxUSE_FONTMAP 
1557 // include old wxCharsetToCodepage() by OK if needed 
1558 #if !wxUSE_GUI || !wxUSE_FONTMAP 
1560 #include "wx/msw/registry.h" 
1562 // this should work if Internet Exploiter is installed 
1563 extern long wxCharsetToCodepage(const wxChar 
*name
) 
1572         wxString 
path(wxT("MIME\\Database\\Charset\\")); 
1574         wxRegKey 
key(wxRegKey::HKCR
, path
); 
1576         if (!key
.Exists()) break; 
1578         // two cases: either there's an AliasForCharset string, 
1579         // or there are Codepage and InternetEncoding dwords. 
1580         // The InternetEncoding gives us the actual encoding, 
1581         // the Codepage just says which Windows character set to 
1582         // use when displaying the data. 
1583         if (key
.HasValue(wxT("InternetEncoding")) && 
1584             key
.QueryValue(wxT("InternetEncoding"), &CP
)) break; 
1586         // no encoding, see if it's an alias 
1587         if (!key
.HasValue(wxT("AliasForCharset")) || 
1588             !key
.QueryValue(wxT("AliasForCharset"), cn
)) break; 
1594 #endif // !wxUSE_GUI || !wxUSE_FONTMAP