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