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(__GNUWIN32__) && !defined(__TWIN32__) 
  65     #include <sys/unistd.h> 
  69 #ifdef __BORLANDC__ // Please someone tell me which version of Borland needs 
  70                     // this (3.1 I believe) and how to test for it. 
  71                     // If this works for Borland 4.0 as well, then no worries. 
  75 // VZ: there is some code using NetXXX() functions to get the full user name: 
  76 //     I don't think it's a good idea because they don't work under Win95 and 
  77 //     seem to return the same as wxGetUserId() under NT. If you really want 
  78 //     to use them, just #define USE_NET_API 
  85 #if defined(__WIN32__) && !defined(__WXWINE__) && !defined(__WXMICROWIN__) 
  94     #if !(defined(_MSC_VER) && (_MSC_VER > 800)) 
  99 //// BEGIN for console support: VC++ only 
 102 #include "wx/msw/msvcrt.h" 
 106 #include "wx/ioswrap.h" 
 108 #include "wx/ioswrap.h" 
 110 /* Need to undef new if including crtdbg.h */ 
 119 #  if defined(__WXDEBUG__) && wxUSE_GLOBAL_MEMORY_OPERATORS && wxUSE_DEBUG_NEW_ALWAYS 
 120 #  define new new(__TFILE__,__LINE__) 
 125 /// END for console support 
 127 // ---------------------------------------------------------------------------- 
 129 // ---------------------------------------------------------------------------- 
 131 // In the WIN.INI file 
 132 static const wxChar WX_SECTION
[] = wxT("wxWindows"); 
 133 static const wxChar eUSERNAME
[]  = wxT("UserName"); 
 135 // these are only used under Win16 
 136 #if !defined(__WIN32__) && !defined(__WXMICROWIN__) 
 137 static const wxChar eHOSTNAME
[]  = wxT("HostName"); 
 138 static const wxChar eUSERID
[]    = wxT("UserId"); 
 141 #ifndef __WXMICROWIN__ 
 143 // ============================================================================ 
 145 // ============================================================================ 
 147 // ---------------------------------------------------------------------------- 
 148 // get host name and related 
 149 // ---------------------------------------------------------------------------- 
 151 // Get hostname only (without domain name) 
 152 bool wxGetHostName(wxChar 
*buf
, int maxSize
) 
 154 #if defined(__WIN32__) && !defined(__TWIN32__) && !defined(__WXMICROWIN__) 
 155     DWORD nSize 
= maxSize
; 
 156     if ( !::GetComputerName(buf
, &nSize
) ) 
 158         wxLogLastError(wxT("GetComputerName")); 
 166     const wxChar 
