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 
= 0 ; 
  31 const short kwxCursorBlank 
= 1 ; 
  32 const short kwxCursorPencil 
= 2 ; 
  33 const short kwxCursorMagnifier 
= 3 ; 
  34 const short kwxCursorNoEntry 
= 4 ; 
  35 const short kwxCursorPaintBrush 
= 5 ; 
  36 const short kwxCursorPointRight 
= 6 ; 
  37 const short kwxCursorPointLeft 
= 7 ; 
  38 const short kwxCursorQuestionArrow 
= 8 ; 
  39 const short kwxCursorRightArrow 
= 9 ; 
  40 const short kwxCursorSizeNS 
= 10 ; 
  41 const short kwxCursorSize 
= 11 ; 
  42 const short kwxCursorSizeNESW 
= 12 ; 
  43 const short kwxCursorSizeNWSE 
= 13 ; 
  44 const short kwxCursorRoller 
= 14 ; 
  45 const short kwxCursorLast 
= kwxCursorRoller 
; 
  47 Cursor gMacCursors
[kwxCursorLast
+1] = 
  50 0x0000, 0x03E0, 0x0630, 0x0808, 0x1004, 0x31C6, 0x2362, 0x2222, 
  51 0x2362, 0x31C6, 0x1004, 0x0808, 0x0630, 0x03E0, 0x0000, 0x0000, 
  52 0x0000, 0x03E0, 0x07F0, 0x0FF8, 0x1FFC, 0x3FFE, 0x3FFE, 0x3FFE, 
  53 0x3FFE, 0x3FFE, 0x1FFC, 0x0FF8, 0x07F0, 0x03E0, 0x0000, 0x0000, 
  58 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
  59 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
  60 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
  61 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
  66 0x00F0, 0x0088, 0x0108, 0x0190, 0x0270, 0x0220, 0x0440, 0x0440, 
  67 0x0880, 0x0880, 0x1100, 0x1E00, 0x1C00, 0x1800, 0x1000, 0x0000, 
  68 0x00F0, 0x00F8, 0x01F8, 0x01F0, 0x03F0, 0x03E0, 0x07C0, 0x07C0, 
  69 0x0F80, 0x0F80, 0x1F00, 0x1E00, 0x1C00, 0x1800, 0x1000, 0x0000, 
  74 0x0000, 0x1E00, 0x2100, 0x4080, 0x4080, 0x4080, 0x4080, 0x2180, 
  75 0x1FC0, 0x00E0, 0x0070, 0x0038, 0x001C, 0x000E, 0x0006, 0x0000, 
  76 0x3F00, 0x7F80, 0xFFC0, 0xFFC0, 0xFFC0, 0xFFC0, 0xFFC0, 0x7FC0, 
  77 0x3FE0, 0x1FF0, 0x00F8, 0x007C, 0x003E, 0x001F, 0x000F, 0x0007, 
  82 0x0000, 0x07E0, 0x1FF0, 0x3838, 0x3C0C, 0x6E0E, 0x6706, 0x6386, 
  83 0x61C6, 0x60E6, 0x7076, 0x303C, 0x1C1C, 0x0FF8, 0x07E0, 0x0000, 
  84 0x0540, 0x0FF0, 0x3FF8, 0x3C3C, 0x7E0E, 0xFF0F, 0x6F86, 0xE7C7, 
  85 0x63E6, 0xE1F7, 0x70FE, 0x707E, 0x3C3C, 0x1FFC, 0x0FF0, 0x0540, 
  90 0x0000, 0x0380, 0x0380, 0x0380, 0x0380, 0x0380, 0x0380, 0x0FE0, 
  91 0x1FF0, 0x1FF0, 0x0000, 0x1FF0, 0x1FF0, 0x1550, 0x1550, 0x1550, 
  92 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x0FE0, 0x1FF0, 
  93 0x3FF8, 0x3FF8, 0x3FF8, 0x3FF8, 0x3FF8, 0x3FF8, 0x3FF8, 0x3FF8, 
  98 0x00C0, 0x0140, 0x0640, 0x08C0, 0x3180, 0x47FE, 0x8001, 0x8001, 
  99 0x81FE, 0x8040, 0x01C0, 0x0040, 0x03C0, 0xC080, 0x3F80, 0x0000, 
 100 0x00C0, 0x01C0, 0x07C0, 0x0FC0, 0x3F80, 0x7FFE, 0xFFFF, 0xFFFF, 
 101 0xFFFE, 0xFFC0, 0xFFC0, 0xFFC0, 0xFFC0, 0xFF80, 0x3F80, 0x0000, 
 106 0x0100, 0x0280, 0x0260, 0x0310, 0x018C, 0x7FE3, 0x8000, 0x8000, 
 107 0x7F80, 0x0200, 0x0380, 0x0200, 0x03C0, 0x0107, 0x01F8, 0x0000, 
 108 0x0100, 0x0380, 0x03E0, 0x03F0, 0x01FC, 0x7FFF, 0xFFFF, 0xFFFF, 
 109 0xFFFF, 0x03FF, 0x03FF, 0x03FF, 0x03FF, 0x01FF, 0x01F8, 0x0000, 
 114 0x0000, 0x4078, 0x60FC, 0x71CE, 0x7986, 0x7C06, 0x7E0E, 0x7F1C, 
 115 0x7FB8, 0x7C30, 0x6C30, 0x4600, 0x0630, 0x0330, 0x0300, 0x0000, 
 116 0xC078, 0xE0FC, 0xF1FE, 0xFBFF, 0xFFCF, 0xFF8F, 0xFF1F, 0xFFBE, 
 117 0xFFFC, 0xFE78, 0xFF78, 0xEFF8, 0xCFF8, 0x87F8, 0x07F8, 0x0300, 
 122 0x0000, 0x0002, 0x0006, 0x000E, 0x001E, 0x003E, 0x007E, 0x00FE, 
 123 0x01FE, 0x003E, 0x0036, 0x0062, 0x0060, 0x00C0, 0x00C0, 0x0000, 
 124 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 
 125 0x03FF, 0x07FF, 0x007F, 0x00F7, 0x00F3, 0x01E1, 0x01E0, 0x01C0, 
 130 0x0000, 0x0080, 0x01C0, 0x03E0, 0x0080, 0x0080, 0x0080, 0x1FFC, 
 131 0x1FFC, 0x0080, 0x0080, 0x0080, 0x03E0, 0x01C0, 0x0080, 0x0000, 
 132 0x0080, 0x01C0, 0x03E0, 0x07F0, 0x0FF8, 0x01C0, 0x3FFE, 0x3FFE, 
 133 0x3FFE, 0x3FFE, 0x01C0, 0x0FF8, 0x07F0, 0x03E0, 0x01C0, 0x0080, 
 138 0x0000, 0x0080, 0x01C0, 0x03E0, 0x0080, 0x0888, 0x188C, 0x3FFE, 
 139 0x188C, 0x0888, 0x0080, 0x03E0, 0x01C0, 0x0080, 0x0000, 0x0000, 
 140 0x0080, 0x01C0, 0x03E0, 0x07F0, 0x0BE8, 0x1DDC, 0x3FFE, 0x7FFF, 
 141 0x3FFE, 0x1DDC, 0x0BE8, 0x07F0, 0x03E0, 0x01C0, 0x0080, 0x0000, 
 146 0x0000, 0x001E, 0x000E, 0x060E, 0x0712, 0x03A0, 0x01C0, 0x00E0, 
 147 0x0170, 0x1238, 0x1C18, 0x1C00, 0x1E00, 0x0000, 0x0000, 0x0000, 
 148 0x007F, 0x003F, 0x0E1F, 0x0F0F, 0x0F97, 0x07E3, 0x03E1, 0x21F0, 
 149 0x31F8, 0x3A7C, 0x3C3C, 0x3E1C, 0x3F00, 0x3F80, 0x0000, 0x0000, 
 154 0x0000, 0x7800, 0x7000, 0x7060, 0x48E0, 0x05C0, 0x0380, 0x0700, 
 155 0x0E80, 0x1C48, 0x1838, 0x0038, 0x0078, 0x0000, 0x0000, 0x0000, 
 156 0xFE00, 0xFC00, 0xF870, 0xF0F0, 0xE9F0, 0xC7E0, 0x87C0, 0x0F84, 
 157 0x1F8C, 0x3E5C, 0x3C3C, 0x387C, 0x00FC, 0x01FC, 0x0000, 0x0000, 
 162 0x0006, 0x000E, 0x001C, 0x0018, 0x0020, 0x0040, 0x00F8, 0x0004, 
 163 0x1FF4, 0x200C, 0x2AA8, 0x1FF0, 0x1F80, 0x3800, 0x6000, 0x8000, 
 164 0x000F, 0x001F, 0x003E, 0x007C, 0x0070, 0x00E0, 0x01FC, 0x3FF6, 
 165 0x7FF6, 0x7FFE, 0x7FFC, 0x7FF8, 0x3FF0, 0x7FC0, 0xF800, 0xE000, 
 169 wxCursor    gMacCurrentCursor 
