]>
git.saurik.com Git - wxWidgets.git/blob - src/common/utilscmn.cpp
5aef920b31ecbb171be4820cba97a0828ca5e2a0
   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 
= wxStrcmp(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
); 
 528     return (wxAcceleratorEntry 
*)NULL
; 
 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();