diff --git a/mdl/m_sdlcrt.pas b/mdl/m_sdlcrt.pas index ba490b4..9ad641f 100644 --- a/mdl/m_sdlcrt.pas +++ b/mdl/m_sdlcrt.pas @@ -39,39 +39,79 @@ Uses SDL; Const - AppWindowX = 800; - AppWindowY = 600; - AppInputSize = 128; + keyENTER = #13; + keyESCAPE = #27; + keyHOME = #71; + keyUP = #72; + keyPGUP = #73; + keyLEFT = #75; + keyRIGHT = #77; + keyEND = #79; + keyDOWN = #80; + keyPGDN = #81; + keyINSERT = #82; + keyDELETE = #83; + + AppInputSize = 128; + SDLAppWindowX : Word = 800; + SDLAppWindowY : Word = 600; Type TSDLScreenMode = (mode_80x25, mode_80x50, mode_132x50); + TSDLKeyMap = Record + SDL : Word; + Key : String[2]; + Shift : String[2]; + Alt : String[2]; + Ctrl : String[2]; + End; + TSDLConsole = Class InputBuffer : Array[1..AppInputSize] of Char; InputPos : Integer; InputSize : Integer; + InputEvent : pSDL_EVENT; + Screen : pSDL_SURFACE; - InputEvent : pSDL_EVENT; - Screen : pSDL_SURFACE; + Constructor Create (InitMode: TSDLScreenMode); + Destructor Destroy; Override; - Constructor Create (InitMode: TSDLScreenMode); - Destructor Destroy; - - Procedure PushInput (Ch: Char); + Procedure PushInput (Ch: Char); + Procedure PushExt (Ch: Char); + Procedure PushStr (Str: String); Procedure ProcessEvent; - Function KeyPressed : Boolean; - Procedure Delay (MS: LongInt); + Function KeyPressed : Boolean; + Function ReadKey : Char; + Procedure Delay (MS: LongInt); End; Implementation +// SDL fails hard with keyboard handling. I think we need to use +// a lookup table that can be externalized into a data file so different +// countries can load their specific keyboard set. +// +// I just assumed things like this would NOT be a problem in SDL. Pretty +// disappointing actually. So below is the US mapping as I get time to +// work on it. + +Const + SDLKeyMapSize = 3; + + SDLKeyMapUS : Array[1..SDLKeyMapSize] of TSDLKeyMap = ( + (SDL:SDLK_1; Key:'1'; Shift:'!'; Alt:'1'; CTRL:'1'), + (SDL:SDLK_2; Key:'2'; Shift:'@'; Alt:'2'; CTRL:'2'), + (SDL:SDLK_SLASH; Key:'/'; Shift:'?'; Alt:'/'; CTRL:'/') + ); + Constructor TSDLConsole.Create (InitMode: TSDLScreenMode); Begin Inherited Create; - SDL_INIT(SDL_INIT_VIDEO OR SDL_INIT_EVENTTHREAD); + SDL_INIT(SDL_INIT_VIDEO); - Screen := SDL_SetVideoMode(AppWindowX, AppWindowY, 32, SDL_SWSURFACE); + Screen := SDL_SetVideoMode(SDLAppWindowX, SDLAppWindowY, 32, SDL_SWSURFACE); If Screen = NIL Then Halt; @@ -96,21 +136,84 @@ Begin If InputSize > AppInputSize Then Begin InputSize := 1; - InputPos := 1; + InputPos := 0; End; InputBuffer[InputSize] := Ch; End; -Procedure TSDLConsole.ProcessEvent; +Procedure TSDLConsole.PushExt (Ch: Char); Begin + PushInput(#0); + PushInput(Ch); +End; + +Procedure TSDLConsole.PushStr (Str: String); +Begin + PushInput (Str[1]); + + If Length(Str) > 1 Then PushInput (Str[2]); +End; + +Procedure TSDLConsole.ProcessEvent; +Var + IsShift : Boolean = False; + IsCaps : Boolean = False; + IsAlt : Boolean = False; + IsCtrl : Boolean = False; + Found : Boolean; + Count : Integer; +Begin + IsShift := (InputEvent^.Key.KeySym.Modifier AND KMOD_SHIFT <> 0); + IsCaps := (InputEvent^.Key.KeySym.Modifier AND KMOD_CAPS <> 0); + IsAlt := (InputEvent^.Key.KeySym.Modifier AND KMOD_ALT <> 0); + IsCtrl := (InputEvent^.Key.KeySym.Modifier AND KMOD_CTRL <> 0); + Case InputEvent^.Type_ of - SDL_KEYDOWN : Case InputEvent^.Key.KeySym.Sym of - // remap SDL keys to pascal CRT - 27 : PushInput(#27); - Else - PushInput(Chr(InputEvent^.Key.KeySym.Sym)); + SDL_KEYDOWN : Begin + Case InputEvent^.Key.KeySym.Sym of + SDLK_A.. + SDLK_Z : Begin + If IsShift or IsCaps Then Dec (InputEvent^.Key.KeySym.Sym, 32); + PushInput (Chr(InputEvent^.Key.KeySym.Sym)); + End; + SDLK_DELETE : PushExt(keyDELETE); + SDLK_UP : PushExt(keyUP); + SDLK_DOWN : PushExt(keyDOWN); + SDLK_RIGHT : PushExt(keyRIGHT); + SDLK_LEFT : PushExt(keyLEFT); + SDLK_INSERT : PushExt(keyINSERT); + SDLK_HOME : PushExt(keyHome); + SDLK_END : PushExt(keyEnd); + SDLK_PAGEUP : PushExt(keyPGUP); + SDLK_PAGEDOWN : PushExt(keyPGDN); + SDLK_NUMLOCK.. + SDLK_COMPOSE : ; + Else + Found := False; + + For Count := 1 to SDLKeyMapSize Do + If InputEvent^.Key.KeySym.Sym = SDLKeyMapUS[Count].SDL Then Begin + If IsShift Then + PushStr(SDLKeyMapUS[Count].Shift) + Else + If IsAlt Then + PushStr(SDLKeyMapUS[Count].Alt) + Else + If IsCTRL Then + PushStr(SDLKeyMapUS[Count].CTRL) + Else + PushStr(SDLKeyMapUS[Count].Key); + + Found := True; + + Break; + End; + + If Not Found Then PushInput(Chr(InputEvent^.Key.KeySym.Sym)); + End; End; + SDL_QUITEV : Halt; End; End; @@ -125,7 +228,25 @@ Begin If Queued > 0 Then ProcessEvent; - Result := InputSize > 0; + Result := InputPos <> InputSize; +End; + +Function TSDLConsole.ReadKey : Char; +Begin + If InputPos = InputSize Then + Repeat + SDL_WaitEvent(InputEvent); + ProcessEvent; + Until (InputSize <> InputPos); + + Inc (InputPos); + + Result := InputBuffer[InputPos]; + + If InputPos = InputSize Then Begin + InputPos := 0; + InputSize := 0; + End; End; Procedure TSDLConsole.Delay (MS: LongInt); diff --git a/mdl/mdltest9.pas b/mdl/mdltest9.pas index 71fef5f..2567976 100644 --- a/mdl/mdltest9.pas +++ b/mdl/mdltest9.pas @@ -5,12 +5,34 @@ Uses Var Console : TSDLConsole; - + Ch : Char; Begin Console := TSDLConsole.Create(Mode_80x25); Repeat - Until Console.KeyPressed; + Ch := Console.ReadKey; + + Case Ch of + #00 : Case Console.ReadKey of + keyUP : WriteLn('Got Up arrow'); + keyDOWN : WriteLn('Got down arrow'); + keyLEFT : WriteLn('Got left arrow'); + keyRIGHT : WriteLn('Got right arrow'); + keyHOME : WriteLn('Got HOME'); + keyEND : WriteLn('Got END'); + keyPGUP : WriteLn('Got PAGE UP'); + keyPGDN : WriteLn('Got PAGE Down'); + keyINSERT : WriteLn('Got INSERT'); + keyDELETE : WriteLn('Got DELETE'); + End; + #27 : Begin + WriteLn('Got escape. Shutting down'); + Break; + End; + Else + WriteLn('Got: ' + Ch); + End; + Until False; Console.Free; End.