@@ -33,12 +33,15 @@ import Control.Monad.Trans.State (StateT(..), evalStateT)
33import Control.Monad.State.Class (MonadState, modify)
33import Control.Monad.State.Class (MonadState, modify)
34import Control.Monad.Trans.Reader (ReaderT(..))
34import Control.Monad.Trans.Reader (ReaderT(..))
36−import Data.Char
36+import qualified Data.ByteString.Char8 as BS8
37+import qualified Data.ByteString as BS
38+import Data.ByteString.Char8 (ByteString)
37import Data.IORef
39import Data.IORef
38import Data.Word (Word8)
40import Data.Word (Word8)
40−import Foreign ( allocaArray, peekArray, Ptr )
42+import Foreign (allocaArray)
41import Foreign.C.Types (CInt(..))
43import Foreign.C.Types (CInt(..))
44+import Foreign.Ptr (Ptr, castPtr)
43import System.IO
46import System.IO
44import System.Posix.IO (fdReadBuf, setFdOption, FdOption(..))
47import System.Posix.IO (fdReadBuf, setFdOption, FdOption(..))
@@ -76,10 +79,10 @@ data InputBuffer = InputBuffer
76makeLenses ''InputBuffer
79makeLenses ''InputBuffer
78data InputState = InputState
81data InputState = InputState
79− { _unprocessedBytes :: String
82+ { _unprocessedBytes :: ByteString
80 , _appliedConfig :: Config
83 , _appliedConfig :: Config
81 , _inputBuffer :: InputBuffer
84 , _inputBuffer :: InputBuffer
82− , _classifier :: String -> KClass
85+ , _classifier :: ByteString -> KClass
85makeLenses ''InputState
88makeLenses ''InputState
@@ -104,7 +107,7 @@ loopInputProcessor = do
104 dropInvalid
107 dropInvalid
105 loopInputProcessor
108 loopInputProcessor
107−addBytesToProcess :: String -> InputM ()
110+addBytesToProcess :: ByteString -> InputM ()
108addBytesToProcess block = unprocessedBytes <>= block
111addBytesToProcess block = unprocessedBytes <>= block
110emit :: Event -> InputM ()
113emit :: Event -> InputM ()
@@ -117,7 +120,7 @@ emit event = do
118-- Precondition: Under the threaded runtime. Only current use is from a
121-- Precondition: Under the threaded runtime. Only current use is from a
119-- forkOS thread. That case satisfies precondition.
122-- forkOS thread. That case satisfies precondition.
120−readFromDevice :: InputM String
123+readFromDevice :: InputM ByteString
121readFromDevice = do
124readFromDevice = do
122 newConfig <- view configRef >>= liftIO . readIORef
125 newConfig <- view configRef >>= liftIO . readIORef
123 oldConfig <- use appliedConfig
126 oldConfig <- use appliedConfig
@@ -137,9 +140,10 @@ readFromDevice = do
137 threadWaitRead fd
140 threadWaitRead fd
138 bytesRead <- fdReadBuf fd bufferPtr (fromIntegral maxBytes)
141 bytesRead <- fdReadBuf fd bufferPtr (fromIntegral maxBytes)
139 if bytesRead > 0
142 if bytesRead > 0
140− then map (chr . fromIntegral) <$> peekArray (fromIntegral bytesRead) bufferPtr
143+ then BS.packCStringLen (castPtr bufferPtr, fromIntegral bytesRead)
141− else return []
144+ else return BS.empty
145+ when (not $ BS.null stringRep) $
142− when (not $ null stringRep) $ logMsg $ "input bytes: " ++ show stringRep
146+ logMsg $ "input bytes: " ++ show (BS8.unpack stringRep)
143 return stringRep
147 return stringRep
145applyConfig :: Fd -> Config -> IO ()
149applyConfig :: Fd -> Config -> IO ()
@@ -165,15 +169,16 @@ dropInvalid = do
165 b <- use unprocessedBytes
169 b <- use unprocessedBytes
166 when (c b == Invalid) $ do
170 when (c b == Invalid) $ do
167 logMsg "dropping input bytes"
171 logMsg "dropping input bytes"
168− unprocessedBytes .= []
172+ unprocessedBytes .= BS8.empty
170runInputProcessorLoop :: ClassifyMap -> Input -> IO ()
174runInputProcessorLoop :: ClassifyMap -> Input -> IO ()
171runInputProcessorLoop classifyTable input = do
175runInputProcessorLoop classifyTable input = do
172 let bufferSize = 1024
176 let bufferSize = 1024
173 allocaArray bufferSize $ \(bufferPtr :: Ptr Word8) -> do
177 allocaArray bufferSize $ \(bufferPtr :: Ptr Word8) -> do
178+ s0 <- InputState BS8.empty
174− s0 <- InputState [] <$> readIORef (_configRef input)
179+ <$> readIORef (_configRef input)
175− <*> pure (InputBuffer bufferPtr bufferSize)
180+ <*> pure (InputBuffer bufferPtr bufferSize)
176− <*> pure (classify classifyTable)
181+ <*> pure (classify classifyTable)
177 runReaderT (evalStateT loopInputProcessor s0) input
182 runReaderT (evalStateT loopInputProcessor s0) input
179-- | Construct two IO actions: one to configure the terminal for Vty and
184-- | Construct two IO actions: one to configure the terminal for Vty and