/*
* Copyright (C) 2002-2010 The DOSBox Team
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: sdl_mapper.cpp,v 1.60 2009-06-01 10:25:51 qbix79 Exp $ */
#include <vector>
#include <list>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <assert.h>
#include "SDL.h"
#include "SDL_thread.h"
#include "dosbox.h"
#include "video.h"
#include "keyboard.h"
#include "joystick.h"
#include "support.h"
#include "mapper.h"
#include "setup.h"
enum {
CLR_BLACK=0,
CLR_WHITE=1,
CLR_RED=2,
CLR_BLUE=3,
CLR_GREEN=4
};
enum BB_Types {
BB_Next,BB_Add,BB_Del,
BB_Save,BB_Exit
};
enum BC_Types {
BC_Mod1,BC_Mod2,BC_Mod3,
BC_Hold
};
#define BMOD_Mod1 0x0001
#define BMOD_Mod2 0x0002
#define BMOD_Mod3 0x0004
#define BFLG_Hold 0x0001
#define BFLG_Repeat 0x0004
#define MAXSTICKS 8
#define MAXACTIVE 16
#define MAXBUTTON 32
#define MAXBUTTON_CAP 16
class CEvent;
class CHandlerEvent;
class CButton;
class CBind;
class CBindGroup;
static void SetActiveEvent(CEvent * event);
static void SetActiveBind(CBind * _bind);
extern Bit8u int10_font_14[256 * 14];
static std::vector<CEvent *> events;
static std::vector<CButton *> buttons;
static std::vector<CBindGroup *> bindgroups;
static std::vector<CHandlerEvent *> handlergroup;
typedef std::list<CBind *> CBindList;
typedef std::list<CEvent *>::iterator CEventList_it;
typedef std::list<CBind *>::iterator CBindList_it;
typedef std::vector<CButton *>::iterator CButton_it;
typedef std::vector<CEvent *>::iterator CEventVector_it;
typedef std::vector<CHandlerEvent *>::iterator CHandlerEventVector_it;
typedef std::vector<CBindGroup *>::iterator CBindGroup_it;
static CBindList holdlist;
class CEvent {
public:
CEvent(char const * const _entry) {
safe_strncpy(entry,_entry,16);
events.push_back(this);
bindlist.clear();
activity=0;
current_value=0;
}
void AddBind(CBind * bind);
virtual ~CEvent() {}
virtual void Active(bool yesno)=0;
virtual void ActivateEvent(bool ev_trigger,bool skip_action)=0;
virtual void DeActivateEvent(bool ev_trigger)=0;
void DeActivateAll(void);
void SetValue(Bits value){
current_value=value;
}
Bits GetValue(void) {
return current_value;
}
char * GetName(void) { return entry; }
virtual bool IsTrigger(void)=0;
CBindList bindlist;
protected:
Bitu activity;
char entry[16];
Bits current_value;
};
/* class for events which can be ON/OFF only: key presses, joystick buttons, joystick hat */
class CTriggeredEvent : public CEvent {
public:
CTriggeredEvent(char const * const _entry) : CEvent(_entry) {}
virtual bool IsTrigger(void) {
return true;
}
void ActivateEvent(bool ev_trigger,bool skip_action) {
if (current_value>25000) {
/* value exceeds boundary, trigger event if not active */
if (!activity && !skip_action) Active(true);
if (activity<32767) activity++;
} else {
if (activity>0) {
/* untrigger event if it is fully inactive */
DeActivateEvent(ev_trigger);
activity=0;
}
}
}
void DeActivateEvent(bool /*ev_trigger*/) {
activity--;
if (!activity) Active(false);
}
};
/* class for events which have a non-boolean state: joystick axis movement */
class CContinuousEvent : public CEvent {
public:
CContinuousEvent(char const * const _entry) : CEvent(_entry) {}
virtual bool IsTrigger(void) {
return false;
}
void ActivateEvent(bool ev_trigger,bool skip_action) {
if (ev_trigger) {
activity++;
if (!skip_action) Active(true);
} else {
/* test if no trigger-activity is present, this cares especially
about activity of the opposite-direction joystick axis for example */
if (!GetActivityCount()) Active(true);
}
}
void DeActivateEvent(bool ev_trigger) {
if (ev_trigger) {
if (activity>0) activity--;
if (activity==0) {
/* test if still some trigger-activity is present,
adjust the state in this case accordingly */
if (GetActivityCount()) RepostActivity();
else Active(false);
}
} else {
if (!GetActivityCount()) Active(false);
}
}
virtual Bitu GetActivityCount(void) {
return activity;
}
virtual void RepostActivity(void) {}
};
class CBind {
public:
virtual ~CBind () {
list->remove(this);
// event->bindlist.remove(this);
}
CBind(CBindList * _list) {
list=_list;
_list->push_back(this);
mods=flags=0;
event=0;
active=holding=false;
}
void AddFlags(char * buf) {
if (mods & BMOD_Mod1) strcat(buf," mod1");
if (mods & BMOD_Mod2) strcat(buf," mod2");
if (mods & BMOD_Mod3) strcat(buf," mod3");
if (flags & BFLG_Hold) strcat(buf," hold");
}
void SetFlags(char * buf) {
char * word;
while (*(word=StripWord(buf))) {
if (!strcasecmp(word,"mod1")) mods|=BMOD_Mod1;
if (!strcasecmp(word,"mod2")) mods|=BMOD_Mod2;
if (!strcasecmp(word,"mod3")) mods|=BMOD_Mod3;
if (!strcasecmp(word,"hold")) flags|=BFLG_Hold;
}
}
void ActivateBind(Bits _value,bool ev_trigger,bool skip_action=false) {
if (event->IsTrigger()) {
/* use value-boundary for on/off events */
if (_value>25000) {
event->SetValue(_value);
if (active) return;
event->ActivateEvent(ev_trigger,skip_action);
active=true;
} else {
if (active) {
event->DeActivateEvent(ev_trigger);
active=false;
}
}
} else {
/* store value for possible later use in the activated event */
event->SetValue(_value);
event->ActivateEvent(ev_trigger,false);
}
}
void DeActivateBind(bool ev_trigger) {
if (event->IsTrigger()) {
if (!active) return;
active=false;
if (flags & BFLG_Hold) {
if (!holding) {
holdlist.push_back(this);
holding=true;
return;
} else {
holdlist.remove(this);
holding=false;
}
}
event->DeActivateEvent(ev_trigger);
} else {
/* store value for possible later use in the activated event */
event->SetValue(0);
event->DeActivateEvent(ev_trigger);
}
}
virtual void ConfigName(char * buf)=0;
virtual void BindName(char * buf)=0;
Bitu mods,flags;
Bit16s value;
CEvent * event;
CBindList * list;
bool active,holding;
};
void CEvent::AddBind(CBind * bind) {
bindlist.push_front(bind);
bind->event=this;
}
void CEvent::DeActivateAll(void) {
for (CBindList_it bit=bindlist.begin();bit!=bindlist.end();bit++) {
(*bit)->DeActivateBind(true);
}
}
class CBindGroup {
public:
CBindGroup() {
bindgroups.push_back(this);
}
void ActivateBindList(CBindList * list,Bits value,bool ev_trigger);
void DeactivateBindList(CBindList * list,bool ev_trigger);
virtual CBind * CreateConfigBind(char *&buf)=0;
virtual CBind * CreateEventBind(SDL_Event * event)=0;
virtual bool CheckEvent(SDL_Event * event)=0;
virtual const char * ConfigStart(void)=0;
virtual const char * BindStart(void)=0;
virtual ~CBindGroup (void) { }
protected:
};
#define MAX_SDLKEYS 323
static bool usescancodes;
static Bit8u scancode_map[MAX_SDLKEYS];
#define Z SDLK_UNKNOWN
#if defined (MACOSX)
static SDLKey sdlkey_map[]={
/* Main block printables */
/*00-05*/ SDLK_a, SDLK_s, SDLK_d, SDLK_f, SDLK_h, SDLK_g,
/*06-0B*/ SDLK_z, SDLK_x, SDLK_c, SDLK_v, SDLK_WORLD_0, SDLK_b,
/*0C-11*/ SDLK_q, SDLK_w, SDLK_e, SDLK_r, SDLK_y, SDLK_t,
/*12-17*/ SDLK_1, SDLK_2, SDLK_3, SDLK_4, SDLK_6, SDLK_5,
/*18-1D*/ SDLK_EQUALS, SDLK_9, SDLK_7, SDLK_MINUS, SDLK_8, SDLK_0,
/*1E-21*/ SDLK_RIGHTBRACKET, SDLK_o, SDLK_u, S
- 1
- 2
前往页