; 
 171 CursHandle 
wxGetStockCursor( int number 
) 
 173     wxASSERT_MSG( number 
>= 0 && number 
<=kwxCursorLast 
, wxT("invalid stock cursor id") ) ; 
 174     CursHandle c 
= (CursHandle
) NewHandle( sizeof(Cursor
) ) ; 
 175     memcpy( *c 
, &gMacCursors
[number
] , sizeof( Cursor 
) ) ; 
 179 wxCursorRefData::wxCursorRefData() 
 184     m_disposeHandle 
= false ; 
 185     m_releaseHandle 
= false ; 
 186     m_isColorCursor 
= false ; 
 190 wxCursorRefData::~wxCursorRefData() 
 192     if ( m_isColorCursor 
) 
 194         ::DisposeCCursor( (CCrsrHandle
) m_hCursor 
) ; 
 196     else if ( m_disposeHandle 
) 
 198         ::DisposeHandle( (Handle 
) m_hCursor 
) ; 
 200     else if ( m_releaseHandle 
) 
 202         // we don't release the resource since it may already 
 212 wxCursor::wxCursor(const char WXUNUSED(bits
)[], int WXUNUSED(width
), int WXUNUSED(height
), 
 213     int WXUNUSED(hotSpotX
), int WXUNUSED(hotSpotY
), const char WXUNUSED(maskBits
)[]) 
 217 wxCursor::wxCursor( const wxImage 
&image 
) 
 219     CreateFromImage( image 
) ; 
 222 wxCursor::wxCursor(const char **bits
)  
 224     (void) CreateFromXpm(bits
); 
 227 wxCursor::wxCursor(char **bits
)  
 229     (void) CreateFromXpm((const char **)bits
); 
 232 bool wxCursor::CreateFromXpm(const char **bits
) 
 234     wxCHECK_MSG( bits 
!= NULL
, FALSE
, wxT("invalid cursor data") ) 
 235     wxXPMDecoder decoder
