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