]> git.saurik.com Git - wxWidgets.git/blame - src/common/utilscmn.cpp
update button style to include BS_MULTILINE when a multiline label is set
[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 1058#if !TARGET_CARBON
13a1e96f 1059 err = ICFindConfigFile(inst, 0, NULL);
f14d6dd1
JS
1060#endif
1061 if (err == noErr)
1062 {
1063 ConstStr255Param hint = 0;
1064 startSel = 0;
76b49cf4 1065 endSel = url.length();
f14d6dd1
JS
1066 err = ICLaunchURL(inst, hint, url.fn_str(), endSel, &startSel, &endSel);
1067 if (err != noErr)
1068 wxLogDebug(wxT("ICLaunchURL error %d"), (int) err);
1069 }
1070 ICStop(inst);
1071 return true;
1072 }
1073 else
1074 {
1075 wxLogDebug(wxT("ICStart error %d"), (int) err);
1076 return false;
1077 }
f728025e 1078#else
889fda0c
RR
1079 // (non-Mac, non-MSW)
1080
1081#ifdef __UNIX__
17ede0b1
RR
1082
1083 wxString desktop = wxTheApp->GetTraits()->GetDesktopEnvironment();
1084
1085 // GNOME and KDE desktops have some applications which should be always installed
1086 // together with their main parts, which give us the
1087 if (desktop == wxT("GNOME"))
889fda0c
RR
1088 {
1089 wxArrayString errors;
1090 wxArrayString output;
17ede0b1
RR
1091
1092 // gconf will tell us the path of the application to use as browser
1093 long res = wxExecute( wxT("gconftool-2 --get /desktop/gnome/applications/browser/exec"),
1094 output, errors, wxEXEC_NODISABLE );
889fda0c
RR
1095 if (res >= 0 && errors.GetCount() == 0)
1096 {
1097 wxString cmd = output[0];
1098 cmd << _T(' ') << url;
1099 if (wxExecute(cmd))
1100 return true;
1101 }
1102 }
17ede0b1
RR
1103 else if (desktop == wxT("KDE"))
1104 {
1105 // kfmclient directly opens the given URL
1106 if (wxExecute(wxT("kfmclient openURL ") + url))
1107 return true;
1108 }
889fda0c
RR
1109#endif
1110
13a1e96f
DS
1111 bool ok = false;
1112 wxString cmd;
1113
1b1b5318 1114#if wxUSE_MIMETYPE
13a1e96f 1115 wxFileType *ft = wxTheMimeTypesManager->GetFileTypeFromExtension(_T("html"));
7999124f 1116 if ( ft )
657a7545 1117 {
7999124f
VZ
1118 wxString mt;
1119 ft->GetMimeType(&mt);
498a1eeb 1120
13a1e96f 1121 ok = ft->GetOpenCommand(&cmd, wxFileType::MessageParameters(url));
7999124f 1122 delete ft;
498a1eeb 1123 }
1b1b5318 1124#endif // wxUSE_MIMETYPE
13a1e96f
DS
1125
1126 if ( !ok || cmd.empty() )
2830b4a4 1127 {
13a1e96f
DS
1128 // fallback to checking for the BROWSER environment variable
1129 cmd = wxGetenv(wxT("BROWSER"));
1130 if ( !cmd.empty() )
1131 cmd << _T(' ') << url;
2830b4a4 1132 }
13a1e96f
DS
1133
1134 ok = ( !cmd.empty() && wxExecute(cmd) );
1135 if (ok)
1136 return ok;
1137
1138 // no file type for HTML extension
1139 wxLogError(_T("No default application configured for HTML files."));
1140
7999124f 1141#endif // !wxUSE_MIMETYPE && !__WXMSW__
532d575b 1142
7999124f
VZ
1143 wxLogSysError(_T("Failed to open URL \"%s\" in default browser."),
1144 url.c_str());
657a7545 1145
7999124f 1146 return false;
498a1eeb
RN
1147}
1148
e90c1d2a 1149// ----------------------------------------------------------------------------
7c072018 1150// Menu accelerators related functions
e90c1d2a
VZ
1151// ----------------------------------------------------------------------------
1152
7c072018 1153wxChar *wxStripMenuCodes(const wxChar *in, wxChar *out)
e90c1d2a 1154{
9a6384ca 1155#if wxUSE_MENUS
7c072018 1156 wxString s = wxMenuItem::GetLabelFromText(in);
9a6384ca
WS
1157#else
1158 wxString str(in);
1159 wxString s = wxStripMenuCodes(str);
1160#endif // wxUSE_MENUS
7c072018
VZ
1161 if ( out )
1162 {
1163 // go smash their buffer if it's not big enough - I love char * params
1164 memcpy(out, s.c_str(), s.length() * sizeof(wxChar));
1165 }
1166 else
1167 {
f526f752
MB
1168 out = new wxChar[s.length() + 1];
1169 wxStrcpy(out, s.c_str());
7c072018
VZ
1170 }
1171
1172 return out;
e90c1d2a
VZ
1173}
1174
74639764 1175wxString wxStripMenuCodes(const wxString& in, int flags)
e90c1d2a 1176{
74639764
VZ
1177 wxASSERT_MSG( flags, _T("this is useless to call without any flags") );
1178
7c072018 1179 wxString out;
79f585d9 1180
7c072018
VZ
1181 size_t len = in.length();
1182 out.reserve(len);
79f585d9 1183
7c072018
VZ
1184 for ( size_t n = 0; n < len; n++ )
1185 {
1186 wxChar ch = in[n];
74639764 1187 if ( (flags & wxStrip_Mnemonics) && ch == _T('&') )
cd6ce4a9 1188 {
7c072018
VZ
1189 // skip it, it is used to introduce the accel char (or to quote
1190 // itself in which case it should still be skipped): note that it
1191 // can't be the last character of the string
1192 if ( ++n == len )
79f585d9 1193 {
7c072018
VZ
1194 wxLogDebug(_T("Invalid menu string '%s'"), in.c_str());
1195 }
1196 else
1197 {
1198 // use the next char instead
1199 ch = in[n];
79f585d9 1200 }
cd6ce4a9 1201 }
74639764 1202 else if ( (flags & wxStrip_Accel) && ch == _T('\t') )
79f585d9 1203 {
7c072018
VZ
1204 // everything after TAB is accel string, exit the loop
1205 break;
79f585d9 1206 }
7c072018
VZ
1207
1208 out += ch;
225fe9d6
VZ
1209 }
1210
7c072018 1211 return out;
cd6ce4a9
VZ
1212}
1213
cbc66a27 1214// ----------------------------------------------------------------------------
7c072018 1215// Window search functions
cbc66a27
VZ
1216// ----------------------------------------------------------------------------
1217
7c072018
VZ
1218/*
1219 * If parent is non-NULL, look through children for a label or title
1220 * matching the specified string. If NULL, look through all top-level windows.
1221 *
1222 */
e2a6f233 1223
7c072018
VZ
1224wxWindow *
1225wxFindWindowByLabel (const wxString& title, wxWindow * parent)
134677bd 1226{
7c072018
VZ
1227 return wxWindow::FindWindowByLabel( title, parent );
1228}
b829bf55 1229
b829bf55 1230
7c072018
VZ
1231/*
1232 * If parent is non-NULL, look through children for a name
1233 * matching the specified string. If NULL, look through all top-level windows.
1234 *
1235 */
134677bd 1236
7c072018
VZ
1237wxWindow *
1238wxFindWindowByName (const wxString& name, wxWindow * parent)
2c18f21d 1239{
7c072018 1240 return wxWindow::FindWindowByName( name, parent );
2c18f21d
VS
1241}
1242
cb719f2e 1243// Returns menu item id or wxNOT_FOUND if none.
7c072018
VZ
1244int
1245wxFindMenuItemId (wxFrame * frame, const wxString& menuString, const wxString& itemString)
e2a6f233 1246{
7c072018 1247#if wxUSE_MENUS
9a6384ca
WS
1248 wxMenuBar *menuBar = frame->GetMenuBar ();
1249 if ( menuBar )
1250 return menuBar->FindMenuItem (menuString, itemString);
7c072018 1251#endif // wxUSE_MENUS
0fb67cd1 1252
9a6384ca 1253 return wxNOT_FOUND;
e2a6f233
JS
1254}
1255
7c072018
VZ
1256// Try to find the deepest child that contains 'pt'.
1257// We go backwards, to try to allow for controls that are spacially
1258// within other controls, but are still siblings (e.g. buttons within
1259// static boxes). Static boxes are likely to be created _before_ controls
1260// that sit inside them.
1261wxWindow* wxFindWindowAtPoint(wxWindow* win, const wxPoint& pt)
e2a6f233 1262{
7c072018
VZ
1263 if (!win->IsShown())
1264 return NULL;
0fb67cd1 1265
7c072018
VZ
1266 // Hack for wxNotebook case: at least in wxGTK, all pages
1267 // claim to be shown, so we must only deal with the selected one.
1268#if wxUSE_NOTEBOOK
1269 if (win->IsKindOf(CLASSINFO(wxNotebook)))
e2a6f233 1270 {
7c072018
VZ
1271 wxNotebook* nb = (wxNotebook*) win;
1272 int sel = nb->GetSelection();
1273 if (sel >= 0)
1274 {
1275 wxWindow* child = nb->GetPage(sel);
1276 wxWindow* foundWin = wxFindWindowAtPoint(child, pt);
1277 if (foundWin)
1278 return foundWin;
1279 }
e2a6f233 1280 }
7c072018 1281#endif
0fb67cd1 1282
df5168c4 1283 wxWindowList::compatibility_iterator node = win->GetChildren().GetLast();
7c072018
VZ
1284 while (node)
1285 {
1286 wxWindow* child = node->GetData();
1287 wxWindow* foundWin = wxFindWindowAtPoint(child, pt);
1288 if (foundWin)
1289 return foundWin;
1290 node = node->GetPrevious();
1291 }
1292
1293 wxPoint pos = win->GetPosition();
1294 wxSize sz = win->GetSize();
7aa7d2d4 1295 if ( !win->IsTopLevel() && win->GetParent() )
7c072018
VZ
1296 {
1297 pos = win->GetParent()->ClientToScreen(pos);
1298 }
1299
1300 wxRect rect(pos, sz);
22a35096 1301 if (rect.Contains(pt))
7c072018 1302 return win;
622eb786
VZ
1303
1304 return NULL;
0fb67cd1
VZ
1305}
1306
7c072018 1307wxWindow* wxGenericFindWindowAtPoint(const wxPoint& pt)
0fb67cd1 1308{
7c072018
VZ
1309 // Go backwards through the list since windows
1310 // on top are likely to have been appended most
1311 // recently.
df5168c4 1312 wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetLast();
7c072018
VZ
1313 while (node)
1314 {
1315 wxWindow* win = node->GetData();
1316 wxWindow* found = wxFindWindowAtPoint(win, pt);
1317 if (found)
1318 return found;
1319 node = node->GetPrevious();
1320 }
1321 return NULL;
1322}
0fb67cd1 1323
7c072018
VZ
1324// ----------------------------------------------------------------------------
1325// GUI helpers
1326// ----------------------------------------------------------------------------
0fb67cd1 1327
7c072018
VZ
1328/*
1329 * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp
1330 * since otherwise the generic code may be pulled in unnecessarily.
1331 */
0fb67cd1 1332
7c072018 1333#if wxUSE_MSGDLG
0fb67cd1 1334
7c072018
VZ
1335int wxMessageBox(const wxString& message, const wxString& caption, long style,
1336 wxWindow *parent, int WXUNUSED(x), int WXUNUSED(y) )
0fb67cd1 1337{
53a6ac21
DS
1338 long decorated_style = style;
1339
1340 if ( ( style & ( wxICON_EXCLAMATION | wxICON_HAND | wxICON_INFORMATION | wxICON_QUESTION ) ) == 0 )
1341 {
1342 decorated_style |= ( style & wxYES ) ? wxICON_QUESTION : wxICON_INFORMATION ;
1343 }
1344
1345 wxMessageDialog dialog(parent, message, caption, decorated_style);
0fb67cd1 1346
7c072018
VZ
1347 int ans = dialog.ShowModal();
1348 switch ( ans )
1349 {
1350 case wxID_OK:
1351 return wxOK;
1352 case wxID_YES:
1353 return wxYES;
1354 case wxID_NO:
1355 return wxNO;
1356 case wxID_CANCEL:
1357 return wxCANCEL;
1358 }
0fb67cd1 1359
7c072018 1360 wxFAIL_MSG( _T("unexpected return code from wxMessageDialog") );
0fb67cd1 1361
7c072018 1362 return wxCANCEL;
e2a6f233
JS
1363}
1364
7c072018 1365#endif // wxUSE_MSGDLG
518b5d2f 1366
7c072018 1367#if wxUSE_TEXTDLG
518b5d2f 1368
7c072018
VZ
1369wxString wxGetTextFromUser(const wxString& message, const wxString& caption,
1370 const wxString& defaultValue, wxWindow *parent,
13d13a9e 1371 wxCoord x, wxCoord y, bool centre )
7c072018
VZ
1372{
1373 wxString str;
13d13a9e
WS
1374 long style = wxTextEntryDialogStyle;
1375
1376 if (centre)
1377 style |= wxCENTRE;
1378 else
1379 style &= ~wxCENTRE;
1380
1381 wxTextEntryDialog dialog(parent, message, caption, defaultValue, style, wxPoint(x, y));
1382
7c072018
VZ
1383 if (dialog.ShowModal() == wxID_OK)
1384 {
1385 str = dialog.GetValue();
1386 }
0fb67cd1 1387
7c072018 1388 return str;
518b5d2f
VZ
1389}
1390
7c072018
VZ
1391wxString wxGetPasswordFromUser(const wxString& message,
1392 const wxString& caption,
1393 const wxString& defaultValue,
b3bb2a74
KH
1394 wxWindow *parent,
1395 wxCoord x, wxCoord y, bool centre )
96c5bd7f 1396{
7c072018 1397 wxString str;
b3bb2a74
KH
1398 long style = wxTextEntryDialogStyle;
1399
1400 if (centre)
1401 style |= wxCENTRE;
1402 else
1403 style &= ~wxCENTRE;
1404
12cfa304
KH
1405 wxPasswordEntryDialog dialog(parent, message, caption, defaultValue,
1406 style, wxPoint(x, y));
7c072018
VZ
1407 if ( dialog.ShowModal() == wxID_OK )
1408 {
1409 str = dialog.GetValue();
1410 }
96c5bd7f 1411
7c072018
VZ
1412 return str;
1413}
96c5bd7f 1414
7c072018 1415#endif // wxUSE_TEXTDLG
96c5bd7f 1416
7c072018 1417#if wxUSE_COLOURDLG
96c5bd7f 1418
f14d6dd1 1419wxColour wxGetColourFromUser(wxWindow *parent, const wxColour& colInit, const wxString& caption)
c51deffc 1420{
7c072018 1421 wxColourData data;
cb719f2e 1422 data.SetChooseFull(true);
7c072018
VZ
1423 if ( colInit.Ok() )
1424 {
1425 data.SetColour((wxColour &)colInit); // const_cast
1426 }
c51deffc 1427
7c072018
VZ
1428 wxColour colRet;
1429 wxColourDialog dialog(parent, &data);
76b49cf4 1430 if (!caption.empty())
f14d6dd1 1431 dialog.SetTitle(caption);
7c072018
VZ
1432 if ( dialog.ShowModal() == wxID_OK )
1433 {
1434 colRet = dialog.GetColourData().GetColour();
1435 }
1436 //else: leave it invalid
1437
1438 return colRet;
c51deffc 1439}
bc385ba9 1440
7c072018 1441#endif // wxUSE_COLOURDLG
bc385ba9 1442
7c072018
VZ
1443#if wxUSE_FONTDLG
1444
f14d6dd1 1445wxFont wxGetFontFromUser(wxWindow *parent, const wxFont& fontInit, const wxString& caption)
bc385ba9 1446{
7c072018
VZ
1447 wxFontData data;
1448 if ( fontInit.Ok() )
bc385ba9 1449 {
7c072018
VZ
1450 data.SetInitialFont(fontInit);
1451 }
bc385ba9 1452
7c072018
VZ
1453 wxFont fontRet;
1454 wxFontDialog dialog(parent, data);
76b49cf4 1455 if (!caption.empty())
f14d6dd1 1456 dialog.SetTitle(caption);
7c072018
VZ
1457 if ( dialog.ShowModal() == wxID_OK )
1458 {
1459 fontRet = dialog.GetFontData().GetChosenFont();
1460 }
1461 //else: leave it invalid
bc385ba9 1462
7c072018 1463 return fontRet;
bc385ba9
VZ
1464}
1465
7c072018 1466#endif // wxUSE_FONTDLG
2b5f62a0 1467
7c072018
VZ
1468// ----------------------------------------------------------------------------
1469// wxSafeYield and supporting functions
1470// ----------------------------------------------------------------------------
2b5f62a0 1471
7c072018
VZ
1472void wxEnableTopLevelWindows(bool enable)
1473{
df5168c4 1474 wxWindowList::compatibility_iterator node;
7c072018
VZ
1475 for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
1476 node->GetData()->Enable(enable);
1477}
2b5f62a0 1478
7c072018
VZ
1479wxWindowDisabler::wxWindowDisabler(wxWindow *winToSkip)
1480{
1481 // remember the top level windows which were already disabled, so that we
1482 // don't reenable them later
1483 m_winDisabled = NULL;
1484
df5168c4 1485 wxWindowList::compatibility_iterator node;
7c072018 1486 for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
2b5f62a0 1487 {
7c072018
VZ
1488 wxWindow *winTop = node->GetData();
1489 if ( winTop == winToSkip )
1490 continue;
2b5f62a0 1491
7c072018
VZ
1492 // we don't need to disable the hidden or already disabled windows
1493 if ( winTop->IsEnabled() && winTop->IsShown() )
2b5f62a0 1494 {
7c072018 1495 winTop->Disable();
2b5f62a0
VZ
1496 }
1497 else
1498 {
7c072018
VZ
1499 if ( !m_winDisabled )
1500 {
1501 m_winDisabled = new wxWindowList;
1502 }
1503
1504 m_winDisabled->Append(winTop);
2b5f62a0
VZ
1505 }
1506 }
2b5f62a0
VZ
1507}
1508
7c072018 1509wxWindowDisabler::~wxWindowDisabler()
cd6ce4a9 1510{
df5168c4 1511 wxWindowList::compatibility_iterator node;
7c072018 1512 for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
cd6ce4a9 1513 {
7c072018
VZ
1514 wxWindow *winTop = node->GetData();
1515 if ( !m_winDisabled || !m_winDisabled->Find(winTop) )
cd6ce4a9 1516 {
7c072018 1517 winTop->Enable();
cd6ce4a9 1518 }
7c072018 1519 //else: had been already disabled, don't reenable
cd6ce4a9 1520 }
f6bcfd97 1521
7c072018 1522 delete m_winDisabled;
f6bcfd97
BP
1523}
1524
7c072018
VZ
1525// Yield to other apps/messages and disable user input to all windows except
1526// the given one
1527bool wxSafeYield(wxWindow *win, bool onlyIfNeeded)
f6bcfd97 1528{
7c072018 1529 wxWindowDisabler wd(win);
21709999 1530
7c072018
VZ
1531 bool rc;
1532 if (onlyIfNeeded)
1533 rc = wxYieldIfNeeded();
1534 else
1535 rc = wxYield();
8461e4c2 1536
7c072018 1537 return rc;
8461e4c2
VZ
1538}
1539
7c072018
VZ
1540// Don't synthesize KeyUp events holding down a key and producing KeyDown
1541// events with autorepeat. On by default and always on in wxMSW. wxGTK version
1542// in utilsgtk.cpp.
1543#ifndef __WXGTK__
1544bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag) )
8461e4c2 1545{
cb719f2e 1546 return true; // detectable auto-repeat is the only mode MSW supports
8461e4c2 1547}
7c072018
VZ
1548#endif // !wxGTK
1549
1550#endif // wxUSE_GUI