1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxCursor class 
   4 // Author:      Stefan Csomor 
   8 // Copyright:   (c) Stefan Csomor 
   9 // Licence:       wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  13 #pragma implementation "cursor.h" 
  19 #include "wx/cursor.h" 
  22 #include "wx/xpmdecod.h" 
  24 #include "wx/mac/private.h" 
  26 #if !USE_SHARED_LIBRARIES 
  27 IMPLEMENT_DYNAMIC_CLASS(wxCursor
, wxBitmap
) 
  30 const short kwxCursorBullseye 
= 10 ; 
  31 const short kwxCursorBlank 
= 11 ; 
  32 const short kwxCursorPencil 
= 12 ; 
  33 const short kwxCursorMagnifier 
= 13 ; 
  34 const short kwxCursorNoEntry 
= 14 ; 
  35 const short kwxCursorPaintBrush 
= 15 ; 
  36 const short kwxCursorPointRight 
= 16 ; 
  37 const short kwxCursorPointLeft 
= 17 ; 
  38 const short kwxCursorQuestionArrow 
= 18 ; 
  39 const short kwxCursorRightArrow 
= 19 ; 
  40 const short kwxCursorSizeNS 
= 20 ; 
  41 const short kwxCursorSize 
= 21 ; 
  42 const short kwxCursorSizeNESW 
= 22 ; 
  43 const short kwxCursorSizeNWSE 
= 23 ; 
  44 const short kwxCursorRoller 
= 24 ; 
  46 wxCursor    gMacCurrentCursor 
; 
  48 wxCursorRefData::wxCursorRefData() 
  53     m_disposeHandle 
= false ; 
  54     m_releaseHandle 
= false ; 
  55     m_isColorCursor 
= false ; 
  59 wxCursorRefData::~wxCursorRefData() 
  61     if ( m_isColorCursor 
) 
  63         ::DisposeCCursor( (CCrsrHandle
) m_hCursor 
) ; 
  65     else if ( m_disposeHandle 
) 
  67         ::DisposeHandle( (Handle 
) m_hCursor 
) ; 
  69     else if ( m_releaseHandle 
) 
  71         // we don't release the resource since it may already 
  81 wxCursor::wxCursor(const char WXUNUSED(bits
)[], int WXUNUSED(width
), int WXUNUSED(height
), 
  82     int WXUNUSED(hotSpotX
), int WXUNUSED(hotSpotY
), const char WXUNUSED(maskBits
)[]) 
  86 wxCursor::wxCursor( const wxImage 
&image 
) 
  88     CreateFromImage( image 
) ; 
  91 wxCursor::wxCursor(const char **bits
)  
  93     (void) CreateFromXpm(bits
); 
  96 wxCursor::wxCursor(char **bits
)  
  98     (void) CreateFromXpm((const char **)bits
); 
 101 bool wxCursor::CreateFromXpm(const char **bits
) 
 103     wxCHECK_MSG( bits 
!= NULL
, FALSE
, wxT("invalid cursor data") ) 
 104     wxXPMDecoder decoder
; 
 105     wxImage img 
= decoder
.ReadData(bits
); 
 106     wxCHECK_MSG( img
.Ok(), FALSE
, wxT("invalid cursor data") )     
 107         CreateFromImage( img 
) ; 
 111 short GetCTabIndex( CTabHandle colors 
, RGBColor 
*col 
) 
 114     unsigned long bestdiff 
= 0xFFFF ; 
 115     for ( int i 
= 0 ; i 
< (**colors
).ctSize 
; ++i 
) 
 117         unsigned long diff 
= abs(col
->red 
-  (**colors
).ctTable
[i
].rgb
.red 
) + 
 118             abs(col
->green 
-  (**colors
).ctTable
[i
].rgb
.green 
) + 
 119             abs(col
->blue 
-  (**colors
).ctTable
[i
].rgb
.blue 
) ; 
 120         if ( diff 
< bestdiff 
) 
 123             retval 
= (**colors
).ctTable
[i
].value 
; 
 129 void wxCursor::CreateFromImage(const wxImage 
& image
)  
 131     m_refData 
= new wxCursorRefData
; 
 133     wxImage image16 
= image
.Scale(16,16) ; 
 134        unsigned char * rgbBits 
= image16
.GetData(); 
 137     int w 
= image16
.GetWidth()  ; 
 138     int h 
= image16
.GetHeight() ; 
 139     bool bHasMask 
= image16
.HasMask() ; 
 141        int hotSpotX 
= image16
.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_X
); 
 142     int hotSpotY 
