1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Various utilities
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 // #pragma implementation "utils.h" // Note: this is done in utilscmn.cpp now.
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
27 #include "wx/cursor.h"
30 #include "wx/msw/private.h"
38 #if !defined(__GNUWIN32__) && !defined(__SALFORDC__)
46 #if defined(__GNUWIN32__) && !defined(__TWIN32__)
47 #include <sys/unistd.h>
53 #ifdef __BORLANDC__ // Please someone tell me which version of Borland needs
54 // this (3.1 I believe) and how to test for it.
55 // If this works for Borland 4.0 as well, then no worries.
71 #if !(defined(_MSC_VER) && (_MSC_VER > 800))
77 //// BEGIN for console support: VC++ only
80 #include "wx/msw/msvcrt.h"
84 #include "wx/ioswrap.h"
87 // N.B. BC++ doesn't have istream.h, ostream.h
94 /* Need to undef new if including crtdbg.h */
103 # if defined(__WXDEBUG__) && wxUSE_GLOBAL_MEMORY_OPERATORS && wxUSE_DEBUG_NEW_ALWAYS
104 # define new new(__FILE__,__LINE__)
109 /// END for console support
111 // In the WIN.INI file
112 static const char WX_SECTION
[] = "wxWindows";
113 static const char eHOSTNAME
[] = "HostName";
114 static const char eUSERID
[] = "UserId";
115 static const char eUSERNAME
[] = "UserName";
117 // For the following functions we SHOULD fill in support
118 // for Windows-NT (which I don't know) as I assume it begin
119 // a POSIX Unix (so claims MS) that it has some special
120 // functions beyond those provided by WinSock
122 // Get full hostname (eg. DoDo.BSn-Germany.crg.de)
123 bool wxGetHostName(char *buf
, int maxSize
)
125 #if defined(__WIN32__) && !defined(__TWIN32__)
126 DWORD nSize
= maxSize
;
127 return (::GetComputerName(buf
, &nSize
) != 0);
130 const char *default_host
= "noname";
132 if ((sysname
= getenv("SYSTEM_NAME")) == NULL
) {
133 GetProfileString(WX_SECTION
, eHOSTNAME
, default_host
, buf
, maxSize
- 1);
135 strncpy(buf
, sysname
, maxSize
- 1);
137 return *buf
? TRUE
: FALSE
;
141 // Get user ID e.g. jacs
142 bool wxGetUserId(char *buf
, int maxSize
)
144 #if defined(__WIN32__) && !defined(__win32s__) && !defined(__TWIN32__)
146 // VZ: why should it be so complicated??
148 // Gets the current user's full name according to the MS article PSS ID
150 // Seems to be the same as the login name for me?
151 char *UserName
= new char[256];
152 char *Domain
= new char[256];
153 DWORD maxCharacters
= 255;
154 GetUserName( UserName
, &maxCharacters
);
155 GetComputerName( Domain
, &maxCharacters
);
157 WCHAR wszUserName
[256]; // Unicode user name
158 WCHAR wszDomain
[256];
161 struct _SERVER_INFO_100
*si100
; // Server structure
162 struct _USER_INFO_2
*ui
; // User structure
164 // Convert ASCII user name and domain to Unicode.
166 MultiByteToWideChar( CP_ACP
, 0, UserName
,
167 strlen(UserName
)+1, wszUserName
, sizeof(wszUserName
) );
168 MultiByteToWideChar( CP_ACP
, 0, Domain
,
169 strlen(Domain
)+1, wszDomain
, sizeof(wszDomain
) );
171 // Get the computer name of a DC for the specified domain.
172 // >If you get a link error on this, include netapi32.lib<
174 NetGetDCName( NULL
, wszDomain
, &ComputerName
);
176 // Look up the user on the DC.
178 if(NetUserGetInfo( (LPWSTR
) ComputerName
,
179 (LPWSTR
) &wszUserName
, 2, (LPBYTE
*) &ui
))
181 printf( "Error getting user information.\n" );
185 // Convert the Unicode full name to ASCII.
187 WideCharToMultiByte( CP_ACP
, 0, ui
->usri2_full_name
,
188 -1, buf
, 256, NULL
, NULL
);
192 DWORD nSize
= maxSize
;
193 if ( ::GetUserName(buf
, &nSize
) == 0 )
195 wxLogSysError("Can not get user name");
203 #else // Win16 or Win32s
205 const char *default_id
= "anonymous";
207 // Can't assume we have NIS (PC-NFS) or some other ID daemon
209 if ( (user
= getenv("USER")) == NULL
&&
210 (user
= getenv("LOGNAME")) == NULL
) {
211 // Use wxWindows configuration data (comming soon)
212 GetProfileString(WX_SECTION
, eUSERID
, default_id
, buf
, maxSize
- 1);
214 strncpy(buf
, user
, maxSize
- 1);
215 return *buf
? TRUE
: FALSE
;
219 // Get user name e.g. Julian Smart
220 bool wxGetUserName(char *buf
, int maxSize
)
222 #if wxUSE_PENWINDOWS && !defined(__WATCOMC__) && !defined(__GNUWIN32__)
223 extern HANDLE g_hPenWin
; // PenWindows Running?
226 // PenWindows Does have a user concept!
227 // Get the current owner of the recognizer
228 GetPrivateProfileString("Current", "User", default_name
, wxBuffer
, maxSize
- 1, "PENWIN.INI");
229 strncpy(buf
, wxBuffer
, maxSize
- 1);
234 // Could use NIS, MS-Mail or other site specific programs
235 // Use wxWindows configuration data
236 bool ok
= GetProfileString(WX_SECTION
, eUSERNAME
, "", buf
, maxSize
- 1) != 0;
239 ok
= wxGetUserId(buf
, maxSize
);
244 strncpy(buf
, "Unknown User", maxSize
);
251 int wxKill(long pid
, int sig
)
257 // Execute a program in an Interactive Shell
260 wxShell(const wxString
& command
)
263 if ((shell
= getenv("COMSPEC")) == NULL
)
264 shell
= "\\COMMAND.COM";
268 sprintf(tmp
, "%s /c %s", shell
, WXSTRINGCAST command
);
272 return (wxExecute((char *)tmp
, FALSE
) != 0);
275 // Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX)
276 long wxGetFreeMemory()
278 #if defined(__WIN32__) && !defined(__BORLANDC__) && !defined(__TWIN32__)
279 MEMORYSTATUS memStatus
;
280 memStatus
.dwLength
= sizeof(MEMORYSTATUS
);
281 GlobalMemoryStatus(&memStatus
);
282 return memStatus
.dwAvailPhys
;
284 return (long)GetFreeSpace(0);
288 // Sleep for nSecs seconds. Attempt a Windows implementation using timers.
289 static bool inTimer
= FALSE
;
290 class wxSleepTimer
: public wxTimer
300 static wxTimer
*wxTheSleepTimer
= NULL
;
302 void wxUsleep(unsigned long milliseconds
)
305 ::Sleep(milliseconds
);
310 wxTheSleepTimer
= new wxSleepTimer
;
312 wxTheSleepTimer
->Start(milliseconds
);
315 if (wxTheApp
->Pending())
316 wxTheApp
->Dispatch();
318 delete wxTheSleepTimer
;
319 wxTheSleepTimer
= NULL
;
323 void wxSleep(int nSecs
)
325 #if 0 // WIN32 hangs app
331 wxTheSleepTimer
= new wxSleepTimer
;
333 wxTheSleepTimer
->Start(nSecs
*1000);
336 if (wxTheApp
->Pending())
337 wxTheApp
->Dispatch();
339 delete wxTheSleepTimer
;
340 wxTheSleepTimer
= NULL
;
344 // Consume all events until no more left
350 // Output a debug mess., in a system dependent fashion.
351 void wxDebugMsg(const char *fmt
...)
354 static char buffer
[512];
356 if (!wxTheApp
->GetWantDebugOutput())
361 wvsprintf(buffer
,fmt
,ap
) ;
362 OutputDebugString((LPCSTR
)buffer
) ;
367 // Non-fatal error: pop up message box and (possibly) continue
368 void wxError(const wxString
& msg
, const wxString
& title
)
370 sprintf(wxBuffer
, "%s\nContinue?", WXSTRINGCAST msg
);
371 if (MessageBox(NULL
, (LPCSTR
)wxBuffer
, (LPCSTR
)WXSTRINGCAST title
,
372 MB_ICONSTOP
| MB_YESNO
) == IDNO
)
376 // Fatal error: pop up message box and abort
377 void wxFatalError(const wxString
& msg
, const wxString
& title
)
379 sprintf(wxBuffer
, "%s: %s", WXSTRINGCAST title
, WXSTRINGCAST msg
);
380 FatalAppExit(0, (LPCSTR
)wxBuffer
);
386 // Removed by RD because IHMO syncronous sound is a Bad Thing. MessageBeep
387 // will do a similar thing anyway if there is no sound card...
389 // Beep(1000,1000) ; // 1kHz during 1 sec.
391 MessageBeep((UINT
)-1) ;
395 // Chris Breeze 27/5/98: revised WIN32 code to
396 // detect WindowsNT correctly
397 int wxGetOsVersion(int *majorVsn
, int *minorVsn
)
399 extern char *wxOsVersion
;
400 if (majorVsn
) *majorVsn
= 0;
401 if (minorVsn
) *minorVsn
= 0;
403 #if defined(__WIN32__) && !defined(__SC__)
405 memset(&info
, 0, sizeof(OSVERSIONINFO
));
406 info
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
407 if (GetVersionEx(&info
))
409 if (majorVsn
) *majorVsn
= info
.dwMajorVersion
;
410 if (minorVsn
) *minorVsn
= info
.dwMinorVersion
;
411 switch (info
.dwPlatformId
)
413 case VER_PLATFORM_WIN32s
:
416 case VER_PLATFORM_WIN32_WINDOWS
:
419 case VER_PLATFORM_WIN32_NT
:
424 return wxWINDOWS
; // error if we get here, return generic value
428 # ifdef __WINDOWS_386__
431 # if !defined(__WATCOMC__) && !defined(GNUWIN32) && wxUSE_PENWINDOWS
432 extern HANDLE g_hPenWin
;
433 retValue
= g_hPenWin
? wxPENWINDOWS
: wxWINDOWS
;
436 // @@@@ To be completed. I don't have the manual here...
437 if (majorVsn
) *majorVsn
= 3 ;
438 if (minorVsn
) *minorVsn
= 1 ;
443 // Reading and writing resources (eg WIN.INI, .Xdefaults)
445 bool wxWriteResource(const wxString
& section
, const wxString
& entry
, const wxString
& value
, const wxString
& file
)
448 return (WritePrivateProfileString((LPCSTR
)WXSTRINGCAST section
, (LPCSTR
)WXSTRINGCAST entry
, (LPCSTR
)value
, (LPCSTR
)WXSTRINGCAST file
) != 0);
450 return (WriteProfileString((LPCSTR
)WXSTRINGCAST section
, (LPCSTR
)WXSTRINGCAST entry
, (LPCSTR
)WXSTRINGCAST value
) != 0);
453 bool wxWriteResource(const wxString
& section
, const wxString
& entry
, float value
, const wxString
& file
)
456 sprintf(buf
, "%.4f", value
);
457 return wxWriteResource(section
, entry
, buf
, file
);
460 bool wxWriteResource(const wxString
& section
, const wxString
& entry
, long value
, const wxString
& file
)
463 sprintf(buf
, "%ld", value
);
464 return wxWriteResource(section
, entry
, buf
, file
);
467 bool wxWriteResource(const wxString
& section
, const wxString
& entry
, int value
, const wxString
& file
)
470 sprintf(buf
, "%d", value
);
471 return wxWriteResource(section
, entry
, buf
, file
);
474 bool wxGetResource(const wxString
& section
, const wxString
& entry
, char **value
, const wxString
& file
)
476 static const char defunkt
[] = "$$default";
479 int n
= GetPrivateProfileString((LPCSTR
)WXSTRINGCAST section
, (LPCSTR
)WXSTRINGCAST entry
, (LPCSTR
)defunkt
,
480 (LPSTR
)wxBuffer
, 1000, (LPCSTR
)WXSTRINGCAST file
);
481 if (n
== 0 || strcmp(wxBuffer
, defunkt
) == 0)
486 int n
= GetProfileString((LPCSTR
)WXSTRINGCAST section
, (LPCSTR
)WXSTRINGCAST entry
, (LPCSTR
)defunkt
,
487 (LPSTR
)wxBuffer
, 1000);
488 if (n
== 0 || strcmp(wxBuffer
, defunkt
) == 0)
491 if (*value
) delete[] (*value
);
492 *value
= copystring(wxBuffer
);
496 bool wxGetResource(const wxString
& section
, const wxString
& entry
, float *value
, const wxString
& file
)
499 bool succ
= wxGetResource(section
, entry
, (char **)&s
, file
);
502 *value
= (float)strtod(s
, NULL
);
509 bool wxGetResource(const wxString
& section
, const wxString
& entry
, long *value
, const wxString
& file
)
512 bool succ
= wxGetResource(section
, entry
, (char **)&s
, file
);
515 *value
= strtol(s
, NULL
, 10);
522 bool wxGetResource(const wxString
& section
, const wxString
& entry
, int *value
, const wxString
& file
)
525 bool succ
= wxGetResource(section
, entry
, (char **)&s
, file
);
528 *value
= (int)strtol(s
, NULL
, 10);
534 #endif // wxUSE_RESOURCES
536 // ---------------------------------------------------------------------------
537 // helper functiosn for showing a "busy" cursor
538 // ---------------------------------------------------------------------------
540 extern HCURSOR gs_wxBusyCursor
= 0; // new, busy cursor
541 static HCURSOR gs_wxBusyCursorOld
= 0; // old cursor
542 static int gs_wxBusyCursorCount
= 0;
544 // Set the cursor to the busy cursor for all windows
545 void wxBeginBusyCursor(wxCursor
*cursor
)
547 if ( gs_wxBusyCursorCount
++ == 0 )
549 gs_wxBusyCursor
= (HCURSOR
)cursor
->GetHCURSOR();
550 gs_wxBusyCursorOld
= ::SetCursor(gs_wxBusyCursor
);
552 //else: nothing to do, already set
555 // Restore cursor to normal
556 void wxEndBusyCursor()
558 wxCHECK_RET( gs_wxBusyCursorCount
> 0,
559 "no matching wxBeginBusyCursor() for wxEndBusyCursor()" );
561 if ( --gs_wxBusyCursorCount
== 0 )
563 ::SetCursor(gs_wxBusyCursorOld
);
565 gs_wxBusyCursorOld
= 0;
569 // TRUE if we're between the above two calls
572 return (gs_wxBusyCursorCount
> 0);
575 // ---------------------------------------------------------------------------
576 const char* wxGetHomeDir(wxString
*pstr
)
578 wxString
& strDir
= *pstr
;
580 #if defined(__UNIX__) && !defined(__TWIN32__)
581 const char *szHome
= getenv("HOME");
582 if ( szHome
== NULL
) {
584 wxLogWarning(_("can't find user's HOME, using current directory."));
590 // add a trailing slash if needed
591 if ( strDir
.Last() != '/' )
595 const char *szHome
= getenv("HOMEDRIVE");
596 if ( szHome
!= NULL
)
598 szHome
= getenv("HOMEPATH");
599 if ( szHome
!= NULL
) {
602 // the idea is that under NT these variables have default values
603 // of "%systemdrive%:" and "\\". As we don't want to create our
604 // config files in the root directory of the system drive, we will
605 // create it in our program's dir. However, if the user took care
606 // to set HOMEPATH to something other than "\\", we suppose that he
607 // knows what he is doing and use the supplied value.
608 if ( strcmp(szHome
, "\\") != 0 )
609 return strDir
.c_str();
613 // Win16 has no idea about home, so use the working directory instead
616 // 260 was taken from windef.h
622 ::GetModuleFileName(::GetModuleHandle(NULL
),
623 strPath
.GetWriteBuf(MAX_PATH
), MAX_PATH
);
624 strPath
.UngetWriteBuf();
626 // extract the dir name
627 wxSplitPath(strPath
, &strDir
, NULL
, NULL
);
631 return strDir
.c_str();
635 char *wxGetUserHome (const wxString
& user
)
638 wxString
user1(user
);
642 if (wxGetUserId(tmp
, sizeof(tmp
)/sizeof(char))) {
643 // Guests belong in the temp dir
644 if (Stricmp(tmp
, "annonymous") == 0) {
645 if ((home
= getenv("TMP")) != NULL
||
646 (home
= getenv("TMPDIR")) != NULL
||
647 (home
= getenv("TEMP")) != NULL
)
648 return *home
? home
: (char*)"\\";
650 if (Stricmp(tmp
, WXSTRINGCAST user1
) == 0)
655 if ((home
= getenv("HOME")) != NULL
)
657 strcpy(wxBuffer
, home
);
658 Unix2DosFilename(wxBuffer
);
661 return NULL
; // No home known!
664 // Check whether this window wants to process messages, e.g. Stop button
665 // in long calculations.
666 bool wxCheckForInterrupt(wxWindow
*wnd
)
670 HWND win
= (HWND
) wnd
->GetHWND();
671 while(PeekMessage(&msg
,win
,0,0,PM_REMOVE
)){
672 TranslateMessage(&msg
);
673 DispatchMessage(&msg
);
675 return TRUE
;//*** temporary?
678 wxFAIL_MSG("wnd==NULL !!!");
680 return FALSE
;//*** temporary?
684 // MSW only: get user-defined resource from the .res file.
685 // Returns NULL or newly-allocated memory, so use delete[] to clean up.
688 char *wxLoadUserResource(const wxString
& resourceName
, const wxString
& resourceType
)
691 #if !defined(__WIN32__) || defined(__TWIN32__)
692 HRSRC hResource
= ::FindResource(wxGetInstance(), WXSTRINGCAST resourceName
, WXSTRINGCAST resourceType
);
695 HRSRC hResource
= ::FindResourceW(wxGetInstance(), WXSTRINGCAST resourceName
, WXSTRINGCAST resourceType
);
697 HRSRC hResource
= ::FindResourceA(wxGetInstance(), WXSTRINGCAST resourceName
, WXSTRINGCAST resourceType
);
703 HGLOBAL hData
= ::LoadResource(wxGetInstance(), hResource
);
706 char *theText
= (char *)LockResource(hData
);
710 s
= copystring(theText
);
714 UnlockResource(hData
);
718 // GlobalFree(hData);
724 void wxGetMousePosition( int* x
, int* y
)
727 GetCursorPos( & pt
);
732 // Return TRUE if we have a colour display
733 bool wxColourDisplay()
735 HDC dc
= ::GetDC((HWND
) NULL
);
737 int noCols
= GetDeviceCaps(dc
, NUMCOLORS
);
738 if ((noCols
== -1) || (noCols
> 2))
742 ReleaseDC((HWND
) NULL
, dc
);
746 // Returns depth of screen
749 HDC dc
= ::GetDC((HWND
) NULL
);
750 int planes
= GetDeviceCaps(dc
, PLANES
);
751 int bitsPerPixel
= GetDeviceCaps(dc
, BITSPIXEL
);
752 int depth
= planes
*bitsPerPixel
;
753 ReleaseDC((HWND
) NULL
, dc
);
757 // Get size of display
758 void wxDisplaySize(int *width
, int *height
)
760 HDC dc
= ::GetDC((HWND
) NULL
);
761 *width
= GetDeviceCaps(dc
, HORZRES
); *height
= GetDeviceCaps(dc
, VERTRES
);
762 ReleaseDC((HWND
) NULL
, dc
);
765 bool wxDirExists(const wxString
& dir
)
767 /* MATTHEW: [6] Always use same code for Win32, call FindClose */
768 #if defined(__WIN32__)
769 WIN32_FIND_DATA fileInfo
;
772 struct ffblk fileInfo
;
774 struct find_t fileInfo
;
778 #if defined(__WIN32__)
779 HANDLE h
= FindFirstFile((LPTSTR
) WXSTRINGCAST dir
,(LPWIN32_FIND_DATA
)&fileInfo
);
781 if (h
==INVALID_HANDLE_VALUE
)
785 return ((fileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) == FILE_ATTRIBUTE_DIRECTORY
);
788 // In Borland findfirst has a different argument
789 // ordering from _dos_findfirst. But _dos_findfirst
790 // _should_ be ok in both MS and Borland... why not?
792 return ((findfirst(WXSTRINGCAST dir
, &fileInfo
, _A_SUBDIR
) == 0 && (fileInfo
.ff_attrib
& _A_SUBDIR
) != 0));
794 return (((_dos_findfirst(WXSTRINGCAST dir
, _A_SUBDIR
, &fileInfo
) == 0) && (fileInfo
.attrib
& _A_SUBDIR
)) != 0);
799 // ---------------------------------------------------------------------------
800 // window information functions
801 // ---------------------------------------------------------------------------
803 wxString WXDLLEXPORT
wxGetWindowText(WXHWND hWnd
)
806 int len
= GetWindowTextLength((HWND
)hWnd
) + 1;
807 GetWindowText((HWND
)hWnd
, str
.GetWriteBuf(len
), len
);
813 wxString WXDLLEXPORT
wxGetWindowClass(WXHWND hWnd
)
817 int len
= 256; // some starting value
821 // as we've #undefined GetClassName we must now manually choose the
822 // right function to call
835 #endif // Twin32/!Twin32
836 #endif // Unicode/ANSI
838 ((HWND
)hWnd
, str
.GetWriteBuf(len
), len
);
843 // the class name might have been truncated, retry with larger
856 WXWORD WXDLLEXPORT
wxGetWindowId(WXHWND hWnd
)
859 return GetWindowWord((HWND
)hWnd
, GWW_ID
);
861 return GetWindowLong((HWND
)hWnd
, GWL_ID
);
866 //------------------------------------------------------------------------
867 // wild character routines
868 //------------------------------------------------------------------------
870 bool wxIsWild( const wxString
& pattern
)
872 wxString tmp
= pattern
;
873 char *pat
= WXSTRINGCAST(tmp
);
876 case '?': case '*': case '[': case '{':
887 bool wxMatchWild( const wxString
& pat
, const wxString
& text
, bool dot_special
)
890 char *pattern
= WXSTRINGCAST(tmp1
);
891 wxString tmp2
= text
;
892 char *str
= WXSTRINGCAST(tmp2
);
895 bool done
= FALSE
, ret_code
, ok
;
896 // Below is for vi fans
897 const char OB
= '{', CB
= '}';
899 // dot_special means '.' only matches '.'
900 if (dot_special
&& *str
== '.' && *pattern
!= *str
)
903 while ((*pattern
!= '\0') && (!done
)
904 && (((*str
=='\0')&&((*pattern
==OB
)||(*pattern
=='*')))||(*str
!='\0'))) {
908 if (*pattern
!= '\0')
915 && (!(ret_code
=wxMatchWild(pattern
, str
++, FALSE
))))
920 while (*pattern
!= '\0')
927 if ((*pattern
== '\0') || (*pattern
== ']')) {
931 if (*pattern
== '\\') {
933 if (*pattern
== '\0') {
938 if (*(pattern
+ 1) == '-') {
941 if (*pattern
== ']') {
945 if (*pattern
== '\\') {
947 if (*pattern
== '\0') {
952 if ((*str
< c
) || (*str
> *pattern
)) {
956 } else if (*pattern
!= *str
) {
961 while ((*pattern
!= ']') && (*pattern
!= '\0')) {
962 if ((*pattern
== '\\') && (*(pattern
+ 1) != '\0'))
966 if (*pattern
!= '\0') {
976 while ((*pattern
!= CB
) && (*pattern
!= '\0')) {
979 while (ok
&& (*cp
!= '\0') && (*pattern
!= '\0')
980 && (*pattern
!= ',') && (*pattern
!= CB
)) {
981 if (*pattern
== '\\')
983 ok
= (*pattern
++ == *cp
++);
985 if (*pattern
== '\0') {
991 while ((*pattern
!= CB
) && (*pattern
!= '\0')) {
992 if (*++pattern
== '\\') {
993 if (*++pattern
== CB
)
998 while (*pattern
!=CB
&& *pattern
!=',' && *pattern
!='\0') {
999 if (*++pattern
== '\\') {
1000 if (*++pattern
== CB
|| *pattern
== ',')
1005 if (*pattern
!= '\0')
1010 if (*str
== *pattern
) {
1017 while (*pattern
== '*')
1019 return ((*str
== '\0') && (*pattern
== '\0'));
1024 #if defined(__WIN95__) && defined(__WXDEBUG__) && wxUSE_DBWIN32
1027 When I started programming with Visual C++ v4.0, I missed one of my favorite
1028 tools -- DBWIN. Finding the code for a simple debug trace utility, DBMON,
1029 on MSDN was a step in the right direction, but it is a console application
1030 and thus has limited features and extensibility. DBWIN32 is my creation
1031 to solve this problem.
1033 The code is essentially a merging of a stripped down version of the DBWIN code
1034 from VC 1.5 and DBMON.C with a few 32 bit changes.
1036 As of version 1.2B, DBWIN32 supports both Win95 and NT. The NT support is
1037 built into the operating system and works just by running DBWIN32. The Win95
1038 team decided not to support this hook, so I have provided code that will do
1039 this for you. See the file WIN95.TXT for instructions on installing this.
1041 If you have questions, problems or suggestions about DBWIN32, I welcome your
1042 feedback and plan to actively maintain the code.
1047 To download dbwin32, see e.g.:
1049 http://ftp.digital.com/pub/micro/NT/WinSite/programr/dbwin32.zip
1052 #if !defined(__MWERKS__) && !defined(__SALFORDC__) && !defined(__TWIN32__)
1053 #include <process.h>
1056 void OutputDebugStringW95(const char* lpOutputString
, ...)
1058 HANDLE heventDBWIN
; /* DBWIN32 synchronization object */
1059 HANDLE heventData
; /* data passing synch object */
1060 HANDLE hSharedFile
; /* memory mapped file shared data */
1061 LPSTR lpszSharedMem
;
1062 char achBuffer
[500];
1064 /* create the output buffer */
1066 va_start(args
, lpOutputString
);
1067 vsprintf(achBuffer
, lpOutputString
, args
);
1071 Do a regular OutputDebugString so that the output is
1072 still seen in the debugger window if it exists.
1074 This ifdef is necessary to avoid infinite recursion
1075 from the inclusion of W95TRACE.H
1078 ::OutputDebugStringW(achBuffer
);
1081 ::OutputDebugString(achBuffer
);
1083 ::OutputDebugStringA(achBuffer
);
1087 /* bail if it's not Win95 */
1089 OSVERSIONINFO VerInfo
;
1090 VerInfo
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
1091 GetVersionEx(&VerInfo
);
1092 if ( VerInfo
.dwPlatformId
!= VER_PLATFORM_WIN32_WINDOWS
)
1096 /* make sure DBWIN is open and waiting */
1097 heventDBWIN
= OpenEvent(EVENT_MODIFY_STATE
, FALSE
, "DBWIN_BUFFER_READY");
1100 //MessageBox(NULL, "DBWIN_BUFFER_READY nonexistent", NULL, MB_OK);
1104 /* get a handle to the data synch object */
1105 heventData
= OpenEvent(EVENT_MODIFY_STATE
, FALSE
, "DBWIN_DATA_READY");
1108 // MessageBox(NULL, "DBWIN_DATA_READY nonexistent", NULL, MB_OK);
1109 CloseHandle(heventDBWIN
);
1113 hSharedFile
= CreateFileMapping((HANDLE
)-1, NULL
, PAGE_READWRITE
, 0, 4096, "DBWIN_BUFFER");
1116 //MessageBox(NULL, "DebugTrace: Unable to create file mapping object DBWIN_BUFFER", "Error", MB_OK);
1117 CloseHandle(heventDBWIN
);
1118 CloseHandle(heventData
);
1122 lpszSharedMem
= (LPSTR
)MapViewOfFile(hSharedFile
, FILE_MAP_WRITE
, 0, 0, 512);
1125 //MessageBox(NULL, "DebugTrace: Unable to map shared memory", "Error", MB_OK);
1126 CloseHandle(heventDBWIN
);
1127 CloseHandle(heventData
);
1131 /* wait for buffer event */
1132 WaitForSingleObject(heventDBWIN
, INFINITE
);
1134 /* write it to the shared memory */
1135 #if defined( __BORLANDC__ ) || defined( __MWERKS__ ) || defined(__SALFORDC__)
1136 *((LPDWORD
)lpszSharedMem
) = getpid();
1138 *((LPDWORD
)lpszSharedMem
) = _getpid();
1141 wsprintf(lpszSharedMem
+ sizeof(DWORD
), "%s", achBuffer
);
1143 /* signal data ready event */
1144 SetEvent(heventData
);
1146 /* clean up handles */
1147 CloseHandle(hSharedFile
);
1148 CloseHandle(heventData
);
1149 CloseHandle(heventDBWIN
);
1160 // maximum mumber of lines the output console should have
1161 static const WORD MAX_CONSOLE_LINES
= 500;
1163 BOOL WINAPI
MyConsoleHandler( DWORD dwCtrlType
) { // control signal type
1168 void wxRedirectIOToConsole()
1172 CONSOLE_SCREEN_BUFFER_INFO coninfo
;
1175 // allocate a console for this app
1178 // set the screen buffer to be big enough to let us scroll text
1179 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE
),
1181 coninfo
.dwSize
.Y
= MAX_CONSOLE_LINES
;
1182 SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE
),
1185 // redirect unbuffered STDOUT to the console
1186 lStdHandle
= (long)GetStdHandle(STD_OUTPUT_HANDLE
);
1187 hConHandle
= _open_osfhandle(lStdHandle
, _O_TEXT
);
1188 if(hConHandle
<= 0) return;
1189 fp
= _fdopen( hConHandle
, "w" );
1191 setvbuf( stdout
, NULL
, _IONBF
, 0 );
1193 // redirect unbuffered STDIN to the console
1194 lStdHandle
= (long)GetStdHandle(STD_INPUT_HANDLE
);
1195 hConHandle
= _open_osfhandle(lStdHandle
, _O_TEXT
);
1196 if(hConHandle
<= 0) return;
1197 fp
= _fdopen( hConHandle
, "r" );
1199 setvbuf( stdin
, NULL
, _IONBF
, 0 );
1201 // redirect unbuffered STDERR to the console
1202 lStdHandle
= (long)GetStdHandle(STD_ERROR_HANDLE
);
1203 hConHandle
= _open_osfhandle(lStdHandle
, _O_TEXT
);
1204 if(hConHandle
<= 0) return;
1205 fp
= _fdopen( hConHandle
, "w" );
1207 setvbuf( stderr
, NULL
, _IONBF
, 0 );
1209 // make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
1210 // point to console as well
1211 ios::sync_with_stdio();
1213 SetConsoleCtrlHandler(MyConsoleHandler
, TRUE
);
1217 void wxRedirectIOToConsole()