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