/* * Copyright © 2006-2016 SplinterGU (Fenix/Bennugd) * Copyright © 2002-2006 Fenix Team (Fenix) * Copyright © 1999-2002 José Luis Cebrián Pagüe (Fenix) * * This file is part of Bennu - Game Development * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 3. This notice may not be removed or altered from any source * distribution. * */ #include #include #include #include "xctype.h" #include "bgddl.h" #include "dlvaracc.h" #define __LIBKEY #include "libkey.h" /* ---------------------------------------------------------------------- */ #include "libkey_exports.h" /* ---------------------------------------------------------------------- */ typedef struct { SDLKey sym; /* SDL virtual keysym */ SDLMod mod; /* current key modifiers */ HOTKEY_CALLBACK callback; } hotkey ; static hotkey * hotkey_list = NULL ; static int hotkey_allocated = 0 ; static int hotkey_count = 0 ; /* ---------------------------------------------------------------------- */ /* Publicas */ key_equiv key_table[127] ; /* Now we have a search table with equivs */ unsigned char * keystate = NULL; /* Pointer to key states */ /* ---------------------------------------------------------------------- */ static int sdl_equiv[SDLK_LAST+1] ; static int equivs[] = { SDLK_RCTRL, 1, SDLK_1, 2, SDLK_KP1, 2, SDLK_2, 3, SDLK_KP2, 3, SDLK_3, 4, SDLK_KP3, 4, SDLK_4, 5, SDLK_KP4, 5, SDLK_5, 6, SDLK_KP5, 6, SDLK_6, 7, SDLK_KP6, 7, SDLK_7, 8, SDLK_KP7, 8, SDLK_8, 9, SDLK_KP8, 9, SDLK_9, 10, SDLK_KP9, 10, SDLK_0, 11, SDLK_KP0, 11, SDLK_MINUS, 12, SDLK_EQUALS, 13, SDLK_BACKSPACE, 14, SDLK_TAB, 15, SDLK_q, 16, SDLK_w, 17, SDLK_e, 18, SDLK_r, 19, SDLK_t, 20, SDLK_y, 21, SDLK_u, 22, SDLK_i, 23, SDLK_o, 24, SDLK_p, 25, SDLK_LEFTBRACKET, 26, SDLK_RIGHTBRACKET, 27, SDLK_RETURN, 28, SDLK_KP_ENTER, 28, SDLK_LCTRL, 29, SDLK_RCTRL, 29, SDLK_LCTRL, 96, SDLK_RCTRL, 94, SDLK_a, 30, SDLK_s, 31, SDLK_d, 32, SDLK_f, 33, SDLK_g, 34, SDLK_h, 35, SDLK_j, 36, SDLK_k, 37, SDLK_l, 38, SDLK_SEMICOLON, 39, SDLK_QUOTE, 40, SDLK_BACKQUOTE, 41, SDLK_LSHIFT, 42, SDLK_BACKSLASH, 43, SDLK_z, 44, SDLK_x, 45, SDLK_c, 46, SDLK_v, 47, SDLK_b, 48, SDLK_n, 49, SDLK_m, 50, SDLK_COMMA, 51, SDLK_PERIOD, 52, SDLK_KP_PERIOD, 52, SDLK_SLASH, 53, SDLK_KP_DIVIDE, 53, SDLK_RSHIFT, 54, /* SDLK_PRINT, 55,*/ SDLK_KP_MULTIPLY, 55, SDLK_LALT, 56, SDLK_RALT, 56, SDLK_LALT, 95, SDLK_RALT, 93, SDLK_MODE, 93, SDLK_MODE, 56, SDLK_RMETA, 56, SDLK_LMETA, 56, SDLK_SPACE, 57, SDLK_CAPSLOCK, 58, SDLK_F1, 59, SDLK_F2, 60, SDLK_F3, 61, SDLK_F4, 62, SDLK_F5, 63, SDLK_F6, 64, SDLK_F7, 65, SDLK_F8, 66, SDLK_F9, 67, SDLK_F10, 68, SDLK_NUMLOCK, 69, SDLK_SCROLLOCK, 70, SDLK_HOME, 71, SDLK_UP, 72, SDLK_PAGEUP, 73, SDLK_KP_MINUS, 74, SDLK_LEFT, 75, SDLK_RIGHT, 77, SDLK_KP_PLUS, 78, SDLK_END, 79, SDLK_DOWN, 80, SDLK_PAGEDOWN, 81, SDLK_INSERT, 82, SDLK_DELETE, 83, SDLK_F11, 87, SDLK_F12, 88, SDLK_LESS, 89, SDLK_PLUS, 90, SDLK_GREATER, 91, SDLK_QUESTION, 92, SDLK_CARET, 93, SDLK_SYSREQ, 55, SDLK_PAUSE, 95, SDLK_MENU, 97, SDLK_LSUPER, 98, SDLK_RSUPER, 99, SDLK_COMPOSE, 99, -1, -1 } ; /* ---------------------------------------------------------------------- */ enum { SHIFTSTATUS = 0, ASCII, SCANCODE }; /* ---------------------------------------------------------------------- */ /* Son las variables que se desea acceder. */ /* El interprete completa esta estructura, si la variable existe. */ /* (usada en tiempo de ejecucion) */ DLVARFIXUP __bgdexport( libkey, globals_fixup )[] = { /* Nombre de variable global, puntero al dato, tamaño del elemento, cantidad de elementos */ { "shift_status" , NULL, -1, -1 }, { "ascii" , NULL, -1, -1 }, { "scan_code" , NULL, -1, -1 }, { NULL , NULL, -1, -1 } }; /* ---------------------------------------------------------------------- */ static void add_key_equiv( int equiv, int keyconst ) { key_equiv * curr = &key_table[keyconst] ; if ( curr->next != NULL ) while ( curr->next != NULL ) curr = curr->next ; if ( curr->sdlk_equiv != 0 ) { curr->next = malloc( sizeof( key_equiv ) ) ; curr = curr->next ; curr->next = NULL ; } curr->sdlk_equiv = equiv ; } /* ---------------------------------------------------------------------- */ void hotkey_add( int mod, int sym, HOTKEY_CALLBACK callback ) { if ( hotkey_count >= hotkey_allocated ) { hotkey_allocated = hotkey_count + 5; hotkey_list = realloc( hotkey_list, hotkey_allocated * sizeof( hotkey_list[0] ) ); } if ( !hotkey_list ) { fprintf( stderr, "No memory for alloc hotkey\n" ); exit( -1 ); } hotkey_list [hotkey_count].mod = mod; hotkey_list [hotkey_count].sym = sym; hotkey_list [hotkey_count].callback = callback; hotkey_count++; } /* ---------------------------------------------------------------------- */ /* * FUNCTION : process_key_events * * Process all pending SDL events, updating all global variables * and handling debug key presses and cannot be changed * * PARAMS : * None * * RETURN VALUE : * None */ static void process_key_events() { SDL_Event e ; SDLMod m ; int k, asc ; int pressed ; key_equiv * curr ; int keypress ; static struct { int ascii ; int scancode ; } keyring [64] ; static int keyring_start = 0, keyring_tail = 0 ; int ignore_key, n; /* Actualizar eventos */ keypress = 0 ; m = SDL_GetModState() ; /* Procesa los eventos pendientes */ /* Reset ascii and scancode if last key was released... */ /* must check all the linked equivs */ pressed = 0 ; if ( GLODWORD( libkey, SCANCODE ) ) { curr = &key_table[GLODWORD( libkey, SCANCODE )] ; while ( curr != NULL && pressed == 0 ) { if ( keystate[curr->sdlk_equiv] ) pressed = 1 ; curr = curr->next ; } } if ( !pressed ) { GLODWORD( libkey, ASCII ) = 0 ; GLODWORD( libkey, SCANCODE ) = 0 ; } while ( SDL_PeepEvents( &e, 1, SDL_GETEVENT, SDL_EVENTMASK(SDL_KEYDOWN)|SDL_EVENTMASK(SDL_KEYUP) ) > 0 ) { switch ( e.type ) { case SDL_KEYDOWN: ignore_key = 0; /* KeyDown HotKey */ if ( hotkey_count ) for ( n = 0; n < hotkey_count; n++ ) { if ((( hotkey_list[n].mod & e.key.keysym.mod ) == hotkey_list[n].mod ) && ( !hotkey_list[n].sym || ( hotkey_list[n].sym == e.key.keysym.sym ) ) ) { ignore_key = hotkey_list[n].callback( e.key.keysym ); } } /* KeyDown HotKey */ if ( ignore_key ) break ; /* Almacena la pulsación de la tecla */ k = sdl_equiv[e.key.keysym.sym]; m = e.key.keysym.mod ; if ( !keypress ) { GLODWORD( libkey, SCANCODE ) = k ; if ( e.key.keysym.unicode ) { asc = win_to_dos[e.key.keysym.unicode & 0xFF] ; /* ascii mayusculas */ if ( asc >= 'a' && asc <= 'z' && ( m & KMOD_LSHIFT || m & KMOD_RSHIFT || keystate[SDLK_CAPSLOCK] ) ) asc -= 0x20 ; } else { asc = 0 ; /* NON PRINTABLE */ } GLODWORD( libkey, ASCII ) = asc ; keypress = 1 ; } else { keyring[keyring_tail].scancode = k ; if ( e.key.keysym.unicode ) { asc = win_to_dos[e.key.keysym.unicode & 0x7F] ; /*ascii mayusculas */ if ( asc >= 'a' && asc <= 'z' && ( m & KMOD_LSHIFT || m & KMOD_RSHIFT || keystate[SDLK_CAPSLOCK] ) ) asc -= 0x20 ; } else { asc = 0 ; /* NON PRINTABLE */ } keyring[keyring_tail].ascii = asc ; if ( ++keyring_tail == 64 ) keyring_tail = 0 ; } break ; case SDL_KEYUP: /* Do nothing, Bennu is key_up unsensitive */ break ; } } if ( !keypress && keyring_start != keyring_tail ) { GLODWORD( libkey, ASCII ) = keyring[keyring_start].ascii ; GLODWORD( libkey, SCANCODE ) = keyring[keyring_start].scancode ; if ( ++keyring_start == 64 ) keyring_start = 0 ; } /* Now actualized every frame... */ GLODWORD( libkey, SHIFTSTATUS ) = ( ( m & KMOD_RSHIFT ) ? STAT_RSHIFT : 0 ) | ( ( m & KMOD_LSHIFT ) ? STAT_LSHIFT : 0 ) | ( ( m & KMOD_CTRL ) ? STAT_CTRL : 0 ) | ( ( m & KMOD_ALT ) ? STAT_ALT : 0 ) | ( ( m & KMOD_RCTRL ) ? STAT_RCTRL : 0 ) | ( ( m & KMOD_LCTRL ) ? STAT_LCTRL : 0 ) | ( ( m & KMOD_RALT ) ? STAT_RALT : 0 ) | ( ( m & KMOD_LALT ) ? STAT_LALT : 0 ) | ( ( m & KMOD_NUM ) ? STAT_NUM : 0 ) | ( ( m & KMOD_CAPS ) ? STAT_CAPS : 0 ) | ( ( m & KMOD_SHIFT ) ? STAT_SHIFT : 0 ) ; } /* ---------------------------------------------------------------------- */ /* Bigest priority first execute Lowest priority last execute */ HOOK __bgdexport( libkey, handler_hooks )[] = { { 4900, process_key_events }, { 0, NULL } } ; /* ---------------------------------------------------------------------- */ /* Funciones de inicializacion del modulo/plugin */ void __bgdexport( libkey, module_initialize )() { int * ptr = equivs ; if ( !SDL_WasInit( SDL_INIT_VIDEO ) ) SDL_InitSubSystem( SDL_INIT_VIDEO ); memset( sdl_equiv, 0, sizeof( sdl_equiv ) ); memset( key_table, 0, sizeof( key_table ) ) ; while ( *ptr != -1 ) { sdl_equiv[*ptr] = ptr[1] ; add_key_equiv( ptr[0], ptr[1] ) ; ptr += 2 ; } if ( !keystate ) keystate = SDL_GetKeyState( NULL ); SDL_EnableUNICODE( 1 ); } /* ---------------------------------------------------------------------- */ void __bgdexport( libkey, module_finalize )() { /* FREE used key_equivs... note base 127 equivs are static not allocated... */ int i ; key_equiv * aux ; key_equiv * curr = key_table ; for ( i = 0;i < 127;i++ ) { if ( curr->next != NULL ) { curr = curr->next ; while ( curr->next != NULL ) { aux = curr ; curr = curr->next; free( aux ) ; } free( curr ) ; } } if ( SDL_WasInit( SDL_INIT_VIDEO ) ) SDL_QuitSubSystem( SDL_INIT_VIDEO ); } /* ---------------------------------------------------------------------- */