1/*
2	Copyright 1999, Be Incorporated.   All Rights Reserved.
3	This file may be used under the terms of the Be Sample Code License.
4
5	Other authors:
6	Mark Watson,
7	Rudolf Cornelissen 4/2003-9/2005
8*/
9
10#define MODULE_BIT 0x20000000
11
12#include "acc_std.h"
13
14status_t SET_CURSOR_SHAPE(uint16 width, uint16 height, uint16 hot_x, uint16 hot_y, uint8 *andMask, uint8 *xorMask)
15{
16	LOG(4,("SET_CURSOR_SHAPE: width %d, height %d, hot_x %d, hot_y %d\n",
17		width, height, hot_x, hot_y));
18
19	if ((width != 16) || (height != 16))
20	{
21		return B_ERROR;
22	}
23	else if ((hot_x >= width) || (hot_y >= height))
24	{
25		return B_ERROR;
26	}
27	else
28	{
29		head1_cursor_define(andMask,xorMask);
30		if ((si->dm.flags & DUALHEAD_BITS) != DUALHEAD_OFF)
31			head2_cursor_define(andMask,xorMask);
32
33		/* Update cursor variables appropriately. */
34		si->cursor.width = width;
35		si->cursor.height = height;
36		si->cursor.hot_x = hot_x;
37		si->cursor.hot_y = hot_y;
38	}
39
40	return B_OK;
41}
42
43/* Move the cursor to the specified position on the desktop, taking account of virtual/dual issues */
44void MOVE_CURSOR(uint16 x, uint16 y)
45{
46	uint16 hds = si->dm.h_display_start;	/* the current horizontal starting pixel */
47	uint16 vds = si->dm.v_display_start;	/* the current vertical starting line */
48	uint16 h_adjust;
49
50	/* clamp cursor to display */
51	if (x >= si->dm.virtual_width) x = si->dm.virtual_width - 1;
52	if (y >= si->dm.virtual_height) y = si->dm.virtual_height - 1;
53
54	/* store, for our info */
55	si->cursor.x = x;
56	si->cursor.y = y;
57
58	/* set up minimum amount to scroll */
59	if (si->dm.flags & DUALHEAD_BITS)
60	{
61		//fixme for VIA...
62		switch(si->dm.space)
63		{
64		case B_RGB16_LITTLE:
65			h_adjust = 0x1f;
66			break;
67		case B_RGB32_LITTLE:
68			h_adjust = 0x0f;
69			break;
70		default:
71			h_adjust = 0x1f;
72			break;
73		}
74	}
75	else
76	{
77		switch(si->dm.space)
78		{
79		case B_CMAP8:
80			h_adjust = 0x07;
81			break;
82		case B_RGB15_LITTLE:case B_RGB16_LITTLE:
83			h_adjust = 0x03;
84			break;
85		case B_RGB32_LITTLE:
86			h_adjust = 0x01;
87			break;
88		default:
89			h_adjust = 0x07;
90			break;
91		}
92	}
93
94	/* adjust h/v_display_start to move cursor onto screen */
95	switch (si->dm.flags & DUALHEAD_BITS)
96	{
97	case DUALHEAD_ON:
98	case DUALHEAD_SWITCH:
99		if (x >= ((si->dm.timing.h_display * 2) + hds))
100		{
101			hds = ((x - (si->dm.timing.h_display * 2)) + 1 + h_adjust) & ~h_adjust;
102			/* make sure we stay within the display! */
103			if ((hds + (si->dm.timing.h_display * 2)) > si->dm.virtual_width)
104				hds -= (h_adjust + 1);
105		}
106		else if (x < hds)
107			hds = x & ~h_adjust;
108		break;
109	default:
110		if (x >= (si->dm.timing.h_display + hds))
111		{
112			hds = ((x - si->dm.timing.h_display) + 1 + h_adjust) & ~h_adjust;
113			/* make sure we stay within the display! */
114			if ((hds + si->dm.timing.h_display) > si->dm.virtual_width)
115				hds -= (h_adjust + 1);
116		}
117		else if (x < hds)
118			hds = x & ~h_adjust;
119		break;
120	}
121
122	if (y >= (si->dm.timing.v_display + vds))
123		vds = y - si->dm.timing.v_display + 1;
124	else if (y < vds)
125		vds = y;
126
127	/* reposition the desktop _and_ the overlay on the display if required */
128	if ((hds!=si->dm.h_display_start) || (vds!=si->dm.v_display_start))
129	{
130		MOVE_DISPLAY(hds,vds);
131		eng_bes_move_overlay();
132	}
133
134	/* put cursor in correct physical position, so stay onscreen (rel. to CRTC) */
135	if (x > (hds + si->cursor.hot_x)) x -= (hds + si->cursor.hot_x);
136	else x = 0;
137	if (y > (vds + si->cursor.hot_y)) y -= (vds + si->cursor.hot_y);
138	else y = 0;
139
140	/* position the cursor on the display */
141	switch (si->dm.flags & DUALHEAD_BITS)
142	{
143	case DUALHEAD_CLONE:
144		head1_cursor_position(x,y);
145		head2_cursor_position(x,y);
146		break;
147	case DUALHEAD_ON:
148	case DUALHEAD_SWITCH:
149		if (x < si->dm.timing.h_display)
150		{
151			if (si->cursor.dh_right)
152			{
153				LOG(4,("MOVE_CURSOR: now on left side\n"));
154				head2_cursor_hide();
155				head1_cursor_show();
156				si->cursor.dh_right = false;
157			}
158			head1_cursor_position(x, y);
159		}
160		else
161		{
162			if (!si->cursor.dh_right)
163			{
164				LOG(4,("MOVE_CURSOR: now on right side\n"));
165				head1_cursor_hide();
166				head2_cursor_show();
167				si->cursor.dh_right = true;
168			}
169			head2_cursor_position((x - si->dm.timing.h_display), y);
170		}
171		break;
172	default: /* singlehead mode */
173		head1_cursor_position(x,y);
174		break;
175	}
176}
177
178void SHOW_CURSOR(bool is_visible)
179{
180	/* record for our info */
181	si->cursor.is_visible = is_visible;
182
183	switch (si->dm.flags & DUALHEAD_BITS)
184	{
185	case DUALHEAD_CLONE:
186		if (is_visible)
187		{
188			head1_cursor_show();
189			head2_cursor_show();
190		}
191		else
192		{
193			head1_cursor_hide();
194			head2_cursor_hide();
195		}
196		break;
197	case DUALHEAD_ON:
198	case DUALHEAD_SWITCH:
199		if (is_visible)
200		{
201			if (!si->cursor.dh_right)
202			{
203				head1_cursor_show();
204			}
205			else
206			{
207				head2_cursor_show();
208			}
209		}
210		else
211		{
212			head1_cursor_hide();
213			head2_cursor_hide();
214		}
215		break;
216	default: /* singlehead mode */
217		if (is_visible)
218		{
219			head1_cursor_show();
220		}
221		else
222		{
223			head1_cursor_hide();
224		}
225		break;
226	}
227}
228