; 
 236     wxImage img 
= decoder
.ReadData(bits
); 
 237     wxCHECK_MSG( img
.Ok(), FALSE
, wxT("invalid cursor data") )     
 238         CreateFromImage( img 
) ; 
 242 short GetCTabIndex( CTabHandle colors 
, RGBColor 
*col 
) 
 245     unsigned long bestdiff 
= 0xFFFF ; 
 246     for ( int i 
= 0 ; i 
< (**colors
).ctSize 
; ++i 
) 
 248         unsigned long diff 
= abs(col
->red 
-  (**colors
).ctTable
[i
].rgb
.red 
) + 
 249             abs(col
->green 
-  (**colors
).ctTable
[i
].rgb
.green 
) + 
 250             abs(col
->blue 
-  (**colors
).ctTable
[i
].rgb
.blue 
) ; 
 251         if ( diff 
< bestdiff 
) 
 254             retval 
= (**colors
).ctTable
[i
].value 
; 
 260 void wxCursor::CreateFromImage(const wxImage 
& image
)  
 262     m_refData 
= new wxCursorRefData
; 
 264     wxImage image16 
= image
.Scale(16,16) ; 
 265        unsigned char * rgbBits 
= image16
.GetData(); 
 268     int w 
= image16
.GetWidth()  ; 
 269     int h 
