diff --git a/System/Console/Haskeline/Backend/Win32.hsc b/System/Console/Haskeline/Backend/Win32.hsc index 023fc75..d9744fe 100644 --- a/System/Console/Haskeline/Backend/Win32.hsc +++ b/System/Console/Haskeline/Backend/Win32.hsc @@ -66,19 +66,23 @@ eventReader :: HANDLE -> IO [Event] eventReader h = do let waitTime = 500 -- milliseconds ret <- c_WaitForSingleObject h waitTime - yield -- otherwise, the above foreign call causes the loop to never - -- respond to the killThread if ret /= (#const WAIT_OBJECT_0) then eventReader h else do es <- readEvents h return $ combineSurrogatePairs $ mapMaybe processEvent es +isSurrogatePair :: Char -> Char -> Maybe Char +isSurrogatePair c1 c2 + | 0xD800 <= ord c1 && ord c1 < 0xDC00 && 0xDC00 <= ord c2 && ord c2 < 0xE000 + = Just $ (((ord c1 .&. 0x3FF) `shiftL` 10) .|. (ord c2 .&. 0x3FF)) + 0x10000 + | otherwise + = Nothing + combineSurrogatePairs :: [Event] -> [Event] combineSurrogatePairs (KeyInput [Key m1 (KeyChar c1)] : KeyInput [Key _ (KeyChar c2)] : es) - | 0xD800 <= ord c1 && ord c1 < 0xDC00 && 0xDC00 <= ord c2 && ord c2 < 0xE000 - = let c = (((ord c1 .&. 0x3FF) `shiftL` 10) .|. (ord c2 .&. 0x3FF)) + 0x10000 - in KeyInput [Key m1 (KeyChar (chr c))] : combineSurrogatePairs es + | Just c <- isSurrogatePair c1 c2 + = KeyInput [Key m1 (KeyChar (chr c))] : combineSurrogatePairs es combineSurrogatePairs (e:es) = e : combineSurrogatePairs es combineSurrogatePairs [] = [] diff --git a/System/Console/Haskeline/Term.hs b/System/Console/Haskeline/Term.hs index 21022a4..954780a 100644 --- a/System/Console/Haskeline/Term.hs +++ b/System/Console/Haskeline/Term.hs @@ -138,18 +138,17 @@ keyEventLoop readEvents eventChan = do isEmpty <- atomically $ isEmptyTChan eventChan if not isEmpty then atomically $ readTChan eventChan - else do - tid <- forkIO $ handleErrorEvent readerLoop - atomically (readTChan eventChan) `finally` killThread tid + else handleErrorEvent readerLoop where + readerLoop :: IO Event readerLoop = do es <- readEvents - if null es - then readerLoop - else atomically $ mapM_ (writeTChan eventChan) es - handleErrorEvent = handle $ \e -> case fromException e of - Just ThreadKilled -> return () - _ -> atomically $ writeTChan eventChan (ErrorEvent e) + case es of + [] -> readerLoop + e : rest -> do atomically $ mapM_ (writeTChan eventChan) rest + return e + + handleErrorEvent = handle $ \e -> return (ErrorEvent e) saveKeys :: TChan Event -> [Key] -> IO () saveKeys ch = atomically . writeTChan ch . KeyInput