]> git.saurik.com Git - wxWidgets.git/blame - src/common/utilscmn.cpp
Compilation fix for r74440 and STL builds.
[wxWidgets.git] / src / common / utilscmn.cpp
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
3452f00b 2// Name: src/common/utilscmn.cpp
c801d85f
KB
3// Purpose: Miscellaneous utility functions and classes
4// Author: Julian Smart
5// Modified by:
6// Created: 29/01/98
7// RCS-ID: $Id$
8// Copyright: (c) 1998 Julian Smart
65571936 9// Licence: wxWindows licence
c801d85f
KB
10/////////////////////////////////////////////////////////////////////////////
11
e90c1d2a
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
c801d85f
KB
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
e90c1d2a 24 #pragma hdrstop
c801d85f
KB
25#endif
26
27#ifndef WX_PRECOMP
fcdb9b38 28 #include "wx/app.h"
e90c1d2a
VZ
29 #include "wx/string.h"
30 #include "wx/utils.h"
974e8d94
VZ
31 #include "wx/intl.h"
32 #include "wx/log.h"
e90c1d2a
VZ
33
34 #if wxUSE_GUI
35 #include "wx/window.h"
e90c1d2a 36 #include "wx/frame.h"
1e6feb95 37 #include "wx/menu.h"
e90c1d2a
VZ
38 #include "wx/msgdlg.h"
39 #include "wx/textdlg.h"
78bcfcfc 40 #include "wx/textctrl.h" // for wxTE_PASSWORD
974e8d94
VZ
41 #if wxUSE_ACCEL
42 #include "wx/menuitem.h"
43 #include "wx/accel.h"
44 #endif // wxUSE_ACCEL
e90c1d2a
VZ
45 #endif // wxUSE_GUI
46#endif // WX_PRECOMP
c801d85f 47
2739d4f0
VZ
48#include "wx/apptrait.h"
49
cd6ce4a9
VZ
50#include "wx/process.h"
51#include "wx/txtstrm.h"
498a1eeb
RN
52#include "wx/uri.h"
53#include "wx/mimetype.h"
54#include "wx/config.h"
ccec9093 55#include "wx/versioninfo.h"
cd6ce4a9 56
4676948b 57#if defined(__WXWINCE__) && wxUSE_DATETIME
50a2e26f 58 #include "wx/datetime.h"
4676948b
JS
59#endif
60
c801d85f
KB
61#include <ctype.h>
62#include <stdio.h>
63#include <stdlib.h>
64#include <string.h>
e90c1d2a 65
13ff2485 66#if !wxONLY_WATCOM_EARLIER_THAN(1,4)
3f4a0c5b
VZ
67 #if !(defined(_MSC_VER) && (_MSC_VER > 800))
68 #include <errno.h>
69 #endif
c801d85f 70#endif
e90c1d2a 71
91b4c08d 72#if wxUSE_GUI
d1c8aaa3 73 #include "wx/notebook.h"
d1c8aaa3 74 #include "wx/statusbr.h"
91b4c08d
VZ
75#endif // wxUSE_GUI
76
1c193821 77#ifndef __WXWINCE__
50a2e26f 78 #include <time.h>
1c193821 79#else
50a2e26f 80 #include "wx/msw/wince/time.h"
1c193821 81#endif
e90c1d2a 82
f14d6dd1 83#ifdef __WXMAC__
50a2e26f 84 #include "wx/osx/private.h"
f14d6dd1
JS
85#endif
86
2415cf67 87#if !defined(__WXWINCE__)
e90c1d2a
VZ
88 #include <sys/types.h>
89 #include <sys/stat.h>
469e1e5c 90#endif
c801d85f 91
d98a58c5 92#if defined(__WINDOWS__)
5e1febfa 93 #include "wx/msw/private.h"
50a2e26f 94 #include "wx/filesys.h"
c801d85f
KB
95#endif
96
6ed3db08
VZ
97#if wxUSE_GUI && defined(__WXGTK__)
98 #include <gtk/gtk.h> // for GTK_XXX_VERSION constants
99#endif
100
ec67cff1 101#if wxUSE_BASE
7c072018 102
e90c1d2a
VZ
103// ============================================================================
104// implementation
105// ============================================================================
c801d85f 106
c801d85f 107// Array used in DecToHex conversion routine.
a243da29 108static const wxChar hexArray[] = wxT("0123456789ABCDEF");
c801d85f
KB
109
110// Convert 2-digit hex number to decimal
a9465653 111int wxHexToDec(const wxString& str)
c801d85f 112{
a9465653
JS
113 char buf[2];
114 buf[0] = str.GetChar(0);
115 buf[1] = str.GetChar(1);
116 return wxHexToDec((const char*) buf);
c801d85f
KB
117}
118
119// Convert decimal integer to 2-character hex string
84fff0b3 120void wxDecToHex(int dec, wxChar *buf)
c801d85f 121{
657a7545
WS
122 int firstDigit = (int)(dec/16.0);
123 int secondDigit = (int)(dec - (firstDigit*16.0));
124 buf[0] = hexArray[firstDigit];
125 buf[1] = hexArray[secondDigit];
126 buf[2] = 0;
c801d85f
KB
127}
128
f728025e
JS
129// Convert decimal integer to 2 characters
130void wxDecToHex(int dec, char* ch1, char* ch2)
131{
132 int firstDigit = (int)(dec/16.0);
133 int secondDigit = (int)(dec - (firstDigit*16.0));
134 (*ch1) = (char) hexArray[firstDigit];
135 (*ch2) = (char) hexArray[secondDigit];
136}
137
fd71308f
JS
138// Convert decimal integer to 2-character hex string
139wxString wxDecToHex(int dec)
140{
84fff0b3 141 wxChar buf[3];
fd71308f
JS
142 wxDecToHex(dec, buf);
143 return wxString(buf);
144}
145
7c072018
VZ
146// ----------------------------------------------------------------------------
147// misc functions
148// ----------------------------------------------------------------------------
c801d85f
KB
149
150// Return the current date/time
e90c1d2a 151wxString wxNow()
c801d85f 152{
4676948b
JS
153#ifdef __WXWINCE__
154#if wxUSE_DATETIME
155 wxDateTime now = wxDateTime::Now();
156 return now.Format();
157#else
158 return wxEmptyString;
159#endif
160#else
d3b9f782 161 time_t now = time(NULL);
2b5f62a0
VZ
162 char *date = ctime(&now);
163 date[24] = '\0';
164 return wxString::FromAscii(date);
4676948b 165#endif
c801d85f
KB
166}
167
24c4d27f 168#if WXWIN_COMPATIBILITY_2_8
08873d36
VZ
169void wxUsleep(unsigned long milliseconds)
170{
171 wxMilliSleep(milliseconds);
172}
2382f4db 173#endif
08873d36 174
7c072018
VZ
175const wxChar *wxGetInstallPrefix()
176{
177 wxString prefix;
178
179 if ( wxGetEnv(wxT("WXPREFIX"), &prefix) )
180 return prefix.c_str();
181
182#ifdef wxINSTALL_PREFIX
183 return wxT(wxINSTALL_PREFIX);
184#else
525d8583 185 return wxEmptyString;
7c072018
VZ
186#endif
187}
188
189wxString wxGetDataDir()
190{
10f206ad
RL
191 wxString dir = wxGetInstallPrefix();
192 dir << wxFILE_SEP_PATH << wxT("share") << wxFILE_SEP_PATH << wxT("wx");
7c072018
VZ
193 return dir;
194}
e90c1d2a 195
8bb6b2c0 196bool wxIsPlatformLittleEndian()
2739d4f0 197{
8bb6b2c0
VZ
198 // Are we little or big endian? This method is from Harbison & Steele.
199 union
200 {
201 long l;
202 char c[sizeof(long)];
203 } u;
204 u.l = 1;
205
206 return u.c[0] == 1;
2739d4f0 207}
1e6feb95 208
8bb6b2c0 209
fad92e2f
FM
210// ----------------------------------------------------------------------------
211// wxPlatform
212// ----------------------------------------------------------------------------
213
230c9077
JS
214/*
215 * Class to make it easier to specify platform-dependent values
216 */
217
218wxArrayInt* wxPlatform::sm_customPlatforms = NULL;
219
4bfec179 220void wxPlatform::Copy(const wxPlatform& platform)
230c9077 221{
4bfec179
JS
222 m_longValue = platform.m_longValue;
223 m_doubleValue = platform.m_doubleValue;
224 m_stringValue = platform.m_stringValue;
225}
226
227wxPlatform wxPlatform::If(int platform, long value)
228{
229 if (Is(platform))
230 return wxPlatform(value);
231 else
232 return wxPlatform();
233}
234
235wxPlatform wxPlatform::IfNot(int platform, long value)
236{
237 if (!Is(platform))
238 return wxPlatform(value);
239 else
240 return wxPlatform();
241}
242
243wxPlatform& wxPlatform::ElseIf(int platform, long value)
244{
245 if (Is(platform))
230c9077
JS
246 m_longValue = value;
247 return *this;
248}
249
4bfec179 250wxPlatform& wxPlatform::ElseIfNot(int platform, long value)
230c9077 251{
4bfec179 252 if (!Is(platform))
230c9077
JS
253 m_longValue = value;
254 return *this;
255}
256
4bfec179 257wxPlatform wxPlatform::If(int platform, double value)
230c9077 258{
4bfec179
JS
259 if (Is(platform))
260 return wxPlatform(value);
261 else
262 return wxPlatform();
263}
264
265wxPlatform wxPlatform::IfNot(int platform, double value)
266{
267 if (!Is(platform))
268 return wxPlatform(value);
269 else
270 return wxPlatform();
271}
272
273wxPlatform& wxPlatform::ElseIf(int platform, double value)
274{
275 if (Is(platform))
230c9077
JS
276 m_doubleValue = value;
277 return *this;
278}
279
4bfec179 280wxPlatform& wxPlatform::ElseIfNot(int platform, double value)
230c9077 281{
4bfec179 282 if (!Is(platform))
230c9077
JS
283 m_doubleValue = value;
284 return *this;
285}
286
4bfec179
JS
287wxPlatform wxPlatform::If(int platform, const wxString& value)
288{
289 if (Is(platform))
290 return wxPlatform(value);
291 else
292 return wxPlatform();
293}
294
295wxPlatform wxPlatform::IfNot(int platform, const wxString& value)
296{
297 if (!Is(platform))
298 return wxPlatform(value);
299 else
300 return wxPlatform();
301}
302
303wxPlatform& wxPlatform::ElseIf(int platform, const wxString& value)
230c9077 304{
4bfec179 305 if (Is(platform))
230c9077
JS
306 m_stringValue = value;
307 return *this;
308}
309
4bfec179 310wxPlatform& wxPlatform::ElseIfNot(int platform, const wxString& value)
230c9077 311{
4bfec179 312 if (!Is(platform))
230c9077
JS
313 m_stringValue = value;
314 return *this;
315}
316
4bfec179 317wxPlatform& wxPlatform::Else(long value)
230c9077
JS
318{
319 m_longValue = value;
320 return *this;
321}
322
4bfec179 323wxPlatform& wxPlatform::Else(double value)
230c9077
JS
324{
325 m_doubleValue = value;
326 return *this;
327}
328
4bfec179 329wxPlatform& wxPlatform::Else(const wxString& value)
230c9077
JS
330{
331 m_stringValue = value;
332 return *this;
333}
334
335void wxPlatform::AddPlatform(int platform)
336{
337 if (!sm_customPlatforms)
338 sm_customPlatforms = new wxArrayInt;
339 sm_customPlatforms->Add(platform);
340}
341
342void wxPlatform::ClearPlatforms()
343{
5276b0a5 344 wxDELETE(sm_customPlatforms);
230c9077
JS
345}
346
347/// Function for testing current platform
348
4bfec179 349bool wxPlatform::Is(int platform)
230c9077 350{
d98a58c5 351#ifdef __WINDOWS__
216c3543 352 if (platform == wxOS_WINDOWS)
230c9077
JS
353 return true;
354#endif
355#ifdef __WXWINCE__
216c3543 356 if (platform == wxOS_WINDOWS_CE)
230c9077
JS
357 return true;
358#endif
a6e8c584
WS
359
360#if 0
361
362// FIXME: wxWinPocketPC and wxWinSmartPhone are unknown symbols
363
230c9077
JS
364#if defined(__WXWINCE__) && defined(__POCKETPC__)
365 if (platform == wxWinPocketPC)
366 return true;
367#endif
368#if defined(__WXWINCE__) && defined(__SMARTPHONE__)
6aa68c25 369 if (platform == wxWinSmartPhone)
230c9077
JS
370 return true;
371#endif
a6e8c584
WS
372
373#endif
374
230c9077 375#ifdef __WXGTK__
216c3543 376 if (platform == wxPORT_GTK)
230c9077
JS
377 return true;
378#endif
379#ifdef __WXMAC__
216c3543 380 if (platform == wxPORT_MAC)
230c9077
JS
381 return true;
382#endif
383#ifdef __WXX11__
216c3543 384 if (platform == wxPORT_X11)
230c9077
JS
385 return true;
386#endif
387#ifdef __UNIX__
216c3543 388 if (platform == wxOS_UNIX)
230c9077
JS
389 return true;
390#endif
8ab09e65
SN
391#ifdef __OS2__
392 if (platform == wxOS_OS2)
393 return true;
394#endif
395#ifdef __WXPM__
396 if (platform == wxPORT_PM)
230c9077
JS
397 return true;
398#endif
55d452c6 399#ifdef __WXCOCOA__
216c3543 400 if (platform == wxPORT_MAC)
230c9077
JS
401 return true;
402#endif
403
404 if (sm_customPlatforms && sm_customPlatforms->Index(platform) != wxNOT_FOUND)
405 return true;
406
407 return false;
408}
409
e90c1d2a 410// ----------------------------------------------------------------------------
7c072018 411// network and user id functions
e90c1d2a 412// ----------------------------------------------------------------------------
c801d85f 413
7c072018
VZ
414// Get Full RFC822 style email address
415bool wxGetEmailAddress(wxChar *address, int maxSize)
c801d85f 416{
7c072018
VZ
417 wxString email = wxGetEmailAddress();
418 if ( !email )
cb719f2e 419 return false;
c801d85f 420
9d4943cd 421 wxStrlcpy(address, email.t_str(), maxSize);
7c072018 422
cb719f2e 423 return true;
c801d85f
KB
424}
425
7c072018 426wxString wxGetEmailAddress()
47bc1060 427{
7c072018 428 wxString email;
974e8d94 429
7c072018 430 wxString host = wxGetFullHostName();
4055ed82 431 if ( !host.empty() )
1e6feb95 432 {
7c072018 433 wxString user = wxGetUserId();
4055ed82 434 if ( !user.empty() )
1e6feb95 435 {
7c072018 436 email << user << wxT('@') << host;
974e8d94 437 }
974e8d94
VZ
438 }
439
7c072018 440 return email;
974e8d94
VZ
441}
442
7c072018 443wxString wxGetUserId()
c801d85f 444{
7c072018 445 static const int maxLoginLen = 256; // FIXME arbitrary number
c801d85f 446
7c072018 447 wxString buf;
4c3ebca9 448 bool ok = wxGetUserId(wxStringBuffer(buf, maxLoginLen), maxLoginLen);
c801d85f 449
7c072018
VZ
450 if ( !ok )
451 buf.Empty();
c801d85f 452
7c072018 453 return buf;
c801d85f
KB
454}
455
7c072018 456wxString wxGetUserName()
c801d85f 457{
7c072018 458 static const int maxUserNameLen = 1024; // FIXME arbitrary number
1e6feb95 459
7c072018 460 wxString buf;
4c3ebca9 461 bool ok = wxGetUserName(wxStringBuffer(buf, maxUserNameLen), maxUserNameLen);
7c072018
VZ
462
463 if ( !ok )
464 buf.Empty();
465
466 return buf;
59a12e90
JS
467}
468
7c072018 469wxString wxGetHostName()
59a12e90 470{
7c072018 471 static const size_t hostnameSize = 257;
c67d6888 472
7c072018 473 wxString buf;
4c3ebca9 474 bool ok = wxGetHostName(wxStringBuffer(buf, hostnameSize), hostnameSize);
59a12e90 475
7c072018
VZ
476 if ( !ok )
477 buf.Empty();
59a12e90 478
7c072018 479 return buf;
59a12e90
JS
480}
481
7c072018 482wxString wxGetFullHostName()
59a12e90 483{
7c072018 484 static const size_t hostnameSize = 257;
c801d85f 485
7c072018 486 wxString buf;
4c3ebca9 487 bool ok = wxGetFullHostName(wxStringBuffer(buf, hostnameSize), hostnameSize);
7c072018
VZ
488
489 if ( !ok )
490 buf.Empty();
c801d85f 491
7c072018
VZ
492 return buf;
493}
c801d85f 494
7c072018
VZ
495wxString wxGetHomeDir()
496{
497 wxString home;
498 wxGetHomeDir(&home);
c801d85f 499
7c072018
VZ
500 return home;
501}
c801d85f 502
c801d85f
KB
503#if 0
504
7c072018 505wxString wxGetCurrentDir()
c801d85f 506{
7c072018
VZ
507 wxString dir;
508 size_t len = 1024;
509 bool ok;
510 do
511 {
512 ok = getcwd(dir.GetWriteBuf(len + 1), len) != NULL;
513 dir.UngetWriteBuf();
c801d85f 514
7c072018
VZ
515 if ( !ok )
516 {
517 if ( errno != ERANGE )
518 {
9a83f860 519 wxLogSysError(wxT("Failed to get current directory"));
c801d85f 520
7c072018
VZ
521 return wxEmptyString;
522 }
3f4a0c5b 523 else
7c072018
VZ
524 {
525 // buffer was too small, retry with a larger one
526 len *= 2;
527 }
3f4a0c5b 528 }
7c072018
VZ
529 //else: ok
530 } while ( !ok );
c801d85f 531
7c072018 532 return dir;
c801d85f
KB
533}
534
7c072018 535#endif // 0
e90c1d2a 536
164db92c
VZ
537// ----------------------------------------------------------------------------
538// Environment
539// ----------------------------------------------------------------------------
540
1f4c7e79 541#ifdef __WXOSX__
edb31724 542#if wxOSX_USE_COCOA_OR_CARBON
1f4c7e79
VZ
543 #include <crt_externs.h>
544#endif
edb31724 545#endif
1f4c7e79 546
164db92c
VZ
547bool wxGetEnvMap(wxEnvVariableHashMap *map)
548{
549 wxCHECK_MSG( map, false, wxS("output pointer can't be NULL") );
550
551#if defined(__VISUALC__)
6f41c109
VZ
552 // This variable only exists to force the CRT to fill the wide char array,
553 // it might only have it in narrow char version until now as we use main()
554 // (and not _wmain()) as our entry point.
555 static wxChar* s_dummyEnvVar = _tgetenv(wxT("TEMP"));
556
164db92c 557 wxChar **env = _tenviron;
cc221535
JJ
558#elif defined(__VMS)
559 // Now this routine wil give false for OpenVMS
560 // TODO : should we do something with logicals?
04b11eb3 561 char **env=NULL;
da0ee16e 562#elif defined(__DARWIN__)
edb31724 563#if wxOSX_USE_COCOA_OR_CARBON
1f4c7e79
VZ
564 // Under Mac shared libraries don't have access to the global environ
565 // variable so use this Mac-specific function instead as advised by
566 // environ(7) under Darwin
567 char ***penv = _NSGetEnviron();
568 if ( !penv )
569 return false;
570 char **env = *penv;
edb31724
SC
571#else
572 char **env=NULL;
573 // todo translate NSProcessInfo environment into map
574#endif
1f4c7e79 575#else // non-MSVC non-Mac
164db92c
VZ
576 // Not sure if other compilers have _tenviron so use the (more standard)
577 // ANSI version only for them.
14c350df
VZ
578
579 // Both POSIX and Single UNIX Specification say that this variable must
580 // exist but not that it must be declared anywhere and, indeed, it's not
b54a0e39
VZ
581 // declared in several common systems (some BSDs, Solaris with native CC)
582 // so we (re)declare it ourselves to deal with these cases. However we do
583 // not do this under MSW where there can be DLL-related complications, i.e.
584 // the variable might be DLL-imported or not. Luckily we don't have to
585 // worry about this as all MSW compilers do seem to define it in their
586 // standard headers anyhow so we can just rely on already having the
587 // correct declaration. And if this turns out to be wrong, we can always
588 // add a configure test checking whether it is declared later.
d98a58c5 589#ifndef __WINDOWS__
eeb415ec 590 extern char **environ;
d98a58c5 591#endif // !__WINDOWS__
14c350df 592
1f4c7e79 593 char **env = environ;
164db92c
VZ
594#endif
595
596 if ( env )
597 {
598 wxString name,
599 value;
600 while ( *env )
601 {
602 const wxString var(*env);
603
604 name = var.BeforeFirst(wxS('='), &value);
605
606 (*map)[name] = value;
607
608 env++;
609 }
610
611 return true;
612 }
613
614 return false;
615}
616
e90c1d2a 617// ----------------------------------------------------------------------------
7c072018 618// wxExecute
e90c1d2a 619// ----------------------------------------------------------------------------
ead7ce10 620
d1c063b9
VZ
621// wxDoExecuteWithCapture() helper: reads an entire stream into one array if
622// the stream is non-NULL (it doesn't do anything if it's NULL).
7c072018 623//
cb719f2e 624// returns true if ok, false if error
7c072018
VZ
625#if wxUSE_STREAMS
626static bool ReadAll(wxInputStream *is, wxArrayString& output)
dfad0599 627{
d1c063b9
VZ
628 if ( !is )
629 return true;
dfad0599 630
7c072018
VZ
631 // the stream could be already at EOF or in wxSTREAM_BROKEN_PIPE state
632 is->Reset();
1e6feb95 633
7c072018 634 wxTextInputStream tis(*is);
1e6feb95 635
8bdc8a9c 636 for ( ;; )
d2f50933 637 {
7c072018 638 wxString line = tis.ReadLine();
8bdc8a9c
VZ
639
640 // check for EOF before other errors as it's not really an error
7c072018 641 if ( is->Eof() )
8bdc8a9c
VZ
642 {
643 // add the last, possibly incomplete, line
644 if ( !line.empty() )
645 output.Add(line);
7c072018 646 break;
8bdc8a9c 647 }
7c072018 648
8bdc8a9c 649 // any other error is fatal
7c072018 650 if ( !*is )
8bdc8a9c
VZ
651 return false;
652
653 output.Add(line);
d2f50933
VZ
654 }
655
8bdc8a9c 656 return true;
dfad0599 657}
7c072018 658#endif // wxUSE_STREAMS
d2f50933 659
7c072018
VZ
660// this is a private function because it hasn't a clean interface: the first
661// array is passed by reference, the second by pointer - instead we have 2
662// public versions of wxExecute() below
663static long wxDoExecuteWithCapture(const wxString& command,
664 wxArrayString& output,
4d172154 665 wxArrayString* error,
164db92c
VZ
666 int flags,
667 const wxExecuteEnv *env)
d2f50933 668{
7c072018
VZ
669 // create a wxProcess which will capture the output
670 wxProcess *process = new wxProcess;
671 process->Redirect();
dfad0599 672
164db92c 673 long rc = wxExecute(command, wxEXEC_SYNC | flags, process, env);
1e6feb95 674
7c072018 675#if wxUSE_STREAMS
d1c063b9
VZ
676 // Notice that while -1 indicates an error exit code for us, a program
677 // exiting with this code could still have written something to its stdout
678 // and, especially, stderr, so we still need to read from them.
679 if ( !ReadAll(process->GetInputStream(), output) )
680 rc = -1;
681
682 if ( error )
bf31fa26 683 {
d1c063b9 684 if ( !ReadAll(process->GetErrorStream(), *error) )
7c072018 685 rc = -1;
7c072018 686 }
e70ba80d
WS
687#else
688 wxUnusedVar(output);
689 wxUnusedVar(error);
690#endif // wxUSE_STREAMS/!wxUSE_STREAMS
91b4c08d 691
7c072018 692 delete process;
1e6feb95 693
7c072018 694 return rc;
7c072018 695}
bf31fa26 696
164db92c
VZ
697long wxExecute(const wxString& command, wxArrayString& output, int flags,
698 const wxExecuteEnv *env)
bf31fa26 699{
164db92c 700 return wxDoExecuteWithCapture(command, output, NULL, flags, env);
7c072018 701}
bf31fa26 702
7c072018
VZ
703long wxExecute(const wxString& command,
704 wxArrayString& output,
4d172154 705 wxArrayString& error,
164db92c
VZ
706 int flags,
707 const wxExecuteEnv *env)
7c072018 708{
164db92c 709 return wxDoExecuteWithCapture(command, output, &error, flags, env);
bf31fa26
VZ
710}
711
c5f0d1f9 712// ----------------------------------------------------------------------------
fad92e2f 713// Id functions
c5f0d1f9
DE
714// ----------------------------------------------------------------------------
715
c5f0d1f9
DE
716// Id generation
717static long wxCurrentId = 100;
718
719long wxNewId()
720{
721 // skip the part of IDs space that contains hard-coded values:
722 if (wxCurrentId == wxID_LOWEST)
723 wxCurrentId = wxID_HIGHEST + 1;
724
725 return wxCurrentId++;
726}
727
728long
729wxGetCurrentId(void) { return wxCurrentId; }
730
731void
732wxRegisterId (long id)
733{
734 if (id >= wxCurrentId)
735 wxCurrentId = id + 1;
736}
737
fe5f448f
RR
738// ----------------------------------------------------------------------------
739// wxQsort, adapted by RR to allow user_data
740// ----------------------------------------------------------------------------
741
742/* This file is part of the GNU C Library.
743 Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
11fe6505 744
fe5f448f
RR
745 Douglas Schmidt kindly gave permission to relicence the
746 code under the wxWindows licence:
11fe6505 747
fe5f448f
RR
748From: "Douglas C. Schmidt" <schmidt@dre.vanderbilt.edu>
749To: Robert Roebling <robert.roebling@uni-ulm.de>
11fe6505 750Subject: Re: qsort licence
fe5f448f
RR
751Date: Mon, 23 Jul 2007 03:44:25 -0500
752Sender: schmidt@dre.vanderbilt.edu
753Message-Id: <20070723084426.64F511000A8@tango.dre.vanderbilt.edu>
754
755Hi Robert,
756
757> [...] I'm asking if you'd be willing to relicence your code
758> under the wxWindows licence. [...]
759
760That's fine with me [...]
761
762Thanks,
763
764 Doug */
765
766
767/* Byte-wise swap two items of size SIZE. */
11fe6505 768#define SWAP(a, b, size) \
fad92e2f
FM
769 do \
770 { \
771 register size_t __size = (size); \
772 register char *__a = (a), *__b = (b); \
11fe6505 773 do \
fad92e2f
FM
774 { \
775 char __tmp = *__a; \
11fe6505 776 *__a++ = *__b; \
fad92e2f
FM
777 *__b++ = __tmp; \
778 } while (--__size > 0); \
fe5f448f
RR
779 } while (0)
780
781/* Discontinue quicksort algorithm when partition gets below this size.
782 This particular magic number was chosen to work best on a Sun 4/260. */
783#define MAX_THRESH 4
784
785/* Stack node declarations used to store unfulfilled partition obligations. */
786typedef struct
787 {
788 char *lo;
789 char *hi;
790 } stack_node;
791
792/* The next 4 #defines implement a very fast in-line stack abstraction. */
11fe6505 793#define STACK_SIZE (8 * sizeof(unsigned long int))
e71bf8b2
VZ
794#define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
795#define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
796#define STACK_NOT_EMPTY (stack < top)
fe5f448f
RR
797
798
799/* Order size using quicksort. This implementation incorporates
800 four optimizations discussed in Sedgewick:
801
802 1. Non-recursive, using an explicit stack of pointer that store the
803 next array partition to sort. To save time, this maximum amount
804 of space required to store an array of MAX_INT is allocated on the
805 stack. Assuming a 32-bit integer, this needs only 32 *
806 sizeof(stack_node) == 136 bits. Pretty cheap, actually.
807
808 2. Chose the pivot element using a median-of-three decision tree.
809 This reduces the probability of selecting a bad pivot value and
810 eliminates certain extraneous comparisons.
811
812 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
813 insertion sort to order the MAX_THRESH items within each partition.
814 This is a big win, since insertion sort is faster for small, mostly
815 sorted array segments.
816
817 4. The larger of the two sub-partitions is always pushed onto the
818 stack first, with the algorithm then concentrating on the
819 smaller partition. This *guarantees* no more than log (n)
820 stack size is needed (actually O(1) in this case)! */
821
4878fbb8 822void wxQsort(void* pbase, size_t total_elems,
449cc351 823 size_t size, wxSortCallback cmp, const void* user_data)
fe5f448f
RR
824{
825 register char *base_ptr = (char *) pbase;
826 const size_t max_thresh = MAX_THRESH * size;
827
828 if (total_elems == 0)
829 /* Avoid lossage with unsigned arithmetic below. */
830 return;
831
832 if (total_elems > MAX_THRESH)
833 {
834 char *lo = base_ptr;
835 char *hi = &lo[size * (total_elems - 1)];
836 stack_node stack[STACK_SIZE];
837 stack_node *top = stack;
838
839 PUSH (NULL, NULL);
840
841 while (STACK_NOT_EMPTY)
842 {
843 char *left_ptr;
844 char *right_ptr;
845
11fe6505
VZ
846 /* Select median value from among LO, MID, and HI. Rearrange
847 LO and HI so the three values are sorted. This lowers the
848 probability of picking a pathological pivot value and
849 skips a comparison for both the LEFT_PTR and RIGHT_PTR. */
850
851 char *mid = lo + size * ((hi - lo) / size >> 1);
852
853 if ((*cmp) ((void *) mid, (void *) lo, user_data) < 0)
854 SWAP (mid, lo, size);
855 if ((*cmp) ((void *) hi, (void *) mid, user_data) < 0)
856 SWAP (mid, hi, size);
857 else
858 goto jump_over;
859 if ((*cmp) ((void *) mid, (void *) lo, user_data) < 0)
860 SWAP (mid, lo, size);
861 jump_over:;
862 left_ptr = lo + size;
863 right_ptr = hi - size;
864
865 /* Here's the famous ``collapse the walls'' section of quicksort.
866 Gotta like those tight inner loops! They are the main reason
867 that this algorithm runs much faster than others. */
868 do
869 {
870 while ((*cmp) ((void *) left_ptr, (void *) mid, user_data) < 0)
871 left_ptr += size;
872
873 while ((*cmp) ((void *) mid, (void *) right_ptr, user_data) < 0)
874 right_ptr -= size;
875
876 if (left_ptr < right_ptr)
877 {
878 SWAP (left_ptr, right_ptr, size);
879 if (mid == left_ptr)
880 mid = right_ptr;
881 else if (mid == right_ptr)
882 mid = left_ptr;
883 left_ptr += size;
884 right_ptr -= size;
885 }
886 else if (left_ptr == right_ptr)
887 {
888 left_ptr += size;
889 right_ptr -= size;
890 break;
891 }
892 }
893 while (left_ptr <= right_ptr);
fe5f448f
RR
894
895 /* Set up pointers for next iteration. First determine whether
896 left and right partitions are below the threshold size. If so,
897 ignore one or both. Otherwise, push the larger partition's
898 bounds on the stack and continue sorting the smaller one. */
899
900 if ((size_t) (right_ptr - lo) <= max_thresh)
901 {
902 if ((size_t) (hi - left_ptr) <= max_thresh)
11fe6505 903 /* Ignore both small partitions. */
fe5f448f
RR
904 POP (lo, hi);
905 else
11fe6505 906 /* Ignore small left partition. */
fe5f448f
RR
907 lo = left_ptr;
908 }
909 else if ((size_t) (hi - left_ptr) <= max_thresh)
11fe6505 910 /* Ignore small right partition. */
fe5f448f
RR
911 hi = right_ptr;
912 else if ((right_ptr - lo) > (hi - left_ptr))
913 {
11fe6505 914 /* Push larger left partition indices. */
fe5f448f
RR
915 PUSH (lo, right_ptr);
916 lo = left_ptr;
917 }
918 else
919 {
11fe6505 920 /* Push larger right partition indices. */
fe5f448f
RR
921 PUSH (left_ptr, hi);
922 hi = right_ptr;
923 }
924 }
925 }
926
927 /* Once the BASE_PTR array is partially sorted by quicksort the rest
928 is completely sorted using insertion sort, since this is efficient
929 for partitions below MAX_THRESH size. BASE_PTR points to the beginning
930 of the array to sort, and END_PTR points at the very last element in
931 the array (*not* one beyond it!). */
932
fe5f448f
RR
933 {
934 char *const end_ptr = &base_ptr[size * (total_elems - 1)];
935 char *tmp_ptr = base_ptr;
e71bf8b2
VZ
936 char *thresh = base_ptr + max_thresh;
937 if ( thresh > end_ptr )
938 thresh = end_ptr;
fe5f448f
RR
939 register char *run_ptr;
940
941 /* Find smallest element in first threshold and place it at the
942 array's beginning. This is the smallest array element,
943 and the operation speeds up insertion sort's inner loop. */
944
945 for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size)
946 if ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, user_data) < 0)
947 tmp_ptr = run_ptr;
948
949 if (tmp_ptr != base_ptr)
950 SWAP (tmp_ptr, base_ptr, size);
951
952 /* Insertion sort, running from left-hand-side up to right-hand-side. */
953
954 run_ptr = base_ptr + size;
955 while ((run_ptr += size) <= end_ptr)
956 {
11fe6505
VZ
957 tmp_ptr = run_ptr - size;
958 while ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, user_data) < 0)
959 tmp_ptr -= size;
fe5f448f 960
11fe6505 961 tmp_ptr += size;
fe5f448f
RR
962 if (tmp_ptr != run_ptr)
963 {
964 char *trav;
965
11fe6505
VZ
966 trav = run_ptr + size;
967 while (--trav >= run_ptr)
fe5f448f
RR
968 {
969 char c = *trav;
970 char *hi, *lo;
971
972 for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo)
973 *hi = *lo;
974 *hi = c;
975 }
976 }
977 }
978 }
979}
980
fad92e2f 981#endif // wxUSE_BASE
fe5f448f
RR
982
983
c5f0d1f9
DE
984
985// ============================================================================
986// GUI-only functions from now on
987// ============================================================================
988
989#if wxUSE_GUI
990
f9837e46
VZ
991// this function is only really implemented for X11-based ports, including GTK1
992// (GTK2 sets detectable auto-repeat automatically anyhow)
993#if !(defined(__WXX11__) || defined(__WXMOTIF__) || \
994 (defined(__WXGTK__) && !defined(__WXGTK20__)))
ef3da29b
VZ
995bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag) )
996{
f9837e46 997 return true;
ef3da29b 998}
f9837e46 999#endif // !X11-based port
ef3da29b 1000
498a1eeb
RN
1001// ----------------------------------------------------------------------------
1002// Launch default browser
1003// ----------------------------------------------------------------------------
1004
d98a58c5 1005#if defined(__WINDOWS__)
5ccb95f6 1006
50a2e26f
FM
1007// implemented in a port-specific utils source file:
1008bool wxDoLaunchDefaultBrowser(const wxString& url, const wxString& scheme, int flags);
42d0df00 1009
7e86b10b 1010#elif defined(__WXX11__) || defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXCOCOA__) || \
766fc092 1011 (defined(__WXOSX__) )
42d0df00 1012
50a2e26f
FM
1013// implemented in a port-specific utils source file:
1014bool wxDoLaunchDefaultBrowser(const wxString& url, int flags);
498a1eeb 1015
f728025e 1016#else
ae46a7fd 1017
50a2e26f
FM
1018// a "generic" implementation:
1019bool wxDoLaunchDefaultBrowser(const wxString& url, int flags)
1020{
1021 // on other platforms try to use mime types or wxExecute...
889fda0c 1022
13a1e96f
DS
1023 bool ok = false;
1024 wxString cmd;
1025
1b1b5318 1026#if wxUSE_MIMETYPE
9a83f860 1027 wxFileType *ft = wxTheMimeTypesManager->GetFileTypeFromExtension(wxT("html"));
7999124f 1028 if ( ft )
657a7545 1029 {
7999124f
VZ
1030 wxString mt;
1031 ft->GetMimeType(&mt);
498a1eeb 1032
13a1e96f 1033 ok = ft->GetOpenCommand(&cmd, wxFileType::MessageParameters(url));
7999124f 1034 delete ft;
498a1eeb 1035 }
1b1b5318 1036#endif // wxUSE_MIMETYPE
13a1e96f
DS
1037
1038 if ( !ok || cmd.empty() )
2830b4a4 1039 {
13a1e96f 1040 // fallback to checking for the BROWSER environment variable
50a2e26f 1041 if ( !wxGetEnv(wxT("BROWSER"), &cmd) || cmd.empty() )
9a83f860 1042 cmd << wxT(' ') << url;
2830b4a4 1043 }
13a1e96f
DS
1044
1045 ok = ( !cmd.empty() && wxExecute(cmd) );
1046 if (ok)
1047 return ok;
1048
1049 // no file type for HTML extension
5519074c 1050 wxLogError(_("No default application configured for HTML files."));
13a1e96f 1051
50a2e26f
FM
1052 return false;
1053}
1054#endif
1055
1056static bool DoLaunchDefaultBrowserHelper(const wxString& urlOrig, int flags)
1057{
1058 // NOTE: we don't have to care about the wxBROWSER_NOBUSYCURSOR flag
1059 // as it was already handled by wxLaunchDefaultBrowser
1060
1061 wxUnusedVar(flags);
1062
1063 wxString url(urlOrig), scheme;
1064 wxURI uri(url);
1065
1066 // this check is useful to avoid that wxURI recognizes as scheme parts of
1067 // the filename, in case urlOrig is a local filename
1068 // (e.g. "C:\\test.txt" when parsed by wxURI reports a scheme == "C")
02b94f4e 1069 bool hasValidScheme = uri.HasScheme() && uri.GetScheme().length() > 1;
50a2e26f 1070
d98a58c5 1071#if defined(__WINDOWS__)
50a2e26f
FM
1072
1073 // NOTE: when testing wxMSW's wxLaunchDefaultBrowser all possible forms
1074 // of the URL/flags should be tested; e.g.:
1075 //
1076 // for (int i=0; i<2; i++)
1077 // {
4290e8ed 1078 // // test arguments without a valid URL scheme:
50a2e26f
FM
1079 // wxLaunchDefaultBrowser("C:\\test.txt", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1080 // wxLaunchDefaultBrowser("wxwidgets.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
4290e8ed
FM
1081 //
1082 // // test arguments with different valid schemes:
50a2e26f
FM
1083 // wxLaunchDefaultBrowser("file:/C%3A/test.txt", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1084 // wxLaunchDefaultBrowser("http://wxwidgets.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
4290e8ed 1085 // wxLaunchDefaultBrowser("mailto:user@host.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
50a2e26f
FM
1086 // }
1087 // (assuming you have a C:\test.txt file)
1088
1089 if ( !hasValidScheme )
1090 {
1091 if (wxFileExists(urlOrig) || wxDirExists(urlOrig))
1092 {
1093 scheme = "file";
1094 // do not prepend the file scheme to the URL as ShellExecuteEx() doesn't like it
1095 }
1096 else
1097 {
1098 url.Prepend(wxS("http://"));
1099 scheme = "http";
1100 }
1101 }
1102 else if ( hasValidScheme )
1103 {
1104 scheme = uri.GetScheme();
1105
1106 if ( uri.GetScheme() == "file" )
1107 {
00aa89f4
VZ
1108 // TODO: extract URLToFileName() to some always compiled in
1109 // function
1110#if wxUSE_FILESYSTEM
4290e8ed 1111 // ShellExecuteEx() doesn't like the "file" scheme when opening local files;
50a2e26f
FM
1112 // remove it
1113 url = wxFileSystem::URLToFileName(url).GetFullPath();
00aa89f4 1114#endif // wxUSE_FILESYSTEM
50a2e26f
FM
1115 }
1116 }
1117
1118 if (wxDoLaunchDefaultBrowser(url, scheme, flags))
1119 return true;
1120 //else: call wxLogSysError
1121#else
1122 if ( !hasValidScheme )
1123 {
1124 // set the scheme of url to "http" or "file" if it does not have one
1125 if (wxFileExists(urlOrig) || wxDirExists(urlOrig))
1126 url.Prepend(wxS("file://"));
1127 else
1128 url.Prepend(wxS("http://"));
1129 }
1130
1131 if (wxDoLaunchDefaultBrowser(url, flags))
1132 return true;
1133 //else: call wxLogSysError
1134#endif
532d575b 1135
5519074c 1136 wxLogSysError(_("Failed to open URL \"%s\" in default browser."),
7999124f 1137 url.c_str());
657a7545 1138
7999124f 1139 return false;
498a1eeb
RN
1140}
1141
f75e0c15
VZ
1142bool wxLaunchDefaultBrowser(const wxString& url, int flags)
1143{
50a2e26f
FM
1144 // NOTE: as documented, "url" may be both a real well-formed URL
1145 // and a local file name
1146
f75e0c15 1147 if ( flags & wxBROWSER_NOBUSYCURSOR )
50a2e26f 1148 return DoLaunchDefaultBrowserHelper(url, flags);
f75e0c15
VZ
1149
1150 wxBusyCursor bc;
50a2e26f 1151 return DoLaunchDefaultBrowserHelper(url, flags);
f75e0c15
VZ
1152}
1153
e90c1d2a 1154// ----------------------------------------------------------------------------
7c072018 1155// Menu accelerators related functions
e90c1d2a
VZ
1156// ----------------------------------------------------------------------------
1157
50a2e26f 1158#if WXWIN_COMPATIBILITY_2_6
7c072018 1159wxChar *wxStripMenuCodes(const wxChar *in, wxChar *out)
e90c1d2a 1160{
9a6384ca 1161#if wxUSE_MENUS
52af3158 1162 wxString s = wxMenuItem::GetLabelText(in);
9a6384ca
WS
1163#else
1164 wxString str(in);
1165 wxString s = wxStripMenuCodes(str);
1166#endif // wxUSE_MENUS
7c072018
VZ
1167 if ( out )
1168 {
1169 // go smash their buffer if it's not big enough - I love char * params
1170 memcpy(out, s.c_str(), s.length() * sizeof(wxChar));
1171 }
1172 else
1173 {
f526f752
MB
1174 out = new wxChar[s.length() + 1];
1175 wxStrcpy(out, s.c_str());
7c072018
VZ
1176 }
1177
1178 return out;
e90c1d2a 1179}
50a2e26f 1180#endif
e90c1d2a 1181
74639764 1182wxString wxStripMenuCodes(const wxString& in, int flags)
e90c1d2a 1183{
9a83f860 1184 wxASSERT_MSG( flags, wxT("this is useless to call without any flags") );
74639764 1185
7c072018 1186 wxString out;
79f585d9 1187
7c072018
VZ
1188 size_t len = in.length();
1189 out.reserve(len);
79f585d9 1190
c833f0cd 1191 for ( wxString::const_iterator it = in.begin(); it != in.end(); ++it )
7c072018 1192 {
c833f0cd 1193 wxChar ch = *it;
9a83f860 1194 if ( (flags & wxStrip_Mnemonics) && ch == wxT('&') )
cd6ce4a9 1195 {
7c072018
VZ
1196 // skip it, it is used to introduce the accel char (or to quote
1197 // itself in which case it should still be skipped): note that it
1198 // can't be the last character of the string
c833f0cd 1199 if ( ++it == in.end() )
79f585d9 1200 {
9a83f860 1201 wxLogDebug(wxT("Invalid menu string '%s'"), in.c_str());
7c072018
VZ
1202 }
1203 else
1204 {
1205 // use the next char instead
c833f0cd 1206 ch = *it;
79f585d9 1207 }
cd6ce4a9 1208 }
9a83f860 1209 else if ( (flags & wxStrip_Accel) && ch == wxT('\t') )
79f585d9 1210 {
7c072018
VZ
1211 // everything after TAB is accel string, exit the loop
1212 break;
79f585d9 1213 }
7c072018
VZ
1214
1215 out += ch;
225fe9d6
VZ
1216 }
1217
7c072018 1218 return out;
cd6ce4a9
VZ
1219}
1220
cbc66a27 1221// ----------------------------------------------------------------------------
7c072018 1222// Window search functions
cbc66a27
VZ
1223// ----------------------------------------------------------------------------
1224
7c072018
VZ
1225/*
1226 * If parent is non-NULL, look through children for a label or title
1227 * matching the specified string. If NULL, look through all top-level windows.
1228 *
1229 */
e2a6f233 1230
7c072018
VZ
1231wxWindow *
1232wxFindWindowByLabel (const wxString& title, wxWindow * parent)
134677bd 1233{
7c072018
VZ
1234 return wxWindow::FindWindowByLabel( title, parent );
1235}
b829bf55 1236
b829bf55 1237
7c072018
VZ
1238/*
1239 * If parent is non-NULL, look through children for a name
1240 * matching the specified string. If NULL, look through all top-level windows.
1241 *
1242 */
134677bd 1243
7c072018
VZ
1244wxWindow *
1245wxFindWindowByName (const wxString& name, wxWindow * parent)
2c18f21d 1246{
7c072018 1247 return wxWindow::FindWindowByName( name, parent );
2c18f21d
VS
1248}
1249
cb719f2e 1250// Returns menu item id or wxNOT_FOUND if none.
7c072018 1251int
8d22935d
VZ
1252wxFindMenuItemId(wxFrame *frame,
1253 const wxString& menuString,
1254 const wxString& itemString)
e2a6f233 1255{
7c072018 1256#if wxUSE_MENUS
9a6384ca
WS
1257 wxMenuBar *menuBar = frame->GetMenuBar ();
1258 if ( menuBar )
1259 return menuBar->FindMenuItem (menuString, itemString);
8d22935d
VZ
1260#else // !wxUSE_MENUS
1261 wxUnusedVar(frame);
1262 wxUnusedVar(menuString);
1263 wxUnusedVar(itemString);
1264#endif // wxUSE_MENUS/!wxUSE_MENUS
0fb67cd1 1265
9a6384ca 1266 return wxNOT_FOUND;
e2a6f233
JS
1267}
1268
7c072018
VZ
1269// Try to find the deepest child that contains 'pt'.
1270// We go backwards, to try to allow for controls that are spacially
1271// within other controls, but are still siblings (e.g. buttons within
1272// static boxes). Static boxes are likely to be created _before_ controls
1273// that sit inside them.
1274wxWindow* wxFindWindowAtPoint(wxWindow* win, const wxPoint& pt)
e2a6f233 1275{
7c072018
VZ
1276 if (!win->IsShown())
1277 return NULL;
0fb67cd1 1278
7c072018
VZ
1279 // Hack for wxNotebook case: at least in wxGTK, all pages
1280 // claim to be shown, so we must only deal with the selected one.
1281#if wxUSE_NOTEBOOK
345c78ca 1282 if (wxDynamicCast(win, wxNotebook))
e2a6f233 1283 {
7c072018
VZ
1284 wxNotebook* nb = (wxNotebook*) win;
1285 int sel = nb->GetSelection();
1286 if (sel >= 0)
1287 {
1288 wxWindow* child = nb->GetPage(sel);
1289 wxWindow* foundWin = wxFindWindowAtPoint(child, pt);
1290 if (foundWin)
1291 return foundWin;
1292 }
e2a6f233 1293 }
7c072018 1294#endif
0fb67cd1 1295
df5168c4 1296 wxWindowList::compatibility_iterator node = win->GetChildren().GetLast();
7c072018
VZ
1297 while (node)
1298 {
1299 wxWindow* child = node->GetData();
1300 wxWindow* foundWin = wxFindWindowAtPoint(child, pt);
1301 if (foundWin)
1302 return foundWin;
1303 node = node->GetPrevious();
1304 }
1305
1306 wxPoint pos = win->GetPosition();
1307 wxSize sz = win->GetSize();
7aa7d2d4 1308 if ( !win->IsTopLevel() && win->GetParent() )
7c072018
VZ
1309 {
1310 pos = win->GetParent()->ClientToScreen(pos);
1311 }
1312
1313 wxRect rect(pos, sz);
22a35096 1314 if (rect.Contains(pt))
7c072018 1315 return win;
622eb786
VZ
1316
1317 return NULL;
0fb67cd1
VZ
1318}
1319
7c072018 1320wxWindow* wxGenericFindWindowAtPoint(const wxPoint& pt)
0fb67cd1 1321{
7c072018
VZ
1322 // Go backwards through the list since windows
1323 // on top are likely to have been appended most
1324 // recently.
df5168c4 1325 wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetLast();
7c072018
VZ
1326 while (node)
1327 {
1328 wxWindow* win = node->GetData();
1329 wxWindow* found = wxFindWindowAtPoint(win, pt);
1330 if (found)
1331 return found;
1332 node = node->GetPrevious();
1333 }
1334 return NULL;
1335}
0fb67cd1 1336
7c072018
VZ
1337// ----------------------------------------------------------------------------
1338// GUI helpers
1339// ----------------------------------------------------------------------------
0fb67cd1 1340
7c072018
VZ
1341/*
1342 * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp
1343 * since otherwise the generic code may be pulled in unnecessarily.
1344 */
0fb67cd1 1345
7c072018 1346#if wxUSE_MSGDLG
0fb67cd1 1347
7c072018
VZ
1348int wxMessageBox(const wxString& message, const wxString& caption, long style,
1349 wxWindow *parent, int WXUNUSED(x), int WXUNUSED(y) )
0fb67cd1 1350{
7e3204b4
VZ
1351 // add the appropriate icon unless this was explicitly disabled by use of
1352 // wxICON_NONE
1353 if ( !(style & wxICON_NONE) && !(style & wxICON_MASK) )
53a6ac21 1354 {
7e3204b4 1355 style |= style & wxYES ? wxICON_QUESTION : wxICON_INFORMATION;
53a6ac21
DS
1356 }
1357
7e3204b4 1358 wxMessageDialog dialog(parent, message, caption, style);
0fb67cd1 1359
7c072018
VZ
1360 int ans = dialog.ShowModal();
1361 switch ( ans )
1362 {
1363 case wxID_OK:
1364 return wxOK;
1365 case wxID_YES:
1366 return wxYES;
1367 case wxID_NO:
1368 return wxNO;
1369 case wxID_CANCEL:
1370 return wxCANCEL;
7112cdd1
VZ
1371 case wxID_HELP:
1372 return wxHELP;
7c072018 1373 }
0fb67cd1 1374
9a83f860 1375 wxFAIL_MSG( wxT("unexpected return code from wxMessageDialog") );
0fb67cd1 1376
7c072018 1377 return wxCANCEL;
e2a6f233
JS
1378}
1379
ccec9093 1380wxVersionInfo wxGetLibraryVersionInfo()
8cf304f8
VZ
1381{
1382 // don't translate these strings, they're for diagnostics purposes only
1383 wxString msg;
32be10a4
VZ
1384 msg.Printf(wxS("wxWidgets Library (%s port)\n")
1385 wxS("Version %d.%d.%d (Unicode: %s, debug level: %d),\n")
1386 wxS("compiled at %s %s\n\n")
1387 wxS("Runtime version of toolkit used is %d.%d.\n"),
1388 wxPlatformInfo::Get().GetPortIdName(),
8cf304f8
VZ
1389 wxMAJOR_VERSION,
1390 wxMINOR_VERSION,
1391 wxRELEASE_NUMBER,
32be10a4
VZ
1392#if wxUSE_UNICODE_UTF8
1393 "UTF-8",
1394#elif wxUSE_UNICODE
1395 "wchar_t",
8cf304f8 1396#else
32be10a4 1397 "none",
8cf304f8 1398#endif
32be10a4 1399 wxDEBUG_LEVEL,
8cf304f8
VZ
1400 __TDATE__,
1401 __TTIME__,
1402 wxPlatformInfo::Get().GetToolkitMajorVersion(),
32be10a4
VZ
1403 wxPlatformInfo::Get().GetToolkitMinorVersion()
1404 );
1405
8cf304f8 1406#ifdef __WXGTK__
32be10a4
VZ
1407 msg += wxString::Format("Compile-time GTK+ version is %d.%d.%d.\n",
1408 GTK_MAJOR_VERSION,
1409 GTK_MINOR_VERSION,
1410 GTK_MICRO_VERSION);
1411#endif // __WXGTK__
1412
ccec9093
VZ
1413 return wxVersionInfo(wxS("wxWidgets"),
1414 wxMAJOR_VERSION,
1415 wxMINOR_VERSION,
1416 wxRELEASE_NUMBER,
1417 msg,
8fcf7cd0 1418 wxS("Copyright (c) 1995-2011 wxWidgets team"));
ccec9093
VZ
1419}
1420
1421void wxInfoMessageBox(wxWindow* parent)
1422{
1423 wxVersionInfo info = wxGetLibraryVersionInfo();
1424 wxString msg = info.ToString();
1425
1426 msg << wxS("\n") << info.GetCopyright();
32be10a4 1427
9a83f860 1428 wxMessageBox(msg, wxT("wxWidgets information"),
8cf304f8
VZ
1429 wxICON_INFORMATION | wxOK,
1430 parent);
1431}
1432
7c072018 1433#endif // wxUSE_MSGDLG
518b5d2f 1434
7c072018 1435#if wxUSE_TEXTDLG
518b5d2f 1436
7c072018
VZ
1437wxString wxGetTextFromUser(const wxString& message, const wxString& caption,
1438 const wxString& defaultValue, wxWindow *parent,
13d13a9e 1439 wxCoord x, wxCoord y, bool centre )
7c072018
VZ
1440{
1441 wxString str;
13d13a9e
WS
1442 long style = wxTextEntryDialogStyle;
1443
1444 if (centre)
1445 style |= wxCENTRE;
1446 else
1447 style &= ~wxCENTRE;
1448
1449 wxTextEntryDialog dialog(parent, message, caption, defaultValue, style, wxPoint(x, y));
1450
7c072018
VZ
1451 if (dialog.ShowModal() == wxID_OK)
1452 {
1453 str = dialog.GetValue();
1454 }
0fb67cd1 1455
7c072018 1456 return str;
518b5d2f
VZ
1457}
1458
7c072018
VZ
1459wxString wxGetPasswordFromUser(const wxString& message,
1460 const wxString& caption,
1461 const wxString& defaultValue,
b3bb2a74
KH
1462 wxWindow *parent,
1463 wxCoord x, wxCoord y, bool centre )
96c5bd7f 1464{
7c072018 1465 wxString str;
b3bb2a74
KH
1466 long style = wxTextEntryDialogStyle;
1467
1468 if (centre)
1469 style |= wxCENTRE;
1470 else
1471 style &= ~wxCENTRE;
1472
12cfa304
KH
1473 wxPasswordEntryDialog dialog(parent, message, caption, defaultValue,
1474 style, wxPoint(x, y));
7c072018
VZ
1475 if ( dialog.ShowModal() == wxID_OK )
1476 {
1477 str = dialog.GetValue();
1478 }
96c5bd7f 1479
7c072018
VZ
1480 return str;
1481}
96c5bd7f 1482
7c072018 1483#endif // wxUSE_TEXTDLG
96c5bd7f 1484
7c072018
VZ
1485// ----------------------------------------------------------------------------
1486// wxSafeYield and supporting functions
1487// ----------------------------------------------------------------------------
2b5f62a0 1488
7c072018
VZ
1489void wxEnableTopLevelWindows(bool enable)
1490{
df5168c4 1491 wxWindowList::compatibility_iterator node;
7c072018
VZ
1492 for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
1493 node->GetData()->Enable(enable);
1494}
2b5f62a0 1495
902ddbfd
SC
1496#if defined(__WXOSX__) && wxOSX_USE_COCOA
1497
1498// defined in evtloop.mm
1499
1500#else
1501
2ecd1756
VZ
1502wxWindowDisabler::wxWindowDisabler(bool disable)
1503{
1504 m_disabled = disable;
1505 if ( disable )
1506 DoDisable();
1507}
1508
7c072018 1509wxWindowDisabler::wxWindowDisabler(wxWindow *winToSkip)
2ecd1756
VZ
1510{
1511 m_disabled = true;
1512 DoDisable(winToSkip);
1513}
1514
1515void wxWindowDisabler::DoDisable(wxWindow *winToSkip)
7c072018
VZ
1516{
1517 // remember the top level windows which were already disabled, so that we
1518 // don't reenable them later
1519 m_winDisabled = NULL;
1520
df5168c4 1521 wxWindowList::compatibility_iterator node;
7c072018 1522 for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
2b5f62a0 1523 {
7c072018
VZ
1524 wxWindow *winTop = node->GetData();
1525 if ( winTop == winToSkip )
1526 continue;
2b5f62a0 1527
7c072018
VZ
1528 // we don't need to disable the hidden or already disabled windows
1529 if ( winTop->IsEnabled() && winTop->IsShown() )
2b5f62a0 1530 {
7c072018 1531 winTop->Disable();
2b5f62a0
VZ
1532 }
1533 else
1534 {
7c072018
VZ
1535 if ( !m_winDisabled )
1536 {
1537 m_winDisabled = new wxWindowList;
1538 }
1539
1540 m_winDisabled->Append(winTop);
2b5f62a0
VZ
1541 }
1542 }
2b5f62a0
VZ
1543}
1544
7c072018 1545wxWindowDisabler::~wxWindowDisabler()
cd6ce4a9 1546{
2ecd1756
VZ
1547 if ( !m_disabled )
1548 return;
1549
df5168c4 1550 wxWindowList::compatibility_iterator node;
7c072018 1551 for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
cd6ce4a9 1552 {
7c072018
VZ
1553 wxWindow *winTop = node->GetData();
1554 if ( !m_winDisabled || !m_winDisabled->Find(winTop) )
cd6ce4a9 1555 {
7c072018 1556 winTop->Enable();
cd6ce4a9 1557 }
7c072018 1558 //else: had been already disabled, don't reenable
cd6ce4a9 1559 }
f6bcfd97 1560
7c072018 1561 delete m_winDisabled;
f6bcfd97
BP
1562}
1563
902ddbfd
SC
1564#endif
1565
7c072018
VZ
1566// Yield to other apps/messages and disable user input to all windows except
1567// the given one
1568bool wxSafeYield(wxWindow *win, bool onlyIfNeeded)
f6bcfd97 1569{
7c072018 1570 wxWindowDisabler wd(win);
21709999 1571
7c072018
VZ
1572 bool rc;
1573 if (onlyIfNeeded)
1574 rc = wxYieldIfNeeded();
1575 else
1576 rc = wxYield();
8461e4c2 1577
7c072018 1578 return rc;
8461e4c2
VZ
1579}
1580
fad92e2f
FM
1581// ----------------------------------------------------------------------------
1582// wxApp::Yield() wrappers for backwards compatibility
1583// ----------------------------------------------------------------------------
1584
1585bool wxYield()
8461e4c2 1586{
fad92e2f
FM
1587 return wxTheApp && wxTheApp->Yield();
1588}
1589
1590bool wxYieldIfNeeded()
1591{
1592 return wxTheApp && wxTheApp->Yield(true);
8461e4c2 1593}
7c072018
VZ
1594
1595#endif // wxUSE_GUI