= image16
.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_Y
); 
 143     if (hotSpotX 
< 0 || hotSpotX 
>= w
) 
 145     if (hotSpotY 
< 0 || hotSpotY 
>= h
) 
 149     // monochrome implementation 
 150     M_CURSORDATA
->m_hCursor 
= NewHandle( sizeof( Cursor 
) ) ; 
 151     M_CURSORDATA
->m_disposeHandle 
= true ; 
 152     HLock( (Handle
) M_CURSORDATA
->m_hCursor 
) ; 
 153     CursPtr cp 
= *(CursHandle
)M_CURSORDATA
->m_hCursor 
; 
 154     memset( cp
->data 
, 0 , sizeof( Bits16 
) ) ; 
 155     memset( cp
->mask 
, 0 , sizeof( Bits16 
) ) ; 
 157     unsigned char mr 
= image16
.GetMaskRed() ; 
 158     unsigned char mg 
= image16
.GetMaskGreen() ; 
 159     unsigned char mb 
= image16
.GetMaskBlue() ; 
 160     for ( int y 
= 0 ; y 
< h 
; ++y 
) 
 165         for ( int x 
= 0 ; x 
< w 
; ++x 
) 
 167             long pos 
= (y 
* w 
+ x
) * 3; 
 169             unsigned char r 
= rgbBits
[pos
] ; 
 170             unsigned char g 
= rgbBits
[pos
+1] ; 
 171             unsigned char b 
= rgbBits
[pos
+2] ; 
 172             if ( bHasMask 
&& r
==mr 
&& g
==mg 
&& b
==mb 
) 
 174                 // masked area, does not appear anywhere 
 178                 if ( (int)r 
+ (int)g 
+ (int)b 
< 0x0200 ) 
 180                     rowbits 
|= ( 1 << (15-x
) ) ; 
 182                 maskbits 
|= ( 1 << (15-x
) ) ; 
 185         cp
->data
[y
] = rowbits 
; 
 186         cp
->mask
[y
] = maskbits 
; 
 190         memcpy( cp
->mask 
, cp
->data 
, sizeof( Bits16
) ) ; 
 192     cp
->hotSpot
.h 
= hotSpotX 
; 
 193     cp
->hotSpot
.v 
= hotSpotY 
; 
 194     HUnlock( (Handle
) M_CURSORDATA
->m_hCursor 
) ; 
 196     PixMapHandle pm 
= (PixMapHandle
) NewHandleClear( sizeof (PixMap
))  ; 
 198     short bytesPerPixel 
= 1 ; 
 200     Rect bounds 
= { 0 , 0 , extent 
, extent 
} ; 
 201     CCrsrHandle ch 
= (CCrsrHandle
) NewHandleClear ( sizeof( CCrsr 
) ) ; 
 202     CTabHandle newColors 
= GetCTable( 8 ) ; 
 203     HandToHand((Handle 
*) &newColors
); 
 204     // set the values to the indices 
 205     for ( int i 
= 0 ; i 
< (**newColors
).ctSize 
; ++i 
) 
 207         (**newColors
).ctTable
[i
].value 
= i 
; 
 209     HLock( (Handle
) ch
) ; 
 210     (**ch
).crsrType 
= 0x8001 ; // color cursors 
 211     (**ch
).crsrMap 
= pm 
;  
 212     short bytesPerRow 
= bytesPerPixel 
* extent 
; 
 215     (**pm
).rowBytes 
= bytesPerRow 
| 0x8000; 
 216     (**pm
).bounds 
= bounds
;         
 217     (**pm
).pmVersion 
= 0;            
 220     (**pm
).hRes 
= 0x00480000; /* 72 DPI default res */ 
 221     (**pm
).vRes 
= 0x00480000; /* 72 DPI default res */ 
 222     (**pm
).pixelSize 
= depth
; 
 223     (**pm
).pixelType 
= 0; 
 225     (**pm
).cmpSize 
= depth
; 
 226     (**pm
).pmTable 
= newColors
; 
 228     (**ch
).crsrData 
= NewHandleClear( extent 
* bytesPerRow 
) ;   
 229     (**ch
).crsrXData 
= NULL 
; 
 230     (**ch
).crsrXValid 
= 0; 
 231     (**ch
).crsrXHandle 
= NULL
; 
 233     (**ch
).crsrHotSpot
.h 
= hotSpotX 
; 
 234     (**ch
).crsrHotSpot
.v 
= hotSpotY 
; 
 235     (**ch
).crsrXTable 
= NULL 
;  
 236     (**ch
).crsrID 
= GetCTSeed() ; 
 238     memset( (**ch
).crsr1Data  
, 0 , sizeof( Bits16 
) ) ; 
 239     memset( (**ch
).crsrMask 
, 0 , sizeof( Bits16 
) ) ; 
 241     unsigned char mr 
