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