]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/utilscmn.cpp
implemented menu drawing in the GTK theme
[wxWidgets.git] / src / common / utilscmn.cpp
... / ...
CommitLineData
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__)
119int 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
130int 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
153static void myLowerString(char *s)
154{
155 while(*s){
156 if(isalpha(*s)) *s = (char)tolower(*s);
157 s++;
158 }
159}
160
161int 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
177int 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__)
216extern "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
234wxChar *
235copystring (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
247static long wxCurrentId = 100;
248
249long
250wxNewId (void)
251{
252 return wxCurrentId++;
253}
254
255long
256wxGetCurrentId(void) { return wxCurrentId; }
257
258void
259wxRegisterId (long id)
260{
261 if (id >= wxCurrentId)
262 wxCurrentId = id + 1;
263}
264
265void
266StringToFloat (const wxChar *s, float *number)
267{
268 if (s && *s && number)
269 *number = (float) wxStrtod (s, (wxChar **) NULL);
270}
271
272void
273StringToDouble (const wxChar *s, double *number)
274{
275 if (s && *s && number)
276 *number = wxStrtod (s, (wxChar **) NULL);
277}
278
279wxChar *
280FloatToString (float number, const wxChar *fmt)
281{
282 static wxChar buf[256];
283
284 wxSprintf (buf, fmt, number);
285 return buf;
286}
287
288wxChar *
289DoubleToString (double number, const wxChar *fmt)
290{
291 static wxChar buf[256];
292
293 wxSprintf (buf, fmt, number);
294 return buf;
295}
296
297void
298StringToInt (const wxChar *s, int *number)
299{
300 if (s && *s && number)
301 *number = (int) wxStrtol (s, (wxChar **) NULL, 10);
302}
303
304void
305StringToLong (const wxChar *s, long *number)
306{
307 if (s && *s && number)
308 *number = wxStrtol (s, (wxChar **) NULL, 10);
309}
310
311wxChar *
312IntToString (int number)
313{
314 static wxChar buf[20];
315
316 wxSprintf (buf, wxT("%d"), number);
317 return buf;
318}
319
320wxChar *
321LongToString (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.
330static wxChar hexArray[] = wxT("0123456789ABCDEF");
331
332// Convert 2-digit hex number to decimal
333int 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
351void 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
361wxString 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
369bool
370StringMatch (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]
410wxString 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
426wxChar *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
442wxString 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
491wxWindow *
492wxFindWindowByLabel (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
515static wxWindow *
516wxFindWindowByLabel1 (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
547wxWindow *
548wxFindWindowByName (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
573static wxWindow *
574wxFindWindowByName1 (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.
599int
600wxFindMenuItemId (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.
616wxWindow* 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
686wxWindow* 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/*
706On 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
713The code below (warty as it is), does what you want on most Unix,
714DOS, 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
734static void
735whereami(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
911int 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
938wxString 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
952wxString 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
972wxColour 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
996wxFont 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
1022char *strdup(const char *s)
1023{
1024 return strcpy( (char*) malloc( strlen( s ) + 1 ) , s ) ;
1025}
1026#endif
1027int isascii( int c )
1028{
1029 return ( c >= 0 && c < 128 ) ;
1030}
1031#endif // __MWERKS__
1032
1033// ----------------------------------------------------------------------------
1034// wxSafeYield and supporting functions
1035// ----------------------------------------------------------------------------
1036
1037void wxEnableTopLevelWindows(bool enable)
1038{
1039 wxWindowList::Node *node;
1040 for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
1041 node->GetData()->Enable(enable);
1042}
1043
1044wxWindowDisabler::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
1073wxWindowDisabler::~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
1091bool 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__
1108bool 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
1116const 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
1130wxString 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
1148bool 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
1160wxString 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
1177wxString 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
1191wxString 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
1205wxString 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
1220wxString 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
1235wxString wxGetHomeDir()
1236{
1237 wxString home;
1238 wxGetHomeDir(&home);
1239
1240 return home;
1241}
1242
1243#if 0
1244
1245wxString 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
1284static 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
1356long wxExecute(const wxString& command, wxArrayString& output)
1357{
1358 return wxDoExecuteWithCapture(command, output, NULL);
1359}
1360
1361long 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
1372bool wxYield()
1373{
1374#if wxUSE_GUI
1375 return wxTheApp && wxTheApp->Yield();
1376#else
1377 return FALSE;
1378#endif
1379}
1380
1381bool wxYieldIfNeeded()
1382{
1383#if wxUSE_GUI
1384 return wxTheApp && wxTheApp->Yield(TRUE);
1385#else
1386 return FALSE;
1387#endif
1388}
1389