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