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