doomgeneric/fbdoom/i_input_sdl.c
2017-12-11 07:31:25 +01:00

408 lines
10 KiB
C

//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// DESCRIPTION:
// DOOM graphics stuff for SDL.
//
#include "SDL/SDL.h"
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#include "config.h"
#include "deh_str.h"
#include "doomtype.h"
#include "doomkeys.h"
#include "i_joystick.h"
#include "i_system.h"
#include "i_swap.h"
#include "i_timer.h"
#include "i_video.h"
#include "i_scale.h"
#include "m_argv.h"
#include "m_config.h"
#include "m_misc.h"
#include "tables.h"
#include "v_video.h"
#include "w_wad.h"
#include "z_zone.h"
// SDL surface for the screen.
static SDL_Surface *screen;
// If true, keyboard mapping is ignored, like in Vanilla Doom.
// The sensible thing to do is to disable this if you have a non-US
// keyboard.
int vanilla_keyboard_mapping = true;
// Is the shift key currently down?
static int shiftdown = 0;
// Lookup table for mapping ASCII characters to their equivalent when
// shift is pressed on an American layout keyboard:
static const char shiftxform[] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
31, ' ', '!', '"', '#', '$', '%', '&',
'"', // shift-'
'(', ')', '*', '+',
'<', // shift-,
'_', // shift--
'>', // shift-.
'?', // shift-/
')', // shift-0
'!', // shift-1
'@', // shift-2
'#', // shift-3
'$', // shift-4
'%', // shift-5
'^', // shift-6
'&', // shift-7
'*', // shift-8
'(', // shift-9
':',
':', // shift-;
'<',
'+', // shift-=
'>', '?', '@',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'[', // shift-[
'!', // shift-backslash - OH MY GOD DOES WATCOM SUCK
']', // shift-]
'"', '_',
'\'', // shift-`
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'{', '|', '}', '~', 127
};
//
// Translates the SDL key
//
static int TranslateKey(SDL_keysym *sym)
{
switch(sym->sym)
{
case SDLK_LEFT: return KEY_LEFTARROW;
case SDLK_RIGHT: return KEY_RIGHTARROW;
case SDLK_DOWN: return KEY_DOWNARROW;
case SDLK_UP: return KEY_UPARROW;
case SDLK_ESCAPE: return KEY_ESCAPE;
case SDLK_RETURN: return KEY_ENTER;
case SDLK_TAB: return KEY_TAB;
case SDLK_F1: return KEY_F1;
case SDLK_F2: return KEY_F2;
case SDLK_F3: return KEY_F3;
case SDLK_F4: return KEY_F4;
case SDLK_F5: return KEY_F5;
case SDLK_F6: return KEY_F6;
case SDLK_F7: return KEY_F7;
case SDLK_F8: return KEY_F8;
case SDLK_F9: return KEY_F9;
case SDLK_F10: return KEY_F10;
case SDLK_F11: return KEY_F11;
case SDLK_F12: return KEY_F12;
case SDLK_PRINT: return KEY_PRTSCR;
case SDLK_BACKSPACE: return KEY_BACKSPACE;
case SDLK_DELETE: return KEY_DEL;
case SDLK_PAUSE: return KEY_PAUSE;
#if !SDL_VERSION_ATLEAST(1, 3, 0)
case SDLK_EQUALS: return KEY_EQUALS;
#endif
case SDLK_MINUS: return KEY_MINUS;
case SDLK_LSHIFT:
case SDLK_RSHIFT:
return KEY_RSHIFT;
case SDLK_LCTRL:
case SDLK_RCTRL:
return KEY_RCTRL;
case SDLK_LALT:
case SDLK_RALT:
#if !SDL_VERSION_ATLEAST(1, 3, 0)
case SDLK_LMETA:
case SDLK_RMETA:
#endif
return KEY_RALT;
case SDLK_CAPSLOCK: return KEY_CAPSLOCK;
case SDLK_SCROLLOCK: return KEY_SCRLCK;
case SDLK_NUMLOCK: return KEY_NUMLOCK;
case SDLK_KP0: return KEYP_0;
case SDLK_KP1: return KEYP_1;
case SDLK_KP2: return KEYP_2;
case SDLK_KP3: return KEYP_3;
case SDLK_KP4: return KEYP_4;
case SDLK_KP5: return KEYP_5;
case SDLK_KP6: return KEYP_6;
case SDLK_KP7: return KEYP_7;
case SDLK_KP8: return KEYP_8;
case SDLK_KP9: return KEYP_9;
case SDLK_KP_PERIOD: return KEYP_PERIOD;
case SDLK_KP_MULTIPLY: return KEYP_MULTIPLY;
case SDLK_KP_PLUS: return KEYP_PLUS;
case SDLK_KP_MINUS: return KEYP_MINUS;
case SDLK_KP_DIVIDE: return KEYP_DIVIDE;
case SDLK_KP_EQUALS: return KEYP_EQUALS;
case SDLK_KP_ENTER: return KEYP_ENTER;
case SDLK_HOME: return KEY_HOME;
case SDLK_INSERT: return KEY_INS;
case SDLK_END: return KEY_END;
case SDLK_PAGEUP: return KEY_PGUP;
case SDLK_PAGEDOWN: return KEY_PGDN;
#ifdef SDL_HAVE_APP_KEYS
case SDLK_APP1: return KEY_F1;
case SDLK_APP2: return KEY_F2;
case SDLK_APP3: return KEY_F3;
case SDLK_APP4: return KEY_F4;
case SDLK_APP5: return KEY_F5;
case SDLK_APP6: return KEY_F6;
#endif
default:
return tolower(sym->sym);
}
}
// Get the equivalent ASCII (Unicode?) character for a keypress.
static int GetTypedChar(SDL_Event *event)
{
int key;
// If Vanilla keyboard mapping enabled, the keyboard
// scan code is used to give the character typed.
// This does not change depending on keyboard layout.
// If you have a German keyboard, pressing 'z' will
// give 'y', for example. It is desirable to be able
// to fix this so that people with non-standard
// keyboard mappings can type properly. If vanilla
// mode is disabled, use the properly translated
// version.
if (vanilla_keyboard_mapping)
{
key = TranslateKey(&event->key.keysym);
// Is shift held down? If so, perform a translation.
if (shiftdown > 0)
{
if (key >= 0 && key < arrlen(shiftxform))
{
key = shiftxform[key];
}
else
{
key = 0;
}
}
return key;
}
else
{
// Unicode value, from key layout.
return tolower(event->key.keysym.unicode);
}
}
static void UpdateShiftStatus(SDL_Event *event)
{
int change;
if (event->type == SDL_KEYDOWN)
{
change = 1;
}
else if (event->type == SDL_KEYUP)
{
change = -1;
}
else
{
return;
}
if (event->key.keysym.sym == SDLK_LSHIFT
|| event->key.keysym.sym == SDLK_RSHIFT)
{
shiftdown += change;
}
}
void I_GetEvent(void)
{
SDL_Event sdlevent;
event_t event;
// possibly not needed
SDL_PumpEvents();
// put event-grabbing stuff in here
while (SDL_PollEvent(&sdlevent))
{
if (sdlevent.type == SDL_QUIT)
{
I_Quit();
}
UpdateShiftStatus(&sdlevent);
// process event
switch (sdlevent.type)
{
case SDL_KEYDOWN:
// data1 has the key pressed, data2 has the character
// (shift-translated, etc)
event.type = ev_keydown;
event.data1 = TranslateKey(&sdlevent.key.keysym);
event.data2 = GetTypedChar(&sdlevent);
if (event.data1 != 0)
{
D_PostEvent(&event);
}
break;
case SDL_KEYUP:
event.type = ev_keyup;
event.data1 = TranslateKey(&sdlevent.key.keysym);
// data2 is just initialized to zero for ev_keyup.
// For ev_keydown it's the shifted Unicode character
// that was typed, but if something wants to detect
// key releases it should do so based on data1
// (key ID), not the printable char.
event.data2 = 0;
if (event.data1 != 0)
{
D_PostEvent(&event);
}
break;
/*
case SDL_MOUSEMOTION:
event.type = ev_mouse;
event.data1 = mouse_button_state;
event.data2 = AccelerateMouse(sdlevent.motion.xrel);
event.data3 = -AccelerateMouse(sdlevent.motion.yrel);
D_PostEvent(&event);
break;
*/
case SDL_QUIT:
event.type = ev_quit;
D_PostEvent(&event);
break;
case SDL_ACTIVEEVENT:
// need to update our focus state
//UpdateFocus();
break;
default:
break;
}
}
}
//void I_ShutdownGraphics(void)
//{
// //SDL_QuitSubSystem(SDL_INIT_VIDEO);
//}
//
// I_StartTic
//
void I_StartTic (void)
{
I_GetEvent();
}
void I_InitInput(void)
{
SDL_Event dummy;
byte *doompal;
char *env;
// Pass through the XSCREENSAVER_WINDOW environment variable to
// SDL_WINDOWID, to embed the SDL window into the Xscreensaver
// window.
env = getenv("XSCREENSAVER_WINDOW");
if (env != NULL)
{
char winenv[30];
int winid;
sscanf(env, "0x%x", &winid);
M_snprintf(winenv, sizeof(winenv), "SDL_WINDOWID=%i", winid);
putenv(winenv);
}
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
I_Error("Failed to initialize video: %s", SDL_GetError());
}
//UpdateFocus();
// We need SDL to give us translated versions of keys as well
SDL_EnableUNICODE(1);
// Repeat key presses - this is what Vanilla Doom does
// Not sure about repeat rate - probably dependent on which DOS
// driver is used. This is good enough though.
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
// clear out any events waiting at the start and center the mouse
while (SDL_PollEvent(&dummy));
}