]> git.saurik.com Git - wxWidgets.git/blame - src/msw/utils.cpp
the modal dialogs restore the focus to the control which had it before the
[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
9// Licence: wxWindows license
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
3e1a3a40
JS
13// Note: this is done in utilscmn.cpp now.
14// #pragma implementation
15// #pragma implementation "utils.h"
2bda0e17
KB
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
77static const char WX_SECTION[] = "wxWindows";
78static const char eHOSTNAME[] = "HostName";
79static const char eUSERID[] = "UserId";
80static const char eUSERNAME[] = "UserName";
81
2bda0e17
KB
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)
88bool 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
107bool 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
174bool 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
81d66cf3
JS
192 extern HANDLE g_hPenWin; // PenWindows Running?
193 if (g_hPenWin)
2bda0e17
KB
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
2bda0e17
KB
211int wxKill(long pid, int sig)
212{
213 return 0;
214}
215
216//
217// Execute a program in an Interactive Shell
218//
219bool
220wxShell(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)
236long 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.
249static bool inTimer = FALSE;
250class wxSleepTimer: public wxTimer
251{
252 public:
253 inline void Notify(void)
254 {
255 inTimer = FALSE;
256 Stop();
257 }
258};
259
260static wxTimer *wxTheSleepTimer = NULL;
261
262void 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
284void wxFlushEvents(void)
285{
286// wxYield();
287}
288
289// Output a debug mess., in a system dependent fashion.
290void 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
307void 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
316void 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
323void wxBell(void)
324{
325#ifdef __WIN32__
326 Beep(1000,1000) ; // 1kHz during 1 sec.
327#else
328 MessageBeep(-1) ;
329#endif
330}
331
6f65e337
JS
332// Chris Breeze 27/5/98: revised WIN32 code to
333// detect WindowsNT correctly
2bda0e17
KB
334int wxGetOsVersion(int *majorVsn, int *minorVsn)
335{
336 extern char *wxOsVersion;
6f65e337
JS
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...
2bda0e17 364 int retValue ;
6f65e337 365# ifdef __WINDOWS_386__
2bda0e17 366 retValue = wxWIN386;
6f65e337 367# else
81d66cf3
JS
368# if !defined(__WATCOMC__) && !defined(GNUWIN32) && USE_PENWINDOWS
369 extern HANDLE g_hPenWin;
370 retValue = g_hPenWin ? wxPENWINDOWS : wxWINDOWS ;
6f65e337
JS
371# endif
372# endif
2bda0e17
KB
373 // @@@@ To be completed. I don't have the manual here...
374 if (majorVsn) *majorVsn = 3 ;
375 if (minorVsn) *minorVsn = 1 ;
376 return retValue ;
6f65e337 377#endif
2bda0e17
KB
378}
379
380// Reading and writing resources (eg WIN.INI, .Xdefaults)
381#if USE_RESOURCES
382bool 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
390bool 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
397bool 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
404bool 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
411bool 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
433bool 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
446bool 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
459bool 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
474static HCURSOR wxBusyCursorOld = 0;
475static int wxBusyCursorCount = 0;
476
477// Set the cursor to the busy cursor for all windows
478void 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
492void 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
506bool wxIsBusy(void)
507{
508 return (wxBusyCursorCount > 0);
509}
510
511// Hack for MS-DOS
512char *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.
543bool 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
2049ba38 563#ifdef __WXMSW__
2bda0e17
KB
564char *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
600void 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
609bool 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
623int 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
634void 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