]>
git.saurik.com Git - wxWidgets.git/blob - src/common/utilscmn.cpp
1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Miscellaneous utility functions and classes
4 // Author: Julian Smart
8 // Copyright: (c) 1998 Julian Smart
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
21 #pragma implementation "utils.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
33 #include "wx/string.h"
39 #include "wx/window.h"
42 #include "wx/msgdlg.h"
43 #include "wx/textdlg.h"
45 #include "wx/menuitem.h"
56 #if !defined(__WATCOMC__)
57 #if !(defined(_MSC_VER) && (_MSC_VER > 800))
65 #include <sys/types.h>
73 // Pattern matching code. (FIXME)
74 // Yes, this path is deliberate (for Borland compilation)
75 #ifdef wx_mac /* MATTHEW: [5] Mac doesn't like paths with "/" */
78 #include "../common/glob.inc"
85 // ----------------------------------------------------------------------------
87 // ----------------------------------------------------------------------------
90 static wxWindow
*wxFindWindowByLabel1(const wxString
& title
, wxWindow
*parent
);
91 static wxWindow
*wxFindWindowByName1 (const wxString
& title
, wxWindow
*parent
);
94 // ============================================================================
96 // ============================================================================
98 // ----------------------------------------------------------------------------
100 // ----------------------------------------------------------------------------
103 int strcasecmp(const char *str_1
, const char *str_2
)
105 register char c1
, c2
;
107 c1
= tolower(*str_1
++);
108 c2
= tolower(*str_2
++);
109 } while ( c1
&& (c1
== c2
) );
114 int strncasecmp(const char *str_1
, const char *str_2
, size_t maxchar
)
117 register char c1
, c2
;
120 c1
= tolower(*str_1
++);
121 c2
= tolower(*str_2
++);
134 // we have no strI functions under VMS, therefore I have implemented
135 // an inefficient but portable version: convert copies of strings to lowercase
136 // and then use the normal comparison
137 static void myLowerString(char *s
)
140 if(isalpha(*s
)) *s
= (char)tolower(*s
);
145 int strcasecmp(const char *str_1
, const char *str_2
)
147 char *temp1
= new char[strlen(str_1
)+1];
148 char *temp2
= new char[strlen(str_2
)+1];
151 myLowerString(temp1
);
152 myLowerString(temp2
);
154 int result
= strcmp(temp1
,temp2
);
161 int strncasecmp(const char *str_1
, const char *str_2
, size_t maxchar
)
163 char *temp1
= new char[strlen(str_1
)+1];
164 char *temp2
= new char[strlen(str_2
)+1];
167 myLowerString(temp1
);
168 myLowerString(temp2
);
170 int result
= strncmp(temp1
,temp2
,maxchar
);
182 #define strcasecmp stricmp
183 #define strncasecmp strnicmp
185 #define strcasecmp _stricmp
186 #define strncasecmp _strnicmp
193 #define strcasecmp stricmp
194 #define strncasecmp strnicmp
197 // This declaration is missing in SunOS!
198 // (Yes, I know it is NOT ANSI-C but its in BSD libc)
199 #if defined(__xlC) || defined(__AIX__) || defined(__GNUG__)
202 int strcasecmp (const char *, const char *);
203 int strncasecmp (const char *, const char *, size_t);
206 #endif /* __WXMSW__ */
209 #define strcasecmp stricmp
210 #define strncasecmp strnicmp
214 copystring (const wxChar
*s
)
216 if (s
== NULL
) s
= wxT("");
217 size_t len
= wxStrlen (s
) + 1;
219 wxChar
*news
= new wxChar
[len
];
220 memcpy (news
, s
, len
* sizeof(wxChar
)); // Should be the fastest
226 static long wxCurrentId
= 100;
231 return wxCurrentId
++;
235 wxGetCurrentId(void) { return wxCurrentId
; }
238 wxRegisterId (long id
)
240 if (id
>= wxCurrentId
)
241 wxCurrentId
= id
+ 1;
245 StringToFloat (wxChar
*s
, float *number
)
247 if (s
&& *s
&& number
)
248 *number
= (float) wxStrtod (s
, (wxChar
**) NULL
);
252 StringToDouble (wxChar
*s
, double *number
)
254 if (s
&& *s
&& number
)
255 *number
= wxStrtod (s
, (wxChar
**) NULL
);
259 FloatToString (float number
, const wxChar
*fmt
)
261 static wxChar buf
[256];
263 // sprintf (buf, "%.2f", number);
264 wxSprintf (buf
, fmt
, number
);
269 DoubleToString (double number
, const wxChar
*fmt
)
271 static wxChar buf
[256];
273 wxSprintf (buf
, fmt
, number
);
278 StringToInt (wxChar
*s
, int *number
)
280 if (s
&& *s
&& number
)
281 *number
= (int) wxStrtol (s
, (wxChar
**) NULL
, 10);
285 StringToLong (wxChar
*s
, long *number
)
287 if (s
&& *s
&& number
)
288 *number
= wxStrtol (s
, (wxChar
**) NULL
, 10);
292 IntToString (int number
)
294 static wxChar buf
[20];
296 wxSprintf (buf
, wxT("%d"), number
);
301 LongToString (long number
)
303 static wxChar buf
[20];
305 wxSprintf (buf
, wxT("%ld"), number
);
309 // Array used in DecToHex conversion routine.
310 static wxChar hexArray
[] = wxT("0123456789ABCDEF");
312 // Convert 2-digit hex number to decimal
313 int wxHexToDec(const wxString
& buf
)
315 int firstDigit
, secondDigit
;
317 if (buf
.GetChar(0) >= wxT('A'))
318 firstDigit
= buf
.GetChar(0) - wxT('A') + 10;
320 firstDigit
= buf
.GetChar(0) - wxT('0');
322 if (buf
.GetChar(1) >= wxT('A'))
323 secondDigit
= buf
.GetChar(1) - wxT('A') + 10;
325 secondDigit
= buf
.GetChar(1) - wxT('0');
327 return firstDigit
* 16 + secondDigit
;
330 // Convert decimal integer to 2-character hex string
331 void wxDecToHex(int dec
, wxChar
*buf
)
333 int firstDigit
= (int)(dec
/16.0);
334 int secondDigit
= (int)(dec
- (firstDigit
*16.0));
335 buf
[0] = hexArray
[firstDigit
];
336 buf
[1] = hexArray
[secondDigit
];
340 // Convert decimal integer to 2-character hex string
341 wxString
wxDecToHex(int dec
)
344 wxDecToHex(dec
, buf
);
345 return wxString(buf
);
348 // Match a string INDEPENDENT OF CASE
350 StringMatch (char *str1
, char *str2
, bool subString
, bool exact
)
352 if (str1
== NULL
|| str2
== NULL
)
359 int len1
= strlen (str1
);
360 int len2
= strlen (str2
);
363 // Search for str1 in str2
364 // Slow .... but acceptable for short strings
365 for (i
= 0; i
<= len2
- len1
; i
++)
367 if (strncasecmp (str1
, str2
+ i
, len1
) == 0)
373 if (strcasecmp (str1
, str2
) == 0)
378 int len1
= strlen (str1
);
379 int len2
= strlen (str2
);
381 if (strncasecmp (str1
, str2
, wxMin (len1
, len2
)) == 0)
388 // Return the current date/time
392 time_t now
= time((time_t *) NULL
);
393 char *date
= ctime(&now
);
395 return wxString(date
);
400 // ----------------------------------------------------------------------------
401 // Menu accelerators related functions
402 // ----------------------------------------------------------------------------
404 wxChar
*wxStripMenuCodes (wxChar
*in
, wxChar
*out
)
407 return (wxChar
*) NULL
;
410 out
= copystring(in
);
412 wxChar
*tmpOut
= out
;
418 // Check && -> &, &x -> x
419 if (*++in
== wxT('&'))
422 else if (*in
== wxT('\t'))
424 // Remove all stuff after \t in X mode, and let the stuff as is
426 // Accelerators are handled in wx_item.cc for Motif, and are not
427 // YET supported in XView
439 wxString
wxStripMenuCodes(const wxString
& str
)
441 wxChar
*buf
= new wxChar
[str
.Length() + 1];
442 wxStripMenuCodes(WXSTRINGCAST str
, buf
);
450 // return wxAcceleratorEntry for the given menu string or NULL if none
452 wxAcceleratorEntry
*wxGetAccelFromString(const wxString
& label
)
454 // check for accelerators: they are given after '\t'
455 int posTab
= label
.Find(wxT('\t'));
456 if ( posTab
!= wxNOT_FOUND
) {
457 // parse the accelerator string
459 int accelFlags
= wxACCEL_NORMAL
;
461 for ( size_t n
= (size_t)posTab
+ 1; n
< label
.Len(); n
++ ) {
462 if ( (label
[n
] == '+') || (label
[n
] == '-') ) {
463 if ( current
== _("ctrl") )
464 accelFlags
|= wxACCEL_CTRL
;
465 else if ( current
== _("alt") )
466 accelFlags
|= wxACCEL_ALT
;
467 else if ( current
== _("shift") )
468 accelFlags
|= wxACCEL_SHIFT
;
470 wxLogDebug(wxT("Unknown accel modifier: '%s'"),
477 current
+= wxTolower(label
[n
]);
481 if ( current
.IsEmpty() ) {
482 wxLogDebug(wxT("No accel key found, accel string ignored."));
485 if ( current
.Len() == 1 ) {
487 keyCode
= wxToupper(current
[0U]);
490 // is it a function key?
491 if ( current
[0U] == 'f' && isdigit(current
[1U]) &&
492 (current
.Len() == 2 ||
493 (current
.Len() == 3 && isdigit(current
[2U]))) ) {
495 wxSscanf(current
.c_str() + 1, wxT("%d"), &n
);
497 keyCode
= WXK_F1
+ n
- 1;
500 #if 0 // this is not supported by GTK+, apparently
501 // several special cases
503 if ( current
== wxT("DEL") ) {
506 else if ( current
== wxT("PGUP") ) {
509 else if ( current
== wxT("PGDN") ) {
515 wxLogDebug(wxT("Unrecognized accel key '%s', accel "
516 "string ignored."), current
.c_str());
523 // we do have something
524 return new wxAcceleratorEntry(accelFlags
, keyCode
);
531 #endif // wxUSE_ACCEL
533 // ----------------------------------------------------------------------------
534 // Window search functions
535 // ----------------------------------------------------------------------------
538 * If parent is non-NULL, look through children for a label or title
539 * matching the specified string. If NULL, look through all top-level windows.
544 wxFindWindowByLabel (const wxString
& title
, wxWindow
* parent
)
548 return wxFindWindowByLabel1(title
, parent
);
552 for ( wxWindowList::Node
* node
= wxTopLevelWindows
.GetFirst();
554 node
= node
->GetNext() )
556 wxWindow
*win
= node
->GetData();
557 wxWindow
*retwin
= wxFindWindowByLabel1 (title
, win
);
563 return (wxWindow
*) NULL
;
568 wxFindWindowByLabel1 (const wxString
& title
, wxWindow
* parent
)
572 if (parent
->GetLabel() == title
)
578 for ( wxWindowList::Node
* node
= parent
->GetChildren().GetFirst();
580 node
= node
->GetNext() )
582 wxWindow
*win
= (wxWindow
*)node
->GetData();
583 wxWindow
*retwin
= wxFindWindowByLabel1 (title
, win
);
590 return (wxWindow
*) NULL
; // Not found
594 * If parent is non-NULL, look through children for a name
595 * matching the specified string. If NULL, look through all top-level windows.
600 wxFindWindowByName (const wxString
& title
, wxWindow
* parent
)
604 return wxFindWindowByName1 (title
, parent
);
608 for ( wxWindowList::Node
* node
= wxTopLevelWindows
.GetFirst();
610 node
= node
->GetNext() )
612 wxWindow
*win
= node
->GetData();
613 wxWindow
*retwin
= wxFindWindowByName1 (title
, win
);
620 // Failed? Try by label instead.
621 return wxFindWindowByLabel(title
, parent
);
626 wxFindWindowByName1 (const wxString
& title
, wxWindow
* parent
)
630 if ( parent
->GetName() == title
)
636 for (wxNode
* node
= parent
->GetChildren().First (); node
; node
= node
->Next ())
638 wxWindow
*win
= (wxWindow
*) node
->Data ();
639 wxWindow
*retwin
= wxFindWindowByName1 (title
, win
);
646 return (wxWindow
*) NULL
; // Not found
650 // Returns menu item id or -1 if none.
652 wxFindMenuItemId (wxFrame
* frame
, const wxString
& menuString
, const wxString
& itemString
)
654 wxMenuBar
*menuBar
= frame
->GetMenuBar ();
657 return menuBar
->FindMenuItem (menuString
, itemString
);
663 On Fri, 21 Jul 1995, Paul Craven wrote:
665 > Is there a way to find the path of running program's executable? I can get
666 > my home directory, and the current directory, but I don't know how to get the
667 > executable directory.
670 The code below (warty as it is), does what you want on most Unix,
671 DOS, and Mac platforms (it's from the ALS Prolog main).
673 || Ken Bowen Applied Logic Systems, Inc. PO Box 180,
674 ||==== Voice: +1 (617)965-9191 Newton Centre,
675 || FAX: +1 (617)965-1636 MA 02159 USA
676 Email: ken@als.com WWW: http://www.als.com
677 ------------------------------------------------------------------------
680 // This code is commented out but it may be integrated with wxWin at
681 // a later date, after testing. Thanks Ken!
684 /*--------------------------------------------------------------------*
685 | whereami is given a filename f in the form: whereami(argv[0])
686 | It returns the directory in which the executable file (containing
687 | this code [main.c] ) may be found. A dot will be returned to indicate
688 | the current directory.
689 *--------------------------------------------------------------------*/
695 register char *cutoff
= NULL
; /* stifle -Wall */
702 * See if the file is accessible either through the current directory
703 * or through an absolute path.
706 if (access(name
, R_OK
) == 0) {
708 /*-------------------------------------------------------------*
709 * The file was accessible without any other work. But the current
710 * working directory might change on us, so if it was accessible
711 * through the cwd, then we should get it for later accesses.
712 *-------------------------------------------------------------*/
715 if (!absolute_pathname(name
)) {
716 #if defined(DOS) || defined(__WIN32__)
722 if (*(name
+ 1) == ':') {
723 if (*name
>= 'a' && *name
<= 'z')
724 drive
= (int) (*name
- 'a' + 1);
726 drive
= (int) (*name
- 'A' + 1);
728 *newrbuf
++ = *(name
+ 1);
729 *newrbuf
++ = DIR_SEPARATOR
;
733 *newrbuf
++ = DIR_SEPARATOR
;
735 if (getcwd(newrbuf
, drive
) == 0) { /* } */
737 if (getcwd(newrbuf
, 1024) == 0) { /* } */
741 if (getwd(imagedir
) == 0) { /* } */
742 #else /* !HAVE_GETWD */
743 if (getcwd(imagedir
, 1024) == 0) {
744 #endif /* !HAVE_GETWD */
746 fatal_error(FE_GETCWD
, 0);
748 for (; *t
; t
++) /* Set t to end of buffer */
750 if (*(t
- 1) == DIR_SEPARATOR
) /* leave slash if already
755 cutoff
= t
; /* otherwise put one in */
756 *t
++ = DIR_SEPARATOR
;
759 #if (!defined(__MAC__) && !defined(__DJGPP__) && !defined(__GO32__) && !defined(__WIN32__))
761 (*t
++ = DIR_SEPARATOR
);
764 /*-------------------------------------------------------------*
765 * Copy the rest of the string and set the cutoff if it was not
766 * already set. If the first character of name is a slash, cutoff
767 * is not presently set but will be on the first iteration of the
769 *-------------------------------------------------------------*/
771 for ((*name
== DIR_SEPARATOR
? (s
= name
+1) : (s
= name
));;) {
772 if (*s
== DIR_SEPARATOR
)
781 /*-------------------------------------------------------------*
782 * Get the path list from the environment. If the path list is
783 * inaccessible for any reason, leave with fatal error.
784 *-------------------------------------------------------------*/
787 if ((s
= getenv("Commands")) == (char *) 0)
789 if ((s
= getenv("PATH")) == (char *) 0)
791 fatal_error(FE_PATH
, 0);
794 * Copy path list into ebuf and set the source pointer to the
795 * beginning of this buffer.
803 while (*s
&& *s
!= PATH_SEPARATOR
)
805 if (t
> imagedir
&& *(t
- 1) == DIR_SEPARATOR
)
806 ; /* do nothing -- slash already is in place */
808 *t
++ = DIR_SEPARATOR
; /* put in the slash */
809 cutoff
= t
- 1; /* set cutoff */
811 if (access(imagedir
, R_OK
) == 0)
815 s
++; /* advance source pointer */
817 fatal_error(FE_INFND
, 0);
822 /*-------------------------------------------------------------*
823 | At this point the full pathname should exist in imagedir and
824 | cutoff should be set to the final slash. We must now determine
825 | whether the file name is a symbolic link or not and chase it down
826 | if it is. Note that we reuse ebuf for getting the link.
827 *-------------------------------------------------------------*/
830 while ((cc
= readlink(imagedir
, ebuf
, 512)) != -1) {
833 if (*s
== DIR_SEPARATOR
) {
840 if (*s
== DIR_SEPARATOR
)
841 cutoff
= t
; /* mark the last slash seen */
842 if (!(*t
++ = *s
++)) /* copy the character */
847 #endif /* HAVE_SYMLINK */
849 strcpy(imagename
, cutoff
+ 1); /* keep the image name */
850 *(cutoff
+ 1) = 0; /* chop off the filename part */
857 // ----------------------------------------------------------------------------
859 // ----------------------------------------------------------------------------
862 * N.B. these convenience functions must be separate from msgdlgg.cpp, textdlgg.cpp
863 * since otherwise the generic code may be pulled in unnecessarily.
866 int wxMessageBox(const wxString
& message
, const wxString
& caption
, long style
,
867 wxWindow
*parent
, int WXUNUSED(x
), int WXUNUSED(y
) )
869 wxMessageDialog
dialog(parent
, message
, caption
, style
);
871 int ans
= dialog
.ShowModal();
892 wxString
wxGetTextFromUser(const wxString
& message
, const wxString
& caption
,
893 const wxString
& defaultValue
, wxWindow
*parent
,
894 int x
, int y
, bool WXUNUSED(centre
) )
896 wxTextEntryDialog
dialog(parent
, message
, caption
, defaultValue
, wxOK
|wxCANCEL
, wxPoint(x
, y
));
897 if (dialog
.ShowModal() == wxID_OK
)
898 return dialog
.GetValue();
902 #endif // wxUSE_TEXTDLG
905 char *strdup(const char *s
)
907 return strcpy( (char*) malloc( strlen( s
) + 1 ) , s
) ;
912 return ( c
>= 0 && c
< 128 ) ;
916 // ----------------------------------------------------------------------------
918 // ----------------------------------------------------------------------------
920 void wxEnableTopLevelWindows(bool enable
)
922 wxWindowList::Node
*node
;
923 for ( node
= wxTopLevelWindows
.GetFirst(); node
; node
= node
->GetNext() )
924 node
->GetData()->Enable(enable
);
927 // Yield to other apps/messages and disable user input
928 bool wxSafeYield(wxWindow
*win
)
930 wxEnableTopLevelWindows(FALSE
);
931 // always enable ourselves
935 wxEnableTopLevelWindows(TRUE
);
939 // Don't synthesize KeyUp events holding down a key and producing KeyDown
940 // events with autorepeat. On by default and always on in wxMSW. wxGTK version
943 bool wxSetDetectableAutoRepeat( bool WXUNUSED(flag
) )
945 return TRUE
; // detectable auto-repeat is the only mode MSW supports
951 // ----------------------------------------------------------------------------
952 // network and user id functions
953 // ----------------------------------------------------------------------------
955 // Get Full RFC822 style email address
956 bool wxGetEmailAddress(wxChar
*address
, int maxSize
)
958 wxString email
= wxGetEmailAddress();
962 wxStrncpy(address
, email
, maxSize
- 1);
963 address
[maxSize
- 1] = wxT('\0');
968 wxString
wxGetEmailAddress()
972 wxString host
= wxGetHostName();
975 wxString user
= wxGetUserId();
978 wxString
email(user
);
979 email
<< wxT('@') << host
;
986 wxString
wxGetUserId()
988 static const int maxLoginLen
= 256; // FIXME arbitrary number
991 bool ok
= wxGetUserId(buf
.GetWriteBuf(maxLoginLen
), maxLoginLen
);
1000 wxString
wxGetUserName()
1002 static const int maxUserNameLen
= 1024; // FIXME arbitrary number
1005 bool ok
= wxGetUserName(buf
.GetWriteBuf(maxUserNameLen
), maxUserNameLen
);
1006 buf
.UngetWriteBuf();
1014 wxString
wxGetHostName()
1016 static const size_t hostnameSize
= 257;
1019 bool ok
= wxGetHostName(buf
.GetWriteBuf(hostnameSize
), hostnameSize
);
1021 buf
.UngetWriteBuf();
1029 wxString
wxGetFullHostName()
1031 static const size_t hostnameSize
= 257;
1034 bool ok
= wxGetFullHostName(buf
.GetWriteBuf(hostnameSize
), hostnameSize
);
1036 buf
.UngetWriteBuf();