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