1 #include "win32\win32guts.h"
2 #ifndef _APRICOT_H_
3 #include "apricot.h"
4 #endif
5 #include "guts.h"
6 #include "Window.h"
7 #include "Icon.h"
8 #include "Application.h"
9 
10 #ifdef __cplusplus
11 extern "C" {
12 #endif
13 
14 
15 #define  sys (( PDrawableData)(( PComponent) self)-> sysData)->
16 #define  dsys( view) (( PDrawableData)(( PComponent) view)-> sysData)->
17 #define var (( PWidget) self)->
18 #define HANDLE sys handle
19 #define DHANDLE(x) dsys(x) handle
20 
21 static unsigned char cursor_dnd_move[] = {
22 0x00,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x40,0x00,0x00,0x00,
23 0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
24 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
25 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
26 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
27 0x15,0x54,0x00,0x00,0x2A,0xAA,0x00,0x00,0x10,0x04,0x00,0x00,0x20,0x02,0x00,0x00,
28 0x10,0x04,0x00,0x00,0x20,0x02,0x00,0x00,0x10,0x04,0x00,0x00,0x29,0xAA,0x00,0x00,
29 0x15,0x94,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x06,0x00,0x00,0x00,
30 0x46,0x00,0x00,0x00,0x6C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7F,0x80,0x00,0x00,
31 0x7F,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x78,0x00,0x00,0x00,
32 0x70,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
33 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
34 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
35 0xC0,0x01,0xFF,0xFF,0xC0,0x01,0xFF,0xFF,0xCF,0xF9,0xFF,0xFF,0xCF,0xF9,0xFF,0xFF,
36 0xCF,0xF9,0xFF,0xFF,0xCF,0xF9,0xFF,0xFF,0xCE,0x39,0xFF,0xFF,0xC0,0x01,0xFF,0xFF,
37 0xC0,0x01,0xFF,0xFF,0xF8,0x7F,0xFF,0xFF,0x78,0x7F,0xFF,0xFF,0x30,0xFF,0xFF,0xFF,
38 0x10,0xFF,0xFF,0xFF,0x01,0xFF,0xFF,0xFF,0x00,0x1F,0xFF,0xFF,0x00,0x3F,0xFF,0xFF,
39 0x00,0x7F,0xFF,0xFF,0x00,0xFF,0xFF,0xFF,0x01,0xFF,0xFF,0xFF,0x03,0xFF,0xFF,0xFF,
40 0x07,0xFF,0xFF,0xFF,0x0F,0xFF,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF,0x3F,0xFF,0xFF,0xFF,
41 0x7F,0xFF,0xFF,0xFF
42 };
43 
44 static unsigned char cursor_dnd_copy[] = {
45 0x00,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x40,0x00,0x00,0x00,
46 0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
47 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
48 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xF0,0x00,
49 0x00,0x1F,0xF0,0x00,0x00,0x1E,0xF0,0x00,0x00,0x1E,0xF0,0x00,0x00,0x18,0x30,0x00,
50 0x15,0x5E,0xF0,0x00,0x2A,0x9E,0xF0,0x00,0x10,0x1F,0xF0,0x00,0x20,0x1F,0xF0,0x00,
51 0x10,0x00,0x00,0x00,0x20,0x02,0x00,0x00,0x10,0x04,0x00,0x00,0x29,0xAA,0x00,0x00,
52 0x15,0x94,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x06,0x00,0x00,0x00,
53 0x46,0x00,0x00,0x00,0x6C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7F,0x80,0x00,0x00,
54 0x7F,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x78,0x00,0x00,0x00,
55 0x70,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
56 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0,0x07,0xFF,0xFF,0xC0,0x07,0xFF,
57 0xFF,0xC0,0x07,0xFF,0xFF,0xC0,0x07,0xFF,0xFF,0xC0,0x07,0xFF,0xFF,0xC0,0x07,0xFF,
58 0xC0,0x00,0x07,0xFF,0xC0,0x00,0x07,0xFF,0xCF,0xC0,0x07,0xFF,0xCF,0xC0,0x07,0xFF,
59 0xCF,0xC0,0x07,0xFF,0xCF,0xF9,0xFF,0xFF,0xCE,0x39,0xFF,0xFF,0xC0,0x01,0xFF,0xFF,
60 0xC0,0x01,0xFF,0xFF,0xF8,0x7F,0xFF,0xFF,0x78,0x7F,0xFF,0xFF,0x30,0xFF,0xFF,0xFF,
61 0x10,0xFF,0xFF,0xFF,0x01,0xFF,0xFF,0xFF,0x00,0x1F,0xFF,0xFF,0x00,0x3F,0xFF,0xFF,
62 0x00,0x7F,0xFF,0xFF,0x00,0xFF,0xFF,0xFF,0x01,0xFF,0xFF,0xFF,0x03,0xFF,0xFF,0xFF,
63 0x07,0xFF,0xFF,0xFF,0x0F,0xFF,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF,0x3F,0xFF,0xFF,0xFF,
64 0x7F,0xFF,0xFF,0xFF
65 };
66 
67 static unsigned char cursor_dnd_link[] = {
68 0x00,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x40,0x00,0x00,0x00,
69 0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
70 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
71 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xF0,0x00,
72 0x00,0x1D,0xF0,0x00,0x00,0x1B,0xF0,0x00,0x00,0x19,0xF0,0x00,0x00,0x18,0xB0,0x00,
73 0x15,0x5C,0x30,0x00,0x2A,0x9E,0x30,0x00,0x10,0x1C,0x30,0x00,0x20,0x1F,0xF0,0x00,
74 0x10,0x00,0x00,0x00,0x20,0x02,0x00,0x00,0x10,0x04,0x00,0x00,0x29,0xAA,0x00,0x00,
75 0x15,0x94,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x06,0x00,0x00,0x00,
76 0x46,0x00,0x00,0x00,0x6C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7F,0x80,0x00,0x00,
77 0x7F,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x78,0x00,0x00,0x00,
78 0x70,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
79 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0,0x07,0xFF,0xFF,0xC0,0x07,0xFF,
80 0xFF,0xC0,0x07,0xFF,0xFF,0xC0,0x07,0xFF,0xFF,0xC0,0x07,0xFF,0xFF,0xC0,0x07,0xFF,
81 0xC0,0x00,0x07,0xFF,0xC0,0x00,0x07,0xFF,0xCF,0xC0,0x07,0xFF,0xCF,0xC0,0x07,0xFF,
82 0xCF,0xC0,0x07,0xFF,0xCF,0xF9,0xFF,0xFF,0xCE,0x39,0xFF,0xFF,0xC0,0x01,0xFF,0xFF,
83 0xC0,0x01,0xFF,0xFF,0xF8,0x7F,0xFF,0xFF,0x78,0x7F,0xFF,0xFF,0x30,0xFF,0xFF,0xFF,
84 0x10,0xFF,0xFF,0xFF,0x01,0xFF,0xFF,0xFF,0x00,0x1F,0xFF,0xFF,0x00,0x3F,0xFF,0xFF,
85 0x00,0x7F,0xFF,0xFF,0x00,0xFF,0xFF,0xFF,0x01,0xFF,0xFF,0xFF,0x03,0xFF,0xFF,0xFF,
86 0x07,0xFF,0xFF,0xFF,0x0F,0xFF,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF,0x3F,0xFF,0xFF,0xFF,
87 0x7F,0xFF,0xFF,0xFF
88 };
89 
90 static HCURSOR drag_cursors[crDragLink - crDragCopy + 1] = { NULL, NULL, NULL };
91 
92 static HCURSOR
create_drag_cursor(int cr)93 create_drag_cursor( int cr )
94 {
95 	unsigned char * bits = NULL;
96 	unsigned int size = 0;
97 	int index = cr - crDragCopy;
98 
99 	if ( cr < crDragCopy || cr > crDragLink)
100 		return NULL;
101 
102 	if ( drag_cursors[index] != NULL )
103 		return drag_cursors[index];
104 
105 	switch (cr) {
106 	case crDragCopy:
107 		bits = cursor_dnd_copy;
108 		size = sizeof(cursor_dnd_copy);
109 		break;
110 	case crDragMove:
111 		bits = cursor_dnd_move;
112 		size = sizeof(cursor_dnd_move);
113 		break;
114 	case crDragLink:
115 		bits = cursor_dnd_link;
116 		size = sizeof(cursor_dnd_link);
117 		break;
118 	}
119 
120 	if (( drag_cursors[index] = CreateIconFromResourceEx(
121 		bits, size,
122 		false, 0x30000,
123 		32, 32,
124 		LR_MONOCHROME | LR_SHARED /* LR_SHARED to release these automatically */
125 	)) == NULL )
126 		apiErr;
127 
128 	return drag_cursors[index];
129 }
130 
131 Bool
cursor_update(Handle self)132 cursor_update( Handle self)
133 {
134 	if ( !is_apt( aptFocused))
135 		return true;
136 	DestroyCaret();
137 	if ( is_apt( aptCursorVis)) {
138 		if ( !CreateCaret(( HWND) var handle, NULL, sys cursorSize. x, sys cursorSize. y)) apiErrRet;
139 		if ( !SetCaretPos( sys cursorPos. x, sys lastSize. y - sys cursorPos. y - sys cursorSize. y)) apiErrRet;
140 		if ( !ShowCaret(( HWND) var handle)) apiErrRet;
141 	}
142 	return true;
143 }
144 
145 Bool
apc_cursor_set_pos(Handle self,int x,int y)146 apc_cursor_set_pos( Handle self, int x, int y)
147 {
148 	objCheck false;
149 	if ( !hwnd_check_limits( x, y, true)) apcErrRet( errInvParams);
150 	sys cursorPos. x = x;
151 	sys cursorPos. y = y;
152 	return cursor_update( self);
153 }
154 
155 Bool
apc_cursor_set_size(Handle self,int x,int y)156 apc_cursor_set_size( Handle self, int x, int y)
157 {
158 	objCheck false;
159 	if ( !hwnd_check_limits( x, y, false)) apcErrRet( errInvParams);
160 	sys cursorSize. x = x;
161 	sys cursorSize. y = y;
162 	return cursor_update( self);
163 }
164 
165 Bool
apc_cursor_set_visible(Handle self,Bool visible)166 apc_cursor_set_visible( Handle self, Bool visible)
167 {
168 	objCheck false;
169 	apt_assign( aptCursorVis, visible);
170 	return cursor_update( self);
171 }
172 
173 Point
apc_cursor_get_pos(Handle self)174 apc_cursor_get_pos( Handle self)
175 {
176 	Point p = {0,0};
177 	objCheck p;
178 	return sys cursorPos;
179 }
180 
181 Point
apc_cursor_get_size(Handle self)182 apc_cursor_get_size( Handle self)
183 {
184 	Point p = {0,0};
185 	objCheck p;
186 	return sys cursorSize;
187 }
188 
189 Bool
apc_cursor_get_visible(Handle self)190 apc_cursor_get_visible( Handle self)
191 {
192 	objCheck false;
193 	return is_apt( aptCursorVis);
194 }
195 
196 Point
apc_pointer_get_hot_spot(Handle self)197 apc_pointer_get_hot_spot( Handle self)
198 {
199 	Point         r = {0,0};
200 	ICONINFO      ii;
201 	objCheck r;
202 	if ( !GetIconInfo( sys pointer, &ii))
203 		apiErr
204 	else {
205 		int y;
206 		BITMAP bitmap;
207 		if ( ii.hbmColor && GetObject( ii.hbmColor, sizeof( BITMAP), ( LPSTR) &bitmap))
208 			y = bitmap.bmHeight;
209 		else if ( GetObject( ii.hbmMask, sizeof( BITMAP), ( LPSTR) &bitmap))
210 			y = bitmap.bmHeight / 2;
211 		else
212 			y = guts. pointerSize. y;
213 		r. x = ii. xHotspot;
214 		r. y = y - ii. yHotspot - 1;
215 		DeleteObject( ii. hbmMask);
216 		DeleteObject( ii. hbmColor);
217 	}
218 	return r;
219 }
220 
221 Point
apc_pointer_get_pos(Handle self)222 apc_pointer_get_pos( Handle self)
223 {
224 	Point p = {0,0};
225 	RECT r;
226 	objCheck p;
227 	if ( !GetCursorPos(( POINT*) &p)) apiErr;
228 	GetWindowRect( HWND_DESKTOP, &r);
229 	p. y = r. bottom - p. y - 1;
230 	return p;
231 }
232 
233 int
apc_pointer_get_shape(Handle self)234 apc_pointer_get_shape( Handle self)
235 {
236 	objCheck 0;
237 	return sys pointerId;
238 }
239 
240 Point
apc_pointer_get_size(Handle self)241 apc_pointer_get_size( Handle self)
242 {
243 	return guts. pointerSize;
244 }
245 
246 Bool
apc_pointer_get_bitmap(Handle self,Handle icon)247 apc_pointer_get_bitmap( Handle self, Handle icon)
248 {
249 	ICONINFO  ii;
250 	PIcon     i = ( PIcon) icon;
251 	HDC dc;
252 	XBITMAPINFO bi = {{
253 		sizeof( BITMAPINFOHEADER), 0, 0, 1, 1
254 	}};
255 	BITMAP bitmap;
256 
257 	bi. bmiHeader. biWidth = guts. pointerSize. x;
258 	bi. bmiHeader. biHeight = guts. pointerSize. y;
259 
260 	if ( icon == NULL_HANDLE)
261 		apcErrRet( errInvParams);
262 	objCheck false;
263 	dobjCheck( icon) false;
264 	if ( !GetIconInfo( sys pointer, &ii))
265 		apiErrRet;
266 	if ( ii.hbmColor && GetObject( ii.hbmColor, sizeof( BITMAP), ( LPSTR) &bitmap))
267 		i-> self-> create_empty( icon, bitmap.bmWidth, bitmap.bmHeight, 1);
268 	else if ( GetObject( ii.hbmMask, sizeof( BITMAP), ( LPSTR) &bitmap))
269 		i-> self-> create_empty( icon, bitmap.bmWidth, bitmap.bmHeight / 2, 1);
270 	else
271 		i-> self-> create_empty( icon, guts. pointerSize. x, guts. pointerSize. y, 1);
272 	if (!( dc = dc_alloc())) return false;
273 	if ( ii. hbmColor) {
274 		HDC ops = dsys( icon) ps;
275 		HBITMAP obm = dsys( icon) bm;
276 		dsys( icon) ps = dc;
277 		dsys( icon) bm = ii. hbmColor;
278 		image_query_bits( icon, false);
279 		if ( !GetDIBits( dc, ii. hbmMask, 0, i-> h, i-> mask, ( BITMAPINFO*) &bi, DIB_RGB_COLORS)) apiErr;
280 		dsys( icon) ps = ops;
281 		dsys( icon) bm = obm;
282 	} else {
283 		bi. bmiHeader. biHeight *= 2;
284 		if ( !GetDIBits( dc, ii. hbmMask, 0, i-> h, i-> data, ( BITMAPINFO*) &bi, DIB_RGB_COLORS)) apiErr;
285 		if ( !GetDIBits( dc, ii. hbmMask, i-> h, i-> h, i-> mask, ( BITMAPINFO*) &bi, DIB_RGB_COLORS)) apiErr;
286 	}
287 	dc_free();
288 	DeleteObject( ii. hbmMask);
289 	DeleteObject( ii. hbmColor);
290 	return true;
291 }
292 
293 Bool
apc_pointer_get_visible(Handle self)294 apc_pointer_get_visible( Handle self)
295 {
296 	objCheck false;
297 	return !guts. pointerInvisible;
298 }
299 
300 Bool
apc_pointer_set_pos(Handle self,int x,int y)301 apc_pointer_set_pos( Handle self, int x, int y)
302 {
303 	RECT r;
304 	if ( !hwnd_check_limits( x, y, true)) apcErrRet( errInvParams);
305 	GetWindowRect( HWND_DESKTOP, &r);
306 	if ( !SetCursorPos( x, r. bottom - y - 1)) apiErrRet;
307 	return true;
308 }
309 
310 Handle ctx_cr2IDC[] =
311 {
312 	crArrow,        ( Handle) IDC_ARROW,
313 	crText,         ( Handle) IDC_IBEAM,
314 	crWait,         ( Handle) IDC_WAIT,
315 	crSize,         ( Handle) IDC_SIZEALL,
316 	crMove,         ( Handle) IDC_SIZEALL,
317 	crSizeWest,     ( Handle) IDC_SIZEWE,
318 	crSizeEast,     ( Handle) IDC_SIZEWE,
319 	crSizeWE,       ( Handle) IDC_SIZEWE,
320 	crSizeNorth,    ( Handle) IDC_SIZENS,
321 	crSizeSouth,    ( Handle) IDC_SIZENS,
322 	crSizeNS,       ( Handle) IDC_SIZENS,
323 	crSizeNW,       ( Handle) IDC_SIZENWSE,
324 	crSizeSE,       ( Handle) IDC_SIZENWSE,
325 	crSizeNE,       ( Handle) IDC_SIZENESW,
326 	crSizeSW,       ( Handle) IDC_SIZENESW,
327 	crInvalid,      ( Handle) IDC_NO,
328         crDragNone,     ( Handle) IDC_NO,
329         crDragCopy,     ( Handle) IDC_HAND,
330         crDragMove,     ( Handle) IDC_HAND,
331         crDragLink,     ( Handle) IDC_HAND,
332 	crCrosshair,    ( Handle) IDC_CROSS,
333 	crUpArrow,      ( Handle) IDC_UPARROW,
334 	crQuestionArrow,( Handle) IDC_HELP,
335 	crHand,         ( Handle) IDC_HAND,
336 	endCtx
337 };
338 
339 static Bool
direct_pointer_change(Handle self)340 direct_pointer_change( Handle self)
341 {
342 	Point p;
343 	if ( var stage != csNormal) return false;
344 	if ( guts.dragSource != NULL ) return true;
345 	if ( !IsWindowVisible( HANDLE)) return false;
346 	p = apc_pointer_get_pos( application);
347 	return self == apc_application_get_widget_from_point( application, p);
348 }
349 
350 Bool
apc_pointer_set_shape(Handle self,int sysPtrId)351 apc_pointer_set_shape( Handle self, int sysPtrId)
352 {
353 	HCURSOR user;
354 
355 	objCheck false;
356 	user = sys pointer2;
357 	if ( sysPtrId < crDefault || sysPtrId > crUser) return false;
358 	sys pointerId = sysPtrId;
359 	if ( sysPtrId == crDefault)
360 	{
361 		Handle owner = var owner;
362 		while( owner)
363 		{
364 			sysPtrId = dsys( owner) pointerId;
365 			if ( sysPtrId != crDefault) break;
366 			owner = (( PComponent) owner)-> owner;
367 		}
368 		if ( sysPtrId == crDefault) sysPtrId = crArrow;
369 		if ( sysPtrId == crUser) user = dsys( owner) pointer2;
370 	}
371 	sys pointer = ( sysPtrId == crUser) ? user :
372 		LoadCursor( NULL, MAKEINTRESOURCE(
373 		ctx_remap_def( sysPtrId, ctx_cr2IDC, true, ( Handle)IDC_ARROW)));
374 
375 	if ( sysPtrId >= crDragCopy && sysPtrId <= crDragLink) {
376 		HCURSOR cursor = create_drag_cursor(sysPtrId);
377 		if ( cursor != NULL ) sys pointer = cursor;
378 	}
379 
380 	if ( direct_pointer_change( self)) {
381 		SetCursor( sys pointer);
382 	}
383 	return true;
384 }
385 
386 Bool
apc_pointer_set_user(Handle self,Handle icon,Point hotSpot)387 apc_pointer_set_user( Handle self, Handle icon, Point hotSpot)
388 {
389 	Bool direct;
390 	HCURSOR cursor;
391 	objCheck false;
392 
393 	apcErrClear;
394 	direct = direct_pointer_change( self);
395 	if (icon) {
396 		Point sz = { PImage(icon)->w, PImage(icon)-> h };
397 		hotSpot. y = sz.y - hotSpot. y - 1;
398 		cursor = image_make_icon_handle( icon, sz, &hotSpot);
399 		if ( apcError) return false;
400 	} else
401 		cursor = NULL;
402 
403 	if ( sys pointer2) {
404 		if ( direct) SetCursor( NULL);
405 		if ( !DestroyCursor( sys pointer2)) apiErr;
406 	}
407 	sys pointer2 = cursor;
408 
409 	if ( sys pointerId == crUser)
410 	{
411 		sys pointer = sys pointer2;
412 		if ( direct) SetCursor( sys pointer);
413 	}
414 	return true;
415 }
416 
417 Bool
apc_pointer_set_visible(Handle self,Bool visible)418 apc_pointer_set_visible( Handle self, Bool visible)
419 {
420 	if ( var stage == csNormal) {
421 		guts. pointerInvisible = !visible;
422 		ShowCursor( visible);
423 		guts. pointerLock += visible ? 1 : -1;
424 	}
425 	return true;
426 }
427 
428 int
apc_pointer_get_state(Handle self)429 apc_pointer_get_state( Handle self)
430 {
431 	return
432 		(( GetKeyState( VK_LBUTTON)  < 0) ? mbLeft     : 0) |
433 		(( GetKeyState( VK_RBUTTON)  < 0) ? mbRight    : 0) |
434 		(( GetKeyState( VK_MBUTTON)  < 0) ? mbMiddle   : 0) |
435 		(( GetKeyState( VK_XBUTTON1) < 0) ? mb4        : 0) |
436 		(( GetKeyState( VK_XBUTTON2) < 0) ? mb5        : 0);
437 }
438 
439 #ifdef __cplusplus
440 }
441 #endif
442