   SDL Text input
  I was looking for a better method of using input from the keyboard for text. I found rather shoddy and unusable examples everywhere that were of no use to me, so after a week or so of trial and error, I came up with my new method of text input:(You can ignore the function calls for all except Cinput->keyPressed() and SDL_GetTicks();These and most of the variables and keystate checks are for my console, which is implemented in my engine.)si8 Econsole::handleInput(){if(!initialized)return 0;ui8 * keys = Cinput->keys;keyTime = SDL_GetTicks();if(keyTime>=keyLastTime+100-keyLock||keyTime<keyLastTime){keyLastTime = keyTime;keyLock = 0;if(keys[SDLK_RETURN]||keys[SDLK_KP_ENTER]){submit();}else if(keys[SDLK_BACKSPACE]){backspace();}else if(keys[SDLK_DELETE]){del();}else if((keys[SDLK_LCTRL]||keys[SDLK_RCTRL])&&(keys[SDLK_EQUALS]||keys[SDLK_PLUS])){if(point<64)point++;}else if((keys[SDLK_LCTRL]||keys[SDLK_RCTRL])&&(keys[SDLK_MINUS]||keys[SDLK_UNDERSCORE])){if(point>1)point--;}else if(keys[SDLK_INSERT]){if(overType)overType = false;else overType = true;}else if(keys[SDLK_LEFT]){if(position==0)return 0;position--;}else if(keys[SDLK_RIGHT]){if(position==sizeof(line)-2||position+1>=strlen(currCmd))return 0;position++;}else if(keys[SDLK_UP]){if(currHist>=numLines)return 0;currHist++;while(lines[numLines-currHist][0]!='#'||!strcmp(lines[numLines-currHist],"#")){if(currHist>=numLines||numLines==0)return 0;currHist++;}for(ui32 i = 0;i<sizeof(line)*sizeof(si8);i++)currCmd='\0';if(currHist!=0)strcpy(currCmd,lines[numLines-currHist]);position = strlen(currCmd)-1;}else if(keys[SDLK_DOWN]){if(currHist==0)return 0;currHist--;if(currHist!=0){while(lines[numLines-currHist][0]!='#'||!strcmp(lines[numLines-currHist],"#")){currHist--;if(currHist==0){for(ui32 i = 0;i<sizeof(line)*sizeof(si8);i++)currCmd='\0';break;}}for(ui32 i = 0;i<sizeof(line)*sizeof(si8);i++)currCmd='\0';strcpy(currCmd,lines[numLines-currHist]);}else {for(ui32 i = 0;i<sizeof(line)*sizeof(si8);i++)currCmd='\0';}currCmd[0] = '#';position = strlen(currCmd)-1;}else if(keys[SDLK_PAGEUP]){if(((numLines-currScroll+1)*point+(numLines-currScroll+1)*(point/4))>y[1]) currScroll++;}else if(keys[SDLK_PAGEDOWN]){if(currScroll>0) currScroll--;}else if(keys[SDLK_END]){position = strlen(currCmd)-1;}else if(keys[SDLK_HOME]){position = 0;}else if(Cinput->keyPressed()&&position<sizeof(line)-2){appendChar(Cinput->decipherChar(Cgfx->event.key.keysym.sym));}else if(Cinput->keymods == 0)keyLock = 50;}return 1;}A more stripped down and less context specific implementation would be:unsigned int keyTime = 0, keyLastTime = 0, keyLock = 0;short keymods = 0;int handleInput(){ui8 * keys = SDL_GetKeyState(NULL);//Get key statekeyTime = SDL_GetTicks();//Get current timekeymods = (SDL_GetModState())-4096;//Get keymods stateif(keyTime>=keyLastTime+100-keyLock||keyTime<keyLastTime){//Check key timer. If no mods, check again in 50ms instead of 100ms.keyLastTime = keyTime;//Set last key time.keyLock = 0;//Set keymod delay to 0if(event.key.state==SDL_PRESSED){//If a key has been presseddoWhateverWithKey(event.key.keysym.sym);//Do stuff with it.}else if(keymods == 0)keyLock = 50;//If a key has not been pressed recently, and no mods, change delay from 100ms to 50ms.}return 0;}It works wonders for me. I hope it does for others too.[Edited by - Ectara on June 17, 2009 2:21:29 PM]
  Decided to rewrite the function in my engine, as I know that this was only a temporary thing, as people who type slow would be in peril. So I wrote this one.if(SDL_PollEvent(&gfx->event)){if(event.type == SDL_KEYDOWN || event.type == SDL_KEYUP){if(vent.type==SDL_KEYDOWN)keyState = EKEYDOWN;else if(event.type==SDL_KEYUP)keyState = EKEYUP;key = event.key.keysym.sym;if((keys[SDLK_RSHIFT]||keys[SDLK_LSHIFT])){switch(key){case SDLK_1:key = SDLK_EXCLAIM;break;case SDLK_2:key = SDLK_AT;break;case SDLK_3:key = SDLK_HASH;break;case SDLK_4:key = SDLK_DOLLAR;break;case SDLK_5:key = 37;/*MODULUS*/break;case SDLK_6:key = SDLK_CARET;break;case SDLK_7:key = SDLK_AMPERSAND;break;case SDLK_8:key = SDLK_ASTERISK;break;case SDLK_9:key = SDLK_LEFTPAREN;break;case SDLK_0:key = SDLK_RIGHTPAREN;break;case SDLK_MINUS:key = SDLK_UNDERSCORE;break;case SDLK_EQUALS:key = SDLK_PLUS;break;case SDLK_BACKQUOTE:key = 126;/*TILDE*/break;case SDLK_QUOTE:key = SDLK_QUOTEDBL;break;case SDLK_SEMICOLON:key = SDLK_COLON;break;case SDLK_COMMA:key = SDLK_LESS;break;case SDLK_PERIOD:key = SDLK_GREATER;break;case 47:/*FORWARDSLASH*/key = SDLK_QUESTION;break;case SDLK_BACKSLASH:key = 124;/*PIPE*/break;case SDLK_LEFTBRACKET:key = 123;/*LEFTBRACE*/break;case SDLK_RIGHTBRACKET:key = 125;/*RIGHTBRACE*/break;default:if(key>96&&key<123)key-=32;break;}}SDL_PumpEvents();}}else{SDL_PumpEvents();}Might look run-of-the-mill, but I cannot stress enough line 34:}SDL_PumpEvents();//<-----------------------}Without this, as most tutorials omit, I get several events, as it does not clear the event information left behind by the last instance of the event. Thus typing became impossible, but not anymore. Ignore the first method; it is now deprecated.   ;  SDL_PumpEvents() is called internally by SDL_PollEvent(). You must have some other issue if you had problems with it. It is a good idea to run SDL_PollEvent() in a while loop, so you consume all available events in a timely fashion.Here is what I would use. I will show you a full program you can test it with. I use the window title to display the text in this test program, you can adapt this to whatever you wish.#include "SDL.h"#include <string>#include <cassert>char getUnicodeValue( const SDL_KeyboardEvent &key ){    assert( SDL_EnableUNICODE(SDL_QUERY) == SDL_ENABLE );    // magic numbers courtesy of SDL docs :)    const int INTERNATIONAL_MASK = 0xFF80, UNICODE_MASK = 0x7F;    int uni = key.keysym.unicode;    if( uni == 0 ) // not translatable key (like up or down arrows)    {   // probably not useful as string input   // we could optionally use this to get some value   // for it: SDL_GetKeyName( key );   return 0;    }    else if( ( uni & INTERNATIONAL_MASK ) == 0 )    {   return static_cast<char>(uni & UNICODE_MASK);    }    else // we have a funky international character. one we can't read :(    {   // we could do nothing, or we can just show some sign of input, like so:   return 0;    }}void handleKey(std::string &current, const SDL_KeyboardEvent &event){switch(event.keysym.sym){case SDLK_BACKSPACE:case SDLK_DELETE:if(!current.empty()){current.erase(current.end() - 1);}break;default:{char key = getUnicodeValue(event);if(key != 0){current += key;}}break;}SDL_WM_SetCaption(current.c_str(), 0);}int main(int, char **){SDL_Init(SDL_INIT_VIDEO);SDL_Surface *screen = SDL_SetVideoMode(800,600, 0, SDL_SWSURFACE);bool running = true;SDL_EnableUNICODE(SDL_ENABLE);std::string input;while(running){SDL_Event event;while(SDL_PollEvent(&event)){if(event.type == SDL_KEYDOWN){handleKey(input, event.key);}else if(event.type == SDL_QUIT){running = false;}}SDL_Flip(screen);}return 0;}Works for meTM.   ;  It's not really working for me... Here is some code. I'm trying to use your method to implement a console... But it's not receiving any input.void Console::handle_input(SDL_Event& event){SDL_EnableUNICODE(SDL_ENABLE);if(event.type == SDL_KEYDOWN) {handleKey(event.key);}SDL_EnableUNICODE(SDL_DISABLE);}void Console::handleKey(const SDL_KeyboardEvent &event){switch(event.keysym.sym) {case SDLK_BACKSPACE:if(console_input.size()) {console_input.erase(--index,1);} break;case SDLK_DELETE:if(index &lt; console_input.size()) {console_input.erase(index,1);} break;case SDLK_LEFT:if(index &lt;= 0) index = 0;else index--;break;case SDLK_RIGHT:if(index &gt;= console_input.size()) index = console_input.size();else index++;break;default:char c = getKey(event);if(c) console_input += c; break;}}char Console::getKey(const SDL_KeyboardEvent& event){if(SDL_EnableUNICODE(SDL_QUERY) == SDL_ENABLE) {Singleton&lt;Log&gt;::getInstance()-&gt;print("SDL_EnableUNICODE == SDL_ENABLE)");} else {Singleton&lt;Log&gt;::getInstance()-&gt;print("SDL_EnableUNICODE == SDL_DISABLED returning)");return '0';}const int INTERNATIONAL_MASK = 0xFF80, UNICODE_MASK = 0x7F;int uni = event.keysym.unicode;if(!uni) {return 0;} else if( ( uni & INTERNATIONAL_MASK ) == 0 ) {   return static_cast&lt;char&gt;(uni & UNICODE_MASK);    } else // we have a funky international character. one we can't read :(    {   // we could do nothing, or we can just show some sign of input, like so:   return 0;    }}Here is the function that calls the console::update() function:void Game::renderConsole(){SDL_Event event;if(SDL_PollEvent(&event)) {if(event.type == SDL_QUIT) gameState-&gt;setState(EXIT);else if(event.type == SDL_KEYDOWN) {if(event.key.keysym.sym == SDLK_BACKQUOTE) {gameState-&gt;setState(GAMEOVER);}}}Log* log = Singleton&lt;Log&gt;::getInstance();Console* console = Singleton&lt;Console&gt;::getInstance();console-&gt;update(event);}Any idea on why the console is not getting any input whatsoever?   