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
;
136 int hotSpotX
= image
.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_X
);
137 int hotSpotY
= image
.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_Y
);
138 int image_w
= image
.GetWidth();
139 int image_h
= image
.GetHeight();
141 wxASSERT_MSG( hotSpotX
>= 0 && hotSpotX
< image_w
&&
142 hotSpotY
>= 0 && hotSpotY
< image_h
,
143 _T("invalid cursor hot spot coordinates") );
145 wxImage
image16(image
); // final image of correct size
147 // if image is too small then place it in the center, resize it if too big
148 if ((w
> image_w
) && (h
> image_h
))
150 wxPoint
offset((w
- image_w
)/2, (h
- image_h
)/2);
151 hotSpotX
= hotSpotX
+ offset
.x
;
152 hotSpotY
= hotSpotY
+ offset
.y
;
154 image16
= image
.Size(wxSize(w
, h
), offset
);
156 else if ((w
!= image_w
) || (h
!= image_h
))
158 hotSpotX
= int(hotSpotX
* double(w
) / double(image_w
));
159 hotSpotY
= int(hotSpotY
* double(h
) / double(image_h
));
161 image16
= image
.Scale(w
, h
);
164 unsigned char * rgbBits
= image16
.GetData();
165 bool bHasMask
= image16
.HasMask() ;
168 // monochrome implementation
169 M_CURSORDATA
->m_hCursor
= NewHandle( sizeof( Cursor
) ) ;
170 M_CURSORDATA
->m_disposeHandle
= true ;
171 HLock( (Handle
) M_CURSORDATA
->m_hCursor
) ;
172 CursPtr cp
= *(CursHandle
)M_CURSORDATA
->m_hCursor
;
173 memset( cp
->data
, 0 , sizeof( Bits16
) ) ;
174 memset( cp
->mask
, 0 , sizeof( Bits16
) ) ;
176 unsigned char mr
= image16
.GetMaskRed() ;
177 unsigned char mg
= image16
.GetMaskGreen() ;
178 unsigned char mb
= image16
.GetMaskBlue() ;
179 for ( int y
= 0 ; y
< h
; ++y
)
184 for ( int x
= 0 ; x
< w
; ++x
)
186 long pos
= (y
* w
+ x
) * 3;
188 unsigned char r
= rgbBits
[pos
] ;
189 unsigned char g
= rgbBits
[pos
+1] ;
190 unsigned char b
= rgbBits
[pos
+2] ;
191 if ( bHasMask
&& r
==mr
&& g
==mg
&& b
==mb
)
193 // masked area, does not appear anywhere
197 if ( (int)r
+ (int)g
+ (int)b
< 0x0200 )
199 rowbits
|= ( 1 << (15-x
) ) ;
201 maskbits
|= ( 1 << (15-x
) ) ;
204 cp
->data
[y
] = rowbits
;
205 cp
->mask
[y
] = maskbits
;
209 memcpy( cp
->mask
, cp
->data
, sizeof( Bits16
) ) ;
211 cp
->hotSpot
.h
= hotSpotX
;
212 cp
->hotSpot
.v
= hotSpotY
;
213 HUnlock( (Handle
) M_CURSORDATA
->m_hCursor
) ;
215 PixMapHandle pm
= (PixMapHandle
) NewHandleClear( sizeof (PixMap
)) ;
217 short bytesPerPixel
= 1 ;
219 Rect bounds
= { 0 , 0 , extent
, extent
} ;
220 CCrsrHandle ch
= (CCrsrHandle
) NewHandleClear ( sizeof( CCrsr
) ) ;
221 CTabHandle newColors
= GetCTable( 8 ) ;
222 HandToHand((Handle
*) &newColors
);
223 // set the values to the indices
224 for ( int i
= 0 ; i
< (**newColors
).ctSize
; ++i
)
226 (**newColors
).ctTable
[i
].value
= i
;
228 HLock( (Handle
) ch
) ;
229 (**ch
).crsrType
= 0x8001 ; // color cursors
230 (**ch
).crsrMap
= pm
;
231 short bytesPerRow
= bytesPerPixel
* extent
;
234 (**pm
).rowBytes
= bytesPerRow
| 0x8000;
235 (**pm
).bounds
= bounds
;
236 (**pm
).pmVersion
= 0;
239 (**pm
).hRes
= 0x00480000; /* 72 DPI default res */
240 (**pm
).vRes
= 0x00480000; /* 72 DPI default res */
241 (**pm
).pixelSize
= depth
;
242 (**pm
).pixelType
= 0;
244 (**pm
).cmpSize
= depth
;
245 (**pm
).pmTable
= newColors
;
247 (**ch
).crsrData
= NewHandleClear( extent
* bytesPerRow
) ;
248 (**ch
).crsrXData
= NULL
;
249 (**ch
).crsrXValid
= 0;
250 (**ch
).crsrXHandle
= NULL
;
252 (**ch
).crsrHotSpot
.h
= hotSpotX
;
253 (**ch
).crsrHotSpot
.v
= hotSpotY
;
254 (**ch
).crsrXTable
= NULL
;
255 (**ch
).crsrID
= GetCTSeed() ;
257 memset( (**ch
).crsr1Data
, 0 , sizeof( Bits16
) ) ;
258 memset( (**ch
).crsrMask
, 0 , sizeof( Bits16
) ) ;
260 unsigned char mr
= image16
.GetMaskRed() ;
261 unsigned char mg
= image16
.GetMaskGreen() ;
262 unsigned char mb
= image16
.GetMaskBlue() ;
263 for ( int y
= 0 ; y
< h
; ++y
)
268 for ( int x
= 0 ; x
< w
; ++x
)
270 long pos
= (y
* w
+ x
) * 3;
272 unsigned char r
= rgbBits
[pos
] ;
273 unsigned char g
= rgbBits
[pos
+1] ;
274 unsigned char b
= rgbBits
[pos
+2] ;
275 RGBColor col
= { 0xFFFF ,0xFFFF, 0xFFFF } ;
277 if ( bHasMask
&& r
==mr
&& g
==mg
&& b
==mb
)
279 // masked area, does not appear anywhere
283 if ( (int)r
+ (int)g
+ (int)b
< 0x0200 )
285 rowbits
|= ( 1 << (15-x
) ) ;
287 maskbits
|= ( 1 << (15-x
) ) ;
289 col
= *((RGBColor
*) wxColor( r
, g
, b
).GetPixel()) ;
291 *((*(**ch
).crsrData
) + y
* bytesPerRow
+ x
) =
292 GetCTabIndex( newColors
, &col
) ;
294 (**ch
).crsr1Data
[y
] = rowbits
;
295 (**ch
).crsrMask
[y
] = maskbits
;
299 memcpy( (**ch
).crsrMask
, (**ch
).crsr1Data
, sizeof( Bits16
) ) ;
302 HUnlock((Handle
) ch
) ;
303 M_CURSORDATA
->m_hCursor
= ch
;
304 M_CURSORDATA
->m_isColorCursor
= true ;
308 wxCursor::wxCursor(const wxString
& cursor_file
, long flags
, int hotSpotX
, int hotSpotY
)
310 m_refData
= new wxCursorRefData
;
311 if ( flags
== wxBITMAP_TYPE_MACCURSOR_RESOURCE
)
314 wxMacStringToPascal( cursor_file
, theName
) ;
316 wxStAppResource resload
;
317 Handle resHandle
= ::GetNamedResource( 'crsr' , theName
) ;
322 GetResInfo( resHandle
, &theId
, &theType
, theName
) ;
323 ReleaseResource( resHandle
) ;
324 M_CURSORDATA
->m_hCursor
= GetCCursor( theId
) ;
325 if ( M_CURSORDATA
->m_hCursor
)
326 M_CURSORDATA
->m_isColorCursor
= true ;
330 Handle resHandle
= ::GetNamedResource( 'CURS' , theName
) ;
335 GetResInfo( resHandle
, &theId
, &theType
, theName
) ;
336 ReleaseResource( resHandle
) ;
337 M_CURSORDATA
->m_hCursor
= GetCursor( theId
) ;
338 if ( M_CURSORDATA
->m_hCursor
)
339 M_CURSORDATA
->m_releaseHandle
= true ;
346 image
.LoadFile( cursor_file
, flags
) ;
349 image
.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_X
,hotSpotX
) ;
350 image
.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y
,hotSpotY
) ;
352 CreateFromImage(image
) ;
357 // Cursors by stock number
358 wxCursor::wxCursor(int cursor_type
)
360 m_refData
= new wxCursorRefData
;
364 case wxCURSOR_COPY_ARROW
:
365 M_CURSORDATA
->m_themeCursor
= kThemeCopyArrowCursor
;
368 M_CURSORDATA
->m_themeCursor
= kThemeWatchCursor
;
371 M_CURSORDATA
->m_themeCursor
= kThemeIBeamCursor
;
374 M_CURSORDATA
->m_themeCursor
= kThemeCrossCursor
;
376 case wxCURSOR_SIZENWSE
:
378 wxStAppResource resload
;
379 M_CURSORDATA
->m_hCursor
= ::GetCursor(kwxCursorSizeNWSE
);
382 case wxCURSOR_SIZENESW
:
384 wxStAppResource resload
;
385 M_CURSORDATA
->m_hCursor
= ::GetCursor(kwxCursorSizeNESW
);
388 case wxCURSOR_SIZEWE
:
390 M_CURSORDATA
->m_themeCursor
= kThemeResizeLeftRightCursor
;
393 case wxCURSOR_SIZENS
:
395 wxStAppResource resload
;
396 M_CURSORDATA
->m_hCursor
= ::GetCursor(kwxCursorSizeNS
);
399 case wxCURSOR_SIZING
:
401 wxStAppResource resload
;
402 M_CURSORDATA
->m_hCursor
= ::GetCursor(kwxCursorSize
);
407 M_CURSORDATA
->m_themeCursor
= kThemePointingHandCursor
;
410 case wxCURSOR_BULLSEYE
:
412 wxStAppResource resload
;
413 M_CURSORDATA
->m_hCursor
= ::GetCursor(kwxCursorBullseye
);
416 case wxCURSOR_PENCIL
:
418 wxStAppResource resload
;
419 M_CURSORDATA
->m_hCursor
= ::GetCursor(kwxCursorPencil
);
422 case wxCURSOR_MAGNIFIER
:
424 wxStAppResource resload
;
425 M_CURSORDATA
->m_hCursor
= ::GetCursor(kwxCursorMagnifier
);
428 case wxCURSOR_NO_ENTRY
:
430 wxStAppResource resload
;
431 M_CURSORDATA
->m_hCursor
= ::GetCursor(kwxCursorNoEntry
);
436 M_CURSORDATA
->m_themeCursor
= kThemeWatchCursor
;
439 case wxCURSOR_PAINT_BRUSH
:
441 wxStAppResource resload
;
442 M_CURSORDATA
->m_hCursor
= ::GetCursor(kwxCursorPaintBrush
);
445 case wxCURSOR_POINT_LEFT
:
447 wxStAppResource resload
;
448 M_CURSORDATA
->m_hCursor
= ::GetCursor(kwxCursorPointLeft
);
451 case wxCURSOR_POINT_RIGHT
:
453 wxStAppResource resload
;
454 M_CURSORDATA
->m_hCursor
= ::GetCursor(kwxCursorPointRight
);
457 case wxCURSOR_QUESTION_ARROW
:
459 wxStAppResource resload
;
460 M_CURSORDATA
->m_hCursor
= ::GetCursor(kwxCursorQuestionArrow
);
465 wxStAppResource resload
;
466 M_CURSORDATA
->m_hCursor
= ::GetCursor(kwxCursorBlank
);
469 case wxCURSOR_RIGHT_ARROW
:
471 wxStAppResource resload
;
472 M_CURSORDATA
->m_hCursor
= ::GetCursor(kwxCursorRightArrow
);
475 case wxCURSOR_SPRAYCAN
:
477 wxStAppResource resload
;
478 M_CURSORDATA
->m_hCursor
= ::GetCursor(kwxCursorRoller
);
483 case wxCURSOR_LEFT_BUTTON
:
484 case wxCURSOR_RIGHT_BUTTON
:
485 case wxCURSOR_MIDDLE_BUTTON
:
487 M_CURSORDATA
->m_themeCursor
= kThemeArrowCursor
;
490 if ( M_CURSORDATA
->m_themeCursor
== -1 )
491 M_CURSORDATA
->m_releaseHandle
= true ;
494 void wxCursor::MacInstall() const
496 gMacCurrentCursor
= *this ;
497 if ( m_refData
&& M_CURSORDATA
->m_themeCursor
!= -1 )
499 SetThemeCursor( M_CURSORDATA
->m_themeCursor
) ;
501 else if ( m_refData
&& M_CURSORDATA
->m_hCursor
)
503 if ( M_CURSORDATA
->m_isColorCursor
)
504 ::SetCCursor( (CCrsrHandle
) M_CURSORDATA
->m_hCursor
) ;
506 ::SetCursor( * (CursHandle
) M_CURSORDATA
->m_hCursor
) ;
510 SetThemeCursor( kThemeArrowCursor
) ;
514 wxCursor::~wxCursor()
518 // Global cursor setting
519 void wxSetCursor(const wxCursor
& cursor
)
521 cursor
.MacInstall() ;