module Game.LambdaHack.Client.UI.Frontend.Std
(
FrontendSession(sescMVar)
, fdisplay, fpromptGetKey, fsyncFrames
, frontendName, startup
) where
import Control.Concurrent
import Control.Concurrent.Async
import qualified Control.Exception as Ex hiding (handle)
import qualified Data.ByteString.Char8 as BS
import Data.Char (chr, ord)
import qualified System.IO as SIO
import qualified Game.LambdaHack.Client.Key as K
import Game.LambdaHack.Client.UI.Animation
import Game.LambdaHack.Common.ClientOptions
import qualified Game.LambdaHack.Common.Color as Color
data FrontendSession = FrontendSession
{ sdebugCli :: !DebugModeCli
, sescMVar :: !(Maybe (MVar ()))
}
frontendName :: String
frontendName = "std"
startup :: DebugModeCli -> (FrontendSession -> IO ()) -> IO ()
startup sdebugCli k = do
a <- async $ k FrontendSession{sescMVar = Nothing, ..}
`Ex.finally` (SIO.hFlush SIO.stdout >> SIO.hFlush SIO.stderr)
wait a
fdisplay :: FrontendSession
-> Bool
-> Maybe SingleFrame
-> IO ()
fdisplay _ _ Nothing = return ()
fdisplay _ _ (Just rawSF) =
let SingleFrame{sfLevel} = overlayOverlay rawSF
bs = map (BS.pack . map Color.acChar . decodeLine) sfLevel ++ [BS.empty]
in mapM_ BS.putStrLn bs
nextEvent :: IO K.KM
nextEvent = do
l <- BS.hGetLine SIO.stdin
let c = case BS.uncons l of
Nothing -> '\n'
Just (hd, _) -> hd
return $! keyTranslate c
fsyncFrames :: FrontendSession -> IO ()
fsyncFrames _ = return ()
fpromptGetKey :: FrontendSession -> SingleFrame -> IO K.KM
fpromptGetKey sess frame = do
fdisplay sess True $ Just frame
nextEvent
keyTranslate :: Char -> K.KM
keyTranslate e = (\(key, modifier) -> K.KM {..}) $
case e of
'\ESC' -> (K.Esc, K.NoModifier)
'\n' -> (K.Return, K.NoModifier)
'\r' -> (K.Return, K.NoModifier)
' ' -> (K.Space, K.NoModifier)
'\t' -> (K.Tab, K.NoModifier)
c | ord '\^A' <= ord c && ord c <= ord '\^Z' ->
(K.Char $ chr $ ord c ord '\^A' + ord 'a', K.Control)
| c `elem` ['1'..'9'] -> (K.KP c, K.NoModifier)
| otherwise -> (K.Char c, K.NoModifier)