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