]> git.saurik.com Git - wxWidgets.git/blame - src/msw/utils.cpp
1. DoSetSize() simplified, DoGetBestSize() introduced
[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
743e0a66 9// Licence: wxWindows license
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
a3b46648 13// #pragma implementation "utils.h" // Note: this is done in utilscmn.cpp now.
2bda0e17
KB
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
a4f96412 20 #pragma hdrstop
2bda0e17
KB
21#endif
22
23#ifndef WX_PRECOMP
a4f96412
VZ
24 #include "wx/setup.h"
25 #include "wx/utils.h"
26 #include "wx/app.h"
27 #include "wx/cursor.h"
743e0a66 28#endif //WX_PRECOMP
2bda0e17
KB
29
30#include "wx/msw/private.h"
31#include "wx/timer.h"
57c208c5 32#include "wx/intl.h"
2bda0e17 33
c030b70f
JS
34#include <windows.h>
35
2bda0e17
KB
36#include <ctype.h>
37
5ea105e0 38#if !defined(__GNUWIN32__) && !defined(__WXWINE__) && !defined(__SALFORDC__)
a4f96412 39 #include <direct.h>
ce3ed50d 40
a4f96412
VZ
41 #ifndef __MWERKS__
42 #include <dos.h>
43 #endif
743e0a66 44#endif //GNUWIN32
2bda0e17 45
57c208c5 46#if defined(__GNUWIN32__) && !defined(__TWIN32__)
a4f96412
VZ
47 #include <sys/unistd.h>
48 #include <sys/stat.h>
743e0a66
VZ
49#endif //GNUWIN32
50
51#include "wx/log.h"
2bda0e17
KB
52
53#ifdef __BORLANDC__ // Please someone tell me which version of Borland needs
54 // this (3.1 I believe) and how to test for it.
55 // If this works for Borland 4.0 as well, then no worries.
a4f96412 56 #include <dir.h>
2bda0e17
KB
57#endif
58
a4f96412
VZ
59// VZ: there is some code using NetXXX() functions to get the full user name:
60// I don't think it's a good idea because they don't work under Win95 and
61// seem to return the same as wxGetUserId() under NT. If you really want
62// to use them, just #define USE_NET_API
63#undef USE_NET_API
64
65#ifdef USE_NET_API
66 #include <lm.h>
67#endif // USE_NET_API
68
5ea105e0 69#if defined(__WIN32__) && !defined(__WXWINE__)
a4f96412 70 #include <io.h>
2bda0e17 71
a4f96412
VZ
72 #ifndef __GNUWIN32__
73 #include <shellapi.h>
74 #endif
2bda0e17
KB
75#endif
76
77#include <stdio.h>
78#include <stdlib.h>
79#include <string.h>
80#ifndef __WATCOMC__
3f4a0c5b
VZ
81 #if !(defined(_MSC_VER) && (_MSC_VER > 800))
82 #include <errno.h>
83 #endif
2bda0e17
KB
84#endif
85#include <stdarg.h>
86
c030b70f 87//// BEGIN for console support: VC++ only
631f1bfe 88#ifdef __VISUALC__
c030b70f 89
3f4a0c5b 90#include "wx/msw/msvcrt.h"
c030b70f 91
3f4a0c5b 92#include <fcntl.h>
c030b70f 93
3f4a0c5b 94#include "wx/ioswrap.h"
c030b70f
JS
95
96#if wxUSE_IOSTREAMH
97// N.B. BC++ doesn't have istream.h, ostream.h
c030b70f
JS
98# include <io.h>
99# include <fstream.h>
c030b70f 100#else
c030b70f 101# include <fstream>
c030b70f
JS
102#endif
103
104/* Need to undef new if including crtdbg.h */
105# ifdef new
106# undef new
107# endif
108
1e6d9499 109#ifndef __WIN16__
c030b70f 110# include <crtdbg.h>
1e6d9499 111#endif
c030b70f
JS
112
113# if defined(__WXDEBUG__) && wxUSE_GLOBAL_MEMORY_OPERATORS && wxUSE_DEBUG_NEW_ALWAYS
114# define new new(__FILE__,__LINE__)
115# endif
116
631f1bfe
JS
117#endif
118 // __VISUALC__
c030b70f
JS
119/// END for console support
120
2bda0e17 121// In the WIN.INI file
837e5743
OK
122static const wxChar WX_SECTION[] = _T("wxWindows");
123static const wxChar eHOSTNAME[] = _T("HostName");
124static const wxChar eUSERID[] = _T("UserId");
125static const wxChar eUSERNAME[] = _T("UserName");
2bda0e17 126
2bda0e17
KB
127// For the following functions we SHOULD fill in support
128// for Windows-NT (which I don't know) as I assume it begin
129// a POSIX Unix (so claims MS) that it has some special
130// functions beyond those provided by WinSock
131
132// Get full hostname (eg. DoDo.BSn-Germany.crg.de)
837e5743 133bool wxGetHostName(wxChar *buf, int maxSize)
2bda0e17 134{
57c208c5 135#if defined(__WIN32__) && !defined(__TWIN32__)
2bda0e17
KB
136 DWORD nSize = maxSize;
137 return (::GetComputerName(buf, &nSize) != 0);
138#else
837e5743
OK
139 wxChar *sysname;
140 const wxChar *default_host = _T("noname");
2bda0e17 141
837e5743 142 if ((sysname = wxGetenv(_T("SYSTEM_NAME"))) == NULL) {
2bda0e17
KB
143 GetProfileString(WX_SECTION, eHOSTNAME, default_host, buf, maxSize - 1);
144 } else
837e5743
OK
145 wxStrncpy(buf, sysname, maxSize - 1);
146 buf[maxSize] = _T('\0');
2bda0e17
KB
147 return *buf ? TRUE : FALSE;
148#endif
149}
150
151// Get user ID e.g. jacs
837e5743 152bool wxGetUserId(wxChar *buf, int maxSize)
2bda0e17 153{
57c208c5 154#if defined(__WIN32__) && !defined(__win32s__) && !defined(__TWIN32__)
0a144271
VZ
155 DWORD nSize = maxSize;
156 if ( ::GetUserName(buf, &nSize) == 0 )
157 {
a4f96412
VZ
158 // actually, it does happen on Win9x if the user didn't log on
159 DWORD res = ::GetEnvironmentVariable("username", buf, maxSize);
160 if ( res == 0 )
161 {
162 // not found
163 return FALSE;
164 }
0a144271
VZ
165 }
166
167 return TRUE;
0a144271 168#else // Win16 or Win32s
837e5743
OK
169 wxChar *user;
170 const wxChar *default_id = _T("anonymous");
2bda0e17
KB
171
172 // Can't assume we have NIS (PC-NFS) or some other ID daemon
173 // So we ...
837e5743 174 if ( (user = wxGetenv(_T("USER"))) == NULL &&
a4f96412
VZ
175 (user = wxGetenv(_T("LOGNAME"))) == NULL )
176 {
2bda0e17
KB
177 // Use wxWindows configuration data (comming soon)
178 GetProfileString(WX_SECTION, eUSERID, default_id, buf, maxSize - 1);
a4f96412
VZ
179 }
180 else
181 {
837e5743 182 wxStrncpy(buf, user, maxSize - 1);
a4f96412
VZ
183 }
184
2bda0e17
KB
185 return *buf ? TRUE : FALSE;
186#endif
187}
188
189// Get user name e.g. Julian Smart
837e5743 190bool wxGetUserName(wxChar *buf, int maxSize)
2bda0e17 191{
0a144271 192#if wxUSE_PENWINDOWS && !defined(__WATCOMC__) && !defined(__GNUWIN32__)
81d66cf3
JS
193 extern HANDLE g_hPenWin; // PenWindows Running?
194 if (g_hPenWin)
2bda0e17
KB
195 {
196 // PenWindows Does have a user concept!
197 // Get the current owner of the recognizer
198 GetPrivateProfileString("Current", "User", default_name, wxBuffer, maxSize - 1, "PENWIN.INI");
199 strncpy(buf, wxBuffer, maxSize - 1);
200 }
201 else
202#endif
203 {
a4f96412
VZ
204#ifdef USE_NET_API
205 CHAR szUserName[256];
206 if ( !wxGetUserId(szUserName, WXSIZEOF(szUserName)) )
207 return FALSE;
208
209 // TODO how to get the domain name?
210 CHAR *szDomain = "";
211
212 // the code is based on the MSDN example (also see KB article Q119670)
213 WCHAR wszUserName[256]; // Unicode user name
214 WCHAR wszDomain[256];
215 LPBYTE ComputerName;
216
217 USER_INFO_2 *ui2; // User structure
218
219 // Convert ANSI user name and domain to Unicode
220 MultiByteToWideChar( CP_ACP, 0, szUserName, strlen(szUserName)+1,
221 wszUserName, WXSIZEOF(wszUserName) );
222 MultiByteToWideChar( CP_ACP, 0, szDomain, strlen(szDomain)+1,
223 wszDomain, WXSIZEOF(wszDomain) );
224
225 // Get the computer name of a DC for the domain.
226 if ( NetGetDCName( NULL, wszDomain, &ComputerName ) != NERR_Success )
227 {
228 wxLogError(_T("Can not find domain controller"));
229
230 goto error;
231 }
232
233 // Look up the user on the DC
234 NET_API_STATUS status = NetUserGetInfo( (LPWSTR)ComputerName,
235 (LPWSTR)&wszUserName,
236 2, // level - we want USER_INFO_2
237 (LPBYTE *) &ui2 );
238 switch ( status )
239 {
240 case NERR_Success:
241 // ok
242 break;
243
244 case NERR_InvalidComputer:
245 wxLogError(_T("Invalid domain controller name."));
246
247 goto error;
248
249 case NERR_UserNotFound:
250 wxLogError(_T("Invalid user name '%s'."), szUserName);
251
252 goto error;
253
254 default:
255 wxLogSysError(_T("Can't get information about user"));
256
257 goto error;
258 }
259
260 // Convert the Unicode full name to ANSI
261 WideCharToMultiByte( CP_ACP, 0, ui2->usri2_full_name, -1,
262 buf, maxSize, NULL, NULL );
263
264 return TRUE;
265
266error:
267 wxLogError(_T("Couldn't look up full user name."));
268
269 return FALSE;
270#else // !USE_NET_API
2bda0e17 271 // Could use NIS, MS-Mail or other site specific programs
b07135ba 272 // Use wxWindows configuration data
837e5743 273 bool ok = GetProfileString(WX_SECTION, eUSERNAME, _T(""), buf, maxSize - 1) != 0;
0a144271
VZ
274 if ( !ok )
275 {
276 ok = wxGetUserId(buf, maxSize);
277 }
278
279 if ( !ok )
280 {
837e5743 281 wxStrncpy(buf, _T("Unknown User"), maxSize);
0a144271 282 }
a4f96412 283#endif // Win32/16
2bda0e17 284 }
0a144271
VZ
285
286 return TRUE;
2bda0e17
KB
287}
288
2bda0e17
KB
289int wxKill(long pid, int sig)
290{
291 return 0;
292}
293
294//
295// Execute a program in an Interactive Shell
296//
297bool
298wxShell(const wxString& command)
299{
837e5743
OK
300 wxChar *shell;
301 if ((shell = wxGetenv(_T("COMSPEC"))) == NULL)
302 shell = _T("\\COMMAND.COM");
2bda0e17 303
837e5743
OK
304 wxChar tmp[255];
305 if (command != _T(""))
306 wxSprintf(tmp, _T("%s /c %s"), shell, WXSTRINGCAST command);
2bda0e17 307 else
837e5743 308 wxStrcpy(tmp, shell);
2bda0e17 309
837e5743 310 return (wxExecute((wxChar *)tmp, FALSE) != 0);
2bda0e17
KB
311}
312
313// Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX)
634903fd 314long wxGetFreeMemory()
2bda0e17 315{
57c208c5 316#if defined(__WIN32__) && !defined(__BORLANDC__) && !defined(__TWIN32__)
2bda0e17
KB
317 MEMORYSTATUS memStatus;
318 memStatus.dwLength = sizeof(MEMORYSTATUS);
319 GlobalMemoryStatus(&memStatus);
320 return memStatus.dwAvailPhys;
321#else
322 return (long)GetFreeSpace(0);
323#endif
324}
325
326// Sleep for nSecs seconds. Attempt a Windows implementation using timers.
327static bool inTimer = FALSE;
328class wxSleepTimer: public wxTimer
329{
330 public:
634903fd 331 inline void Notify()
2bda0e17
KB
332 {
333 inTimer = FALSE;
334 Stop();
335 }
336};
337
338static wxTimer *wxTheSleepTimer = NULL;
339
afb74891
VZ
340void wxUsleep(unsigned long milliseconds)
341{
58a33cb4 342#ifdef __WIN32__
afb74891 343 ::Sleep(milliseconds);
58a33cb4
JS
344#else
345 if (inTimer)
346 return;
347
348 wxTheSleepTimer = new wxSleepTimer;
349 inTimer = TRUE;
350 wxTheSleepTimer->Start(milliseconds);
351 while (inTimer)
352 {
353 if (wxTheApp->Pending())
354 wxTheApp->Dispatch();
355 }
356 delete wxTheSleepTimer;
357 wxTheSleepTimer = NULL;
358#endif
afb74891
VZ
359}
360
2bda0e17
KB
361void wxSleep(int nSecs)
362{
363#if 0 // WIN32 hangs app
364 Sleep( 1000*nSecs );
365#else
366 if (inTimer)
367 return;
368
369 wxTheSleepTimer = new wxSleepTimer;
370 inTimer = TRUE;
371 wxTheSleepTimer->Start(nSecs*1000);
372 while (inTimer)
373 {
374 if (wxTheApp->Pending())
375 wxTheApp->Dispatch();
376 }
377 delete wxTheSleepTimer;
378 wxTheSleepTimer = NULL;
379#endif
380}
381
382// Consume all events until no more left
634903fd 383void wxFlushEvents()
2bda0e17
KB
384{
385// wxYield();
386}
387
388// Output a debug mess., in a system dependent fashion.
837e5743 389void wxDebugMsg(const wxChar *fmt ...)
2bda0e17
KB
390{
391 va_list ap;
837e5743 392 static wxChar buffer[512];
2bda0e17
KB
393
394 if (!wxTheApp->GetWantDebugOutput())
395 return ;
396
397 va_start(ap, fmt);
398
399 wvsprintf(buffer,fmt,ap) ;
837e5743 400 OutputDebugString((LPCTSTR)buffer) ;
2bda0e17
KB
401
402 va_end(ap);
403}
404
405// Non-fatal error: pop up message box and (possibly) continue
406void wxError(const wxString& msg, const wxString& title)
407{
837e5743
OK
408 wxSprintf(wxBuffer, _T("%s\nContinue?"), WXSTRINGCAST msg);
409 if (MessageBox(NULL, (LPCTSTR)wxBuffer, (LPCTSTR)WXSTRINGCAST title,
2bda0e17
KB
410 MB_ICONSTOP | MB_YESNO) == IDNO)
411 wxExit();
412}
413
414// Fatal error: pop up message box and abort
415void wxFatalError(const wxString& msg, const wxString& title)
416{
837e5743
OK
417 wxSprintf(wxBuffer, _T("%s: %s"), WXSTRINGCAST title, WXSTRINGCAST msg);
418 FatalAppExit(0, (LPCTSTR)wxBuffer);
2bda0e17
KB
419}
420
421// Emit a beeeeeep
634903fd 422void wxBell()
2bda0e17 423{
b07135ba
RD
424 // Removed by RD because IHMO syncronous sound is a Bad Thing. MessageBeep
425 // will do a similar thing anyway if there is no sound card...
426//#ifdef __WIN32__
427// Beep(1000,1000) ; // 1kHz during 1 sec.
428//#else
ce200637 429 MessageBeep((UINT)-1) ;
b07135ba 430//#endif
2bda0e17
KB
431}
432
6f65e337
JS
433// Chris Breeze 27/5/98: revised WIN32 code to
434// detect WindowsNT correctly
2bda0e17
KB
435int wxGetOsVersion(int *majorVsn, int *minorVsn)
436{
437 extern char *wxOsVersion;
6f65e337
JS
438 if (majorVsn) *majorVsn = 0;
439 if (minorVsn) *minorVsn = 0;
440
2432b92d 441#if defined(__WIN32__) && !defined(__SC__)
6f65e337
JS
442 OSVERSIONINFO info;
443 memset(&info, 0, sizeof(OSVERSIONINFO));
444 info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
445 if (GetVersionEx(&info))
446 {
447 if (majorVsn) *majorVsn = info.dwMajorVersion;
448 if (minorVsn) *minorVsn = info.dwMinorVersion;
449 switch (info.dwPlatformId)
743e0a66
VZ
450 {
451 case VER_PLATFORM_WIN32s:
452 return wxWIN32S;
453 break;
454 case VER_PLATFORM_WIN32_WINDOWS:
455 return wxWIN95;
456 break;
457 case VER_PLATFORM_WIN32_NT:
458 return wxWINDOWS_NT;
459 break;
6f65e337 460 }
743e0a66
VZ
461 }
462 return wxWINDOWS; // error if we get here, return generic value
6f65e337
JS
463#else
464 // Win16 code...
2432b92d 465 int retValue = 0;
6f65e337 466# ifdef __WINDOWS_386__
2bda0e17 467 retValue = wxWIN386;
6f65e337 468# else
47d67540 469# if !defined(__WATCOMC__) && !defined(GNUWIN32) && wxUSE_PENWINDOWS
81d66cf3
JS
470 extern HANDLE g_hPenWin;
471 retValue = g_hPenWin ? wxPENWINDOWS : wxWINDOWS ;
6f65e337
JS
472# endif
473# endif
2bda0e17
KB
474 // @@@@ To be completed. I don't have the manual here...
475 if (majorVsn) *majorVsn = 3 ;
476 if (minorVsn) *minorVsn = 1 ;
477 return retValue ;
6f65e337 478#endif
2bda0e17
KB
479}
480
481// Reading and writing resources (eg WIN.INI, .Xdefaults)
47d67540 482#if wxUSE_RESOURCES
2bda0e17
KB
483bool wxWriteResource(const wxString& section, const wxString& entry, const wxString& value, const wxString& file)
484{
837e5743
OK
485 if (file != _T(""))
486 return (WritePrivateProfileString((LPCTSTR)WXSTRINGCAST section, (LPCTSTR)WXSTRINGCAST entry, (LPCTSTR)value, (LPCTSTR)WXSTRINGCAST file) != 0);
2bda0e17 487 else
837e5743 488 return (WriteProfileString((LPCTSTR)WXSTRINGCAST section, (LPCTSTR)WXSTRINGCAST entry, (LPCTSTR)WXSTRINGCAST value) != 0);
2bda0e17
KB
489}
490
491bool wxWriteResource(const wxString& section, const wxString& entry, float value, const wxString& file)
492{
837e5743
OK
493 wxChar buf[50];
494 wxSprintf(buf, _T("%.4f"), value);
2bda0e17
KB
495 return wxWriteResource(section, entry, buf, file);
496}
497
498bool wxWriteResource(const wxString& section, const wxString& entry, long value, const wxString& file)
499{
837e5743
OK
500 wxChar buf[50];
501 wxSprintf(buf, _T("%ld"), value);
2bda0e17
KB
502 return wxWriteResource(section, entry, buf, file);
503}
504
505bool wxWriteResource(const wxString& section, const wxString& entry, int value, const wxString& file)
506{
837e5743
OK
507 wxChar buf[50];
508 wxSprintf(buf, _T("%d"), value);
2bda0e17
KB
509 return wxWriteResource(section, entry, buf, file);
510}
511
837e5743 512bool wxGetResource(const wxString& section, const wxString& entry, wxChar **value, const wxString& file)
2bda0e17 513{
837e5743
OK
514 static const wxChar defunkt[] = _T("$$default");
515 if (file != _T(""))
2bda0e17 516 {
837e5743
OK
517 int n = GetPrivateProfileString((LPCTSTR)WXSTRINGCAST section, (LPCTSTR)WXSTRINGCAST entry, (LPCTSTR)defunkt,
518 (LPTSTR)wxBuffer, 1000, (LPCTSTR)WXSTRINGCAST file);
519 if (n == 0 || wxStrcmp(wxBuffer, defunkt) == 0)
2bda0e17
KB
520 return FALSE;
521 }
522 else
523 {
837e5743
OK
524 int n = GetProfileString((LPCTSTR)WXSTRINGCAST section, (LPCTSTR)WXSTRINGCAST entry, (LPCTSTR)defunkt,
525 (LPTSTR)wxBuffer, 1000);
526 if (n == 0 || wxStrcmp(wxBuffer, defunkt) == 0)
2bda0e17
KB
527 return FALSE;
528 }
529 if (*value) delete[] (*value);
530 *value = copystring(wxBuffer);
531 return TRUE;
532 }
533
534bool wxGetResource(const wxString& section, const wxString& entry, float *value, const wxString& file)
535{
837e5743
OK
536 wxChar *s = NULL;
537 bool succ = wxGetResource(section, entry, (wxChar **)&s, file);
2bda0e17
KB
538 if (succ)
539 {
837e5743 540 *value = (float)wxStrtod(s, NULL);
2bda0e17
KB
541 delete[] s;
542 return TRUE;
543 }
544 else return FALSE;
545}
546
547bool wxGetResource(const wxString& section, const wxString& entry, long *value, const wxString& file)
548{
837e5743
OK
549 wxChar *s = NULL;
550 bool succ = wxGetResource(section, entry, (wxChar **)&s, file);
2bda0e17
KB
551 if (succ)
552 {
837e5743 553 *value = wxStrtol(s, NULL, 10);
2bda0e17
KB
554 delete[] s;
555 return TRUE;
556 }
557 else return FALSE;
558}
559
560bool wxGetResource(const wxString& section, const wxString& entry, int *value, const wxString& file)
561{
837e5743
OK
562 wxChar *s = NULL;
563 bool succ = wxGetResource(section, entry, (wxChar **)&s, file);
2bda0e17
KB
564 if (succ)
565 {
837e5743 566 *value = (int)wxStrtol(s, NULL, 10);
b07135ba 567 delete[] s;
2bda0e17
KB
568 return TRUE;
569 }
570 else return FALSE;
571}
47d67540 572#endif // wxUSE_RESOURCES
2bda0e17 573
634903fd 574// ---------------------------------------------------------------------------
25889d3c 575// helper functions for showing a "busy" cursor
634903fd
VZ
576// ---------------------------------------------------------------------------
577
25889d3c
JS
578HCURSOR gs_wxBusyCursor = 0; // new, busy cursor
579HCURSOR gs_wxBusyCursorOld = 0; // old cursor
634903fd 580static int gs_wxBusyCursorCount = 0;
2bda0e17
KB
581
582// Set the cursor to the busy cursor for all windows
583void wxBeginBusyCursor(wxCursor *cursor)
584{
634903fd
VZ
585 if ( gs_wxBusyCursorCount++ == 0 )
586 {
587 gs_wxBusyCursor = (HCURSOR)cursor->GetHCURSOR();
588 gs_wxBusyCursorOld = ::SetCursor(gs_wxBusyCursor);
589 }
590 //else: nothing to do, already set
2bda0e17
KB
591}
592
593// Restore cursor to normal
634903fd 594void wxEndBusyCursor()
2bda0e17 595{
634903fd 596 wxCHECK_RET( gs_wxBusyCursorCount > 0,
837e5743 597 _T("no matching wxBeginBusyCursor() for wxEndBusyCursor()") );
b07135ba 598
634903fd
VZ
599 if ( --gs_wxBusyCursorCount == 0 )
600 {
601 ::SetCursor(gs_wxBusyCursorOld);
602
603 gs_wxBusyCursorOld = 0;
604 }
2bda0e17
KB
605}
606
607// TRUE if we're between the above two calls
634903fd 608bool wxIsBusy()
2bda0e17 609{
634903fd 610 return (gs_wxBusyCursorCount > 0);
b07135ba 611}
2bda0e17 612
634903fd 613// ---------------------------------------------------------------------------
837e5743 614const wxChar* wxGetHomeDir(wxString *pstr)
743e0a66
VZ
615{
616 wxString& strDir = *pstr;
617
57c208c5 618 #if defined(__UNIX__) && !defined(__TWIN32__)
837e5743 619 const wxChar *szHome = wxGetenv("HOME");
743e0a66
VZ
620 if ( szHome == NULL ) {
621 // we're homeless...
622 wxLogWarning(_("can't find user's HOME, using current directory."));
837e5743 623 strDir = _T(".");
743e0a66
VZ
624 }
625 else
626 strDir = szHome;
627
628 // add a trailing slash if needed
837e5743
OK
629 if ( strDir.Last() != _T('/') )
630 strDir << _T('/');
743e0a66
VZ
631 #else // Windows
632 #ifdef __WIN32__
837e5743 633 const wxChar *szHome = wxGetenv(_T("HOMEDRIVE"));
743e0a66
VZ
634 if ( szHome != NULL )
635 strDir << szHome;
837e5743 636 szHome = wxGetenv(_T("HOMEPATH"));
743e0a66
VZ
637 if ( szHome != NULL ) {
638 strDir << szHome;
639
640 // the idea is that under NT these variables have default values
641 // of "%systemdrive%:" and "\\". As we don't want to create our
642 // config files in the root directory of the system drive, we will
643 // create it in our program's dir. However, if the user took care
644 // to set HOMEPATH to something other than "\\", we suppose that he
645 // knows what he is doing and use the supplied value.
837e5743 646 if ( wxStrcmp(szHome, _T("\\")) != 0 )
743e0a66
VZ
647 return strDir.c_str();
648 }
649
650 #else // Win16
651 // Win16 has no idea about home, so use the working directory instead
652 #endif // WIN16/32
653
654 // 260 was taken from windef.h
655 #ifndef MAX_PATH
656 #define MAX_PATH 260
657 #endif
658
659 wxString strPath;
660 ::GetModuleFileName(::GetModuleHandle(NULL),
661 strPath.GetWriteBuf(MAX_PATH), MAX_PATH);
662 strPath.UngetWriteBuf();
663
664 // extract the dir name
665 wxSplitPath(strPath, &strDir, NULL, NULL);
666
667 #endif // UNIX/Win
668
669 return strDir.c_str();
670}
671
2bda0e17 672// Hack for MS-DOS
837e5743 673wxChar *wxGetUserHome (const wxString& user)
2bda0e17 674{
837e5743 675 wxChar *home;
2bda0e17
KB
676 wxString user1(user);
677
837e5743
OK
678 if (user1 != _T("")) {
679 wxChar tmp[64];
2bda0e17
KB
680 if (wxGetUserId(tmp, sizeof(tmp)/sizeof(char))) {
681 // Guests belong in the temp dir
837e5743
OK
682 if (wxStricmp(tmp, _T("annonymous")) == 0) {
683 if ((home = wxGetenv(_T("TMP"))) != NULL ||
684 (home = wxGetenv(_T("TMPDIR"))) != NULL ||
685 (home = wxGetenv(_T("TEMP"))) != NULL)
686 return *home ? home : (wxChar*)_T("\\");
2bda0e17 687 }
837e5743
OK
688 if (wxStricmp(tmp, WXSTRINGCAST user1) == 0)
689 user1 = _T("");
2bda0e17
KB
690 }
691 }
837e5743
OK
692 if (user1 == _T(""))
693 if ((home = wxGetenv(_T("HOME"))) != NULL)
2bda0e17 694 {
837e5743 695 wxStrcpy(wxBuffer, home);
2bda0e17
KB
696 Unix2DosFilename(wxBuffer);
697 return wxBuffer;
698 }
699 return NULL; // No home known!
700}
701
702// Check whether this window wants to process messages, e.g. Stop button
703// in long calculations.
704bool wxCheckForInterrupt(wxWindow *wnd)
705{
743e0a66
VZ
706 if(wnd){
707 MSG msg;
708 HWND win= (HWND) wnd->GetHWND();
709 while(PeekMessage(&msg,win,0,0,PM_REMOVE)){
710 TranslateMessage(&msg);
711 DispatchMessage(&msg);
712 }
713 return TRUE;//*** temporary?
714 }
715 else{
837e5743 716 wxFAIL_MSG(_T("wnd==NULL !!!"));
634903fd 717
743e0a66
VZ
718 return FALSE;//*** temporary?
719 }
2bda0e17
KB
720}
721
722// MSW only: get user-defined resource from the .res file.
723// Returns NULL or newly-allocated memory, so use delete[] to clean up.
724
2049ba38 725#ifdef __WXMSW__
837e5743 726wxChar *wxLoadUserResource(const wxString& resourceName, const wxString& resourceType)
2bda0e17 727{
837e5743 728 wxChar *s = NULL;
57c208c5 729#if !defined(__WIN32__) || defined(__TWIN32__)
2bda0e17
KB
730 HRSRC hResource = ::FindResource(wxGetInstance(), WXSTRINGCAST resourceName, WXSTRINGCAST resourceType);
731#else
732#ifdef UNICODE
733 HRSRC hResource = ::FindResourceW(wxGetInstance(), WXSTRINGCAST resourceName, WXSTRINGCAST resourceType);
734#else
735 HRSRC hResource = ::FindResourceA(wxGetInstance(), WXSTRINGCAST resourceName, WXSTRINGCAST resourceType);
736#endif
737#endif
738
739 if (hResource == 0)
740 return NULL;
741 HGLOBAL hData = ::LoadResource(wxGetInstance(), hResource);
742 if (hData == 0)
743 return NULL;
837e5743 744 wxChar *theText = (wxChar *)LockResource(hData);
2bda0e17
KB
745 if (!theText)
746 return NULL;
b07135ba 747
2bda0e17
KB
748 s = copystring(theText);
749
750 // Obsolete in WIN32
751#ifndef __WIN32__
752 UnlockResource(hData);
753#endif
754
755 // No need??
756// GlobalFree(hData);
757
758 return s;
759}
760#endif
761
762void wxGetMousePosition( int* x, int* y )
763{
764 POINT pt;
765 GetCursorPos( & pt );
766 *x = pt.x;
767 *y = pt.y;
768};
769
770// Return TRUE if we have a colour display
634903fd 771bool wxColourDisplay()
2bda0e17 772{
57c208c5 773 HDC dc = ::GetDC((HWND) NULL);
2bda0e17
KB
774 bool flag;
775 int noCols = GetDeviceCaps(dc, NUMCOLORS);
776 if ((noCols == -1) || (noCols > 2))
777 flag = TRUE;
778 else
779 flag = FALSE;
57c208c5 780 ReleaseDC((HWND) NULL, dc);
2bda0e17
KB
781 return flag;
782}
783
784// Returns depth of screen
634903fd 785int wxDisplayDepth()
2bda0e17 786{
57c208c5 787 HDC dc = ::GetDC((HWND) NULL);
2bda0e17
KB
788 int planes = GetDeviceCaps(dc, PLANES);
789 int bitsPerPixel = GetDeviceCaps(dc, BITSPIXEL);
790 int depth = planes*bitsPerPixel;
57c208c5 791 ReleaseDC((HWND) NULL, dc);
2bda0e17
KB
792 return depth;
793}
794
795// Get size of display
796void wxDisplaySize(int *width, int *height)
797{
57c208c5 798 HDC dc = ::GetDC((HWND) NULL);
2bda0e17 799 *width = GetDeviceCaps(dc, HORZRES); *height = GetDeviceCaps(dc, VERTRES);
57c208c5 800 ReleaseDC((HWND) NULL, dc);
2bda0e17
KB
801}
802
7f555861
JS
803bool wxDirExists(const wxString& dir)
804{
805 /* MATTHEW: [6] Always use same code for Win32, call FindClose */
806#if defined(__WIN32__)
807 WIN32_FIND_DATA fileInfo;
808#else
809#ifdef __BORLANDC__
810 struct ffblk fileInfo;
811#else
812 struct find_t fileInfo;
813#endif
814#endif
815
816#if defined(__WIN32__)
3f4a0c5b
VZ
817 HANDLE h = FindFirstFile((LPTSTR) WXSTRINGCAST dir,(LPWIN32_FIND_DATA)&fileInfo);
818
819 if (h==INVALID_HANDLE_VALUE)
820 return FALSE;
821 else {
822 FindClose(h);
823 return ((fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY);
824 }
7f555861
JS
825#else
826 // In Borland findfirst has a different argument
827 // ordering from _dos_findfirst. But _dos_findfirst
828 // _should_ be ok in both MS and Borland... why not?
829#ifdef __BORLANDC__
830 return ((findfirst(WXSTRINGCAST dir, &fileInfo, _A_SUBDIR) == 0 && (fileInfo.ff_attrib & _A_SUBDIR) != 0));
831#else
832 return (((_dos_findfirst(WXSTRINGCAST dir, _A_SUBDIR, &fileInfo) == 0) && (fileInfo.attrib & _A_SUBDIR)) != 0);
833#endif
834#endif
835}
836
cc2b7472
VZ
837// ---------------------------------------------------------------------------
838// window information functions
839// ---------------------------------------------------------------------------
840
1c4a764c
VZ
841wxString WXDLLEXPORT wxGetWindowText(WXHWND hWnd)
842{
843 wxString str;
844 int len = GetWindowTextLength((HWND)hWnd) + 1;
845 GetWindowText((HWND)hWnd, str.GetWriteBuf(len), len);
846 str.UngetWriteBuf();
847
848 return str;
849}
850
cc2b7472
VZ
851wxString WXDLLEXPORT wxGetWindowClass(WXHWND hWnd)
852{
853 wxString str;
854
855 int len = 256; // some starting value
856
857 for ( ;; )
858 {
859 // as we've #undefined GetClassName we must now manually choose the
860 // right function to call
861 int count =
862
863 #ifndef __WIN32__
864 GetClassName
865 #else // Win32
866 #ifdef UNICODE
867 GetClassNameW
868 #else // !Unicode
869 #ifdef __TWIN32__
870 GetClassName
871 #else // !Twin32
872 GetClassNameA
873 #endif // Twin32/!Twin32
874 #endif // Unicode/ANSI
875 #endif // Win16/32
876 ((HWND)hWnd, str.GetWriteBuf(len), len);
877
878 str.UngetWriteBuf();
879 if ( count == len )
880 {
881 // the class name might have been truncated, retry with larger
882 // buffer
883 len *= 2;
884 }
885 else
886 {
887 break;
888 }
889 }
890
891 return str;
892}
893
42e69d6b 894WXWORD WXDLLEXPORT wxGetWindowId(WXHWND hWnd)
cc2b7472
VZ
895{
896#ifndef __WIN32__
42e69d6b 897 return GetWindowWord((HWND)hWnd, GWW_ID);
cc2b7472 898#else // Win32
42e69d6b 899 return GetWindowLong((HWND)hWnd, GWL_ID);
cc2b7472
VZ
900#endif // Win16/32
901}
902
7f555861
JS
903#if 0
904//------------------------------------------------------------------------
905// wild character routines
906//------------------------------------------------------------------------
907
908bool wxIsWild( const wxString& pattern )
909{
910 wxString tmp = pattern;
911 char *pat = WXSTRINGCAST(tmp);
912 while (*pat) {
3f4a0c5b
VZ
913 switch (*pat++) {
914 case '?': case '*': case '[': case '{':
915 return TRUE;
916 case '\\':
917 if (!*pat++)
918 return FALSE;
919 }
7f555861
JS
920 }
921 return FALSE;
922};
923
924
925bool wxMatchWild( const wxString& pat, const wxString& text, bool dot_special )
926{
927 wxString tmp1 = pat;
928 char *pattern = WXSTRINGCAST(tmp1);
929 wxString tmp2 = text;
930 char *str = WXSTRINGCAST(tmp2);
931 char c;
932 char *cp;
933 bool done = FALSE, ret_code, ok;
934 // Below is for vi fans
935 const char OB = '{', CB = '}';
936
937 // dot_special means '.' only matches '.'
938 if (dot_special && *str == '.' && *pattern != *str)
3f4a0c5b 939 return FALSE;
7f555861
JS
940
941 while ((*pattern != '\0') && (!done)
942 && (((*str=='\0')&&((*pattern==OB)||(*pattern=='*')))||(*str!='\0'))) {
3f4a0c5b
VZ
943 switch (*pattern) {
944 case '\\':
945 pattern++;
946 if (*pattern != '\0')
947 pattern++;
948 break;
949 case '*':
950 pattern++;
951 ret_code = FALSE;
952 while ((*str!='\0')
953 && (!(ret_code=wxMatchWild(pattern, str++, FALSE))))
954 /*loop*/;
955 if (ret_code) {
956 while (*str != '\0')
957 str++;
958 while (*pattern != '\0')
959 pattern++;
960 }
961 break;
962 case '[':
963 pattern++;
964 repeat:
965 if ((*pattern == '\0') || (*pattern == ']')) {
966 done = TRUE;
967 break;
968 }
969 if (*pattern == '\\') {
970 pattern++;
971 if (*pattern == '\0') {
972 done = TRUE;
973 break;
974 }
975 }
976 if (*(pattern + 1) == '-') {
977 c = *pattern;
978 pattern += 2;
979 if (*pattern == ']') {
980 done = TRUE;
981 break;
982 }
983 if (*pattern == '\\') {
984 pattern++;
985 if (*pattern == '\0') {
986 done = TRUE;
987 break;
988 }
989 }
990 if ((*str < c) || (*str > *pattern)) {
991 pattern++;
992 goto repeat;
993 }
994 } else if (*pattern != *str) {
995 pattern++;
996 goto repeat;
997 }
998 pattern++;
999 while ((*pattern != ']') && (*pattern != '\0')) {
1000 if ((*pattern == '\\') && (*(pattern + 1) != '\0'))
1001 pattern++;
1002 pattern++;
1003 }
1004 if (*pattern != '\0') {
1005 pattern++, str++;
1006 }
1007 break;
1008 case '?':
1009 pattern++;
1010 str++;
1011 break;
1012 case OB:
1013 pattern++;
1014 while ((*pattern != CB) && (*pattern != '\0')) {
1015 cp = str;
1016 ok = TRUE;
1017 while (ok && (*cp != '\0') && (*pattern != '\0')
1018 && (*pattern != ',') && (*pattern != CB)) {
1019 if (*pattern == '\\')
1020 pattern++;
1021 ok = (*pattern++ == *cp++);
1022 }
1023 if (*pattern == '\0') {
1024 ok = FALSE;
1025 done = TRUE;
1026 break;
1027 } else if (ok) {
1028 str = cp;
1029 while ((*pattern != CB) && (*pattern != '\0')) {
1030 if (*++pattern == '\\') {
1031 if (*++pattern == CB)
1032 pattern++;
1033 }
1034 }
1035 } else {
1036 while (*pattern!=CB && *pattern!=',' && *pattern!='\0') {
1037 if (*++pattern == '\\') {
7f555861 1038 if (*++pattern == CB || *pattern == ',')
3f4a0c5b
VZ
1039 pattern++;
1040 }
1041 }
1042 }
1043 if (*pattern != '\0')
1044 pattern++;
1045 }
1046 break;
1047 default:
1048 if (*str == *pattern) {
1049 str++, pattern++;
1050 } else {
1051 done = TRUE;
1052 }
1053 }
7f555861
JS
1054 }
1055 while (*pattern == '*')
3f4a0c5b 1056 pattern++;
7f555861
JS
1057 return ((*str == '\0') && (*pattern == '\0'));
1058};
1059
1060#endif
1061
a0a302dc
JS
1062#if defined(__WIN95__) && defined(__WXDEBUG__) && wxUSE_DBWIN32
1063
1064/*
1065When I started programming with Visual C++ v4.0, I missed one of my favorite
1066tools -- DBWIN. Finding the code for a simple debug trace utility, DBMON,
1067on MSDN was a step in the right direction, but it is a console application
1068and thus has limited features and extensibility. DBWIN32 is my creation
1069to solve this problem.
1070
b07135ba 1071The code is essentially a merging of a stripped down version of the DBWIN code
a0a302dc
JS
1072from VC 1.5 and DBMON.C with a few 32 bit changes.
1073
b07135ba 1074As of version 1.2B, DBWIN32 supports both Win95 and NT. The NT support is
a0a302dc
JS
1075built into the operating system and works just by running DBWIN32. The Win95
1076team decided not to support this hook, so I have provided code that will do
1077this for you. See the file WIN95.TXT for instructions on installing this.
1078
1079If you have questions, problems or suggestions about DBWIN32, I welcome your
1080feedback and plan to actively maintain the code.
1081
1082Andrew Tucker
1083ast@halcyon.com
1084
1085To download dbwin32, see e.g.:
1086
1087http://ftp.digital.com/pub/micro/NT/WinSite/programr/dbwin32.zip
1088*/
1089
57c208c5 1090#if !defined(__MWERKS__) && !defined(__SALFORDC__) && !defined(__TWIN32__)
a0a302dc 1091#include <process.h>
17dff81c 1092#endif
a0a302dc 1093
837e5743 1094void OutputDebugStringW95(const wxChar* lpOutputString, ...)
a0a302dc
JS
1095{
1096 HANDLE heventDBWIN; /* DBWIN32 synchronization object */
1097 HANDLE heventData; /* data passing synch object */
1098 HANDLE hSharedFile; /* memory mapped file shared data */
1099 LPSTR lpszSharedMem;
837e5743 1100 wxChar achBuffer[500];
a0a302dc
JS
1101
1102 /* create the output buffer */
1103 va_list args;
1104 va_start(args, lpOutputString);
837e5743 1105 wxVsprintf(achBuffer, lpOutputString, args);
a0a302dc
JS
1106 va_end(args);
1107
b07135ba
RD
1108 /*
1109 Do a regular OutputDebugString so that the output is
a0a302dc
JS
1110 still seen in the debugger window if it exists.
1111
b07135ba 1112 This ifdef is necessary to avoid infinite recursion
a0a302dc
JS
1113 from the inclusion of W95TRACE.H
1114 */
1115#ifdef _UNICODE
1116 ::OutputDebugStringW(achBuffer);
57c208c5
JS
1117#else
1118#ifdef __TWIN32__
1119 ::OutputDebugString(achBuffer);
a0a302dc
JS
1120#else
1121 ::OutputDebugStringA(achBuffer);
57c208c5 1122#endif
a0a302dc
JS
1123#endif
1124
1125 /* bail if it's not Win95 */
1126 {
1127 OSVERSIONINFO VerInfo;
1128 VerInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
1129 GetVersionEx(&VerInfo);
1130 if ( VerInfo.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS )
1131 return;
1132 }
1133
1134 /* make sure DBWIN is open and waiting */
837e5743 1135 heventDBWIN = OpenEvent(EVENT_MODIFY_STATE, FALSE, _T("DBWIN_BUFFER_READY"));
a0a302dc
JS
1136 if ( !heventDBWIN )
1137 {
837e5743 1138 //MessageBox(NULL, _T("DBWIN_BUFFER_READY nonexistent"), NULL, MB_OK);
b07135ba 1139 return;
a0a302dc
JS
1140 }
1141
1142 /* get a handle to the data synch object */
837e5743 1143 heventData = OpenEvent(EVENT_MODIFY_STATE, FALSE, _T("DBWIN_DATA_READY"));
a0a302dc
JS
1144 if ( !heventData )
1145 {
837e5743 1146 // MessageBox(NULL, _T("DBWIN_DATA_READY nonexistent"), NULL, MB_OK);
a0a302dc 1147 CloseHandle(heventDBWIN);
b07135ba 1148 return;
a0a302dc 1149 }
b07135ba 1150
837e5743 1151 hSharedFile = CreateFileMapping((HANDLE)-1, NULL, PAGE_READWRITE, 0, 4096, _T("DBWIN_BUFFER"));
b07135ba 1152 if (!hSharedFile)
a0a302dc 1153 {
837e5743 1154 //MessageBox(NULL, _T("DebugTrace: Unable to create file mapping object DBWIN_BUFFER"), _T("Error"), MB_OK);
a0a302dc
JS
1155 CloseHandle(heventDBWIN);
1156 CloseHandle(heventData);
1157 return;
1158 }
1159
1160 lpszSharedMem = (LPSTR)MapViewOfFile(hSharedFile, FILE_MAP_WRITE, 0, 0, 512);
b07135ba 1161 if (!lpszSharedMem)
a0a302dc 1162 {
837e5743 1163 //MessageBox(NULL, _T("DebugTrace: Unable to map shared memory"), _T("Error"), MB_OK);
a0a302dc
JS
1164 CloseHandle(heventDBWIN);
1165 CloseHandle(heventData);
1166 return;
1167 }
1168
1169 /* wait for buffer event */
1170 WaitForSingleObject(heventDBWIN, INFINITE);
1171
1172 /* write it to the shared memory */
ce3ed50d 1173#if defined( __BORLANDC__ ) || defined( __MWERKS__ ) || defined(__SALFORDC__)
a0a302dc
JS
1174 *((LPDWORD)lpszSharedMem) = getpid();
1175#else
1176 *((LPDWORD)lpszSharedMem) = _getpid();
1177#endif
1178
837e5743 1179 wsprintf((LPTSTR)(lpszSharedMem + sizeof(DWORD)), _T("%s"), achBuffer);
a0a302dc
JS
1180
1181 /* signal data ready event */
1182 SetEvent(heventData);
1183
1184 /* clean up handles */
1185 CloseHandle(hSharedFile);
1186 CloseHandle(heventData);
1187 CloseHandle(heventDBWIN);
1188
1189 return;
1190}
1191
1192
1193#endif
1194
c030b70f 1195
cf45d1f4 1196#if 0
c030b70f
JS
1197
1198// maximum mumber of lines the output console should have
1199static const WORD MAX_CONSOLE_LINES = 500;
1200
1201BOOL WINAPI MyConsoleHandler( DWORD dwCtrlType ) { // control signal type
3f4a0c5b
VZ
1202 FreeConsole();
1203 return TRUE;
c030b70f
JS
1204}
1205
1206void wxRedirectIOToConsole()
1207{
1208 int hConHandle;
1209 long lStdHandle;
1210 CONSOLE_SCREEN_BUFFER_INFO coninfo;
1211 FILE *fp;
1212
1213 // allocate a console for this app
1214 AllocConsole();
1215
1216 // set the screen buffer to be big enough to let us scroll text
3f4a0c5b 1217 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),
c030b70f
JS
1218 &coninfo);
1219 coninfo.dwSize.Y = MAX_CONSOLE_LINES;
3f4a0c5b 1220 SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE),
c030b70f
JS
1221 coninfo.dwSize);
1222
1223 // redirect unbuffered STDOUT to the console
1224 lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
1225 hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
1226 if(hConHandle <= 0) return;
1227 fp = _fdopen( hConHandle, "w" );
1228 *stdout = *fp;
1229 setvbuf( stdout, NULL, _IONBF, 0 );
1230
1231 // redirect unbuffered STDIN to the console
1232 lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
1233 hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
1234 if(hConHandle <= 0) return;
1235 fp = _fdopen( hConHandle, "r" );
1236 *stdin = *fp;
1237 setvbuf( stdin, NULL, _IONBF, 0 );
1238
1239 // redirect unbuffered STDERR to the console
1240 lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
1241 hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
1242 if(hConHandle <= 0) return;
1243 fp = _fdopen( hConHandle, "w" );
1244 *stderr = *fp;
1245 setvbuf( stderr, NULL, _IONBF, 0 );
3f4a0c5b
VZ
1246
1247 // make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
c030b70f
JS
1248 // point to console as well
1249 ios::sync_with_stdio();
1250
3f4a0c5b 1251 SetConsoleCtrlHandler(MyConsoleHandler, TRUE);
c030b70f
JS
1252}
1253#else
1254// Not supported
1255void wxRedirectIOToConsole()
1256{
1257}
1258#endif
1259
1260