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