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