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