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