Yet another UNICODE overhaul - Using seperate buffer for UNICODE chars and only use it in key_ascii() while still using keysyms for the rest of the program so we do not screw up readings by key values altered by modifers - possibly still room to optimize

This commit is contained in:
zicodxx 2008-11-17 23:38:43 +00:00
parent 02e7490c63
commit 02b1872aa9
10 changed files with 151 additions and 186 deletions

View file

@ -3,6 +3,7 @@ D2X-Rebirth Changelog
20081118
--------
main/console.c: When printing Gamelog, make sure canvas is NULL
main/newmenu.c, main/multi.c, main/automap.c, main/gamecntl.c, ui/inputbox.c, ui/menubar.c, arch/sdl/event.c, arch/sdl/key.c, arch/include/key.h: Yet another UNICODE overhaul - Using seperate buffer for UNICODE chars and only use it in key_ascii() while still using keysyms for the rest of the program so we do not screw up readings by key values altered by modifers - possibly still room to optimize
20081115
--------

View file

@ -12,23 +12,9 @@ COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
*/
/*
* $Source: /cvsroot/dxx-rebirth/d2x-rebirth/arch/include/key.h,v $
* $Revision: 1.1.1.1 $
* $Author: zicodxx $
* $Date: 2006/03/17 19:54:32 $
*
* Header for keyboard functions
*
* $Log: key.h,v $
* Revision 1.1.1.1 2006/03/17 19:54:32 zicodxx
* initial import
*
* Revision 1.2 2001/01/28 16:21:54 bradleyb
* More header unification...
*
* Revision 1.1 2001/01/28 05:46:33 bradleyb
* Unified arch headers
*
*/
#ifndef _KEY_H
@ -37,6 +23,8 @@ COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
#include "pstypes.h"
#include "fix.h"
#define KEY_BUFFER_SIZE 16
//==========================================================================
// This installs the int9 vector and initializes the keyboard in buffered
// ASCII mode. key_close simply undoes that.
@ -57,6 +45,9 @@ extern unsigned char keyd_editor_mode;
// Time in seconds when last key was pressed...
extern volatile int keyd_time_when_last_pressed;
// Stores Unicode values registered in one event_loop call
unsigned char unicode_frame_buffer[KEY_BUFFER_SIZE];
//==========================================================================
// These are the "buffered" keypress routines. Use them by setting the
// "keyd_buffer_type" variable.
@ -69,7 +60,7 @@ extern int key_inkey(); // Gets key if one, other returns 0.
extern int key_inkey_time(fix *time); // Same as inkey, but returns the time the key was pressed down.
extern int key_peekkey(); // Same as inkey, but doesn't remove key from buffer.
extern unsigned char key_to_ascii(int keycode);
extern unsigned char key_ascii();
extern void key_debug(); // Does an INT3

View file

@ -12,55 +12,56 @@
#include <stdio.h>
#include <stdlib.h>
#include "key.h"
#include <SDL/SDL.h>
extern void key_handler(SDL_KeyboardEvent *event);
extern void mouse_button_handler(SDL_MouseButtonEvent *mbe);
extern void mouse_motion_handler(SDL_MouseMotionEvent *mme);
#ifndef USE_LINUX_JOY // stpohle - so we can choose at compile time..
extern void joy_button_handler(SDL_JoyButtonEvent *jbe);
extern void joy_hat_handler(SDL_JoyHatEvent *jhe);
extern void joy_axis_handler(SDL_JoyAxisEvent *jae);
#endif
static int initialised=0;
void event_poll()
{
SDL_Event event;
int clean_uniframe=1;
while (SDL_PollEvent(&event)) {
switch(event.type) {
case SDL_KEYDOWN:
case SDL_KEYUP:
key_handler((SDL_KeyboardEvent *)&event);
break;
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
mouse_button_handler((SDL_MouseButtonEvent *)&event);
break;
case SDL_MOUSEMOTION:
mouse_motion_handler((SDL_MouseMotionEvent *)&event);
break;
#ifndef USE_LINUX_JOY // stpohle - so we can choose at compile time..
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
joy_button_handler((SDL_JoyButtonEvent *)&event);
break;
case SDL_JOYAXISMOTION:
joy_axis_handler((SDL_JoyAxisEvent *)&event);
break;
case SDL_JOYHATMOTION:
joy_hat_handler((SDL_JoyHatEvent *)&event);
break;
case SDL_JOYBALLMOTION:
break;
#endif
case SDL_QUIT: {
void quit_request();
quit_request();
} break;
case SDL_KEYDOWN:
case SDL_KEYUP:
if (clean_uniframe)
memset(unicode_frame_buffer,'\0',sizeof(unsigned char)*KEY_BUFFER_SIZE);
clean_uniframe=0;
key_handler((SDL_KeyboardEvent *)&event);
break;
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
mouse_button_handler((SDL_MouseButtonEvent *)&event);
break;
case SDL_MOUSEMOTION:
mouse_motion_handler((SDL_MouseMotionEvent *)&event);
break;
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
joy_button_handler((SDL_JoyButtonEvent *)&event);
break;
case SDL_JOYAXISMOTION:
joy_axis_handler((SDL_JoyAxisEvent *)&event);
break;
case SDL_JOYHATMOTION:
joy_hat_handler((SDL_JoyHatEvent *)&event);
break;
case SDL_JOYBALLMOTION:
break;
case SDL_QUIT: {
void quit_request();
quit_request();
} break;
}
}
}

