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