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