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