= image16
.GetMaskRed() ; 
 242     unsigned char mg 
= image16
.GetMaskGreen() ; 
 243     unsigned char mb 
= image16
.GetMaskBlue() ; 
 244     for ( int y 
= 0 ; y 
< h 
; ++y 
) 
 249         for ( int x 
= 0 ; x 
< w 
; ++x 
) 
 251             long pos 
= (y 
* w 
+ x
) * 3; 
 253             unsigned char r 
= rgbBits
[pos
] ; 
 254             unsigned char g 
= rgbBits
[pos
+1] ; 
 255             unsigned char b 
= rgbBits
[pos
+2] ; 
 256             RGBColor col 
= { 0xFFFF ,0xFFFF, 0xFFFF } ; 
 258             if ( bHasMask 
&& r
==mr 
&& g
==mg 
&& b
==mb 
) 
 260                 // masked area, does not appear anywhere 
 264                 if ( (int)r 
+ (int)g 
+ (int)b 
< 0x0200 ) 
 266                     rowbits 
|= ( 1 << (15-x
) ) ; 
 268                 maskbits 
|= ( 1 << (15-x
) ) ; 
 270                 col 
= *((RGBColor
*) wxColor( r 
, g 
, b 
).GetPixel()) ; 
 272             *((*(**ch
).crsrData
) + y 
* bytesPerRow 
+ x
) =  
 273                 GetCTabIndex( newColors 
, &col
) ; 
 275         (**ch
).crsr1Data
[y
] = rowbits 
; 
 276         (**ch
).crsrMask
[y
] = maskbits 
; 
 280         memcpy( (**ch
).crsrMask 
, (**ch
).crsr1Data 
, sizeof( Bits16
) ) ; 
 283     HUnlock((Handle
) ch
) ; 
 284     M_CURSORDATA
->m_hCursor 
= ch 
; 
 285     M_CURSORDATA
->m_isColorCursor 
= true ; 
 289 wxCursor::wxCursor(const wxString
& cursor_file
, long flags
, int hotSpotX
, int hotSpotY
) 
 291     m_refData 
= new wxCursorRefData
; 
 292     if ( flags 
== wxBITMAP_TYPE_MACCURSOR_RESOURCE 
) 
 295                 wxMacStringToPascal( cursor_file 
, theName 
) ; 
 297         wxStAppResource resload 
; 
 298         Handle resHandle 
= ::GetNamedResource( 'crsr' , theName 
) ; 
 303             GetResInfo( resHandle 
, &theId 
, &theType 
, theName 
) ; 
 304             ReleaseResource( resHandle 
) ; 
 305             M_CURSORDATA
->m_hCursor 
= GetCCursor( theId 
) ; 
 306             if ( M_CURSORDATA
->m_hCursor 
) 
 307                 M_CURSORDATA
->m_isColorCursor 
= true ; 
 311             Handle resHandle 
= ::GetNamedResource( 'CURS' , theName 
) ; 
 316                 GetResInfo( resHandle 
, &theId 
, &theType 
, theName 
) ; 
 317                 ReleaseResource( resHandle 
) ; 
 318                  M_CURSORDATA
->m_hCursor 
= GetCursor( theId 
) ; 
 319                 if ( M_CURSORDATA
->m_hCursor 
) 
 320                     M_CURSORDATA
->m_releaseHandle 
= true ; 
 327         image
.LoadFile( cursor_file 
, flags 
) ; 
 330             image
.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_X
,hotSpotX 
) ; 
 331             image
.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y
,hotSpotY 
) ; 
 333             CreateFromImage(image
) ; 
 338 // Cursors by stock number 
 339 wxCursor::wxCursor(int cursor_type
) 
 341     m_refData 
= new wxCursorRefData
; 
 345     case wxCURSOR_COPY_ARROW
: 
 346         M_CURSORDATA
->m_themeCursor 
= kThemeCopyArrowCursor 
; 
 349         M_CURSORDATA
->m_themeCursor 
= kThemeWatchCursor 
; 
 352         M_CURSORDATA
->m_themeCursor 
= kThemeIBeamCursor 
; 
 355         M_CURSORDATA
->m_themeCursor 
= kThemeCrossCursor
; 
 357     case wxCURSOR_SIZENWSE
: 
 359             wxStAppResource resload 
; 
 360             M_CURSORDATA
->m_hCursor 
= ::GetCursor(kwxCursorSizeNWSE
); 
 363     case wxCURSOR_SIZENESW
: 
 365             wxStAppResource resload 
; 
 366             M_CURSORDATA
