1 /*
2  * Seven Kingdoms: Ancient Adversaries
3  *
4  * Copyright 1997,1998 Enlight Software Ltd.
5  * Copyright 2010,2015 Jesse Allen
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 //Filename    : OMOUSE.CPP
23 //Description : Input event class
24 
25 #include <OMOUSE.h>
26 #include <OMOUSECR.h>
27 #include <OMOUSE2.h>
28 #include <OPOWER.h>
29 #include <KEY.h>
30 #include <OSYS.h>
31 #include <ctype.h>
32 #include <dbglog.h>
33 #include <LocaleRes.h>
34 
35 DBGLOG_DEFAULT_CHANNEL(Mouse);
36 
37 #define VGA_UPDATE_BUF_SIZE	(100*100)
38 static int update_x1, update_y1, update_x2, update_y2;          // coordination of the last double-buffer update area
39 
40 static unsigned any_key_code_map[KEYEVENT_MAX];
41 static unsigned shift_key_code_map[KEYEVENT_MAX];
42 
43 static void reset_key(KeyEventType key_event);
44 
45 //--------- Define Click Threshold -----------//
46 //
47 // Clock tick is incremented 1000 times per second or once per millisecond.
48 //
49 // The minimum time interval between consequent mouse click is set to
50 // = 0.3 seconds
51 //
52 //--------------------------------------------//
53 
54 static unsigned long click_threshold = (long)(0.3 * 1000);
55 
56 
57 //--------- Start of Mouse::Mouse ---------//
58 //
Mouse()59 Mouse::Mouse()
60 {
61 	init_flag = 0;
62 	handle_flicking = 0;
63 	vga_update_buf = NULL;
64 	left_press = right_press = 0;
65 	skey_state = 0;
66 	event_skey_state = 0;
67 	has_mouse_event = 0;
68 	mouse_event_type = (MouseEventType)0;
69 	memset(click_buffer, 0, sizeof(MouseClick) * 2);
70 	scan_code = 0;
71 	key_code = 0;
72 	unique_key_code = 0;
73 	typing_char = 0;
74 	memset(event_buffer, 0, sizeof(MouseEvent) * EVENT_BUFFER_SIZE);
75 	head_ptr = 0;
76 	tail_ptr = 0;
77 	double_speed_threshold = DEFAULT_DOUBLE_SPEED_THRESHOLD;
78 	triple_speed_threshold = DEFAULT_TRIPLE_SPEED_THRESHOLD;
79 	init_key();
80 }
81 //---------- End of Mouse::Mouse ---------//
82 
83 
84 //---------- Begin of Mouse::~Mouse --------//
85 //
86 // Deinitialize the mouse driver, reset event handler
87 //
~Mouse()88 Mouse::~Mouse()
89 {
90 	deinit();
91 }
92 //------------ End of Mouse::~Mouse --------//
93 
94 
95 //------------ Start of Mouse::init ------------//
96 //
init()97 void Mouse::init()
98 {
99 	if( !SDL_WasInit(SDL_INIT_VIDEO) )
100 		return;
101 
102 	update_skey_state();
103 	SDL_StopTextInput();
104 
105 	//------- initialize VGA update buffer -------//
106 
107 	vga_update_buf = mem_add( VGA_UPDATE_BUF_SIZE );
108 
109 	// ------ initialize mouse boundary ---------//
110 	reset_boundary();
111 
112 	// ------- initialize event queue ---------//
113 	head_ptr = tail_ptr = 0;
114 
115 	SDL_ShowCursor(SDL_DISABLE);
116 	cur_x = VGA_WIDTH/2;
117 	cur_y = VGA_HEIGHT/2;
118 
119 	init_flag = 1;
120 }
121 //------------- End of Mouse::init -------------//
122 
123 
124 //------------ Start of Mouse::init_key ------------//
125 //
init_key()126 void Mouse::init_key()
127 {
128 	bind_key(KEYEVENT_FIRM_BUILD, "B");
129 	bind_key(KEYEVENT_FIRM_PATROL, "R");
130 
131 	bind_key(KEYEVENT_TOWN_RECRUIT, "R");
132 	bind_key(KEYEVENT_TOWN_TRAIN, "B");
133 
134 	bind_key(KEYEVENT_UNIT_BUILD, "B");
135 	bind_key(KEYEVENT_UNIT_RETURN, "R");
136 	bind_key(KEYEVENT_UNIT_SETTLE, "T");
137 	bind_key(KEYEVENT_UNIT_UNLOAD, "R");
138 
139 #ifdef BUILD_HOTKEYS
140 	bind_key(KEYEVENT_BUILD_BASE, "P");
141 	bind_key(KEYEVENT_BUILD_CAMP, "F");
142 	bind_key(KEYEVENT_BUILD_FACTORY, "A");
143 	bind_key(KEYEVENT_BUILD_HARBOR, "H");
144 	bind_key(KEYEVENT_BUILD_INN, "I");
145 	bind_key(KEYEVENT_BUILD_MARKET, "M");
146 	bind_key(KEYEVENT_BUILD_MINE, "R");
147 	bind_key(KEYEVENT_BUILD_RESEARCH, "T");
148 	bind_key(KEYEVENT_BUILD_WAR_FACTORY, "W");
149 
150 	bind_key(KEYEVENT_MAP_MODE_CYCLE, "E");
151 #else
152 	bind_key(KEYEVENT_MAP_MODE0, "Q");
153 	bind_key(KEYEVENT_MAP_MODE1, "W");
154 	bind_key(KEYEVENT_MAP_MODE2, "E");
155 #endif
156 	bind_key(KEYEVENT_REPORT_OPAQUE_TOGGLE, "P");
157 	bind_key(KEYEVENT_CLEAR_NEWS, "X");
158 	bind_key(KEYEVENT_OPEN_DIPLOMATIC_MSG, "D");
159 	bind_key(KEYEVENT_OPEN_OPTION_MENU, "O");
160 
161 	bind_key(KEYEVENT_TUTOR_PREV, ",");
162 	bind_key(KEYEVENT_TUTOR_NEXT, ".");
163 
164 	bind_key(KEYEVENT_SAVE_GAME, "S");
165 	bind_key(KEYEVENT_LOAD_GAME, "L");
166 
167 	bind_key(KEYEVENT_OBJECT_PREV, "Up");
168 	bind_key(KEYEVENT_OBJECT_NEXT, "Down");
169 	bind_key(KEYEVENT_NATION_OBJECT_PREV, "Left");
170 	bind_key(KEYEVENT_NATION_OBJECT_NEXT, "Right");
171 
172 	bind_key(KEYEVENT_GOTO_RAW, "J");
173 	bind_key(KEYEVENT_GOTO_KING, "K");
174 	bind_key(KEYEVENT_GOTO_GENERAL, "G");
175 	bind_key(KEYEVENT_GOTO_SPY, "Y");
176 	bind_key(KEYEVENT_GOTO_SHIP, "H");
177 	bind_key(KEYEVENT_GOTO_CAMP, "F");
178 
179 	bind_key(KEYEVENT_CHEAT_ENABLE1, "shift+1");
180 	bind_key(KEYEVENT_CHEAT_ENABLE2, "shift+2");
181 	bind_key(KEYEVENT_CHEAT_ENABLE3, "shift+3");
182 
183 	bind_key(KEYEVENT_MANUF_QUEUE_UP, "Up");
184 	bind_key(KEYEVENT_MANUF_QUEUE_DOWN, "Down");
185 	bind_key(KEYEVENT_MANUF_QUEUE_ADD, "=");
186 	bind_key(KEYEVENT_MANUF_QUEUE_ADD_BATCH, "shift+=");
187 	bind_key(KEYEVENT_MANUF_QUEUE_REMOVE, "-");
188 	bind_key(KEYEVENT_MANUF_QUEUE_REMOVE_BATCH, "shift+-");
189 }
190 //------------- End of Mouse::init_key -------------//
191 
192 
193 //------------ Start of Mouse::deinit ------------//
194 //
deinit()195 void Mouse::deinit()
196 {
197 	if( vga_update_buf )
198 	{
199 		mem_del(vga_update_buf);
200 		vga_update_buf = NULL;
201 	}
202 
203 	init_flag = 0;
204 }
205 //------------- End of Mouse::deinit -------------//
206 
207 
208 //--------- Start of Mouse::hide -------//
209 //
210 // Suspend the mouse function, use resume() to resume to function
211 //
hide()212 void Mouse::hide()
213 {
214 	mouse_cursor.hide_all_flag=1;
215 
216 	mouse_cursor.process(cur_x, cur_y);
217 }
218 //---------- End of Mouse::hide --------//
219 
220 
221 //--------- Start of Mouse::show -------//
222 //
223 // Resume the mouse function which is previously hidden by hide()
224 //
show()225 void Mouse::show()
226 {
227 	mouse_cursor.hide_all_flag=0;
228 
229 	mouse_cursor.process(cur_x, cur_y);
230 }
231 //---------- End of Mouse::show --------//
232 
233 
234 //--------- Begin of Mouse::hide_area ----------//
235 //
hide_area(int x1,int y1,int x2,int y2)236 void Mouse::hide_area(int x1, int y1, int x2, int y2)
237 {
238 	mouse_cursor.hide_area_flag++;
239 
240 	if( mouse_cursor.hide_area_flag!=1 )		// only process for the first call of hide_area()
241 		return;
242 
243 	mouse_cursor.hide_x1 = x1;
244 	mouse_cursor.hide_y1 = y1;
245 	mouse_cursor.hide_x2 = x2;
246 	mouse_cursor.hide_y2 = y2;
247 
248 	int curX = cur_x - mouse_cursor.hot_spot_x;
249 	int curY = cur_y - mouse_cursor.hot_spot_y;
250 
251 	if( misc.is_touch( x1, y1, x2, y2, curX, curY,
252 						 curX+mouse_cursor.icon_width-1,
253 						 curY+mouse_cursor.icon_height-1 ) )
254 	{
255 		if( handle_flicking )
256 		{
257 			update_x1 = MIN(x1, curX);
258 			update_y1 = MIN(y1, curY);
259 			update_x2 = MAX(x2, curX+mouse_cursor.icon_width-1);
260 			update_y2 = MAX(y2, curY+mouse_cursor.icon_height-1);
261 
262 			update_x1 = MAX(0, update_x1);
263 			update_y1 = MAX(0, update_y1);
264 			update_x2 = MIN(VGA_WIDTH-1 , update_x2);
265 			update_y2 = MIN(VGA_HEIGHT-1, update_y2);
266 
267 			err_when( (update_x2-update_x1+1) * (update_y2-update_y1+1) > VGA_UPDATE_BUF_SIZE );
268 
269 			//---- save the update area of the back buf to a temp buffer ----//
270 
271 			vga_back.read_bitmap( update_x1, update_y1, update_x2, update_y2, vga_update_buf );
272 
273 			//--- copy the update area from the front buf to the back buf ---//
274 
275 			IMGcopy( vga_back.buf_ptr(), vga_back.buf_pitch(), vga_front.buf_ptr(), vga_front.buf_pitch(),
276 				update_x1, update_y1, update_x2, update_y2 );
277 
278 			//-- redirect the front VGA buffer pointer to the back VGA buffer --//
279 
280 			vga_front.set_buf_ptr( vga_back.buf_ptr() );
281 		}
282 
283 		//------ hide up the mouse cursor --------//
284 
285 		mouse_cursor.process(cur_x, cur_y);
286 	}
287 }
288 //--------- End of Mouse::hide_area --------------//
289 
290 
291 //--------- Begin of Mouse::show_area ----------//
292 //
show_area()293 void Mouse::show_area()
294 {
295 	mouse_cursor.hide_area_flag--;
296 
297 	if( mouse_cursor.hide_area_flag!=0 )		// only process for the first call of hide_area()
298 		return;
299 
300 	int curX = cur_x - mouse_cursor.hot_spot_x;
301 	int curY = cur_y - mouse_cursor.hot_spot_y;
302 
303 	if( misc.is_touch( mouse_cursor.hide_x1, mouse_cursor.hide_y1,
304 						 mouse_cursor.hide_x2, mouse_cursor.hide_y2,
305 						 curX, curY, curX+mouse_cursor.icon_width-1,
306 						 curY+mouse_cursor.icon_height-1 ) )
307 	{
308 		//----- redisplay the mouse cursor ------//
309 
310 		mouse_cursor.process(cur_x, cur_y);
311 
312 		if( handle_flicking )
313 		{
314 			//--- copy the update area from the back buf to the front buf ---//
315 
316 			IMGcopy( vga_front.buf_ptr(), vga_front.buf_pitch(), vga_back.buf_ptr(), vga_back.buf_pitch(),
317 				update_x1, update_y1, update_x2, update_y2 );
318 
319 			//--- restore the update area of the back buf with the temp buffer ---//
320 
321 			vga_back.fast_put_bitmap( update_x1, update_y1, vga_update_buf );
322 
323 			//--- restore the VGA front buffer's buf ptr ---//
324 
325 			vga_front.set_default_buf_ptr();
326 		}
327 	}
328 }
329 //--------- End of Mouse::show_area --------------//
330 
331 
332 //--------- Start of Mouse::add_event ---------//
333 //
334 // Called by handler interrupt to procss the state
335 //
336 // This assumes a mouse button event, even though it copies any event data
337 // passed in.
add_event(MouseEvent * mouseEvent)338 void Mouse::add_event(MouseEvent *mouseEvent)
339 {
340 	//---- call the game object to see if the mouse cursor icon needs to be changed, or if the nation selection square needs to be activated ----//
341 
342 	power.mouse_handler();
343 
344 	//--------- update the mouse cursor ----------//
345 
346 	mouse_cursor.process(cur_x, cur_y);     // repaint mouse cursor
347 
348 	//-------- save state into the event queue --------//
349 
350 	if((head_ptr == tail_ptr-1) ||            // see if the buffer is full
351 		(head_ptr == EVENT_BUFFER_SIZE-1 && tail_ptr == 0))
352 	{
353 		return;
354 	}
355 
356 	event_buffer[head_ptr] = *mouseEvent;
357 
358 	if(++head_ptr >= EVENT_BUFFER_SIZE)       // increment the head ptr
359 		head_ptr = 0;
360 }
361 //----------- End of Mouse::add_event ----------//
362 
363 
364 //--------- Start of Mouse::add_event ---------//
365 //
366 // Called by handler interrupt to procss the state
367 //
368 // This assumes a mouse button event.
add_event(MouseEventType type)369 void Mouse::add_event(MouseEventType type)
370 {
371 	//---- call the game object to see if the mouse cursor icon needs to be changed, or if the nation selection square needs to be activated ----//
372 
373 	power.mouse_handler();
374 
375 	//--------- update the mouse cursor ----------//
376 
377 	mouse_cursor.process(cur_x, cur_y);     // repaint mouse cursor
378 
379 	//-------- save state into the event queue --------//
380 
381 	if((head_ptr == tail_ptr-1) ||            // see if the buffer is full
382 		(head_ptr == EVENT_BUFFER_SIZE-1 && tail_ptr == 0))
383 	{
384 		return;
385 	}
386 
387 	MouseEvent *ev = event_buffer + head_ptr;
388 
389 	ev->event_type = type;
390 	ev->scan_code = 0;
391 	ev->skey_state = skey_state;
392 	ev->time = misc.get_time();
393 
394 	ev->x = cur_x;
395 	ev->y = cur_y;
396 
397 	switch(type)
398 	{
399 	case LEFT_BUTTON:
400 		left_press = LEFT_BUTTON_MASK;
401 		break;
402 	case LEFT_BUTTON_RELEASE:
403 		left_press = 0;
404 		break;
405 	case RIGHT_BUTTON:
406 		right_press = RIGHT_BUTTON_MASK;
407 		break;
408 	case RIGHT_BUTTON_RELEASE:
409 		right_press = 0;
410 		break;
411 	}
412 
413 	if(++head_ptr >= EVENT_BUFFER_SIZE)       // increment the head ptr
414 		head_ptr = 0;
415 }
416 //----------- End of Mouse::add_event ----------//
417 
418 
419 //--------- Start of Mouse::add_key_event ---------//
420 //
421 // Called by key handler to save the key pressed
422 //
423 // This assumes a keyboard button down event.
add_key_event(unsigned scanCode,unsigned long timeStamp)424 void Mouse::add_key_event(unsigned scanCode, unsigned long timeStamp)
425 {
426 	if((head_ptr == tail_ptr-1) ||               // see if the buffer is full
427 		(head_ptr == EVENT_BUFFER_SIZE-1 && tail_ptr == 0))
428 	{
429 		return;
430 	}
431 
432 	MouseEvent *ev = event_buffer + head_ptr;
433 
434 	ev->event_type = KEY_PRESS;
435 	ev->scan_code = scanCode;
436 	ev->skey_state = skey_state;
437 	ev->time = timeStamp;
438 
439 	// put mouse state
440 	// ev->state = 0;			//ev->state = left_press | right_press;
441 	ev->x = cur_x;
442 	ev->y = cur_y;
443 
444 	if(++head_ptr >= EVENT_BUFFER_SIZE)  // increment the head ptr
445 		head_ptr = 0;
446 }
447 //----------- End of Mouse::add_key_event ----------//
448 
449 
450 //--------- Start of Mouse::get_event ---------//
451 //
452 // Get next event from the event buffer
453 //
454 // return : <int> 1 - event fetched from the event queue
455 //                0 - not event remained in the buffer
456 //
457 // to know what type of event :
458 // 1. check is_mouse_event() or is_key_event()
459 // 2. if is_mouse_event(), check mouse_event_type
460 //			if( LEFT_BUTTON or LEFT_BUTTON_RELEASE, read click_buffer[LEFT_BUTTON]
461 //			if( RIGHT_BUTTON or RIGHT_BUTTON_RELEASE, read click_buffer[RIGHT_BUTTON]
462 // 3. if is_key_event(), check event_skey_state, scan_code and key_code
463 //
get_event()464 int Mouse::get_event()
465 {
466 	if(head_ptr == tail_ptr)     // no event queue left in the buffer
467 	{
468 		scan_code      =0;        // no keyboard event
469 		key_code       =0;
470 		unique_key_code=0;
471 		typing_char    =0;
472 		has_mouse_event=0;        // no mouse event
473 		return 0;
474 	}
475 
476 	//--------- get event from queue ---------//
477 
478 	MouseEvent* eptr = event_buffer + tail_ptr;
479 	MouseClick* cptr;
480 
481 	event_skey_state = eptr->skey_state;
482 	mouse_event_type = eptr->event_type;
483 
484 	switch( eptr->event_type )
485 	{
486 	case LEFT_BUTTON:
487 	case RIGHT_BUTTON:
488 		// set count of other button to zero
489 		click_buffer[LEFT_BUTTON+RIGHT_BUTTON-eptr->event_type].count = 0;
490 		cptr = click_buffer + eptr->event_type;
491 		if( //eptr->event_type == LEFT_BUTTON	&&		// left button has double click
492 			 eptr->time - cptr->time < click_threshold )
493 			cptr->count++;
494 		else
495 			cptr->count = 1;
496 
497 		cptr->time = eptr->time;
498 		cptr->x    = eptr->x;
499       cptr->y    = eptr->y;
500 		scan_code       = 0;
501 		key_code        = 0;
502 		unique_key_code = 0;
503 		typing_char     = 0;
504       has_mouse_event = 1;
505 		break;
506 
507 	case KEY_PRESS:
508 		scan_code = eptr->scan_code;
509 		key_code = mouse.is_key(scan_code, event_skey_state, (unsigned short)0, K_CHAR_KEY);
510 		unique_key_code = mouse.is_key(scan_code, 0, (unsigned short)0, K_UNIQUE_KEY);
511 		typing_char     = 0;
512 		has_mouse_event = 0;
513 		break;
514 
515 	case LEFT_BUTTON_RELEASE:
516 	case RIGHT_BUTTON_RELEASE:
517 		cptr = click_buffer + eptr->event_type - LEFT_BUTTON_RELEASE;
518 		cptr->release_time = eptr->time;
519 		cptr->release_x    = eptr->x;
520 		cptr->release_y    = eptr->y;
521 		scan_code          = 0;
522 		key_code           = 0;
523 		unique_key_code    = 0;
524 		typing_char        = 0;
525 		has_mouse_event    = 1;
526 		break;
527 
528 	case KEY_RELEASE:
529 		// no action
530 		break;
531 
532 	case KEY_TYPING:
533 		scan_code       = 0;
534 		key_code        = 0;
535 		unique_key_code = 0;
536 		typing_char     = eptr->typing;
537 		has_mouse_event = 0;
538 		break;
539 
540 	default:
541 		err_here();
542    }
543 
544    if(++tail_ptr >= EVENT_BUFFER_SIZE)
545       tail_ptr = 0;
546 
547    return 1;
548 }
549 //----------- End of Mouse::get_event ----------//
550 
551 
552 //--------- Begin of Mouse::in_area ----------//
553 //
554 // <Real-time access>
555 //
556 // Detect whether mouse cursor is in the specified area
557 //
558 // <int> x1,y1,x2,y2 = the coordinations of the area
559 //
560 // Return : 1 - if the mouse cursor is in the area
561 //          0 - if not
562 //
in_area(int x1,int y1,int x2,int y2)563 int Mouse::in_area(int x1, int y1, int x2, int y2)
564 {
565 	return( cur_x >= x1 && cur_y >= y1 && cur_x <= x2 && cur_y <= y2 );
566 }
567 //--------- End of Mouse::in_area --------------//
568 
569 
570 //--------- Begin of Mouse::press_area ----------//
571 //
572 // <Real-time access>
573 //
574 // Detect whether the specified area has been pressed by mouse
575 //
576 // <int> x1,y1,x2,y2 = the coordinations of the area
577 // <int> buttonId    = which button ( 0=left, 1-right, 2-left or right )
578 //
579 // Return : 1 - if the area has been pressed (left button)
580 //			   1 - if the area has been pressed (right button)
581 //          0 - if not
582 //
press_area(int x1,int y1,int x2,int y2,int buttonId)583 int Mouse::press_area(int x1, int y1, int x2, int y2, int buttonId)
584 {
585 	if( cur_x >= x1 && cur_y >= y1 && cur_x <= x2 && cur_y <= y2 )
586 	{
587 		if( left_press && (buttonId==0 || buttonId==2) )    // Left button
588 			return 1;
589 
590 		if( right_press && (buttonId==1 || buttonId==2) )   // Right button
591 			return 2;
592 	}
593 
594 	return 0;
595 }
596 //--------- End of Mouse::press_area --------------//
597 
598 
599 //--------- Begin of Mouse::set_boundary ----------//
600 //
601 // for each parameter, put -1 to mean unchange
602 //
set_boundary(int x1,int y1,int x2,int y2)603 void Mouse::set_boundary(int x1, int y1, int x2, int y2)
604 {
605 	if( x1 >= 0)
606 		bound_x1 = x1;
607 	if( y1 >= 0)
608 		bound_y1 = y1;
609 	if( x2 >= 0)
610 		bound_x2 = x2 > MOUSE_X_UPPER_LIMIT ? MOUSE_X_UPPER_LIMIT : x2;
611 	if( y2 >= 0)
612 		bound_y2 = y2 > MOUSE_Y_UPPER_LIMIT ? MOUSE_Y_UPPER_LIMIT : y2;
613 	vga.update_boundary();
614 }
615 //--------- End of Mouse::set_boundary ----------//
616 
617 
618 //--------- Begin of Mouse::reset_boundary ----------//
reset_boundary()619 void Mouse::reset_boundary()
620 {
621 	bound_x1 = 0;
622 	bound_y1 = 0;
623 	bound_x2 = MOUSE_X_UPPER_LIMIT;
624 	bound_y2 = MOUSE_Y_UPPER_LIMIT;
625 	vga.update_boundary();
626 }
627 //--------- End of Mouse::set_boundary ----------//
628 
629 
630 //--------- Begin of Mouse::single_click ----------//
631 //
632 // <Event queue access>
633 //
634 // Detect whether the specified area has been single clicked by mouse
635 //
636 // <int> x1,y1,x2,y2 = the coordinations of the area
637 // [int] buttonId    = which button ( 0=left, 1-right, 2-both)
638 //                     (default:0)
639 //
640 // Return : 1 - if the area has been clicked (left click)
641 //				2 - if the area has been clicked (right click)
642 //          0 - if not
643 //
single_click(int x1,int y1,int x2,int y2,int buttonId)644 int Mouse::single_click(int x1, int y1, int x2, int y2,int buttonId)
645 {
646 	if( !has_mouse_event )
647 		return 0;
648 
649 	MouseClick* cptr;
650 
651 	if( buttonId==0 || buttonId==2 )     // left button
652 	{
653 		cptr = click_buffer+LEFT_BUTTON;
654 
655 		if( mouse_event_type == LEFT_BUTTON
656 			 && cptr->count == 1
657 			 && cptr->x >= x1 && cptr->y >= y1
658 			 && cptr->x <= x2 && cptr->y <= y2 )
659 		{
660 			return 1;
661 		}
662 	}
663 
664 	if( buttonId==1 || buttonId==2 )     // right button
665 	{
666 		cptr = click_buffer+RIGHT_BUTTON;
667 
668 		if( mouse_event_type == RIGHT_BUTTON
669 			 && cptr->count == 1
670 			 && cptr->x >= x1 && cptr->y >= y1
671 			 && cptr->x <= x2 && cptr->y <= y2 )
672 		{
673 			return 2;
674       }
675    }
676 
677    return 0;
678 }
679 //--------- End of Mouse::single_click --------------//
680 
681 
682 //--------- Begin of Mouse::double_click ----------//
683 //
684 // <Event queue access>
685 //
686 // Detect whether the specified area has been double clicked by mouse
687 //
688 // Note : when a mouse double click, it will FIRST generate a SINGLE
689 //        click signal and then a DOUBLE click signal.
690 //        Because a double click is consisted of two single click
691 //
692 // <int> x1,y1,x2,y2 = the coordinations of the area
693 // [int] buttonId    = which button ( 0=left, 1-right, 2-left or right)
694 //                     (default:0)
695 //
696 // Return : 1 - if the area has been clicked (left click)
697 //				2 - if the area has been clicked (right click)
698 //          0 - if not
699 //
double_click(int x1,int y1,int x2,int y2,int buttonId)700 int Mouse::double_click(int x1, int y1, int x2, int y2,int buttonId)
701 {
702 	if( !has_mouse_event )
703       return 0;
704 
705    MouseClick* cptr;
706 
707    if( buttonId==0 || buttonId==2 )     // left button
708    {
709       cptr = click_buffer+LEFT_BUTTON;
710 
711       if( mouse_event_type == LEFT_BUTTON
712 			 && cptr->count == 2
713 			 && cptr->x >= x1 && cptr->y >= y1
714           && cptr->x <= x2 && cptr->y <= y2 )
715       {
716          return 1;
717       }
718    }
719 
720 	if( buttonId==1 || buttonId==2 )     // right button
721    {
722 		cptr = click_buffer+RIGHT_BUTTON;
723 
724       if( mouse_event_type == RIGHT_BUTTON
725 			 && cptr->count == 2
726           && cptr->x >= x1 && cptr->y >= y1
727           && cptr->x <= x2 && cptr->y <= y2 )
728       {
729          return 2;
730       }
731    }
732 
733    return 0;
734 }
735 //--------- End of Mouse::double_click --------------//
736 
737 
738 //--------- Begin of Mouse::any_click ----------//
739 //
740 // <Event queue access>
741 //
742 // Detect whether the specified area has been single or double clicked by mouse
743 //
744 // <int> x1,y1,x2,y2 = the coordinations of the area
745 // [int] buttonId    = which button ( 0=left, 1-right, 2-left or right)
746 //                     (default:0)
747 //
748 // Return : >0 - the no. of click if the area has been clicked
749 //          0  - if not
750 //
any_click(int x1,int y1,int x2,int y2,int buttonId)751 int Mouse::any_click(int x1, int y1, int x2, int y2,int buttonId)
752 {
753    if( !has_mouse_event )
754       return 0;
755 
756 	MouseClick* cptr;
757 
758 	if( buttonId==0 || buttonId==2 )     // left button
759    {
760       cptr = click_buffer+LEFT_BUTTON;
761 
762       if( mouse_event_type == LEFT_BUTTON
763 			 && cptr->count >= 1
764           && cptr->x >= x1 && cptr->y >= y1
765           && cptr->x <= x2 && cptr->y <= y2 )
766       {
767 			return cptr->count;
768       }
769    }
770 
771    if( buttonId==1 || buttonId==2 )     // right button
772    {
773       cptr = click_buffer+RIGHT_BUTTON;
774 
775       if( mouse_event_type == RIGHT_BUTTON
776 			 && cptr->count >= 1
777           && cptr->x >= x1 && cptr->y >= y1
778           && cptr->x <= x2 && cptr->y <= y2 )
779       {
780          return cptr->count;
781       }
782    }
783 
784 	return 0;
785 }
786 //--------- End of Mouse::any_click --------------//
787 
788 
789 //--------- Begin of Mouse::any_click ----------//
790 //
791 // <Event queue access>
792 //
793 // Detect whether the specified area has been single or double clicked by mouse
794 // Only check button, don't check mouse coordination
795 //
796 // [int] buttonId = which button ( 0=left, 1-right, 2-left or right)
797 //                  (default:0)
798 //
799 // Return : >0 - the no. of click if the area has been clicked
800 //          0  - if not
801 //
any_click(int buttonId)802 int Mouse::any_click(int buttonId)
803 {
804 	if( !has_mouse_event )
805       return 0;
806 
807    MouseClick* cptr;
808 
809    if( buttonId==0 || buttonId==2 )     // left button
810    {
811       cptr = click_buffer+LEFT_BUTTON;
812 
813 		if( mouse_event_type == LEFT_BUTTON && cptr->count >= 1 )
814 			return cptr->count;
815    }
816 
817    if( buttonId==1 || buttonId==2 )     // right button
818    {
819       cptr = click_buffer+RIGHT_BUTTON;
820 
821       if( mouse_event_type == RIGHT_BUTTON && cptr->count >= 1 )
822          return cptr->count;
823    }
824 
825 	return 0;
826 }
827 //--------- End of Mouse::any_click --------------//
828 
829 
830 //--------- Begin of Mouse::release_click ----------//
831 //
832 // <Event queue access>
833 //
834 // Detect whether the specified area has been released button by mouse
835 //
836 // <int> x1,y1,x2,y2 = the coordinations of the area
837 // [int] buttonId    = which button ( 0=left, 1-right, 2-both)
838 //                     (default:0)
839 //
840 // Return : 1 - if the area has been clicked (left click)
841 //				2 - if the area has been clicked (right click)
842 //          0 - if not
843 //
release_click(int x1,int y1,int x2,int y2,int buttonId)844 int Mouse::release_click(int x1, int y1, int x2, int y2,int buttonId)
845 {
846 	if( !has_mouse_event )
847 		return 0;
848 
849 	MouseClick* cptr;
850 
851 	if( buttonId==0 || buttonId==2 )     // left button
852 	{
853 		cptr = click_buffer+LEFT_BUTTON;
854 
855 		if( mouse_event_type == LEFT_BUTTON_RELEASE
856 			 && cptr->release_x >= x1 && cptr->release_y >= y1
857 			 && cptr->release_x <= x2 && cptr->release_y <= y2 )
858 		{
859 			return 1;
860 		}
861 	}
862 
863 	if( buttonId==1 || buttonId==2 )     // right button
864 	{
865 		cptr = click_buffer+RIGHT_BUTTON;
866 
867 		if( mouse_event_type == RIGHT_BUTTON_RELEASE
868 			 && cptr->release_x >= x1 && cptr->release_y >= y1
869 			 && cptr->release_x <= x2 && cptr->release_y <= y2 )
870 		{
871 			return 2;
872       }
873    }
874 
875    return 0;
876 }
877 //--------- End of Mouse::release_click --------------//
878 
879 
880 //--------- Begin of Mouse::poll_event ----------//
881 //
882 // Poll mouse events from the direct mouse VXD.
883 //
poll_event()884 void Mouse::poll_event()
885 {
886 }
887 //--------- End of Mouse::poll_event --------------//
888 
889 //--------- Begin of Mouse::get_scroll ---------//
get_scroll(int * x,int * y)890 bool Mouse::get_scroll(int * x, int * y)
891 {
892 	*x = scroll_x;
893 	*y = scroll_y;
894 	scroll_x = 0;
895 	scroll_y = 0;
896 	if (*x != 0 || *y != 0)
897 	{
898 		return true;
899 	}
900 	return false;
901 }
902 //--------- End of Mouse::get_scroll ---------//
903 
904 //--------- Begin of Mouse::process_scroll ---------//
process_scroll(double x,double y)905 void Mouse::process_scroll(double x, double y)
906 {
907 	if (!mouse.scrolling)
908 	{
909 		scroll_prev_y = y;
910 		scroll_prev_x = x;
911 	}
912 	else
913 	{
914 		double dy = y - scroll_prev_y;
915 		scroll_y = dy * scroll_sensitivity;
916 		double dx = x - scroll_prev_x;
917 		scroll_x = dx * scroll_sensitivity;
918 	}
919 	scrolling = true;
920 }
921 //--------- End of Mouse::process_scroll ---------//
922 
923 //--------- Begin of Mouse::process_scroll ---------//
process_scroll(int x,int y)924 void Mouse::process_scroll(int x, int y)
925 {
926 	scroll_y = y;
927 	scroll_x = x;
928 }
929 //--------- End of Mouse::process_scroll ---------//
930 
931 //--------- Begin of Mouse::end_scroll ---------//
end_scroll()932 void Mouse::end_scroll()
933 {
934 	scroll_x = scroll_y = 0;
935 	scroll_prev_x = scroll_prev_y = 0;
936 	scrolling = false;
937 }
938 //--------- End of Mouse::end_scroll ---------//
939 
940 //--------- Begin of Mouse::process_mouse_motion ---------//
process_mouse_motion(int x,int y)941 void Mouse::process_mouse_motion(int x, int y)
942 {
943 	if( vga.mouse_mode == MOUSE_INPUT_ABS )
944 	{
945 		cur_x = x;
946 		cur_y = y;
947 	}
948 	else
949 	{
950 #ifdef MOUSE_ACCEL
951 		cur_x += micky_to_displacement(x);
952 		cur_y += micky_to_displacement(y);
953 #else
954 		cur_x += x;
955 		cur_y += y;
956 #endif
957 	}
958 
959 	if( vga.is_input_grabbed() )
960 	{
961 		if( cur_x < bound_x1 )
962 			cur_x = bound_x1;
963 		else if( cur_x > bound_x2 )
964 			cur_x = bound_x2;
965 		if( cur_y < bound_y1 )
966 			cur_y = bound_y1;
967 		else if( cur_y > bound_y2 )
968 			cur_y = bound_y2;
969 	}
970 
971 	mouse_cursor.process(cur_x, cur_y);     // repaint mouse cursor
972 	power.mouse_handler();
973 }
974 //--------- End of Mouse::process_mouse_motion ---------//
975 
976 // ####### begin Gilbert 31/10 #########//
977 //--------- Begin of Mouse::update_skey_state ----------//
978 // called after task switch to get the lastest state of ctrl/alt/shift key
update_skey_state()979 void Mouse::update_skey_state()
980 {
981 	int modstate = SDL_GetModState();
982 
983 	skey_state = 0;
984 	if (modstate & KMOD_LSHIFT)
985 		skey_state |= LEFT_SHIFT_KEY_MASK;
986 	if (modstate & KMOD_RSHIFT)
987 		skey_state |= RIGHT_SHIFT_KEY_MASK;
988 	if (modstate & KMOD_LCTRL)
989 		skey_state |= LEFT_CONTROL_KEY_MASK;
990 	if (modstate & KMOD_RCTRL)
991 		skey_state |= RIGHT_CONTROL_KEY_MASK;
992 	if (modstate & KMOD_LALT)
993 		skey_state |= LEFT_ALT_KEY_MASK;
994 	if (modstate & KMOD_RALT)
995 #if(defined(FRENCH)||defined(SPANISH))
996 		skey_state |= GRAPH_KEY_MASK;
997 #else
998 		skey_state |= RIGHT_ALT_KEY_MASK;
999 #endif
1000 	if (modstate & KMOD_NUM)
1001 		skey_state |= NUM_LOCK_STATE_MASK;
1002 	if (modstate & KMOD_CAPS)
1003 		skey_state |= CAP_LOCK_STATE_MASK;
1004 	if (modstate & KMOD_MODE) // Alt Gr key
1005 		skey_state |= GRAPH_KEY_MASK;
1006 	skey_state |= INSERT_STATE_MASK; // enable insert mode by default
1007 }
1008 //--------- End of Mouse::update_skey_state ----------//
1009 // ####### end Gilbert 31/10 #########//
1010 
1011 
1012 //--------- Begin of Mouse::wait_press ----------//
1013 //
1014 // Wait until one of the mouse buttons is pressed.
1015 //
1016 // [int] timeOutSecond - no. of seconds to time out. If not
1017 //								 given, there will be no time out.
1018 //
1019 // return: <int> 1-left mouse button
1020 //					  2-right mouse button
1021 //
wait_press(int timeOutSecond)1022 int Mouse::wait_press(int timeOutSecond)
1023 {
1024 	while( mouse.left_press || mouse.any_click() || mouse.key_code )		// avoid repeat clicking
1025 	{
1026 		sys.yield();
1027 		vga.flip();
1028 		mouse.get_event();
1029 	}
1030 
1031 	int rc=0;
1032 	unsigned int timeOutTime = misc.get_time() + timeOutSecond*1000;
1033 
1034 	while(1)
1035 	{
1036 		sys.yield();
1037 		vga.flip();
1038 		mouse.get_event();
1039 
1040 		if( sys.signal_exit_flag == 1 )
1041 		{
1042 			break;
1043 		}
1044 
1045 		if( sys.debug_session )
1046 			sys.blt_virtual_buf();
1047 
1048 		if( right_press || mouse.key_code==KEY_ESC )
1049 		{
1050 			rc = 2;
1051 			break;
1052 		}
1053 
1054 		if( left_press || mouse.key_code )
1055 		{
1056 			rc = 1;
1057 			break;
1058 		}
1059 
1060 		if( timeOutSecond && misc.get_time() > timeOutTime )
1061 			break;
1062 	}
1063 
1064 	while( mouse.left_press || mouse.any_click() || mouse.key_code )		// avoid repeat clicking
1065 	{
1066 		sys.yield();
1067 		vga.flip();
1068 		mouse.get_event();
1069 	}
1070 
1071 	return rc;
1072 }
1073 //--------- End of Mouse::wait_press --------------//
1074 
1075 
1076 //--------- Begin of Mouse::reset_click ----------//
1077 //
1078 // Reset queued mouse clicks.
1079 //
reset_click()1080 void Mouse::reset_click()
1081 {
1082 	click_buffer[0].count=0;
1083 	click_buffer[1].count=0;
1084 }
1085 //--------- End of Mouse::reset_click --------------//
1086 
1087 
1088 // ------ Begin of Mouse::micky_to_displacement -------//
micky_to_displacement(int d)1089 int Mouse::micky_to_displacement(int d)
1090 {
1091 	return abs(d) >= double_speed_threshold ? d+d : d;
1092 }
1093 // ------ End of Mouse::micky_to_displacement -------//
1094 
1095 
1096 // ------ Begin of Mouse::is_key -------//
1097 // compare key with key code
1098 // e.g. to test a key is alt-a,
1099 // call mouse.is_key(mouse.scan_code, mouse.event_skey_state, 'a', K_CHAR_KEY | K_IS_ALT)
1100 //
1101 // pass 0 as charValue to disable checking in charValue
1102 // e.g pressed key is 'a'
1103 // mouse.is_key(mouse.scan_code, mouse.event_skey_state, (unsigned short) 0, K_CHAR_KEY) returns 'a'
1104 // but if key pressed is alt-a
1105 // the same function call returns 0
1106 // use mouse.is_key(mouse.scan_code, mouse.event_skey_state, (unsigned short) 0, K_CHAR_KEY | K_IS_ALT ) instead
1107 //
is_key(unsigned scanCode,unsigned short skeyState,unsigned short charValue,unsigned flags)1108 int Mouse::is_key(unsigned scanCode, unsigned short skeyState, unsigned short charValue, unsigned flags)
1109 {
1110 	unsigned short priChar = 0, shiftChar = 0, capitalChar = 0;
1111 #if(defined(FRENCH)||defined(GERMAN)||defined(SPANISH))
1112 	unsigned short altChar = 0;
1113 #endif
1114 	unsigned onNumPad = 0;
1115 
1116 	switch(scanCode)
1117 	{
1118 	case SDLK_ESCAPE: priChar = shiftChar = capitalChar = KEY_ESC; break;
1119 #if(defined(SPANISH))
1120 	case SDLK_1: priChar = capitalChar = '1'; shiftChar = '!'; altChar = '|'; break;
1121 #else
1122 	case SDLK_1: priChar = capitalChar = '1'; shiftChar = '!'; break;
1123 #endif
1124 #if(defined(FRENCH)||defined(SPANISH))
1125 	case SDLK_2: priChar = capitalChar = '2'; shiftChar = '\"'; altChar = '@'; break;
1126 #elif(defined(GERMAN))
1127 	case SDLK_2: priChar = capitalChar = '2'; shiftChar = '\"'; altChar = (UCHAR)'�'; break;
1128 #else
1129 	case SDLK_2: priChar = capitalChar = '2'; shiftChar = '@'; break;
1130 #endif
1131 #if(defined(FRENCH))
1132 	case SDLK_3: priChar = capitalChar = '3'; shiftChar = '/'; altChar = (UCHAR)'�'; break;
1133 #elif(defined(SPANISH))
1134 	case SDLK_3: priChar = capitalChar = '3'; shiftChar = (UCHAR)'�'; altChar = '#'; break;
1135 #elif(defined(GERMAN))
1136 	case SDLK_3: priChar = capitalChar = '3'; shiftChar = (UCHAR)'�'; altChar = (UCHAR)'�'; break;
1137 #else
1138 	case SDLK_3: priChar = capitalChar = '3'; shiftChar = '#'; break;
1139 #endif
1140 	case SDLK_4: priChar = capitalChar = '4'; shiftChar = '$'; break;
1141 	case SDLK_5: priChar = capitalChar = '5'; shiftChar = '%'; break;
1142 #if(defined(FRENCH))
1143 	case SDLK_6: priChar = capitalChar = '6'; shiftChar = '?'; altChar = (UCHAR)'�';break;
1144 #elif(defined(SPANISH))
1145 	case SDLK_6: priChar = capitalChar = '6'; shiftChar = '&'; break;
1146 #elif(defined(GERMAN))
1147 	case SDLK_6: priChar = capitalChar = '6'; shiftChar = '&'; break;
1148 #else
1149 	case SDLK_6: priChar = capitalChar = '6'; shiftChar = '^'; break;
1150 #endif
1151 #if(defined(GERMAN))
1152 	case SDLK_7: priChar = capitalChar = '7'; shiftChar = '/'; altChar = '{'; break;
1153 	case SDLK_8: priChar = capitalChar = '8'; shiftChar = '('; altChar = '['; break;
1154 	case SDLK_9: priChar = capitalChar = '9'; shiftChar = ')'; altChar = ']'; break;
1155 	case SDLK_0: priChar = capitalChar = '0'; shiftChar = '='; altChar = '}'; break;
1156 	case 0x0c:  priChar = capitalChar = (UCHAR)'�'; shiftChar = '\?'; altChar = '\\'; break;
1157 	case 0x0d:  priChar = capitalChar = (UCHAR)'�'; shiftChar = (UCHAR)'`'; break;
1158 #elif(defined(SPANISH))
1159 	case SDLK_7: priChar = capitalChar = '7'; shiftChar = '/'; break;
1160 	case SDLK_8: priChar = capitalChar = '8'; shiftChar = '('; break;
1161 	case SDLK_9: priChar = capitalChar = '9'; shiftChar = ')'; break;
1162 	case SDLK_0: priChar = capitalChar = '0'; shiftChar = '='; break;
1163 	case 0x0c:  priChar = capitalChar = '\''; shiftChar = '?'; break;
1164 	case 0x0d:  priChar = capitalChar = (UCHAR)'�'; shiftChar = (UCHAR)'�'; break;
1165 #else
1166 	case SDLK_7: priChar = capitalChar = '7'; shiftChar = '&'; break;
1167 	case SDLK_8: priChar = capitalChar = '8'; shiftChar = '*'; break;
1168 	case SDLK_9: priChar = capitalChar = '9'; shiftChar = '('; break;
1169 	case SDLK_0: priChar = capitalChar = '0'; shiftChar = ')'; break;
1170 	case SDLK_MINUS: priChar = capitalChar = '-'; shiftChar = '_'; break;
1171 	case SDLK_EQUALS: priChar = capitalChar = '='; shiftChar = '+'; break;
1172 #endif
1173 	case SDLK_BACKSPACE: priChar = capitalChar = shiftChar = KEY_BACK_SPACE; break;   // backspace
1174 	case SDLK_TAB: priChar = capitalChar = shiftChar = KEY_TAB; break;
1175 #if(defined(GERMAN))
1176 	case SDLK_q: priChar = 'q'; capitalChar = shiftChar = 'Q'; altChar = '@'; break;
1177 #else
1178 	case SDLK_q: priChar = 'q'; capitalChar = shiftChar = 'Q'; break;
1179 #endif
1180 	case SDLK_w: priChar = 'w'; capitalChar = shiftChar = 'W'; break;
1181 	case SDLK_e: priChar = 'e'; capitalChar = shiftChar = 'E'; break;
1182 	case SDLK_r: priChar = 'r'; capitalChar = shiftChar = 'R'; break;
1183 	case SDLK_t: priChar = 't'; capitalChar = shiftChar = 'T'; break;
1184 #if(defined(GERMAN))
1185 	case 0x15:  priChar = 'z'; capitalChar = shiftChar = 'Z'; break;
1186 #else
1187 	case SDLK_y: priChar = 'y'; capitalChar = shiftChar = 'Y'; break;
1188 #endif
1189 	case SDLK_u: priChar = 'u'; capitalChar = shiftChar = 'U'; break;
1190 	case SDLK_i: priChar = 'i'; capitalChar = shiftChar = 'I'; break;
1191 	case SDLK_o: priChar = 'o'; capitalChar = shiftChar = 'O'; break;
1192 	case SDLK_p: priChar = 'p'; capitalChar = shiftChar = 'P'; break;
1193 #if(defined(FRENCH))
1194 	case 0x1a:  priChar = capitalChar = shiftChar = '^'; altChar = '['; break;
1195 	case 0x1b:  priChar = capitalChar = (UCHAR)'�';shiftChar = (UCHAR)'�'; altChar = ']'; break;
1196 #elif(defined(SPANISH))
1197 	case 0x1a:  priChar = capitalChar = '`'; shiftChar = '^'; altChar = '['; break;
1198 	case 0x1b:  priChar = capitalChar = '+';shiftChar = '*'; altChar = ']'; break;
1199 #elif(defined(GERMAN))
1200 	case 0x1a:  priChar = (UCHAR)'�'; capitalChar = shiftChar = (UCHAR)'�'; break;
1201 	case 0x1b:  priChar = capitalChar = shiftChar = '+'; altChar = '~'; break;
1202 #else
1203 	case SDLK_LEFTBRACKET: priChar = capitalChar = '['; shiftChar = '{'; break;
1204 	case SDLK_RIGHTBRACKET: priChar = capitalChar = ']'; shiftChar = '}'; break;
1205 #endif
1206 	case SDLK_KP_ENTER:		// Enter on numeric keypad
1207 		onNumPad = 1;			// fall through
1208 	case SDLK_RETURN: priChar = capitalChar = shiftChar = KEY_RETURN;	break;
1209 	case SDLK_a: priChar = 'a'; capitalChar = shiftChar = 'A'; break;
1210 	case SDLK_s: priChar = 's'; capitalChar = shiftChar = 'S'; break;
1211 	case SDLK_d: priChar = 'd'; capitalChar = shiftChar = 'D'; break;
1212 	case SDLK_f: priChar = 'f'; capitalChar = shiftChar = 'F'; break;
1213 	case SDLK_g: priChar = 'g'; capitalChar = shiftChar = 'G'; break;
1214 	case SDLK_h: priChar = 'h'; capitalChar = shiftChar = 'H'; break;
1215 	case SDLK_j: priChar = 'j'; capitalChar = shiftChar = 'J'; break;
1216 	case SDLK_k: priChar = 'k'; capitalChar = shiftChar = 'K'; break;
1217 	case SDLK_l: priChar = 'l'; capitalChar = shiftChar = 'L'; break;
1218 #if(defined(FRENCH))
1219 	case SDLK_SEMICOLON: priChar = capitalChar = ';'; shiftChar = ':'; altChar = '~'; break;
1220 	case 0x28:  priChar = capitalChar = shiftChar = '`'; altChar = '{'; break;
1221 	case 0x29:  priChar = capitalChar = '#'; shiftChar = '|'; altChar = '\\'; break;
1222 	case 0x2b:  priChar = capitalChar = '<'; shiftChar = '>'; altChar = '}'; break;
1223 #elif(defined(SPANISH))
1224 	case 0x27:  priChar = (UCHAR)'�'; capitalChar = shiftChar = (UCHAR)'�'; break;
1225 	case 0x28:  priChar = capitalChar = (UCHAR)'�'; shiftChar = (UCHAR)'�'; altChar = '{'; break;
1226 	case 0x29:  priChar = capitalChar = (UCHAR)'�'; shiftChar = (UCHAR)'�'; altChar = '\\'; break;
1227 	case 0x2b:  priChar = (UCHAR)'�'; capitalChar = shiftChar = (UCHAR)'�'; altChar = '}'; break;
1228 #elif(defined(GERMAN))
1229 	case 0x27:  priChar = (UCHAR)'�'; capitalChar = shiftChar = (UCHAR)'�'; break;
1230 	case 0x28:  priChar = (UCHAR)'�'; capitalChar = shiftChar = (UCHAR)'�'; break;
1231 	case 0x29:  priChar = capitalChar = '^'; shiftChar = (UCHAR)'�'; break;
1232 	case 0x2b:  priChar = capitalChar = '#'; shiftChar = '\''; break;
1233 #else
1234 	case SDLK_SEMICOLON: priChar = capitalChar = ';'; shiftChar = ':'; break;
1235 	case SDLK_QUOTE: priChar = capitalChar = '\''; shiftChar = '\"'; break;
1236 	case SDLK_BACKQUOTE: priChar = capitalChar = '~'; shiftChar = '`'; break; // Note: this can be reversed on certain keyboards (at the very least on Dutch USA-international keyboards) where ` is the base and ~ the shift
1237 	case SDLK_BACKSLASH: priChar = capitalChar = '\\'; shiftChar = '|'; break;
1238 #endif
1239 #if(defined(GERMAN))
1240 	case 0x2c:  priChar = 'y'; capitalChar = shiftChar = 'Y'; break;
1241 #else
1242 	case SDLK_z: priChar = 'z'; capitalChar = shiftChar = 'Z'; break;
1243 #endif
1244 	case SDLK_x: priChar = 'x'; capitalChar = shiftChar = 'X'; break;
1245 	case SDLK_c: priChar = 'c'; capitalChar = shiftChar = 'C'; break;
1246 	case SDLK_v: priChar = 'v'; capitalChar = shiftChar = 'V'; break;
1247 	case SDLK_b: priChar = 'b'; capitalChar = shiftChar = 'B'; break;
1248 	case SDLK_n: priChar = 'n'; capitalChar = shiftChar = 'N'; break;
1249 #if(defined(GERMAN))
1250 	case SDLK_m: priChar = 'm'; capitalChar = shiftChar = 'M'; altChar = (UCHAR)'�'; break;
1251 #else
1252 	case SDLK_m: priChar = 'm'; capitalChar = shiftChar = 'M'; break;
1253 #endif
1254 #if(defined(FRENCH))
1255 	case SDLK_COMMA: priChar = capitalChar = ','; shiftChar = '\''; altChar = (UCHAR)'�'; break;
1256 	case SDLK_PERIOD: priChar = capitalChar = '.'; shiftChar = '\"'; altChar = (UCHAR)'�'; break;
1257 	case 0x35:  priChar = (UCHAR)'�'; capitalChar = shiftChar = (UCHAR)'�'; altChar = (UCHAR)'�'; break;
1258 #elif(defined(SPANISH))
1259 	case SDLK_COMMA: priChar = capitalChar = ','; shiftChar = ';'; break;
1260 	case SDLK_PERIOD: priChar = capitalChar = '.'; shiftChar = ':'; break;
1261 	case 0x35:  priChar = capitalChar = '-'; shiftChar = '_'; break;
1262 #else
1263 	case SDLK_COMMA: priChar = capitalChar = ','; shiftChar = '<'; break;
1264 	case SDLK_PERIOD: priChar = capitalChar = '.'; shiftChar = '>'; break;
1265 	case SDLK_SLASH: priChar = capitalChar = '/'; shiftChar = '\?'; break;
1266 #endif
1267 	case SDLK_KP_MULTIPLY: priChar = capitalChar = shiftChar = '*'; onNumPad = 1; break; // * on numeric keypad
1268 	case SDLK_SPACE: priChar = capitalChar = shiftChar = ' '; break;
1269 	case SDLK_KP_PLUS: priChar = capitalChar = shiftChar = '+'; onNumPad = 1; break; // + on numeric keypad
1270 	case SDLK_KP_DIVIDE: priChar = capitalChar = shiftChar = '/'; onNumPad = 1; break;		// / on numeric keypad
1271 	case SDLK_KP_MINUS: priChar = capitalChar = shiftChar = '-'; onNumPad = 1; break;	// - on numeric keypad
1272 #if(defined(GERMAN))
1273 	case 0x56:  priChar = capitalChar = '<'; shiftChar = '>'; altChar = '|'; break;
1274 #endif
1275 
1276 	case SDLK_KP_7: priChar = shiftChar = capitalChar = '7'; onNumPad = 1; break;
1277 	case SDLK_KP_8: priChar = shiftChar = capitalChar = '8'; onNumPad = 1; break;
1278 	case SDLK_KP_9: priChar = shiftChar = capitalChar = '9'; onNumPad = 1; break;
1279 	case SDLK_KP_4: priChar = shiftChar = capitalChar = '4'; onNumPad = 1; break;
1280 	case SDLK_KP_5: priChar = shiftChar = capitalChar = '5'; onNumPad = 1; break;
1281 	case SDLK_KP_6: priChar = shiftChar = capitalChar = '6'; onNumPad = 1; break;
1282 	case SDLK_KP_1: priChar = shiftChar = capitalChar = '1'; onNumPad = 1; break;
1283 	case SDLK_KP_2: priChar = shiftChar = capitalChar = '2'; onNumPad = 1; break;
1284 	case SDLK_KP_3: priChar = shiftChar = capitalChar = '3'; onNumPad = 1; break;
1285 	case SDLK_KP_0: priChar = shiftChar = capitalChar = '0'; onNumPad = 1; break;
1286 	case SDLK_KP_PERIOD: priChar = shiftChar = capitalChar = '.'; onNumPad = 1; break;
1287 
1288 	// function keys
1289 	case SDLK_F1: priChar = shiftChar = capitalChar = KEY_F1; break;
1290 	case SDLK_F2: priChar = shiftChar = capitalChar = KEY_F2; break;
1291 	case SDLK_F3: priChar = shiftChar = capitalChar = KEY_F3; break;
1292 	case SDLK_F4: priChar = shiftChar = capitalChar = KEY_F4; break;
1293 	case SDLK_F5: priChar = shiftChar = capitalChar = KEY_F5; break;
1294 	case SDLK_F6: priChar = shiftChar = capitalChar = KEY_F6; break;
1295 	case SDLK_F7: priChar = shiftChar = capitalChar = KEY_F7; break;
1296 	case SDLK_F8: priChar = shiftChar = capitalChar = KEY_F8; break;
1297 	case SDLK_F9: priChar = shiftChar = capitalChar = KEY_F9; break;
1298 	case SDLK_F10: priChar = shiftChar = capitalChar = KEY_F10; break;
1299 	case SDLK_F11: priChar = shiftChar = capitalChar = KEY_F11; break;
1300 	case SDLK_F12: priChar = shiftChar = capitalChar = KEY_F12; break;
1301 
1302 	// arrow keys
1303 #if(defined(GERMAN))
1304 	case 0x67:		// fall through, German keyboard called "Pos 1"
1305 #endif
1306 	case SDLK_HOME: priChar = shiftChar = capitalChar = KEY_HOME; break;
1307 	case SDLK_UP: priChar = shiftChar = capitalChar = KEY_UP; break;
1308 	case SDLK_PAGEUP: priChar = shiftChar = capitalChar = KEY_PGUP; break;
1309 	case SDLK_LEFT: priChar = shiftChar = capitalChar = KEY_LEFT; break;
1310 	case SDLK_RIGHT: priChar = shiftChar = capitalChar = KEY_RIGHT; break;
1311 	case SDLK_END: priChar = shiftChar = capitalChar = KEY_END; break;
1312 	case SDLK_DOWN: priChar = shiftChar = capitalChar = KEY_DOWN; break;
1313 	case SDLK_PAGEDOWN: priChar = shiftChar = capitalChar = KEY_PGDN; break;
1314 	case SDLK_INSERT: priChar = shiftChar = capitalChar = KEY_INS; break;
1315 	case SDLK_DELETE: priChar = shiftChar = capitalChar = KEY_DEL; break;
1316 
1317 #if(defined(SPANISH))
1318 	// other keys
1319 	case 0x56: priChar = capitalChar = '<'; shiftChar = '>'; break;
1320 #endif
1321 
1322 	// other keys found in Japanese keyboard
1323 #if 0   //FIXME: Japanese
1324 	case SDLK_NUMPADCOMMA: priChar = shiftChar = capitalChar = ','; break;
1325 #endif
1326 	case SDLK_KP_EQUALS: priChar = shiftChar = capitalChar = '='; break;
1327 	case SDLK_AT: priChar = shiftChar = capitalChar = '@'; break;
1328 	case SDLK_COLON: priChar = shiftChar = capitalChar = ':'; break;
1329 	case SDLK_UNDERSCORE: priChar = shiftChar = capitalChar = '_'; break;
1330 	default:
1331 		MSG("unhandled key %x\n", scanCode);
1332 	}
1333 
1334 	// check flags
1335 	int retFlag = 1;
1336 
1337 	// check shift key state
1338 	if( !(flags & K_IGNORE_SHIFT) )
1339 	{
1340 		if( flags & K_IS_SHIFT )
1341 		{
1342 			if( !(skeyState & SHIFT_KEY_MASK) )
1343 				retFlag = 0;
1344 		}
1345 		else
1346 		{
1347 			if( skeyState & SHIFT_KEY_MASK )
1348 				retFlag = 0;
1349 		}
1350 	}
1351 
1352 	// check contrl key state
1353 	if( !(flags & K_IGNORE_CTRL) )
1354 	{
1355 		if( flags & K_IS_CTRL )
1356 		{
1357 			if( !(skeyState & CONTROL_KEY_MASK) )
1358 				retFlag = 0;
1359 		}
1360 		else
1361 		{
1362 			if( skeyState & CONTROL_KEY_MASK )
1363 				retFlag = 0;
1364 		}
1365 	}
1366 
1367 	// check alt key state
1368 	if( !(flags & K_IGNORE_ALT) )
1369 	{
1370 		if( flags & K_IS_ALT )
1371 		{
1372 			if( !(skeyState & ALT_KEY_MASK) )
1373 				retFlag = 0;
1374 		}
1375 		else
1376 		{
1377 			if( skeyState & ALT_KEY_MASK )
1378 				retFlag = 0;
1379 		}
1380 	}
1381 
1382 	// check numpad state
1383 	if( !(flags & K_IGNORE_NUMPAD) )
1384 	{
1385 		if( flags & K_ON_NUMPAD )
1386 		{
1387 			if( !onNumPad )
1388 				retFlag = 0;
1389 		}
1390 		else
1391 		{
1392 			if( onNumPad )
1393 				retFlag = 0;
1394 		}
1395 	}
1396 
1397 	unsigned outChar = priChar;
1398 	if( flags & K_TRANSLATE_KEY )
1399 	{
1400 #if(defined(FRENCH)||defined(GERMAN)||defined(SPANISH))
1401 		if( (skeyState & GRAPH_KEY_MASK) && altChar )
1402  		{
1403 			outChar = altChar;
1404  		}
1405  		else
1406  		{
1407 #endif
1408 			if( priChar == capitalChar )
1409 			{
1410 				// non-letter
1411 				outChar = skeyState & SHIFT_KEY_MASK ? shiftChar : priChar;
1412 			}
1413 			else
1414 			{
1415 				// letter
1416 				outChar = skeyState & CAP_LOCK_STATE_MASK ?
1417 					(skeyState & SHIFT_KEY_MASK ? priChar : capitalChar) :
1418 					(skeyState & SHIFT_KEY_MASK ? shiftChar : priChar) ;
1419 			}
1420 #if(defined(FRENCH)||defined(GERMAN)||defined(SPANISH))
1421 		}
1422 #endif
1423 	}
1424 
1425 	if(!retFlag)
1426 		return 0;
1427 
1428 	int retFlag2 = (charValue == 0) || outChar == charValue
1429 		|| ((flags & K_IGNORE_SHIFT) && shiftChar == charValue)
1430 		|| ((flags & K_IGNORE_CAP_LOCK) && capitalChar == charValue)
1431 		|| ((flags & K_CASE_INSENSITIVE) && outChar == (unsigned short) tolower(charValue));
1432 
1433 	if(retFlag2)
1434 		return outChar;
1435 	else
1436 		return 0;
1437 }
1438 // ------ End of Mouse::is_key -------//
1439 
1440 
1441 // ------ Begin of Mouse::is_key -------//
is_key(unsigned scanCode,unsigned short skeyState,char * keyStr,unsigned flags)1442 int Mouse::is_key(unsigned scanCode, unsigned short skeyState, char *keyStr, unsigned flags)
1443 {
1444 	int len = strlen(keyStr);
1445 
1446 	if( len == 0)
1447 		return 0;
1448 	if( len == 1)
1449 		return is_key(scanCode, skeyState, keyStr[0], flags);
1450 
1451 	const char *priChar = NULL;
1452 	const char *numLockChar = NULL;
1453 	int onNumPad = 0;
1454 
1455 	switch(scanCode)
1456 	{
1457 	case SDLK_F1: numLockChar = priChar = "F1"; break;
1458 	case SDLK_F2: numLockChar = priChar = "F2"; break;
1459 	case SDLK_F3: numLockChar = priChar = "F3"; break;
1460 	case SDLK_F4: numLockChar = priChar = "F4"; break;
1461 	case SDLK_F5: numLockChar = priChar = "F5"; break;
1462 	case SDLK_F6: numLockChar = priChar = "F6"; break;
1463 	case SDLK_F7: numLockChar = priChar = "F7"; break;
1464 	case SDLK_F8: numLockChar = priChar = "F8"; break;
1465 	case SDLK_F9: numLockChar = priChar = "F9"; break;
1466 	case SDLK_F10: numLockChar = priChar = "F10"; break;
1467 	case SDLK_F11: numLockChar = priChar = "F11"; break;
1468 	case SDLK_F12: numLockChar = priChar = "F12"; break;
1469 
1470 	case SDLK_KP_7: priChar = "HOME"; numLockChar = "7"; onNumPad = 1; break;
1471 	case SDLK_KP_8: priChar = "UP"; numLockChar = "8"; onNumPad = 1; break;
1472 	case SDLK_KP_9: priChar = "PAGE UP"; numLockChar = "9"; onNumPad = 1; break;
1473 	case SDLK_KP_4: priChar = "LEFT"; numLockChar = "4"; onNumPad = 1; break;
1474 	case SDLK_KP_5: priChar = "CENTER"; numLockChar = "5"; onNumPad = 1; break;
1475 	case SDLK_KP_6: priChar = "RIGHT"; numLockChar = "6"; onNumPad = 1; break;
1476 	case SDLK_KP_1: priChar = "END"; numLockChar = "1"; onNumPad = 1; break;
1477 	case SDLK_KP_2: priChar = "DOWN"; numLockChar = "2"; onNumPad = 1; break;
1478 	case SDLK_KP_3: priChar = "PAGE DOWN"; numLockChar = "3"; onNumPad = 1; break;
1479 	case SDLK_KP_0: priChar = "INSERT"; numLockChar = "0"; onNumPad = 1; break;
1480 	case SDLK_KP_PERIOD: priChar = "DELETE"; numLockChar = "."; onNumPad = 1; break;
1481 
1482 	// keys above arrow keys
1483 	case SDLK_HOME: priChar = numLockChar = "HOME"; break;
1484 	case SDLK_UP: priChar = numLockChar = "UP"; break;
1485 	case SDLK_PAGEUP: priChar = numLockChar = "PAGE UP"; break;
1486 	case SDLK_LEFT: priChar = numLockChar = "LEFT"; break;
1487 	case SDLK_RIGHT: priChar = numLockChar = "RIGHT"; break;
1488 	case SDLK_END: priChar = numLockChar = "END"; break;
1489 	case SDLK_DOWN: priChar = numLockChar = "DOWN"; break;
1490 	case SDLK_PAGEDOWN: priChar = numLockChar = "PAGE DOWN"; break;
1491 	case SDLK_INSERT: priChar = numLockChar = "INSERT"; break;
1492 	case SDLK_DELETE: priChar = numLockChar = "DELETE"; break;
1493 
1494 	// 104-key only
1495 	case SDLK_LGUI: priChar = numLockChar = "LEFT WINDOW"; break;
1496 	case SDLK_RGUI: priChar = numLockChar = "RIGHT WINDOW"; break;
1497 	case SDLK_MENU: priChar = numLockChar = "APP MENU"; break;
1498 	}
1499 
1500 	// check flags
1501 	int retFlag = 1;
1502 
1503 	// check shift key state
1504 	if( !(flags & K_IGNORE_SHIFT) )
1505 	{
1506 		if( flags & K_IS_SHIFT )
1507 		{
1508 			if( !(skeyState & SHIFT_KEY_MASK) )
1509 				retFlag = 0;
1510 		}
1511 		else
1512 		{
1513 			if( skeyState & SHIFT_KEY_MASK )
1514 				retFlag = 0;
1515 		}
1516 	}
1517 
1518 	// check contrl key state
1519 	if( !(flags & K_IGNORE_CTRL) )
1520 	{
1521 		if( flags & K_IS_CTRL )
1522 		{
1523 			if( !(skeyState & CONTROL_KEY_MASK) )
1524 				retFlag = 0;
1525 		}
1526 		else
1527 		{
1528 			if( skeyState & CONTROL_KEY_MASK )
1529 				retFlag = 0;
1530 		}
1531 	}
1532 
1533 	// check alt key state
1534 	if( !(flags & K_IGNORE_ALT) )
1535 	{
1536 		if( flags & K_IS_ALT )
1537 		{
1538 			if( !(skeyState & ALT_KEY_MASK) )
1539 				retFlag = 0;
1540 		}
1541 		else
1542 		{
1543 			if( skeyState & ALT_KEY_MASK )
1544 				retFlag = 0;
1545 		}
1546 	}
1547 
1548 	// check numpad state
1549 	if( !(flags & K_IGNORE_NUMPAD) )
1550 	{
1551 		if( flags & K_ON_NUMPAD )
1552 		{
1553 			if( !onNumPad )
1554 				retFlag = 0;
1555 		}
1556 		else
1557 		{
1558 			if( onNumPad )
1559 				retFlag = 0;
1560 		}
1561 	}
1562 
1563 	const char *outChar = skeyState & NUM_LOCK_STATE_MASK ? numLockChar : priChar;
1564 	int retFlag2 = outChar ? !strcmp(outChar, keyStr) : 0;
1565 
1566 	return retFlag && retFlag2;
1567 }
1568 // ------ End of Mouse::is_key -------//
1569 
1570 
1571 // ------ Begin of Mouse::disp_count_start -------//
disp_count_start()1572 void Mouse::disp_count_start()
1573 {
1574 	// unimplemented
1575 }
1576 // ------ End of Mouse::disp_count_start -------//
1577 
1578 
1579 // ------ Begin of Mouse::disp_count_end -------//
disp_count_end()1580 void Mouse::disp_count_end()
1581 {
1582 	// unimplemented
1583 }
1584 // ------ End of Mouse::disp_count_end -------//
1585 
1586 
1587 // ------ Begin of Mouse::bind_key -------//
1588 //
1589 // Associates keys with events. Mod keys are not supported at this time. The
1590 // string "key" is the SDL representation. Key is converted to the internal
1591 // game representation for key codes.
1592 //
bind_key(KeyEventType key_event,const char * key)1593 int Mouse::bind_key(KeyEventType key_event, const char *key)
1594 {
1595 	SDL_Keycode kc;
1596 	unsigned int *ke;
1597 	const char *key2;
1598 
1599 	key2 = strchr(key, '+');
1600 	if( !key2 )
1601 	{
1602 		kc = SDL_GetKeyFromName(key);
1603 		ke = &any_key_code_map[key_event];
1604 	}
1605 	else
1606 	{
1607 		kc = SDL_GetKeyFromName(key2+1);
1608 		if( !memcmp(key, "shift", 5) )
1609 			ke = &shift_key_code_map[key_event];
1610 		else
1611 			return 0;
1612 	}
1613 	if( kc == SDLK_UNKNOWN )
1614 		return 0;
1615 
1616 	reset_key(key_event);
1617 	*ke = mouse.is_key(kc, 0, (unsigned short)0, K_UNIQUE_KEY);
1618 	return 1;
1619 }
1620 // ------ End of Mouse::bind_key -------//
1621 
1622 
1623 // ------ Begin of Mouse::is_key_event -------//
1624 // checks if key_event's key code is the current key_code
is_key_event(KeyEventType key_event)1625 int Mouse::is_key_event(KeyEventType key_event)
1626 {
1627 	unsigned kc = SDLK_UNKNOWN;
1628 	if( key_event == KEYEVENT_UNSET )
1629 		return 0;
1630 	kc = any_key_code_map[key_event];
1631 	if( skey_state & SHIFT_KEY_MASK )
1632 		kc = shift_key_code_map[key_event];
1633 	return kc ? kc == unique_key_code : 0;
1634 }
1635 // ------ End of Mouse::is_key_event -------//
1636 
1637 
1638 // ------ Begin of Mouse::get_key_code -------//
1639 // get key code of key event
get_key_code(KeyEventType key_event)1640 unsigned Mouse::get_key_code(KeyEventType key_event)
1641 {
1642 	if( any_key_code_map[key_event] )
1643 		return any_key_code_map[key_event];
1644 	if( skey_state & SHIFT_KEY_MASK )
1645 		return shift_key_code_map[key_event];
1646 	return SDLK_UNKNOWN;
1647 }
1648 // ------ End of Mouse::get_key_code -------//
1649 
1650 
1651 // ------ Begin of Mouse::add_typing_event -------//
add_typing_event(char * text,unsigned long timeStamp)1652 void Mouse::add_typing_event(char *text, unsigned long timeStamp)
1653 {
1654 #ifdef ENABLE_NLS
1655 	const char *str = locale_res.conv_str(locale_res.cd_from_sdl, text);
1656 #else
1657 	char *str = text;
1658 #endif
1659 	while( *str )
1660 	{
1661 		if((head_ptr == tail_ptr-1) ||               // see if the buffer is full
1662 			(head_ptr == EVENT_BUFFER_SIZE-1 && tail_ptr == 0))
1663 		{
1664 			break;
1665 		}
1666 
1667 		MouseEvent *ev = event_buffer + head_ptr;
1668 
1669 		ev->event_type = KEY_TYPING;
1670 		ev->scan_code = 0;
1671 		ev->skey_state = skey_state;
1672 		ev->time = timeStamp;
1673 		ev->typing = *str;
1674 
1675 		// put mouse state
1676 		// ev->state = 0;			//ev->state = left_press | right_press;
1677 		ev->x = cur_x;
1678 		ev->y = cur_y;
1679 
1680 		if(++head_ptr >= EVENT_BUFFER_SIZE)  // increment the head ptr
1681 			head_ptr = 0;
1682 
1683 		str++;
1684 	}
1685 }
1686 // ------ End of Mouse::add_typing_event -------//
1687 
1688 
1689 // ------ Begin of static function reset_key -------//
reset_key(KeyEventType key_event)1690 static void reset_key(KeyEventType key_event)
1691 {
1692 	any_key_code_map[key_event] = SDLK_UNKNOWN;
1693 	shift_key_code_map[key_event] = SDLK_UNKNOWN;
1694 }
1695 // ------ End of static function reset_key -------//
1696