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