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