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