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