View file

@ -20,8 +20,6 @@
#include "key.h"
#include "timer.h"
#define KEY_BUFFER_SIZE 16
static unsigned char Installed = 0;
//-------- Variable accessed by outside functions ---------
@ -32,6 +30,7 @@ volatile unsigned char keyd_last_pressed;
volatile unsigned char keyd_last_released;
volatile unsigned char keyd_pressed[256];
volatile int keyd_time_when_last_pressed;
unsigned char unicode_frame_buffer[KEY_BUFFER_SIZE] = { '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' };
typedef struct Key_info {
ubyte state; // state of key 1 == down, 0 == up
@ -295,96 +294,79 @@ key_props key_properties[256] = {
{ "", 255, -1 },
{ "", 255, -1 },
{ "", 255, -1 },
{ "!", '!', SDLK_EXCLAIM },
{ "@", '@', SDLK_AT },
{ "#", '#', SDLK_HASH },
{ "$", '$', SDLK_DOLLAR },
{ "%", '%', -1 }, // 240
{ "^", '^', SDLK_CARET },
{ "&", '&', SDLK_AMPERSAND },
{ "(", '(', SDLK_LEFTPAREN },
{ ")", ')', SDLK_RIGHTPAREN },
{ "_", '_', SDLK_UNDERSCORE },
{ "+", '+', SDLK_PLUS },
{ "{", '{', -1 },
{ "}", '}', -1 },
{ ":", ':', SDLK_COLON },
{ "\"", '"', SDLK_QUOTEDBL }, // 250
{ "~", '~', -1 },
{ "|", '|', -1 },
{ "<", '<', SDLK_LESS },
{ ">", '>', SDLK_GREATER },
{ "?", '?', SDLK_QUESTION }, // 255
};
// As UNICODE chars have no RELEASED state, we save each one together with the symbol assigned to it.
// If a symbol is RELEASED, check the list and we know which unicode we just released!
// This way we almost "emulate" the RELEASED state for UNICODE chars.
int sym2unimap[KEY_BUFFER_SIZE][2] =
{
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ -1, -1 },
{ "", 255, -1 },
{ "", 255, -1 },
{ "", 255, -1 },
{ "", 255, -1 },
{ "", 255, -1 }, // 240
{ "", 255, -1 },
{ "", 255, -1 },
{ "", 255, -1 },
{ "", 255, -1 },
{ "", 255, -1 },
{ "", 255, -1 },
{ "", 255, -1 },
{ "", 255, -1 },
{ "", 255, -1 },
{ "", 255, -1 }, // 250
{ "", 255, -1 },
{ "", 255, -1 },
{ "", 255, -1 },
{ "", 255, -1 },
{ "", 255, -1 }, // 255
};
char *key_text[256];
unsigned char key_to_ascii(int keycode)
unsigned char key_ascii()
{
keycode &= 0xFF;
return key_properties[keycode].ascii_value;
static unsigned char unibuffer[KEY_BUFFER_SIZE] = { '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' };
int i=0, offset=0, count=0;
offset=strlen((const char*)unibuffer);
// move temporal chars from unicode_frame_buffer to empty space behind last unibuffer char (if any)
for (i=offset; i < KEY_BUFFER_SIZE; i++)
if (unicode_frame_buffer[count] != '\0')
{
unibuffer[i]=unicode_frame_buffer[count];
unicode_frame_buffer[count]='\0';
count++;
}
// unibuffer is not empty. store first char, remove it, shift all chars one step left and then print our char
if (unibuffer[0] != '\0')
{
unsigned char retval = unibuffer[0];
unsigned char unibuffer_shift[KEY_BUFFER_SIZE];
memset(unibuffer_shift,'\0',sizeof(unsigned char)*KEY_BUFFER_SIZE);
memcpy(unibuffer_shift,unibuffer+1,sizeof(unsigned char)*(KEY_BUFFER_SIZE-1));
memcpy(unibuffer,unibuffer_shift,sizeof(unsigned char)*KEY_BUFFER_SIZE);
return retval;
}
else
return 255;
}
void key_handler(SDL_KeyboardEvent *event)
void key_handler(SDL_KeyboardEvent *event, int counter)
{
ubyte state;
int i, keycode, event_keysym=-1, event_keyuni=-1, key_state;
int i, keycode, event_keysym=-1, key_state;
Key_info *key;
unsigned char temp;
// Read SDLK symbol and state
event_keysym = event->keysym.sym;
key_state = (event->state == SDL_PRESSED);
// Read (latin) unicode
if (event->keysym.unicode > 31 && event->keysym.unicode < 255)
{
event_keyuni = tolower(event->keysym.unicode);
// Now add the UNICODE char to our map (see comment on sym2unimap declaration)
// fill the unicode frame-related unicode buffer
if (key_state && event->keysym.unicode > 31 && event->keysym.unicode < 255)
for (i = 0; i < KEY_BUFFER_SIZE; i++)
{
if (sym2unimap[i][0] == -1)
if (unicode_frame_buffer[i] == '\0')
{
sym2unimap[i][0] = event_keyuni;
sym2unimap[i][1] = event_keysym;
unicode_frame_buffer[i] = event->keysym.unicode;
break;
}
}
}
else // no valid UNICODE - possibly 0 - see if we remove it from the list
{
for (i = 0; i < KEY_BUFFER_SIZE; i++)
{
if (event_keysym == sym2unimap[i][1])
{
event_keyuni = sym2unimap[i][0];
sym2unimap[i][0] = sym2unimap[i][1] = -1;
}
}
}
key_state = (event->state == SDL_PRESSED);
//=====================================================
@ -392,9 +374,7 @@ void key_handler(SDL_KeyboardEvent *event)
keycode = i;
key = &(key_data.keys[keycode]);
if (key_properties[i].ascii_value == event_keyuni && key_properties[i].ascii_value != 255)
state = key_state;
else if ((event_keyuni == -1 || event_keyuni == event_keysym) && key_properties[i].sym == event_keysym)
if (key_properties[i].sym == event_keysym)
state = key_state;
else
state = key->last_state;
@ -482,12 +462,7 @@ void key_flush()
for (i=0; i<KEY_BUFFER_SIZE; i++ ) {
key_data.keybuffer[i] = 0;
key_data.time_pressed[i] = 0;
}
//Clear the unicode map
for (i=0; i<KEY_BUFFER_SIZE; i++ ) {
sym2unimap[i][0] = -1;
sym2unimap[i][1] = -1;
unicode_frame_buffer[i] = '\0';
}
//use gettimeofday here:

View file

@ -1354,8 +1354,8 @@ void MarkerInputMessage(int key)
DefiningMarkerMessage = 0;
break;
default:
if (key > 0) {
int ascii = key_to_ascii(key);
{
int ascii = key_ascii();
if ((ascii < 255 ))
if (Marker_index < 38 )
{

View file

@ -1822,7 +1822,7 @@ void FinalCheats(int key)
int i;
char *cryptstring;
key=key_to_ascii(key);
key=key_ascii();
for (i=0;i<15;i++)
CheatBuffer[i]=CheatBuffer[i+1];
@ -2228,58 +2228,55 @@ void ReadControls()
if (Newdemo_state == ND_STATE_PLAYBACK )
update_vcr_state();
while ((key=key_inkey_time(&key_time)) != 0) {
if (con_events(key) && con_render)
game_flush_inputs();
key=key_inkey();
if (DefiningMarkerMessage)
{
MarkerInputMessage(key);
continue;
}
if (con_events(key) && con_render)
return;
if (DefiningMarkerMessage)
{
MarkerInputMessage(key);
return;
}
#ifdef NETWORK
if ( (Game_mode & GM_MULTI) && (multi_sending_message || multi_defining_message) )
{
multi_message_input_sub(key);
continue;
}
if ( (Game_mode & GM_MULTI) && (multi_sending_message || multi_defining_message) )
{
multi_message_input_sub(key);
return;
}
#endif
#ifndef RELEASE
#ifdef NETWORK
if ((key&KEY_DEBUGGED)&&(Game_mode&GM_MULTI)) {
Network_message_reciever = 100; // Send to everyone...
sprintf( Network_message, "%s %s", TXT_I_AM_A, TXT_CHEATER);
}
#endif
#endif
if (Player_is_dead)
HandleDeathKey(key);
if (Endlevel_sequence)
HandleEndlevelKey(key);
else if (Newdemo_state == ND_STATE_PLAYBACK ) {
HandleDemoKey(key);
#ifndef RELEASE
#ifdef NETWORK
if ((key&KEY_DEBUGGED)&&(Game_mode&GM_MULTI)) {
Network_message_reciever = 100; // Send to everyone...
sprintf( Network_message, "%s %s", TXT_I_AM_A, TXT_CHEATER);
}
HandleTestKey(key);
#endif
} else {
FinalCheats(key);
HandleSystemKey(key);
HandleVRKey(key);
HandleGameKey(key);
#ifndef RELEASE
HandleTestKey(key);
#endif
if (Player_is_dead)
HandleDeathKey(key);
if (Endlevel_sequence)
HandleEndlevelKey(key);
else if (Newdemo_state == ND_STATE_PLAYBACK ) {
HandleDemoKey(key);
#ifndef RELEASE
HandleTestKey(key);
#endif
} else {
FinalCheats(key);
HandleSystemKey(key);
HandleVRKey(key);
HandleGameKey(key);
#ifndef RELEASE
HandleTestKey(key);
#endif
}
}
// if ((Players[Player_num].flags & PLAYER_FLAGS_CONVERTER) && keyd_pressed[KEY_F8] && (keyd_pressed[KEY_LALT] || keyd_pressed[KEY_RALT]))
// transfer_energy_to_shield(key_down_time(KEY_F8));
}
}

View file

@ -1292,8 +1292,8 @@ void multi_message_input_sub(int key)
game_flush_inputs();
break;
default:
if (key > 0) {
int ascii = key_to_ascii(key);
{
int ascii = key_ascii();
if ((ascii < 255 ) && (ascii != 37)) {
if (multi_message_index < MAX_MESSAGE_LEN-2 ) {
Network_message[multi_message_index++] = ascii;

View file

@ -1264,7 +1264,7 @@ int newmenu_do4( char * title, char * subtitle, int nitems, newmenu_item * item,
item[choice].value--;
item[choice].text[item[choice].value] = 0;
} else {
ascii = key_to_ascii(k);
ascii = key_ascii();
if ((ascii < 255 ) && (item[choice].value < item[choice].text_len ))
{
int allowed;
@ -1289,7 +1289,7 @@ int newmenu_do4( char * title, char * subtitle, int nitems, newmenu_item * item,
}
else if ((item[choice].type!=NM_TYPE_INPUT) && (item[choice].type!=NM_TYPE_INPUT_MENU) )
{
ascii = key_to_ascii(k);
ascii = key_ascii();
if (ascii < 255 ) {
int choice1 = choice;
ascii = toupper(ascii);
@ -1804,8 +1804,8 @@ ReadFileNames:
break;
default:
if (key > 0) {
int ascii = key_to_ascii(key);
{
int ascii = key_ascii();
if ( ascii < 255 ) {
int cc,cc1;
cc=cc1=citem+1;
@ -2105,8 +2105,8 @@ int newmenu_listbox1( char * title, int nitems, char * items[], int allow_abort_
break;
default:
if (key > 0) {
int ascii = key_to_ascii(key);
{
int ascii = key_ascii();
if ( ascii < 255 ) {
int cc,cc1;
cc=cc1=citem+1;

View file

@ -143,7 +143,7 @@ void ui_inputbox_do( UI_GADGET_INPUTBOX * inputbox, int keypress )
if (inputbox->first_time) inputbox->first_time = 0;
break;
default:
ascii = key_to_ascii(keypress);
ascii = key_ascii();
if ((ascii < 255 ) && (inputbox->position < inputbox->length-2))
{
if (inputbox->first_time) {

View file

@ -195,7 +195,7 @@ int menu_match_keypress( MENU * menu, int keypress )
keypress &= 0xFF;
c = key_to_ascii(keypress);
c = key_ascii();
for (i=0; i< menu->NumItems; i++ )
{