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