= image16
.GetHeight() ; 
 270     bool bHasMask 
= image16
.HasMask() ; 
 272        int hotSpotX 
= image16
.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_X
); 
 273     int hotSpotY 
= image16
.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_Y
); 
 274     if (hotSpotX 
< 0 || hotSpotX 
>= w
) 
 276     if (hotSpotY 
< 0 || hotSpotY 
>= h
) 
 279     PixMapHandle pm 
= (PixMapHandle
) NewHandleClear( sizeof (PixMap
))  ; 
 281     short bytesPerPixel 
= 1 ; 
 283     Rect bounds 
= { 0 , 0 , extent 
, extent 
} ; 
 284     CCrsrHandle ch 
= (CCrsrHandle
) NewHandleClear ( sizeof( CCrsr 
) ) ; 
 285     CTabHandle newColors 
= GetCTable( 8 ) ; 
 286     HandToHand((Handle 
*) &newColors
); 
 287     // set the values to the indices 
 288     for ( int i 
= 0 ; i 
< (**newColors
).ctSize 
; ++i 
) 
 290         (**newColors
).ctTable
[i
].value 
= i 
; 
 292     HLock( (Handle
) ch
) ; 
 293     (**ch
).crsrType 
= 0x8001 ; // color cursors 
 294     (**ch
).crsrMap 
= pm 
;  
 295     short bytesPerRow 
= bytesPerPixel 
* extent 
; 
 298     (**pm
).rowBytes 
= bytesPerRow 
| 0x8000; 
 299     (**pm
).bounds 
= bounds
;         
 300     (**pm
).pmVersion 
= 0;            
 303     (**pm
).hRes 
= 0x00480000; /* 72 DPI default res */ 
 304     (**pm
).vRes 
= 0x00480000; /* 72 DPI default res */ 
 305     (**pm
).pixelSize 
= depth
; 
 306     (**pm
).pixelType 
= 0; 
 308     (**pm
).cmpSize 
= depth
; 
 309     (**pm
).pmTable 
= newColors
; 
 311     (**ch
).crsrData 
= NewHandleClear( extent 
* bytesPerRow 
) ;   
 312     (**ch
).crsrXData 
= NULL 
; 
 313     (**ch
).crsrXValid 
= 0; 
 314     (**ch
).crsrXHandle 
= NULL
; 
 316     (**ch
).crsrHotSpot
.h 
= hotSpotX 
; 
 317     (**ch
).crsrHotSpot
.v 
= hotSpotY 
; 
 318     (**ch
).crsrXTable 
= NULL 
;  
 319     (**ch
).crsrID 
= GetCTSeed() ; 
 321     memset( (**ch
).crsr1Data  
, 0 , sizeof( Bits16 
) ) ; 
 322     memset( (**ch
).crsrMask 
, 0 , sizeof( Bits16 
) ) ; 
 324     unsigned char mr 
= image16
.GetMaskRed() ; 
 325     unsigned char mg 
= image16
.GetMaskGreen() ; 
 326     unsigned char mb 
= image16
.GetMaskBlue() ; 
 327     for ( int y 
= 0 ; y 
< h 
; ++y 
) 
 332         for ( int x 
= 0 ; x 
< w 
; ++x 
) 
 334             long pos 
= (y 
* w 
+ x
) * 3; 
 336             unsigned char r 
= rgbBits
[pos
] ; 
 337             unsigned char g 
= rgbBits
[pos
+1] ; 
 338             unsigned char b 
