]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/msw/utils.cpp
catches program exceptions in release build (VC++ only)
[wxWidgets.git] / src / msw / utils.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: utils.cpp
3// Purpose: Various utilities
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart and Markus Holzem
9// Licence: wxWindows license
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13// #pragma implementation "utils.h" // Note: this is done in utilscmn.cpp now.
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
23#ifndef WX_PRECOMP
24#include "wx/setup.h"
25#include "wx/utils.h"
26#include "wx/app.h"
27#include "wx/cursor.h"
28#endif //WX_PRECOMP
29
30#include "wx/msw/private.h"
31#include "wx/timer.h"
32
33#include <windows.h>
34
35#include <ctype.h>
36
37#ifndef __GNUWIN32__
38#include <direct.h>
39#ifndef __MWERKS__
40#include <dos.h>
41#endif
42#endif //GNUWIN32
43
44#ifdef __GNUWIN32__
45#include <sys/unistd.h>
46#include <sys/stat.h>
47#endif //GNUWIN32
48
49#include "wx/log.h"
50
51#ifdef __BORLANDC__ // Please someone tell me which version of Borland needs
52 // this (3.1 I believe) and how to test for it.
53 // If this works for Borland 4.0 as well, then no worries.
54#include <dir.h>
55#endif
56
57#ifdef __WIN32__
58#include <io.h>
59
60#ifndef __GNUWIN32__
61#include <shellapi.h>
62#endif
63#endif
64
65#include <stdio.h>
66#include <stdlib.h>
67#include <string.h>
68#ifndef __WATCOMC__
69#if !(defined(_MSC_VER) && (_MSC_VER > 800))
70#include <errno.h>
71#endif
72#endif
73#include <stdarg.h>
74
75//// BEGIN for console support: VC++ only
76
77#if defined(__WXDEBUG__) && !defined(__WIN16__) && defined(_MSC_VER) && !defined(__NO_VC_CRTDBG__)
78 #define wxUSE_VC_CRTDBG
79#else
80 #undef wxUSE_VC_CRTDBG
81#endif
82
83#ifdef wxUSE_VC_CRTDBG
84 // VC++ uses this macro as debug/release mode indicator
85 #ifndef _DEBUG
86 #define _DEBUG
87 #endif
88
89 #include <fcntl.h>
90
91#if wxUSE_IOSTREAMH
92// N.B. BC++ doesn't have istream.h, ostream.h
93# include <iostream.h>
94# include <io.h>
95# include <fstream.h>
96
97#else
98# include <istream>
99# include <ostream>
100# include <fstream>
101# ifdef _MSC_VER
102 using namespace std;
103# endif
104#endif
105
106/* Need to undef new if including crtdbg.h */
107# ifdef new
108# undef new
109# endif
110
111#ifndef __WIN16__
112# include <crtdbg.h>
113#endif
114
115# if defined(__WXDEBUG__) && wxUSE_GLOBAL_MEMORY_OPERATORS && wxUSE_DEBUG_NEW_ALWAYS
116# define new new(__FILE__,__LINE__)
117# endif
118
119#endif
120
121/// END for console support
122
123// In the WIN.INI file
124static const char WX_SECTION[] = "wxWindows";
125static const char eHOSTNAME[] = "HostName";
126static const char eUSERID[] = "UserId";
127static const char eUSERNAME[] = "UserName";
128
129// For the following functions we SHOULD fill in support
130// for Windows-NT (which I don't know) as I assume it begin
131// a POSIX Unix (so claims MS) that it has some special
132// functions beyond those provided by WinSock
133
134// Get full hostname (eg. DoDo.BSn-Germany.crg.de)
135bool wxGetHostName(char *buf, int maxSize)
136{
137#ifdef __WIN32__
138 DWORD nSize = maxSize;
139 return (::GetComputerName(buf, &nSize) != 0);
140#else
141 char *sysname;
142 const char *default_host = "noname";
143
144 if ((sysname = getenv("SYSTEM_NAME")) == NULL) {
145 GetProfileString(WX_SECTION, eHOSTNAME, default_host, buf, maxSize - 1);
146 } else
147 strncpy(buf, sysname, maxSize - 1);
148 buf[maxSize] = '\0';
149 return *buf ? TRUE : FALSE;
150#endif
151}
152
153// Get user ID e.g. jacs
154bool wxGetUserId(char *buf, int maxSize)
155{
156#if defined(__WIN32__) && !defined(__win32s__)
157
158 // VZ: why should it be so complicated??
159#if 0
160 // Gets the current user's full name according to the MS article PSS ID
161 // Number: Q119670
162 // Seems to be the same as the login name for me?
163 char *UserName = new char[256];
164 char *Domain = new char[256];
165 DWORD maxCharacters = 255;
166 GetUserName( UserName, &maxCharacters );
167 GetComputerName( Domain, &maxCharacters );
168
169 WCHAR wszUserName[256]; // Unicode user name
170 WCHAR wszDomain[256];
171 LPBYTE ComputerName;
172
173 struct _SERVER_INFO_100 *si100; // Server structure
174 struct _USER_INFO_2 *ui; // User structure
175
176 // Convert ASCII user name and domain to Unicode.
177
178 MultiByteToWideChar( CP_ACP, 0, UserName,
179 strlen(UserName)+1, wszUserName, sizeof(wszUserName) );
180 MultiByteToWideChar( CP_ACP, 0, Domain,
181 strlen(Domain)+1, wszDomain, sizeof(wszDomain) );
182
183 // Get the computer name of a DC for the specified domain.
184 // >If you get a link error on this, include netapi32.lib<
185
186 NetGetDCName( NULL, wszDomain, &ComputerName );
187
188 // Look up the user on the DC.
189
190 if(NetUserGetInfo( (LPWSTR) ComputerName,
191 (LPWSTR) &wszUserName, 2, (LPBYTE *) &ui))
192 {
193 printf( "Error getting user information.\n" );
194 return( FALSE );
195 }
196
197 // Convert the Unicode full name to ASCII.
198
199 WideCharToMultiByte( CP_ACP, 0, ui->usri2_full_name,
200 -1, buf, 256, NULL, NULL );
201 }
202 return( TRUE );
203#else // 1
204 DWORD nSize = maxSize;
205 if ( ::GetUserName(buf, &nSize) == 0 )
206 {
207 wxLogSysError("Can not get user name");
208
209 return FALSE;
210 }
211
212 return TRUE;
213#endif // 0/1
214
215#else // Win16 or Win32s
216 char *user;
217 const char *default_id = "anonymous";
218
219 // Can't assume we have NIS (PC-NFS) or some other ID daemon
220 // So we ...
221 if ( (user = getenv("USER")) == NULL &&
222 (user = getenv("LOGNAME")) == NULL ) {
223 // Use wxWindows configuration data (comming soon)
224 GetProfileString(WX_SECTION, eUSERID, default_id, buf, maxSize - 1);
225 } else
226 strncpy(buf, user, maxSize - 1);
227 return *buf ? TRUE : FALSE;
228#endif
229}
230
231// Get user name e.g. Julian Smart
232bool wxGetUserName(char *buf, int maxSize)
233{
234#if wxUSE_PENWINDOWS && !defined(__WATCOMC__) && !defined(__GNUWIN32__)
235 extern HANDLE g_hPenWin; // PenWindows Running?
236 if (g_hPenWin)
237 {
238 // PenWindows Does have a user concept!
239 // Get the current owner of the recognizer
240 GetPrivateProfileString("Current", "User", default_name, wxBuffer, maxSize - 1, "PENWIN.INI");
241 strncpy(buf, wxBuffer, maxSize - 1);
242 }
243 else
244#endif
245 {
246 // Could use NIS, MS-Mail or other site specific programs
247 // Use wxWindows configuration data
248 bool ok = GetProfileString(WX_SECTION, eUSERNAME, "", buf, maxSize - 1) != 0;
249 if ( !ok )
250 {
251 ok = wxGetUserId(buf, maxSize);
252 }
253
254 if ( !ok )
255 {
256 strncpy(buf, "Unknown User", maxSize);
257 }
258 }
259
260 return TRUE;
261}
262
263int wxKill(long pid, int sig)
264{
265 return 0;
266}
267
268//
269// Execute a program in an Interactive Shell
270//
271bool
272wxShell(const wxString& command)
273{
274 char *shell;
275 if ((shell = getenv("COMSPEC")) == NULL)
276 shell = "\\COMMAND.COM";
277
278 char tmp[255];
279 if (command != "")
280 sprintf(tmp, "%s /c %s", shell, WXSTRINGCAST command);
281 else
282 strcpy(tmp, shell);
283
284 return (wxExecute((char *)tmp, FALSE) != 0);
285}
286
287// Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX)
288long wxGetFreeMemory(void)
289{
290#if defined(__WIN32__) && !defined(__BORLANDC__)
291 MEMORYSTATUS memStatus;
292 memStatus.dwLength = sizeof(MEMORYSTATUS);
293 GlobalMemoryStatus(&memStatus);
294 return memStatus.dwAvailPhys;
295#else
296 return (long)GetFreeSpace(0);
297#endif
298}
299
300// Sleep for nSecs seconds. Attempt a Windows implementation using timers.
301static bool inTimer = FALSE;
302class wxSleepTimer: public wxTimer
303{
304 public:
305 inline void Notify(void)
306 {
307 inTimer = FALSE;
308 Stop();
309 }
310};
311
312static wxTimer *wxTheSleepTimer = NULL;
313
314void wxSleep(int nSecs)
315{
316#if 0 // WIN32 hangs app
317 Sleep( 1000*nSecs );
318#else
319 if (inTimer)
320 return;
321
322 wxTheSleepTimer = new wxSleepTimer;
323 inTimer = TRUE;
324 wxTheSleepTimer->Start(nSecs*1000);
325 while (inTimer)
326 {
327 if (wxTheApp->Pending())
328 wxTheApp->Dispatch();
329 }
330 delete wxTheSleepTimer;
331 wxTheSleepTimer = NULL;
332#endif
333}
334
335// Consume all events until no more left
336void wxFlushEvents(void)
337{
338// wxYield();
339}
340
341// Output a debug mess., in a system dependent fashion.
342void wxDebugMsg(const char *fmt ...)
343{
344 va_list ap;
345 static char buffer[512];
346
347 if (!wxTheApp->GetWantDebugOutput())
348 return ;
349
350 va_start(ap, fmt);
351
352 wvsprintf(buffer,fmt,ap) ;
353 OutputDebugString((LPCSTR)buffer) ;
354
355 va_end(ap);
356}
357
358// Non-fatal error: pop up message box and (possibly) continue
359void wxError(const wxString& msg, const wxString& title)
360{
361 sprintf(wxBuffer, "%s\nContinue?", WXSTRINGCAST msg);
362 if (MessageBox(NULL, (LPCSTR)wxBuffer, (LPCSTR)WXSTRINGCAST title,
363 MB_ICONSTOP | MB_YESNO) == IDNO)
364 wxExit();
365}
366
367// Fatal error: pop up message box and abort
368void wxFatalError(const wxString& msg, const wxString& title)
369{
370 sprintf(wxBuffer, "%s: %s", WXSTRINGCAST title, WXSTRINGCAST msg);
371 FatalAppExit(0, (LPCSTR)wxBuffer);
372}
373
374// Emit a beeeeeep
375void wxBell(void)
376{
377 // Removed by RD because IHMO syncronous sound is a Bad Thing. MessageBeep
378 // will do a similar thing anyway if there is no sound card...
379//#ifdef __WIN32__
380// Beep(1000,1000) ; // 1kHz during 1 sec.
381//#else
382 MessageBeep((UINT)-1) ;
383//#endif
384}
385
386// Chris Breeze 27/5/98: revised WIN32 code to
387// detect WindowsNT correctly
388int wxGetOsVersion(int *majorVsn, int *minorVsn)
389{
390 extern char *wxOsVersion;
391 if (majorVsn) *majorVsn = 0;
392 if (minorVsn) *minorVsn = 0;
393
394#if defined(__WIN32__) && !defined(__SC__)
395 OSVERSIONINFO info;
396 memset(&info, 0, sizeof(OSVERSIONINFO));
397 info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
398 if (GetVersionEx(&info))
399 {
400 if (majorVsn) *majorVsn = info.dwMajorVersion;
401 if (minorVsn) *minorVsn = info.dwMinorVersion;
402 switch (info.dwPlatformId)
403 {
404 case VER_PLATFORM_WIN32s:
405 return wxWIN32S;
406 break;
407 case VER_PLATFORM_WIN32_WINDOWS:
408 return wxWIN95;
409 break;
410 case VER_PLATFORM_WIN32_NT:
411 return wxWINDOWS_NT;
412 break;
413 }
414 }
415 return wxWINDOWS; // error if we get here, return generic value
416#else
417 // Win16 code...
418 int retValue = 0;
419# ifdef __WINDOWS_386__
420 retValue = wxWIN386;
421# else
422# if !defined(__WATCOMC__) && !defined(GNUWIN32) && wxUSE_PENWINDOWS
423 extern HANDLE g_hPenWin;
424 retValue = g_hPenWin ? wxPENWINDOWS : wxWINDOWS ;
425# endif
426# endif
427 // @@@@ To be completed. I don't have the manual here...
428 if (majorVsn) *majorVsn = 3 ;
429 if (minorVsn) *minorVsn = 1 ;
430 return retValue ;
431#endif
432}
433
434// Reading and writing resources (eg WIN.INI, .Xdefaults)
435#if wxUSE_RESOURCES
436bool wxWriteResource(const wxString& section, const wxString& entry, const wxString& value, const wxString& file)
437{
438 if (file != "")
439 return (WritePrivateProfileString((LPCSTR)WXSTRINGCAST section, (LPCSTR)WXSTRINGCAST entry, (LPCSTR)value, (LPCSTR)WXSTRINGCAST file) != 0);
440 else
441 return (WriteProfileString((LPCSTR)WXSTRINGCAST section, (LPCSTR)WXSTRINGCAST entry, (LPCSTR)WXSTRINGCAST value) != 0);
442}
443
444bool wxWriteResource(const wxString& section, const wxString& entry, float value, const wxString& file)
445{
446 char buf[50];
447 sprintf(buf, "%.4f", value);
448 return wxWriteResource(section, entry, buf, file);
449}
450
451bool wxWriteResource(const wxString& section, const wxString& entry, long value, const wxString& file)
452{
453 char buf[50];
454 sprintf(buf, "%ld", value);
455 return wxWriteResource(section, entry, buf, file);
456}
457
458bool wxWriteResource(const wxString& section, const wxString& entry, int value, const wxString& file)
459{
460 char buf[50];
461 sprintf(buf, "%d", value);
462 return wxWriteResource(section, entry, buf, file);
463}
464
465bool wxGetResource(const wxString& section, const wxString& entry, char **value, const wxString& file)
466{
467 static const char defunkt[] = "$$default";
468 if (file != "")
469 {
470 int n = GetPrivateProfileString((LPCSTR)WXSTRINGCAST section, (LPCSTR)WXSTRINGCAST entry, (LPCSTR)defunkt,
471 (LPSTR)wxBuffer, 1000, (LPCSTR)WXSTRINGCAST file);
472 if (n == 0 || strcmp(wxBuffer, defunkt) == 0)
473 return FALSE;
474 }
475 else
476 {
477 int n = GetProfileString((LPCSTR)WXSTRINGCAST section, (LPCSTR)WXSTRINGCAST entry, (LPCSTR)defunkt,
478 (LPSTR)wxBuffer, 1000);
479 if (n == 0 || strcmp(wxBuffer, defunkt) == 0)
480 return FALSE;
481 }
482 if (*value) delete[] (*value);
483 *value = copystring(wxBuffer);
484 return TRUE;
485 }
486
487bool wxGetResource(const wxString& section, const wxString& entry, float *value, const wxString& file)
488{
489 char *s = NULL;
490 bool succ = wxGetResource(section, entry, (char **)&s, file);
491 if (succ)
492 {
493 *value = (float)strtod(s, NULL);
494 delete[] s;
495 return TRUE;
496 }
497 else return FALSE;
498}
499
500bool wxGetResource(const wxString& section, const wxString& entry, long *value, const wxString& file)
501{
502 char *s = NULL;
503 bool succ = wxGetResource(section, entry, (char **)&s, file);
504 if (succ)
505 {
506 *value = strtol(s, NULL, 10);
507 delete[] s;
508 return TRUE;
509 }
510 else return FALSE;
511}
512
513bool wxGetResource(const wxString& section, const wxString& entry, int *value, const wxString& file)
514{
515 char *s = NULL;
516 bool succ = wxGetResource(section, entry, (char **)&s, file);
517 if (succ)
518 {
519 *value = (int)strtol(s, NULL, 10);
520 delete[] s;
521 return TRUE;
522 }
523 else return FALSE;
524}
525#endif // wxUSE_RESOURCES
526
527// Old cursor
528static HCURSOR wxBusyCursorOld = 0;
529static int wxBusyCursorCount = 0;
530
531// Set the cursor to the busy cursor for all windows
532void wxBeginBusyCursor(wxCursor *cursor)
533{
534 wxBusyCursorCount ++;
535 if (wxBusyCursorCount == 1)
536 {
537 wxBusyCursorOld = ::SetCursor((HCURSOR) cursor->GetHCURSOR());
538 }
539 else
540 {
541 (void)::SetCursor((HCURSOR) cursor->GetHCURSOR());
542 }
543}
544
545// Restore cursor to normal
546void wxEndBusyCursor(void)
547{
548 if (wxBusyCursorCount == 0)
549 return;
550
551 wxBusyCursorCount --;
552 if (wxBusyCursorCount == 0)
553 {
554 ::SetCursor(wxBusyCursorOld);
555 wxBusyCursorOld = 0;
556 }
557}
558
559// TRUE if we're between the above two calls
560bool wxIsBusy(void)
561{
562 return (wxBusyCursorCount > 0);
563}
564
565const char* wxGetHomeDir(wxString *pstr)
566{
567 wxString& strDir = *pstr;
568
569 #ifdef __UNIX__
570 const char *szHome = getenv("HOME");
571 if ( szHome == NULL ) {
572 // we're homeless...
573 wxLogWarning(_("can't find user's HOME, using current directory."));
574 strDir = ".";
575 }
576 else
577 strDir = szHome;
578
579 // add a trailing slash if needed
580 if ( strDir.Last() != '/' )
581 strDir << '/';
582 #else // Windows
583 #ifdef __WIN32__
584 const char *szHome = getenv("HOMEDRIVE");
585 if ( szHome != NULL )
586 strDir << szHome;
587 szHome = getenv("HOMEPATH");
588 if ( szHome != NULL ) {
589 strDir << szHome;
590
591 // the idea is that under NT these variables have default values
592 // of "%systemdrive%:" and "\\". As we don't want to create our
593 // config files in the root directory of the system drive, we will
594 // create it in our program's dir. However, if the user took care
595 // to set HOMEPATH to something other than "\\", we suppose that he
596 // knows what he is doing and use the supplied value.
597 if ( strcmp(szHome, "\\") != 0 )
598 return strDir.c_str();
599 }
600
601 #else // Win16
602 // Win16 has no idea about home, so use the working directory instead
603 #endif // WIN16/32
604
605 // 260 was taken from windef.h
606 #ifndef MAX_PATH
607 #define MAX_PATH 260
608 #endif
609
610 wxString strPath;
611 ::GetModuleFileName(::GetModuleHandle(NULL),
612 strPath.GetWriteBuf(MAX_PATH), MAX_PATH);
613 strPath.UngetWriteBuf();
614
615 // extract the dir name
616 wxSplitPath(strPath, &strDir, NULL, NULL);
617
618 #endif // UNIX/Win
619
620 return strDir.c_str();
621}
622
623// Hack for MS-DOS
624char *wxGetUserHome (const wxString& user)
625{
626 char *home;
627 wxString user1(user);
628
629 if (user1 != "") {
630 char tmp[64];
631 if (wxGetUserId(tmp, sizeof(tmp)/sizeof(char))) {
632 // Guests belong in the temp dir
633 if (Stricmp(tmp, "annonymous") == 0) {
634 if ((home = getenv("TMP")) != NULL ||
635 (home = getenv("TMPDIR")) != NULL ||
636 (home = getenv("TEMP")) != NULL)
637 return *home ? home : "\\";
638 }
639 if (Stricmp(tmp, WXSTRINGCAST user1) == 0)
640 user1 = "";
641 }
642 }
643 if (user1 == "")
644 if ((home = getenv("HOME")) != NULL)
645 {
646 strcpy(wxBuffer, home);
647 Unix2DosFilename(wxBuffer);
648 return wxBuffer;
649 }
650 return NULL; // No home known!
651}
652
653// Check whether this window wants to process messages, e.g. Stop button
654// in long calculations.
655bool wxCheckForInterrupt(wxWindow *wnd)
656{
657 if(wnd){
658 MSG msg;
659 HWND win= (HWND) wnd->GetHWND();
660 while(PeekMessage(&msg,win,0,0,PM_REMOVE)){
661 TranslateMessage(&msg);
662 DispatchMessage(&msg);
663 }
664 return TRUE;//*** temporary?
665 }
666 else{
667 wxError("wnd==NULL !!!");
668 return FALSE;//*** temporary?
669 }
670}
671
672// MSW only: get user-defined resource from the .res file.
673// Returns NULL or newly-allocated memory, so use delete[] to clean up.
674
675#ifdef __WXMSW__
676char *wxLoadUserResource(const wxString& resourceName, const wxString& resourceType)
677{
678 char *s = NULL;
679#ifndef __WIN32__
680 HRSRC hResource = ::FindResource(wxGetInstance(), WXSTRINGCAST resourceName, WXSTRINGCAST resourceType);
681#else
682#ifdef UNICODE
683 HRSRC hResource = ::FindResourceW(wxGetInstance(), WXSTRINGCAST resourceName, WXSTRINGCAST resourceType);
684#else
685 HRSRC hResource = ::FindResourceA(wxGetInstance(), WXSTRINGCAST resourceName, WXSTRINGCAST resourceType);
686#endif
687#endif
688
689 if (hResource == 0)
690 return NULL;
691 HGLOBAL hData = ::LoadResource(wxGetInstance(), hResource);
692 if (hData == 0)
693 return NULL;
694 char *theText = (char *)LockResource(hData);
695 if (!theText)
696 return NULL;
697
698 s = copystring(theText);
699
700 // Obsolete in WIN32
701#ifndef __WIN32__
702 UnlockResource(hData);
703#endif
704
705 // No need??
706// GlobalFree(hData);
707
708 return s;
709}
710#endif
711
712void wxGetMousePosition( int* x, int* y )
713{
714 POINT pt;
715 GetCursorPos( & pt );
716 *x = pt.x;
717 *y = pt.y;
718};
719
720// Return TRUE if we have a colour display
721bool wxColourDisplay(void)
722{
723 HDC dc = ::GetDC(NULL);
724 bool flag;
725 int noCols = GetDeviceCaps(dc, NUMCOLORS);
726 if ((noCols == -1) || (noCols > 2))
727 flag = TRUE;
728 else
729 flag = FALSE;
730 ReleaseDC(NULL, dc);
731 return flag;
732}
733
734// Returns depth of screen
735int wxDisplayDepth(void)
736{
737 HDC dc = ::GetDC(NULL);
738 int planes = GetDeviceCaps(dc, PLANES);
739 int bitsPerPixel = GetDeviceCaps(dc, BITSPIXEL);
740 int depth = planes*bitsPerPixel;
741 ReleaseDC(NULL, dc);
742 return depth;
743}
744
745// Get size of display
746void wxDisplaySize(int *width, int *height)
747{
748 HDC dc = ::GetDC(NULL);
749 *width = GetDeviceCaps(dc, HORZRES); *height = GetDeviceCaps(dc, VERTRES);
750 ReleaseDC(NULL, dc);
751}
752
753bool wxDirExists(const wxString& dir)
754{
755 /* MATTHEW: [6] Always use same code for Win32, call FindClose */
756#if defined(__WIN32__)
757 WIN32_FIND_DATA fileInfo;
758#else
759#ifdef __BORLANDC__
760 struct ffblk fileInfo;
761#else
762 struct find_t fileInfo;
763#endif
764#endif
765
766#if defined(__WIN32__)
767 HANDLE h = FindFirstFile((LPTSTR) WXSTRINGCAST dir,(LPWIN32_FIND_DATA)&fileInfo);
768
769 if (h==INVALID_HANDLE_VALUE)
770 return FALSE;
771 else {
772 FindClose(h);
773 return ((fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY);
774 }
775#else
776 // In Borland findfirst has a different argument
777 // ordering from _dos_findfirst. But _dos_findfirst
778 // _should_ be ok in both MS and Borland... why not?
779#ifdef __BORLANDC__
780 return ((findfirst(WXSTRINGCAST dir, &fileInfo, _A_SUBDIR) == 0 && (fileInfo.ff_attrib & _A_SUBDIR) != 0));
781#else
782 return (((_dos_findfirst(WXSTRINGCAST dir, _A_SUBDIR, &fileInfo) == 0) && (fileInfo.attrib & _A_SUBDIR)) != 0);
783#endif
784#endif
785}
786
787wxString WXDLLEXPORT wxGetWindowText(WXHWND hWnd)
788{
789 wxString str;
790 int len = GetWindowTextLength((HWND)hWnd) + 1;
791 GetWindowText((HWND)hWnd, str.GetWriteBuf(len), len);
792 str.UngetWriteBuf();
793
794 return str;
795}
796
797#if 0
798//------------------------------------------------------------------------
799// wild character routines
800//------------------------------------------------------------------------
801
802bool wxIsWild( const wxString& pattern )
803{
804 wxString tmp = pattern;
805 char *pat = WXSTRINGCAST(tmp);
806 while (*pat) {
807 switch (*pat++) {
808 case '?': case '*': case '[': case '{':
809 return TRUE;
810 case '\\':
811 if (!*pat++)
812 return FALSE;
813 }
814 }
815 return FALSE;
816};
817
818
819bool wxMatchWild( const wxString& pat, const wxString& text, bool dot_special )
820{
821 wxString tmp1 = pat;
822 char *pattern = WXSTRINGCAST(tmp1);
823 wxString tmp2 = text;
824 char *str = WXSTRINGCAST(tmp2);
825 char c;
826 char *cp;
827 bool done = FALSE, ret_code, ok;
828 // Below is for vi fans
829 const char OB = '{', CB = '}';
830
831 // dot_special means '.' only matches '.'
832 if (dot_special && *str == '.' && *pattern != *str)
833 return FALSE;
834
835 while ((*pattern != '\0') && (!done)
836 && (((*str=='\0')&&((*pattern==OB)||(*pattern=='*')))||(*str!='\0'))) {
837 switch (*pattern) {
838 case '\\':
839 pattern++;
840 if (*pattern != '\0')
841 pattern++;
842 break;
843 case '*':
844 pattern++;
845 ret_code = FALSE;
846 while ((*str!='\0')
847 && (!(ret_code=wxMatchWild(pattern, str++, FALSE))))
848 /*loop*/;
849 if (ret_code) {
850 while (*str != '\0')
851 str++;
852 while (*pattern != '\0')
853 pattern++;
854 }
855 break;
856 case '[':
857 pattern++;
858 repeat:
859 if ((*pattern == '\0') || (*pattern == ']')) {
860 done = TRUE;
861 break;
862 }
863 if (*pattern == '\\') {
864 pattern++;
865 if (*pattern == '\0') {
866 done = TRUE;
867 break;
868 }
869 }
870 if (*(pattern + 1) == '-') {
871 c = *pattern;
872 pattern += 2;
873 if (*pattern == ']') {
874 done = TRUE;
875 break;
876 }
877 if (*pattern == '\\') {
878 pattern++;
879 if (*pattern == '\0') {
880 done = TRUE;
881 break;
882 }
883 }
884 if ((*str < c) || (*str > *pattern)) {
885 pattern++;
886 goto repeat;
887 }
888 } else if (*pattern != *str) {
889 pattern++;
890 goto repeat;
891 }
892 pattern++;
893 while ((*pattern != ']') && (*pattern != '\0')) {
894 if ((*pattern == '\\') && (*(pattern + 1) != '\0'))
895 pattern++;
896 pattern++;
897 }
898 if (*pattern != '\0') {
899 pattern++, str++;
900 }
901 break;
902 case '?':
903 pattern++;
904 str++;
905 break;
906 case OB:
907 pattern++;
908 while ((*pattern != CB) && (*pattern != '\0')) {
909 cp = str;
910 ok = TRUE;
911 while (ok && (*cp != '\0') && (*pattern != '\0')
912 && (*pattern != ',') && (*pattern != CB)) {
913 if (*pattern == '\\')
914 pattern++;
915 ok = (*pattern++ == *cp++);
916 }
917 if (*pattern == '\0') {
918 ok = FALSE;
919 done = TRUE;
920 break;
921 } else if (ok) {
922 str = cp;
923 while ((*pattern != CB) && (*pattern != '\0')) {
924 if (*++pattern == '\\') {
925 if (*++pattern == CB)
926 pattern++;
927 }
928 }
929 } else {
930 while (*pattern!=CB && *pattern!=',' && *pattern!='\0') {
931 if (*++pattern == '\\') {
932 if (*++pattern == CB || *pattern == ',')
933 pattern++;
934 }
935 }
936 }
937 if (*pattern != '\0')
938 pattern++;
939 }
940 break;
941 default:
942 if (*str == *pattern) {
943 str++, pattern++;
944 } else {
945 done = TRUE;
946 }
947 }
948 }
949 while (*pattern == '*')
950 pattern++;
951 return ((*str == '\0') && (*pattern == '\0'));
952};
953
954#endif
955
956#if defined(__WIN95__) && defined(__WXDEBUG__) && wxUSE_DBWIN32
957
958/*
959When I started programming with Visual C++ v4.0, I missed one of my favorite
960tools -- DBWIN. Finding the code for a simple debug trace utility, DBMON,
961on MSDN was a step in the right direction, but it is a console application
962and thus has limited features and extensibility. DBWIN32 is my creation
963to solve this problem.
964
965The code is essentially a merging of a stripped down version of the DBWIN code
966from VC 1.5 and DBMON.C with a few 32 bit changes.
967
968As of version 1.2B, DBWIN32 supports both Win95 and NT. The NT support is
969built into the operating system and works just by running DBWIN32. The Win95
970team decided not to support this hook, so I have provided code that will do
971this for you. See the file WIN95.TXT for instructions on installing this.
972
973If you have questions, problems or suggestions about DBWIN32, I welcome your
974feedback and plan to actively maintain the code.
975
976Andrew Tucker
977ast@halcyon.com
978
979To download dbwin32, see e.g.:
980
981http://ftp.digital.com/pub/micro/NT/WinSite/programr/dbwin32.zip
982*/
983
984#ifndef __MWERKS__
985#include <process.h>
986#endif
987
988void OutputDebugStringW95(const char* lpOutputString, ...)
989{
990 HANDLE heventDBWIN; /* DBWIN32 synchronization object */
991 HANDLE heventData; /* data passing synch object */
992 HANDLE hSharedFile; /* memory mapped file shared data */
993 LPSTR lpszSharedMem;
994 char achBuffer[500];
995
996 /* create the output buffer */
997 va_list args;
998 va_start(args, lpOutputString);
999 vsprintf(achBuffer, lpOutputString, args);
1000 va_end(args);
1001
1002 /*
1003 Do a regular OutputDebugString so that the output is
1004 still seen in the debugger window if it exists.
1005
1006 This ifdef is necessary to avoid infinite recursion
1007 from the inclusion of W95TRACE.H
1008 */
1009#ifdef _UNICODE
1010 ::OutputDebugStringW(achBuffer);
1011#else
1012 ::OutputDebugStringA(achBuffer);
1013#endif
1014
1015 /* bail if it's not Win95 */
1016 {
1017 OSVERSIONINFO VerInfo;
1018 VerInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
1019 GetVersionEx(&VerInfo);
1020 if ( VerInfo.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS )
1021 return;
1022 }
1023
1024 /* make sure DBWIN is open and waiting */
1025 heventDBWIN = OpenEvent(EVENT_MODIFY_STATE, FALSE, "DBWIN_BUFFER_READY");
1026 if ( !heventDBWIN )
1027 {
1028 //MessageBox(NULL, "DBWIN_BUFFER_READY nonexistent", NULL, MB_OK);
1029 return;
1030 }
1031
1032 /* get a handle to the data synch object */
1033 heventData = OpenEvent(EVENT_MODIFY_STATE, FALSE, "DBWIN_DATA_READY");
1034 if ( !heventData )
1035 {
1036 // MessageBox(NULL, "DBWIN_DATA_READY nonexistent", NULL, MB_OK);
1037 CloseHandle(heventDBWIN);
1038 return;
1039 }
1040
1041 hSharedFile = CreateFileMapping((HANDLE)-1, NULL, PAGE_READWRITE, 0, 4096, "DBWIN_BUFFER");
1042 if (!hSharedFile)
1043 {
1044 //MessageBox(NULL, "DebugTrace: Unable to create file mapping object DBWIN_BUFFER", "Error", MB_OK);
1045 CloseHandle(heventDBWIN);
1046 CloseHandle(heventData);
1047 return;
1048 }
1049
1050 lpszSharedMem = (LPSTR)MapViewOfFile(hSharedFile, FILE_MAP_WRITE, 0, 0, 512);
1051 if (!lpszSharedMem)
1052 {
1053 //MessageBox(NULL, "DebugTrace: Unable to map shared memory", "Error", MB_OK);
1054 CloseHandle(heventDBWIN);
1055 CloseHandle(heventData);
1056 return;
1057 }
1058
1059 /* wait for buffer event */
1060 WaitForSingleObject(heventDBWIN, INFINITE);
1061
1062 /* write it to the shared memory */
1063#if defined( __BORLANDC__ ) || defined( __MWERKS__ )
1064 *((LPDWORD)lpszSharedMem) = getpid();
1065#else
1066 *((LPDWORD)lpszSharedMem) = _getpid();
1067#endif
1068
1069 wsprintf(lpszSharedMem + sizeof(DWORD), "%s", achBuffer);
1070
1071 /* signal data ready event */
1072 SetEvent(heventData);
1073
1074 /* clean up handles */
1075 CloseHandle(hSharedFile);
1076 CloseHandle(heventData);
1077 CloseHandle(heventDBWIN);
1078
1079 return;
1080}
1081
1082
1083#endif
1084
1085
1086#ifdef wxUSE_VC_CRTDBG
1087
1088// maximum mumber of lines the output console should have
1089static const WORD MAX_CONSOLE_LINES = 500;
1090
1091BOOL WINAPI MyConsoleHandler( DWORD dwCtrlType ) { // control signal type
1092 FreeConsole();
1093 return TRUE;
1094}
1095
1096void wxRedirectIOToConsole()
1097{
1098 int hConHandle;
1099 long lStdHandle;
1100 CONSOLE_SCREEN_BUFFER_INFO coninfo;
1101 FILE *fp;
1102
1103 // allocate a console for this app
1104 AllocConsole();
1105
1106 // set the screen buffer to be big enough to let us scroll text
1107 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),
1108 &coninfo);
1109 coninfo.dwSize.Y = MAX_CONSOLE_LINES;
1110 SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE),
1111 coninfo.dwSize);
1112
1113 // redirect unbuffered STDOUT to the console
1114 lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
1115 hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
1116 if(hConHandle <= 0) return;
1117 fp = _fdopen( hConHandle, "w" );
1118 *stdout = *fp;
1119 setvbuf( stdout, NULL, _IONBF, 0 );
1120
1121 // redirect unbuffered STDIN to the console
1122 lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
1123 hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
1124 if(hConHandle <= 0) return;
1125 fp = _fdopen( hConHandle, "r" );
1126 *stdin = *fp;
1127 setvbuf( stdin, NULL, _IONBF, 0 );
1128
1129 // redirect unbuffered STDERR to the console
1130 lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
1131 hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
1132 if(hConHandle <= 0) return;
1133 fp = _fdopen( hConHandle, "w" );
1134 *stderr = *fp;
1135 setvbuf( stderr, NULL, _IONBF, 0 );
1136
1137 // make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
1138 // point to console as well
1139 ios::sync_with_stdio();
1140
1141 SetConsoleCtrlHandler(MyConsoleHandler, TRUE);
1142
1143}
1144#else
1145// Not supported
1146void wxRedirectIOToConsole()
1147{
1148}
1149#endif
1150
1151