->m_hCursor 
= ::GetCursor(kwxCursorSizeNESW
); 
 369     case wxCURSOR_SIZEWE
: 
 371             M_CURSORDATA
->m_themeCursor 
= kThemeResizeLeftRightCursor
; 
 374     case wxCURSOR_SIZENS
: 
 376             wxStAppResource resload 
; 
 377             M_CURSORDATA
->m_hCursor 
= ::GetCursor(kwxCursorSizeNS
); 
 380     case wxCURSOR_SIZING
: 
 382             wxStAppResource resload 
; 
 383             M_CURSORDATA
->m_hCursor 
= ::GetCursor(kwxCursorSize
); 
 388             M_CURSORDATA
->m_themeCursor 
= kThemePointingHandCursor
; 
 391     case wxCURSOR_BULLSEYE
: 
 393             wxStAppResource resload 
; 
 394             M_CURSORDATA
->m_hCursor 
= ::GetCursor(kwxCursorBullseye
); 
 397     case wxCURSOR_PENCIL
: 
 399             wxStAppResource resload 
; 
 400             M_CURSORDATA
->m_hCursor 
= ::GetCursor(kwxCursorPencil
); 
 403     case wxCURSOR_MAGNIFIER
: 
 405             wxStAppResource resload 
; 
 406             M_CURSORDATA
->m_hCursor 
= ::GetCursor(kwxCursorMagnifier
); 
 409     case wxCURSOR_NO_ENTRY
: 
 411             wxStAppResource resload 
; 
 412             M_CURSORDATA
->m_hCursor 
= ::GetCursor(kwxCursorNoEntry
); 
 417             M_CURSORDATA
->m_themeCursor 
= kThemeWatchCursor
; 
 420     case wxCURSOR_PAINT_BRUSH
: 
 422             wxStAppResource resload 
; 
 423             M_CURSORDATA
->m_hCursor 
= ::GetCursor(kwxCursorPaintBrush
); 
 426     case wxCURSOR_POINT_LEFT
: 
 428             wxStAppResource resload 
; 
 429             M_CURSORDATA
->m_hCursor 
= ::GetCursor(kwxCursorPointLeft
); 
 432     case wxCURSOR_POINT_RIGHT
: 
 434             wxStAppResource resload 
; 
 435             M_CURSORDATA
->m_hCursor 
= ::GetCursor(kwxCursorPointRight
); 
 438     case wxCURSOR_QUESTION_ARROW
: 
 440             wxStAppResource resload 
; 
 441             M_CURSORDATA
->m_hCursor 
= ::GetCursor(kwxCursorQuestionArrow
); 
 446             wxStAppResource resload 
; 
 447             M_CURSORDATA
->m_hCursor 
= ::GetCursor(kwxCursorBlank
); 
 450     case wxCURSOR_RIGHT_ARROW
: 
 452             wxStAppResource resload 
; 
 453             M_CURSORDATA
->m_hCursor 
= ::GetCursor(kwxCursorRightArrow
); 
 456     case wxCURSOR_SPRAYCAN
: 
 458             wxStAppResource resload 
; 
 459             M_CURSORDATA
->m_hCursor 
= ::GetCursor(kwxCursorRoller
); 
 464     case wxCURSOR_LEFT_BUTTON
: 
 465     case wxCURSOR_RIGHT_BUTTON
: 
 466     case wxCURSOR_MIDDLE_BUTTON
: 
 468         M_CURSORDATA
->m_themeCursor 
= kThemeArrowCursor 
; 
 471     if ( M_CURSORDATA
->m_themeCursor 
== -1 ) 
 472         M_CURSORDATA
->m_releaseHandle 
= true ; 
 475 void wxCursor::MacInstall() const  
 477     gMacCurrentCursor 
= *this ; 
 478     if ( m_refData 
&& M_CURSORDATA
->m_themeCursor 
!= -1 ) 
 480         SetThemeCursor( M_CURSORDATA
->m_themeCursor 
) ; 
 482     else if ( m_refData 
&& M_CURSORDATA
->m_hCursor 
) 
 484         if ( M_CURSORDATA
->m_isColorCursor 
) 
 485             ::SetCCursor( (CCrsrHandle
) M_CURSORDATA
->m_hCursor 
) ; 
 487             ::SetCursor( * (CursHandle
) M_CURSORDATA
->m_hCursor 
) ; 
 491         SetThemeCursor( kThemeArrowCursor 
) ; 
 495 wxCursor::~wxCursor() 
 499 // Global cursor setting 
 500 void wxSetCursor(const wxCursor
& cursor
) 
 502     cursor
.MacInstall() ;