diff --git a/mdl/m_input_darwin.pas b/mdl/m_input_darwin.pas new file mode 100644 index 0000000..1573a7a --- /dev/null +++ b/mdl/m_input_darwin.pas @@ -0,0 +1,397 @@ +{$I M_OPS.PAS} + +Unit m_Input_Darwin; + +Interface + +Const + ttyIn = 0; + ttyInBufSize = 256; + KeyBufferSize = 20; + ttyOut=1; + InSize=256; + + AltKeyStr : string[38]='qwertyuiopasdfghjklzxcvbnm1234567890-='; + AltCodeStr : string[38]=#016#017#018#019#020#021#022#023#024#025#030#031#032#033#034#035#036#037#038+ + #044#045#046#047#048#049#050#120#121#122#123#124#125#126#127#128#129#130#131; + +Type + TInputDarwin = Class + InBuf : Array[0..ttyInBufSize - 1] of Char; + InCnt : LongInt; + InHead : LongInt; + InTail : LongInt; + KeyBuffer : Array[0..KeyBufferSize-1] of Char; + KeyPut, + KeySend : longint; + + Function ttyRecvChar : Char; +Procedure PushKey(Ch:char); +Function PopKey:char; +Procedure PushExt(b:byte); +Function FAltKey(ch:char):byte; +function sysKeyPressed: boolean; +function KeyWait (MS: LongInt) : boolean; +Function KeyPressed:Boolean; +Function ReadKey:char; +Procedure PurgeInputData; + Constructor Create; + Destructor Destroy; Override; +(* + Procedure AddBuffer (Ch: Char); + Function KeyPressed : Boolean; + Function ReadKey : Char; +*) + End; + +Implementation + +Uses + baseunix, + m_DateTime; + +Constructor TInputDarwin.Create; +Begin + Inherited Create; +End; + +Destructor TInputDarwin.Destroy; +Begin + Inherited Destroy; +End; + +Procedure TInputDarwin.PurgeInputData; +Begin + If KeyPressed Then + Repeat + ReadKey; + Until Not KeyPressed; +End; + +Function TInputDarwin.ttyRecvChar : Char; +var + Readed,i : longint; +begin +{Buffer Empty? Yes, Input from StdIn} + if (InHead=InTail) then + begin + {Calc Amount of Chars to Read} + i:=InSize-InHead; + if InTail>InHead then + i:=InTail-InHead; + {Read} + Readed:=fpRead(TTYIn,InBuf[InHead],i); + {Increase Counters} + inc(InCnt,Readed); + inc(InHead,Readed); + {Wrap if End has Reached} + if InHead>=InSize then + InHead:=0; + end; +{Check Buffer} + if (InCnt=0) then + ttyRecvChar:=#0 + else + begin + ttyRecvChar:=InBuf[InTail]; + dec(InCnt); + inc(InTail); + if InTail>=InSize then + InTail:=0; + end; +end; + +Procedure TInputDarwin.PushKey(Ch:char); +Var + Tmp : Longint; +Begin + Tmp:=KeyPut; + Inc(KeyPut); + If KeyPut>=KeyBufferSize Then + KeyPut:=0; + If KeyPut<>KeySend Then + KeyBuffer[Tmp]:=Ch + Else + KeyPut:=Tmp; +End; + + + +Function TInputDarwin.PopKey:char; +Begin + If KeyPut<>KeySend Then + Begin + PopKey:=KeyBuffer[KeySend]; + Inc(KeySend); + If KeySend>=KeyBufferSize Then + KeySend:=0; + End + Else + PopKey:=#0; +End; + + + +Procedure TInputDarwin.PushExt(b:byte); +begin + PushKey(#0); + PushKey(chr(b)); +end; + + + +Function TInputDarwin.FAltKey(ch:char):byte; +var + Idx : longint; +Begin + Idx:=Pos(ch,AltKeyStr); + if Idx>0 then + FAltKey:=byte(AltCodeStr[Idx]) + else + FAltKey:=0; +End; + +{ This one doesn't care about keypresses already processed by readkey } +{ and waiting in the KeyBuffer, only about waiting keypresses at the } +{ TTYLevel (including ones that are waiting in the TTYRecvChar buffer) } + +function TInputDarwin.sysKeyPressed: boolean; +var + fdsin : tfdSet; +begin + if (InCnt>0) then + sysKeyPressed:=true + else + begin + fpFD_Zero(fdsin); + fpFD_Set(TTYin,fdsin); + sysKeypressed:=(fpSelect(TTYIn+1,@fdsin,nil,nil,0)>0); + end; +end; + +Function TInputDarwin.KeyWait (MS : LongInt) : Boolean; +var + fdsin : tfdset; +begin + result := true; + + if (keysend <> keyput) or (incnt > 0) then exit; + + fpFD_Zero(fdsin); + fpFD_Set(ttyin,fdsin); + if fpSelect(ttyin+1,@fdsin,nil,nil,ms) <= 0 then + result := false; +end; + +Function TInputDarwin.KeyPressed:Boolean; +Begin + Keypressed := (KeySend<>KeyPut) or sysKeyPressed; +End; + +Function TInputDarwin.ReadKey:char; +Var + ch : char; + OldState, + State : longint; + FDS : tFDSet; +Begin +{Check Buffer first} + if KeySend<>KeyPut then + begin + ReadKey:=PopKey; + exit; + end; +{Wait for Key} +{ Only if none are waiting! (JM) } + if not sysKeyPressed then + begin + fpFD_Zero (FDS); + fpFD_Set (0,FDS); + fpSelect (ttyin+1,@FDS,nil,nil,nil); + end; + + ch:=ttyRecvChar; +{Esc Found ?} + CASE ch OF + #27: begin + State:=1; + //WaitMS(10); + + + { This has to be sysKeyPressed and not "keyPressed", since after } + { one iteration keyPressed will always be true because of the } + { pushKey commands (JM) } + while (State<>0) and (sysKeyPressed) do + begin + ch:=ttyRecvChar; + OldState:=State; + State:=0; + case OldState of + 1 : begin {Esc} + case ch of + 'a'..'z', + '0'..'9', + '-','=' : PushExt(FAltKey(ch)); + #10 : PushKey(#10); + '[' : State:=2; +{$IFDEF Unix} + 'O': State:=7; +{$ENDIF} + else + begin + PushKey(ch); + PushKey(#27); + end; + end; + end; + 2 : begin {Esc[} + case ch of + '[' : State:=3; + 'A' : PushExt(72); + 'B' : PushExt(80); + 'C' : PushExt(77); + 'D' : PushExt(75); + 'F' : PushExt(79); {End} + 'G' : PushExt(81); {PageDown} + 'H' : PushExt(71); + 'I' : PushExt(73); {PageUp} + 'K' : PushExt(79); + 'L' : PushExt(82); {Insert - Deekoo} + 'M' : PushExt(59); {F1-F10 - Deekoo} + 'N' : PushExt(60); {F2} + 'O' : PushExt(61); {F3} + 'P' : PushExt(62); {F4} + 'Q' : PushExt(63); {F5} + 'R' : PushExt(64); {F6} + 'S' : PushExt(65); {F7} + 'T' : PushExt(66); {F8} + 'U' : PushExt(67); {F9} + 'V' : PushExt(68); {F10} + {Not sure if TP/BP handles F11 and F12 like this normally; + In pcemu, a TP7 executable handles 'em this way, though.} + 'W' : PushExt(133); {F11} + 'X' : PushExt(134); {F12} + 'Y' : PushExt(84); {Shift-F1} + 'Z' : PushExt(85); {Shift-F2} + 'a' : PushExt(86); {Shift-F3} + 'b' : PushExt(87); {Shift-F4} + 'c' : PushExt(88); {Shift-F5} + 'd' : PushExt(89); {Shift-F6} + 'e' : PushExt(90); {Shift-F7} + 'f' : PushExt(91); {Shift-F8} + 'g' : PushExt(92); {Shift-F9} + 'h' : PushExt(93); {Shift-F10} + 'i' : PushExt(135); {Shift-F11} + 'j' : PushExt(136); {Shift-F12} + 'k' : PushExt(94); {Ctrl-F1} + 'l' : PushExt(95); + 'm' : PushExt(96); + 'n' : PushExt(97); + 'o' : PushExt(98); + 'p' : PushExt(99); + 'q' : PushExt(100); + 'r' : PushExt(101); + 's' : PushExt(102); + 't' : PushExt(103); {Ctrl-F10} + 'u' : PushExt(137); {Ctrl-F11} + 'v' : PushExt(138); {Ctrl-F12} + '1' : State:=4; + '2' : State:=5; + '3' : State:=6; + '4' : PushExt(79); + '5' : PushExt(73); + '6' : PushExt(81); + else + begin + PushKey(ch); + PushKey('['); + PushKey(#27); + end; + end; + if ch in ['4'..'6'] then + State:=255; + end; + 3 : begin {Esc[[} + case ch of + 'A' : PushExt(59); + 'B' : PushExt(60); + 'C' : PushExt(61); + 'D' : PushExt(62); + 'E' : PushExt(63); + end; + end; + 4 : begin {Esc[1} + case ch of + '~' : PushExt(71); + '5' : State := 8; + '7' : PushExt(64); + '8' : PushExt(65); + '9' : PushExt(66); + end; + if not (Ch in ['~', '5']) then + State:=255; + end; + 5 : begin {Esc[2} + case ch of + '~' : PushExt(82); + '0' : pushExt(67); + '1' : PushExt(68); + '3' : PushExt(133); {F11} + {Esc[23~ is also shift-F1,shift-F11} + '4' : PushExt(134); {F12} + {Esc[24~ is also shift-F2,shift-F12} + '5' : PushExt(86); {Shift-F3} + '6' : PushExt(87); {Shift-F4} + '8' : PushExt(88); {Shift-F5} + '9' : PushExt(89); {Shift-F6} + end; + if (Ch<>'~') then + State:=255; + end; + 6 : begin {Esc[3} + case ch of + '~' : PushExt(83); {Del} + '1' : PushExt(90); {Shift-F7} + '2' : PushExt(91); {Shift-F8} + '3' : PushExt(92); {Shift-F9} + '4' : PushExt(93); {Shift-F10} + end; + if (Ch<>'~') then + State:=255; + end; +{$ifdef Unix} // Linux? + 7 : begin {Esc[O} + case ch of + 'A' : PushExt(72); + 'B' : PushExt(80); + 'C' : PushExt(77); + 'D' : PushExt(75); + 'F' : PushExt(79); + 'H' : PushExt(71); + 'P' : PushExt(59); + 'Q' : PushExt(60); + 'R' : PushExt(61); + 'S' : PushExt(62); + end; + end; +{$endif} + 8 : begin {Esc[15} + case ch of + '~' : PushExt(63); + end; + end; + 255 : ; + end; + if State<>0 then + {WaitMS(10)}; + end; + if State=1 then + PushKey(ch); + end; + #127: PushKey(#8); + else PushKey(ch); + End; + ReadKey:=PopKey; +End; + +End. diff --git a/mdl/m_input_linux.pas b/mdl/m_input_linux.pas new file mode 100644 index 0000000..79c570a --- /dev/null +++ b/mdl/m_input_linux.pas @@ -0,0 +1,340 @@ +{$I M_OPS.PAS} + +Unit m_Input_Linux; + +Interface + +Const + ttyIn = 0; + ttyInBufSize = 256; + KeyBufferSize = 20; + ttyOut = 1; + InSize = 256; + + AltKeyStr : string[38]='qwertyuiopasdfghjklzxcvbnm1234567890-='; + AltCodeStr : string[38]=#016#017#018#019#020#021#022#023#024#025#030#031#032#033#034#035#036#037#038+ + #044#045#046#047#048#049#050#120#121#122#123#124#125#126#127#128#129#130#131; +Type + TInputLinux = Class + InBuf : Array[0..ttyInBufSize - 1] of Char; + InCnt : LongInt; + InHead : LongInt; + InTail : LongInt; + KeyBuffer : Array[0..KeyBufferSize - 1] of Char; + KeyPut, + KeySend : LongInt; + + Function ttyRecvChar : Char; + Procedure PushKey (Ch : Char); + Function PopKey : Char; + Procedure PushExt (B : Byte); + Function FAltKey (Ch : Char) : Byte; + Function sysKeyPressed : Boolean; + Function KeyWait (MS: LongInt) : Boolean; + Function KeyPressed : Boolean; + Function ReadKey : Char; + Procedure PurgeInputData; + Constructor Create; + Destructor Destroy; Override; + End; + +Implementation + +Uses + baseunix, + m_DateTime; + +Constructor TInputLinux.Create; +Begin + Inherited Create; +End; + +Destructor TInputLinux.Destroy; +Begin + Inherited Destroy; +End; + +Procedure TInputLinux.PurgeInputData; +Begin + While KeyPressed Do + ReadKey; +End; + +Function TInputLinux.ttyRecvChar : Char; +var + Readed,i : longint; +begin +{Buffer Empty? Yes, Input from StdIn} + if (InHead=InTail) then + begin + {Calc Amount of Chars to Read} + i:=InSize-InHead; + if InTail>InHead then + i:=InTail-InHead; + {Read} + Readed:=fpRead(TTYIn,InBuf[InHead],i); + {Increase Counters} + inc(InCnt,Readed); + inc(InHead,Readed); + {Wrap if End has Reached} + if InHead>=InSize then + InHead:=0; + end; +{Check Buffer} + if (InCnt=0) then + ttyRecvChar:=#0 + else + begin + ttyRecvChar:=InBuf[InTail]; + dec(InCnt); + inc(InTail); + if InTail>=InSize then + InTail:=0; + end; +end; + +Procedure TInputLinux.PushKey(Ch:char); +Var + Tmp : Longint; +Begin + Tmp:=KeyPut; + Inc(KeyPut); + If KeyPut>=KeyBufferSize Then + KeyPut:=0; + If KeyPut<>KeySend Then + KeyBuffer[Tmp]:=Ch + Else + KeyPut:=Tmp; +End; + +Function TInputLinux.PopKey:char; +Begin + If KeyPut<>KeySend Then + Begin + PopKey:=KeyBuffer[KeySend]; + Inc(KeySend); + If KeySend>=KeyBufferSize Then + KeySend:=0; + End + Else + PopKey:=#0; +End; + +Procedure TInputLinux.PushExt(b:byte); +begin + PushKey(#0); + PushKey(chr(b)); +end; + +Function TInputLinux.FAltKey(ch:char):byte; +var + Idx : longint; +Begin + Idx:=Pos(ch,AltKeyStr); + if Idx>0 then + FAltKey:=byte(AltCodeStr[Idx]) + else + FAltKey:=0; +End; + +{ This one doesn't care about keypresses already processed by readkey } +{ and waiting in the KeyBuffer, only about waiting keypresses at the } +{ TTYLevel (including ones that are waiting in the TTYRecvChar buffer) } + +function TInputLinux.sysKeyPressed: boolean; +var + fdsin : tfdSet; +begin + if (InCnt>0) then + sysKeyPressed:=true + else + begin + fpFD_Zero(fdsin); + fpFD_Set(TTYin,fdsin); + sysKeypressed:=(fpSelect(TTYIn+1,@fdsin,nil,nil,0)>0); + end; +end; + +Function TInputLinux.KeyWait (MS : LongInt) : Boolean; +var + fdsin : tfdset; +begin + result := true; + + if (keysend <> keyput) or (incnt > 0) then exit; + + fpFD_Zero(fdsin); + fpFD_Set(ttyin,fdsin); + if fpSelect(ttyin+1,@fdsin,nil,nil,ms) <= 0 then + result := false; +end; + +Function TInputLinux.KeyPressed:Boolean; +Begin + Keypressed := (KeySend<>KeyPut) or sysKeyPressed; +End; + +Function TInputLinux.ReadKey:char; +Var + ch : char; + OldState, + State : longint; + FDS : tFDSet; +Begin +{Check Buffer first} + if KeySend<>KeyPut then + begin + ReadKey:=PopKey; + exit; + end; +{Wait for Key} +{ Only if none are waiting! (JM) } + if not sysKeyPressed then + begin + fpFD_Zero (FDS); + fpFD_Set (0,FDS); + fpSelect (ttyin+1,@FDS,nil,nil,nil); + end; + + ch:=ttyRecvChar; +{Esc Found ?} + CASE ch OF + #27: begin + State:=1; + //WaitMS(10); + + + { This has to be sysKeyPressed and not "keyPressed", since after } + { one iteration keyPressed will always be true because of the } + { pushKey commands (JM) } + while (State<>0) and (sysKeyPressed) do + begin + ch:=ttyRecvChar; + OldState:=State; + State:=0; + case OldState of + 1 : begin {Esc} + case ch of + 'a'..'z', + '0'..'9', + '-','=' : PushExt(FAltKey(ch)); + #10 : PushKey(#10); + '[' : State := 2; + 'O': State := 7; + else + begin + PushKey(ch); + PushKey(#27); + end; + end; + end; + 2 : begin {Esc[} + case ch of + '[' : State := 3; + 'A' : PushExt(72); + 'B' : PushExt(80); + 'C' : PushExt(77); + 'D' : PushExt(75); + 'G' : PushKey('5'); {Center key, Linux} + 'H' : PushExt(71); + 'K' : PushExt(79); + 'U' : PushExt(81); //syncterm nonsense + 'V' : PushExt(73); //syncterm nonsense + '1' : State:=4; + '2' : State:=5; + '3' : State:=6; + '4' : PushExt(79); + '5' : PushExt(73); + '6' : PushExt(81); + else + begin + PushKey(ch); + PushKey('['); + PushKey(#27); + end; + end; + if ch in ['4'..'6'] then + State:=255; + end; + 3 : begin {Esc[[} + case ch of + 'A' : PushExt(59); + 'B' : PushExt(60); + 'C' : PushExt(61); + 'D' : PushExt(62); + 'E' : PushExt(63); + end; + end; + 4 : begin {Esc[1} + case ch of + '~' : PushExt(71); + '5' : State := 8; + '7' : PushExt(64); + '8' : PushExt(65); + '9' : PushExt(66); + end; + if not (Ch in ['~', '5']) then + State:=255; + end; + 5 : begin {Esc[2} + case ch of + '~' : PushExt(82); + '0' : pushExt(67); + '1' : PushExt(68); + '3' : PushExt(133); {F11} + {Esc[23~ is also shift-F1,shift-F11} + '4' : PushExt(134); {F12} + {Esc[24~ is also shift-F2,shift-F12} + '5' : PushExt(86); {Shift-F3} + '6' : PushExt(87); {Shift-F4} + '8' : PushExt(88); {Shift-F5} + '9' : PushExt(89); {Shift-F6} + end; + if (Ch<>'~') then + State:=255; + end; + 6 : begin {Esc[3} + case ch of + '~' : PushExt(83); {Del} + '1' : PushExt(90); {Shift-F7} + '2' : PushExt(91); {Shift-F8} + '3' : PushExt(92); {Shift-F9} + '4' : PushExt(93); {Shift-F10} + end; + if (Ch<>'~') then + State:=255; + end; + 7 : begin {Esc[O} + case ch of + 'A' : PushExt(72); + 'B' : PushExt(80); + 'C' : PushExt(77); + 'D' : PushExt(75); + 'F' : PushExt(79); + 'H' : PushExt(71); + 'P' : PushExt(59); + 'Q' : PushExt(60); + 'R' : PushExt(61); + 'S' : PushExt(62); + end; + end; + 8 : begin {Esc[15} + case ch of + '~' : PushExt(63); + end; + end; + 255 : ; + end; + if State<>0 then + {WaitMS(10)}; + end; + if State=1 then + PushKey(ch); + end; + #127: PushKey(#8); + else PushKey(ch); + End; + ReadKey:=PopKey; +End; + +End. \ No newline at end of file