= rgbBits
[pos
+2] ; 
 339             RGBColor col 
= { 0xFFFF ,0xFFFF, 0xFFFF } ; 
 341             if ( bHasMask 
&& r
==mr 
&& g
==mg 
&& b
==mb 
) 
 343                 // masked area, does not appear anywhere 
 347                 if ( (int)r 
+ (int)g 
+ (int)b 
< 0x0200 ) 
 349                     rowbits 
|= ( 1 << (15-x
) ) ; 
 351                 maskbits 
|= ( 1 << (15-x
) ) ; 
 353                 col 
= *((RGBColor
*) wxColor( r 
, g 
, b 
).GetPixel()) ; 
 355             *((*(**ch
).crsrData
) + y 
* bytesPerRow 
+ x
) =  
 356                 GetCTabIndex( newColors 
, &col
) ; 
 358         (**ch
).crsr1Data
[y
] = rowbits 
; 
 359         (**ch
).crsrMask
[y
] = maskbits 
; 
 363         memcpy( (**ch
).crsrMask 
, (**ch
).crsr1Data 
, sizeof( Bits16
) ) ; 
 366     HUnlock((Handle
) ch
) ; 
 367     M_CURSORDATA
->m_hCursor 
= ch 
; 
 368     M_CURSORDATA
->m_isColorCursor 
= true ; 
 371 wxCursor::wxCursor(const wxString
& cursor_file
, long flags
, int hotSpotX
, int hotSpotY
) 
 373     m_refData 
= new wxCursorRefData
; 
 374     if ( flags 
== wxBITMAP_TYPE_MACCURSOR_RESOURCE 
) 
 377                 wxMacStringToPascal( cursor_file 
, theName 
) ; 
 379         Handle resHandle 
= ::GetNamedResource( 'crsr' , theName 
) ; 
 384             GetResInfo( resHandle 
, &theId 
, &theType 
, theName 
) ; 
 385             ReleaseResource( resHandle 
) ; 
 386             M_CURSORDATA
->m_hCursor 
= GetCCursor( theId 
) ; 
 387             if ( M_CURSORDATA
->m_hCursor 
) 
 388                 M_CURSORDATA
->m_isColorCursor 
= true ; 
 392             Handle resHandle 
= ::GetNamedResource( 'CURS' , theName 
) ; 
 397                 GetResInfo( resHandle 
, &theId 
, &theType 
, theName 
) ; 
 398                 ReleaseResource( resHandle 
) ; 
 399                  M_CURSORDATA
->m_hCursor 
= GetCursor( theId 
) ; 
 400                 if ( M_CURSORDATA
->m_hCursor 
) 
 401                     M_CURSORDATA
->m_releaseHandle 
= true ; 
 408         image
.LoadFile( cursor_file 
, flags 
) ; 
 411             image
.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_X
,hotSpotX 
) ; 
 412             image
.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y
,hotSpotY 
) ; 
 414             CreateFromImage(image
) ; 
 419 // Cursors by stock number 
 420 wxCursor::wxCursor(int cursor_type
) 
 422     m_refData 
= new wxCursorRefData
; 
 426     case wxCURSOR_COPY_ARROW
: 
 427         M_CURSORDATA
->m_themeCursor 
= kThemeCopyArrowCursor 
; 
 430         M_CURSORDATA
->m_themeCursor 
= kThemeWatchCursor 
; 
 433         M_CURSORDATA
->m_themeCursor 
= kThemeIBeamCursor 
; 
 436         M_CURSORDATA
->m_themeCursor 
= kThemeCrossCursor
; 
 438     case wxCURSOR_SIZENWSE
: 
 440             M_CURSORDATA
->m_hCursor 
= wxGetStockCursor(kwxCursorSizeNWSE
); 
 443     case wxCURSOR_SIZENESW
: 
 445             M_CURSORDATA
->m_hCursor 
= wxGetStockCursor(kwxCursorSizeNESW
); 
 448     case wxCURSOR_SIZEWE
