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() ;