Tidied copyright and date for wxMac files
[wxWidgets.git] / src / mac / carbon / cursor.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: cursor.cpp
3 // Purpose: wxCursor class
4 // Author: Stefan Csomor
5 // Modified by:
6 // Created: 1998-01-01
7 // RCS-ID: $Id$
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "cursor.h"
14 #endif
15
16 #include "wx/defs.h"
17
18 #include "wx/app.h"
19 #include "wx/cursor.h"
20 #include "wx/icon.h"
21 #include "wx/image.h"
22 #include "wx/mac/private.h"
23
24 #if !USE_SHARED_LIBRARIES
25 IMPLEMENT_DYNAMIC_CLASS(wxCursor, wxBitmap)
26 #endif
27
28 const short kwxCursorBullseye = 10 ;
29 const short kwxCursorBlank = 11 ;
30 const short kwxCursorPencil = 12 ;
31 const short kwxCursorMagnifier = 13 ;
32 const short kwxCursorNoEntry = 14 ;
33 const short kwxCursorPaintBrush = 15 ;
34 const short kwxCursorPointRight = 16 ;
35 const short kwxCursorPointLeft = 17 ;
36 const short kwxCursorQuestionArrow = 18 ;
37 const short kwxCursorRightArrow = 19 ;
38 const short kwxCursorSizeNS = 20 ;
39 const short kwxCursorSize = 21 ;
40 const short kwxCursorSizeNESW = 22 ;
41 const short kwxCursorSizeNWSE = 23 ;
42 const short kwxCursorRoller = 24 ;
43
44 wxCursor gMacCurrentCursor ;
45
46 wxCursorRefData::wxCursorRefData()
47 {
48 m_width = 16;
49 m_height = 16;
50 m_hCursor = NULL ;
51 m_disposeHandle = false ;
52 m_releaseHandle = false ;
53 m_isColorCursor = false ;
54 m_themeCursor = -1 ;
55 }
56
57 wxCursorRefData::~wxCursorRefData()
58 {
59 if ( m_isColorCursor )
60 {
61 ::DisposeCCursor( (CCrsrHandle) m_hCursor ) ;
62 }
63 else if ( m_disposeHandle )
64 {
65 ::DisposeHandle( (Handle ) m_hCursor ) ;
66 }
67 else if ( m_releaseHandle )
68 {
69 // we don't release the resource since it may already
70 // be in use again
71 }
72 }
73
74 // Cursors
75 wxCursor::wxCursor()
76 {
77 }
78
79 wxCursor::wxCursor(const char WXUNUSED(bits)[], int WXUNUSED(width), int WXUNUSED(height),
80 int WXUNUSED(hotSpotX), int WXUNUSED(hotSpotY), const char WXUNUSED(maskBits)[])
81 {
82 }
83
84 wxCursor::wxCursor( const wxImage &image )
85 {
86 CreateFromImage( image ) ;
87 }
88
89 void wxCursor::CreateFromImage(const wxImage & image)
90 {
91 m_refData = new wxCursorRefData;
92
93 wxImage image16 = image.Scale(16,16) ;
94 unsigned char * rgbBits = image16.GetData();
95
96
97 int w = image16.GetWidth() ;
98 int h = image16.GetHeight() ;
99 bool bHasMask = image16.HasMask() ;
100
101 int hotSpotX = image16.GetOptionInt(wxCUR_HOTSPOT_X);
102 int hotSpotY = image16.GetOptionInt(wxCUR_HOTSPOT_Y);
103 if (hotSpotX < 0 || hotSpotX >= w)
104 hotSpotX = 0;
105 if (hotSpotY < 0 || hotSpotY >= h)
106 hotSpotY = 0;
107
108 M_CURSORDATA->m_hCursor = NewHandle( sizeof( Cursor ) ) ;
109 M_CURSORDATA->m_disposeHandle = true ;
110 HLock( (Handle) M_CURSORDATA->m_hCursor ) ;
111 CursPtr cp = *(CursHandle)M_CURSORDATA->m_hCursor ;
112 memset( cp->data , 0 , sizeof( Bits16 ) ) ;
113 memset( cp->mask , 0 , sizeof( Bits16 ) ) ;
114
115 unsigned char mr = image16.GetMaskRed() ;
116 unsigned char mg = image16.GetMaskGreen() ;
117 unsigned char mb = image16.GetMaskBlue() ;
118 for ( int y = 0 ; y < h ; ++y )
119 {
120 short rowbits = 0 ;
121 short maskbits = 0 ;
122
123 for ( int x = 0 ; x < w ; ++x )
124 {
125 long pos = (y * w + x) * 3;
126
127 unsigned char r = rgbBits[pos] ;
128 unsigned char g = rgbBits[pos+1] ;
129 unsigned char b = rgbBits[pos+2] ;
130 if ( bHasMask && r==mr && g==mg && b==mb )
131 {
132 // masked area, does not appear anywhere
133 }
134 else
135 {
136 if ( (int)r + (int)g + (int)b < 0x60 )
137 {
138 rowbits |= ( 1 << (15-x) ) ;
139 }
140 maskbits |= ( 1 << (15-x) ) ;
141 }
142 }
143 cp->data[y] = rowbits ;
144 cp->mask[y] = maskbits ;
145 }
146 if ( !bHasMask )
147 {
148 memcpy( cp->mask , cp->data , sizeof( Bits16) ) ;
149 }
150
151 cp->hotSpot.h = hotSpotX ;
152 cp->hotSpot.v = hotSpotY ;
153 HUnlock( (Handle) M_CURSORDATA->m_hCursor ) ;
154 }
155
156 wxCursor::wxCursor(const wxString& cursor_file, long flags, int hotSpotX, int hotSpotY)
157 {
158 m_refData = new wxCursorRefData;
159 if ( flags == wxBITMAP_TYPE_MACCURSOR_RESOURCE )
160 {
161 Str255 theName ;
162
163 #if TARGET_CARBON
164 c2pstrcpy( (StringPtr) theName , cursor_file ) ;
165 #else
166 strcpy( (char *) theName , cursor_file ) ;
167 c2pstr( (char *) theName ) ;
168 #endif
169
170 wxStAppResource resload ;
171 Handle resHandle = ::GetNamedResource( 'crsr' , theName ) ;
172 if ( resHandle )
173 {
174 short theId = -1 ;
175 OSType theType ;
176 GetResInfo( resHandle , &theId , &theType , theName ) ;
177 ReleaseResource( resHandle ) ;
178 M_CURSORDATA->m_hCursor = GetCCursor( theId ) ;
179 if ( M_CURSORDATA->m_hCursor )
180 M_CURSORDATA->m_isColorCursor = true ;
181 }
182 else
183 {
184 Handle resHandle = ::GetNamedResource( 'CURS' , theName ) ;
185 if ( resHandle )
186 {
187 short theId = -1 ;
188 OSType theType ;
189 GetResInfo( resHandle , &theId , &theType , theName ) ;
190 ReleaseResource( resHandle ) ;
191 M_CURSORDATA->m_hCursor = GetCursor( theId ) ;
192 if ( M_CURSORDATA->m_hCursor )
193 M_CURSORDATA->m_releaseHandle = true ;
194 }
195 }
196 }
197 else
198 {
199 wxImage image ;
200 image.LoadFile( cursor_file , flags ) ;
201 if( image.Ok() )
202 {
203 image.SetOption(wxCUR_HOTSPOT_X,hotSpotX ) ;
204 image.SetOption(wxCUR_HOTSPOT_Y,hotSpotY ) ;
205 delete m_refData ;
206 CreateFromImage(image) ;
207 }
208 }
209 }
210
211 // Cursors by stock number
212 wxCursor::wxCursor(int cursor_type)
213 {
214 m_refData = new wxCursorRefData;
215
216 switch (cursor_type)
217 {
218 case wxCURSOR_WAIT:
219 M_CURSORDATA->m_themeCursor = kThemeWatchCursor ;
220 break;
221 case wxCURSOR_IBEAM:
222 M_CURSORDATA->m_themeCursor = kThemeIBeamCursor ;
223 break;
224 case wxCURSOR_CROSS:
225 M_CURSORDATA->m_themeCursor = kThemeCrossCursor;
226 break;
227 case wxCURSOR_SIZENWSE:
228 {
229 wxStAppResource resload ;
230 M_CURSORDATA->m_hCursor = ::GetCursor(kwxCursorSizeNWSE);
231 }
232 break;
233 case wxCURSOR_SIZENESW:
234 {
235 wxStAppResource resload ;
236 M_CURSORDATA->m_hCursor = ::GetCursor(kwxCursorSizeNESW);
237 }
238 break;
239 case wxCURSOR_SIZEWE:
240 {
241 M_CURSORDATA->m_themeCursor = kThemeResizeLeftRightCursor;
242 }
243 break;
244 case wxCURSOR_SIZENS:
245 {
246 wxStAppResource resload ;
247 M_CURSORDATA->m_hCursor = ::GetCursor(kwxCursorSizeNS);
248 }
249 break;
250 case wxCURSOR_SIZING:
251 {
252 wxStAppResource resload ;
253 M_CURSORDATA->m_hCursor = ::GetCursor(kwxCursorSize);
254 }
255 break;
256 case wxCURSOR_HAND:
257 {
258 M_CURSORDATA->m_themeCursor = kThemePointingHandCursor;
259 }
260 break;
261 case wxCURSOR_BULLSEYE:
262 {
263 wxStAppResource resload ;
264 M_CURSORDATA->m_hCursor = ::GetCursor(kwxCursorBullseye);
265 }
266 break;
267 case wxCURSOR_PENCIL:
268 {
269 wxStAppResource resload ;
270 M_CURSORDATA->m_hCursor = ::GetCursor(kwxCursorPencil);
271 }
272 break;
273 case wxCURSOR_MAGNIFIER:
274 {
275 wxStAppResource resload ;
276 M_CURSORDATA->m_hCursor = ::GetCursor(kwxCursorMagnifier);
277 }
278 break;
279 case wxCURSOR_NO_ENTRY:
280 {
281 wxStAppResource resload ;
282 M_CURSORDATA->m_hCursor = ::GetCursor(kwxCursorNoEntry);
283 }
284 break;
285 case wxCURSOR_WATCH:
286 {
287 M_CURSORDATA->m_themeCursor = kThemeWatchCursor;
288 break;
289 }
290 case wxCURSOR_PAINT_BRUSH:
291 {
292 wxStAppResource resload ;
293 M_CURSORDATA->m_hCursor = ::GetCursor(kwxCursorPaintBrush);
294 break;
295 }
296 case wxCURSOR_POINT_LEFT:
297 {
298 wxStAppResource resload ;
299 M_CURSORDATA->m_hCursor = ::GetCursor(kwxCursorPointLeft);
300 break;
301 }
302 case wxCURSOR_POINT_RIGHT:
303 {
304 wxStAppResource resload ;
305 M_CURSORDATA->m_hCursor = ::GetCursor(kwxCursorPointRight);
306 break;
307 }
308 case wxCURSOR_QUESTION_ARROW:
309 {
310 wxStAppResource resload ;
311 M_CURSORDATA->m_hCursor = ::GetCursor(kwxCursorQuestionArrow);
312 break;
313 }
314 case wxCURSOR_BLANK:
315 {
316 wxStAppResource resload ;
317 M_CURSORDATA->m_hCursor = ::GetCursor(kwxCursorBlank);
318 break;
319 }
320 case wxCURSOR_RIGHT_ARROW:
321 {
322 wxStAppResource resload ;
323 M_CURSORDATA->m_hCursor = ::GetCursor(kwxCursorRightArrow);
324 break;
325 }
326 case wxCURSOR_SPRAYCAN:
327 {
328 wxStAppResource resload ;
329 M_CURSORDATA->m_hCursor = ::GetCursor(kwxCursorRoller);
330 break;
331 }
332 case wxCURSOR_CHAR:
333 case wxCURSOR_ARROW:
334 case wxCURSOR_LEFT_BUTTON:
335 case wxCURSOR_RIGHT_BUTTON:
336 case wxCURSOR_MIDDLE_BUTTON:
337 default:
338 M_CURSORDATA->m_themeCursor = kThemeArrowCursor ;
339 break;
340 }
341 if ( M_CURSORDATA->m_themeCursor == -1 )
342 M_CURSORDATA->m_releaseHandle = true ;
343 }
344
345 void wxCursor::MacInstall() const
346 {
347 gMacCurrentCursor = *this ;
348 if ( m_refData && M_CURSORDATA->m_themeCursor != -1 )
349 {
350 SetThemeCursor( M_CURSORDATA->m_themeCursor ) ;
351 }
352 else if ( m_refData && M_CURSORDATA->m_hCursor )
353 {
354 if ( M_CURSORDATA->m_isColorCursor )
355 ::SetCCursor( (CCrsrHandle) M_CURSORDATA->m_hCursor ) ;
356 else
357 ::SetCursor( * (CursHandle) M_CURSORDATA->m_hCursor ) ;
358 }
359 else
360 {
361 SetThemeCursor( kThemeArrowCursor ) ;
362 }
363 }
364
365 wxCursor::~wxCursor()
366 {
367 }
368
369 // Global cursor setting
370 void wxSetCursor(const wxCursor& cursor)
371 {
372 cursor.MacInstall() ;
373 }
374
375