Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
41 KB
Referenced Files
None
Subscribers
None
diff --git a/util/init.cpp b/util/init.cpp
index eacd3de4..030acf81 100644
--- a/util/init.cpp
+++ b/util/init.cpp
@@ -1,504 +1,502 @@
#ifdef USE_ALLEGRO
#include <allegro.h>
#ifdef ALLEGRO_WINDOWS
#include <winalleg.h>
#endif
#endif
#ifdef USE_ALLEGRO5
#include <allegro5/allegro.h>
#include <allegro5/allegro_image.h>
#endif
#ifdef USE_SDL
#include <SDL.h>
#endif
#ifndef WINDOWS
#include <signal.h>
#include <string.h>
#endif
#ifdef LINUX
#include <execinfo.h>
#endif
/* don't be a boring tuna */
// #warning you are ugly
#include "globals.h"
#include "init.h"
#include "network/network.h"
#include "thread.h"
#include <time.h>
#include <ostream>
#include "dumb/include/dumb.h"
#ifdef USE_ALLEGRO
#include "dumb/include/aldumb.h"
#include "loadpng/loadpng.h"
#include "gif/algif.h"
#endif
#include "bitmap.h"
#include "funcs.h"
#include "file-system.h"
#include "font.h"
#include "sound.h"
#include "configuration.h"
#include "script/script.h"
#include "music.h"
#include "loading.h"
#include "input/keyboard.h"
#ifdef WII
#include <fat.h>
#endif
using namespace std;
volatile int Global::speed_counter = 0;
/* enough seconds for 136 years */
volatile unsigned int Global::second_counter = 0;
/* the original engine was running at 90 ticks per second, but we dont
* need to render that fast, so TICS_PER_SECOND is really fps and
* LOGIC_MULTIPLIER will be used to adjust the speed counter to its
* original value.
*/
const int Global::TICS_PER_SECOND = 40;
const double Global::LOGIC_MULTIPLIER = (double) 90 / (double) Global::TICS_PER_SECOND;
#ifdef USE_ALLEGRO
const int Global::WINDOWED = GFX_AUTODETECT_WINDOWED;
const int Global::FULLSCREEN = GFX_AUTODETECT_FULLSCREEN;
#else
/* FIXME: use enums here or something */
const int Global::WINDOWED = 0;
const int Global::FULLSCREEN = 1;
#endif
/* game counter, controls FPS */
static void inc_speed_counter(){
/* probably put input polling here, InputManager::poll() */
Global::speed_counter += 1;
}
#ifdef USE_ALLEGRO
END_OF_FUNCTION( inc_speed_counter )
#endif
/* if you need to count seconds for some reason.. */
static void inc_second_counter() {
Global::second_counter += 1;
}
#ifdef USE_ALLEGRO
END_OF_FUNCTION( inc_second_counter )
#endif
#if !defined(WINDOWS) && !defined(WII) && !defined(MINPSPW) && !defined(PS3) && !defined(NDS)
#ifdef LINUX
static void print_stack_trace(){
/* use addr2line on these addresses to get a filename and line number */
void *trace[128];
int frames = backtrace(trace, 128);
printf("Stack trace\n");
for (int i = 0; i < frames; i++){
printf(" %p\n", trace[i]);
}
}
#endif
static void handleSigSegV(int i, siginfo_t * sig, void * data){
const char * message = "Bug! Caught a memory violation. Shutting down..\n";
int dont_care = write(1, message, 48);
dont_care = dont_care;
#ifdef LINUX
print_stack_trace();
#endif
// Global::shutdown_message = "Bug! Caught a memory violation. Shutting down..";
Bitmap::setGfxModeText();
#ifdef USE_ALLEGRO
allegro_exit();
#endif
#ifdef USE_SDL
SDL_Quit();
#endif
/* write to a log file or something because sigsegv shouldn't
* normally happen.
*/
exit(1);
}
#else
#endif
/* catch a socket being closed prematurely on unix */
#if !defined(WINDOWS) && !defined(WII) && !defined(MINPSPW) && !defined(PS3) && !defined(NDS)
static void handleSigPipe( int i, siginfo_t * sig, void * data ){
}
/*
static void handleSigUsr1( int i, siginfo_t * sig, void * data ){
pthread_exit( NULL );
}
*/
#endif
static void registerSignals(){
#if !defined(WINDOWS) && !defined(WII) && !defined(MINPSPW) && !defined(PS3) && !defined(NDS)
struct sigaction action;
memset( &action, 0, sizeof(struct sigaction) );
action.sa_sigaction = handleSigPipe;
sigaction( SIGPIPE, &action, NULL );
memset( &action, 0, sizeof(struct sigaction) );
action.sa_sigaction = handleSigSegV;
sigaction( SIGSEGV, &action, NULL );
/*
action.sa_sigaction = handleSigUsr1;
sigaction( SIGUSR1, &action, NULL );
*/
#endif
}
/* should probably call the janitor here or something */
static void close_paintown(){
Music::pause();
Bitmap::setGfxModeText();
#ifdef USE_ALLEGRO
allegro_exit();
#endif
exit(0);
}
namespace Global{
extern int do_shutdown;
}
static void close_window(){
/* when do_shutdown is 1 the game will attempt to throw ShutdownException
* wherever it is. If the game is stuck or the code doesn't throw
* ShutdownException then when the user tries to close the window
* twice we just forcifully shutdown.
*/
Global::do_shutdown += 1;
if (Global::do_shutdown == 2){
close_paintown();
}
}
#ifdef USE_ALLEGRO
END_OF_FUNCTION(close_window)
#endif
#ifdef USE_ALLEGRO5
struct TimerInfo{
TimerInfo(void (*x)(), ALLEGRO_TIMER * y):
tick(x), timer(y){}
void (*tick)();
ALLEGRO_TIMER * timer;
};
static void * do_timer(void * info){
TimerInfo * timerInfo = (TimerInfo*) info;
ALLEGRO_EVENT_SOURCE * source = al_get_timer_event_source(timerInfo->timer);
ALLEGRO_EVENT_QUEUE * queue = al_create_event_queue();
al_register_event_source(queue, source);
while (true){
ALLEGRO_EVENT event;
al_wait_for_event(queue, &event);
timerInfo->tick();
}
al_destroy_event_queue(queue);
al_destroy_timer(timerInfo->timer);
delete timerInfo;
}
static Util::Thread::Id start_timer(void (*func)(), int frequency){
ALLEGRO_TIMER * timer = al_create_timer(ALLEGRO_BPS_TO_SECS(frequency));
if (timer == NULL){
Global::debug(0) << "Could not create timer" << endl;
}
al_start_timer(timer);
TimerInfo * info = new TimerInfo(func, timer);
Util::Thread::Id thread;
Util::Thread::createThread(&thread, NULL, (Util::Thread::ThreadFunction) do_timer, (void*) info);
return thread;
}
static void initSystem(ostream & out){
out << "Allegro5 initialize " << (al_init() ? "Ok" : "Failed") << endl;
uint32_t version = al_get_allegro_version();
int major = version >> 24;
int minor = (version >> 16) & 255;
int revision = (version >> 8) & 255;
int release = version & 255;
out << "Allegro5 version " << major << "." << minor << "." << revision << "." << release << endl;
al_init_image_addon();
al_install_keyboard();
al_set_app_name("Paintown");
start_timer(inc_speed_counter, Global::TICS_PER_SECOND);
// start_timer(inc_second_counter, 1);
}
#endif
#ifdef USE_ALLEGRO
static void initSystem(ostream & out){
out << "Allegro version: " << ALLEGRO_VERSION_STR << endl;
out << "Allegro init: " <<allegro_init()<<endl;
out << "Install timer: " <<install_timer()<<endl;
/* png */
loadpng_init();
algif_init();
out<<"Install keyboard: "<<install_keyboard()<<endl;
/* do we need the mouse?? */
// out<<"Install mouse: "<<install_mouse()<<endl;
out<<"Install joystick: "<<install_joystick(JOY_TYPE_AUTODETECT)<<endl;
/* 16 bit color depth */
set_color_depth(16);
LOCK_VARIABLE( speed_counter );
LOCK_VARIABLE( second_counter );
LOCK_FUNCTION( (void *)inc_speed_counter );
LOCK_FUNCTION( (void *)inc_second_counter );
/* set up the timers */
out<<"Install game timer: "<< install_int_ex(inc_speed_counter, BPS_TO_TIMER(Global::TICS_PER_SECOND))<<endl;
out<<"Install second timer: "<<install_int_ex(inc_second_counter, BPS_TO_TIMER(1))<<endl;
/* keep running in the background */
set_display_switch_mode(SWITCH_BACKGROUND);
/* close window when the X is pressed */
LOCK_FUNCTION(close_window);
set_close_button_callback(close_window);
}
#endif
#ifdef USE_SDL
// static pthread_t events;
struct TimerInfo{
TimerInfo(void (*x)(), int y):
tick(x), frequency(y){}
void (*tick)();
int frequency;
};
static void * do_timer(void * arg){
TimerInfo info = *(TimerInfo *) arg;
uint32_t delay = (uint32_t)(1000.0 / (double) info.frequency);
/* assuming SDL_GetTicks() starts at 0, this should last for about 50 days
* before overflowing. overflow should work out fine. Assuming activate occurs
* when the difference between now and ticks is at least 6, the following will happen.
* ticks now now-ticks
* 4294967294 4294967294 0
* 4294967294 4294967295 1
* 4294967294 0 2
* 4294967294 1 3
* 4294967294 2 4
* 4294967294 3 5
* 4294967294 4 6
* Activate
* 3 5 2
* 3 6 3
* 3 7 4
* 3 8 5
* 3 9 6
* Activate
*
* Can 'now' ever be much larger than 'ticks' due to overflow?
* It doesn't seem like it.
*/
uint32_t ticks = SDL_GetTicks();
/* TODO: pass in some variable that tells this loop to quit */
while (true){
uint32_t now = SDL_GetTicks();
while (now - ticks >= delay){
// Global::debug(0) << "Tick!" << endl;
info.tick();
ticks += delay;
}
SDL_Delay(1);
}
delete (TimerInfo *) arg;
return NULL;
}
static Util::Thread::Id start_timer(void (*func)(), int frequency){
TimerInfo * speed = new TimerInfo(func, frequency);
/*
speed.tick = func;
speed.frequency = frequency;
*/
Util::Thread::Id thread;
Util::Thread::createThread(&thread, NULL, (Util::Thread::ThreadFunction) do_timer, (void*) speed);
return thread;
}
#if 0
static void * handleEvents(void * arg){
bool done = false;
while (!done){
SDL_Event event;
int ok = SDL_WaitEvent(&event);
if (ok){
switch (event.type){
case SDL_QUIT : {
done = true;
close_window();
break;
}
default : {
// Global::debug(0) << "Ignoring SDL event " << event.type << endl;
break;
}
}
}
}
return NULL;
}
#endif
/*
static void doSDLQuit(){
SDL_Event quit;
quit.type = SDL_QUIT;
SDL_PushEvent(&quit);
Global::debug(0) << "Waiting for SDL event handler to finish" << endl;
pthread_join(events, NULL);
SDL_Quit();
}
*/
static void initSystem(ostream & out){
out << "SDL Init: ";
int ok = SDL_Init(SDL_INIT_VIDEO |
SDL_INIT_AUDIO |
SDL_INIT_TIMER |
SDL_INIT_JOYSTICK |
SDL_INIT_NOPARACHUTE);
if (ok == 0){
out << "Ok" << endl;
} else {
out << "Failed (" << ok << ") - " << SDL_GetError() << endl;
exit(ok);
}
/* Just do SDL thread init
#ifdef MINPSPW
pthread_init();
#endif
*/
start_timer(inc_speed_counter, Global::TICS_PER_SECOND);
start_timer(inc_second_counter, 1);
try{
SDL_Surface * icon = SDL_LoadBMP(Filesystem::find(Filesystem::RelativePath("menu/icon.bmp")).path().c_str());
if (icon != NULL){
SDL_WM_SetIcon(icon, NULL);
}
} catch (const Filesystem::NotFound & failed){
Global::debug(0) << "Could not find window icon: " << failed.getTrace() << endl;
}
SDL_WM_SetCaption("Paintown", NULL);
SDL_EnableUNICODE(1);
SDL_JoystickEventState(1);
atexit(SDL_Quit);
// atexit(doSDLQuit);
}
#endif
bool Global::init(int gfx){
ostream & out = Global::debug( 0 );
out << "-- BEGIN init --" << endl;
out << "Data path is " << Util::getDataPath2().path() << endl;
out << "Paintown version " << Global::getVersionString() << endl;
out << "Build date " << __DATE__ << " " << __TIME__ << endl;
#ifdef WII
fatInitDefault();
#endif
/* do implementation specific setup */
initSystem(out);
dumb_register_stdfiles();
Sound::initialize();
Filesystem::initialize();
Bitmap::SCALE_X = GFX_X;
Bitmap::SCALE_Y = GFX_Y;
Configuration::loadConfigurations();
const int sx = Configuration::getScreenWidth();
const int sy = Configuration::getScreenHeight();
if (gfx == -1){
gfx = Configuration::getFullscreen() ? Global::FULLSCREEN : Global::WINDOWED;
} else {
Configuration::setFullscreen(gfx == Global::FULLSCREEN);
}
/* set up the screen */
int gfxCode = Bitmap::setGraphicsMode(gfx, sx, sy);
if (gfxCode == 0){
out << "Set graphics mode: Ok" << endl;
} else {
out << "Set graphics mode: Failed! (" << gfxCode << ")" << endl;
return false;
}
/* music */
atexit(&dumb_exit);
- Keyboard::disableKeyRepeat();
-
out << "Initialize random number generator" << endl;
/* initialize random number generator */
srand(time(NULL));
registerSignals();
#ifdef HAVE_NETWORKING
out << "Initialize network" << endl;
Network::init();
atexit(Network::closeAll);
#endif
/* this mutex is used to show the loading screen while the game loads */
// Util::Thread::initializeLock(&Loader::loading_screen_mutex);
out << "-- END init --" << endl;
/*
const Font & font = Font::getDefaultFont();
// font.setSize(30, 30);
Bitmap temp(font.textLength("Loading") + 1, font.getHeight("Loading") + 1);
font.printf(0, 0, Bitmap::makeColor(255, 255, 255), temp, "Loading", 0);
temp.BlitToScreen(sx / 2, sy / 2);
*/
Bitmap white(sx, sy);
white.fill(Bitmap::makeColor(255, 255, 255));
white.BlitToScreen();
return true;
}
diff --git a/util/input/keyboard.cpp b/util/input/keyboard.cpp
index a60f14cb..12f309b7 100644
--- a/util/input/keyboard.cpp
+++ b/util/input/keyboard.cpp
@@ -1,403 +1,432 @@
#ifdef USE_ALLEGRO
#include "allegro/keyboard.cpp"
#endif
#ifdef USE_SDL
#include "sdl/keyboard.cpp"
#endif
#ifdef USE_ALLEGRO5
#include "allegro5/keyboard.cpp"
#endif
+std::vector<bool> Keyboard::repeatState;
bool Keyboard::isNumber( int key ){
return key == Key_0 ||
key == Key_1 ||
key == Key_2 ||
key == Key_3 ||
key == Key_4 ||
key == Key_5 ||
key == Key_6 ||
key == Key_7 ||
key == Key_8 ||
key == Key_9;
}
bool Keyboard::isChar( int key ){
return key == Key_A ||
key == Key_B ||
key == Key_C ||
key == Key_D ||
key == Key_E ||
key == Key_F ||
key == Key_G ||
key == Key_H ||
key == Key_I ||
key == Key_J ||
key == Key_K ||
key == Key_L ||
key == Key_M ||
key == Key_N ||
key == Key_O ||
key == Key_P ||
key == Key_Q ||
key == Key_R ||
key == Key_S ||
key == Key_T ||
key == Key_U ||
key == Key_V ||
key == Key_W ||
key == Key_X ||
key == Key_Y ||
key == Key_Z ||
key == Key_MINUS;
}
bool Keyboard::isAlpha( int key ){
return isNumber( key ) || isChar( key );
}
const char * Keyboard::keyToName( int key ){
switch ( key ){
case Keyboard::Key_A : return "A";
case Keyboard::Key_B : return "B";
case Keyboard::Key_C : return "C";
case Keyboard::Key_D : return "D";
case Keyboard::Key_E : return "E";
case Keyboard::Key_F : return "F";
case Keyboard::Key_G : return "G";
case Keyboard::Key_H : return "H";
case Keyboard::Key_I : return "I";
case Keyboard::Key_J : return "J";
case Keyboard::Key_K : return "K";
case Keyboard::Key_L : return "L";
case Keyboard::Key_M : return "M";
case Keyboard::Key_N : return "N";
case Keyboard::Key_O : return "O";
case Keyboard::Key_P : return "P";
case Keyboard::Key_Q : return "Q";
case Keyboard::Key_R : return "R";
case Keyboard::Key_S : return "S";
case Keyboard::Key_T : return "T";
case Keyboard::Key_U : return "U";
case Keyboard::Key_V : return "V";
case Keyboard::Key_W : return "W";
case Keyboard::Key_X : return "X";
case Keyboard::Key_Y : return "Y";
case Keyboard::Key_Z : return "Z";
case Keyboard::Key_0 : return "0";
case Keyboard::Key_1 : return "1";
case Keyboard::Key_2 : return "2";
case Keyboard::Key_3 : return "3";
case Keyboard::Key_4 : return "4";
case Keyboard::Key_5 : return "5";
case Keyboard::Key_6 : return "6";
case Keyboard::Key_7 : return "7";
case Keyboard::Key_8 : return "8";
case Keyboard::Key_9 : return "9";
case Keyboard::Key_0_PAD : return "0_PAD";
case Keyboard::Key_1_PAD : return "1_PAD";
case Keyboard::Key_2_PAD : return "2_PAD";
case Keyboard::Key_3_PAD : return "3_PAD";
case Keyboard::Key_4_PAD : return "4_PAD";
case Keyboard::Key_5_PAD : return "5_PAD";
case Keyboard::Key_6_PAD : return "6_PAD";
case Keyboard::Key_7_PAD : return "7_PAD";
case Keyboard::Key_8_PAD : return "8_PAD";
case Keyboard::Key_9_PAD : return "9_PAD";
case Keyboard::Key_F1 : return "F1";
case Keyboard::Key_F2 : return "F2";
case Keyboard::Key_F3 : return "F3";
case Keyboard::Key_F4 : return "F4";
case Keyboard::Key_F5 : return "F5";
case Keyboard::Key_F6 : return "F6";
case Keyboard::Key_F7 : return "F7";
case Keyboard::Key_F8 : return "F8";
case Keyboard::Key_F9 : return "F9";
case Keyboard::Key_F10 : return "F10";
case Keyboard::Key_F11 : return "F11";
case Keyboard::Key_F12 : return "F12";
case Keyboard::Key_ESC : return "ESC";
case Keyboard::Key_TILDE : return "~";
case Keyboard::Key_MINUS : return "-";
case Keyboard::Key_EQUALS : return "=";
case Keyboard::Key_BACKSPACE : return "BACKSPACE";
case Keyboard::Key_TAB : return "TAB";
case Keyboard::Key_OPENBRACE : return "OPENBRACE";
case Keyboard::Key_CLOSEBRACE : return "CLOSEBRACE";
case Keyboard::Key_ENTER : return "ENTER";
case Keyboard::Key_COLON : return "COLON";
case Keyboard::Key_QUOTE : return "QUOTE";
case Keyboard::Key_BACKSLASH : return "BACKSLASH";
case Keyboard::Key_BACKSLASH2 : return "BACKSLASH2";
case Keyboard::Key_COMMA : return "COMMA";
case Keyboard::Key_STOP : return ".";
case Keyboard::Key_SLASH : return "SLASH";
case Keyboard::Key_SPACE : return "SPACE";
case Keyboard::Key_INSERT : return "INSERT";
case Keyboard::Key_DEL : return "DEL";
case Keyboard::Key_HOME : return "HOME";
case Keyboard::Key_END : return "END";
case Keyboard::Key_PGUP : return "PGUP";
case Keyboard::Key_PGDN : return "PGDN";
case Keyboard::Key_LEFT : return "LEFT";
case Keyboard::Key_RIGHT : return "RIGHT";
case Keyboard::Key_UP : return "UP";
case Keyboard::Key_DOWN : return "DOWN";
case Keyboard::Key_SLASH_PAD : return "SLASH_PAD";
case Keyboard::Key_ASTERISK : return "ASTERISK";
case Keyboard::Key_MINUS_PAD : return "MINUS_PAD";
case Keyboard::Key_PLUS_PAD : return "PLUS_PAD";
case Keyboard::Key_DEL_PAD : return "DEL_PAD";
case Keyboard::Key_ENTER_PAD : return "ENTER_PAD";
case Keyboard::Key_PRTSCR : return "PRTSCR";
case Keyboard::Key_PAUSE : return "PAUSE";
case Keyboard::Key_ABNT_C1 : return "ABNT_C1";
case Keyboard::Key_YEN : return "YEN";
case Keyboard::Key_KANA : return "KANA";
case Keyboard::Key_CONVERT : return "CONVERT";
case Keyboard::Key_NOCONVERT : return "NOCONVERT";
case Keyboard::Key_AT : return "AT";
case Keyboard::Key_CIRCUMFLEX : return "CIRCUMFLEX";
case Keyboard::Key_COLON2 : return "COLON2";
case Keyboard::Key_KANJI : return "KANJI";
case Keyboard::Key_EQUALS_PAD : return "EQUALS_PAD";
case Keyboard::Key_BACKQUOTE : return "BACKQUOTE";
case Keyboard::Key_SEMICOLON : return "SEMICOLON";
case Keyboard::Key_COMMAND : return "COMMAND";
/*
case Keyboard::Key_UNKNOWN1 : return "UNKNOWN1";
case Keyboard::Key_UNKNOWN2 : return "UNKNOWN2";
case Keyboard::Key_UNKNOWN3 : return "UNKNOWN3";
case Keyboard::Key_UNKNOWN4 : return "UNKNOWN4";
case Keyboard::Key_UNKNOWN5 : return "UNKNOWN5";
case Keyboard::Key_UNKNOWN6 : return "UNKNOWN6";
case Keyboard::Key_UNKNOWN7 : return "UNKNOWN7";
case Keyboard::Key_UNKNOWN8 : return "UNKNOWN8";
*/
// case Keyboard::Key_MODIFIERS : return "MODIFIERS";
case Keyboard::Key_LSHIFT : return "LSHIFT";
case Keyboard::Key_RSHIFT : return "RSHIFT";
case Keyboard::Key_LCONTROL : return "LCONTROL";
case Keyboard::Key_RCONTROL : return "RCONTROL";
case Keyboard::Key_ALT : return "ALT";
case Keyboard::Key_ALTGR : return "ALTGR";
case Keyboard::Key_LWIN : return "LWIN";
case Keyboard::Key_RWIN : return "RWIN";
case Keyboard::Key_MENU : return "MENU";
case Keyboard::Key_SCRLOCK : return "SCRLOCK";
case Keyboard::Key_NUMLOCK : return "NUMLOCK";
case Keyboard::Key_CAPSLOCK : return "CAPSLOCK";
default : return "Unknown key";
}
}
void Keyboard::setDelay( const int key, const int delay ){
key_delay[ key ] = delay;
}
void Keyboard::setAllDelay( const int delay ){
setDelay( Key_A, delay );
setDelay( Key_B, delay );
setDelay( Key_C, delay );
setDelay( Key_D, delay );
setDelay( Key_E, delay );
setDelay( Key_F, delay );
setDelay( Key_G, delay );
setDelay( Key_H, delay );
setDelay( Key_I, delay );
setDelay( Key_J, delay );
setDelay( Key_K, delay );
setDelay( Key_L, delay );
setDelay( Key_M, delay );
setDelay( Key_N, delay );
setDelay( Key_O, delay );
setDelay( Key_P, delay );
setDelay( Key_Q, delay );
setDelay( Key_R, delay );
setDelay( Key_S, delay );
setDelay( Key_T, delay );
setDelay( Key_U, delay );
setDelay( Key_V, delay );
setDelay( Key_W, delay );
setDelay( Key_X, delay );
setDelay( Key_Y, delay );
setDelay( Key_Z, delay );
setDelay( Key_0, delay );
setDelay( Key_1, delay );
setDelay( Key_2, delay );
setDelay( Key_3, delay );
setDelay( Key_4, delay );
setDelay( Key_5, delay );
setDelay( Key_6, delay );
setDelay( Key_7, delay );
setDelay( Key_8, delay );
setDelay( Key_9, delay );
setDelay( Key_0_PAD, delay );
setDelay( Key_1_PAD, delay );
setDelay( Key_2_PAD, delay );
setDelay( Key_3_PAD, delay );
setDelay( Key_4_PAD, delay );
setDelay( Key_5_PAD, delay );
setDelay( Key_6_PAD, delay );
setDelay( Key_7_PAD, delay );
setDelay( Key_8_PAD, delay );
setDelay( Key_9_PAD, delay );
setDelay( Key_F1, delay );
setDelay( Key_F2, delay );
setDelay( Key_F3, delay );
setDelay( Key_F4, delay );
setDelay( Key_F5, delay );
setDelay( Key_F6, delay );
setDelay( Key_F7, delay );
setDelay( Key_F8, delay );
setDelay( Key_F9, delay );
setDelay( Key_F10, delay );
setDelay( Key_F11, delay );
setDelay( Key_F12, delay );
setDelay( Key_ESC, delay );
setDelay( Key_TILDE, delay );
setDelay( Key_MINUS, delay );
setDelay( Key_EQUALS, delay );
setDelay( Key_BACKSPACE, delay );
setDelay( Key_TAB, delay );
setDelay( Key_OPENBRACE, delay );
setDelay( Key_CLOSEBRACE, delay );
setDelay( Key_ENTER, delay );
setDelay( Key_COLON, delay );
setDelay( Key_QUOTE, delay );
setDelay( Key_BACKSLASH, delay );
setDelay( Key_BACKSLASH2, delay );
setDelay( Key_COMMA, delay );
setDelay( Key_STOP, delay );
setDelay( Key_SLASH, delay );
setDelay( Key_SPACE, delay );
setDelay( Key_INSERT, delay );
setDelay( Key_DEL, delay );
setDelay( Key_HOME, delay );
setDelay( Key_END, delay );
setDelay( Key_PGUP, delay );
setDelay( Key_PGDN, delay );
setDelay( Key_LEFT, delay );
setDelay( Key_RIGHT, delay );
setDelay( Key_UP, delay );
setDelay( Key_DOWN, delay );
setDelay( Key_SLASH_PAD, delay );
setDelay( Key_ASTERISK, delay );
setDelay( Key_MINUS_PAD, delay );
setDelay( Key_PLUS_PAD, delay );
setDelay( Key_DEL_PAD, delay );
setDelay( Key_ENTER_PAD, delay );
setDelay( Key_PRTSCR, delay );
setDelay( Key_PAUSE, delay );
setDelay( Key_ABNT_C1, delay );
setDelay( Key_YEN, delay );
setDelay( Key_KANA, delay );
setDelay( Key_CONVERT, delay );
setDelay( Key_NOCONVERT, delay );
setDelay( Key_AT, delay );
setDelay( Key_CIRCUMFLEX, delay );
setDelay( Key_COLON2, delay );
setDelay( Key_KANJI, delay );
setDelay( Key_EQUALS_PAD, delay );
setDelay( Key_BACKQUOTE, delay );
setDelay( Key_SEMICOLON, delay );
setDelay( Key_COMMAND, delay );
/*
setDelay( Key_UNKNOWN1, delay );
setDelay( Key_UNKNOWN2, delay );
setDelay( Key_UNKNOWN3, delay );
setDelay( Key_UNKNOWN4, delay );
setDelay( Key_UNKNOWN5, delay );
setDelay( Key_UNKNOWN6, delay );
setDelay( Key_UNKNOWN7, delay );
setDelay( Key_UNKNOWN8, delay );
*/
setDelay( Key_MODIFIERS, delay );
setDelay( Key_LSHIFT, delay );
setDelay( Key_RSHIFT, delay );
setDelay( Key_LCONTROL, delay );
setDelay( Key_RCONTROL, delay );
setDelay( Key_ALT, delay );
setDelay( Key_ALTGR, delay );
setDelay( Key_LWIN, delay );
setDelay( Key_RWIN, delay );
setDelay( Key_MENU, delay );
setDelay( Key_SCRLOCK, delay );
setDelay( Key_NUMLOCK, delay );
setDelay( Key_CAPSLOCK, delay );
}
void Keyboard::press(KeyType key, unicode_t unicode){
keyState[key].key = key;
keyState[key].unicode = unicode;
keyState[key].enabled = true;
// if (enableBuffer){
buffer.push_back(keyState[key]);
// }
/*
KeyData data(key, unicode, true);
for (std::vector<Observer>::iterator it = observers.begin(); it != observers.end(); it++){
Observer observer = (*it);
observer.callback(data, observer.extra);
}
*/
}
void Keyboard::release(KeyType key){
keyState[key].enabled = false;
buffer.push_back(keyState[key]);
/*
KeyData data(key, 0, false);
for (std::vector<Observer>::iterator it = observers.begin(); it != observers.end(); it++){
Observer observer = (*it);
observer.callback(data, observer.extra);
}
*/
}
void Keyboard::readBufferedKeys(std::vector<int> & keys){
for (std::vector<KeyData>::iterator it = buffer.begin(); it != buffer.end(); it++){
const KeyData & data = *it;
keys.push_back(data.key);
}
}
std::vector<Keyboard::KeyData> Keyboard::readData(){
std::vector<Keyboard::KeyData> out;
for (std::map<KeyType, KeyData>::iterator it = keyState.begin(); it != keyState.end(); it++){
KeyType key = it->first;
const KeyData & data = it->second;
if (data.enabled){
out.push_back(data);
}
}
return out;
}
std::vector<Keyboard::unicode_t> Keyboard::readText(){
std::vector<Keyboard::unicode_t> out;
for (std::map<KeyType, KeyData>::iterator it = keyState.begin(); it != keyState.end(); it++){
KeyType key = it->first;
const KeyData & data = it->second;
if (data.enabled){
out.push_back(data.unicode);
}
}
return out;
}
+
+void Keyboard::pushRepeatState(bool enabled){
+ if (enabled){
+ enableKeyRepeat();
+ } else {
+ disableKeyRepeat();
+ }
+ repeatState.push_back(enabled);
+}
+
+void Keyboard::popRepeatState(){
+ if (repeatState.size() > 0){
+ bool last = repeatState.back();
+ repeatState.pop_back();
+ bool enabled = true;
+ if (repeatState.size() > 0){
+ enabled = repeatState.back();
+ }
+
+ if (enabled != last){
+ if (enabled){
+ enableKeyRepeat();
+ } else {
+ disableKeyRepeat();
+ }
+ }
+ }
+}
/*
void Keyboard::addObserver(ObserverCallback observer, void * data){
observers.push_back(Observer(observer, data));
}
void Keyboard::removeObserver(ObserverCallback observer, void * data){
for (std::vector<Observer>::iterator it = observers.begin(); it != observers.end(); it++){
const Observer & what = *it;
if (what.callback == observer && what.extra == data){
observers.erase(it);
break;
}
}
}
*/
diff --git a/util/input/keyboard.h b/util/input/keyboard.h
index 3fe23c41..903fd6ec 100644
--- a/util/input/keyboard.h
+++ b/util/input/keyboard.h
@@ -1,264 +1,269 @@
#ifndef _paintown_keyboard_h
#define _paintown_keyboard_h
#include <map>
#include <vector>
#include <stdint.h>
/* handles allegro key[] array better than keypressed()
* and readkey()
*/
class Keyboard{
private:
Keyboard();
public:
friend class InputManager;
typedef const int KeyType;
typedef uint32_t unicode_t;
struct KeyData{
KeyData():
key(-1),
unicode(-1),
enabled(false){
}
KeyData(int key, unicode_t unicode, bool enabled):
key(key),
unicode(unicode),
enabled(enabled){
}
int key;
/* Converted to a unicode character in UTF-32 */
unicode_t unicode;
/* whether the key is being pressed */
bool enabled;
};
/*
typedef void (*ObserverCallback)(const KeyData & data, void * extra);
struct Observer{
Observer():
callback(NULL),
extra(NULL){
}
Observer(ObserverCallback callback, void * extra):
callback(callback),
extra(extra){
}
ObserverCallback callback;
void * extra;
};
*/
/* poll:
* Put the keys in Allegro's key[] array into our map of int -> bool
*/
void poll();
/* wait for all keys to be released */
void wait();
/* []:
* Extract a boolean value given a key number
*/
#if 0
inline bool operator[] ( const int i ){
/* if the key has been pressed for the first time return true */
if ( my_keys[ i ] < 0 ){
my_keys[ i ] = 1;
return true;
}
bool b = my_keys[ i ] > key_delay[ i ];
if ( b ){
my_keys[ i ] = 1;
}
return b;
}
#endif
/* keypressed:
* Returns true if a key is pressed
*/
bool keypressed();
/* readKeys:
* Store all pressed keys in a user supplied vector
*/
void readKeys(std::vector< int > & all_keys);
void readBufferedKeys(std::vector<int> & keys);
std::vector<KeyData> readData();
std::vector<unicode_t> readText();
// int readKey();
void clear();
-
- static void disableKeyRepeat();
- static void enableKeyRepeat();
+
+ /* sets the latest repeat state. popping the state restores the previous state */
+ static void pushRepeatState(bool enabled);
+ static void popRepeatState();
void setDelay( const int key, const int delay );
void setAllDelay( const int delay );
inline const std::vector<KeyData> & getBufferedKeys() const {
return buffer;
}
static const char * keyToName( int key );
static bool isNumber( int key );
static bool isChar( int key );
static bool isAlpha( int key );
static KeyType Key_A;
static KeyType Key_B;
static KeyType Key_C;
static KeyType Key_D;
static KeyType Key_E;
static KeyType Key_F;
static KeyType Key_G;
static KeyType Key_H;
static KeyType Key_I;
static KeyType Key_J;
static KeyType Key_K;
static KeyType Key_L;
static KeyType Key_M;
static KeyType Key_N;
static KeyType Key_O;
static KeyType Key_P;
static KeyType Key_Q;
static KeyType Key_R;
static KeyType Key_S;
static KeyType Key_T;
static KeyType Key_U;
static KeyType Key_V;
static KeyType Key_W;
static KeyType Key_X;
static KeyType Key_Y;
static KeyType Key_Z;
static KeyType Key_0;
static KeyType Key_1;
static KeyType Key_2;
static KeyType Key_3;
static KeyType Key_4;
static KeyType Key_5;
static KeyType Key_6;
static KeyType Key_7;
static KeyType Key_8;
static KeyType Key_9;
static KeyType Key_0_PAD;
static KeyType Key_1_PAD;
static KeyType Key_2_PAD;
static KeyType Key_3_PAD;
static KeyType Key_4_PAD;
static KeyType Key_5_PAD;
static KeyType Key_6_PAD;
static KeyType Key_7_PAD;
static KeyType Key_8_PAD;
static KeyType Key_9_PAD;
static KeyType Key_F1;
static KeyType Key_F2;
static KeyType Key_F3;
static KeyType Key_F4;
static KeyType Key_F5;
static KeyType Key_F6;
static KeyType Key_F7;
static KeyType Key_F8;
static KeyType Key_F9;
static KeyType Key_F10;
static KeyType Key_F11;
static KeyType Key_F12;
static KeyType Key_ESC;
static KeyType Key_TILDE;
static KeyType Key_MINUS;
static KeyType Key_EQUALS;
static KeyType Key_BACKSPACE;
static KeyType Key_TAB;
static KeyType Key_OPENBRACE;
static KeyType Key_CLOSEBRACE;
static KeyType Key_ENTER;
static KeyType Key_COLON;
static KeyType Key_QUOTE;
static KeyType Key_BACKSLASH;
static KeyType Key_BACKSLASH2;
static KeyType Key_COMMA;
static KeyType Key_STOP;
static KeyType Key_SLASH;
static KeyType Key_SPACE;
static KeyType Key_INSERT;
static KeyType Key_DEL;
static KeyType Key_HOME;
static KeyType Key_END;
static KeyType Key_PGUP;
static KeyType Key_PGDN;
static KeyType Key_LEFT;
static KeyType Key_RIGHT;
static KeyType Key_UP;
static KeyType Key_DOWN;
static KeyType Key_SLASH_PAD;
static KeyType Key_ASTERISK;
static KeyType Key_MINUS_PAD;
static KeyType Key_PLUS_PAD;
static KeyType Key_DEL_PAD;
static KeyType Key_ENTER_PAD;
static KeyType Key_PRTSCR;
static KeyType Key_PAUSE;
static KeyType Key_ABNT_C1;
static KeyType Key_YEN;
static KeyType Key_KANA;
static KeyType Key_CONVERT;
static KeyType Key_NOCONVERT;
static KeyType Key_AT;
static KeyType Key_CIRCUMFLEX;
static KeyType Key_COLON2;
static KeyType Key_KANJI;
static KeyType Key_EQUALS_PAD;
static KeyType Key_BACKQUOTE;
static KeyType Key_SEMICOLON;
static KeyType Key_COMMAND;
/*
static KeyType Key_UNKNOWN1;
static KeyType Key_UNKNOWN2;
static KeyType Key_UNKNOWN3;
static KeyType Key_UNKNOWN4;
static KeyType Key_UNKNOWN5;
static KeyType Key_UNKNOWN6;
static KeyType Key_UNKNOWN7;
static KeyType Key_UNKNOWN8;
*/
static KeyType Key_MODIFIERS;
static KeyType Key_LSHIFT;
static KeyType Key_RSHIFT;
static KeyType Key_LCONTROL;
static KeyType Key_RCONTROL;
static KeyType Key_ALT;
static KeyType Key_ALTGR;
static KeyType Key_LWIN;
static KeyType Key_RWIN;
static KeyType Key_MENU;
static KeyType Key_SCRLOCK;
static KeyType Key_NUMLOCK;
static KeyType Key_CAPSLOCK;
void press(KeyType key, unicode_t unicode);
void release(KeyType key);
/*
virtual void addObserver(ObserverCallback observer, void * extra);
virtual void removeObserver(ObserverCallback observer, void * extra);
*/
protected:
+ static void disableKeyRepeat();
+ static void enableKeyRepeat();
+
// std::map<int,int> my_keys;
std::map<int,int> key_delay;
// std::vector<Observer> observers;
std::map<KeyType, KeyData> keyState;
std::vector<KeyData> buffer;
bool enableBuffer;
+ static std::vector<bool> repeatState;
};
#endif
diff --git a/util/input/text-input.cpp b/util/input/text-input.cpp
index 8a1412f6..4e3bcee0 100644
--- a/util/input/text-input.cpp
+++ b/util/input/text-input.cpp
@@ -1,210 +1,210 @@
#include "input-map.h"
#include "text-input.h"
#include "input-manager.h"
#include "keyboard.h"
#include <string.h>
#include <sstream>
#include <string>
using namespace std;
static const int Shift = 198;
static const int Control = 199;
static const int Backspace = 200;
TextInput::TextInput(const string & start):
InputMap<unsigned char>(),
blockingKeys(false),
enabled(false),
handle(201){
const int delay = 100;
/*
set(Keyboard::Key_TILDE, delay * 2, false, Toggle);
set(Keyboard::Key_ESC, delay, false, Esc);
set(Keyboard::Key_ENTER, 0, false, Enter);
*/
// set(Keyboard::Key_LCONTROL, 0, false, Control);
set(Keyboard::Key_BACKSPACE, delay, false, Backspace);
/*
set(Keyboard::Key_LSHIFT, 0, false, Shift);
set(Keyboard::Key_RSHIFT, 0, false, Shift);
*/
text.str(start);
text.rdbuf()->pubseekoff(0, ios_base::end, ios_base::out);
text.clear();
}
int TextInput::nextHandle(){
int i = handle;
handle += 1;
return i;
}
void TextInput::addBlockingHandle(int key, callback function, void * data){
int handle = nextHandle();
set(key, 1, true, handle);
callbacks[handle] = Callback(function, data);
}
void TextInput::addHandle(int key, int delay, callback function, void * data){
int handle = nextHandle();
set(key, delay, false, handle);
callbacks[handle] = Callback(function, data);
}
bool TextInput::doInput(){
bool modified = false;
/* TODO: ensure these codes are consistent across platforms. So far
* they seem to work in windows xp and linux (ubuntu)
*/
const Keyboard::unicode_t control_u = 21;
const Keyboard::unicode_t control_w = 23;
if (enabled){
vector<InputEvent> events = InputManager::getEvents(*this);
/* the order of reading input is arbitrary right now. I'm not
* sure it matters what order things are done in, but probably
* a few corner cases exist. When they come up please document them.
*/
for (vector<InputEvent>::iterator it = events.begin(); it != events.end(); it++){
InputEvent event = *it;
if (event.enabled){
if (event.out == Backspace){
backspace();
modified = true;
}
if (callbacks.find(event.out) != callbacks.end()){
Callback & callback = callbacks[event.out];
callback.function(callback.data);
}
if (event.unicode == control_u){
clearInput();
modified = true;
}
if (event.unicode == control_w){
deleteLastWord();
modified = true;
}
/* FIXME: whats the maximum unicode value? */
if (event.unicode >= 32 && event.unicode < 0xffffff){
this->text << (unsigned char) event.unicode;
modified = true;
}
}
}
}
return modified;
}
void TextInput::enable(){
InputManager::captureInput(*this);
enabled = true;
- Keyboard::enableKeyRepeat();
+ Keyboard::pushRepeatState(true);
}
void TextInput::disable(){
InputManager::releaseInput(*this);
enabled = false;
- Keyboard::disableKeyRepeat();
+ Keyboard::popRepeatState();
}
string TextInput::getText(){
return text.str();
}
/*
void TextInput::clear(){
text.str("");
text.clear();
}
*/
void TextInput::setText(const std::string & text){
this->text.str(text);
this->text.rdbuf()->pubseekoff(0, ios_base::end, ios_base::out);
this->text.clear();
}
void TextInput::clearInput(){
text.str(string());
text.rdbuf()->pubseekoff(0, ios_base::end, ios_base::out);
text.clear();
}
void TextInput::backspace(){
string now = text.str();
now = now.substr(0, now.size()-1);
text.str(now);
text.rdbuf()->pubseekoff(0, ios_base::end, ios_base::out);
text.clear();
}
void TextInput::deleteLastWord(){
string now = text.str();
// Global::debug(0) << "Delete last word '" << now << "'" << endl;
if (now.size() > 0){
if (now.at(now.size() - 1) != ' '){
int here = now.size() - 1;
while (here > 0 && now.at(here) != ' '){
here -= 1;
}
if (now.at(here) == ' '){
here += 1;
}
now.erase(here);
} else {
int here = now.size() - 1;
while (here > 0 && now.at(here) == ' '){
here -= 1;
}
if (here > 0){
while (here > 0 && now.at(here) != ' '){
here -= 1;
}
if (now.at(here) == ' '){
here += 1;
}
}
now.erase(here);
}
text.str(now);
text.rdbuf()->pubseekoff(0, ios_base::end, ios_base::out);
text.clear();
}
/*
size_t get = now.rfind(" ");
if (get != string::npos){
Global::debug(0) << "get " << get << " size " << now.size() << endl;
if (get == now.size() - 1){
get = now.find_last_not_of(' ');
get = now.rfind(' ', get);
if (get != string::npos){
get = 0;
}
now.erase(get + 1);
} else {
now = now.substr(0, get + 1);
}
text.str(now);
text.rdbuf()->pubseekoff(0, ios_base::end, ios_base::out);
text.clear();
} else {
clearInput();
}
*/
}
TextInput::~TextInput(){
disable();
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Jun 11, 11:24 AM (3 w, 4 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
68734
Default Alt Text
(41 KB)

Event Timeline