*default_host 
= wxT("noname"); 
 168     if ((sysname 
= wxGetenv(wxT("SYSTEM_NAME"))) == NULL
) { 
 169         GetProfileString(WX_SECTION
, eHOSTNAME
, default_host
, buf
, maxSize 
- 1); 
 171         wxStrncpy(buf
, sysname
, maxSize 
- 1); 
 172     buf
[maxSize
] = wxT('\0'); 
 173     return *buf 
? TRUE 
: FALSE
; 
 177 // get full hostname (with domain name if possible) 
 178 bool wxGetFullHostName(wxChar 
*buf
, int maxSize
) 
 180 #if defined(__WIN32__) && !defined(__TWIN32__) && !defined(__WXMICROWIN__) && ! (defined(__GNUWIN32__) && !defined(__MINGW32__)) 
 181     // TODO should use GetComputerNameEx() when available 
 183     if ( WSAStartup(MAKEWORD(1, 1), &wsa
) == 0 ) 
 187         if ( gethostname(bufA
, WXSIZEOF(bufA
)) == 0 ) 
 189             // gethostname() won't usually include the DNS domain name, for 
 190             // this we need to work a bit more 
 191             if ( !strchr(bufA
, '.') ) 
 193                 struct hostent 
*pHostEnt 
=  gethostbyname(bufA
); 
 197                     // Windows will use DNS internally now 
 198                     pHostEnt 
= gethostbyaddr(pHostEnt
->h_addr
, 4, PF_INET
); 
 203                     host 
= pHostEnt
->h_name
; 
 212             wxStrncpy(buf
, host
, maxSize
); 
 219     return wxGetHostName(buf
, maxSize
); 
 222 // Get user ID e.g. jacs 
 223 bool wxGetUserId(wxChar 
*buf
, int maxSize
) 
 225 #if defined(__WIN32__) && !defined(__win32s__) && !defined(__TWIN32__) && !defined(__WXMICROWIN__) 
 226     DWORD nSize 
= maxSize
; 
 227     if ( ::GetUserName(buf
, &nSize
) == 0 ) 
 229         // actually, it does happen on Win9x if the user didn't log on 
 230         DWORD res 
= ::GetEnvironmentVariable(wxT("username"), buf
, maxSize
); 
 239 #else   // Win16 or Win32s 
 241     const wxChar 
*default_id 
= wxT("anonymous"); 
 243     // Can't assume we have NIS (PC-NFS) or some other ID daemon 
 245     if (  (user 
= wxGetenv(wxT("USER"))) == NULL 
&& 
 246             (user 
= wxGetenv(wxT("LOGNAME"))) == NULL 
) 
 248         // Use wxWindows configuration data (comming soon) 
 249         GetProfileString(WX_SECTION
, eUSERID
, default_id
, buf
, maxSize 
- 1); 
 253         wxStrncpy(buf
, user
, maxSize 
- 1); 
 256     return *buf 
? TRUE 
: FALSE
; 
 260 // Get user name e.g. Julian Smart 
 261 bool wxGetUserName(wxChar 
*buf
, int maxSize
) 
 263 #if wxUSE_PENWINDOWS && !defined(__WATCOMC__) && !defined(__GNUWIN32__) 
 264     extern HANDLE g_hPenWin
; // PenWindows Running? 
 267         // PenWindows Does have a user concept! 
 268         // Get the current owner of the recognizer 
 269         GetPrivateProfileString("Current", "User", default_name
, wxBuffer
, maxSize 
- 1, "PENWIN.INI"); 
 270         strncpy(buf
, wxBuffer
, maxSize 
- 1); 
 276         CHAR szUserName
[256]; 
 277         if ( !wxGetUserId(szUserName
, WXSIZEOF(szUserName
)) ) 
 280         // TODO how to get the domain name? 
 283         // the code is based on the MSDN example (also see KB article Q119670) 
 284         WCHAR wszUserName
[256];          // Unicode user name 
 285         WCHAR wszDomain
[256]; 
 288         USER_INFO_2 
*ui2
;         // User structure 
 290         // Convert ANSI user name and domain to Unicode 
 291         MultiByteToWideChar( CP_ACP
, 0, szUserName
, strlen(szUserName
)+1, 
 292                 wszUserName
, WXSIZEOF(wszUserName
) ); 
 293         MultiByteToWideChar( CP_ACP
, 0, szDomain
, strlen(szDomain
)+1, 
 294                 wszDomain
, WXSIZEOF(wszDomain
) ); 
 296         // Get the computer name of a DC for the domain. 
 297         if ( NetGetDCName( NULL
, wszDomain
, &ComputerName 
) != NERR_Success 
) 
 299             wxLogError(wxT("Can not find domain controller")); 
 304         // Look up the user on the DC 
 305         NET_API_STATUS status 
= NetUserGetInfo( (LPWSTR
)ComputerName
, 
 306                 (LPWSTR
)&wszUserName
, 
 307                 2, // level - we want USER_INFO_2 
 315             case NERR_InvalidComputer
: 
 316                 wxLogError(wxT("Invalid domain controller name.")); 
 320             case NERR_UserNotFound
: 
 321                 wxLogError(wxT("Invalid user name '%s'."), szUserName
); 
 326                 wxLogSysError(wxT("Can't get information about user")); 
 331         // Convert the Unicode full name to ANSI 
 332         WideCharToMultiByte( CP_ACP
, 0, ui2
->usri2_full_name
, -1, 
 333                 buf
, maxSize
, NULL
, NULL 
); 
 338         wxLogError(wxT("Couldn't look up full user name.")); 
 341 #else  // !USE_NET_API 
 342         // Could use NIS, MS-Mail or other site specific programs 
 343         // Use wxWindows configuration data 
 344         bool ok 
= GetProfileString(WX_SECTION
, eUSERNAME
, wxT(""), buf
, maxSize 
- 1) != 0; 
 347             ok 
= wxGetUserId(buf
, maxSize
); 
 352             wxStrncpy(buf
, wxT("Unknown User"), maxSize
); 
 360 const wxChar
* wxGetHomeDir(wxString 
*pstr
) 
 362   wxString
& strDir 
= *pstr
; 
 364   #if defined(__UNIX__) && !defined(__TWIN32__) 
 365     const wxChar 
*szHome 
= wxGetenv("HOME"); 
 366     if ( szHome 
== NULL 
) { 
 368       wxLogWarning(_("can't find user's HOME, using current directory.")); 
 374     // add a trailing slash if needed 
 375     if ( strDir
.Last() != wxT('/') ) 
 379       const wxChar 
*szHome 
= wxGetenv(wxT("HOMEDRIVE")); 
 380       if ( szHome 
!= NULL 
) 
 382       szHome 
= wxGetenv(wxT("HOMEPATH")); 
 383       if ( szHome 
!= NULL 
) { 
 386         // the idea is that under NT these variables have default values 
 387         // of "%systemdrive%:" and "\\". As we don't want to create our 
 388         // config files in the root directory of the system drive, we will 
 389         // create it in our program's dir. However, if the user took care 
 390         // to set HOMEPATH to something other than "\\", we suppose that he 
 391         // knows what he is doing and use the supplied value. 
 392         if ( wxStrcmp(szHome
, wxT("\\")) != 0 ) 
 393           return strDir
.c_str(); 
 397       // Win16 has no idea about home, so use the working directory instead 
 400     // 260 was taken from windef.h 
 406     ::GetModuleFileName(::GetModuleHandle(NULL
), 
 407                         strPath
.GetWriteBuf(MAX_PATH
), MAX_PATH
); 
 408     strPath
.UngetWriteBuf(); 
 410     // extract the dir name 
 411     wxSplitPath(strPath
, &strDir
, NULL
, NULL
); 
 415   return strDir
.c_str(); 
 418 wxChar 
*wxGetUserHome(const wxString
& WXUNUSED(user
)) 
 420     // VZ: the old code here never worked for user != "" anyhow! Moreover, it 
 421     //     returned sometimes a malloc()'d pointer, sometimes a pointer to a 
 422     //     static buffer and sometimes I don't even know what. 
 423     static wxString s_home
; 
 425     return (wxChar 
*)wxGetHomeDir(&s_home
); 
 428 bool wxDirExists(const wxString
& dir
) 
 430 #ifdef __WXMICROWIN__ 
 431     return wxPathExist(dir
); 
 432 #elif defined(__WIN32__) 
 433     DWORD attribs 
= GetFileAttributes(dir
); 
 434     return ((attribs 
!= (DWORD
)-1) && (attribs 
& FILE_ATTRIBUTE_DIRECTORY
)); 
 437         struct ffblk fileInfo
; 
 439         struct find_t fileInfo
; 
 441     // In Borland findfirst has a different argument 
 442     // ordering from _dos_findfirst. But _dos_findfirst 
 443     // _should_ be ok in both MS and Borland... why not? 
 445         return (findfirst(dir
, &fileInfo
, _A_SUBDIR
) == 0 && 
 446                (fileInfo
.ff_attrib 
& _A_SUBDIR
) != 0); 
 448         return (_dos_findfirst(dir
, _A_SUBDIR
, &fileInfo
) == 0) && 
 449                ((fileInfo
.attrib 
& _A_SUBDIR
) != 0); 
 454 bool wxGetDiskSpace(const wxString
& path
, wxLongLong 
*pTotal
, wxLongLong 
*pFree
) 
 460     // GetDiskFreeSpaceEx() is not available under original Win95, check for 
 462     typedef BOOL (*GetDiskFreeSpaceEx_t
)(LPCTSTR
, 
 468         pGetDiskFreeSpaceEx 
= (GetDiskFreeSpaceEx_t
)::GetProcAddress
 
 470                                 ::GetModuleHandle(_T("kernel32.dll")), 
 472                                 "GetDiskFreeSpaceExW" 
 474                                 "GetDiskFreeSpaceExA" 
 478     if ( pGetDiskFreeSpaceEx 
) 
 480         ULARGE_INTEGER bytesFree
, bytesTotal
; 
 482         // may pass the path as is, GetDiskFreeSpaceEx() is smart enough 
 483         if ( !pGetDiskFreeSpaceEx(path
, 
 488             wxLogLastError(_T("GetDiskFreeSpaceEx")); 
 495             *pTotal 
= wxLongLong(bytesTotal
.HighPart
, bytesTotal
.LowPart
); 
 500             *pFree 
= wxLongLong(bytesFree
.HighPart
, bytesFree
.LowPart
); 
 506         // there's a problem with drives larger than 2GB, GetDiskFreeSpaceEx() 
 507         // should be used instead - but if it's not available, fall back on 
 508         // GetDiskFreeSpace() nevertheless... 
 510         DWORD lSectorsPerCluster
, 
 512               lNumberOfFreeClusters
, 
 513               lTotalNumberOfClusters
; 
 515         // FIXME: this is wrong, we should extract the root drive from path 
 516         //        instead, but this is the job for wxFileName... 
 517         if ( !::GetDiskFreeSpace(path
, 
 520                                  &lNumberOfFreeClusters
, 
 521                                  &lTotalNumberOfClusters
) ) 
 523             wxLogLastError(_T("GetDiskFreeSpace")); 
 528         wxLongLong lBytesPerCluster 
= lSectorsPerCluster
; 
 529         lBytesPerCluster 
*= lBytesPerSector
; 
 533             *pTotal 
= lBytesPerCluster
; 
 534             *pTotal 
*= lTotalNumberOfClusters
; 
 539             *pFree 
= lBytesPerCluster
; 
 540             *pFree 
*= lNumberOfFreeClusters
; 
 547 // ---------------------------------------------------------------------------- 
 549 // ---------------------------------------------------------------------------- 
 551 bool wxGetEnv(const wxString
& var
, wxString 
*value
) 
 554     const wxChar
* ret 
= wxGetenv(var
); 
 563     // first get the size of the buffer 
 564     DWORD dwRet 
= ::GetEnvironmentVariable(var
, NULL
, 0); 
 567         // this means that there is no such variable 
 573         (void)::GetEnvironmentVariable(var
, value
->GetWriteBuf(dwRet
), dwRet
); 
 574         value
->UngetWriteBuf(); 
 581 bool wxSetEnv(const wxString
& var
, const wxChar 
*value
) 
 583     // some compilers have putenv() or _putenv() or _wputenv() but it's better 
 584     // to always use Win32 function directly instead of dealing with them 
 585 #if defined(__WIN32__) 
 586     if ( !::SetEnvironmentVariable(var
, value
) ) 
 588         wxLogLastError(_T("SetEnvironmentVariable")); 
 594 #else // no way to set env vars 
 599 // ---------------------------------------------------------------------------- 
 600 // process management 
 601 // ---------------------------------------------------------------------------- 
 605 // structure used to pass parameters from wxKill() to wxEnumFindByPidProc() 
 606 struct wxFindByPidParams
 
 608     wxFindByPidParams() { hwnd 
= 0; pid 
= 0; } 
 610     // the HWND used to return the result 
 613     // the PID we're looking from 
 617 // wxKill helper: EnumWindows() callback which is used to find the first (top 
 618 // level) window belonging to the given process 
 619 BOOL CALLBACK 
wxEnumFindByPidProc(HWND hwnd
, LPARAM lParam
) 
 622     (void)::GetWindowThreadProcessId(hwnd
, &pid
); 
 624     wxFindByPidParams 
*params 
= (wxFindByPidParams 
*)lParam
; 
 625     if ( pid 
== params
->pid 
) 
 627         // remember the window we found 
 630         // return FALSE to stop the enumeration 
 634     // continue enumeration 
 640 int wxKill(long pid
, wxSignal sig
, wxKillError 
*krc
) 
 643     // get the process handle to operate on 
 644     HANDLE hProcess 
= ::OpenProcess(SYNCHRONIZE 
| 
 646                                     PROCESS_QUERY_INFORMATION
, 
 647                                     FALSE
, // not inheritable 
 649     if ( hProcess 
== NULL 
) 
 653             if ( ::GetLastError() == ERROR_ACCESS_DENIED 
) 
 655                 *krc 
= wxKILL_ACCESS_DENIED
; 
 659                 *krc 
= wxKILL_NO_PROCESS
; 
 670             // kill the process forcefully returning -1 as error code 
 671             if ( !::TerminateProcess(hProcess
, (UINT
)-1) ) 
 673                 wxLogSysError(_("Failed to kill process %d"), pid
); 
 677                     // this is not supposed to happen if we could open the 
 687             // do nothing, we just want to test for process existence 
 691             // any other signal means "terminate" 
 693                 wxFindByPidParams params
; 
 694                 params
.pid 
= (DWORD
)pid
; 
 696                 // EnumWindows() has nice semantics: it returns 0 if it found 
 697                 // something or if an error occured and non zero if it 
 698                 // enumerated all the window 
 699                 if ( !::EnumWindows(wxEnumFindByPidProc
, (LPARAM
)¶ms
) ) 
 701                     // did we find any window? 
 704                         // tell the app to close 
 706                         // NB: this is the harshest way, the app won't have 
 707                         //     opportunity to save any files, for example, but 
 708                         //     this is probably what we want here. If not we 
 709                         //     can also use SendMesageTimeout(WM_CLOSE) 
 710                         if ( !::PostMessage(params
.hwnd
, WM_QUIT
, 0, 0) ) 
 712                             wxLogLastError(_T("PostMessage(WM_QUIT)")); 
 715                     else // it was an error then 
 717                         wxLogLastError(_T("EnumWindows")); 
 722                 else // no windows for this PID 
 739         // as we wait for a short time, we can use just WaitForSingleObject() 
 740         // and not MsgWaitForMultipleObjects() 
 741         switch ( ::WaitForSingleObject(hProcess
, 500 /* msec */) ) 
 744                 // process terminated 
 745                 if ( !::GetExitCodeProcess(hProcess
, &rc
) ) 
 747                     wxLogLastError(_T("GetExitCodeProcess")); 
 752                 wxFAIL_MSG( _T("unexpected WaitForSingleObject() return") ); 
 756                 wxLogLastError(_T("WaitForSingleObject")); 
 771         // just to suppress the warnings about uninitialized variable 
 775     ::CloseHandle(hProcess
); 
 777     // the return code is the same as from Unix kill(): 0 if killed 
 778     // successfully or -1 on error 
 779     if ( sig 
== wxSIGNONE 
) 
 781         if ( ok 
&& rc 
== STILL_ACTIVE 
) 
 783             // there is such process => success 
 789         if ( ok 
&& rc 
!= STILL_ACTIVE 
) 
 796     wxFAIL_MSG( _T("not implemented") ); 
 797 #endif // Win32/Win16 
 803 // Execute a program in an Interactive Shell 
 804 bool wxShell(const wxString
& command
) 
 806     wxChar 
*shell 
= wxGetenv(wxT("COMSPEC")); 
 808         shell 
= wxT("\\COMMAND.COM"); 
 818         // pass the command to execute to the command processor 
 819         cmd
.Printf(wxT("%s /c %s"), shell
, command
.c_str()); 
 822     return wxExecute(cmd
, TRUE 
/* sync */) != 0; 
 825 // ---------------------------------------------------------------------------- 
 827 // ---------------------------------------------------------------------------- 
 829 // Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX) 
 830 long wxGetFreeMemory() 
 832 #if defined(__WIN32__) && !defined(__BORLANDC__) && !defined(__TWIN32__) 
 833     MEMORYSTATUS memStatus
; 
 834     memStatus
.dwLength 
= sizeof(MEMORYSTATUS
); 
 835     GlobalMemoryStatus(&memStatus
); 
 836     return memStatus
.dwAvailPhys
; 
 838     return (long)GetFreeSpace(0); 
 845     ::MessageBeep((UINT
)-1);        // default sound 
 848 wxString 
wxGetOsDescription() 
 856     info
.dwOSVersionInfoSize 
= sizeof(OSVERSIONINFO
); 
 857     if ( ::GetVersionEx(&info
) ) 
 859         switch ( info
.dwPlatformId 
) 
 861             case VER_PLATFORM_WIN32s
: 
 862                 str 
= _("Win32s on Windows 3.1"); 
 865             case VER_PLATFORM_WIN32_WINDOWS
: 
 866                 str
.Printf(_("Windows 9%c"), 
 867                            info
.dwMinorVersion 
== 0 ? _T('5') : _T('8')); 
 868                 if ( !wxIsEmpty(info
.szCSDVersion
) ) 
 870                     str 
<< _T(" (") << info
.szCSDVersion 
<< _T(')'); 
 874             case VER_PLATFORM_WIN32_NT
: 
 875                 str
.Printf(_T("Windows NT %lu.%lu (build %lu"), 
 879                 if ( !wxIsEmpty(info
.szCSDVersion
) ) 
 881                     str 
<< _T(", ") << info
.szCSDVersion
; 
 889         wxFAIL_MSG( _T("GetVersionEx() failed") ); // should never happen 
 894     return _("Windows 3.1"); 
 898 int wxGetOsVersion(int *majorVsn
, int *minorVsn
) 
 900 #if defined(__WIN32__) && !defined(__SC__) 
 904     info
.dwOSVersionInfoSize 
= sizeof(OSVERSIONINFO
); 
 905     if ( ::GetVersionEx(&info
) ) 
 908             *majorVsn 
= info
.dwMajorVersion
; 
 910             *minorVsn 
= info
.dwMinorVersion
; 
 912         switch ( info
.dwPlatformId 
) 
 914             case VER_PLATFORM_WIN32s
: 
 917             case VER_PLATFORM_WIN32_WINDOWS
: 
 920             case VER_PLATFORM_WIN32_NT
: 
 925     return wxWINDOWS
; // error if we get here, return generic value 
 927     int retValue 
= wxWINDOWS
; 
 928     #ifdef __WINDOWS_386__ 
 931         #if !defined(__WATCOMC__) && !defined(GNUWIN32) && wxUSE_PENWINDOWS 
 932             extern HANDLE g_hPenWin
; 
 933             retValue 
= g_hPenWin 
? wxPENWINDOWS 
: wxWINDOWS
; 
 946 // ---------------------------------------------------------------------------- 
 948 // ---------------------------------------------------------------------------- 
 954 // Sleep for nSecs seconds. Attempt a Windows implementation using timers. 
 955 static bool gs_inTimer 
= FALSE
; 
 957 class wxSleepTimer 
: public wxTimer
 
 960     virtual void Notify() 
 967 static wxTimer 
*wxTheSleepTimer 
= NULL
; 
 969 void wxUsleep(unsigned long milliseconds
) 
 972     ::Sleep(milliseconds
); 
 977     wxTheSleepTimer 
= new wxSleepTimer
; 
 979     wxTheSleepTimer
->Start(milliseconds
); 
 982         if (wxTheApp
->Pending()) 
 983             wxTheApp
->Dispatch(); 
 985     delete wxTheSleepTimer
; 
 986     wxTheSleepTimer 
= NULL
; 
 987 #endif // Win32/!Win32 
 990 void wxSleep(int nSecs
) 
 995     wxTheSleepTimer 
= new wxSleepTimer
; 
 997     wxTheSleepTimer
->Start(nSecs
*1000); 
1000         if (wxTheApp
->Pending()) 
1001             wxTheApp
->Dispatch(); 
1003     delete wxTheSleepTimer
; 
1004     wxTheSleepTimer 
= NULL
; 
1007 // Consume all events until no more left 
1008 void wxFlushEvents() 
1013 #endif // wxUSE_TIMER 
1015 #elif defined(__WIN32__) // wxUSE_GUI 
1017 void wxUsleep(unsigned long milliseconds
) 
1019     ::Sleep(milliseconds
); 
1022 void wxSleep(int nSecs
) 
1024     wxUsleep(1000*nSecs
); 
1027 #endif // wxUSE_GUI/!wxUSE_GUI 
1031 // ---------------------------------------------------------------------------- 
1032 // deprecated (in favour of wxLog) log functions 
1033 // ---------------------------------------------------------------------------- 
1037 // Output a debug mess., in a system dependent fashion. 
1038 #ifndef __WXMICROWIN__ 
1039 void wxDebugMsg(const wxChar 
*fmt 
...) 
1042   static wxChar buffer
[512]; 
1044   if (!wxTheApp
->GetWantDebugOutput()) 
1049   wvsprintf(buffer
,fmt
,ap
) ; 
1050   OutputDebugString((LPCTSTR
)buffer
) ; 
1055 // Non-fatal error: pop up message box and (possibly) continue 
1056 void wxError(const wxString
& msg
, const wxString
& title
) 
1058   wxSprintf(wxBuffer
, wxT("%s\nContinue?"), WXSTRINGCAST msg
); 
1059   if (MessageBox(NULL
, (LPCTSTR
)wxBuffer
, (LPCTSTR
)WXSTRINGCAST title
, 
1060              MB_ICONSTOP 
| MB_YESNO
) == IDNO
) 
1064 // Fatal error: pop up message box and abort 
1065 void wxFatalError(const wxString
& msg
, const wxString
& title
) 
1067   wxSprintf(wxBuffer
, wxT("%s: %s"), WXSTRINGCAST title
, WXSTRINGCAST msg
); 
1068   FatalAppExit(0, (LPCTSTR
)wxBuffer
); 
1070 #endif // __WXMICROWIN__ 
1072 // ---------------------------------------------------------------------------- 
1073 // functions to work with .INI files 
1074 // ---------------------------------------------------------------------------- 
1076 // Reading and writing resources (eg WIN.INI, .Xdefaults) 
1078 bool wxWriteResource(const wxString
& section
, const wxString
& entry
, const wxString
& value
, const wxString
& file
) 
1080   if (file 
!= wxT("")) 
1081 // Don't know what the correct cast should be, but it doesn't 
1082 // compile in BC++/16-bit without this cast. 
1083 #if !defined(__WIN32__) 
1084     return (WritePrivateProfileString((const char*) section
, (const char*) entry
, (const char*) value
, (const char*) file
) != 0); 
1086     return (WritePrivateProfileString((LPCTSTR
)WXSTRINGCAST section
, (LPCTSTR
)WXSTRINGCAST entry
, (LPCTSTR
)value
, (LPCTSTR
)WXSTRINGCAST file
) != 0); 
1089     return (WriteProfileString((LPCTSTR
)WXSTRINGCAST section
, (LPCTSTR
)WXSTRINGCAST entry
, (LPCTSTR
)WXSTRINGCAST value
) != 0); 
1092 bool wxWriteResource(const wxString
& section
, const wxString
& entry
, float value
, const wxString
& file
) 
1095     buf
.Printf(wxT("%.4f"), value
); 
1097     return wxWriteResource(section
, entry
, buf
, file
); 
1100 bool wxWriteResource(const wxString
& section
, const wxString
& entry
, long value
, const wxString
& file
) 
1103     buf
.Printf(wxT("%ld"), value
); 
1105     return wxWriteResource(section
, entry
, buf
, file
); 
1108 bool wxWriteResource(const wxString
& section
, const wxString
& entry
, int value
, const wxString
& file
) 
1111     buf
.Printf(wxT("%d"), value
); 
1113     return wxWriteResource(section
, entry
, buf
, file
); 
1116 bool wxGetResource(const wxString
& section
, const wxString
& entry
, wxChar 
**value
, const wxString
& file
) 
1118     static const wxChar defunkt
[] = wxT("$$default"); 
1119     if (file 
!= wxT("")) 
1121         int n 
= GetPrivateProfileString((LPCTSTR
)WXSTRINGCAST section
, (LPCTSTR
)WXSTRINGCAST entry
, (LPCTSTR
)defunkt
, 
1122                 (LPTSTR
)wxBuffer
, 1000, (LPCTSTR
)WXSTRINGCAST file
); 
1123         if (n 
== 0 || wxStrcmp(wxBuffer
, defunkt
) == 0) 
1128         int n 
= GetProfileString((LPCTSTR
)WXSTRINGCAST section
, (LPCTSTR
)WXSTRINGCAST entry
, (LPCTSTR
)defunkt
, 
1129                 (LPTSTR
)wxBuffer
, 1000); 
1130         if (n 
== 0 || wxStrcmp(wxBuffer
, defunkt
) == 0) 
1133     if (*value
) delete[] (*value
); 
1134     *value 
= copystring(wxBuffer
); 
1138 bool wxGetResource(const wxString
& section
, const wxString
& entry
, float *value
, const wxString
& file
) 
1141     bool succ 
= wxGetResource(section
, entry
, (wxChar 
**)&s
, file
); 
1144         *value 
= (float)wxStrtod(s
, NULL
); 
1151 bool wxGetResource(const wxString
& section
, const wxString
& entry
, long *value
, const wxString
& file
) 
1154     bool succ 
= wxGetResource(section
, entry
, (wxChar 
**)&s
, file
); 
1157         *value 
= wxStrtol(s
, NULL
, 10); 
1164 bool wxGetResource(const wxString
& section
, const wxString
& entry
, int *value
, const wxString
& file
) 
1167     bool succ 
= wxGetResource(section
, entry
, (wxChar 
**)&s
, file
); 
1170         *value 
= (int)wxStrtol(s
, NULL
, 10); 
1176 #endif // wxUSE_RESOURCES 
1178 // --------------------------------------------------------------------------- 
1179 // helper functions for showing a "busy" cursor 
1180 // --------------------------------------------------------------------------- 
1182 static HCURSOR gs_wxBusyCursor 
= 0;     // new, busy cursor 
1183 static HCURSOR gs_wxBusyCursorOld 
= 0;  // old cursor 
1184 static int gs_wxBusyCursorCount 
= 0; 
1186 extern HCURSOR 
wxGetCurrentBusyCursor() 
1188     return gs_wxBusyCursor
; 
1191 // Set the cursor to the busy cursor for all windows 
1192 void wxBeginBusyCursor(wxCursor 
*cursor
) 
1194     if ( gs_wxBusyCursorCount
++ == 0 ) 
1196         gs_wxBusyCursor 
= (HCURSOR
)cursor
->GetHCURSOR(); 
1197 #ifndef __WXMICROWIN__ 
1198         gs_wxBusyCursorOld 
= ::SetCursor(gs_wxBusyCursor
); 
1201     //else: nothing to do, already set 
1204 // Restore cursor to normal 
1205 void wxEndBusyCursor() 
1207     wxCHECK_RET( gs_wxBusyCursorCount 
> 0, 
1208                  wxT("no matching wxBeginBusyCursor() for wxEndBusyCursor()") ); 
1210     if ( --gs_wxBusyCursorCount 
== 0 ) 
1212 #ifndef __WXMICROWIN__ 
1213         ::SetCursor(gs_wxBusyCursorOld
); 
1215         gs_wxBusyCursorOld 
= 0; 
1219 // TRUE if we're between the above two calls 
1222   return (gs_wxBusyCursorCount 
> 0); 
1225 // Check whether this window wants to process messages, e.g. Stop button 
1226 // in long calculations. 
1227 bool wxCheckForInterrupt(wxWindow 
*wnd
) 
1229     wxCHECK( wnd
, FALSE 
); 
1232     while ( ::PeekMessage(&msg
, GetHwndOf(wnd
), 0, 0, PM_REMOVE
) ) 
1234         ::TranslateMessage(&msg
); 
1235         ::DispatchMessage(&msg
); 
1241 // MSW only: get user-defined resource from the .res file. 
1242 // Returns NULL or newly-allocated memory, so use delete[] to clean up. 
1244 #ifndef __WXMICROWIN__ 
1245 wxChar 
*wxLoadUserResource(const wxString
& resourceName
, const wxString
& resourceType
) 
1247     HRSRC hResource 
= ::FindResource(wxGetInstance(), resourceName
, resourceType
); 
1248     if ( hResource 
== 0 ) 
1251     HGLOBAL hData 
= ::LoadResource(wxGetInstance(), hResource
); 
1255     wxChar 
*theText 
= (wxChar 
*)::LockResource(hData
); 
1259     // Not all compilers put a zero at the end of the resource (e.g. BC++ doesn't). 
1260     // so we need to find the length of the resource. 
1261     int len 
= ::SizeofResource(wxGetInstance(), hResource
); 
1262     wxChar  
*s 
= new wxChar
[len
+1]; 
1263     wxStrncpy(s
,theText
,len
); 
1266     // wxChar *s = copystring(theText); 
1268     // Obsolete in WIN32 
1270     UnlockResource(hData
); 
1274     //  GlobalFree(hData); 
1280 // ---------------------------------------------------------------------------- 
1282 // ---------------------------------------------------------------------------- 
1284 // See also the wxGetMousePosition in window.cpp 
1285 // Deprecated: use wxPoint wxGetMousePosition() instead 
1286 void wxGetMousePosition( int* x
, int* y 
) 
1289     GetCursorPos( & pt 
); 
1294 // Return TRUE if we have a colour display 
1295 bool wxColourDisplay() 
1297 #ifdef __WXMICROWIN__ 
1301     // this function is called from wxDC ctor so it is called a *lot* of times 
1302     // hence we optimize it a bit but doign the check only once 
1304     // this should be MT safe as only the GUI thread (holding the GUI mutex) 
1306     static int s_isColour 
= -1; 
1308     if ( s_isColour 
== -1 ) 
1311         int noCols 
= ::GetDeviceCaps(dc
, NUMCOLORS
); 
1313         s_isColour 
= (noCols 
== -1) || (noCols 
> 2); 
1316     return s_isColour 
!= 0; 
1320 // Returns depth of screen 
1321 int wxDisplayDepth() 
1324     return GetDeviceCaps(dc
, PLANES
) * GetDeviceCaps(dc
, BITSPIXEL
); 
1327 // Get size of display 
1328 void wxDisplaySize(int *width
, int *height
) 
1330 #ifdef __WXMICROWIN__ 
1332     HWND hWnd 
= GetDesktopWindow(); 
1333     ::GetWindowRect(hWnd
, & rect
); 
1335     *width 
= rect
.right 
- rect
.left
; 
1336     *height 
= rect
.bottom 
- rect
.top
; 
1340     if ( width 
) *width 
= GetDeviceCaps(dc
, HORZRES
); 
1341     if ( height 
) *height 
= GetDeviceCaps(dc
, VERTRES
); 
1345 void wxDisplaySizeMM(int *width
, int *height
) 
1347 #ifdef __WXMICROWIN__ 
1349     *width 
= 0; * height 
= 0; 
1353     if ( width 
) *width 
= GetDeviceCaps(dc
, HORZSIZE
); 
1354     if ( height 
) *height 
= GetDeviceCaps(dc
, VERTSIZE
); 
1358 void wxClientDisplayRect(int *x
, int *y
, int *width
, int *height
) 
1360 #if defined(__WIN16__) || defined(__WXMICROWIN__) 
1362     wxDisplaySize(width
, height
); 
1364     // Determine the desktop dimensions minus the taskbar and any other 
1365     // special decorations... 
1368     SystemParametersInfo(SPI_GETWORKAREA
, 0, &r
, 0); 
1371     if (width
)  *width 
= r
.right 
- r
.left
; 
1372     if (height
) *height 
= r
.bottom 
- r
.top
; 
1377 // --------------------------------------------------------------------------- 
1378 // window information functions 
1379 // --------------------------------------------------------------------------- 
1381 wxString WXDLLEXPORT 
wxGetWindowText(WXHWND hWnd
) 
1384     int len 
= GetWindowTextLength((HWND
)hWnd
) + 1; 
1385     GetWindowText((HWND
)hWnd
, str
.GetWriteBuf(len
), len
); 
1386     str
.UngetWriteBuf(); 
1391 wxString WXDLLEXPORT 
wxGetWindowClass(WXHWND hWnd
) 
1393 #ifdef __WXMICROWIN__ 
1395     return wxEmptyString
; 
1399     int len 
= 256; // some starting value 
1403         // as we've #undefined GetClassName we must now manually choose the 
1404         // right function to call 
1417                 #endif // Twin32/!Twin32 
1418             #endif // Unicode/ANSI 
1420                                     ((HWND
)hWnd
, str
.GetWriteBuf(len
), len
); 
1422         str
.UngetWriteBuf(); 
1425             // the class name might have been truncated, retry with larger 
1439 WXWORD WXDLLEXPORT 
wxGetWindowId(WXHWND hWnd
) 
1442     return (WXWORD
)GetWindowWord((HWND
)hWnd
, GWW_ID
); 
1444     return (WXWORD
)GetWindowLong((HWND
)hWnd
, GWL_ID
); 
1452 // ---------------------------------------------------------------------------- 
1454 // ---------------------------------------------------------------------------- 
1456 extern void PixelToHIMETRIC(LONG 
*x
, LONG 
*y
) 
1460     int iWidthMM 
= GetDeviceCaps(hdcRef
, HORZSIZE
), 
1461         iHeightMM 
= GetDeviceCaps(hdcRef
, VERTSIZE
), 
1462         iWidthPels 
= GetDeviceCaps(hdcRef
, HORZRES
), 
1463         iHeightPels 
= GetDeviceCaps(hdcRef
, VERTRES
); 
1465     *x 
*= (iWidthMM 
* 100); 
1467     *y 
*= (iHeightMM 
* 100); 
1471 extern void HIMETRICToPixel(LONG 
*x
, LONG 
*y
) 
1475     int iWidthMM 
= GetDeviceCaps(hdcRef
, HORZSIZE
), 
1476         iHeightMM 
= GetDeviceCaps(hdcRef
, VERTSIZE
), 
1477         iWidthPels 
= GetDeviceCaps(hdcRef
, HORZRES
), 
1478         iHeightPels 
= GetDeviceCaps(hdcRef
, VERTRES
); 
1481     *x 
/= (iWidthMM 
* 100); 
1483     *y 
/= (iHeightMM 
* 100); 
1489 //------------------------------------------------------------------------ 
1490 // wild character routines 
1491 //------------------------------------------------------------------------ 
1493 bool wxIsWild( const wxString
& pattern 
) 
1495   wxString tmp 
= pattern
; 
1496   char *pat 
= WXSTRINGCAST(tmp
); 
1499   case '?': case '*': case '[': case '{': 
1510 bool wxMatchWild( const wxString
& pat
, const wxString
& text
, bool dot_special 
) 
1512   wxString tmp1 
= pat
; 
1513   char *pattern 
= WXSTRINGCAST(tmp1
); 
1514   wxString tmp2 
= text
; 
1515   char *str 
= WXSTRINGCAST(tmp2
); 
1518     bool done 
= FALSE
, ret_code
, ok
; 
1519     // Below is for vi fans 
1520     const char OB 
= '{', CB 
= '}'; 
1522     // dot_special means '.' only matches '.' 
1523     if (dot_special 
&& *str 
== '.' && *pattern 
!= *str
) 
1526     while ((*pattern 
!= '\0') && (!done
) 
1527     && (((*str
=='\0')&&((*pattern
==OB
)||(*pattern
=='*')))||(*str
!='\0'))) { 
1531       if (*pattern 
!= '\0') 
1538       && (!(ret_code
=wxMatchWild(pattern
, str
++, FALSE
)))) 
1541     while (*str 
!= '\0') 
1543     while (*pattern 
!= '\0') 
1550       if ((*pattern 
== '\0') || (*pattern 
== ']')) { 
1554       if (*pattern 
== '\\') { 
1556     if (*pattern 
== '\0') { 
1561       if (*(pattern 
+ 1) == '-') { 
1564     if (*pattern 
== ']') { 
1568     if (*pattern 
== '\\') { 
1570         if (*pattern 
== '\0') { 
1575     if ((*str 
< c
) || (*str 
> *pattern
)) { 
1579       } else if (*pattern 
!= *str
) { 
1584       while ((*pattern 
!= ']') && (*pattern 
!= '\0')) { 
1585     if ((*pattern 
== '\\') && (*(pattern 
+ 1) != '\0')) 
1589       if (*pattern 
!= '\0') { 
1599       while ((*pattern 
!= CB
) && (*pattern 
!= '\0')) { 
1602     while (ok 
&& (*cp 
!= '\0') && (*pattern 
!= '\0') 
1603     &&  (*pattern 
!= ',') && (*pattern 
!= CB
)) { 
1604         if (*pattern 
== '\\') 
1606         ok 
= (*pattern
++ == *cp
++); 
1608     if (*pattern 
== '\0') { 
1614         while ((*pattern 
!= CB
) && (*pattern 
!= '\0')) { 
1615       if (*++pattern 
== '\\') { 
1616           if (*++pattern 
== CB
) 
1621         while (*pattern
!=CB 
&& *pattern
!=',' && *pattern
!='\0') { 
1622       if (*++pattern 
== '\\') { 
1623                             if (*++pattern 
== CB 
|| *pattern 
== ',') 
1628     if (*pattern 
!= '\0') 
1633       if (*str 
== *pattern
) { 
1640     while (*pattern 
== '*') 
1642     return ((*str 
== '\0') && (*pattern 
== '\0')); 
1649 // maximum mumber of lines the output console should have 
1650 static const WORD MAX_CONSOLE_LINES 
= 500; 
1652 BOOL WINAPI 
MyConsoleHandler( DWORD dwCtrlType 
) {   //  control signal type 
1657 void wxRedirectIOToConsole() 
1661     CONSOLE_SCREEN_BUFFER_INFO coninfo
; 
1664     // allocate a console for this app 
1667     // set the screen buffer to be big enough to let us scroll text 
1668     GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE
), 
1670     coninfo
.dwSize
.Y 
= MAX_CONSOLE_LINES
; 
1671     SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE
), 
1674     // redirect unbuffered STDOUT to the console 
1675     lStdHandle 
= (long)GetStdHandle(STD_OUTPUT_HANDLE
); 
1676     hConHandle 
= _open_osfhandle(lStdHandle
, _O_TEXT
); 
1677     if(hConHandle 
<= 0) return; 
1678     fp 
= _fdopen( hConHandle
, "w" ); 
1680     setvbuf( stdout
, NULL
, _IONBF
, 0 ); 
1682     // redirect unbuffered STDIN to the console 
1683     lStdHandle 
= (long)GetStdHandle(STD_INPUT_HANDLE
); 
1684     hConHandle 
= _open_osfhandle(lStdHandle
, _O_TEXT
); 
1685     if(hConHandle 
<= 0) return; 
1686     fp 
= _fdopen( hConHandle
, "r" ); 
1688     setvbuf( stdin
, NULL
, _IONBF
, 0 ); 
1690     // redirect unbuffered STDERR to the console 
1691     lStdHandle 
= (long)GetStdHandle(STD_ERROR_HANDLE
); 
1692     hConHandle 
= _open_osfhandle(lStdHandle
, _O_TEXT
); 
1693     if(hConHandle 
<= 0) return; 
1694     fp 
= _fdopen( hConHandle
, "w" ); 
1696     setvbuf( stderr
, NULL
, _IONBF
, 0 ); 
1698     // make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog 
1699     // point to console as well 
1700     ios::sync_with_stdio(); 
1702     SetConsoleCtrlHandler(MyConsoleHandler
, TRUE
); 
1706 void wxRedirectIOToConsole() 
1711 #ifdef __WXMICROWIN__ 
1712 int wxGetOsVersion(int *majorVsn
, int *minorVsn
) 
1715     if (majorVsn
) *majorVsn 
= 0; 
1716     if (minorVsn
) *minorVsn 
= 0;