]> git.saurik.com Git - wxWidgets.git/blame - src/common/utilscmn.cpp
Correct bug in the wxSpinCtrlGeneric sub-controls resizing.
[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 551#ifdef __WXOSX__
edb31724 552#if wxOSX_USE_COCOA_OR_CARBON
1f4c7e79
VZ
553 #include <crt_externs.h>
554#endif
edb31724 555#endif
1f4c7e79 556
164db92c
VZ
557bool wxGetEnvMap(wxEnvVariableHashMap *map)
558{
559 wxCHECK_MSG( map, false, wxS("output pointer can't be NULL") );
560
561#if defined(__VISUALC__)
562 wxChar **env = _tenviron;
cc221535
JJ
563#elif defined(__VMS)
564 // Now this routine wil give false for OpenVMS
565 // TODO : should we do something with logicals?
04b11eb3 566 char **env=NULL;
1f4c7e79 567#elif defined(__WXOSX__)
edb31724 568#if wxOSX_USE_COCOA_OR_CARBON
1f4c7e79
VZ
569 // Under Mac shared libraries don't have access to the global environ
570 // variable so use this Mac-specific function instead as advised by
571 // environ(7) under Darwin
572 char ***penv = _NSGetEnviron();
573 if ( !penv )
574 return false;
575 char **env = *penv;
edb31724
SC
576#else
577 char **env=NULL;
578 // todo translate NSProcessInfo environment into map
579#endif
1f4c7e79 580#else // non-MSVC non-Mac
164db92c
VZ
581 // Not sure if other compilers have _tenviron so use the (more standard)
582 // ANSI version only for them.
1f4c7e79 583 char **env = environ;
164db92c
VZ
584#endif
585
586 if ( env )
587 {
588 wxString name,
589 value;
590 while ( *env )
591 {
592 const wxString var(*env);
593
594 name = var.BeforeFirst(wxS('='), &value);
595
596 (*map)[name] = value;
597
598 env++;
599 }
600
601 return true;
602 }
603
604 return false;
605}
606
e90c1d2a 607// ----------------------------------------------------------------------------
7c072018 608// wxExecute
e90c1d2a 609// ----------------------------------------------------------------------------
ead7ce10 610
7c072018
VZ
611// wxDoExecuteWithCapture() helper: reads an entire stream into one array
612//
cb719f2e 613// returns true if ok, false if error
7c072018
VZ
614#if wxUSE_STREAMS
615static bool ReadAll(wxInputStream *is, wxArrayString& output)
dfad0599 616{
9a83f860 617 wxCHECK_MSG( is, false, wxT("NULL stream in wxExecute()?") );
dfad0599 618
7c072018
VZ
619 // the stream could be already at EOF or in wxSTREAM_BROKEN_PIPE state
620 is->Reset();
1e6feb95 621
7c072018 622 wxTextInputStream tis(*is);
1e6feb95 623
8bdc8a9c 624 for ( ;; )
d2f50933 625 {
7c072018 626 wxString line = tis.ReadLine();
8bdc8a9c
VZ
627
628 // check for EOF before other errors as it's not really an error
7c072018 629 if ( is->Eof() )
8bdc8a9c
VZ
630 {
631 // add the last, possibly incomplete, line
632 if ( !line.empty() )
633 output.Add(line);
7c072018 634 break;
8bdc8a9c 635 }
7c072018 636
8bdc8a9c 637 // any other error is fatal
7c072018 638 if ( !*is )
8bdc8a9c
VZ
639 return false;
640
641 output.Add(line);
d2f50933
VZ
642 }
643
8bdc8a9c 644 return true;
dfad0599 645}
7c072018 646#endif // wxUSE_STREAMS
d2f50933 647
7c072018
VZ
648// this is a private function because it hasn't a clean interface: the first
649// array is passed by reference, the second by pointer - instead we have 2
650// public versions of wxExecute() below
651static long wxDoExecuteWithCapture(const wxString& command,
652 wxArrayString& output,
4d172154 653 wxArrayString* error,
164db92c
VZ
654 int flags,
655 const wxExecuteEnv *env)
d2f50933 656{
7c072018
VZ
657 // create a wxProcess which will capture the output
658 wxProcess *process = new wxProcess;
659 process->Redirect();
dfad0599 660
164db92c 661 long rc = wxExecute(command, wxEXEC_SYNC | flags, process, env);
1e6feb95 662
7c072018
VZ
663#if wxUSE_STREAMS
664 if ( rc != -1 )
bf31fa26 665 {
7c072018
VZ
666 if ( !ReadAll(process->GetInputStream(), output) )
667 rc = -1;
91b4c08d 668
7c072018
VZ
669 if ( error )
670 {
671 if ( !ReadAll(process->GetErrorStream(), *error) )
672 rc = -1;
673 }
91b4c08d 674
7c072018 675 }
e70ba80d
WS
676#else
677 wxUnusedVar(output);
678 wxUnusedVar(error);
679#endif // wxUSE_STREAMS/!wxUSE_STREAMS
91b4c08d 680
7c072018 681 delete process;
1e6feb95 682
7c072018 683 return rc;
7c072018 684}
bf31fa26 685
164db92c
VZ
686long wxExecute(const wxString& command, wxArrayString& output, int flags,
687 const wxExecuteEnv *env)
bf31fa26 688{
164db92c 689 return wxDoExecuteWithCapture(command, output, NULL, flags, env);
7c072018 690}
bf31fa26 691
7c072018
VZ
692long wxExecute(const wxString& command,
693 wxArrayString& output,
4d172154 694 wxArrayString& error,
164db92c
VZ
695 int flags,
696 const wxExecuteEnv *env)
7c072018 697{
164db92c 698 return wxDoExecuteWithCapture(command, output, &error, flags, env);
bf31fa26
VZ
699}
700
c5f0d1f9 701// ----------------------------------------------------------------------------
fad92e2f 702// Id functions
c5f0d1f9
DE
703// ----------------------------------------------------------------------------
704
c5f0d1f9
DE
705// Id generation
706static long wxCurrentId = 100;
707
708long wxNewId()
709{
710 // skip the part of IDs space that contains hard-coded values:
711 if (wxCurrentId == wxID_LOWEST)
712 wxCurrentId = wxID_HIGHEST + 1;
713
714 return wxCurrentId++;
715}
716
717long
718wxGetCurrentId(void) { return wxCurrentId; }
719
720void
721wxRegisterId (long id)
722{
723 if (id >= wxCurrentId)
724 wxCurrentId = id + 1;
725}
726
fe5f448f
RR
727// ----------------------------------------------------------------------------
728// wxQsort, adapted by RR to allow user_data
729// ----------------------------------------------------------------------------
730
731/* This file is part of the GNU C Library.
732 Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
11fe6505 733
fe5f448f
RR
734 Douglas Schmidt kindly gave permission to relicence the
735 code under the wxWindows licence:
11fe6505 736
fe5f448f
RR
737From: "Douglas C. Schmidt" <schmidt@dre.vanderbilt.edu>
738To: Robert Roebling <robert.roebling@uni-ulm.de>
11fe6505 739Subject: Re: qsort licence
fe5f448f
RR
740Date: Mon, 23 Jul 2007 03:44:25 -0500
741Sender: schmidt@dre.vanderbilt.edu
742Message-Id: <20070723084426.64F511000A8@tango.dre.vanderbilt.edu>
743
744Hi Robert,
745
746> [...] I'm asking if you'd be willing to relicence your code
747> under the wxWindows licence. [...]
748
749That's fine with me [...]
750
751Thanks,
752
753 Doug */
754
755
756/* Byte-wise swap two items of size SIZE. */
11fe6505 757#define SWAP(a, b, size) \
fad92e2f
FM
758 do \
759 { \
760 register size_t __size = (size); \
761 register char *__a = (a), *__b = (b); \
11fe6505 762 do \
fad92e2f
FM
763 { \
764 char __tmp = *__a; \
11fe6505 765 *__a++ = *__b; \
fad92e2f
FM
766 *__b++ = __tmp; \
767 } while (--__size > 0); \
fe5f448f
RR
768 } while (0)
769
770/* Discontinue quicksort algorithm when partition gets below this size.
771 This particular magic number was chosen to work best on a Sun 4/260. */
772#define MAX_THRESH 4
773
774/* Stack node declarations used to store unfulfilled partition obligations. */
775typedef struct
776 {
777 char *lo;
778 char *hi;
779 } stack_node;
780
781/* The next 4 #defines implement a very fast in-line stack abstraction. */
11fe6505 782#define STACK_SIZE (8 * sizeof(unsigned long int))
e71bf8b2
VZ
783#define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
784#define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
785#define STACK_NOT_EMPTY (stack < top)
fe5f448f
RR
786
787
788/* Order size using quicksort. This implementation incorporates
789 four optimizations discussed in Sedgewick:
790
791 1. Non-recursive, using an explicit stack of pointer that store the
792 next array partition to sort. To save time, this maximum amount
793 of space required to store an array of MAX_INT is allocated on the
794 stack. Assuming a 32-bit integer, this needs only 32 *
795 sizeof(stack_node) == 136 bits. Pretty cheap, actually.
796
797 2. Chose the pivot element using a median-of-three decision tree.
798 This reduces the probability of selecting a bad pivot value and
799 eliminates certain extraneous comparisons.
800
801 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
802 insertion sort to order the MAX_THRESH items within each partition.
803 This is a big win, since insertion sort is faster for small, mostly
804 sorted array segments.
805
806 4. The larger of the two sub-partitions is always pushed onto the
807 stack first, with the algorithm then concentrating on the
808 smaller partition. This *guarantees* no more than log (n)
809 stack size is needed (actually O(1) in this case)! */
810
811void wxQsort(void *const pbase, size_t total_elems,
11fe6505 812 size_t size, CMPFUNCDATA cmp, const void* user_data)
fe5f448f
RR
813{
814 register char *base_ptr = (char *) pbase;
815 const size_t max_thresh = MAX_THRESH * size;
816
817 if (total_elems == 0)
818 /* Avoid lossage with unsigned arithmetic below. */
819 return;
820
821 if (total_elems > MAX_THRESH)
822 {
823 char *lo = base_ptr;
824 char *hi = &lo[size * (total_elems - 1)];
825 stack_node stack[STACK_SIZE];
826 stack_node *top = stack;
827
828 PUSH (NULL, NULL);
829
830 while (STACK_NOT_EMPTY)
831 {
832 char *left_ptr;
833 char *right_ptr;
834
11fe6505
VZ
835 /* Select median value from among LO, MID, and HI. Rearrange
836 LO and HI so the three values are sorted. This lowers the
837 probability of picking a pathological pivot value and
838 skips a comparison for both the LEFT_PTR and RIGHT_PTR. */
839
840 char *mid = lo + size * ((hi - lo) / size >> 1);
841
842 if ((*cmp) ((void *) mid, (void *) lo, user_data) < 0)
843 SWAP (mid, lo, size);
844 if ((*cmp) ((void *) hi, (void *) mid, user_data) < 0)
845 SWAP (mid, hi, size);
846 else
847 goto jump_over;
848 if ((*cmp) ((void *) mid, (void *) lo, user_data) < 0)
849 SWAP (mid, lo, size);
850 jump_over:;
851 left_ptr = lo + size;
852 right_ptr = hi - size;
853
854 /* Here's the famous ``collapse the walls'' section of quicksort.
855 Gotta like those tight inner loops! They are the main reason
856 that this algorithm runs much faster than others. */
857 do
858 {
859 while ((*cmp) ((void *) left_ptr, (void *) mid, user_data) < 0)
860 left_ptr += size;
861
862 while ((*cmp) ((void *) mid, (void *) right_ptr, user_data) < 0)
863 right_ptr -= size;
864
865 if (left_ptr < right_ptr)
866 {
867 SWAP (left_ptr, right_ptr, size);
868 if (mid == left_ptr)
869 mid = right_ptr;
870 else if (mid == right_ptr)
871 mid = left_ptr;
872 left_ptr += size;
873 right_ptr -= size;
874 }
875 else if (left_ptr == right_ptr)
876 {
877 left_ptr += size;
878 right_ptr -= size;
879 break;
880 }
881 }
882 while (left_ptr <= right_ptr);
fe5f448f
RR
883
884 /* Set up pointers for next iteration. First determine whether
885 left and right partitions are below the threshold size. If so,
886 ignore one or both. Otherwise, push the larger partition's
887 bounds on the stack and continue sorting the smaller one. */
888
889 if ((size_t) (right_ptr - lo) <= max_thresh)
890 {
891 if ((size_t) (hi - left_ptr) <= max_thresh)
11fe6505 892 /* Ignore both small partitions. */
fe5f448f
RR
893 POP (lo, hi);
894 else
11fe6505 895 /* Ignore small left partition. */
fe5f448f
RR
896 lo = left_ptr;
897 }
898 else if ((size_t) (hi - left_ptr) <= max_thresh)
11fe6505 899 /* Ignore small right partition. */
fe5f448f
RR
900 hi = right_ptr;
901 else if ((right_ptr - lo) > (hi - left_ptr))
902 {
11fe6505 903 /* Push larger left partition indices. */
fe5f448f
RR
904 PUSH (lo, right_ptr);
905 lo = left_ptr;
906 }
907 else
908 {
11fe6505 909 /* Push larger right partition indices. */
fe5f448f
RR
910 PUSH (left_ptr, hi);
911 hi = right_ptr;
912 }
913 }
914 }
915
916 /* Once the BASE_PTR array is partially sorted by quicksort the rest
917 is completely sorted using insertion sort, since this is efficient
918 for partitions below MAX_THRESH size. BASE_PTR points to the beginning
919 of the array to sort, and END_PTR points at the very last element in
920 the array (*not* one beyond it!). */
921
fe5f448f
RR
922 {
923 char *const end_ptr = &base_ptr[size * (total_elems - 1)];
924 char *tmp_ptr = base_ptr;
e71bf8b2
VZ
925 char *thresh = base_ptr + max_thresh;
926 if ( thresh > end_ptr )
927 thresh = end_ptr;
fe5f448f
RR
928 register char *run_ptr;
929
930 /* Find smallest element in first threshold and place it at the
931 array's beginning. This is the smallest array element,
932 and the operation speeds up insertion sort's inner loop. */
933
934 for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size)
935 if ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, user_data) < 0)
936 tmp_ptr = run_ptr;
937
938 if (tmp_ptr != base_ptr)
939 SWAP (tmp_ptr, base_ptr, size);
940
941 /* Insertion sort, running from left-hand-side up to right-hand-side. */
942
943 run_ptr = base_ptr + size;
944 while ((run_ptr += size) <= end_ptr)
945 {
11fe6505
VZ
946 tmp_ptr = run_ptr - size;
947 while ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, user_data) < 0)
948 tmp_ptr -= size;
fe5f448f 949
11fe6505 950 tmp_ptr += size;
fe5f448f
RR
951 if (tmp_ptr != run_ptr)
952 {
953 char *trav;
954
11fe6505
VZ
955 trav = run_ptr + size;
956 while (--trav >= run_ptr)
fe5f448f
RR
957 {
958 char c = *trav;
959 char *hi, *lo;
960
961 for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo)
962 *hi = *lo;
963 *hi = c;
964 }
965 }
966 }
967 }
968}
969
fad92e2f 970#endif // wxUSE_BASE
fe5f448f
RR
971
972
c5f0d1f9
DE
973
974// ============================================================================
975// GUI-only functions from now on
976// ============================================================================
977
978#if wxUSE_GUI
979
f9837e46
VZ
980// this function is only really implemented for X11-based ports, including GTK1
981// (GTK2 sets detectable auto-repeat automatically anyhow)
982#if !(defined(__WXX11__) || defined(__WXMOTIF__) || \
983 (defined(__WXGTK__) && !defined(__WXGTK20__)))
ef3da29b
VZ
984bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag) )
985{
f9837e46 986 return true;
ef3da29b 987}
f9837e46 988#endif // !X11-based port
ef3da29b 989
498a1eeb
RN
990// ----------------------------------------------------------------------------
991// Launch default browser
992// ----------------------------------------------------------------------------
993
7999124f 994#if defined(__WXMSW__)
5ccb95f6 995
50a2e26f
FM
996// implemented in a port-specific utils source file:
997bool wxDoLaunchDefaultBrowser(const wxString& url, const wxString& scheme, int flags);
42d0df00 998
7e86b10b 999#elif defined(__WXX11__) || defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXCOCOA__) || \
766fc092 1000 (defined(__WXOSX__) )
42d0df00 1001
50a2e26f
FM
1002// implemented in a port-specific utils source file:
1003bool wxDoLaunchDefaultBrowser(const wxString& url, int flags);
498a1eeb 1004
f728025e 1005#else
ae46a7fd 1006
50a2e26f
FM
1007// a "generic" implementation:
1008bool wxDoLaunchDefaultBrowser(const wxString& url, int flags)
1009{
1010 // on other platforms try to use mime types or wxExecute...
889fda0c 1011
13a1e96f
DS
1012 bool ok = false;
1013 wxString cmd;
1014
1b1b5318 1015#if wxUSE_MIMETYPE
9a83f860 1016 wxFileType *ft = wxTheMimeTypesManager->GetFileTypeFromExtension(wxT("html"));
7999124f 1017 if ( ft )
657a7545 1018 {
7999124f
VZ
1019 wxString mt;
1020 ft->GetMimeType(&mt);
498a1eeb 1021
13a1e96f 1022 ok = ft->GetOpenCommand(&cmd, wxFileType::MessageParameters(url));
7999124f 1023 delete ft;
498a1eeb 1024 }
1b1b5318 1025#endif // wxUSE_MIMETYPE
13a1e96f
DS
1026
1027 if ( !ok || cmd.empty() )
2830b4a4 1028 {
13a1e96f 1029 // fallback to checking for the BROWSER environment variable
50a2e26f 1030 if ( !wxGetEnv(wxT("BROWSER"), &cmd) || cmd.empty() )
9a83f860 1031 cmd << wxT(' ') << url;
2830b4a4 1032 }
13a1e96f
DS
1033
1034 ok = ( !cmd.empty() && wxExecute(cmd) );
1035 if (ok)
1036 return ok;
1037
1038 // no file type for HTML extension
5519074c 1039 wxLogError(_("No default application configured for HTML files."));
13a1e96f 1040
50a2e26f
FM
1041 return false;
1042}
1043#endif
1044
1045static bool DoLaunchDefaultBrowserHelper(const wxString& urlOrig, int flags)
1046{
1047 // NOTE: we don't have to care about the wxBROWSER_NOBUSYCURSOR flag
1048 // as it was already handled by wxLaunchDefaultBrowser
1049
1050 wxUnusedVar(flags);
1051
1052 wxString url(urlOrig), scheme;
1053 wxURI uri(url);
1054
1055 // this check is useful to avoid that wxURI recognizes as scheme parts of
1056 // the filename, in case urlOrig is a local filename
1057 // (e.g. "C:\\test.txt" when parsed by wxURI reports a scheme == "C")
02b94f4e 1058 bool hasValidScheme = uri.HasScheme() && uri.GetScheme().length() > 1;
50a2e26f
FM
1059
1060#if defined(__WXMSW__)
1061
1062 // NOTE: when testing wxMSW's wxLaunchDefaultBrowser all possible forms
1063 // of the URL/flags should be tested; e.g.:
1064 //
1065 // for (int i=0; i<2; i++)
1066 // {
4290e8ed 1067 // // test arguments without a valid URL scheme:
50a2e26f
FM
1068 // wxLaunchDefaultBrowser("C:\\test.txt", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1069 // wxLaunchDefaultBrowser("wxwidgets.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
4290e8ed
FM
1070 //
1071 // // test arguments with different valid schemes:
50a2e26f
FM
1072 // wxLaunchDefaultBrowser("file:/C%3A/test.txt", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
1073 // wxLaunchDefaultBrowser("http://wxwidgets.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
4290e8ed 1074 // wxLaunchDefaultBrowser("mailto:user@host.org", i==0 ? 0 : wxBROWSER_NEW_WINDOW);
50a2e26f
FM
1075 // }
1076 // (assuming you have a C:\test.txt file)
1077
1078 if ( !hasValidScheme )
1079 {
1080 if (wxFileExists(urlOrig) || wxDirExists(urlOrig))
1081 {
1082 scheme = "file";
1083 // do not prepend the file scheme to the URL as ShellExecuteEx() doesn't like it
1084 }
1085 else
1086 {
1087 url.Prepend(wxS("http://"));
1088 scheme = "http";
1089 }
1090 }
1091 else if ( hasValidScheme )
1092 {
1093 scheme = uri.GetScheme();
1094
1095 if ( uri.GetScheme() == "file" )
1096 {
00aa89f4
VZ
1097 // TODO: extract URLToFileName() to some always compiled in
1098 // function
1099#if wxUSE_FILESYSTEM
4290e8ed 1100 // ShellExecuteEx() doesn't like the "file" scheme when opening local files;
50a2e26f
FM
1101 // remove it
1102 url = wxFileSystem::URLToFileName(url).GetFullPath();
00aa89f4 1103#endif // wxUSE_FILESYSTEM
50a2e26f
FM
1104 }
1105 }
1106
1107 if (wxDoLaunchDefaultBrowser(url, scheme, flags))
1108 return true;
1109 //else: call wxLogSysError
1110#else
1111 if ( !hasValidScheme )
1112 {
1113 // set the scheme of url to "http" or "file" if it does not have one
1114 if (wxFileExists(urlOrig) || wxDirExists(urlOrig))
1115 url.Prepend(wxS("file://"));
1116 else
1117 url.Prepend(wxS("http://"));
1118 }
1119
1120 if (wxDoLaunchDefaultBrowser(url, flags))
1121 return true;
1122 //else: call wxLogSysError
1123#endif
532d575b 1124
5519074c 1125 wxLogSysError(_("Failed to open URL \"%s\" in default browser."),
7999124f 1126 url.c_str());
657a7545 1127
7999124f 1128 return false;
498a1eeb
RN
1129}
1130
f75e0c15
VZ
1131bool wxLaunchDefaultBrowser(const wxString& url, int flags)
1132{
50a2e26f
FM
1133 // NOTE: as documented, "url" may be both a real well-formed URL
1134 // and a local file name
1135
f75e0c15 1136 if ( flags & wxBROWSER_NOBUSYCURSOR )
50a2e26f 1137 return DoLaunchDefaultBrowserHelper(url, flags);
f75e0c15
VZ
1138
1139 wxBusyCursor bc;
50a2e26f 1140 return DoLaunchDefaultBrowserHelper(url, flags);
f75e0c15
VZ
1141}
1142
e90c1d2a 1143// ----------------------------------------------------------------------------
7c072018 1144// Menu accelerators related functions
e90c1d2a
VZ
1145// ----------------------------------------------------------------------------
1146
50a2e26f 1147#if WXWIN_COMPATIBILITY_2_6
7c072018 1148wxChar *wxStripMenuCodes(const wxChar *in, wxChar *out)
e90c1d2a 1149{
9a6384ca 1150#if wxUSE_MENUS
52af3158 1151 wxString s = wxMenuItem::GetLabelText(in);
9a6384ca
WS
1152#else
1153 wxString str(in);
1154 wxString s = wxStripMenuCodes(str);
1155#endif // wxUSE_MENUS
7c072018
VZ
1156 if ( out )
1157 {
1158 // go smash their buffer if it's not big enough - I love char * params
1159 memcpy(out, s.c_str(), s.length() * sizeof(wxChar));
1160 }
1161 else
1162 {
f526f752
MB
1163 out = new wxChar[s.length() + 1];
1164 wxStrcpy(out, s.c_str());
7c072018
VZ
1165 }
1166
1167 return out;
e90c1d2a 1168}
50a2e26f 1169#endif
e90c1d2a 1170
74639764 1171wxString wxStripMenuCodes(const wxString& in, int flags)
e90c1d2a 1172{
9a83f860 1173 wxASSERT_MSG( flags, wxT("this is useless to call without any flags") );
74639764 1174
7c072018 1175 wxString out;
79f585d9 1176
7c072018
VZ
1177 size_t len = in.length();
1178 out.reserve(len);
79f585d9 1179
7c072018
VZ
1180 for ( size_t n = 0; n < len; n++ )
1181 {
1182 wxChar ch = in[n];
9a83f860 1183 if ( (flags & wxStrip_Mnemonics) && ch == wxT('&') )
cd6ce4a9 1184 {
7c072018
VZ
1185 // skip it, it is used to introduce the accel char (or to quote
1186 // itself in which case it should still be skipped): note that it
1187 // can't be the last character of the string
1188 if ( ++n == len )
79f585d9 1189 {
9a83f860 1190 wxLogDebug(wxT("Invalid menu string '%s'"), in.c_str());
7c072018
VZ
1191 }
1192 else
1193 {
1194 // use the next char instead
1195 ch = in[n];
79f585d9 1196 }
cd6ce4a9 1197 }
9a83f860 1198 else if ( (flags & wxStrip_Accel) && ch == wxT('\t') )
79f585d9 1199 {
7c072018
VZ
1200 // everything after TAB is accel string, exit the loop
1201 break;
79f585d9 1202 }
7c072018
VZ
1203
1204 out += ch;
225fe9d6
VZ
1205 }
1206
7c072018 1207 return out;
cd6ce4a9
VZ
1208}
1209
cbc66a27 1210// ----------------------------------------------------------------------------
7c072018 1211// Window search functions
cbc66a27
VZ
1212// ----------------------------------------------------------------------------
1213
7c072018
VZ
1214/*
1215 * If parent is non-NULL, look through children for a label or title
1216 * matching the specified string. If NULL, look through all top-level windows.
1217 *
1218 */
e2a6f233 1219
7c072018
VZ
1220wxWindow *
1221wxFindWindowByLabel (const wxString& title, wxWindow * parent)
134677bd 1222{
7c072018
VZ
1223 return wxWindow::FindWindowByLabel( title, parent );
1224}
b829bf55 1225
b829bf55 1226
7c072018
VZ
1227/*
1228 * If parent is non-NULL, look through children for a name
1229 * matching the specified string. If NULL, look through all top-level windows.
1230 *
1231 */
134677bd 1232
7c072018
VZ
1233wxWindow *
1234wxFindWindowByName (const wxString& name, wxWindow * parent)
2c18f21d 1235{
7c072018 1236 return wxWindow::FindWindowByName( name, parent );
2c18f21d
VS
1237}
1238
cb719f2e 1239// Returns menu item id or wxNOT_FOUND if none.
7c072018 1240int
8d22935d
VZ
1241wxFindMenuItemId(wxFrame *frame,
1242 const wxString& menuString,
1243 const wxString& itemString)
e2a6f233 1244{
7c072018 1245#if wxUSE_MENUS
9a6384ca
WS
1246 wxMenuBar *menuBar = frame->GetMenuBar ();
1247 if ( menuBar )
1248 return menuBar->FindMenuItem (menuString, itemString);
8d22935d
VZ
1249#else // !wxUSE_MENUS
1250 wxUnusedVar(frame);
1251 wxUnusedVar(menuString);
1252 wxUnusedVar(itemString);
1253#endif // wxUSE_MENUS/!wxUSE_MENUS
0fb67cd1 1254
9a6384ca 1255 return wxNOT_FOUND;
e2a6f233
JS
1256}
1257
7c072018
VZ
1258// Try to find the deepest child that contains 'pt'.
1259// We go backwards, to try to allow for controls that are spacially
1260// within other controls, but are still siblings (e.g. buttons within
1261// static boxes). Static boxes are likely to be created _before_ controls
1262// that sit inside them.
1263wxWindow* wxFindWindowAtPoint(wxWindow* win, const wxPoint& pt)
e2a6f233 1264{
7c072018
VZ
1265 if (!win->IsShown())
1266 return NULL;
0fb67cd1 1267
7c072018
VZ
1268 // Hack for wxNotebook case: at least in wxGTK, all pages
1269 // claim to be shown, so we must only deal with the selected one.
1270#if wxUSE_NOTEBOOK
1271 if (win->IsKindOf(CLASSINFO(wxNotebook)))
e2a6f233 1272 {
7c072018
VZ
1273 wxNotebook* nb = (wxNotebook*) win;
1274 int sel = nb->GetSelection();
1275 if (sel >= 0)
1276 {
1277 wxWindow* child = nb->GetPage(sel);
1278 wxWindow* foundWin = wxFindWindowAtPoint(child, pt);
1279 if (foundWin)
1280 return foundWin;
1281 }
e2a6f233 1282 }
7c072018 1283#endif
0fb67cd1 1284
df5168c4 1285 wxWindowList::compatibility_iterator node = win->GetChildren().GetLast();
7c072018
VZ
1286 while (node)
1287 {
1288 wxWindow* child = node->GetData();
1289 wxWindow* foundWin = wxFindWindowAtPoint(child, pt);
1290 if (foundWin)
1291 return foundWin;
1292 node = node->GetPrevious();
1293 }
1294
1295 wxPoint pos = win->GetPosition();
1296 wxSize sz = win->GetSize();
7aa7d2d4 1297 if ( !win->IsTopLevel() && win->GetParent() )
7c072018
VZ
1298 {
1299 pos = win->GetParent()->ClientToScreen(pos);
1300 }
1301
1302 wxRect rect(pos, sz);
22a35096 1303 if (rect.Contains(pt))
7c072018 1304 return win;
622eb786
VZ
1305
1306 return NULL;
0fb67cd1
VZ
1307}
1308
7c072018 1309wxWindow* wxGenericFindWindowAtPoint(const wxPoint& pt)
0fb67cd1 1310{
7c072018
VZ
1311 // Go backwards through the list since windows
1312 // on top are likely to have been appended most
1313 // recently.
df5168c4 1314 wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetLast();
7c072018
VZ
1315 while (node)
1316 {
1317 wxWindow* win = node->GetData();
1318 wxWindow* found = wxFindWindowAtPoint(win, pt);
1319 if (found)
1320 return found;
1321 node = node->GetPrevious();
1322 }
1323 return NULL;
1324}
0fb67cd1 1325
7c072018
VZ
1326// ----------------------------------------------------------------------------
1327// GUI helpers
1328// ----------------------------------------------------------------------------
0fb67cd1 1329
7c072018
VZ
1330/*
1331 * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp
1332 * since otherwise the generic code may be pulled in unnecessarily.
1333 */
0fb67cd1 1334
7c072018 1335#if wxUSE_MSGDLG
0fb67cd1 1336
7c072018
VZ
1337int wxMessageBox(const wxString& message, const wxString& caption, long style,
1338 wxWindow *parent, int WXUNUSED(x), int WXUNUSED(y) )
0fb67cd1 1339{
7e3204b4
VZ
1340 // add the appropriate icon unless this was explicitly disabled by use of
1341 // wxICON_NONE
1342 if ( !(style & wxICON_NONE) && !(style & wxICON_MASK) )
53a6ac21 1343 {
7e3204b4 1344 style |= style & wxYES ? wxICON_QUESTION : wxICON_INFORMATION;
53a6ac21
DS
1345 }
1346
7e3204b4 1347 wxMessageDialog dialog(parent, message, caption, style);
0fb67cd1 1348
7c072018
VZ
1349 int ans = dialog.ShowModal();
1350 switch ( ans )
1351 {
1352 case wxID_OK:
1353 return wxOK;
1354 case wxID_YES:
1355 return wxYES;
1356 case wxID_NO:
1357 return wxNO;
1358 case wxID_CANCEL:
1359 return wxCANCEL;
1360 }
0fb67cd1 1361
9a83f860 1362 wxFAIL_MSG( wxT("unexpected return code from wxMessageDialog") );
0fb67cd1 1363
7c072018 1364 return wxCANCEL;
e2a6f233
JS
1365}
1366
ccec9093 1367wxVersionInfo wxGetLibraryVersionInfo()
8cf304f8
VZ
1368{
1369 // don't translate these strings, they're for diagnostics purposes only
1370 wxString msg;
32be10a4
VZ
1371 msg.Printf(wxS("wxWidgets Library (%s port)\n")
1372 wxS("Version %d.%d.%d (Unicode: %s, debug level: %d),\n")
1373 wxS("compiled at %s %s\n\n")
1374 wxS("Runtime version of toolkit used is %d.%d.\n"),
1375 wxPlatformInfo::Get().GetPortIdName(),
8cf304f8
VZ
1376 wxMAJOR_VERSION,
1377 wxMINOR_VERSION,
1378 wxRELEASE_NUMBER,
32be10a4
VZ
1379#if wxUSE_UNICODE_UTF8
1380 "UTF-8",
1381#elif wxUSE_UNICODE
1382 "wchar_t",
8cf304f8 1383#else
32be10a4 1384 "none",
8cf304f8 1385#endif
32be10a4 1386 wxDEBUG_LEVEL,
8cf304f8
VZ
1387 __TDATE__,
1388 __TTIME__,
1389 wxPlatformInfo::Get().GetToolkitMajorVersion(),
32be10a4
VZ
1390 wxPlatformInfo::Get().GetToolkitMinorVersion()
1391 );
1392
8cf304f8 1393#ifdef __WXGTK__
32be10a4
VZ
1394 msg += wxString::Format("Compile-time GTK+ version is %d.%d.%d.\n",
1395 GTK_MAJOR_VERSION,
1396 GTK_MINOR_VERSION,
1397 GTK_MICRO_VERSION);
1398#endif // __WXGTK__
1399
ccec9093
VZ
1400 return wxVersionInfo(wxS("wxWidgets"),
1401 wxMAJOR_VERSION,
1402 wxMINOR_VERSION,
1403 wxRELEASE_NUMBER,
1404 msg,
1405 wxS("Copyright (c) 1995-2010 wxWidgets team"));
1406}
1407
1408void wxInfoMessageBox(wxWindow* parent)
1409{
1410 wxVersionInfo info = wxGetLibraryVersionInfo();
1411 wxString msg = info.ToString();
1412
1413 msg << wxS("\n") << info.GetCopyright();
32be10a4 1414
9a83f860 1415 wxMessageBox(msg, wxT("wxWidgets information"),
8cf304f8
VZ
1416 wxICON_INFORMATION | wxOK,
1417 parent);
1418}
1419
7c072018 1420#endif // wxUSE_MSGDLG
518b5d2f 1421
7c072018 1422#if wxUSE_TEXTDLG
518b5d2f 1423
7c072018
VZ
1424wxString wxGetTextFromUser(const wxString& message, const wxString& caption,
1425 const wxString& defaultValue, wxWindow *parent,
13d13a9e 1426 wxCoord x, wxCoord y, bool centre )
7c072018
VZ
1427{
1428 wxString str;
13d13a9e
WS
1429 long style = wxTextEntryDialogStyle;
1430
1431 if (centre)
1432 style |= wxCENTRE;
1433 else
1434 style &= ~wxCENTRE;
1435
1436 wxTextEntryDialog dialog(parent, message, caption, defaultValue, style, wxPoint(x, y));
1437
7c072018
VZ
1438 if (dialog.ShowModal() == wxID_OK)
1439 {
1440 str = dialog.GetValue();
1441 }
0fb67cd1 1442
7c072018 1443 return str;
518b5d2f
VZ
1444}
1445
7c072018
VZ
1446wxString wxGetPasswordFromUser(const wxString& message,
1447 const wxString& caption,
1448 const wxString& defaultValue,
b3bb2a74
KH
1449 wxWindow *parent,
1450 wxCoord x, wxCoord y, bool centre )
96c5bd7f 1451{
7c072018 1452 wxString str;
b3bb2a74
KH
1453 long style = wxTextEntryDialogStyle;
1454
1455 if (centre)
1456 style |= wxCENTRE;
1457 else
1458 style &= ~wxCENTRE;
1459
12cfa304
KH
1460 wxPasswordEntryDialog dialog(parent, message, caption, defaultValue,
1461 style, wxPoint(x, y));
7c072018
VZ
1462 if ( dialog.ShowModal() == wxID_OK )
1463 {
1464 str = dialog.GetValue();
1465 }
96c5bd7f 1466
7c072018
VZ
1467 return str;
1468}
96c5bd7f 1469
7c072018 1470#endif // wxUSE_TEXTDLG
96c5bd7f 1471
7c072018 1472#if wxUSE_COLOURDLG
96c5bd7f 1473
f75e0c15
VZ
1474wxColour wxGetColourFromUser(wxWindow *parent,
1475 const wxColour& colInit,
e6ef9ea4
VZ
1476 const wxString& caption,
1477 wxColourData *ptrData)
c51deffc 1478{
e6ef9ea4
VZ
1479 // contains serialized representation of wxColourData used the last time
1480 // the dialog was shown: we want to reuse it the next time in order to show
1481 // the same custom colours to the user (and we can't just have static
1482 // wxColourData itself because it's a GUI object and so should be destroyed
1483 // before GUI shutdown and doing it during static cleanup is too late)
1484 static wxString s_strColourData;
1485
7c072018 1486 wxColourData data;
e6ef9ea4 1487 if ( !ptrData )
7c072018 1488 {
e6ef9ea4
VZ
1489 ptrData = &data;
1490 if ( !s_strColourData.empty() )
1491 {
1492 if ( !data.FromString(s_strColourData) )
1493 {
1494 wxFAIL_MSG( "bug in wxColourData::FromString()?" );
1495 }
1496
1497#ifdef __WXMSW__
1498 // we don't get back the "choose full" flag value from the native
1499 // dialog and so we can't preserve it between runs, so we decide to
1500 // always use it as it seems better than not using it (user can
1501 // just ignore the extra controls in the dialog but having to click
1502 // a button each time to show them would be very annoying
1503 data.SetChooseFull(true);
1504#endif // __WXMSW__
1505 }
1506 }
1507
1508 if ( colInit.IsOk() )
1509 {
1510 ptrData->SetColour(colInit);
7c072018 1511 }
c51deffc 1512
7c072018 1513 wxColour colRet;
e6ef9ea4 1514 wxColourDialog dialog(parent, ptrData);
76b49cf4 1515 if (!caption.empty())
f14d6dd1 1516 dialog.SetTitle(caption);
7c072018
VZ
1517 if ( dialog.ShowModal() == wxID_OK )
1518 {
e6ef9ea4
VZ
1519 *ptrData = dialog.GetColourData();
1520 colRet = ptrData->GetColour();
1521 s_strColourData = ptrData->ToString();
7c072018 1522 }
e6ef9ea4 1523 //else: leave colRet invalid
7c072018
VZ
1524
1525 return colRet;
c51deffc 1526}
bc385ba9 1527
7c072018 1528#endif // wxUSE_COLOURDLG
bc385ba9 1529
7c072018
VZ
1530#if wxUSE_FONTDLG
1531
f14d6dd1 1532wxFont wxGetFontFromUser(wxWindow *parent, const wxFont& fontInit, const wxString& caption)
bc385ba9 1533{
7c072018
VZ
1534 wxFontData data;
1535 if ( fontInit.Ok() )
bc385ba9 1536 {
7c072018
VZ
1537 data.SetInitialFont(fontInit);
1538 }
bc385ba9 1539
7c072018
VZ
1540 wxFont fontRet;
1541 wxFontDialog dialog(parent, data);
76b49cf4 1542 if (!caption.empty())
f14d6dd1 1543 dialog.SetTitle(caption);
7c072018
VZ
1544 if ( dialog.ShowModal() == wxID_OK )
1545 {
1546 fontRet = dialog.GetFontData().GetChosenFont();
1547 }
1548 //else: leave it invalid
bc385ba9 1549
7c072018 1550 return fontRet;
bc385ba9
VZ
1551}
1552
7c072018 1553#endif // wxUSE_FONTDLG
2b5f62a0 1554
7c072018
VZ
1555// ----------------------------------------------------------------------------
1556// wxSafeYield and supporting functions
1557// ----------------------------------------------------------------------------
2b5f62a0 1558
7c072018
VZ
1559void wxEnableTopLevelWindows(bool enable)
1560{
df5168c4 1561 wxWindowList::compatibility_iterator node;
7c072018
VZ
1562 for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
1563 node->GetData()->Enable(enable);
1564}
2b5f62a0 1565
2ecd1756
VZ
1566wxWindowDisabler::wxWindowDisabler(bool disable)
1567{
1568 m_disabled = disable;
1569 if ( disable )
1570 DoDisable();
1571}
1572
7c072018 1573wxWindowDisabler::wxWindowDisabler(wxWindow *winToSkip)
2ecd1756
VZ
1574{
1575 m_disabled = true;
1576 DoDisable(winToSkip);
1577}
1578
1579void wxWindowDisabler::DoDisable(wxWindow *winToSkip)
7c072018
VZ
1580{
1581 // remember the top level windows which were already disabled, so that we
1582 // don't reenable them later
1583 m_winDisabled = NULL;
1584
df5168c4 1585 wxWindowList::compatibility_iterator node;
7c072018 1586 for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
2b5f62a0 1587 {
7c072018
VZ
1588 wxWindow *winTop = node->GetData();
1589 if ( winTop == winToSkip )
1590 continue;
2b5f62a0 1591
7c072018
VZ
1592 // we don't need to disable the hidden or already disabled windows
1593 if ( winTop->IsEnabled() && winTop->IsShown() )
2b5f62a0 1594 {
7c072018 1595 winTop->Disable();
2b5f62a0
VZ
1596 }
1597 else
1598 {
7c072018
VZ
1599 if ( !m_winDisabled )
1600 {
1601 m_winDisabled = new wxWindowList;
1602 }
1603
1604 m_winDisabled->Append(winTop);
2b5f62a0
VZ
1605 }
1606 }
2b5f62a0
VZ
1607}
1608
7c072018 1609wxWindowDisabler::~wxWindowDisabler()
cd6ce4a9 1610{
2ecd1756
VZ
1611 if ( !m_disabled )
1612 return;
1613
df5168c4 1614 wxWindowList::compatibility_iterator node;
7c072018 1615 for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
cd6ce4a9 1616 {
7c072018
VZ
1617 wxWindow *winTop = node->GetData();
1618 if ( !m_winDisabled || !m_winDisabled->Find(winTop) )
cd6ce4a9 1619 {
7c072018 1620 winTop->Enable();
cd6ce4a9 1621 }
7c072018 1622 //else: had been already disabled, don't reenable
cd6ce4a9 1623 }
f6bcfd97 1624
7c072018 1625 delete m_winDisabled;
f6bcfd97
BP
1626}
1627
7c072018
VZ
1628// Yield to other apps/messages and disable user input to all windows except
1629// the given one
1630bool wxSafeYield(wxWindow *win, bool onlyIfNeeded)
f6bcfd97 1631{
7c072018 1632 wxWindowDisabler wd(win);
21709999 1633
7c072018
VZ
1634 bool rc;
1635 if (onlyIfNeeded)
1636 rc = wxYieldIfNeeded();
1637 else
1638 rc = wxYield();
8461e4c2 1639
7c072018 1640 return rc;
8461e4c2
VZ
1641}
1642
fad92e2f
FM
1643// ----------------------------------------------------------------------------
1644// wxApp::Yield() wrappers for backwards compatibility
1645// ----------------------------------------------------------------------------
1646
1647bool wxYield()
8461e4c2 1648{
fad92e2f
FM
1649 return wxTheApp && wxTheApp->Yield();
1650}
1651
1652bool wxYieldIfNeeded()
1653{
1654 return wxTheApp && wxTheApp->Yield(true);
8461e4c2 1655}
7c072018
VZ
1656
1657#endif // wxUSE_GUI