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