]> git.saurik.com Git - wxWidgets.git/blob - src/msw/utils.cpp
wxToolBar API changes; now frames manage their toolbar & statusbar properly;
[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 // Note: this is done in utilscmn.cpp now.
14 // #pragma implementation
15 // #pragma implementation "utils.h"
16 #endif
17
18 // For compilers that support precompilation, includes "wx.h".
19 #include "wx/wxprec.h"
20
21 #ifdef __BORLANDC__
22 #pragma hdrstop
23 #endif
24
25 #ifndef WX_PRECOMP
26 #include "wx/setup.h"
27 #include "wx/utils.h"
28 #include "wx/app.h"
29 #include "wx/cursor.h"
30 #endif
31
32 #include "wx/msw/private.h"
33 #include "wx/timer.h"
34
35 #include <ctype.h>
36
37 #ifndef __GNUWIN32__
38 #include <direct.h>
39 #include <dos.h>
40 #endif
41
42 #ifdef __GNUWIN32__
43 #include <sys/unistd.h>
44 #include <sys/stat.h>
45 #ifndef __MINGW32__
46 #include <std.h>
47 #endif
48
49 #define stricmp strcasecmp
50 #endif
51
52 #ifdef __BORLANDC__ // Please someone tell me which version of Borland needs
53 // this (3.1 I believe) and how to test for it.
54 // If this works for Borland 4.0 as well, then no worries.
55 #include <dir.h>
56 #endif
57
58 #ifdef __WIN32__
59 #include <io.h>
60
61 #ifndef __GNUWIN32__
62 #include <shellapi.h>
63 #endif
64 #endif
65
66 #include <stdio.h>
67 #include <stdlib.h>
68 #include <string.h>
69 #ifndef __WATCOMC__
70 #if !(defined(_MSC_VER) && (_MSC_VER > 800))
71 #include <errno.h>
72 #endif
73 #endif
74 #include <stdarg.h>
75
76 // In the WIN.INI file
77 static const char WX_SECTION[] = "wxWindows";
78 static const char eHOSTNAME[] = "HostName";
79 static const char eUSERID[] = "UserId";
80 static const char eUSERNAME[] = "UserName";
81
82 // For the following functions we SHOULD fill in support
83 // for Windows-NT (which I don't know) as I assume it begin
84 // a POSIX Unix (so claims MS) that it has some special
85 // functions beyond those provided by WinSock
86
87 // Get full hostname (eg. DoDo.BSn-Germany.crg.de)
88 bool wxGetHostName(char *buf, int maxSize)
89 {
90 #ifdef __WIN32__
91 DWORD nSize = maxSize;
92 return (::GetComputerName(buf, &nSize) != 0);
93 #else
94 char *sysname;
95 const char *default_host = "noname";
96
97 if ((sysname = getenv("SYSTEM_NAME")) == NULL) {
98 GetProfileString(WX_SECTION, eHOSTNAME, default_host, buf, maxSize - 1);
99 } else
100 strncpy(buf, sysname, maxSize - 1);
101 buf[maxSize] = '\0';
102 return *buf ? TRUE : FALSE;
103 #endif
104 }
105
106 // Get user ID e.g. jacs
107 bool wxGetUserId(char *buf, int maxSize)
108 {
109 #if defined(__WIN32__) && !defined(__win32s__) && 0
110 // Gets the current user's full name according to the MS article PSS ID
111 // Number: Q119670
112 // Seems to be the same as the login name for me?
113 char *UserName = new char[256];
114 char *Domain = new char[256];
115 DWORD maxCharacters = 255;
116 GetUserName( UserName, &maxCharacters );
117 GetComputerName( Domain, &maxCharacters );
118
119 WCHAR wszUserName[256]; // Unicode user name
120 WCHAR wszDomain[256];
121 LPBYTE ComputerName;
122
123 struct _SERVER_INFO_100 *si100; // Server structure
124 struct _USER_INFO_2 *ui; // User structure
125
126 // Convert ASCII user name and domain to Unicode.
127
128 MultiByteToWideChar( CP_ACP, 0, UserName,
129 strlen(UserName)+1, wszUserName, sizeof(wszUserName) );
130 MultiByteToWideChar( CP_ACP, 0, Domain,
131 strlen(Domain)+1, wszDomain, sizeof(wszDomain) );
132
133 // Get the computer name of a DC for the specified domain.
134 // >If you get a link error on this, include netapi32.lib<
135
136 NetGetDCName( NULL, wszDomain, &ComputerName );
137
138 // Look up the user on the DC.
139
140 if(NetUserGetInfo( (LPWSTR) ComputerName,
141 (LPWSTR) &wszUserName, 2, (LPBYTE *) &ui))
142 {
143 printf( "Error getting user information.\n" );
144 return( FALSE );
145 }
146
147 // Convert the Unicode full name to ASCII.
148
149 WideCharToMultiByte( CP_ACP, 0, ui->usri2_full_name,
150 -1, buf, 256, NULL, NULL );
151 }
152 return( TRUE );
153 /*
154 DWORD nSize = maxSize;
155 return ::GetUserName(buf, &nSize);
156 */
157 #else
158 char *user;
159 const char *default_id = "anonymous";
160
161 // Can't assume we have NIS (PC-NFS) or some other ID daemon
162 // So we ...
163 if ( (user = getenv("USER")) == NULL &&
164 (user = getenv("LOGNAME")) == NULL ) {
165 // Use wxWindows configuration data (comming soon)
166 GetProfileString(WX_SECTION, eUSERID, default_id, buf, maxSize - 1);
167 } else
168 strncpy(buf, user, maxSize - 1);
169 return *buf ? TRUE : FALSE;
170 #endif
171 }
172
173 // Get user name e.g. Julian Smart
174 bool wxGetUserName(char *buf, int maxSize)
175 {
176 const char *default_name = "Unknown User";
177 #if defined(__WIN32__)
178 /*
179 DWORD nSize = maxSize;
180 In VC++ 4.0, results in unresolved symbol __imp__GetUserNameA
181 if (GetUserName(buf, &nSize))
182 return TRUE;
183 else
184 */
185 // Could use NIS, MS-Mail or other site specific programs
186 // Use wxWindows configuration data
187 GetProfileString(WX_SECTION, eUSERNAME, default_name, buf, maxSize - 1);
188 return *buf ? TRUE : FALSE;
189 // }
190 #else
191 #if !defined(__WATCOMC__) && !defined(__GNUWIN32__) && USE_PENWINDOWS
192 extern HANDLE g_hPenWin; // PenWindows Running?
193 if (g_hPenWin)
194 {
195 // PenWindows Does have a user concept!
196 // Get the current owner of the recognizer
197 GetPrivateProfileString("Current", "User", default_name, wxBuffer, maxSize - 1, "PENWIN.INI");
198 strncpy(buf, wxBuffer, maxSize - 1);
199 }
200 else
201 #endif
202 {
203 // Could use NIS, MS-Mail or other site specific programs
204 // Use wxWindows configuration data
205 GetProfileString(WX_SECTION, eUSERNAME, default_name, buf, maxSize - 1);
206 }
207 return *buf ? TRUE : FALSE;
208 #endif
209 }
210
211 int wxKill(long pid, int sig)
212 {
213 return 0;
214 }
215
216 //
217 // Execute a program in an Interactive Shell
218 //
219 bool
220 wxShell(const wxString& command)
221 {
222 char *shell;
223 if ((shell = getenv("COMSPEC")) == NULL)
224 shell = "\\COMMAND.COM";
225
226 char tmp[255];
227 if (command != "")
228 sprintf(tmp, "%s /c %s", shell, WXSTRINGCAST command);
229 else
230 strcpy(tmp, shell);
231
232 return (wxExecute((char *)tmp, FALSE) != 0);
233 }
234
235 // Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX)
236 long wxGetFreeMemory(void)
237 {
238 #if defined(__WIN32__) && !defined(__BORLANDC__)
239 MEMORYSTATUS memStatus;
240 memStatus.dwLength = sizeof(MEMORYSTATUS);
241 GlobalMemoryStatus(&memStatus);
242 return memStatus.dwAvailPhys;
243 #else
244 return (long)GetFreeSpace(0);
245 #endif
246 }
247
248 // Sleep for nSecs seconds. Attempt a Windows implementation using timers.
249 static bool inTimer = FALSE;
250 class wxSleepTimer: public wxTimer
251 {
252 public:
253 inline void Notify(void)
254 {
255 inTimer = FALSE;
256 Stop();
257 }
258 };
259
260 static wxTimer *wxTheSleepTimer = NULL;
261
262 void wxSleep(int nSecs)
263 {
264 #if 0 // WIN32 hangs app
265 Sleep( 1000*nSecs );
266 #else
267 if (inTimer)
268 return;
269
270 wxTheSleepTimer = new wxSleepTimer;
271 inTimer = TRUE;
272 wxTheSleepTimer->Start(nSecs*1000);
273 while (inTimer)
274 {
275 if (wxTheApp->Pending())
276 wxTheApp->Dispatch();
277 }
278 delete wxTheSleepTimer;
279 wxTheSleepTimer = NULL;
280 #endif
281 }
282
283 // Consume all events until no more left
284 void wxFlushEvents(void)
285 {
286 // wxYield();
287 }
288
289 // Output a debug mess., in a system dependent fashion.
290 void wxDebugMsg(const char *fmt ...)
291 {
292 va_list ap;
293 static char buffer[512];
294
295 if (!wxTheApp->GetWantDebugOutput())
296 return ;
297
298 va_start(ap, fmt);
299
300 wvsprintf(buffer,fmt,ap) ;
301 OutputDebugString((LPCSTR)buffer) ;
302
303 va_end(ap);
304 }
305
306 // Non-fatal error: pop up message box and (possibly) continue
307 void wxError(const wxString& msg, const wxString& title)
308 {
309 sprintf(wxBuffer, "%s\nContinue?", WXSTRINGCAST msg);
310 if (MessageBox(NULL, (LPCSTR)wxBuffer, (LPCSTR)WXSTRINGCAST title,
311 MB_ICONSTOP | MB_YESNO) == IDNO)
312 wxExit();
313 }
314
315 // Fatal error: pop up message box and abort
316 void wxFatalError(const wxString& msg, const wxString& title)
317 {
318 sprintf(wxBuffer, "%s: %s", WXSTRINGCAST title, WXSTRINGCAST msg);
319 FatalAppExit(0, (LPCSTR)wxBuffer);
320 }
321
322 // Emit a beeeeeep
323 void wxBell(void)
324 {
325 #ifdef __WIN32__
326 Beep(1000,1000) ; // 1kHz during 1 sec.
327 #else
328 MessageBeep(-1) ;
329 #endif
330 }
331
332 // Chris Breeze 27/5/98: revised WIN32 code to
333 // detect WindowsNT correctly
334 int wxGetOsVersion(int *majorVsn, int *minorVsn)
335 {
336 extern char *wxOsVersion;
337 if (majorVsn) *majorVsn = 0;
338 if (minorVsn) *minorVsn = 0;
339
340 #ifdef WIN32
341 OSVERSIONINFO info;
342 memset(&info, 0, sizeof(OSVERSIONINFO));
343 info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
344 if (GetVersionEx(&info))
345 {
346 if (majorVsn) *majorVsn = info.dwMajorVersion;
347 if (minorVsn) *minorVsn = info.dwMinorVersion;
348 switch (info.dwPlatformId)
349 {
350 case VER_PLATFORM_WIN32s:
351 return wxWIN32S;
352 break;
353 case VER_PLATFORM_WIN32_WINDOWS:
354 return wxWIN95;
355 break;
356 case VER_PLATFORM_WIN32_NT:
357 return wxWINDOWS_NT;
358 break;
359 }
360 }
361 return wxWINDOWS; // error if we get here, return generic value
362 #else
363 // Win16 code...
364 int retValue ;
365 # ifdef __WINDOWS_386__
366 retValue = wxWIN386;
367 # else
368 # if !defined(__WATCOMC__) && !defined(GNUWIN32) && USE_PENWINDOWS
369 extern HANDLE g_hPenWin;
370 retValue = g_hPenWin ? wxPENWINDOWS : wxWINDOWS ;
371 # endif
372 # endif
373 // @@@@ To be completed. I don't have the manual here...
374 if (majorVsn) *majorVsn = 3 ;
375 if (minorVsn) *minorVsn = 1 ;
376 return retValue ;
377 #endif
378 }
379
380 // Reading and writing resources (eg WIN.INI, .Xdefaults)
381 #if USE_RESOURCES
382 bool wxWriteResource(const wxString& section, const wxString& entry, const wxString& value, const wxString& file)
383 {
384 if (file != "")
385 return (WritePrivateProfileString((LPCSTR)WXSTRINGCAST section, (LPCSTR)WXSTRINGCAST entry, (LPCSTR)value, (LPCSTR)WXSTRINGCAST file) != 0);
386 else
387 return (WriteProfileString((LPCSTR)WXSTRINGCAST section, (LPCSTR)WXSTRINGCAST entry, (LPCSTR)WXSTRINGCAST value) != 0);
388 }
389
390 bool wxWriteResource(const wxString& section, const wxString& entry, float value, const wxString& file)
391 {
392 char buf[50];
393 sprintf(buf, "%.4f", value);
394 return wxWriteResource(section, entry, buf, file);
395 }
396
397 bool wxWriteResource(const wxString& section, const wxString& entry, long value, const wxString& file)
398 {
399 char buf[50];
400 sprintf(buf, "%ld", value);
401 return wxWriteResource(section, entry, buf, file);
402 }
403
404 bool wxWriteResource(const wxString& section, const wxString& entry, int value, const wxString& file)
405 {
406 char buf[50];
407 sprintf(buf, "%d", value);
408 return wxWriteResource(section, entry, buf, file);
409 }
410
411 bool wxGetResource(const wxString& section, const wxString& entry, char **value, const wxString& file)
412 {
413 static const char defunkt[] = "$$default";
414 if (file != "")
415 {
416 int n = GetPrivateProfileString((LPCSTR)WXSTRINGCAST section, (LPCSTR)WXSTRINGCAST entry, (LPCSTR)defunkt,
417 (LPSTR)wxBuffer, 1000, (LPCSTR)WXSTRINGCAST file);
418 if (n == 0 || strcmp(wxBuffer, defunkt) == 0)
419 return FALSE;
420 }
421 else
422 {
423 int n = GetProfileString((LPCSTR)WXSTRINGCAST section, (LPCSTR)WXSTRINGCAST entry, (LPCSTR)defunkt,
424 (LPSTR)wxBuffer, 1000);
425 if (n == 0 || strcmp(wxBuffer, defunkt) == 0)
426 return FALSE;
427 }
428 if (*value) delete[] (*value);
429 *value = copystring(wxBuffer);
430 return TRUE;
431 }
432
433 bool wxGetResource(const wxString& section, const wxString& entry, float *value, const wxString& file)
434 {
435 char *s = NULL;
436 bool succ = wxGetResource(section, entry, (char **)&s, file);
437 if (succ)
438 {
439 *value = (float)strtod(s, NULL);
440 delete[] s;
441 return TRUE;
442 }
443 else return FALSE;
444 }
445
446 bool wxGetResource(const wxString& section, const wxString& entry, long *value, const wxString& file)
447 {
448 char *s = NULL;
449 bool succ = wxGetResource(section, entry, (char **)&s, file);
450 if (succ)
451 {
452 *value = strtol(s, NULL, 10);
453 delete[] s;
454 return TRUE;
455 }
456 else return FALSE;
457 }
458
459 bool wxGetResource(const wxString& section, const wxString& entry, int *value, const wxString& file)
460 {
461 char *s = NULL;
462 bool succ = wxGetResource(section, entry, (char **)&s, file);
463 if (succ)
464 {
465 *value = (int)strtol(s, NULL, 10);
466 delete[] s;
467 return TRUE;
468 }
469 else return FALSE;
470 }
471 #endif // USE_RESOURCES
472
473 // Old cursor
474 static HCURSOR wxBusyCursorOld = 0;
475 static int wxBusyCursorCount = 0;
476
477 // Set the cursor to the busy cursor for all windows
478 void wxBeginBusyCursor(wxCursor *cursor)
479 {
480 wxBusyCursorCount ++;
481 if (wxBusyCursorCount == 1)
482 {
483 wxBusyCursorOld = ::SetCursor((HCURSOR) cursor->GetHCURSOR());
484 }
485 else
486 {
487 (void)::SetCursor((HCURSOR) cursor->GetHCURSOR());
488 }
489 }
490
491 // Restore cursor to normal
492 void wxEndBusyCursor(void)
493 {
494 if (wxBusyCursorCount == 0)
495 return;
496
497 wxBusyCursorCount --;
498 if (wxBusyCursorCount == 0)
499 {
500 ::SetCursor(wxBusyCursorOld);
501 wxBusyCursorOld = 0;
502 }
503 }
504
505 // TRUE if we're between the above two calls
506 bool wxIsBusy(void)
507 {
508 return (wxBusyCursorCount > 0);
509 }
510
511 // Hack for MS-DOS
512 char *wxGetUserHome (const wxString& user)
513 {
514 char *home;
515 wxString user1(user);
516
517 if (user1 != "") {
518 char tmp[64];
519 if (wxGetUserId(tmp, sizeof(tmp)/sizeof(char))) {
520 // Guests belong in the temp dir
521 if (stricmp(tmp, "annonymous") == 0) {
522 if ((home = getenv("TMP")) != NULL ||
523 (home = getenv("TMPDIR")) != NULL ||
524 (home = getenv("TEMP")) != NULL)
525 return *home ? home : "\\";
526 }
527 if (stricmp(tmp, WXSTRINGCAST user1) == 0)
528 user1 = "";
529 }
530 }
531 if (user1 == "")
532 if ((home = getenv("HOME")) != NULL)
533 {
534 strcpy(wxBuffer, home);
535 Unix2DosFilename(wxBuffer);
536 return wxBuffer;
537 }
538 return NULL; // No home known!
539 }
540
541 // Check whether this window wants to process messages, e.g. Stop button
542 // in long calculations.
543 bool wxCheckForInterrupt(wxWindow *wnd)
544 {
545 if(wnd){
546 MSG msg;
547 HWND win= (HWND) wnd->GetHWND();
548 while(PeekMessage(&msg,win,0,0,PM_REMOVE)){
549 TranslateMessage(&msg);
550 DispatchMessage(&msg);
551 }
552 return TRUE;//*** temporary?
553 }
554 else{
555 wxError("wnd==NULL !!!");
556 return FALSE;//*** temporary?
557 }
558 }
559
560 // MSW only: get user-defined resource from the .res file.
561 // Returns NULL or newly-allocated memory, so use delete[] to clean up.
562
563 #ifdef __WXMSW__
564 char *wxLoadUserResource(const wxString& resourceName, const wxString& resourceType)
565 {
566 char *s = NULL;
567 #ifndef __WIN32__
568 HRSRC hResource = ::FindResource(wxGetInstance(), WXSTRINGCAST resourceName, WXSTRINGCAST resourceType);
569 #else
570 #ifdef UNICODE
571 HRSRC hResource = ::FindResourceW(wxGetInstance(), WXSTRINGCAST resourceName, WXSTRINGCAST resourceType);
572 #else
573 HRSRC hResource = ::FindResourceA(wxGetInstance(), WXSTRINGCAST resourceName, WXSTRINGCAST resourceType);
574 #endif
575 #endif
576
577 if (hResource == 0)
578 return NULL;
579 HGLOBAL hData = ::LoadResource(wxGetInstance(), hResource);
580 if (hData == 0)
581 return NULL;
582 char *theText = (char *)LockResource(hData);
583 if (!theText)
584 return NULL;
585
586 s = copystring(theText);
587
588 // Obsolete in WIN32
589 #ifndef __WIN32__
590 UnlockResource(hData);
591 #endif
592
593 // No need??
594 // GlobalFree(hData);
595
596 return s;
597 }
598 #endif
599
600 void wxGetMousePosition( int* x, int* y )
601 {
602 POINT pt;
603 GetCursorPos( & pt );
604 *x = pt.x;
605 *y = pt.y;
606 };
607
608 // Return TRUE if we have a colour display
609 bool wxColourDisplay(void)
610 {
611 HDC dc = ::GetDC(NULL);
612 bool flag;
613 int noCols = GetDeviceCaps(dc, NUMCOLORS);
614 if ((noCols == -1) || (noCols > 2))
615 flag = TRUE;
616 else
617 flag = FALSE;
618 ReleaseDC(NULL, dc);
619 return flag;
620 }
621
622 // Returns depth of screen
623 int wxDisplayDepth(void)
624 {
625 HDC dc = ::GetDC(NULL);
626 int planes = GetDeviceCaps(dc, PLANES);
627 int bitsPerPixel = GetDeviceCaps(dc, BITSPIXEL);
628 int depth = planes*bitsPerPixel;
629 ReleaseDC(NULL, dc);
630 return depth;
631 }
632
633 // Get size of display
634 void wxDisplaySize(int *width, int *height)
635 {
636 HDC dc = ::GetDC(NULL);
637 *width = GetDeviceCaps(dc, HORZRES); *height = GetDeviceCaps(dc, VERTRES);
638 ReleaseDC(NULL, dc);
639 }
640