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