: 
 450             M_CURSORDATA
->m_themeCursor 
= kThemeResizeLeftRightCursor
; 
 453     case wxCURSOR_SIZENS
: 
 455             M_CURSORDATA
->m_hCursor 
= wxGetStockCursor(kwxCursorSizeNS
); 
 458     case wxCURSOR_SIZING
: 
 460             M_CURSORDATA
->m_hCursor 
= wxGetStockCursor(kwxCursorSize
); 
 465             M_CURSORDATA
->m_themeCursor 
= kThemePointingHandCursor
; 
 468     case wxCURSOR_BULLSEYE
: 
 470             M_CURSORDATA
->m_hCursor 
= wxGetStockCursor(kwxCursorBullseye
); 
 473     case wxCURSOR_PENCIL
: 
 475             M_CURSORDATA
->m_hCursor 
= wxGetStockCursor(kwxCursorPencil
); 
 478     case wxCURSOR_MAGNIFIER
: 
 480             M_CURSORDATA
->m_hCursor 
= wxGetStockCursor(kwxCursorMagnifier
); 
 483     case wxCURSOR_NO_ENTRY
: 
 485             M_CURSORDATA
->m_hCursor 
= wxGetStockCursor(kwxCursorNoEntry
); 
 490             M_CURSORDATA
->m_themeCursor 
= kThemeWatchCursor
; 
 493     case wxCURSOR_PAINT_BRUSH
: 
 495             M_CURSORDATA
->m_hCursor 
= wxGetStockCursor(kwxCursorPaintBrush
); 
 498     case wxCURSOR_POINT_LEFT
: 
 500             M_CURSORDATA
->m_hCursor 
= wxGetStockCursor(kwxCursorPointLeft
); 
 503     case wxCURSOR_POINT_RIGHT
: 
 505             M_CURSORDATA
->m_hCursor 
= wxGetStockCursor(kwxCursorPointRight
); 
 508     case wxCURSOR_QUESTION_ARROW
: 
 510             M_CURSORDATA
->m_hCursor 
= wxGetStockCursor(kwxCursorQuestionArrow
); 
 515             M_CURSORDATA
->m_hCursor 
= wxGetStockCursor(kwxCursorBlank
); 
 518     case wxCURSOR_RIGHT_ARROW
: 
 520             M_CURSORDATA
->m_hCursor 
= wxGetStockCursor(kwxCursorRightArrow
); 
 523     case wxCURSOR_SPRAYCAN
: 
 525             M_CURSORDATA
->m_hCursor 
= wxGetStockCursor(kwxCursorRoller
); 
 530     case wxCURSOR_LEFT_BUTTON
: 
 531     case wxCURSOR_RIGHT_BUTTON
: 
 532     case wxCURSOR_MIDDLE_BUTTON
: 
 534         M_CURSORDATA
->m_themeCursor 
= kThemeArrowCursor 
; 
 537     if ( M_CURSORDATA
->m_themeCursor 
== -1 ) 
 538         M_CURSORDATA
->m_releaseHandle 
= true ; 
 541 void wxCursor::MacInstall() const  
 543     gMacCurrentCursor 
= *this ; 
 544     if ( m_refData 
&& M_CURSORDATA
->m_themeCursor 
!= -1 ) 
 546         SetThemeCursor( M_CURSORDATA
->m_themeCursor 
) ; 
 548     else if ( m_refData 
&& M_CURSORDATA
->m_hCursor 
) 
 550         if ( M_CURSORDATA
->m_isColorCursor 
) 
 551             ::SetCCursor( (CCrsrHandle
) M_CURSORDATA
->m_hCursor 
) ; 
 553             ::SetCursor( * (CursHandle
) M_CURSORDATA
->m_hCursor 
) ; 
 557         SetThemeCursor( kThemeArrowCursor 
) ; 
 561 wxCursor::~wxCursor() 
 565 // Global cursor setting 
 566 void wxSetCursor(const wxCursor
& cursor
) 
 568     cursor
.MacInstall() ;