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