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