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