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 wxStAppResource resload
;
380 Handle resHandle
= ::GetNamedResource( 'crsr' , theName
) ;
385 GetResInfo( resHandle
, &theId
, &theType
, theName
) ;
386 ReleaseResource( resHandle
) ;
387 M_CURSORDATA
->m_hCursor
= GetCCursor( theId
) ;
388 if ( M_CURSORDATA
->m_hCursor
)
389 M_CURSORDATA
->m_isColorCursor
= true ;
393 Handle resHandle
= ::GetNamedResource( 'CURS' , theName
) ;
398 GetResInfo( resHandle
, &theId
, &theType
, theName
) ;
399 ReleaseResource( resHandle
) ;
400 M_CURSORDATA
->m_hCursor
= GetCursor( theId
) ;
401 if ( M_CURSORDATA
->m_hCursor
)
402 M_CURSORDATA
->m_releaseHandle
= true ;
409 image
.LoadFile( cursor_file
, flags
) ;
412 image
.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_X
,hotSpotX
) ;
413 image
.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y
,hotSpotY
) ;
415 CreateFromImage(image
) ;
420 // Cursors by stock number
421 wxCursor::wxCursor(int cursor_type
)
423 m_refData
= new wxCursorRefData
;
427 case wxCURSOR_COPY_ARROW
:
428 M_CURSORDATA
->m_themeCursor
= kThemeCopyArrowCursor
;
431 M_CURSORDATA
->m_themeCursor
= kThemeWatchCursor
;
434 M_CURSORDATA
->m_themeCursor
= kThemeIBeamCursor
;
437 M_CURSORDATA
->m_themeCursor
= kThemeCrossCursor
;
439 case wxCURSOR_SIZENWSE
:
441 M_CURSORDATA
->m_hCursor
= wxGetStockCursor(kwxCursorSizeNWSE
);
444 case wxCURSOR_SIZENESW
:
446 M_CURSORDATA
->m_hCursor
= wxGetStockCursor(kwxCursorSizeNESW
);
449 case wxCURSOR_SIZEWE
:
451 M_CURSORDATA
->m_themeCursor
= kThemeResizeLeftRightCursor
;
454 case wxCURSOR_SIZENS
:
456 M_CURSORDATA
->m_hCursor
= wxGetStockCursor(kwxCursorSizeNS
);
459 case wxCURSOR_SIZING
:
461 M_CURSORDATA
->m_hCursor
= wxGetStockCursor(kwxCursorSize
);
466 M_CURSORDATA
->m_themeCursor
= kThemePointingHandCursor
;
469 case wxCURSOR_BULLSEYE
:
471 M_CURSORDATA
->m_hCursor
= wxGetStockCursor(kwxCursorBullseye
);
474 case wxCURSOR_PENCIL
:
476 M_CURSORDATA
->m_hCursor
= wxGetStockCursor(kwxCursorPencil
);
479 case wxCURSOR_MAGNIFIER
:
481 M_CURSORDATA
->m_hCursor
= wxGetStockCursor(kwxCursorMagnifier
);
484 case wxCURSOR_NO_ENTRY
:
486 M_CURSORDATA
->m_hCursor
= wxGetStockCursor(kwxCursorNoEntry
);
491 M_CURSORDATA
->m_themeCursor
= kThemeWatchCursor
;
494 case wxCURSOR_PAINT_BRUSH
:
496 M_CURSORDATA
->m_hCursor
= wxGetStockCursor(kwxCursorPaintBrush
);
499 case wxCURSOR_POINT_LEFT
:
501 M_CURSORDATA
->m_hCursor
= wxGetStockCursor(kwxCursorPointLeft
);
504 case wxCURSOR_POINT_RIGHT
:
506 M_CURSORDATA
->m_hCursor
= wxGetStockCursor(kwxCursorPointRight
);
509 case wxCURSOR_QUESTION_ARROW
:
511 M_CURSORDATA
->m_hCursor
= wxGetStockCursor(kwxCursorQuestionArrow
);
516 M_CURSORDATA
->m_hCursor
= wxGetStockCursor(kwxCursorBlank
);
519 case wxCURSOR_RIGHT_ARROW
:
521 M_CURSORDATA
->m_hCursor
= wxGetStockCursor(kwxCursorRightArrow
);
524 case wxCURSOR_SPRAYCAN
:
526 M_CURSORDATA
->m_hCursor
= wxGetStockCursor(kwxCursorRoller
);
531 case wxCURSOR_LEFT_BUTTON
:
532 case wxCURSOR_RIGHT_BUTTON
:
533 case wxCURSOR_MIDDLE_BUTTON
:
535 M_CURSORDATA
->m_themeCursor
= kThemeArrowCursor
;
538 if ( M_CURSORDATA
->m_themeCursor
== -1 )
539 M_CURSORDATA
->m_releaseHandle
= true ;
542 void wxCursor::MacInstall() const
544 gMacCurrentCursor
= *this ;
545 if ( m_refData
&& M_CURSORDATA
->m_themeCursor
!= -1 )
547 SetThemeCursor( M_CURSORDATA
->m_themeCursor
) ;
549 else if ( m_refData
&& M_CURSORDATA
->m_hCursor
)
551 if ( M_CURSORDATA
->m_isColorCursor
)
552 ::SetCCursor( (CCrsrHandle
) M_CURSORDATA
->m_hCursor
) ;
554 ::SetCursor( * (CursHandle
) M_CURSORDATA
->m_hCursor
) ;
558 SetThemeCursor( kThemeArrowCursor
) ;
562 wxCursor::~wxCursor()
566 // Global cursor setting
567 void wxSetCursor(const wxCursor
& cursor
)
569 cursor
.MacInstall() ;