1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     Various utilities 
   4 // Author:      Stefan Csomor 
   8 // Copyright:   (c) Stefan Csomor 
   9 // Licence:       wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  13 // Note: this is done in utilscmn.cpp now. 
  14 // #pragma implementation "utils.h" 
  20 #include "wx/apptrait.h" 
  23     #include "wx/mac/uma.h" 
  34 #  include "MoreFilesX.h" 
  36 #  include "MoreFiles.h" 
  37 #  include "MoreFilesExtras.h" 
  45 #include "ATSUnicode.h" 
  46 #include "TextCommon.h" 
  47 #include "TextEncodingConverter.h" 
  49 #if defined(__WXMAC__) 
  50   #include  "wx/mac/private.h"  // includes mac headers 
  53 #if defined(__MWERKS__) && wxUSE_UNICODE 
  57 // --------------------------------------------------------------------------- 
  58 // code used in both base and GUI compilation 
  59 // --------------------------------------------------------------------------- 
  61 // our OS version is the same in non GUI and GUI cases 
  62 static int DoGetOSVersion(int *majorVsn
, int *minorVsn
) 
  66     // are there x-platform conventions ? 
  68     Gestalt(gestaltSystemVersion
, &theSystem
) ; 
  69     if (minorVsn 
!= NULL
) { 
  70         *minorVsn 
= (theSystem 
& 0xFF ) ; 
  72     if (majorVsn 
!= NULL
) { 
  73         *majorVsn 
= (theSystem 
>> 8 ) ; 
  85 // defined in unix/utilsunx.cpp for Mac OS X 
  87 // get full hostname (with domain name if possible) 
  88 bool wxGetFullHostName(wxChar 
*buf
, int maxSize
) 
  90     return wxGetHostName(buf
, maxSize
); 
  93 // Get hostname only (without domain name) 
  94 bool wxGetHostName(wxChar 
*buf
, int maxSize
) 
  96     // Gets Chooser name of user by examining a System resource. 
  98     const short kComputerNameID 
= -16413; 
 100     short oldResFile 
= CurResFile() ; 
 102     StringHandle chooserName 
= (StringHandle
)::GetString(kComputerNameID
); 
 103     UseResFile(oldResFile
); 
 105     if (chooserName 
&& *chooserName
) 
 107         HLock( (Handle
) chooserName 
) ; 
 108         wxString name 
= wxMacMakeStringFromPascal( *chooserName 
) ; 
 109         HUnlock( (Handle
) chooserName 
) ; 
 110         ReleaseResource( (Handle
) chooserName 
) ; 
 111         wxStrncpy( buf 
, name 
, maxSize 
- 1 ) ; 
 119 // Get user ID e.g. jacs 
 120 bool wxGetUserId(wxChar 
*buf
, int maxSize
) 
 122   return wxGetUserName( buf 
, maxSize 
) ; 
 125 const wxChar
* wxGetHomeDir(wxString 
*pstr
) 
 127     *pstr 
= wxMacFindFolder(  (short) kOnSystemDisk
, kPreferencesFolderType
, kDontCreateFolder 
) ; 
 128     return pstr
->c_str() ; 
 131 // Get user name e.g. Stefan Csomor 
 132 bool wxGetUserName(wxChar 
*buf
, int maxSize
) 
 134     // Gets Chooser name of user by examining a System resource. 
 136     const short kChooserNameID 
= -16096; 
 138     short oldResFile 
= CurResFile() ; 
 140     StringHandle chooserName 
= (StringHandle
)::GetString(kChooserNameID
); 
 141     UseResFile(oldResFile
); 
 143     if (chooserName 
&& *chooserName
) 
 145         HLock( (Handle
) chooserName 
) ; 
 146         wxString name 
= wxMacMakeStringFromPascal( *chooserName 
) ; 
 147         HUnlock( (Handle
) chooserName 
) ; 
 148         ReleaseResource( (Handle
) chooserName 
) ; 
 149         wxStrncpy( buf 
, name 
, maxSize 
- 1 ) ; 
 157 int wxKill(long pid
, wxSignal sig 
, wxKillError 
*rc 
) 
 163 WXDLLEXPORT 
bool wxGetEnv(const wxString
& var
, wxString 
*value
) 
 165     // TODO : under classic there is no environement support, under X yes 
 169 // set the env var name to the given value, return TRUE on success 
 170 WXDLLEXPORT 
bool wxSetEnv(const wxString
& var
, const wxChar 
*value
) 
 172     // TODO : under classic there is no environement support, under X yes 
 177 // Execute a program in an Interactive Shell 
 179 bool wxShell(const wxString
& command
) 
 185 // Shutdown or reboot the PC 
 186 bool wxShutdown(wxShutdownFlags wFlags
) 
 192 // Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX) 
 193 long wxGetFreeMemory() 
 198 void wxUsleep(unsigned long milliseconds
) 
 200     clock_t start 
= clock() ; 
 204     } while( clock() - start 
< milliseconds 
/  1000.0 * CLOCKS_PER_SEC 
) ; 
 207 void wxSleep(int nSecs
) 
 209     wxUsleep(1000*nSecs
); 
 212 // Consume all events until no more left 
 217 #endif // !__DARWIN__ 
 225 wxToolkitInfo
& wxConsoleAppTraits::GetToolkitInfo() 
 227     static wxToolkitInfo info
; 
 228     info
.os 
= DoGetOSVersion(&info
.versionMajor
, &info
.versionMinor
); 
 229     info
.name 
= _T("wxBase"); 
 237 wxToolkitInfo
& wxGUIAppTraits::GetToolkitInfo() 
 239     static wxToolkitInfo info
; 
 240     info
.os 
= DoGetOSVersion(&info
.versionMajor
, &info
.versionMinor
); 
 241     info
.shortName 
= _T("mac"); 
 242     info
.name 
= _T("wxMac"); 
 243 #ifdef __WXUNIVERSAL__ 
 244     info
.shortName 
<< _T("univ"); 
 245     info
.name 
<< _T("/wxUniversal"); 
 250 // Reading and writing resources (eg WIN.INI, .Xdefaults) 
 252 bool wxWriteResource(const wxString
& section
, const wxString
& entry
, const wxString
& value
, const wxString
& file
) 
 258 bool wxWriteResource(const wxString
& section
, const wxString
& entry
, float value
, const wxString
& file
) 
 261     buf
.Printf(wxT("%.4f"), value
); 
 263     return wxWriteResource(section
, entry
, buf
, file
); 
 266 bool wxWriteResource(const wxString
& section
, const wxString
& entry
, long value
, const wxString
& file
) 
 269     buf
.Printf(wxT("%ld"), value
); 
 271     return wxWriteResource(section
, entry
, buf
, file
); 
 274 bool wxWriteResource(const wxString
& section
, const wxString
& entry
, int value
, const wxString
& file
) 
 277     buf
.Printf(wxT("%d"), value
); 
 279     return wxWriteResource(section
, entry
, buf
, file
); 
 282 bool wxGetResource(const wxString
& section
, const wxString
& entry
, char **value
, const wxString
& file
) 
 288 bool wxGetResource(const wxString
& section
, const wxString
& entry
, float *value
, const wxString
& file
) 
 291     bool succ 
= wxGetResource(section
, entry
, (char **)&s
, file
); 
 294         *value 
= (float)strtod(s
, NULL
); 
 301 bool wxGetResource(const wxString
& section
, const wxString
& entry
, long *value
, const wxString
& file
) 
 304     bool succ 
= wxGetResource(section
, entry
, (char **)&s
, file
); 
 307         *value 
= strtol(s
, NULL
, 10); 
 314 bool wxGetResource(const wxString
& section
, const wxString
& entry
, int *value
, const wxString
& file
) 
 317     bool succ 
= wxGetResource(section
, entry
, (char **)&s
, file
); 
 320         *value 
= (int)strtol(s
, NULL
, 10); 
 326 #endif // wxUSE_RESOURCES 
 328 int gs_wxBusyCursorCount 
= 0; 
 329 extern wxCursor    gMacCurrentCursor 
; 
 330 wxCursor        gMacStoredActiveCursor 
; 
 332 // Set the cursor to the busy cursor for all windows 
 333 void wxBeginBusyCursor(wxCursor 
*cursor
) 
 335     if (gs_wxBusyCursorCount
++ == 0) 
 337         gMacStoredActiveCursor 
= gMacCurrentCursor 
; 
 338         cursor
->MacInstall() ; 
 340     //else: nothing to do, already set 
 343 // Restore cursor to normal 
 344 void wxEndBusyCursor() 
 346     wxCHECK_RET( gs_wxBusyCursorCount 
> 0, 
 347         wxT("no matching wxBeginBusyCursor() for wxEndBusyCursor()") ); 
 349     if (--gs_wxBusyCursorCount 
== 0) 
 351         gMacStoredActiveCursor
.MacInstall() ; 
 352         gMacStoredActiveCursor 
= wxNullCursor 
; 
 356 // TRUE if we're between the above two calls 
 359     return (gs_wxBusyCursorCount 
> 0); 
 366 wxString 
wxMacFindFolder( short        vol
, 
 368               Boolean      createFolder
) 
 374     if ( FindFolder( vol
, folderType
, createFolder
, &vRefNum
, &dirID
) == noErr
) 
 377         if ( FSMakeFSSpec( vRefNum 
, dirID 
, "\p" , &file 
) == noErr 
) 
 379             strDir 
= wxMacFSSpec2MacFilename( &file 
) + wxFILE_SEP_PATH 
; 
 389 // Check whether this window wants to process messages, e.g. Stop button 
 390 // in long calculations. 
 391 bool wxCheckForInterrupt(wxWindow 
*wnd
) 
 397 void wxGetMousePosition( int* x
, int* y 
) 
 402     LocalToGlobal( &pt 
) ; 
 407 // Return TRUE if we have a colour display 
 408 bool wxColourDisplay() 
 413 // Returns depth of screen 
 417     SetRect(&globRect
, -32760, -32760, 32760, 32760); 
 418     GDHandle    theMaxDevice
; 
 421     theMaxDevice 
= GetMaxDevice(&globRect
); 
 422     if (theMaxDevice 
!= nil
) 
 423         theDepth 
= (**(**theMaxDevice
).gdPMap
).pixelSize
; 
 428 // Get size of display 
 429 void wxDisplaySize(int *width
, int *height
) 
 432     GetQDGlobalsScreenBits( &screenBits 
); 
 435         *width 
= screenBits
.bounds
.right 
- screenBits
.bounds
.left  
; 
 437     if (height 
!= NULL
) { 
 438         *height 
= screenBits
.bounds
.bottom 
- screenBits
.bounds
.top 
; 
 442 void wxDisplaySizeMM(int *width
, int *height
) 
 444     wxDisplaySize(width
, height
); 
 445     // on mac 72 is fixed (at least now ;-) 
 446     float cvPt2Mm 
= 25.4 / 72; 
 449         *width 
= int( *width 
* cvPt2Mm 
); 
 451     if (height 
!= NULL
) { 
 452         *height 
= int( *height 
* cvPt2Mm 
); 
 456 void wxClientDisplayRect(int *x
, int *y
, int *width
, int *height
) 
 459     GetQDGlobalsScreenBits( &screenBits 
); 
 465         *width 
= screenBits
.bounds
.right 
- screenBits
.bounds
.left  
; 
 467     if (height 
!= NULL
) { 
 468         *height 
= screenBits
.bounds
.bottom 
- screenBits
.bounds
.top 
; 
 473     GetThemeMenuBarHeight( &mheight 
) ; 
 475     mheight 
= LMGetMBarHeight() ; 
 477     if (height 
!= NULL
) { 
 484 wxWindow
* wxFindWindowAtPoint(const wxPoint
& pt
) 
 486     return wxGenericFindWindowAtPoint(pt
); 
 493 wxString 
wxGetOsDescription() 
 495 #ifdef WXWIN_OS_DESCRIPTION 
 496     // use configure generated description if available 
 497     return wxString(wxT("MacOS (")) + wxT(WXWIN_OS_DESCRIPTION
) + wxString(wxT(")")); 
 499     return wxT("MacOS") ; //TODO:define further 
 504 wxChar 
*wxGetUserHome (const wxString
& user
) 
 510 bool wxGetDiskSpace(const wxString
& path
, wxLongLong 
*pTotal
, wxLongLong 
*pFree
) 
 520     int pos 
= p
.Find(':') ; 
 521     if ( pos 
!= wxNOT_FOUND 
) { 
 530     wxMacStringToPascal( p  
, volumeName 
) ; 
 531     OSErr err 
= XGetVolumeInfoNoName( volumeName 
, 0 , &pb 
) ; 
 532     if ( err 
== noErr 
) { 
 534         (*pTotal
) = wxLongLong( pb
.ioVTotalBytes 
) ; 
 537         (*pFree
) = wxLongLong( pb
.ioVFreeBytes 
) ; 
 541     return err 
== noErr 
; 
 543 #endif // !__DARWIN__ 
 545 //--------------------------------------------------------------------------- 
 546 // wxMac Specific utility functions 
 547 //--------------------------------------------------------------------------- 
 551 char StringMac
[] =  "\x0d\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" 
 552                     "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" 
 553                     "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xae\xaf" 
 554                     "\xb1\xb4\xb5\xb6\xbb\xbc\xbe\xbf" 
 555                     "\xc0\xc1\xc2\xc4\xc7\xc8\xc9\xcb\xcc\xcd\xce\xcf" 
 556                     "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd8\xca\xdb" ; 
 558 char StringANSI
[] = "\x0a\xC4\xC5\xC7\xC9\xD1\xD6\xDC\xE1\xE0\xE2\xE4\xE3\xE5\xE7\xE9\xE8" 
 559                     "\xEA\xEB\xED\xEC\xEE\xEF\xF1\xF3\xF2\xF4\xF6\xF5\xFA\xF9\xFB\xFC" 
 560                     "\x86\xBA\xA2\xA3\xA7\x95\xB6\xDF\xAE\xA9\x99\xB4\xA8\xC6\xD8" 
 561                     "\xB1\xA5\xB5\xF0\xAA\xBA\xE6\xF8" 
 562                     "\xBF\xA1\xAC\x83\xAB\xBB\x85\xC0\xC3\xD5\x8C\x9C" 
 563                     "\x96\x97\x93\x94\x91\x92\xF7\xFF\xA0\x80" ; 
 565 void wxMacConvertFromPC( const char *from 
, char *to 
, int len 
) 
 570         for( int i 
= 0 ; i 
< len 
; ++ i 
) 
 572             c 
= strchr( StringANSI 
, *from 
) ; 
 575                 *to 
= StringMac
[ c 
- StringANSI
] ; 
 583         for( int i 
= 0 ; i 
< len 
; ++ i 
) 
 585             c 
= strchr( StringANSI 
, *from 
) ; 
 588                 *to 
= StringMac
[ c 
- StringANSI
] ; 
 600 void wxMacConvertToPC( const char *from 
, char *to 
, int len 
) 
 605         for( int i 
= 0 ; i 
< len 
; ++ i 
) 
 607             c 
= strchr( StringMac 
, *from 
) ; 
 610                 *to 
= StringANSI
[ c 
- StringMac
] ; 
 618         for( int i 
= 0 ; i 
< len 
; ++ i 
) 
 620             c 
= strchr( StringMac 
, *from 
) ; 
 623                 *to 
= StringANSI
[ c 
- StringMac
] ; 
 635 TECObjectRef s_TECNativeCToUnicode 
= NULL 
; 
 636 TECObjectRef s_TECUnicodeToNativeC 
= NULL 
; 
 638 void wxMacSetupConverters() 
 640     // if we assume errors are happening here we need low level debugging 
 641     // since the high level assert will use the encoders that are not yet 
 644     const TextEncodingBase kEncoding 
= CFStringGetSystemEncoding(); 
 646     const TextEncodingBase kEncoding 
= kTextEncodingMacRoman
; 
 648     OSStatus status 
= noErr 
; 
 649     status 
= TECCreateConverter(&s_TECNativeCToUnicode
, 
 651                                 kTextEncodingUnicodeDefault
); 
 654     status 
= TECCreateConverter(&s_TECUnicodeToNativeC
, 
 655                                 kTextEncodingUnicodeDefault
, 
 659 void wxMacCleanupConverters() 
 661     OSStatus status 
= noErr 
; 
 662     status 
= TECDisposeConverter(s_TECNativeCToUnicode
); 
 664     status 
= TECDisposeConverter(s_TECUnicodeToNativeC
); 
 667 wxWCharBuffer 
wxMacStringToWString( const wxString 
&from 
) 
 670     wxWCharBuffer 
result( from
.wc_str() ) ; 
 672     OSStatus status 
= noErr 
; 
 673     ByteCount byteOutLen 
; 
 674     ByteCount byteInLen 
= from
.Length() ; 
 675     ByteCount byteBufferLen 
= byteInLen 
*2 ; 
 676     wxWCharBuffer 
result( from
.Length() ) ; 
 677     status 
= TECConvertText(s_TECNativeCToUnicode
, (ConstTextPtr
)from
.c_str() , byteInLen
, &byteInLen
, 
 678         (TextPtr
)result
.data(), byteBufferLen
, &byteOutLen
); 
 679     result
.data()[byteOutLen
/2] = 0 ; 
 685 wxString 
wxMacMakeStringFromCString( const char * from 
, int len 
) 
 687     OSStatus status 
= noErr 
; 
 689     wxChar
* buf 
= result
.GetWriteBuf( len 
) ; 
 691     ByteCount byteOutLen 
; 
 692     ByteCount byteInLen 
= len 
; 
 693     ByteCount byteBufferLen 
= len 
*2 ; 
 695     status 
= TECConvertText(s_TECNativeCToUnicode
, (ConstTextPtr
)from 
, byteInLen
, &byteInLen
, 
 696         (TextPtr
)buf
, byteBufferLen
, &byteOutLen
); 
 698     memcpy( buf 
, from 
, len 
) ; 
 701     result
.UngetWriteBuf() ; 
 705 wxString 
wxMacMakeStringFromCString( const char * from 
) 
 707     return wxMacMakeStringFromCString( from 
, strlen(from
) ) ; 
 710 wxCharBuffer 
wxMacStringToCString( const wxString 
&from 
) 
 713     OSStatus status 
= noErr 
; 
 714     ByteCount byteOutLen 
; 
 715     ByteCount byteInLen 
= from
.Length() * 2 ; 
 716     ByteCount byteBufferLen 
= from
.Length() ; 
 717     wxCharBuffer 
result( from
.Length() ) ; 
 718     status 
= TECConvertText(s_TECUnicodeToNativeC 
, (ConstTextPtr
)from
.wc_str() , byteInLen
, &byteInLen
, 
 719         (TextPtr
)result
.data(), byteBufferLen
, &byteOutLen
); 
 722     return wxCharBuffer( from
.c_str() ) ; 
 727 void wxMacStringToPascal( const wxString
&from 
, StringPtr to 
) 
 729     wxCharBuffer buf 
= from
.mb_str( wxConvLocal 
) ; 
 730     int len 
= strlen(buf
) ; 
 735     memcpy( (char*) &to
[1] , buf 
, len 
) ; 
 738 wxString 
wxMacMakeStringFromPascal( ConstStringPtr from 
) 
 740     return wxString( (char*) &from
[1] , wxConvLocal 
, from
[0] ) ; 
 749 // CFStringRefs (Carbon only) 
 753 // converts this string into a carbon foundation string with optional pc 2 mac encoding 
 754 void wxMacCFStringHolder::Assign( const wxString 
&str 
) 
 757         m_cfs 
= CFStringCreateWithCharacters( kCFAllocatorDefault
, 
 758                 (const unsigned short*)str
.wc_str(), str
.Len() ); 
 760     m_cfs 
= CFStringCreateWithCString( kCFAllocatorSystemDefault 
, str
.c_str() , 
 761         CFStringGetSystemEncoding() ) ; 
 766 wxString 
wxMacCFStringHolder::AsString() 
 769     Size len 
= CFStringGetLength( m_cfs 
)  ; 
 770     wxChar
* buf 
= result
.GetWriteBuf( len 
) ; 
 772     CFStringGetCharacters( m_cfs 
, CFRangeMake( 0 , len 
) , (UniChar
*) buf 
) ; 
 774     CFStringGetCString( m_cfs 
, buf 
, len
+1 , CFStringGetSystemEncoding() ) ; 
 777     result
.UngetWriteBuf() ; 
 781 #endif //TARGET_CARBON 
 783 // ---------------------------------------------------------------------------- 
 785 // ---------------------------------------------------------------------------- 
 787 #if defined(__WXMAC__) && !defined(__DARWIN__) && defined(__MWERKS__) && (__MWERKS__ >= 0x2400) 
 789 // MetroNub stuff doesn't seem to work in CodeWarrior 5.3 Carbon builds... 
 791 #ifndef __MetroNubUtils__ 
 792 #include "MetroNubUtils.h" 
 799 #if TARGET_API_MAC_CARBON 
 801     #include <CodeFragments.h> 
 803     extern "C" long CallUniversalProc(UniversalProcPtr theProcPtr
, ProcInfoType procInfo
, ...); 
 805     ProcPtr gCallUniversalProc_Proc 
= NULL
; 
 809 static MetroNubUserEntryBlock
*    gMetroNubEntry 
= NULL
; 
 811 static long fRunOnce 
= false; 
 813 /* --------------------------------------------------------------------------- 
 815    --------------------------------------------------------------------------- */ 
 817 Boolean 
IsMetroNubInstalled() 
 824         gMetroNubEntry 
= NULL
; 
 826         if (Gestalt(gestaltSystemVersion
, &value
) == noErr 
&& value 
< 0x1000) 
 828             /* look for MetroNub's Gestalt selector */ 
 829             if (Gestalt(kMetroNubUserSignature
, &result
) == noErr
) 
 832             #if TARGET_API_MAC_CARBON 
 833                 if (gCallUniversalProc_Proc 
== NULL
) 
 835                     CFragConnectionID   connectionID
; 
 838                     ProcPtr             symbolAddress
; 
 840                     CFragSymbolClass    symbolClass
; 
 842                     symbolAddress 
= NULL
; 
 843                     err 
= GetSharedLibrary("\pInterfaceLib", kPowerPCCFragArch
, kFindCFrag
, 
 844                                            &connectionID
, &mainAddress
, errorString
); 
 848                         gCallUniversalProc_Proc 
= NULL
; 
 852                     err 
= FindSymbol(connectionID
, "\pCallUniversalProc", 
 853                                     (Ptr 
*) &gCallUniversalProc_Proc
, &symbolClass
); 
 857                         gCallUniversalProc_Proc 
= NULL
; 
 864                     MetroNubUserEntryBlock
* block 
= (MetroNubUserEntryBlock 
*)result
; 
 866                     /* make sure the version of the API is compatible */ 
 867                     if (block
->apiLowVersion 
<= kMetroNubUserAPIVersion 
&& 
 868                         kMetroNubUserAPIVersion 
<= block
->apiHiVersion
) 
 869                         gMetroNubEntry 
= block
;        /* success! */ 
 878 #if TARGET_API_MAC_CARBON 
 879     return (gMetroNubEntry 
!= NULL 
&& gCallUniversalProc_Proc 
!= NULL
); 
 881     return (gMetroNubEntry 
!= NULL
); 
 885 /* --------------------------------------------------------------------------- 
 886         IsMWDebuggerRunning                                            [v1 API] 
 887    --------------------------------------------------------------------------- */ 
 889 Boolean 
IsMWDebuggerRunning() 
 891     if (IsMetroNubInstalled()) 
 892         return CallIsDebuggerRunningProc(gMetroNubEntry
->isDebuggerRunning
); 
 897 /* --------------------------------------------------------------------------- 
 898         AmIBeingMWDebugged                                            [v1 API] 
 899    --------------------------------------------------------------------------- */ 
 901 Boolean 
AmIBeingMWDebugged() 
 903     if (IsMetroNubInstalled()) 
 904         return CallAmIBeingDebuggedProc(gMetroNubEntry
->amIBeingDebugged
); 
 909 extern bool WXDLLEXPORT 
wxIsDebuggerRunning() 
 911     return IsMWDebuggerRunning() && AmIBeingMWDebugged(); 
 916 extern bool WXDLLEXPORT 
wxIsDebuggerRunning() 
 921 #endif // defined(__WXMAC__) && !defined(__DARWIN__) && (__MWERKS__ >= 0x2400)