1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Various utilities
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 // #pragma implementation "utils.h" // Note: this is done in utilscmn.cpp now.
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
27 #include "wx/cursor.h"
30 #include "wx/msw/private.h"
41 #include <sys/unistd.h>
47 #ifdef __BORLANDC__ // Please someone tell me which version of Borland needs
48 // this (3.1 I believe) and how to test for it.
49 // If this works for Borland 4.0 as well, then no worries.
65 #if !(defined(_MSC_VER) && (_MSC_VER > 800))
71 // In the WIN.INI file
72 static const char WX_SECTION
[] = "wxWindows";
73 static const char eHOSTNAME
[] = "HostName";
74 static const char eUSERID
[] = "UserId";
75 static const char eUSERNAME
[] = "UserName";
77 // For the following functions we SHOULD fill in support
78 // for Windows-NT (which I don't know) as I assume it begin
79 // a POSIX Unix (so claims MS) that it has some special
80 // functions beyond those provided by WinSock
82 // Get full hostname (eg. DoDo.BSn-Germany.crg.de)
83 bool wxGetHostName(char *buf
, int maxSize
)
86 DWORD nSize
= maxSize
;
87 return (::GetComputerName(buf
, &nSize
) != 0);
90 const char *default_host
= "noname";
92 if ((sysname
= getenv("SYSTEM_NAME")) == NULL
) {
93 GetProfileString(WX_SECTION
, eHOSTNAME
, default_host
, buf
, maxSize
- 1);
95 strncpy(buf
, sysname
, maxSize
- 1);
97 return *buf
? TRUE
: FALSE
;
101 // Get user ID e.g. jacs
102 bool wxGetUserId(char *buf
, int maxSize
)
104 #if defined(__WIN32__) && !defined(__win32s__) && 0
105 // Gets the current user's full name according to the MS article PSS ID
107 // Seems to be the same as the login name for me?
108 char *UserName
= new char[256];
109 char *Domain
= new char[256];
110 DWORD maxCharacters
= 255;
111 GetUserName( UserName
, &maxCharacters
);
112 GetComputerName( Domain
, &maxCharacters
);
114 WCHAR wszUserName
[256]; // Unicode user name
115 WCHAR wszDomain
[256];
118 struct _SERVER_INFO_100
*si100
; // Server structure
119 struct _USER_INFO_2
*ui
; // User structure
121 // Convert ASCII user name and domain to Unicode.
123 MultiByteToWideChar( CP_ACP
, 0, UserName
,
124 strlen(UserName
)+1, wszUserName
, sizeof(wszUserName
) );
125 MultiByteToWideChar( CP_ACP
, 0, Domain
,
126 strlen(Domain
)+1, wszDomain
, sizeof(wszDomain
) );
128 // Get the computer name of a DC for the specified domain.
129 // >If you get a link error on this, include netapi32.lib<
131 NetGetDCName( NULL
, wszDomain
, &ComputerName
);
133 // Look up the user on the DC.
135 if(NetUserGetInfo( (LPWSTR
) ComputerName
,
136 (LPWSTR
) &wszUserName
, 2, (LPBYTE
*) &ui
))
138 printf( "Error getting user information.\n" );
142 // Convert the Unicode full name to ASCII.
144 WideCharToMultiByte( CP_ACP
, 0, ui
->usri2_full_name
,
145 -1, buf
, 256, NULL
, NULL
);
149 DWORD nSize = maxSize;
150 return ::GetUserName(buf, &nSize);
154 const char *default_id
= "anonymous";
156 // Can't assume we have NIS (PC-NFS) or some other ID daemon
158 if ( (user
= getenv("USER")) == NULL
&&
159 (user
= getenv("LOGNAME")) == NULL
) {
160 // Use wxWindows configuration data (comming soon)
161 GetProfileString(WX_SECTION
, eUSERID
, default_id
, buf
, maxSize
- 1);
163 strncpy(buf
, user
, maxSize
- 1);
164 return *buf
? TRUE
: FALSE
;
168 // Get user name e.g. Julian Smart
169 bool wxGetUserName(char *buf
, int maxSize
)
171 const char *default_name
= "Unknown User";
172 #if defined(__WIN32__)
174 DWORD nSize = maxSize;
175 In VC++ 4.0, results in unresolved symbol __imp__GetUserNameA
176 if (GetUserName(buf, &nSize))
180 // Could use NIS, MS-Mail or other site specific programs
181 // Use wxWindows configuration data
182 GetProfileString(WX_SECTION
, eUSERNAME
, default_name
, buf
, maxSize
- 1);
183 return *buf
? TRUE
: FALSE
;
186 #if !defined(__WATCOMC__) && !defined(__GNUWIN32__) && wxUSE_PENWINDOWS
187 extern HANDLE g_hPenWin
; // PenWindows Running?
190 // PenWindows Does have a user concept!
191 // Get the current owner of the recognizer
192 GetPrivateProfileString("Current", "User", default_name
, wxBuffer
, maxSize
- 1, "PENWIN.INI");
193 strncpy(buf
, wxBuffer
, maxSize
- 1);
198 // Could use NIS, MS-Mail or other site specific programs
199 // Use wxWindows configuration data
200 GetProfileString(WX_SECTION
, eUSERNAME
, default_name
, buf
, maxSize
- 1);
202 return *buf
? TRUE
: FALSE
;
206 int wxKill(long pid
, int sig
)
212 // Execute a program in an Interactive Shell
215 wxShell(const wxString
& command
)
218 if ((shell
= getenv("COMSPEC")) == NULL
)
219 shell
= "\\COMMAND.COM";
223 sprintf(tmp
, "%s /c %s", shell
, WXSTRINGCAST command
);
227 return (wxExecute((char *)tmp
, FALSE
) != 0);
230 // Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX)
231 long wxGetFreeMemory(void)
233 #if defined(__WIN32__) && !defined(__BORLANDC__)
234 MEMORYSTATUS memStatus
;
235 memStatus
.dwLength
= sizeof(MEMORYSTATUS
);
236 GlobalMemoryStatus(&memStatus
);
237 return memStatus
.dwAvailPhys
;
239 return (long)GetFreeSpace(0);
243 // Sleep for nSecs seconds. Attempt a Windows implementation using timers.
244 static bool inTimer
= FALSE
;
245 class wxSleepTimer
: public wxTimer
248 inline void Notify(void)
255 static wxTimer
*wxTheSleepTimer
= NULL
;
257 void wxSleep(int nSecs
)
259 #if 0 // WIN32 hangs app
265 wxTheSleepTimer
= new wxSleepTimer
;
267 wxTheSleepTimer
->Start(nSecs
*1000);
270 if (wxTheApp
->Pending())
271 wxTheApp
->Dispatch();
273 delete wxTheSleepTimer
;
274 wxTheSleepTimer
= NULL
;
278 // Consume all events until no more left
279 void wxFlushEvents(void)
284 // Output a debug mess., in a system dependent fashion.
285 void wxDebugMsg(const char *fmt
...)
288 static char buffer
[512];
290 if (!wxTheApp
->GetWantDebugOutput())
295 wvsprintf(buffer
,fmt
,ap
) ;
296 OutputDebugString((LPCSTR
)buffer
) ;
301 // Non-fatal error: pop up message box and (possibly) continue
302 void wxError(const wxString
& msg
, const wxString
& title
)
304 sprintf(wxBuffer
, "%s\nContinue?", WXSTRINGCAST msg
);
305 if (MessageBox(NULL
, (LPCSTR
)wxBuffer
, (LPCSTR
)WXSTRINGCAST title
,
306 MB_ICONSTOP
| MB_YESNO
) == IDNO
)
310 // Fatal error: pop up message box and abort
311 void wxFatalError(const wxString
& msg
, const wxString
& title
)
313 sprintf(wxBuffer
, "%s: %s", WXSTRINGCAST title
, WXSTRINGCAST msg
);
314 FatalAppExit(0, (LPCSTR
)wxBuffer
);
321 Beep(1000,1000) ; // 1kHz during 1 sec.
327 // Chris Breeze 27/5/98: revised WIN32 code to
328 // detect WindowsNT correctly
329 int wxGetOsVersion(int *majorVsn
, int *minorVsn
)
331 extern char *wxOsVersion
;
332 if (majorVsn
) *majorVsn
= 0;
333 if (minorVsn
) *minorVsn
= 0;
337 memset(&info
, 0, sizeof(OSVERSIONINFO
));
338 info
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
339 if (GetVersionEx(&info
))
341 if (majorVsn
) *majorVsn
= info
.dwMajorVersion
;
342 if (minorVsn
) *minorVsn
= info
.dwMinorVersion
;
343 switch (info
.dwPlatformId
)
345 case VER_PLATFORM_WIN32s
:
348 case VER_PLATFORM_WIN32_WINDOWS
:
351 case VER_PLATFORM_WIN32_NT
:
356 return wxWINDOWS
; // error if we get here, return generic value
360 # ifdef __WINDOWS_386__
363 # if !defined(__WATCOMC__) && !defined(GNUWIN32) && wxUSE_PENWINDOWS
364 extern HANDLE g_hPenWin
;
365 retValue
= g_hPenWin
? wxPENWINDOWS
: wxWINDOWS
;
368 // @@@@ To be completed. I don't have the manual here...
369 if (majorVsn
) *majorVsn
= 3 ;
370 if (minorVsn
) *minorVsn
= 1 ;
375 // Reading and writing resources (eg WIN.INI, .Xdefaults)
377 bool wxWriteResource(const wxString
& section
, const wxString
& entry
, const wxString
& value
, const wxString
& file
)
380 return (WritePrivateProfileString((LPCSTR
)WXSTRINGCAST section
, (LPCSTR
)WXSTRINGCAST entry
, (LPCSTR
)value
, (LPCSTR
)WXSTRINGCAST file
) != 0);
382 return (WriteProfileString((LPCSTR
)WXSTRINGCAST section
, (LPCSTR
)WXSTRINGCAST entry
, (LPCSTR
)WXSTRINGCAST value
) != 0);
385 bool wxWriteResource(const wxString
& section
, const wxString
& entry
, float value
, const wxString
& file
)
388 sprintf(buf
, "%.4f", value
);
389 return wxWriteResource(section
, entry
, buf
, file
);
392 bool wxWriteResource(const wxString
& section
, const wxString
& entry
, long value
, const wxString
& file
)
395 sprintf(buf
, "%ld", value
);
396 return wxWriteResource(section
, entry
, buf
, file
);
399 bool wxWriteResource(const wxString
& section
, const wxString
& entry
, int value
, const wxString
& file
)
402 sprintf(buf
, "%d", value
);
403 return wxWriteResource(section
, entry
, buf
, file
);
406 bool wxGetResource(const wxString
& section
, const wxString
& entry
, char **value
, const wxString
& file
)
408 static const char defunkt
[] = "$$default";
411 int n
= GetPrivateProfileString((LPCSTR
)WXSTRINGCAST section
, (LPCSTR
)WXSTRINGCAST entry
, (LPCSTR
)defunkt
,
412 (LPSTR
)wxBuffer
, 1000, (LPCSTR
)WXSTRINGCAST file
);
413 if (n
== 0 || strcmp(wxBuffer
, defunkt
) == 0)
418 int n
= GetProfileString((LPCSTR
)WXSTRINGCAST section
, (LPCSTR
)WXSTRINGCAST entry
, (LPCSTR
)defunkt
,
419 (LPSTR
)wxBuffer
, 1000);
420 if (n
== 0 || strcmp(wxBuffer
, defunkt
) == 0)
423 if (*value
) delete[] (*value
);
424 *value
= copystring(wxBuffer
);
428 bool wxGetResource(const wxString
& section
, const wxString
& entry
, float *value
, const wxString
& file
)
431 bool succ
= wxGetResource(section
, entry
, (char **)&s
, file
);
434 *value
= (float)strtod(s
, NULL
);
441 bool wxGetResource(const wxString
& section
, const wxString
& entry
, long *value
, const wxString
& file
)
444 bool succ
= wxGetResource(section
, entry
, (char **)&s
, file
);
447 *value
= strtol(s
, NULL
, 10);
454 bool wxGetResource(const wxString
& section
, const wxString
& entry
, int *value
, const wxString
& file
)
457 bool succ
= wxGetResource(section
, entry
, (char **)&s
, file
);
460 *value
= (int)strtol(s
, NULL
, 10);
466 #endif // wxUSE_RESOURCES
469 static HCURSOR wxBusyCursorOld
= 0;
470 static int wxBusyCursorCount
= 0;
472 // Set the cursor to the busy cursor for all windows
473 void wxBeginBusyCursor(wxCursor
*cursor
)
475 wxBusyCursorCount
++;
476 if (wxBusyCursorCount
== 1)
478 wxBusyCursorOld
= ::SetCursor((HCURSOR
) cursor
->GetHCURSOR());
482 (void)::SetCursor((HCURSOR
) cursor
->GetHCURSOR());
486 // Restore cursor to normal
487 void wxEndBusyCursor(void)
489 if (wxBusyCursorCount
== 0)
492 wxBusyCursorCount
--;
493 if (wxBusyCursorCount
== 0)
495 ::SetCursor(wxBusyCursorOld
);
500 // TRUE if we're between the above two calls
503 return (wxBusyCursorCount
> 0);
506 const char* WXDLLEXPORT
wxGetHomeDir(wxString
*pstr
)
508 wxString
& strDir
= *pstr
;
511 const char *szHome
= getenv("HOME");
512 if ( szHome
== NULL
) {
514 wxLogWarning(_("can't find user's HOME, using current directory."));
520 // add a trailing slash if needed
521 if ( strDir
.Last() != '/' )
525 const char *szHome
= getenv("HOMEDRIVE");
526 if ( szHome
!= NULL
)
528 szHome
= getenv("HOMEPATH");
529 if ( szHome
!= NULL
) {
532 // the idea is that under NT these variables have default values
533 // of "%systemdrive%:" and "\\". As we don't want to create our
534 // config files in the root directory of the system drive, we will
535 // create it in our program's dir. However, if the user took care
536 // to set HOMEPATH to something other than "\\", we suppose that he
537 // knows what he is doing and use the supplied value.
538 if ( strcmp(szHome
, "\\") != 0 )
539 return strDir
.c_str();
543 // Win16 has no idea about home, so use the working directory instead
546 // 260 was taken from windef.h
552 ::GetModuleFileName(::GetModuleHandle(NULL
),
553 strPath
.GetWriteBuf(MAX_PATH
), MAX_PATH
);
554 strPath
.UngetWriteBuf();
556 // extract the dir name
557 wxSplitPath(strPath
, &strDir
, NULL
, NULL
);
561 return strDir
.c_str();
565 char *wxGetUserHome (const wxString
& user
)
568 wxString
user1(user
);
572 if (wxGetUserId(tmp
, sizeof(tmp
)/sizeof(char))) {
573 // Guests belong in the temp dir
574 if (Stricmp(tmp
, "annonymous") == 0) {
575 if ((home
= getenv("TMP")) != NULL
||
576 (home
= getenv("TMPDIR")) != NULL
||
577 (home
= getenv("TEMP")) != NULL
)
578 return *home
? home
: "\\";
580 if (Stricmp(tmp
, WXSTRINGCAST user1
) == 0)
585 if ((home
= getenv("HOME")) != NULL
)
587 strcpy(wxBuffer
, home
);
588 Unix2DosFilename(wxBuffer
);
591 return NULL
; // No home known!
594 // Check whether this window wants to process messages, e.g. Stop button
595 // in long calculations.
596 bool wxCheckForInterrupt(wxWindow
*wnd
)
600 HWND win
= (HWND
) wnd
->GetHWND();
601 while(PeekMessage(&msg
,win
,0,0,PM_REMOVE
)){
602 TranslateMessage(&msg
);
603 DispatchMessage(&msg
);
605 return TRUE
;//*** temporary?
608 wxError("wnd==NULL !!!");
609 return FALSE
;//*** temporary?
613 // MSW only: get user-defined resource from the .res file.
614 // Returns NULL or newly-allocated memory, so use delete[] to clean up.
617 char *wxLoadUserResource(const wxString
& resourceName
, const wxString
& resourceType
)
621 HRSRC hResource
= ::FindResource(wxGetInstance(), WXSTRINGCAST resourceName
, WXSTRINGCAST resourceType
);
624 HRSRC hResource
= ::FindResourceW(wxGetInstance(), WXSTRINGCAST resourceName
, WXSTRINGCAST resourceType
);
626 HRSRC hResource
= ::FindResourceA(wxGetInstance(), WXSTRINGCAST resourceName
, WXSTRINGCAST resourceType
);
632 HGLOBAL hData
= ::LoadResource(wxGetInstance(), hResource
);
635 char *theText
= (char *)LockResource(hData
);
639 s
= copystring(theText
);
643 UnlockResource(hData
);
647 // GlobalFree(hData);
653 void wxGetMousePosition( int* x
, int* y
)
656 GetCursorPos( & pt
);
661 // Return TRUE if we have a colour display
662 bool wxColourDisplay(void)
664 HDC dc
= ::GetDC(NULL
);
666 int noCols
= GetDeviceCaps(dc
, NUMCOLORS
);
667 if ((noCols
== -1) || (noCols
> 2))
675 // Returns depth of screen
676 int wxDisplayDepth(void)
678 HDC dc
= ::GetDC(NULL
);
679 int planes
= GetDeviceCaps(dc
, PLANES
);
680 int bitsPerPixel
= GetDeviceCaps(dc
, BITSPIXEL
);
681 int depth
= planes
*bitsPerPixel
;
686 // Get size of display
687 void wxDisplaySize(int *width
, int *height
)
689 HDC dc
= ::GetDC(NULL
);
690 *width
= GetDeviceCaps(dc
, HORZRES
); *height
= GetDeviceCaps(dc
, VERTRES
);
694 bool wxDirExists(const wxString
& dir
)
696 /* MATTHEW: [6] Always use same code for Win32, call FindClose */
697 #if defined(__WIN32__)
698 WIN32_FIND_DATA fileInfo
;
701 struct ffblk fileInfo
;
703 struct find_t fileInfo
;
707 #if defined(__WIN32__)
708 HANDLE h
= FindFirstFile((LPTSTR
) WXSTRINGCAST dir
,(LPWIN32_FIND_DATA
)&fileInfo
);
710 if (h
==INVALID_HANDLE_VALUE
)
714 return ((fileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) == FILE_ATTRIBUTE_DIRECTORY
);
717 // In Borland findfirst has a different argument
718 // ordering from _dos_findfirst. But _dos_findfirst
719 // _should_ be ok in both MS and Borland... why not?
721 return ((findfirst(WXSTRINGCAST dir
, &fileInfo
, _A_SUBDIR
) == 0 && (fileInfo
.ff_attrib
& _A_SUBDIR
) != 0));
723 return (((_dos_findfirst(WXSTRINGCAST dir
, _A_SUBDIR
, &fileInfo
) == 0) && (fileInfo
.attrib
& _A_SUBDIR
)) != 0);
728 wxString WXDLLEXPORT
wxGetWindowText(WXHWND hWnd
)
731 int len
= GetWindowTextLength((HWND
)hWnd
) + 1;
732 GetWindowText((HWND
)hWnd
, str
.GetWriteBuf(len
), len
);
739 //------------------------------------------------------------------------
740 // wild character routines
741 //------------------------------------------------------------------------
743 bool wxIsWild( const wxString
& pattern
)
745 wxString tmp
= pattern
;
746 char *pat
= WXSTRINGCAST(tmp
);
749 case '?': case '*': case '[': case '{':
760 bool wxMatchWild( const wxString
& pat
, const wxString
& text
, bool dot_special
)
763 char *pattern
= WXSTRINGCAST(tmp1
);
764 wxString tmp2
= text
;
765 char *str
= WXSTRINGCAST(tmp2
);
768 bool done
= FALSE
, ret_code
, ok
;
769 // Below is for vi fans
770 const char OB
= '{', CB
= '}';
772 // dot_special means '.' only matches '.'
773 if (dot_special
&& *str
== '.' && *pattern
!= *str
)
776 while ((*pattern
!= '\0') && (!done
)
777 && (((*str
=='\0')&&((*pattern
==OB
)||(*pattern
=='*')))||(*str
!='\0'))) {
781 if (*pattern
!= '\0')
788 && (!(ret_code
=wxMatchWild(pattern
, str
++, FALSE
))))
793 while (*pattern
!= '\0')
800 if ((*pattern
== '\0') || (*pattern
== ']')) {
804 if (*pattern
== '\\') {
806 if (*pattern
== '\0') {
811 if (*(pattern
+ 1) == '-') {
814 if (*pattern
== ']') {
818 if (*pattern
== '\\') {
820 if (*pattern
== '\0') {
825 if ((*str
< c
) || (*str
> *pattern
)) {
829 } else if (*pattern
!= *str
) {
834 while ((*pattern
!= ']') && (*pattern
!= '\0')) {
835 if ((*pattern
== '\\') && (*(pattern
+ 1) != '\0'))
839 if (*pattern
!= '\0') {
849 while ((*pattern
!= CB
) && (*pattern
!= '\0')) {
852 while (ok
&& (*cp
!= '\0') && (*pattern
!= '\0')
853 && (*pattern
!= ',') && (*pattern
!= CB
)) {
854 if (*pattern
== '\\')
856 ok
= (*pattern
++ == *cp
++);
858 if (*pattern
== '\0') {
864 while ((*pattern
!= CB
) && (*pattern
!= '\0')) {
865 if (*++pattern
== '\\') {
866 if (*++pattern
== CB
)
871 while (*pattern
!=CB
&& *pattern
!=',' && *pattern
!='\0') {
872 if (*++pattern
== '\\') {
873 if (*++pattern
== CB
|| *pattern
== ',')
878 if (*pattern
!= '\0')
883 if (*str
== *pattern
) {
890 while (*pattern
== '*')
892 return ((*str
== '\0') && (*pattern
== '\0'));