]> git.saurik.com Git - wxWidgets.git/blame - src/common/utilscmn.cpp
Skip spurious blank JavaScript events in wxWebView.
[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
586 // declared in several common systems (some BSDs, Solaris with native CC).
eeb415ec 587 extern char **environ;
14c350df 588
1f4c7e79 589 char **env = environ;
164db92c
VZ
590#endif
591
592 if ( env )
593 {
594 wxString name,
595 value;
596 while ( *env )
597 {
598 const wxString var(*env);
599
600 name = var.BeforeFirst(wxS('='), &value);
601
602 (*map)[name] = value;
603
604 env++;
605 }
606
607 return true;
608 }
609
610 return false;
611}
612
e90c1d2a 613// ----------------------------------------------------------------------------
7c072018 614// wxExecute
e90c1d2a 615// ----------------------------------------------------------------------------
ead7ce10 616
7c072018
VZ
617// wxDoExecuteWithCapture() helper: reads an entire stream into one array
618//
cb719f2e 619// returns true if ok, false if error
7c072018
VZ
620#if wxUSE_STREAMS
621static bool ReadAll(wxInputStream *is, wxArrayString& output)
dfad0599 622{
9a83f860 623 wxCHECK_MSG( is, false, wxT("NULL stream in wxExecute()?") );
dfad0599 624
7c072018
VZ
625 // the stream could be already at EOF or in wxSTREAM_BROKEN_PIPE state
626 is->Reset();
1e6feb95 627
7c072018 628 wxTextInputStream tis(*is);
1e6feb95 629
8bdc8a9c 630 for ( ;; )
d2f50933 631 {
7c072018 632 wxString line = tis.ReadLine();
8bdc8a9c
VZ
633
634 // check for EOF before other errors as it's not really an error
7c072018 635 if ( is->Eof() )
8bdc8a9c
VZ
636 {
637 // add the last, possibly incomplete, line
638 if ( !line.empty() )
639 output.Add(line);
7c072018 640 break;
8bdc8a9c 641 }
7c072018 642
8bdc8a9c 643 // any other error is fatal
7c072018 644 if ( !*is )
8bdc8a9c
VZ
645 return false;
646
647 output.Add(line);
d2f50933
VZ
648 }
649
8bdc8a9c 650 return true;
dfad0599 651}
7c072018 652#endif // wxUSE_STREAMS
d2f50933 653
7c072018
VZ
654// this is a private function because it hasn't a clean interface: the first
655// array is passed by reference, the second by pointer - instead we have 2
656// public versions of wxExecute() below
657static long wxDoExecuteWithCapture(const wxString& command,
658 wxArrayString& output,
4d172154 659 wxArrayString* error,
164db92c
VZ
660 int flags,
661 const wxExecuteEnv *env)
d2f50933 662{
7c072018
VZ
663 // create a wxProcess which will capture the output
664 wxProcess *process = new wxProcess;
665 process->Redirect();
dfad0599 666
164db92c 667 long rc = wxExecute(command, wxEXEC_SYNC | flags, process, env);
1e6feb95 668
7c072018
VZ
669#if wxUSE_STREAMS
670 if ( rc != -1 )
bf31fa26 671 {
7c072018
VZ
672 if ( !ReadAll(process->GetInputStream(), output) )
673 rc = -1;
91b4c08d 674
7c072018
VZ
675 if ( error )
676 {
677 if ( !ReadAll(process->GetErrorStream(), *error) )
678 rc = -1;
679 }
91b4c08d 680
7c072018 681 }
e70ba80d
WS
682#else
683 wxUnusedVar(output);
684 wxUnusedVar(error);
685#endif // wxUSE_STREAMS/!wxUSE_STREAMS
91b4c08d 686
7c072018 687 delete process;
1e6feb95 688
7c072018 689 return rc;
7c072018 690}
bf31fa26 691
164db92c
VZ
692long wxExecute(const wxString& command, wxArrayString& output, int flags,
693 const wxExecuteEnv *env)
bf31fa26 694{
164db92c 695 return wxDoExecuteWithCapture(command, output, NULL, flags, env);
7c072018 696}
bf31fa26 697
7c072018
VZ
698long wxExecute(const wxString& command,
699 wxArrayString& output,
4d172154 700 wxArrayString& error,
164db92c
VZ
701 int flags,
702 const wxExecuteEnv *env)
7c072018 703{
164db92c 704 return wxDoExecuteWithCapture(command, output, &error, flags, env);
bf31fa26
VZ
705}
706
c5f0d1f9 707// ----------------------------------------------------------------------------
fad92e2f 708// Id functions
c5f0d1f9
DE
709// ----------------------------------------------------------------------------
710
c5f0d1f9
DE
711// Id generation
712static long wxCurrentId = 100;
713
714long wxNewId()
715{
716 // skip the part of IDs space that contains hard-coded values:
717 if (wxCurrentId == wxID_LOWEST)
718 wxCurrentId = wxID_HIGHEST + 1;
719
720 return wxCurrentId++;
721}
722
723long
724wxGetCurrentId(void) { return wxCurrentId; }
725
726void
727wxRegisterId (long id)
728{
729 if (id >= wxCurrentId)
730 wxCurrentId = id + 1;
731}
732
fe5f448f
RR
733// ----------------------------------------------------------------------------
734// wxQsort, adapted by RR to allow user_data
735// ----------------------------------------------------------------------------
736
737/* This file is part of the GNU C Library.
738 Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
11fe6505 739
fe5f448f
RR
740 Douglas Schmidt kindly gave permission to relicence the
741 code under the wxWindows licence:
11fe6505 742
fe5f448f
RR
743From: "Douglas C. Schmidt" <schmidt@dre.vanderbilt.edu>
744To: Robert Roebling <robert.roebling@uni-ulm.de>
11fe6505 745Subject: Re: qsort licence
fe5f448f
RR
746Date: Mon, 23 Jul 2007 03:44:25 -0500
747Sender: schmidt@dre.vanderbilt.edu
748Message-Id: <20070723084426.64F511000A8@tango.dre.vanderbilt.edu>
749
750Hi Robert,
751
752> [...] I'm asking if you'd be willing to relicence your code
753> under the wxWindows licence. [...]
754
755That's fine with me [...]
756
757Thanks,
758
759 Doug */
760
761
762/* Byte-wise swap two items of size SIZE. */
11fe6505 763#define SWAP(a, b, size) \
fad92e2f
FM
764 do \
765 { \
766 register size_t __size = (size); \
767 register char *__a = (a), *__b = (b); \
11fe6505 768 do \
fad92e2f
FM
769 { \
770 char __tmp = *__a; \
11fe6505 771 *__a++ = *__b; \
fad92e2f
FM
772 *__b++ = __tmp; \
773 } while (--__size > 0); \
fe5f448f
RR
774 } while (0)
775
776/* Discontinue quicksort algorithm when partition gets below this size.
777 This particular magic number was chosen to work best on a Sun 4/260. */
778#define MAX_THRESH 4
779
780/* Stack node declarations used to store unfulfilled partition obligations. */
781typedef struct
782 {
783 char *lo;
784 char *hi;
785 } stack_node;
786
787/* The next 4 #defines implement a very fast in-line stack abstraction. */
11fe6505 788#define STACK_SIZE (8 * sizeof(unsigned long int))
e71bf8b2
VZ
789#define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
790#define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
791#define STACK_NOT_EMPTY (stack < top)
fe5f448f
RR
792
793
794/* Order size using quicksort. This implementation incorporates
795 four optimizations discussed in Sedgewick:
796
797 1. Non-recursive, using an explicit stack of pointer that store the
798 next array partition to sort. To save time, this maximum amount
799 of space required to store an array of MAX_INT is allocated on the
800 stack. Assuming a 32-bit integer, this needs only 32 *
801 sizeof(stack_node) == 136 bits. Pretty cheap, actually.
802
803 2. Chose the pivot element using a median-of-three decision tree.
804 This reduces the probability of selecting a bad pivot value and
805 eliminates certain extraneous comparisons.
806
807 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
808 insertion sort to order the MAX_THRESH items within each partition.
809 This is a big win, since insertion sort is faster for small, mostly
810 sorted array segments.
811
812 4. The larger of the two sub-partitions is always pushed onto the
813 stack first, with the algorithm then concentrating on the
814 smaller partition. This *guarantees* no more than log (n)
815 stack size is needed (actually O(1) in this case)! */
816
4878fbb8 817void wxQsort(void* pbase, size_t total_elems,
449cc351 818 size_t size, wxSortCallback cmp, const void* user_data)
fe5f448f
RR
819{
820 register char *base_ptr = (char *) pbase;
821 const size_t max_thresh = MAX_THRESH * size;
822
823 if (total_elems == 0)
824 /* Avoid lossage with unsigned arithmetic below. */
825 return;
826
827 if (total_elems > MAX_THRESH)
828 {
829 char *lo = base_ptr;
830 char *hi = &lo[size * (total_elems - 1)];
831 stack_node stack[STACK_SIZE];
832 stack_node *top = stack;
833
834 PUSH (NULL, NULL);
835
836 while (STACK_NOT_EMPTY)
837 {
838 char *left_ptr;
839 char *right_ptr;
840
11fe6505
VZ
841 /* Select median value from among LO, MID, and HI. Rearrange
842 LO and HI so the three values are sorted. This lowers the
843 probability of picking a pathological pivot value and
844 skips a comparison for both the LEFT_PTR and RIGHT_PTR. */
845
846 char *mid = lo + size * ((hi - lo) / size >> 1);
847
848 if ((*cmp) ((void *) mid, (void *) lo, user_data) < 0)
849 SWAP (mid, lo, size);
850 if ((*cmp) ((void *) hi, (void *) mid, user_data) < 0)
851 SWAP (mid, hi, size);
852 else
853 goto jump_over;
854 if ((*cmp) ((void *) mid, (void *) lo, user_data) < 0)
855 SWAP (mid, lo, size);
856 jump_over:;
857 left_ptr = lo + size;
858 right_ptr = hi - size;
859
860 /* Here's the famous ``collapse the walls'' section of quicksort.
861 Gotta like those tight inner loops! They are the main reason
862 that this algorithm runs much faster than others. */
863 do
864 {
865 while ((*cmp) ((void *) left_ptr, (void *) mid, user_data) < 0)
866 left_ptr += size;
867
868 while ((*cmp) ((void *) mid, (void *) right_ptr, user_data) < 0)
869 right_ptr -= size;
870
871 if (left_ptr < right_ptr)
872 {
873 SWAP (left_ptr, right_ptr, size);
874 if (mid == left_ptr)
875 mid = right_ptr;
876 else if (mid == right_ptr)
877 mid = left_ptr;
878 left_ptr += size;
879 right_ptr -= size;
880 }
881 else if (left_ptr == right_ptr)
882 {
883 left_ptr += size;
884 right_ptr -= size;
885 break;
886 }
887 }
888 while (left_ptr <= right_ptr);
fe5f448f
RR
889
890 /* Set up pointers for next iteration. First determine whether
891 left and right partitions are below the threshold size. If so,
892 ignore one or both. Otherwise, push the larger partition's
893 bounds on the stack and continue sorting the smaller one. */
894
895 if ((size_t) (right_ptr - lo) <= max_thresh)
896 {
897 if ((size_t) (hi - left_ptr) <= max_thresh)
11fe6505 898 /* Ignore both small partitions. */
fe5f448f
RR
899 POP (lo, hi);
900 else
11fe6505 901 /* Ignore small left partition. */
fe5f448f
RR
902 lo = left_ptr;
903 }
904 else if ((size_t) (hi - left_ptr) <= max_thresh)
11fe6505 905 /* Ignore small right partition. */
fe5f448f
RR
906 hi = right_ptr;
907 else if ((right_ptr - lo) > (hi - left_ptr))
908 {
11fe6505 909 /* Push larger left partition indices. */
fe5f448f
RR
910 PUSH (lo, right_ptr);
911 lo = left_ptr;
912 }
913 else
914 {
11fe6505 915 /* Push larger right partition indices. */
fe5f448f
RR
916 PUSH (left_ptr, hi);
917 hi = right_ptr;
918 }
919 }
920 }
921
922 /* Once the BASE_PTR array is partially sorted by quicksort the rest
923 is completely sorted using insertion sort, since this is efficient
924 for partitions below MAX_THRESH size. BASE_PTR points to the beginning
925 of the array to sort, and END_PTR points at the very last element in
926 the array (*not* one beyond it!). */
927
fe5f448f
RR
928 {
929 char *const end_ptr = &base_ptr[size * (total_elems - 1)];
930 char *tmp_ptr = base_ptr;
e71bf8b2
VZ
931 char *thresh = base_ptr + max_thresh;
932 if ( thresh > end_ptr )
933 thresh = end_ptr;
fe5f448f
RR
934 register char *run_ptr;
935
936 /* Find smallest element in first threshold and place it at the
937 array's beginning. This is the smallest array element,
938 and the operation speeds up insertion sort's inner loop. */
939
940 for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size)
941 if ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, user_data) < 0)
942 tmp_ptr = run_ptr;
943
944 if (tmp_ptr != base_ptr)
945 SWAP (tmp_ptr, base_ptr, size);
946
947 /* Insertion sort, running from left-hand-side up to right-hand-side. */
948
949 run_ptr = base_ptr + size;
950 while ((run_ptr += size) <= end_ptr)
951 {
11fe6505
VZ
952 tmp_ptr = run_ptr - size;
953 while ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, user_data) < 0)
954 tmp_ptr -= size;
fe5f448f 955
11fe6505 956 tmp_ptr += size;
fe5f448f
RR
957 if (tmp_ptr != run_ptr)
958 {
959 char *trav;
960
11fe6505
VZ
961 trav = run_ptr + size;
962 while (--trav >= run_ptr)
fe5f448f
RR
963 {
964 char c = *trav;
965 char *hi, *lo;
966
967 for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo)
968 *hi = *lo;
969 *hi = c;
970 }
971 }
972 }
973 }
974}
975
fad92e2f 976#endif // wxUSE_BASE
fe5f448f
RR
977
978
c5f0d1f9
DE
979
980// ============================================================================
981// GUI-only functions from now on
982// ============================================================================
983
984#if wxUSE_GUI
985
f9837e46
VZ
986// this function is only really implemented for X11-based ports, including GTK1
987// (GTK2 sets detectable auto-repeat automatically anyhow)
988#if !(defined(__WXX11__) || defined(__WXMOTIF__) || \
989 (defined(__WXGTK__) && !defined(__WXGTK20__)))
ef3da29b
VZ
990bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag) )
991{
f9837e46 992 return true;
ef3da29b 993}
f9837e46 994#endif // !X11-based port
ef3da29b 995
498a1eeb
RN
996// ----------------------------------------------------------------------------
997// Launch default browser
998// ----------------------------------------------------------------------------
999
7999124f 1000#if defined(__WXMSW__)
5ccb95f6 1001
50a2e26f
FM
1002// implemented in a port-specific utils source file:
1003bool wxDoLaunchDefaultBrowser(const wxString& url, const wxString& scheme, int flags);
42d0df00 1004
7e86b10b 1005#elif defined(__WXX11__) || defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXCOCOA__) || \
766fc092 1006 (defined(__WXOSX__) )
42d0df00 1007
50a2e26f
FM
1008// implemented in a port-specific utils source file:
1009bool wxDoLaunchDefaultBrowser(const wxString& url, int flags);
498a1eeb 1010
f728025e 1011#else
ae46a7fd 1012
50a2e26f
FM
1013// a "generic" implementation:
1014bool wxDoLaunchDefaultBrowser(const wxString& url, int flags)
1015{
1016 // on other platforms try to use mime types or wxExecute...
889fda0c 1017
13a1e96f
DS
1018 bool ok = false;
1019 wxString cmd;
1020
1b1b5318 1021#if wxUSE_MIMETYPE
9a83f860 1022 wxFileType *ft = wxTheMimeTypesManager->GetFileTypeFromExtension(wxT("html"));
7999124f 1023 if ( ft )
657a7545 1024 {
7999124f
VZ
1025 wxString mt;
1026 ft->GetMimeType(&mt);
498a1eeb 1027
13a1e96f 1028 ok = ft->GetOpenCommand(&cmd, wxFileType::MessageParameters(url));
7999124f 1029 delete ft;
498a1eeb 1030 }
1b1b5318 1031#endif // wxUSE_MIMETYPE
13a1e96f
DS
1032
1033 if ( !ok || cmd.empty() )
2830b4a4 1034 {
13a1e96f 1035 // fallback to checking for the BROWSER environment variable
50a2e26f 1036 if ( !wxGetEnv(wxT("BROWSER"), &cmd) || cmd.empty() )
9a83f860 1037 cmd << wxT(' ') << url;
2830b4a4 1038 }
13a1e96f
DS
1039
1040 ok = ( !cmd.empty() && wxExecute(cmd) );
1041 if (ok)
1042 return ok;
1043
1044 // no file type for HTML extension
5519074c 1045 wxLogError(_("No default application configured for HTML files."));
13a1e96f 1046
50a2e26f
FM
1047 return false;
1048}
1049#endif
1050
1051static bool DoLaunchDefaultBrowserHelper(const wxString& urlOrig, int flags)
1052{
1053 // NOTE: we don't have to care about the wxBROWSER_NOBUSYCURSOR flag
1054 // as it was already handled by wxLaunchDefaultBrowser
1055
1056 wxUnusedVar(flags);
1057
1058 wxString url(urlOrig), scheme;
1059 wxURI uri(url);
1060
1061 // this check is useful to avoid that wxURI recognizes as scheme parts of
1062 // the filename, in case urlOrig is a local filename
1063 // (e.g. "C:\\test.txt" when parsed by wxURI reports a scheme == "C")
02b94f4e 1064 bool hasValidScheme = uri.HasScheme() && uri.GetScheme().length() > 1;
50a2e26f
FM
1065
1066#if defined(__WXMSW__)
1067
1068 // NOTE: when testing wxMSW's wxLaunchDefaultBrowser all possible forms
1069 // of the URL/flags should be tested; e.g.:
1070 //
1071 // for (int i=0; i<2; i++)
1072 // {
4290e8ed 1073 // // test arguments without a valid URL scheme:
50a2e26f
FM
1074 // wxLaunchDefaultBrowser("C:\\test.txt", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1075 // wxLaunchDefaultBrowser("wxwidgets.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
4290e8ed
FM
1076 //
1077 // // test arguments with different valid schemes:
50a2e26f
FM
1078 // wxLaunchDefaultBrowser("file:/C%3A/test.txt", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1079 // wxLaunchDefaultBrowser("http://wxwidgets.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
4290e8ed 1080 // wxLaunchDefaultBrowser("mailto:user@host.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
50a2e26f
FM
1081 // }
1082 // (assuming you have a C:\test.txt file)
1083
1084 if ( !hasValidScheme )
1085 {
1086 if (wxFileExists(urlOrig) || wxDirExists(urlOrig))
1087 {
1088 scheme = "file";
1089 // do not prepend the file scheme to the URL as ShellExecuteEx() doesn't like it
1090 }
1091 else
1092 {
1093 url.Prepend(wxS("http://"));
1094 scheme = "http";
1095 }
1096 }
1097 else if ( hasValidScheme )
1098 {
1099 scheme = uri.GetScheme();
1100
1101 if ( uri.GetScheme() == "file" )
1102 {
00aa89f4
VZ
1103 // TODO: extract URLToFileName() to some always compiled in
1104 // function
1105#if wxUSE_FILESYSTEM
4290e8ed 1106 // ShellExecuteEx() doesn't like the "file" scheme when opening local files;
50a2e26f
FM
1107 // remove it
1108 url = wxFileSystem::URLToFileName(url).GetFullPath();
00aa89f4 1109#endif // wxUSE_FILESYSTEM
50a2e26f
FM
1110 }
1111 }
1112
1113 if (wxDoLaunchDefaultBrowser(url, scheme, flags))
1114 return true;
1115 //else: call wxLogSysError
1116#else
1117 if ( !hasValidScheme )
1118 {
1119 // set the scheme of url to "http" or "file" if it does not have one
1120 if (wxFileExists(urlOrig) || wxDirExists(urlOrig))
1121 url.Prepend(wxS("file://"));
1122 else
1123 url.Prepend(wxS("http://"));
1124 }
1125
1126 if (wxDoLaunchDefaultBrowser(url, flags))
1127 return true;
1128 //else: call wxLogSysError
1129#endif
532d575b 1130
5519074c 1131 wxLogSysError(_("Failed to open URL \"%s\" in default browser."),
7999124f 1132 url.c_str());
657a7545 1133
7999124f 1134 return false;
498a1eeb
RN
1135}
1136
f75e0c15
VZ
1137bool wxLaunchDefaultBrowser(const wxString& url, int flags)
1138{
50a2e26f
FM
1139 // NOTE: as documented, "url" may be both a real well-formed URL
1140 // and a local file name
1141
f75e0c15 1142 if ( flags & wxBROWSER_NOBUSYCURSOR )
50a2e26f 1143 return DoLaunchDefaultBrowserHelper(url, flags);
f75e0c15
VZ
1144
1145 wxBusyCursor bc;
50a2e26f 1146 return DoLaunchDefaultBrowserHelper(url, flags);
f75e0c15
VZ
1147}
1148
e90c1d2a 1149// ----------------------------------------------------------------------------
7c072018 1150// Menu accelerators related functions
e90c1d2a
VZ
1151// ----------------------------------------------------------------------------
1152
50a2e26f 1153#if WXWIN_COMPATIBILITY_2_6
7c072018 1154wxChar *wxStripMenuCodes(const wxChar *in, wxChar *out)
e90c1d2a 1155{
9a6384ca 1156#if wxUSE_MENUS
52af3158 1157 wxString s = wxMenuItem::GetLabelText(in);
9a6384ca
WS
1158#else
1159 wxString str(in);
1160 wxString s = wxStripMenuCodes(str);
1161#endif // wxUSE_MENUS
7c072018
VZ
1162 if ( out )
1163 {
1164 // go smash their buffer if it's not big enough - I love char * params
1165 memcpy(out, s.c_str(), s.length() * sizeof(wxChar));
1166 }
1167 else
1168 {
f526f752
MB
1169 out = new wxChar[s.length() + 1];
1170 wxStrcpy(out, s.c_str());
7c072018
VZ
1171 }
1172
1173 return out;
e90c1d2a 1174}
50a2e26f 1175#endif
e90c1d2a 1176
74639764 1177wxString wxStripMenuCodes(const wxString& in, int flags)
e90c1d2a 1178{
9a83f860 1179 wxASSERT_MSG( flags, wxT("this is useless to call without any flags") );
74639764 1180
7c072018 1181 wxString out;
79f585d9 1182
7c072018
VZ
1183 size_t len = in.length();
1184 out.reserve(len);
79f585d9 1185
7c072018
VZ
1186 for ( size_t n = 0; n < len; n++ )
1187 {
1188 wxChar ch = in[n];
9a83f860 1189 if ( (flags & wxStrip_Mnemonics) && ch == wxT('&') )
cd6ce4a9 1190 {
7c072018
VZ
1191 // skip it, it is used to introduce the accel char (or to quote
1192 // itself in which case it should still be skipped): note that it
1193 // can't be the last character of the string
1194 if ( ++n == len )
79f585d9 1195 {
9a83f860 1196 wxLogDebug(wxT("Invalid menu string '%s'"), in.c_str());
7c072018
VZ
1197 }
1198 else
1199 {
1200 // use the next char instead
1201 ch = in[n];
79f585d9 1202 }
cd6ce4a9 1203 }
9a83f860 1204 else if ( (flags & wxStrip_Accel) && ch == wxT('\t') )
79f585d9 1205 {
7c072018
VZ
1206 // everything after TAB is accel string, exit the loop
1207 break;
79f585d9 1208 }
7c072018
VZ
1209
1210 out += ch;
225fe9d6
VZ
1211 }
1212
7c072018 1213 return out;
cd6ce4a9
VZ
1214}
1215
cbc66a27 1216// ----------------------------------------------------------------------------
7c072018 1217// Window search functions
cbc66a27
VZ
1218// ----------------------------------------------------------------------------
1219
7c072018
VZ
1220/*
1221 * If parent is non-NULL, look through children for a label or title
1222 * matching the specified string. If NULL, look through all top-level windows.
1223 *
1224 */
e2a6f233 1225
7c072018
VZ
1226wxWindow *
1227wxFindWindowByLabel (const wxString& title, wxWindow * parent)
134677bd 1228{
7c072018
VZ
1229 return wxWindow::FindWindowByLabel( title, parent );
1230}
b829bf55 1231
b829bf55 1232
7c072018
VZ
1233/*
1234 * If parent is non-NULL, look through children for a name
1235 * matching the specified string. If NULL, look through all top-level windows.
1236 *
1237 */
134677bd 1238
7c072018
VZ
1239wxWindow *
1240wxFindWindowByName (const wxString& name, wxWindow * parent)
2c18f21d 1241{
7c072018 1242 return wxWindow::FindWindowByName( name, parent );
2c18f21d
VS
1243}
1244
cb719f2e 1245// Returns menu item id or wxNOT_FOUND if none.
7c072018 1246int
8d22935d
VZ
1247wxFindMenuItemId(wxFrame *frame,
1248 const wxString& menuString,
1249 const wxString& itemString)
e2a6f233 1250{
7c072018 1251#if wxUSE_MENUS
9a6384ca
WS
1252 wxMenuBar *menuBar = frame->GetMenuBar ();
1253 if ( menuBar )
1254 return menuBar->FindMenuItem (menuString, itemString);
8d22935d
VZ
1255#else // !wxUSE_MENUS
1256 wxUnusedVar(frame);
1257 wxUnusedVar(menuString);
1258 wxUnusedVar(itemString);
1259#endif // wxUSE_MENUS/!wxUSE_MENUS
0fb67cd1 1260
9a6384ca 1261 return wxNOT_FOUND;
e2a6f233
JS
1262}
1263
7c072018
VZ
1264// Try to find the deepest child that contains 'pt'.
1265// We go backwards, to try to allow for controls that are spacially
1266// within other controls, but are still siblings (e.g. buttons within
1267// static boxes). Static boxes are likely to be created _before_ controls
1268// that sit inside them.
1269wxWindow* wxFindWindowAtPoint(wxWindow* win, const wxPoint& pt)
e2a6f233 1270{
7c072018
VZ
1271 if (!win->IsShown())
1272 return NULL;
0fb67cd1 1273
7c072018
VZ
1274 // Hack for wxNotebook case: at least in wxGTK, all pages
1275 // claim to be shown, so we must only deal with the selected one.
1276#if wxUSE_NOTEBOOK
1277 if (win->IsKindOf(CLASSINFO(wxNotebook)))
e2a6f233 1278 {
7c072018
VZ
1279 wxNotebook* nb = (wxNotebook*) win;
1280 int sel = nb->GetSelection();
1281 if (sel >= 0)
1282 {
1283 wxWindow* child = nb->GetPage(sel);
1284 wxWindow* foundWin = wxFindWindowAtPoint(child, pt);
1285 if (foundWin)
1286 return foundWin;
1287 }
e2a6f233 1288 }
7c072018 1289#endif
0fb67cd1 1290
df5168c4 1291 wxWindowList::compatibility_iterator node = win->GetChildren().GetLast();
7c072018
VZ
1292 while (node)
1293 {
1294 wxWindow* child = node->GetData();
1295 wxWindow* foundWin = wxFindWindowAtPoint(child, pt);
1296 if (foundWin)
1297 return foundWin;
1298 node = node->GetPrevious();
1299 }
1300
1301 wxPoint pos = win->GetPosition();
1302 wxSize sz = win->GetSize();
7aa7d2d4 1303 if ( !win->IsTopLevel() && win->GetParent() )
7c072018
VZ
1304 {
1305 pos = win->GetParent()->ClientToScreen(pos);
1306 }
1307
1308 wxRect rect(pos, sz);
22a35096 1309 if (rect.Contains(pt))
7c072018 1310 return win;
622eb786
VZ
1311
1312 return NULL;
0fb67cd1
VZ
1313}
1314
7c072018 1315wxWindow* wxGenericFindWindowAtPoint(const wxPoint& pt)
0fb67cd1 1316{
7c072018
VZ
1317 // Go backwards through the list since windows
1318 // on top are likely to have been appended most
1319 // recently.
df5168c4 1320 wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetLast();
7c072018
VZ
1321 while (node)
1322 {
1323 wxWindow* win = node->GetData();
1324 wxWindow* found = wxFindWindowAtPoint(win, pt);
1325 if (found)
1326 return found;
1327 node = node->GetPrevious();
1328 }
1329 return NULL;
1330}
0fb67cd1 1331
7c072018
VZ
1332// ----------------------------------------------------------------------------
1333// GUI helpers
1334// ----------------------------------------------------------------------------
0fb67cd1 1335
7c072018
VZ
1336/*
1337 * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp
1338 * since otherwise the generic code may be pulled in unnecessarily.
1339 */
0fb67cd1 1340
7c072018 1341#if wxUSE_MSGDLG
0fb67cd1 1342
7c072018
VZ
1343int wxMessageBox(const wxString& message, const wxString& caption, long style,
1344 wxWindow *parent, int WXUNUSED(x), int WXUNUSED(y) )
0fb67cd1 1345{
7e3204b4
VZ
1346 // add the appropriate icon unless this was explicitly disabled by use of
1347 // wxICON_NONE
1348 if ( !(style & wxICON_NONE) && !(style & wxICON_MASK) )
53a6ac21 1349 {
7e3204b4 1350 style |= style & wxYES ? wxICON_QUESTION : wxICON_INFORMATION;
53a6ac21
DS
1351 }
1352
7e3204b4 1353 wxMessageDialog dialog(parent, message, caption, style);
0fb67cd1 1354
7c072018
VZ
1355 int ans = dialog.ShowModal();
1356 switch ( ans )
1357 {
1358 case wxID_OK:
1359 return wxOK;
1360 case wxID_YES:
1361 return wxYES;
1362 case wxID_NO:
1363 return wxNO;
1364 case wxID_CANCEL:
1365 return wxCANCEL;
7112cdd1
VZ
1366 case wxID_HELP:
1367 return wxHELP;
7c072018 1368 }
0fb67cd1 1369
9a83f860 1370 wxFAIL_MSG( wxT("unexpected return code from wxMessageDialog") );
0fb67cd1 1371
7c072018 1372 return wxCANCEL;
e2a6f233
JS
1373}
1374
ccec9093 1375wxVersionInfo wxGetLibraryVersionInfo()
8cf304f8
VZ
1376{
1377 // don't translate these strings, they're for diagnostics purposes only
1378 wxString msg;
32be10a4
VZ
1379 msg.Printf(wxS("wxWidgets Library (%s port)\n")
1380 wxS("Version %d.%d.%d (Unicode: %s, debug level: %d),\n")
1381 wxS("compiled at %s %s\n\n")
1382 wxS("Runtime version of toolkit used is %d.%d.\n"),
1383 wxPlatformInfo::Get().GetPortIdName(),
8cf304f8
VZ
1384 wxMAJOR_VERSION,
1385 wxMINOR_VERSION,
1386 wxRELEASE_NUMBER,
32be10a4
VZ
1387#if wxUSE_UNICODE_UTF8
1388 "UTF-8",
1389#elif wxUSE_UNICODE
1390 "wchar_t",
8cf304f8 1391#else
32be10a4 1392 "none",
8cf304f8 1393#endif
32be10a4 1394 wxDEBUG_LEVEL,
8cf304f8
VZ
1395 __TDATE__,
1396 __TTIME__,
1397 wxPlatformInfo::Get().GetToolkitMajorVersion(),
32be10a4
VZ
1398 wxPlatformInfo::Get().GetToolkitMinorVersion()
1399 );
1400
8cf304f8 1401#ifdef __WXGTK__
32be10a4
VZ
1402 msg += wxString::Format("Compile-time GTK+ version is %d.%d.%d.\n",
1403 GTK_MAJOR_VERSION,
1404 GTK_MINOR_VERSION,
1405 GTK_MICRO_VERSION);
1406#endif // __WXGTK__
1407
ccec9093
VZ
1408 return wxVersionInfo(wxS("wxWidgets"),
1409 wxMAJOR_VERSION,
1410 wxMINOR_VERSION,
1411 wxRELEASE_NUMBER,
1412 msg,
8fcf7cd0 1413 wxS("Copyright (c) 1995-2011 wxWidgets team"));
ccec9093
VZ
1414}
1415
1416void wxInfoMessageBox(wxWindow* parent)
1417{
1418 wxVersionInfo info = wxGetLibraryVersionInfo();
1419 wxString msg = info.ToString();
1420
1421 msg << wxS("\n") << info.GetCopyright();
32be10a4 1422
9a83f860 1423 wxMessageBox(msg, wxT("wxWidgets information"),
8cf304f8
VZ
1424 wxICON_INFORMATION | wxOK,
1425 parent);
1426}
1427
7c072018 1428#endif // wxUSE_MSGDLG
518b5d2f 1429
7c072018 1430#if wxUSE_TEXTDLG
518b5d2f 1431
7c072018
VZ
1432wxString wxGetTextFromUser(const wxString& message, const wxString& caption,
1433 const wxString& defaultValue, wxWindow *parent,
13d13a9e 1434 wxCoord x, wxCoord y, bool centre )
7c072018
VZ
1435{
1436 wxString str;
13d13a9e
WS
1437 long style = wxTextEntryDialogStyle;
1438
1439 if (centre)
1440 style |= wxCENTRE;
1441 else
1442 style &= ~wxCENTRE;
1443
1444 wxTextEntryDialog dialog(parent, message, caption, defaultValue, style, wxPoint(x, y));
1445
7c072018
VZ
1446 if (dialog.ShowModal() == wxID_OK)
1447 {
1448 str = dialog.GetValue();
1449 }
0fb67cd1 1450
7c072018 1451 return str;
518b5d2f
VZ
1452}
1453
7c072018
VZ
1454wxString wxGetPasswordFromUser(const wxString& message,
1455 const wxString& caption,
1456 const wxString& defaultValue,
b3bb2a74
KH
1457 wxWindow *parent,
1458 wxCoord x, wxCoord y, bool centre )
96c5bd7f 1459{
7c072018 1460 wxString str;
b3bb2a74
KH
1461 long style = wxTextEntryDialogStyle;
1462
1463 if (centre)
1464 style |= wxCENTRE;
1465 else
1466 style &= ~wxCENTRE;
1467
12cfa304
KH
1468 wxPasswordEntryDialog dialog(parent, message, caption, defaultValue,
1469 style, wxPoint(x, y));
7c072018
VZ
1470 if ( dialog.ShowModal() == wxID_OK )
1471 {
1472 str = dialog.GetValue();
1473 }
96c5bd7f 1474
7c072018
VZ
1475 return str;
1476}
96c5bd7f 1477
7c072018 1478#endif // wxUSE_TEXTDLG
96c5bd7f 1479
7c072018 1480#if wxUSE_COLOURDLG
96c5bd7f 1481
f75e0c15
VZ
1482wxColour wxGetColourFromUser(wxWindow *parent,
1483 const wxColour& colInit,
e6ef9ea4
VZ
1484 const wxString& caption,
1485 wxColourData *ptrData)
c51deffc 1486{
e6ef9ea4
VZ
1487 // contains serialized representation of wxColourData used the last time
1488 // the dialog was shown: we want to reuse it the next time in order to show
1489 // the same custom colours to the user (and we can't just have static
1490 // wxColourData itself because it's a GUI object and so should be destroyed
1491 // before GUI shutdown and doing it during static cleanup is too late)
1492 static wxString s_strColourData;
1493
7c072018 1494 wxColourData data;
e6ef9ea4 1495 if ( !ptrData )
7c072018 1496 {
e6ef9ea4
VZ
1497 ptrData = &data;
1498 if ( !s_strColourData.empty() )
1499 {
1500 if ( !data.FromString(s_strColourData) )
1501 {
1502 wxFAIL_MSG( "bug in wxColourData::FromString()?" );
1503 }
1504
1505#ifdef __WXMSW__
1506 // we don't get back the "choose full" flag value from the native
1507 // dialog and so we can't preserve it between runs, so we decide to
1508 // always use it as it seems better than not using it (user can
1509 // just ignore the extra controls in the dialog but having to click
1510 // a button each time to show them would be very annoying
1511 data.SetChooseFull(true);
1512#endif // __WXMSW__
1513 }
1514 }
1515
1516 if ( colInit.IsOk() )
1517 {
1518 ptrData->SetColour(colInit);
7c072018 1519 }
c51deffc 1520
7c072018 1521 wxColour colRet;
e6ef9ea4 1522 wxColourDialog dialog(parent, ptrData);
76b49cf4 1523 if (!caption.empty())
f14d6dd1 1524 dialog.SetTitle(caption);
7c072018
VZ
1525 if ( dialog.ShowModal() == wxID_OK )
1526 {
e6ef9ea4
VZ
1527 *ptrData = dialog.GetColourData();
1528 colRet = ptrData->GetColour();
1529 s_strColourData = ptrData->ToString();
7c072018 1530 }
e6ef9ea4 1531 //else: leave colRet invalid
7c072018
VZ
1532
1533 return colRet;
c51deffc 1534}
bc385ba9 1535
7c072018 1536#endif // wxUSE_COLOURDLG
bc385ba9 1537
7c072018
VZ
1538#if wxUSE_FONTDLG
1539
f14d6dd1 1540wxFont wxGetFontFromUser(wxWindow *parent, const wxFont& fontInit, const wxString& caption)
bc385ba9 1541{
7c072018 1542 wxFontData data;
a1b806b9 1543 if ( fontInit.IsOk() )
bc385ba9 1544 {
7c072018
VZ
1545 data.SetInitialFont(fontInit);
1546 }
bc385ba9 1547
7c072018
VZ
1548 wxFont fontRet;
1549 wxFontDialog dialog(parent, data);
76b49cf4 1550 if (!caption.empty())
f14d6dd1 1551 dialog.SetTitle(caption);
7c072018
VZ
1552 if ( dialog.ShowModal() == wxID_OK )
1553 {
1554 fontRet = dialog.GetFontData().GetChosenFont();
1555 }
1556 //else: leave it invalid
bc385ba9 1557
7c072018 1558 return fontRet;
bc385ba9
VZ
1559}
1560
7c072018 1561#endif // wxUSE_FONTDLG
2b5f62a0 1562
7c072018
VZ
1563// ----------------------------------------------------------------------------
1564// wxSafeYield and supporting functions
1565// ----------------------------------------------------------------------------
2b5f62a0 1566
7c072018
VZ
1567void wxEnableTopLevelWindows(bool enable)
1568{
df5168c4 1569 wxWindowList::compatibility_iterator node;
7c072018
VZ
1570 for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
1571 node->GetData()->Enable(enable);
1572}
2b5f62a0 1573
902ddbfd
SC
1574#if defined(__WXOSX__) && wxOSX_USE_COCOA
1575
1576// defined in evtloop.mm
1577
1578#else
1579
2ecd1756
VZ
1580wxWindowDisabler::wxWindowDisabler(bool disable)
1581{
1582 m_disabled = disable;
1583 if ( disable )
1584 DoDisable();
1585}
1586
7c072018 1587wxWindowDisabler::wxWindowDisabler(wxWindow *winToSkip)
2ecd1756
VZ
1588{
1589 m_disabled = true;
1590 DoDisable(winToSkip);
1591}
1592
1593void wxWindowDisabler::DoDisable(wxWindow *winToSkip)
7c072018
VZ
1594{
1595 // remember the top level windows which were already disabled, so that we
1596 // don't reenable them later
1597 m_winDisabled = NULL;
1598
df5168c4 1599 wxWindowList::compatibility_iterator node;
7c072018 1600 for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
2b5f62a0 1601 {
7c072018
VZ
1602 wxWindow *winTop = node->GetData();
1603 if ( winTop == winToSkip )
1604 continue;
2b5f62a0 1605
7c072018
VZ
1606 // we don't need to disable the hidden or already disabled windows
1607 if ( winTop->IsEnabled() && winTop->IsShown() )
2b5f62a0 1608 {
7c072018 1609 winTop->Disable();
2b5f62a0
VZ
1610 }
1611 else
1612 {
7c072018
VZ
1613 if ( !m_winDisabled )
1614 {
1615 m_winDisabled = new wxWindowList;
1616 }
1617
1618 m_winDisabled->Append(winTop);
2b5f62a0
VZ
1619 }
1620 }
2b5f62a0
VZ
1621}
1622
7c072018 1623wxWindowDisabler::~wxWindowDisabler()
cd6ce4a9 1624{
2ecd1756
VZ
1625 if ( !m_disabled )
1626 return;
1627
df5168c4 1628 wxWindowList::compatibility_iterator node;
7c072018 1629 for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
cd6ce4a9 1630 {
7c072018
VZ
1631 wxWindow *winTop = node->GetData();
1632 if ( !m_winDisabled || !m_winDisabled->Find(winTop) )
cd6ce4a9 1633 {
7c072018 1634 winTop->Enable();
cd6ce4a9 1635 }
7c072018 1636 //else: had been already disabled, don't reenable
cd6ce4a9 1637 }
f6bcfd97 1638
7c072018 1639 delete m_winDisabled;
f6bcfd97
BP
1640}
1641
902ddbfd
SC
1642#endif
1643
7c072018
VZ
1644// Yield to other apps/messages and disable user input to all windows except
1645// the given one
1646bool wxSafeYield(wxWindow *win, bool onlyIfNeeded)
f6bcfd97 1647{
7c072018 1648 wxWindowDisabler wd(win);
21709999 1649
7c072018
VZ
1650 bool rc;
1651 if (onlyIfNeeded)
1652 rc = wxYieldIfNeeded();
1653 else
1654 rc = wxYield();
8461e4c2 1655
7c072018 1656 return rc;
8461e4c2
VZ
1657}
1658
fad92e2f
FM
1659// ----------------------------------------------------------------------------
1660// wxApp::Yield() wrappers for backwards compatibility
1661// ----------------------------------------------------------------------------
1662
1663bool wxYield()
8461e4c2 1664{
fad92e2f
FM
1665 return wxTheApp && wxTheApp->Yield();
1666}
1667
1668bool wxYieldIfNeeded()
1669{
1670 return wxTheApp && wxTheApp->Yield(true);
8461e4c2 1671}
7c072018
VZ
1672
1673#endif // wxUSE_GUI