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