]> git.saurik.com Git - wxWidgets.git/blob - src/common/utilscmn.cpp
Fixed a bug in the latest 'micro optimization' - was skipping one
[wxWidgets.git] / src / common / utilscmn.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: 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 license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "utils.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #ifndef WX_PRECOMP
32 #include "wx/defs.h"
33 #include "wx/string.h"
34 #include "wx/utils.h"
35 #include "wx/intl.h"
36 #include "wx/log.h"
37
38 #if wxUSE_GUI
39 #include "wx/window.h"
40 #include "wx/menu.h"
41 #include "wx/frame.h"
42 #include "wx/msgdlg.h"
43 #include "wx/textdlg.h"
44 #if wxUSE_ACCEL
45 #include "wx/menuitem.h"
46 #include "wx/accel.h"
47 #endif // wxUSE_ACCEL
48 #endif // wxUSE_GUI
49 #endif // WX_PRECOMP
50
51 #include "wx/process.h"
52 #include "wx/txtstrm.h"
53
54 #include <ctype.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58
59 #if !defined(__WATCOMC__)
60 #if !(defined(_MSC_VER) && (_MSC_VER > 800))
61 #include <errno.h>
62 #endif
63 #endif
64
65 #if wxUSE_GUI
66 #include "wx/colordlg.h"
67 #endif // wxUSE_GUI
68
69 #include <time.h>
70
71 #ifndef __MWERKS__
72 #include <sys/types.h>
73 #include <sys/stat.h>
74 #endif
75
76 #ifdef __SALFORDC__
77 #include <clib.h>
78 #endif
79
80 #ifdef __WXMSW__
81 #include "wx/msw/private.h"
82 #endif
83
84 // ----------------------------------------------------------------------------
85 // function protoypes
86 // ----------------------------------------------------------------------------
87
88 #if wxUSE_GUI
89 static wxWindow *wxFindWindowByLabel1(const wxString& title, wxWindow *parent);
90 static wxWindow *wxFindWindowByName1 (const wxString& title, wxWindow *parent);
91 #endif // wxUSE_GUI
92
93 // ============================================================================
94 // implementation
95 // ============================================================================
96
97 // ----------------------------------------------------------------------------
98 // string functions
99 // ----------------------------------------------------------------------------
100
101 #ifdef __WXMAC__
102 int strcasecmp(const char *str_1, const char *str_2)
103 {
104 register char c1, c2;
105 do {
106 c1 = tolower(*str_1++);
107 c2 = tolower(*str_2++);
108 } while ( c1 && (c1 == c2) );
109
110 return c1 - c2;
111 }
112
113 int strncasecmp(const char *str_1, const char *str_2, size_t maxchar)
114 {
115
116 register char c1, c2;
117 while( maxchar--)
118 {
119 c1 = tolower(*str_1++);
120 c2 = tolower(*str_2++);
121
122 if ( !c1 || c1!=c2 )
123 return c1 - c2;
124
125 } ;
126
127 return 0 ;
128
129 }
130 #endif // wxMAC
131
132 #if defined( __VMS__ ) && ( __VMS_VER < 70000000 )
133 // we have no strI functions under VMS, therefore I have implemented
134 // an inefficient but portable version: convert copies of strings to lowercase
135 // and then use the normal comparison
136 static void myLowerString(char *s)
137 {
138 while(*s){
139 if(isalpha(*s)) *s = (char)tolower(*s);
140 s++;
141 }
142 }
143
144 int strcasecmp(const char *str_1, const char *str_2)
145 {
146 char *temp1 = new char[strlen(str_1)+1];
147 char *temp2 = new char[strlen(str_2)+1];
148 strcpy(temp1,str_1);
149 strcpy(temp2,str_2);
150 myLowerString(temp1);
151 myLowerString(temp2);
152
153 int result = wxStrcmp(temp1,temp2);
154 delete[] temp1;
155 delete[] temp2;
156
157 return(result);
158 }
159
160 int strncasecmp(const char *str_1, const char *str_2, size_t maxchar)
161 {
162 char *temp1 = new char[strlen(str_1)+1];
163 char *temp2 = new char[strlen(str_2)+1];
164 strcpy(temp1,str_1);
165 strcpy(temp2,str_2);
166 myLowerString(temp1);
167 myLowerString(temp2);
168
169 int result = strncmp(temp1,temp2,maxchar);
170 delete[] temp1;
171 delete[] temp2;
172
173 return(result);
174 }
175 #endif // __VMS__
176
177 #ifdef __WINDOWS__
178
179 #ifndef __GNUWIN32__
180 #ifndef __MWERKS__
181 #define strcasecmp stricmp
182 #define strncasecmp strnicmp
183 #else
184 #define strcasecmp _stricmp
185 #define strncasecmp _strnicmp
186 #endif
187 #endif
188
189 #else
190
191 #ifdef __EMX__
192 #define strcasecmp stricmp
193 #define strncasecmp strnicmp
194 #endif
195
196 // This declaration is missing in SunOS!
197 // (Yes, I know it is NOT ANSI-C but its in BSD libc)
198 #if defined(__xlC) || defined(__AIX__) || defined(__GNUG__)
199 extern "C"
200 {
201 int strcasecmp (const char *, const char *);
202 int strncasecmp (const char *, const char *, size_t);
203 }
204 #endif
205 #endif /* __WXMSW__ */
206
207 #ifdef __WXPM__
208 #define strcasecmp stricmp
209 #define strncasecmp strnicmp
210 #endif
211
212 wxChar *
213 copystring (const wxChar *s)
214 {
215 if (s == NULL) s = wxT("");
216 size_t len = wxStrlen (s) + 1;
217
218 wxChar *news = new wxChar[len];
219 memcpy (news, s, len * sizeof(wxChar)); // Should be the fastest
220
221 return news;
222 }
223
224 // Id generation
225 static long wxCurrentId = 100;
226
227 long
228 wxNewId (void)
229 {
230 return wxCurrentId++;
231 }
232
233 long
234 wxGetCurrentId(void) { return wxCurrentId; }
235
236 void
237 wxRegisterId (long id)
238 {
239 if (id >= wxCurrentId)
240 wxCurrentId = id + 1;
241 }
242
243 void
244 StringToFloat (wxChar *s, float *number)
245 {
246 if (s && *s && number)
247 *number = (float) wxStrtod (s, (wxChar **) NULL);
248 }
249
250 void
251 StringToDouble (wxChar *s, double *number)
252 {
253 if (s && *s && number)
254 *number = wxStrtod (s, (wxChar **) NULL);
255 }
256
257 wxChar *
258 FloatToString (float number, const wxChar *fmt)
259 {
260 static wxChar buf[256];
261
262 // sprintf (buf, "%.2f", number);
263 wxSprintf (buf, fmt, number);
264 return buf;
265 }
266
267 wxChar *
268 DoubleToString (double number, const wxChar *fmt)
269 {
270 static wxChar buf[256];
271
272 wxSprintf (buf, fmt, number);
273 return buf;
274 }
275
276 void
277 StringToInt (wxChar *s, int *number)
278 {
279 if (s && *s && number)
280 *number = (int) wxStrtol (s, (wxChar **) NULL, 10);
281 }
282
283 void
284 StringToLong (wxChar *s, long *number)
285 {
286 if (s && *s && number)
287 *number = wxStrtol (s, (wxChar **) NULL, 10);
288 }
289
290 wxChar *
291 IntToString (int number)
292 {
293 static wxChar buf[20];
294
295 wxSprintf (buf, wxT("%d"), number);
296 return buf;
297 }
298
299 wxChar *
300 LongToString (long number)
301 {
302 static wxChar buf[20];
303
304 wxSprintf (buf, wxT("%ld"), number);
305 return buf;
306 }
307
308 // Array used in DecToHex conversion routine.
309 static wxChar hexArray[] = wxT("0123456789ABCDEF");
310
311 // Convert 2-digit hex number to decimal
312 int wxHexToDec(const wxString& buf)
313 {
314 int firstDigit, secondDigit;
315
316 if (buf.GetChar(0) >= wxT('A'))
317 firstDigit = buf.GetChar(0) - wxT('A') + 10;
318 else
319 firstDigit = buf.GetChar(0) - wxT('0');
320
321 if (buf.GetChar(1) >= wxT('A'))
322 secondDigit = buf.GetChar(1) - wxT('A') + 10;
323 else
324 secondDigit = buf.GetChar(1) - wxT('0');
325
326 return firstDigit * 16 + secondDigit;
327 }
328
329 // Convert decimal integer to 2-character hex string
330 void wxDecToHex(int dec, wxChar *buf)
331 {
332 int firstDigit = (int)(dec/16.0);
333 int secondDigit = (int)(dec - (firstDigit*16.0));
334 buf[0] = hexArray[firstDigit];
335 buf[1] = hexArray[secondDigit];
336 buf[2] = 0;
337 }
338
339 // Convert decimal integer to 2-character hex string
340 wxString wxDecToHex(int dec)
341 {
342 wxChar buf[3];
343 wxDecToHex(dec, buf);
344 return wxString(buf);
345 }
346
347 // Match a string INDEPENDENT OF CASE
348 bool
349 StringMatch (char *str1, char *str2, bool subString, bool exact)
350 {
351 if (str1 == NULL || str2 == NULL)
352 return FALSE;
353 if (str1 == str2)
354 return TRUE;
355
356 if (subString)
357 {
358 int len1 = strlen (str1);
359 int len2 = strlen (str2);
360 int i;
361
362 // Search for str1 in str2
363 // Slow .... but acceptable for short strings
364 for (i = 0; i <= len2 - len1; i++)
365 {
366 if (strncasecmp (str1, str2 + i, len1) == 0)
367 return TRUE;
368 }
369 }
370 else if (exact)
371 {
372 if (strcasecmp (str1, str2) == 0)
373 return TRUE;
374 }
375 else
376 {
377 int len1 = strlen (str1);
378 int len2 = strlen (str2);
379
380 if (strncasecmp (str1, str2, wxMin (len1, len2)) == 0)
381 return TRUE;
382 }
383
384 return FALSE;
385 }
386
387 // Return the current date/time
388 // [volatile]
389 wxString wxNow()
390 {
391 time_t now = time((time_t *) NULL);
392 char *date = ctime(&now);
393 date[24] = '\0';
394 return wxString(date);
395 }
396
397 #if wxUSE_GUI
398
399 // ----------------------------------------------------------------------------
400 // Menu accelerators related functions
401 // ----------------------------------------------------------------------------
402
403 wxChar *wxStripMenuCodes (wxChar *in, wxChar *out)
404 {
405 if (!in)
406 return (wxChar *) NULL;
407
408 if (!out)
409 out = copystring(in);
410
411 wxChar *tmpOut = out;
412
413 while (*in)
414 {
415 if (*in == wxT('&'))
416 {
417 // Check && -> &, &x -> x
418 if (*++in == wxT('&'))
419 *out++ = *in++;
420 }
421 else if (*in == wxT('\t'))
422 {
423 // Remove all stuff after \t in X mode, and let the stuff as is
424 // in Windows mode.
425 // Accelerators are handled in wx_item.cc for Motif, and are not
426 // YET supported in XView
427 break;
428 }
429 else
430 *out++ = *in++;
431 } // while
432
433 *out = wxT('\0');
434
435 return tmpOut;
436 }
437
438 wxString wxStripMenuCodes(const wxString& str)
439 {
440 wxChar *buf = new wxChar[str.Length() + 1];
441 wxStripMenuCodes(WXSTRINGCAST str, buf);
442 wxString str1(buf);
443 delete[] buf;
444 return str1;
445 }
446
447 #if wxUSE_ACCEL
448
449 // return wxAcceleratorEntry for the given menu string or NULL if none
450 // specified
451 wxAcceleratorEntry *wxGetAccelFromString(const wxString& label)
452 {
453 // check for accelerators: they are given after '\t'
454 int posTab = label.Find(wxT('\t'));
455 if ( posTab != wxNOT_FOUND ) {
456 // parse the accelerator string
457 int keyCode = 0;
458 int accelFlags = wxACCEL_NORMAL;
459 wxString current;
460 for ( size_t n = (size_t)posTab + 1; n < label.Len(); n++ ) {
461 if ( (label[n] == '+') || (label[n] == '-') ) {
462 if ( current == _("ctrl") )
463 accelFlags |= wxACCEL_CTRL;
464 else if ( current == _("alt") )
465 accelFlags |= wxACCEL_ALT;
466 else if ( current == _("shift") )
467 accelFlags |= wxACCEL_SHIFT;
468 else {
469 wxLogDebug(wxT("Unknown accel modifier: '%s'"),
470 current.c_str());
471 }
472
473 current.Empty();
474 }
475 else {
476 current += wxTolower(label[n]);
477 }
478 }
479
480 if ( current.IsEmpty() ) {
481 wxLogDebug(wxT("No accel key found, accel string ignored."));
482 }
483 else {
484 if ( current.Len() == 1 ) {
485 // it's a letter
486 keyCode = wxToupper(current[0U]);
487 }
488 else {
489 // is it a function key?
490 if ( current[0U] == 'f' && isdigit(current[1U]) &&
491 (current.Len() == 2 ||
492 (current.Len() == 3 && isdigit(current[2U]))) ) {
493 int n;
494 wxSscanf(current.c_str() + 1, wxT("%d"), &n);
495
496 keyCode = WXK_F1 + n - 1;
497 }
498 else {
499 #if 0 // this is not supported by GTK+, apparently
500 // several special cases
501 current.MakeUpper();
502 if ( current == wxT("DEL") ) {
503 keyCode = VK_DELETE;
504 }
505 else if ( current == wxT("PGUP") ) {
506 keyCode = VK_PRIOR;
507 }
508 else if ( current == wxT("PGDN") ) {
509 keyCode = VK_NEXT;
510 }
511 else
512 #endif // 0
513 {
514 wxLogDebug(wxT("Unrecognized accel key '%s', accel "
515 "string ignored."), current.c_str());
516 }
517 }
518 }
519 }
520
521 if ( keyCode ) {
522 // we do have something
523 return new wxAcceleratorEntry(accelFlags, keyCode);
524 }
525 }
526
527 return (wxAcceleratorEntry *)NULL;
528 }
529
530 #endif // wxUSE_ACCEL
531
532 // ----------------------------------------------------------------------------
533 // Window search functions
534 // ----------------------------------------------------------------------------
535
536 /*
537 * If parent is non-NULL, look through children for a label or title
538 * matching the specified string. If NULL, look through all top-level windows.
539 *
540 */
541
542 wxWindow *
543 wxFindWindowByLabel (const wxString& title, wxWindow * parent)
544 {
545 if (parent)
546 {
547 return wxFindWindowByLabel1(title, parent);
548 }
549 else
550 {
551 for ( wxWindowList::Node * node = wxTopLevelWindows.GetFirst();
552 node;
553 node = node->GetNext() )
554 {
555 wxWindow *win = node->GetData();
556 wxWindow *retwin = wxFindWindowByLabel1 (title, win);
557 if (retwin)
558 return retwin;
559 } // for()
560
561 }
562 return (wxWindow *) NULL;
563 }
564
565 // Recursive
566 static wxWindow *
567 wxFindWindowByLabel1 (const wxString& title, wxWindow * parent)
568 {
569 if (parent)
570 {
571 if (parent->GetLabel() == title)
572 return parent;
573 }
574
575 if (parent)
576 {
577 for ( wxWindowList::Node * node = parent->GetChildren().GetFirst();
578 node;
579 node = node->GetNext() )
580 {
581 wxWindow *win = (wxWindow *)node->GetData();
582 wxWindow *retwin = wxFindWindowByLabel1 (title, win);
583 if (retwin)
584 return retwin;
585 }
586
587 }
588
589 return (wxWindow *) NULL; // Not found
590 }
591
592 /*
593 * If parent is non-NULL, look through children for a name
594 * matching the specified string. If NULL, look through all top-level windows.
595 *
596 */
597
598 wxWindow *
599 wxFindWindowByName (const wxString& title, wxWindow * parent)
600 {
601 if (parent)
602 {
603 return wxFindWindowByName1 (title, parent);
604 }
605 else
606 {
607 for ( wxWindowList::Node * node = wxTopLevelWindows.GetFirst();
608 node;
609 node = node->GetNext() )
610 {
611 wxWindow *win = node->GetData();
612 wxWindow *retwin = wxFindWindowByName1 (title, win);
613 if (retwin)
614 return retwin;
615 }
616
617 }
618
619 // Failed? Try by label instead.
620 return wxFindWindowByLabel(title, parent);
621 }
622
623 // Recursive
624 static wxWindow *
625 wxFindWindowByName1 (const wxString& title, wxWindow * parent)
626 {
627 if (parent)
628 {
629 if ( parent->GetName() == title )
630 return parent;
631 }
632
633 if (parent)
634 {
635 for (wxNode * node = parent->GetChildren().First (); node; node = node->Next ())
636 {
637 wxWindow *win = (wxWindow *) node->Data ();
638 wxWindow *retwin = wxFindWindowByName1 (title, win);
639 if (retwin)
640 return retwin;
641 } // for()
642
643 }
644
645 return (wxWindow *) NULL; // Not found
646
647 }
648
649 // Returns menu item id or -1 if none.
650 int
651 wxFindMenuItemId (wxFrame * frame, const wxString& menuString, const wxString& itemString)
652 {
653 wxMenuBar *menuBar = frame->GetMenuBar ();
654 if (!menuBar)
655 return -1;
656 return menuBar->FindMenuItem (menuString, itemString);
657 }
658
659 #endif // wxUSE_GUI
660
661 /*
662 On Fri, 21 Jul 1995, Paul Craven wrote:
663
664 > Is there a way to find the path of running program's executable? I can get
665 > my home directory, and the current directory, but I don't know how to get the
666 > executable directory.
667 >
668
669 The code below (warty as it is), does what you want on most Unix,
670 DOS, and Mac platforms (it's from the ALS Prolog main).
671
672 || Ken Bowen Applied Logic Systems, Inc. PO Box 180,
673 ||==== Voice: +1 (617)965-9191 Newton Centre,
674 || FAX: +1 (617)965-1636 MA 02159 USA
675 Email: ken@als.com WWW: http://www.als.com
676 ------------------------------------------------------------------------
677 */
678
679 // This code is commented out but it may be integrated with wxWin at
680 // a later date, after testing. Thanks Ken!
681 #if 0
682
683 /*--------------------------------------------------------------------*
684 | whereami is given a filename f in the form: whereami(argv[0])
685 | It returns the directory in which the executable file (containing
686 | this code [main.c] ) may be found. A dot will be returned to indicate
687 | the current directory.
688 *--------------------------------------------------------------------*/
689
690 static void
691 whereami(name)
692 char *name;
693 {
694 register char *cutoff = NULL; /* stifle -Wall */
695 register char *s;
696 register char *t;
697 int cc;
698 char ebuf[4096];
699
700 /*
701 * See if the file is accessible either through the current directory
702 * or through an absolute path.
703 */
704
705 if (access(name, R_OK) == 0) {
706
707 /*-------------------------------------------------------------*
708 * The file was accessible without any other work. But the current
709 * working directory might change on us, so if it was accessible
710 * through the cwd, then we should get it for later accesses.
711 *-------------------------------------------------------------*/
712
713 t = imagedir;
714 if (!absolute_pathname(name)) {
715 #if defined(DOS) || defined(__WIN32__)
716 int drive;
717 char *newrbuf;
718
719 newrbuf = imagedir;
720 #ifndef __DJGPP__
721 if (*(name + 1) == ':') {
722 if (*name >= 'a' && *name <= 'z')
723 drive = (int) (*name - 'a' + 1);
724 else
725 drive = (int) (*name - 'A' + 1);
726 *newrbuf++ = *name;
727 *newrbuf++ = *(name + 1);
728 *newrbuf++ = DIR_SEPARATOR;
729 }
730 else {
731 drive = 0;
732 *newrbuf++ = DIR_SEPARATOR;
733 }
734 if (getcwd(newrbuf, drive) == 0) { /* } */
735 #else
736 if (getcwd(newrbuf, 1024) == 0) { /* } */
737 #endif
738 #else /* DOS */
739 #ifdef HAVE_GETWD
740 if (getwd(imagedir) == 0) { /* } */
741 #else /* !HAVE_GETWD */
742 if (getcwd(imagedir, 1024) == 0) {
743 #endif /* !HAVE_GETWD */
744 #endif /* DOS */
745 fatal_error(FE_GETCWD, 0);
746 }
747 for (; *t; t++) /* Set t to end of buffer */
748 ;
749 if (*(t - 1) == DIR_SEPARATOR) /* leave slash if already
750 * last char
751 */
752 cutoff = t - 1;
753 else {
754 cutoff = t; /* otherwise put one in */
755 *t++ = DIR_SEPARATOR;
756 }
757 }
758 #if (!defined(__MAC__) && !defined(__DJGPP__) && !defined(__GO32__) && !defined(__WIN32__))
759 else
760 (*t++ = DIR_SEPARATOR);
761 #endif
762
763 /*-------------------------------------------------------------*
764 * Copy the rest of the string and set the cutoff if it was not
765 * already set. If the first character of name is a slash, cutoff
766 * is not presently set but will be on the first iteration of the
767 * loop below.
768 *-------------------------------------------------------------*/
769
770 for ((*name == DIR_SEPARATOR ? (s = name+1) : (s = name));;) {
771 if (*s == DIR_SEPARATOR)
772 cutoff = t;
773 if (!(*t++ = *s++))
774 break;
775 }
776
777 }
778 else {
779
780 /*-------------------------------------------------------------*
781 * Get the path list from the environment. If the path list is
782 * inaccessible for any reason, leave with fatal error.
783 *-------------------------------------------------------------*/
784
785 #ifdef __MAC__
786 if ((s = getenv("Commands")) == (char *) 0)
787 #else
788 if ((s = getenv("PATH")) == (char *) 0)
789 #endif
790 fatal_error(FE_PATH, 0);
791
792 /*
793 * Copy path list into ebuf and set the source pointer to the
794 * beginning of this buffer.
795 */
796
797 strcpy(ebuf, s);
798 s = ebuf;
799
800 for (;;) {
801 t = imagedir;
802 while (*s && *s != PATH_SEPARATOR)
803 *t++ = *s++;
804 if (t > imagedir && *(t - 1) == DIR_SEPARATOR)
805 ; /* do nothing -- slash already is in place */
806 else
807 *t++ = DIR_SEPARATOR; /* put in the slash */
808 cutoff = t - 1; /* set cutoff */
809 strcpy(t, name);
810 if (access(imagedir, R_OK) == 0)
811 break;
812
813 if (*s)
814 s++; /* advance source pointer */
815 else
816 fatal_error(FE_INFND, 0);
817 }
818
819 }
820
821 /*-------------------------------------------------------------*
822 | At this point the full pathname should exist in imagedir and
823 | cutoff should be set to the final slash. We must now determine
824 | whether the file name is a symbolic link or not and chase it down
825 | if it is. Note that we reuse ebuf for getting the link.
826 *-------------------------------------------------------------*/
827
828 #ifdef HAVE_SYMLINK
829 while ((cc = readlink(imagedir, ebuf, 512)) != -1) {
830 ebuf[cc] = 0;
831 s = ebuf;
832 if (*s == DIR_SEPARATOR) {
833 t = imagedir;
834 }
835 else {
836 t = cutoff + 1;
837 }
838 for (;;) {
839 if (*s == DIR_SEPARATOR)
840 cutoff = t; /* mark the last slash seen */
841 if (!(*t++ = *s++)) /* copy the character */
842 break;
843 }
844 }
845
846 #endif /* HAVE_SYMLINK */
847
848 strcpy(imagename, cutoff + 1); /* keep the image name */
849 *(cutoff + 1) = 0; /* chop off the filename part */
850 }
851
852 #endif
853
854 #if wxUSE_GUI
855
856 // ----------------------------------------------------------------------------
857 // GUI helpers
858 // ----------------------------------------------------------------------------
859
860 /*
861 * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp
862 * since otherwise the generic code may be pulled in unnecessarily.
863 */
864
865 int wxMessageBox(const wxString& message, const wxString& caption, long style,
866 wxWindow *parent, int WXUNUSED(x), int WXUNUSED(y) )
867 {
868 wxMessageDialog dialog(parent, message, caption, style);
869
870 int ans = dialog.ShowModal();
871 switch ( ans )
872 {
873 case wxID_OK:
874 return wxOK;
875 case wxID_YES:
876 return wxYES;
877 case wxID_NO:
878 return wxNO;
879 default:
880 case wxID_CANCEL:
881 return wxCANCEL;
882 }
883 }
884
885 #if wxUSE_TEXTDLG
886 wxString wxGetTextFromUser(const wxString& message, const wxString& caption,
887 const wxString& defaultValue, wxWindow *parent,
888 int x, int y, bool WXUNUSED(centre) )
889 {
890 wxString str;
891 wxTextEntryDialog dialog(parent, message, caption, defaultValue, wxOK|wxCANCEL, wxPoint(x, y));
892 if (dialog.ShowModal() == wxID_OK)
893 {
894 str = dialog.GetValue();
895 }
896
897 return str;
898 }
899
900 wxString wxGetPasswordFromUser(const wxString& message,
901 const wxString& caption,
902 const wxString& defaultValue,
903 wxWindow *parent)
904 {
905 wxString str;
906 wxTextEntryDialog dialog(parent, message, caption, defaultValue,
907 wxOK | wxCANCEL | wxTE_PASSWORD);
908 if ( dialog.ShowModal() == wxID_OK )
909 {
910 str = dialog.GetValue();
911 }
912
913 return str;
914 }
915
916 #endif // wxUSE_TEXTDLG
917
918 wxColour wxGetColourFromUser(wxWindow *parent, const wxColour& colInit)
919 {
920 wxColourData data;
921 data.SetChooseFull(TRUE);
922 if ( colInit.Ok() )
923 {
924 data.SetColour((wxColour &)colInit); // const_cast
925 }
926
927 wxColour colRet;
928 wxColourDialog dialog(parent, &data);
929 if ( dialog.ShowModal() == wxID_OK )
930 {
931 colRet = dialog.GetColourData().GetColour();
932 }
933 //else: leave it invalid
934
935 return colRet;
936 }
937
938 // ----------------------------------------------------------------------------
939 // missing C RTL functions (FIXME shouldn't be here at all)
940 // ----------------------------------------------------------------------------
941
942 #ifdef __MWERKS__
943 char *strdup(const char *s)
944 {
945 return strcpy( (char*) malloc( strlen( s ) + 1 ) , s ) ;
946 }
947
948 int isascii( int c )
949 {
950 return ( c >= 0 && c < 128 ) ;
951 }
952 #endif // __MWERKS__
953
954 // ----------------------------------------------------------------------------
955 // wxSafeYield and supporting functions
956 // ----------------------------------------------------------------------------
957
958 void wxEnableTopLevelWindows(bool enable)
959 {
960 wxWindowList::Node *node;
961 for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
962 node->GetData()->Enable(enable);
963 }
964
965 wxWindowDisabler::wxWindowDisabler(wxWindow *winToSkip)
966 {
967 #ifdef __WXMSW__
968 #ifdef __WIN32__
969 // and the top level window too
970 HWND hwndFG = ::GetForegroundWindow();
971 m_winTop = hwndFG ? wxFindWinFromHandle((WXHWND)hwndFG) : (wxWindow *)NULL;
972 #else
973 HWND hwndFG = ::GetTopWindow();
974 m_winTop = hwndFG ? wxFindWinFromHandle((WXHWND)hwndFG) : (wxWindow *)NULL;
975 #endif
976 #endif // MSW
977
978 // remember the top level windows which were already disabled, so that we
979 // don't reenable them later
980 m_winDisabled = NULL;
981
982 wxWindowList::Node *node;
983 for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
984 {
985 wxWindow *winTop = node->GetData();
986 if ( winTop == winToSkip )
987 continue;
988
989 if ( winTop->IsEnabled() )
990 {
991 winTop->Disable();
992 }
993 else
994 {
995 if ( !m_winDisabled )
996 {
997 m_winDisabled = new wxWindowList;
998 }
999
1000 m_winDisabled->Append(winTop);
1001 }
1002 }
1003 }
1004
1005 wxWindowDisabler::~wxWindowDisabler()
1006 {
1007 wxWindowList::Node *node;
1008 for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
1009 {
1010 wxWindow *winTop = node->GetData();
1011 if ( !m_winDisabled || !m_winDisabled->Find(winTop) )
1012 {
1013 winTop->Enable();
1014 }
1015 //else: had been already disabled, don't reenable
1016 }
1017
1018 delete m_winDisabled;
1019
1020 #ifdef __WXMSW__
1021 #ifdef __WIN32__
1022 if ( m_winTop )
1023 {
1024 if ( !::SetForegroundWindow(GetHwndOf(m_winTop)) )
1025 {
1026 wxLogLastError("SetForegroundWindow");
1027 }
1028 }
1029 #else
1030 if ( m_winTop )
1031 {
1032 // 16-bit SetForegroundWindow() replacement
1033 RECT reWin;
1034 GetWindowRect(m_winTop, &reWin);
1035 SetWindowPos (m_winTop, HWND_TOP,
1036 reWin.left, reWin.top,
1037 reWin.right - reWin.left, reWin.bottom,
1038 SWP_SHOWWINDOW);
1039 }
1040 #endif
1041 #endif // MSW
1042 }
1043
1044 // Yield to other apps/messages and disable user input to all windows except
1045 // the given one
1046 bool wxSafeYield(wxWindow *win)
1047 {
1048 wxWindowDisabler wd;
1049
1050 bool rc = wxYield();
1051
1052 return rc;
1053 }
1054
1055 // ----------------------------------------------------------------------------
1056 // misc functions
1057 // ----------------------------------------------------------------------------
1058
1059 // Don't synthesize KeyUp events holding down a key and producing KeyDown
1060 // events with autorepeat. On by default and always on in wxMSW. wxGTK version
1061 // in utilsgtk.cpp.
1062 #ifndef __WXGTK__
1063 bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag) )
1064 {
1065 return TRUE; // detectable auto-repeat is the only mode MSW supports
1066 }
1067 #endif // !wxGTK
1068
1069 #endif // wxUSE_GUI
1070
1071 // ----------------------------------------------------------------------------
1072 // network and user id functions
1073 // ----------------------------------------------------------------------------
1074
1075 // Get Full RFC822 style email address
1076 bool wxGetEmailAddress(wxChar *address, int maxSize)
1077 {
1078 wxString email = wxGetEmailAddress();
1079 if ( !email )
1080 return FALSE;
1081
1082 wxStrncpy(address, email, maxSize - 1);
1083 address[maxSize - 1] = wxT('\0');
1084
1085 return TRUE;
1086 }
1087
1088 wxString wxGetEmailAddress()
1089 {
1090 wxString email;
1091
1092 wxString host = wxGetHostName();
1093 if ( !!host )
1094 {
1095 wxString user = wxGetUserId();
1096 if ( !!user )
1097 {
1098 wxString email(user);
1099 email << wxT('@') << host;
1100 }
1101 }
1102
1103 return email;
1104 }
1105
1106 wxString wxGetUserId()
1107 {
1108 static const int maxLoginLen = 256; // FIXME arbitrary number
1109
1110 wxString buf;
1111 bool ok = wxGetUserId(buf.GetWriteBuf(maxLoginLen), maxLoginLen);
1112 buf.UngetWriteBuf();
1113
1114 if ( !ok )
1115 buf.Empty();
1116
1117 return buf;
1118 }
1119
1120 wxString wxGetUserName()
1121 {
1122 static const int maxUserNameLen = 1024; // FIXME arbitrary number
1123
1124 wxString buf;
1125 bool ok = wxGetUserName(buf.GetWriteBuf(maxUserNameLen), maxUserNameLen);
1126 buf.UngetWriteBuf();
1127
1128 if ( !ok )
1129 buf.Empty();
1130
1131 return buf;
1132 }
1133
1134 wxString wxGetHostName()
1135 {
1136 static const size_t hostnameSize = 257;
1137
1138 wxString buf;
1139 bool ok = wxGetHostName(buf.GetWriteBuf(hostnameSize), hostnameSize);
1140
1141 buf.UngetWriteBuf();
1142
1143 if ( !ok )
1144 buf.Empty();
1145
1146 return buf;
1147 }
1148
1149 wxString wxGetFullHostName()
1150 {
1151 static const size_t hostnameSize = 257;
1152
1153 wxString buf;
1154 bool ok = wxGetFullHostName(buf.GetWriteBuf(hostnameSize), hostnameSize);
1155
1156 buf.UngetWriteBuf();
1157
1158 if ( !ok )
1159 buf.Empty();
1160
1161 return buf;
1162 }
1163
1164 wxString wxGetHomeDir()
1165 {
1166 wxString home;
1167 wxGetHomeDir(&home);
1168
1169 return home;
1170 }
1171
1172 #if 0
1173
1174 wxString wxGetCurrentDir()
1175 {
1176 wxString dir;
1177 size_t len = 1024;
1178 bool ok;
1179 do
1180 {
1181 ok = getcwd(dir.GetWriteBuf(len + 1), len) != NULL;
1182 dir.UngetWriteBuf();
1183
1184 if ( !ok )
1185 {
1186 if ( errno != ERANGE )
1187 {
1188 wxLogSysError(_T("Failed to get current directory"));
1189
1190 return wxEmptyString;
1191 }
1192 else
1193 {
1194 // buffer was too small, retry with a larger one
1195 len *= 2;
1196 }
1197 }
1198 //else: ok
1199 } while ( !ok );
1200
1201 return dir;
1202 }
1203
1204 #endif // 0
1205
1206 // ----------------------------------------------------------------------------
1207 // wxExecute
1208 // ----------------------------------------------------------------------------
1209
1210 long wxExecute(const wxString& command, wxArrayString& output)
1211 {
1212 // create a wxProcess which will capture the output
1213 wxProcess *process = new wxProcess;
1214 process->Redirect();
1215
1216 long rc = wxExecute(command, TRUE /* sync */, process);
1217 if ( rc != -1 )
1218 {
1219 wxInputStream& is = *process->GetInputStream();
1220 wxTextInputStream tis(is);
1221 while ( !is.Eof() && is.IsOk() )
1222 {
1223 wxString line = tis.ReadLine();
1224 if ( is.LastError() )
1225 break;
1226
1227 output.Add(line);
1228 }
1229 }
1230
1231 return rc;
1232 }