1 /*
2  * UAE - The Un*x Amiga Emulator
3  *
4  * Additional Win32 helper functions not calling any system routines
5  *
6  * (c) 1997 Mathias Ortmann
7  * (c) 1999-2001 Brian King
8  * (c) 2000-2001 Bernd Roesch
9  */
10 
11 #include "sysconfig.h"
12 
13 #include <assert.h>
14 #include <ctype.h>
15 #include <signal.h>
16 #include <windows.h>
17 
18 #include "sysdeps.h"
19 #include "uae.h"
20 #include "options.h"
21 #include "memory.h"
22 #include "custom.h"
23 #include "newcpu.h"
24 #include "keyboard.h"
25 #include "xwin.h"
26 #include "drawing.h"
27 #include "disk.h"
28 #include "keybuf.h"
29 #include "gui.h"
30 #include "osdep/win32.h"
31 #include "osdep/win32gui.h"
32 #include "debug.h"
33 
34 //#define DBG_KEYBD 1
35 static int keystate[AK_RCTRL+1];
36 static HKL keyboardlayoutid;
37 static WORD keyboardlangid;
38 
helppressed(void)39 static int helppressed (void)
40 {
41     return GetAsyncKeyState (VK_END) & 0x8000;
42 }
43 
shiftpressed(void)44 static int shiftpressed (void)
45 {
46     return GetAsyncKeyState (VK_SHIFT) & 0x8000 ? 1 : 0;
47 }
48 
getcapslock(void)49 static int getcapslock (void)
50 {
51     BYTE keyState[256];
52 #ifdef _WIN32_WCE
53     return( GetKeyState( VK_CAPITAL ) & 1 );
54 #else
55     GetKeyboardState (keyState);
56     return keyState[VK_CAPITAL] & 1;
57 #endif
58 }
59 
getascii(UINT vk,UINT scancode)60 static char getascii( UINT vk, UINT scancode )
61 {
62     BYTE keyState[256];
63     char buffer[2];
64     int result;
65 #ifndef _WIN32_WCE
66     GetKeyboardState (keyState);
67     result = ToAscii( vk, scancode, keyState, (LPWORD)buffer, 0 );
68     if( result == 1 )
69 	result = buffer[0];
70 #endif
71     return result;
72 }
73 
74 /* there's a problem remaining with the semantics of the '#' key on U.S. keyboards */
scancode2amiga(int keycode,int scancode)75 static int scancode2amiga (int keycode, int scancode)
76 {
77 	static int firstscan=0;
78 	if (!firstscan)
79 	{
80 	    keyboardlayoutid=GetKeyboardLayout(0);
81 	    keyboardlangid=LOWORD(keyboardlayoutid);
82 	    firstscan=1;
83 	}
84 #if DEBUG_KBD
85     write_log ( "keycode = 0x%x, scancode = 0x%x\n", keycode, scancode );
86 #endif
87 
88     if(keyboardlangid==MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN))
89     {
90 	if (keystate[AK_CTRL] &&
91 	    keystate[AK_RALT])
92 	{
93 	    switch (keycode & 0xff)
94 	    {
95 	    case 0xdb:
96 		return AK_BACKSLASH;
97 	    case 0x51:          //@
98 		record_key ((AK_CTRL << 1)+1);
99 		return 0x10;
100 	    case 0xbb:          //~
101 		record_key ((AK_CTRL << 1)+1);
102 		return 0x1b;
103 
104 	    }
105 	}
106     }
107 
108 #define USE_OLD_SHIFT_CODE
109 
110     switch (keycode & 0xff)
111     {
112 #ifndef USE_OLD_SHIFT_CODE
113     case VK_SHIFT:
114 	{
115 	    SHORT lsh, rsh;
116 	    lsh = GetKeyState( VK_LSHIFT );
117 	    rsh = GetKeyState( VK_RSHIFT );
118 	    if( !keystate[AK_RSH] && (rsh & 0x8000))
119 		return AK_RSH;
120 	    if( keystate[AK_RSH] && !(rsh & 0x8000))
121 		return AK_RSH;
122 	    if( !keystate[AK_LSH] && (lsh & 0x8000))
123 		return AK_LSH;
124 	    if( keystate[AK_LSH] && !(lsh & 0x8000))
125 		return AK_LSH;
126 	}
127 #endif
128      case VK_INSERT:
129      case VK_LWIN:
130 	return AK_LAMI;
131      case VK_HOME:
132      case VK_RWIN:
133 	return AK_RAMI;
134      case VK_MENU:
135 	 return scancode & KF_EXTENDED ? AK_RALT:AK_LALT;
136      case VK_APPS: /* Map Windows "Menu" key to Right-Alt of Amiga, for Stefan Stuntz */
137 	 return AK_RALT;
138      case VK_SCROLL:
139 	return AK_inhibit;
140      case VK_F11:
141 #if 0
142 	 if( currprefs.win32_ctrl_F11_is_quit )
143 	 {
144 	    if (GetAsyncKeyState (VK_CONTROL)&0x8000)
145 		uae_quit();
146 	 }
147 #endif
148 	 return AK_BACKSLASH;
149      case VK_F12:
150 	 if (GetAsyncKeyState (VK_CONTROL)&0x8000)
151 	     return -6;
152 	 if( shiftpressed() )
153 	     return -5;
154 	 else
155 	     return -2;
156 	 break;
157      case VK_PAUSE:
158 	return -3;
159      case VK_DECIMAL:
160 	return AK_NPDEL;
161      case VK_DIVIDE:
162 	return AK_NPDIV;
163      case VK_MULTIPLY:
164 	return AK_NPMUL;
165      case VK_SUBTRACT:
166 	return AK_NPSUB;
167      case VK_ADD:
168 	return AK_NPADD;
169      case VK_NUMPAD0:
170 	return AK_NP0;
171      case VK_NUMPAD1:
172 	return AK_NP1;
173      case VK_NUMPAD2:
174 	return AK_NP2;
175      case VK_NUMPAD3:
176 	return AK_NP3;
177      case VK_NUMPAD4:
178 	return AK_NP4;
179      case VK_NUMPAD5:
180 	return AK_NP5;
181      case VK_NUMPAD6:
182 	return AK_NP6;
183      case VK_NUMPAD7:
184 	return AK_NP7;
185      case VK_NUMPAD8:
186 	return AK_NP8;
187      case VK_NUMPAD9:
188 	return AK_NP9;
189      case VK_UP:
190 	return AK_UP;
191      case VK_DOWN:
192 	return AK_DN;
193      case VK_LEFT:
194 	return AK_LF;
195      case VK_RIGHT:
196 	return AK_RT;
197      case VK_CONTROL:
198 	return scancode & KF_EXTENDED ? AK_RCTRL : AK_CTRL;
199      case VK_RETURN:
200 	return scancode & KF_EXTENDED ? AK_ENT : AK_RET;
201      case VK_CAPITAL:
202 	return -4;
203      case VK_F1:
204 	if (helppressed ())
205 	    return -10 - shiftpressed ();
206 	return AK_F1;
207      case VK_F2:
208 	if (helppressed ())
209 	    return -12 - shiftpressed ();
210 	return AK_F2;
211     case VK_F3:
212 	if (helppressed ())
213 	    return -14 - shiftpressed ();
214 	return AK_F3;
215     case VK_F4:
216 	if (helppressed ())
217 	    return -16 - shiftpressed ();
218 	return AK_F4;
219      case VK_F5:
220 	return AK_F5;
221      case VK_F6:
222 	return AK_F6;
223      case VK_F7:
224 	return AK_F7;
225      case VK_F8:
226 	return AK_F8;
227      case VK_F9:
228 	return AK_F9;
229      case VK_F10:
230 	return AK_F10;
231      case VK_NEXT:
232 	return AK_HELP;
233     }
234 
235     switch (scancode) {
236      case 0x01:
237 	return 0x45;
238      case 0x29:
239 	return 0x00;
240      case 0x02:
241 	return 0x01;
242      case 0x03:
243 	return 0x02;
244      case 0x04:
245 	return 0x03;
246      case 0x05:
247 	return 0x04;
248      case 0x06:
249 	return 0x05;
250      case 0x07:
251 	return 0x06;
252      case 0x08:
253 	return 0x07;
254      case 0x09:
255 	return 0x08;
256      case 0x0a:
257 	return 0x09;
258      case 0x0b:
259 	return 0x0a;
260      case 0x0c:
261 	return 0x0b;
262      case 0x0d:
263 	return 0x0c;
264      case 0x57: /* This is F11 */
265 	return AK_BACKSLASH;
266      case 0x0e:
267 	return 0x41;
268      case 0x0f:
269 	return 0x42;
270      case 0x10:
271 	return 0x10;
272      case 0x11:
273 	return 0x11;
274      case 0x12:
275 	return 0x12;
276      case 0x13:
277 	return 0x13;
278      case 0x14:
279 	return 0x14;
280      case 0x15:
281 	return 0x15;
282      case 0x16:
283 	return 0x16;
284      case 0x17:
285 	return 0x17;
286      case 0x18:
287 	return 0x18;
288      case 0x19:
289 	return 0x19;
290      case 0x1a:
291 	return 0x1a;
292      case 0x1b:
293 	return 0x1b;
294 	/* special handling for caps lock: return 0x63*/
295      case 0x3a:
296 	return 0x62;
297      case 0x1e:
298 	return 0x20;
299      case 0x1f:
300 	return 0x21;
301      case 0x20:
302 	return 0x22;
303      case 0x21:
304 	return 0x23;
305      case 0x22:
306 	return 0x24;
307      case 0x23:
308 	return 0x25;
309      case 0x24:
310 	return 0x26;
311      case 0x25:
312 	return 0x27;
313      case 0x26:
314 	return 0x28;
315      case 0x27:
316 	return AK_SEMICOLON;
317      case 0x28:
318 	return AK_QUOTE;
319      case 0x2b: /* This scancode is \ on US keyboards, but # on German ones - figure out which! */
320 	 if( getascii( keycode & 0xFF, scancode ) == '#' )
321 	     return AK_NUMBERSIGN;
322 	 else
323 	     return AK_BACKSLASH;
324 	 break;
325 #ifdef USE_OLD_SHIFT_CODE
326      case 0x2a:
327 	return AK_LSH;
328      case 0x36:
329 	return AK_RSH;
330 #endif
331      case 0x56:
332 	return AK_LTGT;
333      case 0x2c:
334 	return 0x31;
335      case 0x2d:
336 	return 0x32;
337      case 0x2e:
338 	return 0x33;
339      case 0x2f:
340 	return 0x34;
341      case 0x30:
342 	return 0x35;
343      case 0x31:
344 	return 0x36;
345      case 0x32:
346 	return 0x37;
347      case 0x33:
348 	return 0x38;
349      case 0x34:
350 	return 0x39;
351      case 0x35:
352 	return 0x3a;
353      case 0x38:
354 	return 0x64;
355      case 0x39:
356 	return 0x40;
357      case 0x153:
358 	return 0x46;
359      case 0x51:
360 	return 0x5f;
361      case 0x52:
362 	return AK_LAMI;
363      case 0x47:
364 	return AK_RAMI;
365      case 0x4b:
366 	return 0x4f;
367      case 0x50:
368 	return 0x4d;
369      case 0x4d:
370 	return 0x4e;
371      case 0x48:
372 	return 0x4c;
373      case 0x4e:
374 	return 0x5e;
375      case 0x4a:
376 	return 0x4a;
377      case 0x37:
378 	return 0x5d;
379     }
380 
381     return -1;
382 }
383 
clearallkeys()384 void clearallkeys()
385 {
386     int i;
387     for(i = 0; i <AK_CTRL + 1; i++)
388 	my_kbd_handler (0, i, 0);
389     for(i = 0; i < AK_CTRL + 1; i++)
390 	my_kbd_handler (i, 0, 0);
391     buttonstate[0] = 0;
392     buttonstate[1] = 0;
393     buttonstate[2] = 0;
394 }
395 
my_kbd_handler(int keycode,int scancode,int newstate)396 int my_kbd_handler (int keycode, int scancode, int newstate)
397 {
398     int akey = scancode2amiga (keycode, scancode);
399 
400 #ifdef DEBUG_KBD
401     write_log ( "kbd_handler: keycode 0x%x, scancode 0x%x, newstate %d\n", keycode, scancode, newstate );
402 #endif
403     if (akey < 0) {
404 
405 	switch (akey) {
406 #ifndef _WIN32_WCE
407 	 case -2:
408 	    if (newstate)
409 		{
410 		clearallkeys();
411 		WIN32GUI_DisplayGUI(-1);
412 		}
413 	    return 0;
414 
415 	 case -3:
416 	    if (newstate)
417 		toggle_sound = 1;
418 	    return 0;
419 	 case -4:
420 	    if (newstate) {
421 		akey = 0x62;
422 		newstate = getcapslock ();
423 	    }
424 	    break;
425      case -5:
426 	 if( newstate )
427 	 {
428 	    // Bring up GUI-based debugger here
429 	  if(currprefs.illegal_mem)
430 		   {
431 
432 
433 	     if(picasso_on)changed_prefs.gfx_pfullscreen=0;
434 		 else changed_prefs.gfx_afullscreen=0;
435 
436 		 check_prefs_changed_gfx();
437 	 activate_debugger();
438 
439 
440 	 }
441 
442 		 }
443 	 return 0;
444 	 break;
445 	 case -6:
446 		 if(newstate)
447 		 {
448 		 if(picasso_on)changed_prefs.gfx_pfullscreen=!changed_prefs.gfx_pfullscreen;
449 		 else changed_prefs.gfx_afullscreen=!changed_prefs.gfx_afullscreen;
450 
451 		 return 0;
452 		 }
453 		 break;
454 	 default:
455 
456 	     if (newstate && akey >= -17 && akey <= -10)
457 	     {
458 		 akey = -10 - akey;
459 
460 		 if (akey & 1)
461 		 {
462 		     akey >>= 1;
463 		     disk_eject (akey);
464 		     return 0;
465 		 }
466 		 akey >>= 1;
467 
468 		 WIN32GUI_DisplayGUI( akey );
469 	     }
470 	     return 0;
471 #endif
472 	}
473     }
474     if (akey == AK_inhibit) {
475 	if (newstate)
476 	    toggle_inhibit_frame (IHF_SCROLLLOCK);
477 	return 0;
478     }
479     if( akey > AK_RCTRL )
480 	return 0;
481     if (keystate[akey] == newstate)
482 	return 0;
483     keystate[akey] = newstate;
484 
485     if (newstate)
486 	record_key (akey << 1);
487     else
488 	record_key ((akey << 1) + 1);
489 
490     /* "Affengriff" */
491 	if(  (keystate[AK_CTRL] || keystate[AK_RCTRL] ) && keystate[AK_LAMI] && keystate[AK_RAMI])uae_reset();
492     //if(  (keystate[AK_CTRL] || keystate[AK_RCTRL] ) && keystate[AK_RAMI])uae_reset();
493 
494     return 0;
495 }
496 
497