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